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