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

source code of llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp