10b57cec5SDimitry Andric //===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implements the info about Hexagon target spec. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "HexagonTargetMachine.h" 140b57cec5SDimitry Andric #include "Hexagon.h" 150b57cec5SDimitry Andric #include "HexagonISelLowering.h" 16e8d8bef9SDimitry Andric #include "HexagonLoopIdiomRecognition.h" 17bdd1243dSDimitry Andric #include "HexagonMachineFunctionInfo.h" 180b57cec5SDimitry Andric #include "HexagonMachineScheduler.h" 190b57cec5SDimitry Andric #include "HexagonTargetObjectFile.h" 200b57cec5SDimitry Andric #include "HexagonTargetTransformInfo.h" 21e8d8bef9SDimitry Andric #include "HexagonVectorLoopCarriedReuse.h" 220b57cec5SDimitry Andric #include "TargetInfo/HexagonTargetInfo.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 250eae32dcSDimitry Andric #include "llvm/CodeGen/VLIWMachineScheduler.h" 260b57cec5SDimitry Andric #include "llvm/IR/Module.h" 27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 28e8d8bef9SDimitry Andric #include "llvm/Passes/PassBuilder.h" 290b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 300b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 31bdd1243dSDimitry Andric #include <optional> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric using namespace llvm; 340b57cec5SDimitry Andric 3581ad6265SDimitry Andric static cl::opt<bool> 3681ad6265SDimitry Andric EnableCExtOpt("hexagon-cext", cl::Hidden, cl::init(true), 3781ad6265SDimitry Andric cl::desc("Enable Hexagon constant-extender optimization")); 380b57cec5SDimitry Andric 3981ad6265SDimitry Andric static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::init(true), 4081ad6265SDimitry Andric cl::desc("Enable RDF-based optimizations")); 410b57cec5SDimitry Andric 42*0fca6ea1SDimitry Andric cl::opt<unsigned> RDFFuncBlockLimit( 43*0fca6ea1SDimitry Andric "rdf-bb-limit", cl::Hidden, cl::init(1000), 44*0fca6ea1SDimitry Andric cl::desc("Basic block limit for a function for RDF optimizations")); 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric static cl::opt<bool> 47*0fca6ea1SDimitry Andric DisableHardwareLoops("disable-hexagon-hwloops", cl::Hidden, 48*0fca6ea1SDimitry Andric cl::desc("Disable Hardware Loops for Hexagon target")); 490b57cec5SDimitry Andric 5081ad6265SDimitry Andric static cl::opt<bool> 5181ad6265SDimitry Andric DisableAModeOpt("disable-hexagon-amodeopt", cl::Hidden, 520b57cec5SDimitry Andric cl::desc("Disable Hexagon Addressing Mode Optimization")); 530b57cec5SDimitry Andric 5481ad6265SDimitry Andric static cl::opt<bool> 5581ad6265SDimitry Andric DisableHexagonCFGOpt("disable-hexagon-cfgopt", cl::Hidden, 560b57cec5SDimitry Andric cl::desc("Disable Hexagon CFG Optimization")); 570b57cec5SDimitry Andric 5881ad6265SDimitry Andric static cl::opt<bool> 5981ad6265SDimitry Andric DisableHCP("disable-hcp", cl::Hidden, 6081ad6265SDimitry Andric cl::desc("Disable Hexagon constant propagation")); 610b57cec5SDimitry Andric 62*0fca6ea1SDimitry Andric static cl::opt<bool> DisableStoreWidening("disable-store-widen", cl::Hidden, 63*0fca6ea1SDimitry Andric cl::init(false), 64*0fca6ea1SDimitry Andric cl::desc("Disable store widening")); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static cl::opt<bool> EnableExpandCondsets("hexagon-expand-condsets", 6781ad6265SDimitry Andric cl::init(true), cl::Hidden, 680b57cec5SDimitry Andric cl::desc("Early expansion of MUX")); 690b57cec5SDimitry Andric 70*0fca6ea1SDimitry Andric static cl::opt<bool> EnableTfrCleanup("hexagon-tfr-cleanup", cl::init(true), 71*0fca6ea1SDimitry Andric cl::Hidden, 72*0fca6ea1SDimitry Andric cl::desc("Cleanup of TFRs/COPYs")); 73*0fca6ea1SDimitry Andric 740b57cec5SDimitry Andric static cl::opt<bool> EnableEarlyIf("hexagon-eif", cl::init(true), cl::Hidden, 7581ad6265SDimitry Andric cl::desc("Enable early if-conversion")); 760b57cec5SDimitry Andric 77*0fca6ea1SDimitry Andric static cl::opt<bool> EnableCopyHoist("hexagon-copy-hoist", cl::init(true), 78*0fca6ea1SDimitry Andric cl::Hidden, cl::ZeroOrMore, 79*0fca6ea1SDimitry Andric cl::desc("Enable Hexagon copy hoisting")); 80*0fca6ea1SDimitry Andric 81*0fca6ea1SDimitry Andric static cl::opt<bool> 82*0fca6ea1SDimitry Andric EnableGenInsert("hexagon-insert", cl::init(true), cl::Hidden, 83*0fca6ea1SDimitry Andric cl::desc("Generate \"insert\" instructions")); 840b57cec5SDimitry Andric 8581ad6265SDimitry Andric static cl::opt<bool> 8681ad6265SDimitry Andric EnableCommGEP("hexagon-commgep", cl::init(true), cl::Hidden, 8781ad6265SDimitry Andric cl::desc("Enable commoning of GEP instructions")); 880b57cec5SDimitry Andric 89*0fca6ea1SDimitry Andric static cl::opt<bool> 90*0fca6ea1SDimitry Andric EnableGenExtract("hexagon-extract", cl::init(true), cl::Hidden, 91*0fca6ea1SDimitry Andric cl::desc("Generate \"extract\" instructions")); 920b57cec5SDimitry Andric 93*0fca6ea1SDimitry Andric static cl::opt<bool> EnableGenMux( 94*0fca6ea1SDimitry Andric "hexagon-mux", cl::init(true), cl::Hidden, 950b57cec5SDimitry Andric cl::desc("Enable converting conditional transfers into MUX instructions")); 960b57cec5SDimitry Andric 97*0fca6ea1SDimitry Andric static cl::opt<bool> 98*0fca6ea1SDimitry Andric EnableGenPred("hexagon-gen-pred", cl::init(true), cl::Hidden, 99*0fca6ea1SDimitry Andric cl::desc("Enable conversion of arithmetic operations to " 1000b57cec5SDimitry Andric "predicate instructions")); 1010b57cec5SDimitry Andric 10281ad6265SDimitry Andric static cl::opt<bool> 10381ad6265SDimitry Andric EnableLoopPrefetch("hexagon-loop-prefetch", cl::Hidden, 1040b57cec5SDimitry Andric cl::desc("Enable loop data prefetch on Hexagon")); 1050b57cec5SDimitry Andric 106*0fca6ea1SDimitry Andric static cl::opt<bool> 107*0fca6ea1SDimitry Andric DisableHSDR("disable-hsdr", cl::init(false), cl::Hidden, 1080b57cec5SDimitry Andric cl::desc("Disable splitting double registers")); 1090b57cec5SDimitry Andric 110*0fca6ea1SDimitry Andric static cl::opt<bool> 111*0fca6ea1SDimitry Andric EnableGenMemAbs("hexagon-mem-abs", cl::init(true), cl::Hidden, 112*0fca6ea1SDimitry Andric cl::desc("Generate absolute set instructions")); 113*0fca6ea1SDimitry Andric 1140b57cec5SDimitry Andric static cl::opt<bool> EnableBitSimplify("hexagon-bit", cl::init(true), 115*0fca6ea1SDimitry Andric cl::Hidden, 116*0fca6ea1SDimitry Andric cl::desc("Bit simplification")); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric static cl::opt<bool> EnableLoopResched("hexagon-loop-resched", cl::init(true), 119*0fca6ea1SDimitry Andric cl::Hidden, 120*0fca6ea1SDimitry Andric cl::desc("Loop rescheduling")); 1210b57cec5SDimitry Andric 122*0fca6ea1SDimitry Andric static cl::opt<bool> HexagonNoOpt("hexagon-noopt", cl::init(false), cl::Hidden, 123*0fca6ea1SDimitry Andric cl::desc("Disable backend optimizations")); 1240b57cec5SDimitry Andric 12581ad6265SDimitry Andric static cl::opt<bool> 12681ad6265SDimitry Andric EnableVectorPrint("enable-hexagon-vector-print", cl::Hidden, 1270b57cec5SDimitry Andric cl::desc("Enable Hexagon Vector print instr pass")); 1280b57cec5SDimitry Andric 12981ad6265SDimitry Andric static cl::opt<bool> 13081ad6265SDimitry Andric EnableVExtractOpt("hexagon-opt-vextract", cl::Hidden, cl::init(true), 13181ad6265SDimitry Andric cl::desc("Enable vextract optimization")); 1320b57cec5SDimitry Andric 13381ad6265SDimitry Andric static cl::opt<bool> 13481ad6265SDimitry Andric EnableVectorCombine("hexagon-vector-combine", cl::Hidden, cl::init(true), 13581ad6265SDimitry Andric cl::desc("Enable HVX vector combining")); 136e8d8bef9SDimitry Andric 13781ad6265SDimitry Andric static cl::opt<bool> EnableInitialCFGCleanup( 13881ad6265SDimitry Andric "hexagon-initial-cfg-cleanup", cl::Hidden, cl::init(true), 1390b57cec5SDimitry Andric cl::desc("Simplify the CFG after atomic expansion pass")); 1400b57cec5SDimitry Andric 141e8d8bef9SDimitry Andric static cl::opt<bool> EnableInstSimplify("hexagon-instsimplify", cl::Hidden, 14281ad6265SDimitry Andric cl::init(true), 143e8d8bef9SDimitry Andric cl::desc("Enable instsimplify")); 144e8d8bef9SDimitry Andric 1450b57cec5SDimitry Andric /// HexagonTargetMachineModule - Note that this is used on hosts that 1460b57cec5SDimitry Andric /// cannot link in a library unless there are references into the 1470b57cec5SDimitry Andric /// library. In particular, it seems that it is not possible to get 1480b57cec5SDimitry Andric /// things to work on Win32 without this. Though it is unused, do not 1490b57cec5SDimitry Andric /// remove it. 1500b57cec5SDimitry Andric extern "C" int HexagonTargetMachineModule; 1510b57cec5SDimitry Andric int HexagonTargetMachineModule = 0; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric static ScheduleDAGInstrs *createVLIWMachineSched(MachineSchedContext *C) { 1540eae32dcSDimitry Andric ScheduleDAGMILive *DAG = new VLIWMachineScheduler( 1550eae32dcSDimitry Andric C, std::make_unique<HexagonConvergingVLIWScheduler>()); 1568bcb0991SDimitry Andric DAG->addMutation(std::make_unique<HexagonSubtarget::UsrOverflowMutation>()); 1578bcb0991SDimitry Andric DAG->addMutation(std::make_unique<HexagonSubtarget::HVXMemLatencyMutation>()); 1588bcb0991SDimitry Andric DAG->addMutation(std::make_unique<HexagonSubtarget::CallMutation>()); 1590b57cec5SDimitry Andric DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI)); 1600b57cec5SDimitry Andric return DAG; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric static MachineSchedRegistry 1640b57cec5SDimitry Andric SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler", 1650b57cec5SDimitry Andric createVLIWMachineSched); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric namespace llvm { 168*0fca6ea1SDimitry Andric extern char &HexagonCopyHoistingID; 1690b57cec5SDimitry Andric extern char &HexagonExpandCondsetsID; 170*0fca6ea1SDimitry Andric extern char &HexagonTfrCleanupID; 1710b57cec5SDimitry Andric void initializeHexagonBitSimplifyPass(PassRegistry &); 172*0fca6ea1SDimitry Andric void initializeHexagonCopyHoistingPass(PassRegistry &); 1730b57cec5SDimitry Andric void initializeHexagonConstExtendersPass(PassRegistry &); 1740b57cec5SDimitry Andric void initializeHexagonConstPropagationPass(PassRegistry &); 17504eeddc0SDimitry Andric void initializeHexagonCopyToCombinePass(PassRegistry &); 1760b57cec5SDimitry Andric void initializeHexagonEarlyIfConversionPass(PassRegistry &); 1770b57cec5SDimitry Andric void initializeHexagonExpandCondsetsPass(PassRegistry &); 178*0fca6ea1SDimitry Andric void initializeHexagonGenMemAbsolutePass(PassRegistry &); 1790b57cec5SDimitry Andric void initializeHexagonGenMuxPass(PassRegistry &); 1800b57cec5SDimitry Andric void initializeHexagonHardwareLoopsPass(PassRegistry &); 181e8d8bef9SDimitry Andric void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &); 182*0fca6ea1SDimitry Andric void initializeHexagonLoopAlignPass(PassRegistry &); 1830b57cec5SDimitry Andric void initializeHexagonNewValueJumpPass(PassRegistry &); 1840b57cec5SDimitry Andric void initializeHexagonOptAddrModePass(PassRegistry &); 1850b57cec5SDimitry Andric void initializeHexagonPacketizerPass(PassRegistry &); 1860b57cec5SDimitry Andric void initializeHexagonRDFOptPass(PassRegistry &); 1870b57cec5SDimitry Andric void initializeHexagonSplitDoubleRegsPass(PassRegistry &); 188*0fca6ea1SDimitry Andric void initializeHexagonTfrCleanupPass(PassRegistry &); 189bdd1243dSDimitry Andric void initializeHexagonVExtractPass(PassRegistry &); 190e8d8bef9SDimitry Andric void initializeHexagonVectorCombineLegacyPass(PassRegistry &); 191e8d8bef9SDimitry Andric void initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PassRegistry &); 1920b57cec5SDimitry Andric Pass *createHexagonLoopIdiomPass(); 193e8d8bef9SDimitry Andric Pass *createHexagonVectorLoopCarriedReuseLegacyPass(); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric FunctionPass *createHexagonBitSimplify(); 1960b57cec5SDimitry Andric FunctionPass *createHexagonBranchRelaxation(); 1970b57cec5SDimitry Andric FunctionPass *createHexagonCallFrameInformation(); 1980b57cec5SDimitry Andric FunctionPass *createHexagonCFGOptimizer(); 1990b57cec5SDimitry Andric FunctionPass *createHexagonCommonGEP(); 2000b57cec5SDimitry Andric FunctionPass *createHexagonConstExtenders(); 2010b57cec5SDimitry Andric FunctionPass *createHexagonConstPropagationPass(); 202*0fca6ea1SDimitry Andric FunctionPass *createHexagonCopyHoisting(); 2030b57cec5SDimitry Andric FunctionPass *createHexagonCopyToCombine(); 2040b57cec5SDimitry Andric FunctionPass *createHexagonEarlyIfConversion(); 2050b57cec5SDimitry Andric FunctionPass *createHexagonFixupHwLoops(); 2060b57cec5SDimitry Andric FunctionPass *createHexagonGenExtract(); 2070b57cec5SDimitry Andric FunctionPass *createHexagonGenInsert(); 208*0fca6ea1SDimitry Andric FunctionPass *createHexagonGenMemAbsolute(); 2090b57cec5SDimitry Andric FunctionPass *createHexagonGenMux(); 2100b57cec5SDimitry Andric FunctionPass *createHexagonGenPredicate(); 2110b57cec5SDimitry Andric FunctionPass *createHexagonHardwareLoops(); 2120b57cec5SDimitry Andric FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, 2135f757f3fSDimitry Andric CodeGenOptLevel OptLevel); 214*0fca6ea1SDimitry Andric FunctionPass *createHexagonLoopAlign(); 2150b57cec5SDimitry Andric FunctionPass *createHexagonLoopRescheduling(); 2160b57cec5SDimitry Andric FunctionPass *createHexagonNewValueJump(); 2170b57cec5SDimitry Andric FunctionPass *createHexagonOptAddrMode(); 218e8d8bef9SDimitry Andric FunctionPass *createHexagonOptimizeSZextends(); 2190b57cec5SDimitry Andric FunctionPass *createHexagonPacketizer(bool Minimal); 2200b57cec5SDimitry Andric FunctionPass *createHexagonPeephole(); 2210b57cec5SDimitry Andric FunctionPass *createHexagonRDFOpt(); 2220b57cec5SDimitry Andric FunctionPass *createHexagonSplitConst32AndConst64(); 2230b57cec5SDimitry Andric FunctionPass *createHexagonSplitDoubleRegs(); 2240b57cec5SDimitry Andric FunctionPass *createHexagonStoreWidening(); 225*0fca6ea1SDimitry Andric FunctionPass *createHexagonTfrCleanup(); 226e8d8bef9SDimitry Andric FunctionPass *createHexagonVectorCombineLegacyPass(); 2270b57cec5SDimitry Andric FunctionPass *createHexagonVectorPrint(); 2280b57cec5SDimitry Andric FunctionPass *createHexagonVExtract(); 229*0fca6ea1SDimitry Andric } // namespace llvm 2300b57cec5SDimitry Andric 231bdd1243dSDimitry Andric static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) { 23281ad6265SDimitry Andric return RM.value_or(Reloc::Static); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 235480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonTarget() { 2360b57cec5SDimitry Andric // Register the target. 2370b57cec5SDimitry Andric RegisterTargetMachine<HexagonTargetMachine> X(getTheHexagonTarget()); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric PassRegistry &PR = *PassRegistry::getPassRegistry(); 2400b57cec5SDimitry Andric initializeHexagonBitSimplifyPass(PR); 2410b57cec5SDimitry Andric initializeHexagonConstExtendersPass(PR); 2420b57cec5SDimitry Andric initializeHexagonConstPropagationPass(PR); 24304eeddc0SDimitry Andric initializeHexagonCopyToCombinePass(PR); 2440b57cec5SDimitry Andric initializeHexagonEarlyIfConversionPass(PR); 245*0fca6ea1SDimitry Andric initializeHexagonGenMemAbsolutePass(PR); 2460b57cec5SDimitry Andric initializeHexagonGenMuxPass(PR); 2470b57cec5SDimitry Andric initializeHexagonHardwareLoopsPass(PR); 248e8d8bef9SDimitry Andric initializeHexagonLoopIdiomRecognizeLegacyPassPass(PR); 2490b57cec5SDimitry Andric initializeHexagonNewValueJumpPass(PR); 2500b57cec5SDimitry Andric initializeHexagonOptAddrModePass(PR); 2510b57cec5SDimitry Andric initializeHexagonPacketizerPass(PR); 2520b57cec5SDimitry Andric initializeHexagonRDFOptPass(PR); 2530b57cec5SDimitry Andric initializeHexagonSplitDoubleRegsPass(PR); 254e8d8bef9SDimitry Andric initializeHexagonVectorCombineLegacyPass(PR); 255e8d8bef9SDimitry Andric initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PR); 2560b57cec5SDimitry Andric initializeHexagonVExtractPass(PR); 257*0fca6ea1SDimitry Andric initializeHexagonDAGToDAGISelLegacyPass(PR); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT, 2610b57cec5SDimitry Andric StringRef CPU, StringRef FS, 2620b57cec5SDimitry Andric const TargetOptions &Options, 263bdd1243dSDimitry Andric std::optional<Reloc::Model> RM, 264bdd1243dSDimitry Andric std::optional<CodeModel::Model> CM, 2655f757f3fSDimitry Andric CodeGenOptLevel OL, bool JIT) 2660b57cec5SDimitry Andric // Specify the vector alignment explicitly. For v512x1, the calculated 2670b57cec5SDimitry Andric // alignment would be 512*alignment(i1), which is 512 bytes, instead of 2680b57cec5SDimitry Andric // the required minimum of 64 bytes. 2690b57cec5SDimitry Andric : LLVMTargetMachine( 2700b57cec5SDimitry Andric T, 2710b57cec5SDimitry Andric "e-m:e-p:32:32:32-a:0-n16:32-" 2720b57cec5SDimitry Andric "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-" 2730b57cec5SDimitry Andric "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048", 2740b57cec5SDimitry Andric TT, CPU, FS, Options, getEffectiveRelocModel(RM), 2750b57cec5SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), 2765f757f3fSDimitry Andric (HexagonNoOpt ? CodeGenOptLevel::None : OL)), 277*0fca6ea1SDimitry Andric TLOF(std::make_unique<HexagonTargetObjectFile>()), 278*0fca6ea1SDimitry Andric Subtarget(Triple(TT), CPU, FS, *this) { 279*0fca6ea1SDimitry Andric initializeHexagonCopyHoistingPass(*PassRegistry::getPassRegistry()); 2800b57cec5SDimitry Andric initializeHexagonExpandCondsetsPass(*PassRegistry::getPassRegistry()); 281*0fca6ea1SDimitry Andric initializeHexagonLoopAlignPass(*PassRegistry::getPassRegistry()); 282*0fca6ea1SDimitry Andric initializeHexagonTfrCleanupPass(*PassRegistry::getPassRegistry()); 2830b57cec5SDimitry Andric initAsmInfo(); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric const HexagonSubtarget * 2870b57cec5SDimitry Andric HexagonTargetMachine::getSubtargetImpl(const Function &F) const { 2880b57cec5SDimitry Andric AttributeList FnAttrs = F.getAttributes(); 289*0fca6ea1SDimitry Andric Attribute CPUAttr = FnAttrs.getFnAttr("target-cpu"); 290*0fca6ea1SDimitry Andric Attribute FSAttr = FnAttrs.getFnAttr("target-features"); 2910b57cec5SDimitry Andric 292e8d8bef9SDimitry Andric std::string CPU = 293e8d8bef9SDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 294e8d8bef9SDimitry Andric std::string FS = 295e8d8bef9SDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 2965ffd83dbSDimitry Andric // Append the preexisting target features last, so that +mattr overrides 2975ffd83dbSDimitry Andric // the "unsafe-fp-math" function attribute. 2985ffd83dbSDimitry Andric // Creating a separate target feature is not strictly necessary, it only 2995ffd83dbSDimitry Andric // exists to make "unsafe-fp-math" force creating a new subtarget. 3005ffd83dbSDimitry Andric 301fe6060f1SDimitry Andric if (F.getFnAttribute("unsafe-fp-math").getValueAsBool()) 3025ffd83dbSDimitry Andric FS = FS.empty() ? "+unsafe-fp" : "+unsafe-fp," + FS; 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 3050b57cec5SDimitry Andric if (!I) { 3060b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 3070b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 3080b57cec5SDimitry Andric // function that reside in TargetOptions. 3090b57cec5SDimitry Andric resetTargetOptions(F); 3108bcb0991SDimitry Andric I = std::make_unique<HexagonSubtarget>(TargetTriple, CPU, FS, *this); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric return I.get(); 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 315*0fca6ea1SDimitry Andric void HexagonTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { 316*0fca6ea1SDimitry Andric #define GET_PASS_REGISTRY "HexagonPassRegistry.def" 317*0fca6ea1SDimitry Andric #include "llvm/Passes/TargetPassRegistry.inc" 318*0fca6ea1SDimitry Andric 319e8d8bef9SDimitry Andric PB.registerLateLoopOptimizationsEPCallback( 320349cc55cSDimitry Andric [=](LoopPassManager &LPM, OptimizationLevel Level) { 321e8d8bef9SDimitry Andric LPM.addPass(HexagonLoopIdiomRecognitionPass()); 322e8d8bef9SDimitry Andric }); 323e8d8bef9SDimitry Andric PB.registerLoopOptimizerEndEPCallback( 324349cc55cSDimitry Andric [=](LoopPassManager &LPM, OptimizationLevel Level) { 325e8d8bef9SDimitry Andric LPM.addPass(HexagonVectorLoopCarriedReusePass()); 3260b57cec5SDimitry Andric }); 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric TargetTransformInfo 33081ad6265SDimitry Andric HexagonTargetMachine::getTargetTransformInfo(const Function &F) const { 3310b57cec5SDimitry Andric return TargetTransformInfo(HexagonTTIImpl(this, F)); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 334bdd1243dSDimitry Andric MachineFunctionInfo *HexagonTargetMachine::createMachineFunctionInfo( 335bdd1243dSDimitry Andric BumpPtrAllocator &Allocator, const Function &F, 336bdd1243dSDimitry Andric const TargetSubtargetInfo *STI) const { 337bdd1243dSDimitry Andric return HexagonMachineFunctionInfo::create<HexagonMachineFunctionInfo>( 338bdd1243dSDimitry Andric Allocator, F, STI); 339bdd1243dSDimitry Andric } 340bdd1243dSDimitry Andric 34181ad6265SDimitry Andric HexagonTargetMachine::~HexagonTargetMachine() = default; 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric namespace { 3440b57cec5SDimitry Andric /// Hexagon Code Generator Pass Configuration Options. 3450b57cec5SDimitry Andric class HexagonPassConfig : public TargetPassConfig { 3460b57cec5SDimitry Andric public: 3470b57cec5SDimitry Andric HexagonPassConfig(HexagonTargetMachine &TM, PassManagerBase &PM) 3480b57cec5SDimitry Andric : TargetPassConfig(TM, PM) {} 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric HexagonTargetMachine &getHexagonTargetMachine() const { 3510b57cec5SDimitry Andric return getTM<HexagonTargetMachine>(); 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric ScheduleDAGInstrs * 3550b57cec5SDimitry Andric createMachineScheduler(MachineSchedContext *C) const override { 3560b57cec5SDimitry Andric return createVLIWMachineSched(C); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric void addIRPasses() override; 3600b57cec5SDimitry Andric bool addInstSelector() override; 3610b57cec5SDimitry Andric void addPreRegAlloc() override; 3620b57cec5SDimitry Andric void addPostRegAlloc() override; 3630b57cec5SDimitry Andric void addPreSched2() override; 3640b57cec5SDimitry Andric void addPreEmitPass() override; 3650b57cec5SDimitry Andric }; 3660b57cec5SDimitry Andric } // namespace 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) { 3690b57cec5SDimitry Andric return new HexagonPassConfig(*this, PM); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric void HexagonPassConfig::addIRPasses() { 3730b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 3745f757f3fSDimitry Andric bool NoOpt = (getOptLevel() == CodeGenOptLevel::None); 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric if (!NoOpt) { 377e8d8bef9SDimitry Andric if (EnableInstSimplify) 378e8d8bef9SDimitry Andric addPass(createInstSimplifyLegacyPass()); 3790b57cec5SDimitry Andric addPass(createDeadCodeEliminationPass()); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 382*0fca6ea1SDimitry Andric addPass(createAtomicExpandLegacyPass()); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric if (!NoOpt) { 3850b57cec5SDimitry Andric if (EnableInitialCFGCleanup) 386e8d8bef9SDimitry Andric addPass(createCFGSimplificationPass(SimplifyCFGOptions() 387e8d8bef9SDimitry Andric .forwardSwitchCondToPhi(true) 388fb03ea46SDimitry Andric .convertSwitchRangeToICmp(true) 389e8d8bef9SDimitry Andric .convertSwitchToLookupTable(true) 390e8d8bef9SDimitry Andric .needCanonicalLoops(false) 391e8d8bef9SDimitry Andric .hoistCommonInsts(true) 392e8d8bef9SDimitry Andric .sinkCommonInsts(true))); 3930b57cec5SDimitry Andric if (EnableLoopPrefetch) 3940b57cec5SDimitry Andric addPass(createLoopDataPrefetchPass()); 395e8d8bef9SDimitry Andric if (EnableVectorCombine) 396e8d8bef9SDimitry Andric addPass(createHexagonVectorCombineLegacyPass()); 3970b57cec5SDimitry Andric if (EnableCommGEP) 3980b57cec5SDimitry Andric addPass(createHexagonCommonGEP()); 3990b57cec5SDimitry Andric // Replace certain combinations of shifts and ands with extracts. 4000b57cec5SDimitry Andric if (EnableGenExtract) 4010b57cec5SDimitry Andric addPass(createHexagonGenExtract()); 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric bool HexagonPassConfig::addInstSelector() { 4060b57cec5SDimitry Andric HexagonTargetMachine &TM = getHexagonTargetMachine(); 4075f757f3fSDimitry Andric bool NoOpt = (getOptLevel() == CodeGenOptLevel::None); 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric if (!NoOpt) 4100b57cec5SDimitry Andric addPass(createHexagonOptimizeSZextends()); 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric addPass(createHexagonISelDag(TM, getOptLevel())); 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric if (!NoOpt) { 4150b57cec5SDimitry Andric if (EnableVExtractOpt) 4160b57cec5SDimitry Andric addPass(createHexagonVExtract()); 4170b57cec5SDimitry Andric // Create logical operations on predicate registers. 4180b57cec5SDimitry Andric if (EnableGenPred) 4190b57cec5SDimitry Andric addPass(createHexagonGenPredicate()); 4200b57cec5SDimitry Andric // Rotate loops to expose bit-simplification opportunities. 4210b57cec5SDimitry Andric if (EnableLoopResched) 4220b57cec5SDimitry Andric addPass(createHexagonLoopRescheduling()); 4230b57cec5SDimitry Andric // Split double registers. 4240b57cec5SDimitry Andric if (!DisableHSDR) 4250b57cec5SDimitry Andric addPass(createHexagonSplitDoubleRegs()); 4260b57cec5SDimitry Andric // Bit simplification. 4270b57cec5SDimitry Andric if (EnableBitSimplify) 4280b57cec5SDimitry Andric addPass(createHexagonBitSimplify()); 4290b57cec5SDimitry Andric addPass(createHexagonPeephole()); 4300b57cec5SDimitry Andric // Constant propagation. 4310b57cec5SDimitry Andric if (!DisableHCP) { 4320b57cec5SDimitry Andric addPass(createHexagonConstPropagationPass()); 4330b57cec5SDimitry Andric addPass(&UnreachableMachineBlockElimID); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric if (EnableGenInsert) 4360b57cec5SDimitry Andric addPass(createHexagonGenInsert()); 4370b57cec5SDimitry Andric if (EnableEarlyIf) 4380b57cec5SDimitry Andric addPass(createHexagonEarlyIfConversion()); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric 4410b57cec5SDimitry Andric return false; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric void HexagonPassConfig::addPreRegAlloc() { 4455f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) { 4460b57cec5SDimitry Andric if (EnableCExtOpt) 4470b57cec5SDimitry Andric addPass(createHexagonConstExtenders()); 4480b57cec5SDimitry Andric if (EnableExpandCondsets) 4490b57cec5SDimitry Andric insertPass(&RegisterCoalescerID, &HexagonExpandCondsetsID); 450*0fca6ea1SDimitry Andric if (EnableCopyHoist) 451*0fca6ea1SDimitry Andric insertPass(&RegisterCoalescerID, &HexagonCopyHoistingID); 452*0fca6ea1SDimitry Andric if (EnableTfrCleanup) 453*0fca6ea1SDimitry Andric insertPass(&VirtRegRewriterID, &HexagonTfrCleanupID); 4540b57cec5SDimitry Andric if (!DisableStoreWidening) 4550b57cec5SDimitry Andric addPass(createHexagonStoreWidening()); 456*0fca6ea1SDimitry Andric if (EnableGenMemAbs) 457*0fca6ea1SDimitry Andric addPass(createHexagonGenMemAbsolute()); 4580b57cec5SDimitry Andric if (!DisableHardwareLoops) 4590b57cec5SDimitry Andric addPass(createHexagonHardwareLoops()); 4600b57cec5SDimitry Andric } 4615f757f3fSDimitry Andric if (TM->getOptLevel() >= CodeGenOptLevel::Default) 4620b57cec5SDimitry Andric addPass(&MachinePipelinerID); 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric void HexagonPassConfig::addPostRegAlloc() { 4665f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) { 4670b57cec5SDimitry Andric if (EnableRDFOpt) 4680b57cec5SDimitry Andric addPass(createHexagonRDFOpt()); 4690b57cec5SDimitry Andric if (!DisableHexagonCFGOpt) 4700b57cec5SDimitry Andric addPass(createHexagonCFGOptimizer()); 4710b57cec5SDimitry Andric if (!DisableAModeOpt) 4720b57cec5SDimitry Andric addPass(createHexagonOptAddrMode()); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric void HexagonPassConfig::addPreSched2() { 4770b57cec5SDimitry Andric addPass(createHexagonCopyToCombine()); 4785f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) 4790b57cec5SDimitry Andric addPass(&IfConverterID); 4800b57cec5SDimitry Andric addPass(createHexagonSplitConst32AndConst64()); 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric void HexagonPassConfig::addPreEmitPass() { 4845f757f3fSDimitry Andric bool NoOpt = (getOptLevel() == CodeGenOptLevel::None); 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric if (!NoOpt) 4870b57cec5SDimitry Andric addPass(createHexagonNewValueJump()); 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric addPass(createHexagonBranchRelaxation()); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric if (!NoOpt) { 4920b57cec5SDimitry Andric if (!DisableHardwareLoops) 4930b57cec5SDimitry Andric addPass(createHexagonFixupHwLoops()); 4940b57cec5SDimitry Andric // Generate MUX from pairs of conditional transfers. 4950b57cec5SDimitry Andric if (EnableGenMux) 4960b57cec5SDimitry Andric addPass(createHexagonGenMux()); 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // Packetization is mandatory: it handles gather/scatter at all opt levels. 500349cc55cSDimitry Andric addPass(createHexagonPacketizer(NoOpt)); 5010b57cec5SDimitry Andric 502*0fca6ea1SDimitry Andric if (!NoOpt) 503*0fca6ea1SDimitry Andric addPass(createHexagonLoopAlign()); 504*0fca6ea1SDimitry Andric 5050b57cec5SDimitry Andric if (EnableVectorPrint) 506349cc55cSDimitry Andric addPass(createHexagonVectorPrint()); 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // Add CFI instructions if necessary. 509349cc55cSDimitry Andric addPass(createHexagonCallFrameInformation()); 5100b57cec5SDimitry Andric } 511