1//===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Implements the info about Hexagon target spec.
10//
11//===----------------------------------------------------------------------===//
12
13#include "HexagonTargetMachine.h"
14#include "Hexagon.h"
15#include "HexagonISelLowering.h"
16#include "HexagonLoopIdiomRecognition.h"
17#include "HexagonMachineFunctionInfo.h"
18#include "HexagonMachineScheduler.h"
19#include "HexagonTargetObjectFile.h"
20#include "HexagonTargetTransformInfo.h"
21#include "HexagonVectorLoopCarriedReuse.h"
22#include "TargetInfo/HexagonTargetInfo.h"
23#include "llvm/CodeGen/Passes.h"
24#include "llvm/CodeGen/TargetPassConfig.h"
25#include "llvm/CodeGen/VLIWMachineScheduler.h"
26#include "llvm/IR/Module.h"
27#include "llvm/MC/TargetRegistry.h"
28#include "llvm/Passes/PassBuilder.h"
29#include "llvm/Support/CommandLine.h"
30#include "llvm/Transforms/Scalar.h"
31#include <optional>
32
33using namespace llvm;
34
35static cl::opt<bool>
36 EnableCExtOpt("hexagon-cext", cl::Hidden, cl::init(Val: true),
37 cl::desc("Enable Hexagon constant-extender optimization"));
38
39static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::init(Val: true),
40 cl::desc("Enable RDF-based optimizations"));
41
42cl::opt<unsigned> RDFFuncBlockLimit(
43 "rdf-bb-limit", cl::Hidden, cl::init(Val: 1000),
44 cl::desc("Basic block limit for a function for RDF optimizations"));
45
46static cl::opt<bool>
47 DisableHardwareLoops("disable-hexagon-hwloops", cl::Hidden,
48 cl::desc("Disable Hardware Loops for Hexagon target"));
49
50static cl::opt<bool>
51 DisableAModeOpt("disable-hexagon-amodeopt", cl::Hidden,
52 cl::desc("Disable Hexagon Addressing Mode Optimization"));
53
54static cl::opt<bool>
55 DisableHexagonCFGOpt("disable-hexagon-cfgopt", cl::Hidden,
56 cl::desc("Disable Hexagon CFG Optimization"));
57
58static cl::opt<bool>
59 DisableHCP("disable-hcp", cl::Hidden,
60 cl::desc("Disable Hexagon constant propagation"));
61
62static cl::opt<bool> DisableStoreWidening("disable-store-widen", cl::Hidden,
63 cl::init(Val: false),
64 cl::desc("Disable store widening"));
65
66static cl::opt<bool> EnableExpandCondsets("hexagon-expand-condsets",
67 cl::init(Val: true), cl::Hidden,
68 cl::desc("Early expansion of MUX"));
69
70static cl::opt<bool> EnableTfrCleanup("hexagon-tfr-cleanup", cl::init(Val: true),
71 cl::Hidden,
72 cl::desc("Cleanup of TFRs/COPYs"));
73
74static cl::opt<bool> EnableEarlyIf("hexagon-eif", cl::init(Val: true), cl::Hidden,
75 cl::desc("Enable early if-conversion"));
76
77static cl::opt<bool> EnableCopyHoist("hexagon-copy-hoist", cl::init(Val: true),
78 cl::Hidden, cl::ZeroOrMore,
79 cl::desc("Enable Hexagon copy hoisting"));
80
81static cl::opt<bool>
82 EnableGenInsert("hexagon-insert", cl::init(Val: true), cl::Hidden,
83 cl::desc("Generate \"insert\" instructions"));
84
85static cl::opt<bool>
86 EnableCommGEP("hexagon-commgep", cl::init(Val: true), cl::Hidden,
87 cl::desc("Enable commoning of GEP instructions"));
88
89static cl::opt<bool>
90 EnableGenExtract("hexagon-extract", cl::init(Val: true), cl::Hidden,
91 cl::desc("Generate \"extract\" instructions"));
92
93static cl::opt<bool> EnableGenMux(
94 "hexagon-mux", cl::init(Val: true), cl::Hidden,
95 cl::desc("Enable converting conditional transfers into MUX instructions"));
96
97static cl::opt<bool>
98 EnableGenPred("hexagon-gen-pred", cl::init(Val: true), cl::Hidden,
99 cl::desc("Enable conversion of arithmetic operations to "
100 "predicate instructions"));
101
102static cl::opt<bool>
103 EnableLoopPrefetch("hexagon-loop-prefetch", cl::Hidden,
104 cl::desc("Enable loop data prefetch on Hexagon"));
105
106static cl::opt<bool>
107 DisableHSDR("disable-hsdr", cl::init(Val: false), cl::Hidden,
108 cl::desc("Disable splitting double registers"));
109
110static cl::opt<bool>
111 EnableGenMemAbs("hexagon-mem-abs", cl::init(Val: true), cl::Hidden,
112 cl::desc("Generate absolute set instructions"));
113
114static cl::opt<bool> EnableBitSimplify("hexagon-bit", cl::init(Val: true),
115 cl::Hidden,
116 cl::desc("Bit simplification"));
117
118static cl::opt<bool> EnableLoopResched("hexagon-loop-resched", cl::init(Val: true),
119 cl::Hidden,
120 cl::desc("Loop rescheduling"));
121
122static cl::opt<bool> HexagonNoOpt("hexagon-noopt", cl::init(Val: false), cl::Hidden,
123 cl::desc("Disable backend optimizations"));
124
125static cl::opt<bool>
126 EnableVectorPrint("enable-hexagon-vector-print", cl::Hidden,
127 cl::desc("Enable Hexagon Vector print instr pass"));
128
129static cl::opt<bool>
130 EnableVExtractOpt("hexagon-opt-vextract", cl::Hidden, cl::init(Val: true),
131 cl::desc("Enable vextract optimization"));
132
133static cl::opt<bool>
134 EnableVectorCombine("hexagon-vector-combine", cl::Hidden, cl::init(Val: true),
135 cl::desc("Enable HVX vector combining"));
136
137static cl::opt<bool> EnableInitialCFGCleanup(
138 "hexagon-initial-cfg-cleanup", cl::Hidden, cl::init(Val: true),
139 cl::desc("Simplify the CFG after atomic expansion pass"));
140
141static cl::opt<bool> EnableInstSimplify("hexagon-instsimplify", cl::Hidden,
142 cl::init(Val: true),
143 cl::desc("Enable instsimplify"));
144
145/// HexagonTargetMachineModule - Note that this is used on hosts that
146/// cannot link in a library unless there are references into the
147/// library. In particular, it seems that it is not possible to get
148/// things to work on Win32 without this. Though it is unused, do not
149/// remove it.
150extern "C" int HexagonTargetMachineModule;
151int HexagonTargetMachineModule = 0;
152
153static ScheduleDAGInstrs *createVLIWMachineSched(MachineSchedContext *C) {
154 ScheduleDAGMILive *DAG = new VLIWMachineScheduler(
155 C, std::make_unique<HexagonConvergingVLIWScheduler>());
156 DAG->addMutation(Mutation: std::make_unique<HexagonSubtarget::UsrOverflowMutation>());
157 DAG->addMutation(Mutation: std::make_unique<HexagonSubtarget::HVXMemLatencyMutation>());
158 DAG->addMutation(Mutation: std::make_unique<HexagonSubtarget::CallMutation>());
159 DAG->addMutation(Mutation: createCopyConstrainDAGMutation(TII: DAG->TII, TRI: DAG->TRI));
160 return DAG;
161}
162
163static MachineSchedRegistry
164 SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler",
165 createVLIWMachineSched);
166
167namespace llvm {
168extern char &HexagonCopyHoistingID;
169extern char &HexagonExpandCondsetsID;
170extern char &HexagonTfrCleanupID;
171void initializeHexagonBitSimplifyPass(PassRegistry &);
172void initializeHexagonCopyHoistingPass(PassRegistry &);
173void initializeHexagonConstExtendersPass(PassRegistry &);
174void initializeHexagonConstPropagationPass(PassRegistry &);
175void initializeHexagonCopyToCombinePass(PassRegistry &);
176void initializeHexagonEarlyIfConversionPass(PassRegistry &);
177void initializeHexagonExpandCondsetsPass(PassRegistry &);
178void initializeHexagonGenMemAbsolutePass(PassRegistry &);
179void initializeHexagonGenMuxPass(PassRegistry &);
180void initializeHexagonHardwareLoopsPass(PassRegistry &);
181void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &);
182void initializeHexagonLoopAlignPass(PassRegistry &);
183void initializeHexagonNewValueJumpPass(PassRegistry &);
184void initializeHexagonOptAddrModePass(PassRegistry &);
185void initializeHexagonPacketizerPass(PassRegistry &);
186void initializeHexagonRDFOptPass(PassRegistry &);
187void initializeHexagonSplitDoubleRegsPass(PassRegistry &);
188void initializeHexagonTfrCleanupPass(PassRegistry &);
189void initializeHexagonVExtractPass(PassRegistry &);
190void initializeHexagonVectorCombineLegacyPass(PassRegistry &);
191void initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PassRegistry &);
192Pass *createHexagonLoopIdiomPass();
193Pass *createHexagonVectorLoopCarriedReuseLegacyPass();
194
195FunctionPass *createHexagonBitSimplify();
196FunctionPass *createHexagonBranchRelaxation();
197FunctionPass *createHexagonCallFrameInformation();
198FunctionPass *createHexagonCFGOptimizer();
199FunctionPass *createHexagonCommonGEP();
200FunctionPass *createHexagonConstExtenders();
201FunctionPass *createHexagonConstPropagationPass();
202FunctionPass *createHexagonCopyHoisting();
203FunctionPass *createHexagonCopyToCombine();
204FunctionPass *createHexagonEarlyIfConversion();
205FunctionPass *createHexagonFixupHwLoops();
206FunctionPass *createHexagonGenExtract();
207FunctionPass *createHexagonGenInsert();
208FunctionPass *createHexagonGenMemAbsolute();
209FunctionPass *createHexagonGenMux();
210FunctionPass *createHexagonGenPredicate();
211FunctionPass *createHexagonHardwareLoops();
212FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
213 CodeGenOptLevel OptLevel);
214FunctionPass *createHexagonLoopAlign();
215FunctionPass *createHexagonLoopRescheduling();
216FunctionPass *createHexagonNewValueJump();
217FunctionPass *createHexagonOptAddrMode();
218FunctionPass *createHexagonOptimizeSZextends();
219FunctionPass *createHexagonPacketizer(bool Minimal);
220FunctionPass *createHexagonPeephole();
221FunctionPass *createHexagonRDFOpt();
222FunctionPass *createHexagonSplitConst32AndConst64();
223FunctionPass *createHexagonSplitDoubleRegs();
224FunctionPass *createHexagonStoreWidening();
225FunctionPass *createHexagonTfrCleanup();
226FunctionPass *createHexagonVectorCombineLegacyPass();
227FunctionPass *createHexagonVectorPrint();
228FunctionPass *createHexagonVExtract();
229} // namespace llvm
230
231static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
232 return RM.value_or(u: Reloc::Static);
233}
234
235extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonTarget() {
236 // Register the target.
237 RegisterTargetMachine<HexagonTargetMachine> X(getTheHexagonTarget());
238
239 PassRegistry &PR = *PassRegistry::getPassRegistry();
240 initializeHexagonBitSimplifyPass(PR);
241 initializeHexagonConstExtendersPass(PR);
242 initializeHexagonConstPropagationPass(PR);
243 initializeHexagonCopyToCombinePass(PR);
244 initializeHexagonEarlyIfConversionPass(PR);
245 initializeHexagonGenMemAbsolutePass(PR);
246 initializeHexagonGenMuxPass(PR);
247 initializeHexagonHardwareLoopsPass(PR);
248 initializeHexagonLoopIdiomRecognizeLegacyPassPass(PR);
249 initializeHexagonNewValueJumpPass(PR);
250 initializeHexagonOptAddrModePass(PR);
251 initializeHexagonPacketizerPass(PR);
252 initializeHexagonRDFOptPass(PR);
253 initializeHexagonSplitDoubleRegsPass(PR);
254 initializeHexagonVectorCombineLegacyPass(PR);
255 initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PR);
256 initializeHexagonVExtractPass(PR);
257 initializeHexagonDAGToDAGISelLegacyPass(PR);
258}
259
260HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT,
261 StringRef CPU, StringRef FS,
262 const TargetOptions &Options,
263 std::optional<Reloc::Model> RM,
264 std::optional<CodeModel::Model> CM,
265 CodeGenOptLevel OL, bool JIT)
266 // Specify the vector alignment explicitly. For v512x1, the calculated
267 // alignment would be 512*alignment(i1), which is 512 bytes, instead of
268 // the required minimum of 64 bytes.
269 : LLVMTargetMachine(
270 T,
271 "e-m:e-p:32:32:32-a:0-n16:32-"
272 "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-"
273 "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048",
274 TT, CPU, FS, Options, getEffectiveRelocModel(RM),
275 getEffectiveCodeModel(CM, Default: CodeModel::Small),
276 (HexagonNoOpt ? CodeGenOptLevel::None : OL)),
277 TLOF(std::make_unique<HexagonTargetObjectFile>()),
278 Subtarget(Triple(TT), CPU, FS, *this) {
279 initializeHexagonCopyHoistingPass(*PassRegistry::getPassRegistry());
280 initializeHexagonExpandCondsetsPass(*PassRegistry::getPassRegistry());
281 initializeHexagonLoopAlignPass(*PassRegistry::getPassRegistry());
282 initializeHexagonTfrCleanupPass(*PassRegistry::getPassRegistry());
283 initAsmInfo();
284}
285
286const HexagonSubtarget *
287HexagonTargetMachine::getSubtargetImpl(const Function &F) const {
288 AttributeList FnAttrs = F.getAttributes();
289 Attribute CPUAttr = FnAttrs.getFnAttr(Kind: "target-cpu");
290 Attribute FSAttr = FnAttrs.getFnAttr(Kind: "target-features");
291
292 std::string CPU =
293 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
294 std::string FS =
295 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
296 // Append the preexisting target features last, so that +mattr overrides
297 // the "unsafe-fp-math" function attribute.
298 // Creating a separate target feature is not strictly necessary, it only
299 // exists to make "unsafe-fp-math" force creating a new subtarget.
300
301 if (F.getFnAttribute(Kind: "unsafe-fp-math").getValueAsBool())
302 FS = FS.empty() ? "+unsafe-fp" : "+unsafe-fp," + FS;
303
304 auto &I = SubtargetMap[CPU + FS];
305 if (!I) {
306 // This needs to be done before we create a new subtarget since any
307 // creation will depend on the TM and the code generation flags on the
308 // function that reside in TargetOptions.
309 resetTargetOptions(F);
310 I = std::make_unique<HexagonSubtarget>(args: TargetTriple, args&: CPU, args&: FS, args: *this);
311 }
312 return I.get();
313}
314
315void HexagonTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
316#define GET_PASS_REGISTRY "HexagonPassRegistry.def"
317#include "llvm/Passes/TargetPassRegistry.inc"
318
319 PB.registerLateLoopOptimizationsEPCallback(
320 C: [=](LoopPassManager &LPM, OptimizationLevel Level) {
321 LPM.addPass(Pass: HexagonLoopIdiomRecognitionPass());
322 });
323 PB.registerLoopOptimizerEndEPCallback(
324 C: [=](LoopPassManager &LPM, OptimizationLevel Level) {
325 LPM.addPass(Pass: HexagonVectorLoopCarriedReusePass());
326 });
327}
328
329TargetTransformInfo
330HexagonTargetMachine::getTargetTransformInfo(const Function &F) const {
331 return TargetTransformInfo(HexagonTTIImpl(this, F));
332}
333
334MachineFunctionInfo *HexagonTargetMachine::createMachineFunctionInfo(
335 BumpPtrAllocator &Allocator, const Function &F,
336 const TargetSubtargetInfo *STI) const {
337 return HexagonMachineFunctionInfo::create<HexagonMachineFunctionInfo>(
338 Allocator, F, STI);
339}
340
341HexagonTargetMachine::~HexagonTargetMachine() = default;
342
343namespace {
344/// Hexagon Code Generator Pass Configuration Options.
345class HexagonPassConfig : public TargetPassConfig {
346public:
347 HexagonPassConfig(HexagonTargetMachine &TM, PassManagerBase &PM)
348 : TargetPassConfig(TM, PM) {}
349
350 HexagonTargetMachine &getHexagonTargetMachine() const {
351 return getTM<HexagonTargetMachine>();
352 }
353
354 ScheduleDAGInstrs *
355 createMachineScheduler(MachineSchedContext *C) const override {
356 return createVLIWMachineSched(C);
357 }
358
359 void addIRPasses() override;
360 bool addInstSelector() override;
361 void addPreRegAlloc() override;
362 void addPostRegAlloc() override;
363 void addPreSched2() override;
364 void addPreEmitPass() override;
365};
366} // namespace
367
368TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) {
369 return new HexagonPassConfig(*this, PM);
370}
371
372void HexagonPassConfig::addIRPasses() {
373 TargetPassConfig::addIRPasses();
374 bool NoOpt = (getOptLevel() == CodeGenOptLevel::None);
375
376 if (!NoOpt) {
377 if (EnableInstSimplify)
378 addPass(P: createInstSimplifyLegacyPass());
379 addPass(P: createDeadCodeEliminationPass());
380 }
381
382 addPass(P: createAtomicExpandLegacyPass());
383
384 if (!NoOpt) {
385 if (EnableInitialCFGCleanup)
386 addPass(P: createCFGSimplificationPass(Options: SimplifyCFGOptions()
387 .forwardSwitchCondToPhi(B: true)
388 .convertSwitchRangeToICmp(B: true)
389 .convertSwitchToLookupTable(B: true)
390 .needCanonicalLoops(B: false)
391 .hoistCommonInsts(B: true)
392 .sinkCommonInsts(B: true)));
393 if (EnableLoopPrefetch)
394 addPass(P: createLoopDataPrefetchPass());
395 if (EnableVectorCombine)
396 addPass(P: createHexagonVectorCombineLegacyPass());
397 if (EnableCommGEP)
398 addPass(P: createHexagonCommonGEP());
399 // Replace certain combinations of shifts and ands with extracts.
400 if (EnableGenExtract)
401 addPass(P: createHexagonGenExtract());
402 }
403}
404
405bool HexagonPassConfig::addInstSelector() {
406 HexagonTargetMachine &TM = getHexagonTargetMachine();
407 bool NoOpt = (getOptLevel() == CodeGenOptLevel::None);
408
409 if (!NoOpt)
410 addPass(P: createHexagonOptimizeSZextends());
411
412 addPass(P: createHexagonISelDag(TM, OptLevel: getOptLevel()));
413
414 if (!NoOpt) {
415 if (EnableVExtractOpt)
416 addPass(P: createHexagonVExtract());
417 // Create logical operations on predicate registers.
418 if (EnableGenPred)
419 addPass(P: createHexagonGenPredicate());
420 // Rotate loops to expose bit-simplification opportunities.
421 if (EnableLoopResched)
422 addPass(P: createHexagonLoopRescheduling());
423 // Split double registers.
424 if (!DisableHSDR)
425 addPass(P: createHexagonSplitDoubleRegs());
426 // Bit simplification.
427 if (EnableBitSimplify)
428 addPass(P: createHexagonBitSimplify());
429 addPass(P: createHexagonPeephole());
430 // Constant propagation.
431 if (!DisableHCP) {
432 addPass(P: createHexagonConstPropagationPass());
433 addPass(PassID: &UnreachableMachineBlockElimID);
434 }
435 if (EnableGenInsert)
436 addPass(P: createHexagonGenInsert());
437 if (EnableEarlyIf)
438 addPass(P: createHexagonEarlyIfConversion());
439 }
440
441 return false;
442}
443
444void HexagonPassConfig::addPreRegAlloc() {
445 if (getOptLevel() != CodeGenOptLevel::None) {
446 if (EnableCExtOpt)
447 addPass(P: createHexagonConstExtenders());
448 if (EnableExpandCondsets)
449 insertPass(TargetPassID: &RegisterCoalescerID, InsertedPassID: &HexagonExpandCondsetsID);
450 if (EnableCopyHoist)
451 insertPass(TargetPassID: &RegisterCoalescerID, InsertedPassID: &HexagonCopyHoistingID);
452 if (EnableTfrCleanup)
453 insertPass(TargetPassID: &VirtRegRewriterID, InsertedPassID: &HexagonTfrCleanupID);
454 if (!DisableStoreWidening)
455 addPass(P: createHexagonStoreWidening());
456 if (EnableGenMemAbs)
457 addPass(P: createHexagonGenMemAbsolute());
458 if (!DisableHardwareLoops)
459 addPass(P: createHexagonHardwareLoops());
460 }
461 if (TM->getOptLevel() >= CodeGenOptLevel::Default)
462 addPass(PassID: &MachinePipelinerID);
463}
464
465void HexagonPassConfig::addPostRegAlloc() {
466 if (getOptLevel() != CodeGenOptLevel::None) {
467 if (EnableRDFOpt)
468 addPass(P: createHexagonRDFOpt());
469 if (!DisableHexagonCFGOpt)
470 addPass(P: createHexagonCFGOptimizer());
471 if (!DisableAModeOpt)
472 addPass(P: createHexagonOptAddrMode());
473 }
474}
475
476void HexagonPassConfig::addPreSched2() {
477 addPass(P: createHexagonCopyToCombine());
478 if (getOptLevel() != CodeGenOptLevel::None)
479 addPass(PassID: &IfConverterID);
480 addPass(P: createHexagonSplitConst32AndConst64());
481}
482
483void HexagonPassConfig::addPreEmitPass() {
484 bool NoOpt = (getOptLevel() == CodeGenOptLevel::None);
485
486 if (!NoOpt)
487 addPass(P: createHexagonNewValueJump());
488
489 addPass(P: createHexagonBranchRelaxation());
490
491 if (!NoOpt) {
492 if (!DisableHardwareLoops)
493 addPass(P: createHexagonFixupHwLoops());
494 // Generate MUX from pairs of conditional transfers.
495 if (EnableGenMux)
496 addPass(P: createHexagonGenMux());
497 }
498
499 // Packetization is mandatory: it handles gather/scatter at all opt levels.
500 addPass(P: createHexagonPacketizer(Minimal: NoOpt));
501
502 if (!NoOpt)
503 addPass(P: createHexagonLoopAlign());
504
505 if (EnableVectorPrint)
506 addPass(P: createHexagonVectorPrint());
507
508 // Add CFI instructions if necessary.
509 addPass(P: createHexagonCallFrameInformation());
510}
511