1*0b57cec5SDimitry Andric //===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // Implements the info about Hexagon target spec. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "HexagonTargetMachine.h" 14*0b57cec5SDimitry Andric #include "Hexagon.h" 15*0b57cec5SDimitry Andric #include "HexagonISelLowering.h" 16*0b57cec5SDimitry Andric #include "HexagonMachineScheduler.h" 17*0b57cec5SDimitry Andric #include "HexagonTargetObjectFile.h" 18*0b57cec5SDimitry Andric #include "HexagonTargetTransformInfo.h" 19*0b57cec5SDimitry Andric #include "TargetInfo/HexagonTargetInfo.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 22*0b57cec5SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 23*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 24*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 25*0b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 26*0b57cec5SDimitry Andric #include "llvm/Transforms/IPO/PassManagerBuilder.h" 27*0b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric using namespace llvm; 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric static cl::opt<bool> EnableCExtOpt("hexagon-cext", cl::Hidden, cl::ZeroOrMore, 32*0b57cec5SDimitry Andric cl::init(true), cl::desc("Enable Hexagon constant-extender optimization")); 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::ZeroOrMore, 35*0b57cec5SDimitry Andric cl::init(true), cl::desc("Enable RDF-based optimizations")); 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric static cl::opt<bool> DisableHardwareLoops("disable-hexagon-hwloops", 38*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Disable Hardware Loops for Hexagon target")); 39*0b57cec5SDimitry Andric 40*0b57cec5SDimitry Andric static cl::opt<bool> DisableAModeOpt("disable-hexagon-amodeopt", 41*0b57cec5SDimitry Andric cl::Hidden, cl::ZeroOrMore, cl::init(false), 42*0b57cec5SDimitry Andric cl::desc("Disable Hexagon Addressing Mode Optimization")); 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric static cl::opt<bool> DisableHexagonCFGOpt("disable-hexagon-cfgopt", 45*0b57cec5SDimitry Andric cl::Hidden, cl::ZeroOrMore, cl::init(false), 46*0b57cec5SDimitry Andric cl::desc("Disable Hexagon CFG Optimization")); 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric static cl::opt<bool> DisableHCP("disable-hcp", cl::init(false), cl::Hidden, 49*0b57cec5SDimitry Andric cl::ZeroOrMore, cl::desc("Disable Hexagon constant propagation")); 50*0b57cec5SDimitry Andric 51*0b57cec5SDimitry Andric static cl::opt<bool> DisableStoreWidening("disable-store-widen", 52*0b57cec5SDimitry Andric cl::Hidden, cl::init(false), cl::desc("Disable store widening")); 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric static cl::opt<bool> EnableExpandCondsets("hexagon-expand-condsets", 55*0b57cec5SDimitry Andric cl::init(true), cl::Hidden, cl::ZeroOrMore, 56*0b57cec5SDimitry Andric cl::desc("Early expansion of MUX")); 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric static cl::opt<bool> EnableEarlyIf("hexagon-eif", cl::init(true), cl::Hidden, 59*0b57cec5SDimitry Andric cl::ZeroOrMore, cl::desc("Enable early if-conversion")); 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric static cl::opt<bool> EnableGenInsert("hexagon-insert", cl::init(true), 62*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Generate \"insert\" instructions")); 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric static cl::opt<bool> EnableCommGEP("hexagon-commgep", cl::init(true), 65*0b57cec5SDimitry Andric cl::Hidden, cl::ZeroOrMore, cl::desc("Enable commoning of GEP instructions")); 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric static cl::opt<bool> EnableGenExtract("hexagon-extract", cl::init(true), 68*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Generate \"extract\" instructions")); 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric static cl::opt<bool> EnableGenMux("hexagon-mux", cl::init(true), cl::Hidden, 71*0b57cec5SDimitry Andric cl::desc("Enable converting conditional transfers into MUX instructions")); 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric static cl::opt<bool> EnableGenPred("hexagon-gen-pred", cl::init(true), 74*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Enable conversion of arithmetic operations to " 75*0b57cec5SDimitry Andric "predicate instructions")); 76*0b57cec5SDimitry Andric 77*0b57cec5SDimitry Andric static cl::opt<bool> EnableLoopPrefetch("hexagon-loop-prefetch", 78*0b57cec5SDimitry Andric cl::init(false), cl::Hidden, cl::ZeroOrMore, 79*0b57cec5SDimitry Andric cl::desc("Enable loop data prefetch on Hexagon")); 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric static cl::opt<bool> DisableHSDR("disable-hsdr", cl::init(false), cl::Hidden, 82*0b57cec5SDimitry Andric cl::desc("Disable splitting double registers")); 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric static cl::opt<bool> EnableBitSimplify("hexagon-bit", cl::init(true), 85*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Bit simplification")); 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric static cl::opt<bool> EnableLoopResched("hexagon-loop-resched", cl::init(true), 88*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Loop rescheduling")); 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric static cl::opt<bool> HexagonNoOpt("hexagon-noopt", cl::init(false), 91*0b57cec5SDimitry Andric cl::Hidden, cl::desc("Disable backend optimizations")); 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric static cl::opt<bool> EnableVectorPrint("enable-hexagon-vector-print", 94*0b57cec5SDimitry Andric cl::Hidden, cl::ZeroOrMore, cl::init(false), 95*0b57cec5SDimitry Andric cl::desc("Enable Hexagon Vector print instr pass")); 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric static cl::opt<bool> EnableVExtractOpt("hexagon-opt-vextract", cl::Hidden, 98*0b57cec5SDimitry Andric cl::ZeroOrMore, cl::init(true), cl::desc("Enable vextract optimization")); 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric static cl::opt<bool> EnableInitialCFGCleanup("hexagon-initial-cfg-cleanup", 101*0b57cec5SDimitry Andric cl::Hidden, cl::ZeroOrMore, cl::init(true), 102*0b57cec5SDimitry Andric cl::desc("Simplify the CFG after atomic expansion pass")); 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric /// HexagonTargetMachineModule - Note that this is used on hosts that 105*0b57cec5SDimitry Andric /// cannot link in a library unless there are references into the 106*0b57cec5SDimitry Andric /// library. In particular, it seems that it is not possible to get 107*0b57cec5SDimitry Andric /// things to work on Win32 without this. Though it is unused, do not 108*0b57cec5SDimitry Andric /// remove it. 109*0b57cec5SDimitry Andric extern "C" int HexagonTargetMachineModule; 110*0b57cec5SDimitry Andric int HexagonTargetMachineModule = 0; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric static ScheduleDAGInstrs *createVLIWMachineSched(MachineSchedContext *C) { 113*0b57cec5SDimitry Andric ScheduleDAGMILive *DAG = 114*0b57cec5SDimitry Andric new VLIWMachineScheduler(C, make_unique<ConvergingVLIWScheduler>()); 115*0b57cec5SDimitry Andric DAG->addMutation(make_unique<HexagonSubtarget::UsrOverflowMutation>()); 116*0b57cec5SDimitry Andric DAG->addMutation(make_unique<HexagonSubtarget::HVXMemLatencyMutation>()); 117*0b57cec5SDimitry Andric DAG->addMutation(make_unique<HexagonSubtarget::CallMutation>()); 118*0b57cec5SDimitry Andric DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI)); 119*0b57cec5SDimitry Andric return DAG; 120*0b57cec5SDimitry Andric } 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric static MachineSchedRegistry 123*0b57cec5SDimitry Andric SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler", 124*0b57cec5SDimitry Andric createVLIWMachineSched); 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric namespace llvm { 127*0b57cec5SDimitry Andric extern char &HexagonExpandCondsetsID; 128*0b57cec5SDimitry Andric void initializeHexagonBitSimplifyPass(PassRegistry&); 129*0b57cec5SDimitry Andric void initializeHexagonConstExtendersPass(PassRegistry&); 130*0b57cec5SDimitry Andric void initializeHexagonConstPropagationPass(PassRegistry&); 131*0b57cec5SDimitry Andric void initializeHexagonEarlyIfConversionPass(PassRegistry&); 132*0b57cec5SDimitry Andric void initializeHexagonExpandCondsetsPass(PassRegistry&); 133*0b57cec5SDimitry Andric void initializeHexagonGenMuxPass(PassRegistry&); 134*0b57cec5SDimitry Andric void initializeHexagonHardwareLoopsPass(PassRegistry&); 135*0b57cec5SDimitry Andric void initializeHexagonLoopIdiomRecognizePass(PassRegistry&); 136*0b57cec5SDimitry Andric void initializeHexagonVectorLoopCarriedReusePass(PassRegistry&); 137*0b57cec5SDimitry Andric void initializeHexagonNewValueJumpPass(PassRegistry&); 138*0b57cec5SDimitry Andric void initializeHexagonOptAddrModePass(PassRegistry&); 139*0b57cec5SDimitry Andric void initializeHexagonPacketizerPass(PassRegistry&); 140*0b57cec5SDimitry Andric void initializeHexagonRDFOptPass(PassRegistry&); 141*0b57cec5SDimitry Andric void initializeHexagonSplitDoubleRegsPass(PassRegistry&); 142*0b57cec5SDimitry Andric void initializeHexagonVExtractPass(PassRegistry&); 143*0b57cec5SDimitry Andric Pass *createHexagonLoopIdiomPass(); 144*0b57cec5SDimitry Andric Pass *createHexagonVectorLoopCarriedReusePass(); 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric FunctionPass *createHexagonBitSimplify(); 147*0b57cec5SDimitry Andric FunctionPass *createHexagonBranchRelaxation(); 148*0b57cec5SDimitry Andric FunctionPass *createHexagonCallFrameInformation(); 149*0b57cec5SDimitry Andric FunctionPass *createHexagonCFGOptimizer(); 150*0b57cec5SDimitry Andric FunctionPass *createHexagonCommonGEP(); 151*0b57cec5SDimitry Andric FunctionPass *createHexagonConstExtenders(); 152*0b57cec5SDimitry Andric FunctionPass *createHexagonConstPropagationPass(); 153*0b57cec5SDimitry Andric FunctionPass *createHexagonCopyToCombine(); 154*0b57cec5SDimitry Andric FunctionPass *createHexagonEarlyIfConversion(); 155*0b57cec5SDimitry Andric FunctionPass *createHexagonFixupHwLoops(); 156*0b57cec5SDimitry Andric FunctionPass *createHexagonGenExtract(); 157*0b57cec5SDimitry Andric FunctionPass *createHexagonGenInsert(); 158*0b57cec5SDimitry Andric FunctionPass *createHexagonGenMux(); 159*0b57cec5SDimitry Andric FunctionPass *createHexagonGenPredicate(); 160*0b57cec5SDimitry Andric FunctionPass *createHexagonHardwareLoops(); 161*0b57cec5SDimitry Andric FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, 162*0b57cec5SDimitry Andric CodeGenOpt::Level OptLevel); 163*0b57cec5SDimitry Andric FunctionPass *createHexagonLoopRescheduling(); 164*0b57cec5SDimitry Andric FunctionPass *createHexagonNewValueJump(); 165*0b57cec5SDimitry Andric FunctionPass *createHexagonOptimizeSZextends(); 166*0b57cec5SDimitry Andric FunctionPass *createHexagonOptAddrMode(); 167*0b57cec5SDimitry Andric FunctionPass *createHexagonPacketizer(bool Minimal); 168*0b57cec5SDimitry Andric FunctionPass *createHexagonPeephole(); 169*0b57cec5SDimitry Andric FunctionPass *createHexagonRDFOpt(); 170*0b57cec5SDimitry Andric FunctionPass *createHexagonSplitConst32AndConst64(); 171*0b57cec5SDimitry Andric FunctionPass *createHexagonSplitDoubleRegs(); 172*0b57cec5SDimitry Andric FunctionPass *createHexagonStoreWidening(); 173*0b57cec5SDimitry Andric FunctionPass *createHexagonVectorPrint(); 174*0b57cec5SDimitry Andric FunctionPass *createHexagonVExtract(); 175*0b57cec5SDimitry Andric } // end namespace llvm; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { 178*0b57cec5SDimitry Andric if (!RM.hasValue()) 179*0b57cec5SDimitry Andric return Reloc::Static; 180*0b57cec5SDimitry Andric return *RM; 181*0b57cec5SDimitry Andric } 182*0b57cec5SDimitry Andric 183*0b57cec5SDimitry Andric extern "C" void LLVMInitializeHexagonTarget() { 184*0b57cec5SDimitry Andric // Register the target. 185*0b57cec5SDimitry Andric RegisterTargetMachine<HexagonTargetMachine> X(getTheHexagonTarget()); 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric PassRegistry &PR = *PassRegistry::getPassRegistry(); 188*0b57cec5SDimitry Andric initializeHexagonBitSimplifyPass(PR); 189*0b57cec5SDimitry Andric initializeHexagonConstExtendersPass(PR); 190*0b57cec5SDimitry Andric initializeHexagonConstPropagationPass(PR); 191*0b57cec5SDimitry Andric initializeHexagonEarlyIfConversionPass(PR); 192*0b57cec5SDimitry Andric initializeHexagonGenMuxPass(PR); 193*0b57cec5SDimitry Andric initializeHexagonHardwareLoopsPass(PR); 194*0b57cec5SDimitry Andric initializeHexagonLoopIdiomRecognizePass(PR); 195*0b57cec5SDimitry Andric initializeHexagonVectorLoopCarriedReusePass(PR); 196*0b57cec5SDimitry Andric initializeHexagonNewValueJumpPass(PR); 197*0b57cec5SDimitry Andric initializeHexagonOptAddrModePass(PR); 198*0b57cec5SDimitry Andric initializeHexagonPacketizerPass(PR); 199*0b57cec5SDimitry Andric initializeHexagonRDFOptPass(PR); 200*0b57cec5SDimitry Andric initializeHexagonSplitDoubleRegsPass(PR); 201*0b57cec5SDimitry Andric initializeHexagonVExtractPass(PR); 202*0b57cec5SDimitry Andric } 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT, 205*0b57cec5SDimitry Andric StringRef CPU, StringRef FS, 206*0b57cec5SDimitry Andric const TargetOptions &Options, 207*0b57cec5SDimitry Andric Optional<Reloc::Model> RM, 208*0b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 209*0b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 210*0b57cec5SDimitry Andric // Specify the vector alignment explicitly. For v512x1, the calculated 211*0b57cec5SDimitry Andric // alignment would be 512*alignment(i1), which is 512 bytes, instead of 212*0b57cec5SDimitry Andric // the required minimum of 64 bytes. 213*0b57cec5SDimitry Andric : LLVMTargetMachine( 214*0b57cec5SDimitry Andric T, 215*0b57cec5SDimitry Andric "e-m:e-p:32:32:32-a:0-n16:32-" 216*0b57cec5SDimitry Andric "i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-" 217*0b57cec5SDimitry Andric "v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048", 218*0b57cec5SDimitry Andric TT, CPU, FS, Options, getEffectiveRelocModel(RM), 219*0b57cec5SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), 220*0b57cec5SDimitry Andric (HexagonNoOpt ? CodeGenOpt::None : OL)), 221*0b57cec5SDimitry Andric TLOF(make_unique<HexagonTargetObjectFile>()) { 222*0b57cec5SDimitry Andric initializeHexagonExpandCondsetsPass(*PassRegistry::getPassRegistry()); 223*0b57cec5SDimitry Andric initAsmInfo(); 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric const HexagonSubtarget * 227*0b57cec5SDimitry Andric HexagonTargetMachine::getSubtargetImpl(const Function &F) const { 228*0b57cec5SDimitry Andric AttributeList FnAttrs = F.getAttributes(); 229*0b57cec5SDimitry Andric Attribute CPUAttr = 230*0b57cec5SDimitry Andric FnAttrs.getAttribute(AttributeList::FunctionIndex, "target-cpu"); 231*0b57cec5SDimitry Andric Attribute FSAttr = 232*0b57cec5SDimitry Andric FnAttrs.getAttribute(AttributeList::FunctionIndex, "target-features"); 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 235*0b57cec5SDimitry Andric ? CPUAttr.getValueAsString().str() 236*0b57cec5SDimitry Andric : TargetCPU; 237*0b57cec5SDimitry Andric std::string FS = !FSAttr.hasAttribute(Attribute::None) 238*0b57cec5SDimitry Andric ? FSAttr.getValueAsString().str() 239*0b57cec5SDimitry Andric : TargetFS; 240*0b57cec5SDimitry Andric 241*0b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 242*0b57cec5SDimitry Andric if (!I) { 243*0b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 244*0b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 245*0b57cec5SDimitry Andric // function that reside in TargetOptions. 246*0b57cec5SDimitry Andric resetTargetOptions(F); 247*0b57cec5SDimitry Andric I = llvm::make_unique<HexagonSubtarget>(TargetTriple, CPU, FS, *this); 248*0b57cec5SDimitry Andric } 249*0b57cec5SDimitry Andric return I.get(); 250*0b57cec5SDimitry Andric } 251*0b57cec5SDimitry Andric 252*0b57cec5SDimitry Andric void HexagonTargetMachine::adjustPassManager(PassManagerBuilder &PMB) { 253*0b57cec5SDimitry Andric PMB.addExtension( 254*0b57cec5SDimitry Andric PassManagerBuilder::EP_LateLoopOptimizations, 255*0b57cec5SDimitry Andric [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) { 256*0b57cec5SDimitry Andric PM.add(createHexagonLoopIdiomPass()); 257*0b57cec5SDimitry Andric }); 258*0b57cec5SDimitry Andric PMB.addExtension( 259*0b57cec5SDimitry Andric PassManagerBuilder::EP_LoopOptimizerEnd, 260*0b57cec5SDimitry Andric [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) { 261*0b57cec5SDimitry Andric PM.add(createHexagonVectorLoopCarriedReusePass()); 262*0b57cec5SDimitry Andric }); 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric TargetTransformInfo 266*0b57cec5SDimitry Andric HexagonTargetMachine::getTargetTransformInfo(const Function &F) { 267*0b57cec5SDimitry Andric return TargetTransformInfo(HexagonTTIImpl(this, F)); 268*0b57cec5SDimitry Andric } 269*0b57cec5SDimitry Andric 270*0b57cec5SDimitry Andric 271*0b57cec5SDimitry Andric HexagonTargetMachine::~HexagonTargetMachine() {} 272*0b57cec5SDimitry Andric 273*0b57cec5SDimitry Andric namespace { 274*0b57cec5SDimitry Andric /// Hexagon Code Generator Pass Configuration Options. 275*0b57cec5SDimitry Andric class HexagonPassConfig : public TargetPassConfig { 276*0b57cec5SDimitry Andric public: 277*0b57cec5SDimitry Andric HexagonPassConfig(HexagonTargetMachine &TM, PassManagerBase &PM) 278*0b57cec5SDimitry Andric : TargetPassConfig(TM, PM) {} 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric HexagonTargetMachine &getHexagonTargetMachine() const { 281*0b57cec5SDimitry Andric return getTM<HexagonTargetMachine>(); 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric 284*0b57cec5SDimitry Andric ScheduleDAGInstrs * 285*0b57cec5SDimitry Andric createMachineScheduler(MachineSchedContext *C) const override { 286*0b57cec5SDimitry Andric return createVLIWMachineSched(C); 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric 289*0b57cec5SDimitry Andric void addIRPasses() override; 290*0b57cec5SDimitry Andric bool addInstSelector() override; 291*0b57cec5SDimitry Andric void addPreRegAlloc() override; 292*0b57cec5SDimitry Andric void addPostRegAlloc() override; 293*0b57cec5SDimitry Andric void addPreSched2() override; 294*0b57cec5SDimitry Andric void addPreEmitPass() override; 295*0b57cec5SDimitry Andric }; 296*0b57cec5SDimitry Andric } // namespace 297*0b57cec5SDimitry Andric 298*0b57cec5SDimitry Andric TargetPassConfig *HexagonTargetMachine::createPassConfig(PassManagerBase &PM) { 299*0b57cec5SDimitry Andric return new HexagonPassConfig(*this, PM); 300*0b57cec5SDimitry Andric } 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andric void HexagonPassConfig::addIRPasses() { 303*0b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 304*0b57cec5SDimitry Andric bool NoOpt = (getOptLevel() == CodeGenOpt::None); 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric if (!NoOpt) { 307*0b57cec5SDimitry Andric addPass(createConstantPropagationPass()); 308*0b57cec5SDimitry Andric addPass(createDeadCodeEliminationPass()); 309*0b57cec5SDimitry Andric } 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 312*0b57cec5SDimitry Andric 313*0b57cec5SDimitry Andric if (!NoOpt) { 314*0b57cec5SDimitry Andric if (EnableInitialCFGCleanup) 315*0b57cec5SDimitry Andric addPass(createCFGSimplificationPass(1, true, true, false, true)); 316*0b57cec5SDimitry Andric if (EnableLoopPrefetch) 317*0b57cec5SDimitry Andric addPass(createLoopDataPrefetchPass()); 318*0b57cec5SDimitry Andric if (EnableCommGEP) 319*0b57cec5SDimitry Andric addPass(createHexagonCommonGEP()); 320*0b57cec5SDimitry Andric // Replace certain combinations of shifts and ands with extracts. 321*0b57cec5SDimitry Andric if (EnableGenExtract) 322*0b57cec5SDimitry Andric addPass(createHexagonGenExtract()); 323*0b57cec5SDimitry Andric } 324*0b57cec5SDimitry Andric } 325*0b57cec5SDimitry Andric 326*0b57cec5SDimitry Andric bool HexagonPassConfig::addInstSelector() { 327*0b57cec5SDimitry Andric HexagonTargetMachine &TM = getHexagonTargetMachine(); 328*0b57cec5SDimitry Andric bool NoOpt = (getOptLevel() == CodeGenOpt::None); 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric if (!NoOpt) 331*0b57cec5SDimitry Andric addPass(createHexagonOptimizeSZextends()); 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric addPass(createHexagonISelDag(TM, getOptLevel())); 334*0b57cec5SDimitry Andric 335*0b57cec5SDimitry Andric if (!NoOpt) { 336*0b57cec5SDimitry Andric if (EnableVExtractOpt) 337*0b57cec5SDimitry Andric addPass(createHexagonVExtract()); 338*0b57cec5SDimitry Andric // Create logical operations on predicate registers. 339*0b57cec5SDimitry Andric if (EnableGenPred) 340*0b57cec5SDimitry Andric addPass(createHexagonGenPredicate()); 341*0b57cec5SDimitry Andric // Rotate loops to expose bit-simplification opportunities. 342*0b57cec5SDimitry Andric if (EnableLoopResched) 343*0b57cec5SDimitry Andric addPass(createHexagonLoopRescheduling()); 344*0b57cec5SDimitry Andric // Split double registers. 345*0b57cec5SDimitry Andric if (!DisableHSDR) 346*0b57cec5SDimitry Andric addPass(createHexagonSplitDoubleRegs()); 347*0b57cec5SDimitry Andric // Bit simplification. 348*0b57cec5SDimitry Andric if (EnableBitSimplify) 349*0b57cec5SDimitry Andric addPass(createHexagonBitSimplify()); 350*0b57cec5SDimitry Andric addPass(createHexagonPeephole()); 351*0b57cec5SDimitry Andric // Constant propagation. 352*0b57cec5SDimitry Andric if (!DisableHCP) { 353*0b57cec5SDimitry Andric addPass(createHexagonConstPropagationPass()); 354*0b57cec5SDimitry Andric addPass(&UnreachableMachineBlockElimID); 355*0b57cec5SDimitry Andric } 356*0b57cec5SDimitry Andric if (EnableGenInsert) 357*0b57cec5SDimitry Andric addPass(createHexagonGenInsert()); 358*0b57cec5SDimitry Andric if (EnableEarlyIf) 359*0b57cec5SDimitry Andric addPass(createHexagonEarlyIfConversion()); 360*0b57cec5SDimitry Andric } 361*0b57cec5SDimitry Andric 362*0b57cec5SDimitry Andric return false; 363*0b57cec5SDimitry Andric } 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric void HexagonPassConfig::addPreRegAlloc() { 366*0b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 367*0b57cec5SDimitry Andric if (EnableCExtOpt) 368*0b57cec5SDimitry Andric addPass(createHexagonConstExtenders()); 369*0b57cec5SDimitry Andric if (EnableExpandCondsets) 370*0b57cec5SDimitry Andric insertPass(&RegisterCoalescerID, &HexagonExpandCondsetsID); 371*0b57cec5SDimitry Andric if (!DisableStoreWidening) 372*0b57cec5SDimitry Andric addPass(createHexagonStoreWidening()); 373*0b57cec5SDimitry Andric if (!DisableHardwareLoops) 374*0b57cec5SDimitry Andric addPass(createHexagonHardwareLoops()); 375*0b57cec5SDimitry Andric } 376*0b57cec5SDimitry Andric if (TM->getOptLevel() >= CodeGenOpt::Default) 377*0b57cec5SDimitry Andric addPass(&MachinePipelinerID); 378*0b57cec5SDimitry Andric } 379*0b57cec5SDimitry Andric 380*0b57cec5SDimitry Andric void HexagonPassConfig::addPostRegAlloc() { 381*0b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 382*0b57cec5SDimitry Andric if (EnableRDFOpt) 383*0b57cec5SDimitry Andric addPass(createHexagonRDFOpt()); 384*0b57cec5SDimitry Andric if (!DisableHexagonCFGOpt) 385*0b57cec5SDimitry Andric addPass(createHexagonCFGOptimizer()); 386*0b57cec5SDimitry Andric if (!DisableAModeOpt) 387*0b57cec5SDimitry Andric addPass(createHexagonOptAddrMode()); 388*0b57cec5SDimitry Andric } 389*0b57cec5SDimitry Andric } 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric void HexagonPassConfig::addPreSched2() { 392*0b57cec5SDimitry Andric addPass(createHexagonCopyToCombine()); 393*0b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) 394*0b57cec5SDimitry Andric addPass(&IfConverterID); 395*0b57cec5SDimitry Andric addPass(createHexagonSplitConst32AndConst64()); 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric void HexagonPassConfig::addPreEmitPass() { 399*0b57cec5SDimitry Andric bool NoOpt = (getOptLevel() == CodeGenOpt::None); 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric if (!NoOpt) 402*0b57cec5SDimitry Andric addPass(createHexagonNewValueJump()); 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric addPass(createHexagonBranchRelaxation()); 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric if (!NoOpt) { 407*0b57cec5SDimitry Andric if (!DisableHardwareLoops) 408*0b57cec5SDimitry Andric addPass(createHexagonFixupHwLoops()); 409*0b57cec5SDimitry Andric // Generate MUX from pairs of conditional transfers. 410*0b57cec5SDimitry Andric if (EnableGenMux) 411*0b57cec5SDimitry Andric addPass(createHexagonGenMux()); 412*0b57cec5SDimitry Andric } 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric // Packetization is mandatory: it handles gather/scatter at all opt levels. 415*0b57cec5SDimitry Andric addPass(createHexagonPacketizer(NoOpt), false); 416*0b57cec5SDimitry Andric 417*0b57cec5SDimitry Andric if (EnableVectorPrint) 418*0b57cec5SDimitry Andric addPass(createHexagonVectorPrint(), false); 419*0b57cec5SDimitry Andric 420*0b57cec5SDimitry Andric // Add CFI instructions if necessary. 421*0b57cec5SDimitry Andric addPass(createHexagonCallFrameInformation(), false); 422*0b57cec5SDimitry Andric } 423