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