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
33 using namespace llvm;
34
35 static cl::opt<bool>
36 EnableCExtOpt("hexagon-cext", cl::Hidden, cl::init(true),
37 cl::desc("Enable Hexagon constant-extender optimization"));
38
39 static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::init(true),
40 cl::desc("Enable RDF-based optimizations"));
41
42 cl::opt<unsigned> RDFFuncBlockLimit(
43 "rdf-bb-limit", cl::Hidden, cl::init(1000),
44 cl::desc("Basic block limit for a function for RDF optimizations"));
45
46 static cl::opt<bool>
47 DisableHardwareLoops("disable-hexagon-hwloops", cl::Hidden,
48 cl::desc("Disable Hardware Loops for Hexagon target"));
49
50 static cl::opt<bool>
51 DisableAModeOpt("disable-hexagon-amodeopt", cl::Hidden,
52 cl::desc("Disable Hexagon Addressing Mode Optimization"));
53
54 static cl::opt<bool>
55 DisableHexagonCFGOpt("disable-hexagon-cfgopt", cl::Hidden,
56 cl::desc("Disable Hexagon CFG Optimization"));
57
58 static cl::opt<bool>
59 DisableHCP("disable-hcp", cl::Hidden,
60 cl::desc("Disable Hexagon constant propagation"));
61
62 static cl::opt<bool> DisableStoreWidening("disable-store-widen", cl::Hidden,
63 cl::init(false),
64 cl::desc("Disable store widening"));
65
66 static cl::opt<bool> EnableExpandCondsets("hexagon-expand-condsets",
67 cl::init(true), cl::Hidden,
68 cl::desc("Early expansion of MUX"));
69
70 static cl::opt<bool> EnableTfrCleanup("hexagon-tfr-cleanup", cl::init(true),
71 cl::Hidden,
72 cl::desc("Cleanup of TFRs/COPYs"));
73
74 static cl::opt<bool> EnableEarlyIf("hexagon-eif", cl::init(true), cl::Hidden,
75 cl::desc("Enable early if-conversion"));
76
77 static cl::opt<bool> EnableCopyHoist("hexagon-copy-hoist", cl::init(true),
78 cl::Hidden, cl::ZeroOrMore,
79 cl::desc("Enable Hexagon copy hoisting"));
80
81 static cl::opt<bool>
82 EnableGenInsert("hexagon-insert", cl::init(true), cl::Hidden,
83 cl::desc("Generate \"insert\" instructions"));
84
85 static cl::opt<bool>
86 EnableCommGEP("hexagon-commgep", cl::init(true), cl::Hidden,
87 cl::desc("Enable commoning of GEP instructions"));
88
89 static cl::opt<bool>
90 EnableGenExtract("hexagon-extract", cl::init(true), cl::Hidden,
91 cl::desc("Generate \"extract\" instructions"));
92
93 static cl::opt<bool> EnableGenMux(
94 "hexagon-mux", cl::init(true), cl::Hidden,
95 cl::desc("Enable converting conditional transfers into MUX instructions"));
96
97 static cl::opt<bool>
98 EnableGenPred("hexagon-gen-pred", cl::init(true), cl::Hidden,
99 cl::desc("Enable conversion of arithmetic operations to "
100 "predicate instructions"));
101
102 static cl::opt<bool>
103 EnableLoopPrefetch("hexagon-loop-prefetch", cl::Hidden,
104 cl::desc("Enable loop data prefetch on Hexagon"));
105
106 static cl::opt<bool>
107 DisableHSDR("disable-hsdr", cl::init(false), cl::Hidden,
108 cl::desc("Disable splitting double registers"));
109
110 static cl::opt<bool>
111 EnableGenMemAbs("hexagon-mem-abs", cl::init(true), cl::Hidden,
112 cl::desc("Generate absolute set instructions"));
113
114 static cl::opt<bool> EnableBitSimplify("hexagon-bit", cl::init(true),
115 cl::Hidden,
116 cl::desc("Bit simplification"));
117
118 static cl::opt<bool> EnableLoopResched("hexagon-loop-resched", cl::init(true),
119 cl::Hidden,
120 cl::desc("Loop rescheduling"));
121
122 static cl::opt<bool> HexagonNoOpt("hexagon-noopt", cl::init(false), cl::Hidden,
123 cl::desc("Disable backend optimizations"));
124
125 static cl::opt<bool>
126 EnableVectorPrint("enable-hexagon-vector-print", cl::Hidden,
127 cl::desc("Enable Hexagon Vector print instr pass"));
128
129 static cl::opt<bool>
130 EnableVExtractOpt("hexagon-opt-vextract", cl::Hidden, cl::init(true),
131 cl::desc("Enable vextract optimization"));
132
133 static cl::opt<bool>
134 EnableVectorCombine("hexagon-vector-combine", cl::Hidden, cl::init(true),
135 cl::desc("Enable HVX vector combining"));
136
137 static cl::opt<bool> EnableInitialCFGCleanup(
138 "hexagon-initial-cfg-cleanup", cl::Hidden, cl::init(true),
139 cl::desc("Simplify the CFG after atomic expansion pass"));
140
141 static cl::opt<bool> EnableInstSimplify("hexagon-instsimplify", cl::Hidden,
142 cl::init(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.
150 extern "C" int HexagonTargetMachineModule;
151 int HexagonTargetMachineModule = 0;
152
createVLIWMachineSched(MachineSchedContext * C)153 static ScheduleDAGInstrs *createVLIWMachineSched(MachineSchedContext *C) {
154 ScheduleDAGMILive *DAG = new VLIWMachineScheduler(
155 C, std::make_unique<HexagonConvergingVLIWScheduler>());
156 DAG->addMutation(std::make_unique<HexagonSubtarget::UsrOverflowMutation>());
157 DAG->addMutation(std::make_unique<HexagonSubtarget::HVXMemLatencyMutation>());
158 DAG->addMutation(std::make_unique<HexagonSubtarget::CallMutation>());
159 DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI));
160 return DAG;
161 }
162
163 static MachineSchedRegistry
164 SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler",
165 createVLIWMachineSched);
166
167 namespace llvm {
168 extern char &HexagonCopyHoistingID;
169 extern char &HexagonExpandCondsetsID;
170 extern char &HexagonTfrCleanupID;
171 void initializeHexagonBitSimplifyPass(PassRegistry &);
172 void initializeHexagonCopyHoistingPass(PassRegistry &);
173 void initializeHexagonConstExtendersPass(PassRegistry &);
174 void initializeHexagonConstPropagationPass(PassRegistry &);
175 void initializeHexagonCopyToCombinePass(PassRegistry &);
176 void initializeHexagonEarlyIfConversionPass(PassRegistry &);
177 void initializeHexagonExpandCondsetsPass(PassRegistry &);
178 void initializeHexagonGenMemAbsolutePass(PassRegistry &);
179 void initializeHexagonGenMuxPass(PassRegistry &);
180 void initializeHexagonHardwareLoopsPass(PassRegistry &);
181 void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &);
182 void initializeHexagonLoopAlignPass(PassRegistry &);
183 void initializeHexagonNewValueJumpPass(PassRegistry &);
184 void initializeHexagonOptAddrModePass(PassRegistry &);
185 void initializeHexagonPacketizerPass(PassRegistry &);
186 void initializeHexagonRDFOptPass(PassRegistry &);
187 void initializeHexagonSplitDoubleRegsPass(PassRegistry &);
188 void initializeHexagonTfrCleanupPass(PassRegistry &);
189 void initializeHexagonVExtractPass(PassRegistry &);
190 void initializeHexagonVectorCombineLegacyPass(PassRegistry &);
191 void initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PassRegistry &);
192 Pass *createHexagonLoopIdiomPass();
193 Pass *createHexagonVectorLoopCarriedReuseLegacyPass();
194
195 FunctionPass *createHexagonBitSimplify();
196 FunctionPass *createHexagonBranchRelaxation();
197 FunctionPass *createHexagonCallFrameInformation();
198 FunctionPass *createHexagonCFGOptimizer();
199 FunctionPass *createHexagonCommonGEP();
200 FunctionPass *createHexagonConstExtenders();
201 FunctionPass *createHexagonConstPropagationPass();
202 FunctionPass *createHexagonCopyHoisting();
203 FunctionPass *createHexagonCopyToCombine();
204 FunctionPass *createHexagonEarlyIfConversion();
205 FunctionPass *createHexagonFixupHwLoops();
206 FunctionPass *createHexagonGenExtract();
207 FunctionPass *createHexagonGenInsert();
208 FunctionPass *createHexagonGenMemAbsolute();
209 FunctionPass *createHexagonGenMux();
210 FunctionPass *createHexagonGenPredicate();
211 FunctionPass *createHexagonHardwareLoops();
212 FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM,
213 CodeGenOptLevel OptLevel);
214 FunctionPass *createHexagonLoopAlign();
215 FunctionPass *createHexagonLoopRescheduling();
216 FunctionPass *createHexagonNewValueJump();
217 FunctionPass *createHexagonOptAddrMode();
218 FunctionPass *createHexagonOptimizeSZextends();
219 FunctionPass *createHexagonPacketizer(bool Minimal);
220 FunctionPass *createHexagonPeephole();
221 FunctionPass *createHexagonRDFOpt();
222 FunctionPass *createHexagonSplitConst32AndConst64();
223 FunctionPass *createHexagonSplitDoubleRegs();
224 FunctionPass *createHexagonStoreWidening();
225 FunctionPass *createHexagonTfrCleanup();
226 FunctionPass *createHexagonVectorCombineLegacyPass();
227 FunctionPass *createHexagonVectorPrint();
228 FunctionPass *createHexagonVExtract();
229 } // namespace llvm
230
getEffectiveRelocModel(std::optional<Reloc::Model> RM)231 static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
232 return RM.value_or(Reloc::Static);
233 }
234
LLVMInitializeHexagonTarget()235 extern "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
HexagonTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool JIT)260 HexagonTargetMachine::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, 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
286 const HexagonSubtarget *
getSubtargetImpl(const Function & F) const287 HexagonTargetMachine::getSubtargetImpl(const Function &F) const {
288 AttributeList FnAttrs = F.getAttributes();
289 Attribute CPUAttr = FnAttrs.getFnAttr("target-cpu");
290 Attribute FSAttr = FnAttrs.getFnAttr("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("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>(TargetTriple, CPU, FS, *this);
311 }
312 return I.get();
313 }
314
registerPassBuilderCallbacks(PassBuilder & PB)315 void HexagonTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
316 #define GET_PASS_REGISTRY "HexagonPassRegistry.def"
317 #include "llvm/Passes/TargetPassRegistry.inc"
318
319 PB.registerLateLoopOptimizationsEPCallback(
320 [=](LoopPassManager &LPM, OptimizationLevel Level) {
321 LPM.addPass(HexagonLoopIdiomRecognitionPass());
322 });
323 PB.registerLoopOptimizerEndEPCallback(
324 [=](LoopPassManager &LPM, OptimizationLevel Level) {
325 LPM.addPass(HexagonVectorLoopCarriedReusePass());
326 });
327 }
328
329 TargetTransformInfo
getTargetTransformInfo(const Function & F) const330 HexagonTargetMachine::getTargetTransformInfo(const Function &F) const {
331 return TargetTransformInfo(HexagonTTIImpl(this, F));
332 }
333
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const334 MachineFunctionInfo *HexagonTargetMachine::createMachineFunctionInfo(
335 BumpPtrAllocator &Allocator, const Function &F,
336 const TargetSubtargetInfo *STI) const {
337 return HexagonMachineFunctionInfo::create<HexagonMachineFunctionInfo>(
338 Allocator, F, STI);
339 }
340
341 HexagonTargetMachine::~HexagonTargetMachine() = default;
342
343 namespace {
344 /// Hexagon Code Generator Pass Configuration Options.
345 class HexagonPassConfig : public TargetPassConfig {
346 public:
HexagonPassConfig(HexagonTargetMachine & TM,PassManagerBase & PM)347 HexagonPassConfig(HexagonTargetMachine &TM, PassManagerBase &PM)
348 : TargetPassConfig(TM, PM) {}
349
getHexagonTargetMachine() const350 HexagonTargetMachine &getHexagonTargetMachine() const {
351 return getTM<HexagonTargetMachine>();
352 }
353
354 ScheduleDAGInstrs *
createMachineScheduler(MachineSchedContext * C) const355 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
createPassConfig(PassManagerBase & PM)368 TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) {
369 return new HexagonPassConfig(*this, PM);
370 }
371
addIRPasses()372 void HexagonPassConfig::addIRPasses() {
373 TargetPassConfig::addIRPasses();
374 bool NoOpt = (getOptLevel() == CodeGenOptLevel::None);
375
376 if (!NoOpt) {
377 if (EnableInstSimplify)
378 addPass(createInstSimplifyLegacyPass());
379 addPass(createDeadCodeEliminationPass());
380 }
381
382 addPass(createAtomicExpandLegacyPass());
383
384 if (!NoOpt) {
385 if (EnableInitialCFGCleanup)
386 addPass(createCFGSimplificationPass(SimplifyCFGOptions()
387 .forwardSwitchCondToPhi(true)
388 .convertSwitchRangeToICmp(true)
389 .convertSwitchToLookupTable(true)
390 .needCanonicalLoops(false)
391 .hoistCommonInsts(true)
392 .sinkCommonInsts(true)));
393 if (EnableLoopPrefetch)
394 addPass(createLoopDataPrefetchPass());
395 if (EnableVectorCombine)
396 addPass(createHexagonVectorCombineLegacyPass());
397 if (EnableCommGEP)
398 addPass(createHexagonCommonGEP());
399 // Replace certain combinations of shifts and ands with extracts.
400 if (EnableGenExtract)
401 addPass(createHexagonGenExtract());
402 }
403 }
404
addInstSelector()405 bool HexagonPassConfig::addInstSelector() {
406 HexagonTargetMachine &TM = getHexagonTargetMachine();
407 bool NoOpt = (getOptLevel() == CodeGenOptLevel::None);
408
409 if (!NoOpt)
410 addPass(createHexagonOptimizeSZextends());
411
412 addPass(createHexagonISelDag(TM, getOptLevel()));
413
414 if (!NoOpt) {
415 if (EnableVExtractOpt)
416 addPass(createHexagonVExtract());
417 // Create logical operations on predicate registers.
418 if (EnableGenPred)
419 addPass(createHexagonGenPredicate());
420 // Rotate loops to expose bit-simplification opportunities.
421 if (EnableLoopResched)
422 addPass(createHexagonLoopRescheduling());
423 // Split double registers.
424 if (!DisableHSDR)
425 addPass(createHexagonSplitDoubleRegs());
426 // Bit simplification.
427 if (EnableBitSimplify)
428 addPass(createHexagonBitSimplify());
429 addPass(createHexagonPeephole());
430 // Constant propagation.
431 if (!DisableHCP) {
432 addPass(createHexagonConstPropagationPass());
433 addPass(&UnreachableMachineBlockElimID);
434 }
435 if (EnableGenInsert)
436 addPass(createHexagonGenInsert());
437 if (EnableEarlyIf)
438 addPass(createHexagonEarlyIfConversion());
439 }
440
441 return false;
442 }
443
addPreRegAlloc()444 void HexagonPassConfig::addPreRegAlloc() {
445 if (getOptLevel() != CodeGenOptLevel::None) {
446 if (EnableCExtOpt)
447 addPass(createHexagonConstExtenders());
448 if (EnableExpandCondsets)
449 insertPass(&RegisterCoalescerID, &HexagonExpandCondsetsID);
450 if (EnableCopyHoist)
451 insertPass(&RegisterCoalescerID, &HexagonCopyHoistingID);
452 if (EnableTfrCleanup)
453 insertPass(&VirtRegRewriterID, &HexagonTfrCleanupID);
454 if (!DisableStoreWidening)
455 addPass(createHexagonStoreWidening());
456 if (EnableGenMemAbs)
457 addPass(createHexagonGenMemAbsolute());
458 if (!DisableHardwareLoops)
459 addPass(createHexagonHardwareLoops());
460 }
461 if (TM->getOptLevel() >= CodeGenOptLevel::Default)
462 addPass(&MachinePipelinerID);
463 }
464
addPostRegAlloc()465 void HexagonPassConfig::addPostRegAlloc() {
466 if (getOptLevel() != CodeGenOptLevel::None) {
467 if (EnableRDFOpt)
468 addPass(createHexagonRDFOpt());
469 if (!DisableHexagonCFGOpt)
470 addPass(createHexagonCFGOptimizer());
471 if (!DisableAModeOpt)
472 addPass(createHexagonOptAddrMode());
473 }
474 }
475
addPreSched2()476 void HexagonPassConfig::addPreSched2() {
477 addPass(createHexagonCopyToCombine());
478 if (getOptLevel() != CodeGenOptLevel::None)
479 addPass(&IfConverterID);
480 addPass(createHexagonSplitConst32AndConst64());
481 }
482
addPreEmitPass()483 void HexagonPassConfig::addPreEmitPass() {
484 bool NoOpt = (getOptLevel() == CodeGenOptLevel::None);
485
486 if (!NoOpt)
487 addPass(createHexagonNewValueJump());
488
489 addPass(createHexagonBranchRelaxation());
490
491 if (!NoOpt) {
492 if (!DisableHardwareLoops)
493 addPass(createHexagonFixupHwLoops());
494 // Generate MUX from pairs of conditional transfers.
495 if (EnableGenMux)
496 addPass(createHexagonGenMux());
497 }
498
499 // Packetization is mandatory: it handles gather/scatter at all opt levels.
500 addPass(createHexagonPacketizer(NoOpt));
501
502 if (!NoOpt)
503 addPass(createHexagonLoopAlign());
504
505 if (EnableVectorPrint)
506 addPass(createHexagonVectorPrint());
507
508 // Add CFI instructions if necessary.
509 addPass(createHexagonCallFrameInformation());
510 }
511