NVPTXTargetMachine.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. //===-- NVPTXTargetMachine.cpp - Define TargetMachine for NVPTX -----------===//
  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. // Top-level implementation for the NVPTX target.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "NVPTXTargetMachine.h"
  13. #include "NVPTX.h"
  14. #include "NVPTXAllocaHoisting.h"
  15. #include "NVPTXAtomicLower.h"
  16. #include "NVPTXLowerAggrCopies.h"
  17. #include "NVPTXMachineFunctionInfo.h"
  18. #include "NVPTXTargetObjectFile.h"
  19. #include "NVPTXTargetTransformInfo.h"
  20. #include "TargetInfo/NVPTXTargetInfo.h"
  21. #include "llvm/ADT/STLExtras.h"
  22. #include "llvm/ADT/Triple.h"
  23. #include "llvm/Analysis/TargetTransformInfo.h"
  24. #include "llvm/CodeGen/Passes.h"
  25. #include "llvm/CodeGen/TargetPassConfig.h"
  26. #include "llvm/IR/IntrinsicsNVPTX.h"
  27. #include "llvm/IR/LegacyPassManager.h"
  28. #include "llvm/MC/TargetRegistry.h"
  29. #include "llvm/Pass.h"
  30. #include "llvm/Passes/PassBuilder.h"
  31. #include "llvm/Support/CommandLine.h"
  32. #include "llvm/Target/TargetMachine.h"
  33. #include "llvm/Target/TargetOptions.h"
  34. #include "llvm/Transforms/Scalar.h"
  35. #include "llvm/Transforms/Scalar/GVN.h"
  36. #include "llvm/Transforms/Vectorize.h"
  37. #include <cassert>
  38. #include <optional>
  39. #include <string>
  40. using namespace llvm;
  41. // LSV is still relatively new; this switch lets us turn it off in case we
  42. // encounter (or suspect) a bug.
  43. static cl::opt<bool>
  44. DisableLoadStoreVectorizer("disable-nvptx-load-store-vectorizer",
  45. cl::desc("Disable load/store vectorizer"),
  46. cl::init(false), cl::Hidden);
  47. // TODO: Remove this flag when we are confident with no regressions.
  48. static cl::opt<bool> DisableRequireStructuredCFG(
  49. "disable-nvptx-require-structured-cfg",
  50. cl::desc("Transitional flag to turn off NVPTX's requirement on preserving "
  51. "structured CFG. The requirement should be disabled only when "
  52. "unexpected regressions happen."),
  53. cl::init(false), cl::Hidden);
  54. static cl::opt<bool> UseShortPointersOpt(
  55. "nvptx-short-ptr",
  56. cl::desc(
  57. "Use 32-bit pointers for accessing const/local/shared address spaces."),
  58. cl::init(false), cl::Hidden);
  59. namespace llvm {
  60. void initializeGenericToNVVMPass(PassRegistry&);
  61. void initializeNVPTXAllocaHoistingPass(PassRegistry &);
  62. void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry&);
  63. void initializeNVPTXAtomicLowerPass(PassRegistry &);
  64. void initializeNVPTXLowerAggrCopiesPass(PassRegistry &);
  65. void initializeNVPTXLowerAllocaPass(PassRegistry &);
  66. void initializeNVPTXLowerArgsPass(PassRegistry &);
  67. void initializeNVPTXProxyRegErasurePass(PassRegistry &);
  68. void initializeNVVMIntrRangePass(PassRegistry &);
  69. void initializeNVVMReflectPass(PassRegistry &);
  70. } // end namespace llvm
  71. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeNVPTXTarget() {
  72. // Register the target.
  73. RegisterTargetMachine<NVPTXTargetMachine32> X(getTheNVPTXTarget32());
  74. RegisterTargetMachine<NVPTXTargetMachine64> Y(getTheNVPTXTarget64());
  75. PassRegistry &PR = *PassRegistry::getPassRegistry();
  76. // FIXME: This pass is really intended to be invoked during IR optimization,
  77. // but it's very NVPTX-specific.
  78. initializeNVVMReflectPass(PR);
  79. initializeNVVMIntrRangePass(PR);
  80. initializeGenericToNVVMPass(PR);
  81. initializeNVPTXAllocaHoistingPass(PR);
  82. initializeNVPTXAssignValidGlobalNamesPass(PR);
  83. initializeNVPTXAtomicLowerPass(PR);
  84. initializeNVPTXLowerArgsPass(PR);
  85. initializeNVPTXLowerAllocaPass(PR);
  86. initializeNVPTXLowerAggrCopiesPass(PR);
  87. initializeNVPTXProxyRegErasurePass(PR);
  88. initializeNVPTXDAGToDAGISelPass(PR);
  89. }
  90. static std::string computeDataLayout(bool is64Bit, bool UseShortPointers) {
  91. std::string Ret = "e";
  92. if (!is64Bit)
  93. Ret += "-p:32:32";
  94. else if (UseShortPointers)
  95. Ret += "-p3:32:32-p4:32:32-p5:32:32";
  96. Ret += "-i64:64-i128:128-v16:16-v32:32-n16:32:64";
  97. return Ret;
  98. }
  99. NVPTXTargetMachine::NVPTXTargetMachine(const Target &T, const Triple &TT,
  100. StringRef CPU, StringRef FS,
  101. const TargetOptions &Options,
  102. std::optional<Reloc::Model> RM,
  103. std::optional<CodeModel::Model> CM,
  104. CodeGenOpt::Level OL, bool is64bit)
  105. // The pic relocation model is used regardless of what the client has
  106. // specified, as it is the only relocation model currently supported.
  107. : LLVMTargetMachine(T, computeDataLayout(is64bit, UseShortPointersOpt), TT,
  108. CPU, FS, Options, Reloc::PIC_,
  109. getEffectiveCodeModel(CM, CodeModel::Small), OL),
  110. is64bit(is64bit), UseShortPointers(UseShortPointersOpt),
  111. TLOF(std::make_unique<NVPTXTargetObjectFile>()),
  112. Subtarget(TT, std::string(CPU), std::string(FS), *this),
  113. StrPool(StrAlloc) {
  114. if (TT.getOS() == Triple::NVCL)
  115. drvInterface = NVPTX::NVCL;
  116. else
  117. drvInterface = NVPTX::CUDA;
  118. if (!DisableRequireStructuredCFG)
  119. setRequiresStructuredCFG(true);
  120. initAsmInfo();
  121. }
  122. NVPTXTargetMachine::~NVPTXTargetMachine() = default;
  123. void NVPTXTargetMachine32::anchor() {}
  124. NVPTXTargetMachine32::NVPTXTargetMachine32(const Target &T, const Triple &TT,
  125. StringRef CPU, StringRef FS,
  126. const TargetOptions &Options,
  127. std::optional<Reloc::Model> RM,
  128. std::optional<CodeModel::Model> CM,
  129. CodeGenOpt::Level OL, bool JIT)
  130. : NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
  131. void NVPTXTargetMachine64::anchor() {}
  132. NVPTXTargetMachine64::NVPTXTargetMachine64(const Target &T, const Triple &TT,
  133. StringRef CPU, StringRef FS,
  134. const TargetOptions &Options,
  135. std::optional<Reloc::Model> RM,
  136. std::optional<CodeModel::Model> CM,
  137. CodeGenOpt::Level OL, bool JIT)
  138. : NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
  139. namespace {
  140. class NVPTXPassConfig : public TargetPassConfig {
  141. public:
  142. NVPTXPassConfig(NVPTXTargetMachine &TM, PassManagerBase &PM)
  143. : TargetPassConfig(TM, PM) {}
  144. NVPTXTargetMachine &getNVPTXTargetMachine() const {
  145. return getTM<NVPTXTargetMachine>();
  146. }
  147. void addIRPasses() override;
  148. bool addInstSelector() override;
  149. void addPreRegAlloc() override;
  150. void addPostRegAlloc() override;
  151. void addMachineSSAOptimization() override;
  152. FunctionPass *createTargetRegisterAllocator(bool) override;
  153. void addFastRegAlloc() override;
  154. void addOptimizedRegAlloc() override;
  155. bool addRegAssignAndRewriteFast() override {
  156. llvm_unreachable("should not be used");
  157. }
  158. bool addRegAssignAndRewriteOptimized() override {
  159. llvm_unreachable("should not be used");
  160. }
  161. private:
  162. // If the opt level is aggressive, add GVN; otherwise, add EarlyCSE. This
  163. // function is only called in opt mode.
  164. void addEarlyCSEOrGVNPass();
  165. // Add passes that propagate special memory spaces.
  166. void addAddressSpaceInferencePasses();
  167. // Add passes that perform straight-line scalar optimizations.
  168. void addStraightLineScalarOptimizationPasses();
  169. };
  170. } // end anonymous namespace
  171. TargetPassConfig *NVPTXTargetMachine::createPassConfig(PassManagerBase &PM) {
  172. return new NVPTXPassConfig(*this, PM);
  173. }
  174. MachineFunctionInfo *NVPTXTargetMachine::createMachineFunctionInfo(
  175. BumpPtrAllocator &Allocator, const Function &F,
  176. const TargetSubtargetInfo *STI) const {
  177. return NVPTXMachineFunctionInfo::create<NVPTXMachineFunctionInfo>(Allocator,
  178. F, STI);
  179. }
  180. void NVPTXTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
  181. PB.registerPipelineParsingCallback(
  182. [](StringRef PassName, FunctionPassManager &PM,
  183. ArrayRef<PassBuilder::PipelineElement>) {
  184. if (PassName == "nvvm-reflect") {
  185. PM.addPass(NVVMReflectPass());
  186. return true;
  187. }
  188. if (PassName == "nvvm-intr-range") {
  189. PM.addPass(NVVMIntrRangePass());
  190. return true;
  191. }
  192. return false;
  193. });
  194. PB.registerPipelineStartEPCallback(
  195. [this](ModulePassManager &PM, OptimizationLevel Level) {
  196. FunctionPassManager FPM;
  197. FPM.addPass(NVVMReflectPass(Subtarget.getSmVersion()));
  198. // FIXME: NVVMIntrRangePass is causing numerical discrepancies,
  199. // investigate and re-enable.
  200. // FPM.addPass(NVVMIntrRangePass(Subtarget.getSmVersion()));
  201. PM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
  202. });
  203. }
  204. TargetTransformInfo
  205. NVPTXTargetMachine::getTargetTransformInfo(const Function &F) const {
  206. return TargetTransformInfo(NVPTXTTIImpl(this, F));
  207. }
  208. std::pair<const Value *, unsigned>
  209. NVPTXTargetMachine::getPredicatedAddrSpace(const Value *V) const {
  210. if (auto *II = dyn_cast<IntrinsicInst>(V)) {
  211. switch (II->getIntrinsicID()) {
  212. case Intrinsic::nvvm_isspacep_const:
  213. return std::make_pair(II->getArgOperand(0), llvm::ADDRESS_SPACE_CONST);
  214. case Intrinsic::nvvm_isspacep_global:
  215. return std::make_pair(II->getArgOperand(0), llvm::ADDRESS_SPACE_GLOBAL);
  216. case Intrinsic::nvvm_isspacep_local:
  217. return std::make_pair(II->getArgOperand(0), llvm::ADDRESS_SPACE_LOCAL);
  218. case Intrinsic::nvvm_isspacep_shared:
  219. return std::make_pair(II->getArgOperand(0), llvm::ADDRESS_SPACE_SHARED);
  220. default:
  221. break;
  222. }
  223. }
  224. return std::make_pair(nullptr, -1);
  225. }
  226. void NVPTXPassConfig::addEarlyCSEOrGVNPass() {
  227. if (getOptLevel() == CodeGenOpt::Aggressive)
  228. addPass(createGVNPass());
  229. else
  230. addPass(createEarlyCSEPass());
  231. }
  232. void NVPTXPassConfig::addAddressSpaceInferencePasses() {
  233. // NVPTXLowerArgs emits alloca for byval parameters which can often
  234. // be eliminated by SROA.
  235. addPass(createSROAPass());
  236. addPass(createNVPTXLowerAllocaPass());
  237. addPass(createInferAddressSpacesPass());
  238. addPass(createNVPTXAtomicLowerPass());
  239. }
  240. void NVPTXPassConfig::addStraightLineScalarOptimizationPasses() {
  241. addPass(createSeparateConstOffsetFromGEPPass());
  242. addPass(createSpeculativeExecutionPass());
  243. // ReassociateGEPs exposes more opportunites for SLSR. See
  244. // the example in reassociate-geps-and-slsr.ll.
  245. addPass(createStraightLineStrengthReducePass());
  246. // SeparateConstOffsetFromGEP and SLSR creates common expressions which GVN or
  247. // EarlyCSE can reuse. GVN generates significantly better code than EarlyCSE
  248. // for some of our benchmarks.
  249. addEarlyCSEOrGVNPass();
  250. // Run NaryReassociate after EarlyCSE/GVN to be more effective.
  251. addPass(createNaryReassociatePass());
  252. // NaryReassociate on GEPs creates redundant common expressions, so run
  253. // EarlyCSE after it.
  254. addPass(createEarlyCSEPass());
  255. }
  256. void NVPTXPassConfig::addIRPasses() {
  257. // The following passes are known to not play well with virtual regs hanging
  258. // around after register allocation (which in our case, is *all* registers).
  259. // We explicitly disable them here. We do, however, need some functionality
  260. // of the PrologEpilogCodeInserter pass, so we emulate that behavior in the
  261. // NVPTXPrologEpilog pass (see NVPTXPrologEpilogPass.cpp).
  262. disablePass(&PrologEpilogCodeInserterID);
  263. disablePass(&MachineLateInstrsCleanupID);
  264. disablePass(&MachineCopyPropagationID);
  265. disablePass(&TailDuplicateID);
  266. disablePass(&StackMapLivenessID);
  267. disablePass(&LiveDebugValuesID);
  268. disablePass(&PostRAMachineSinkingID);
  269. disablePass(&PostRASchedulerID);
  270. disablePass(&FuncletLayoutID);
  271. disablePass(&PatchableFunctionID);
  272. disablePass(&ShrinkWrapID);
  273. // NVVMReflectPass is added in addEarlyAsPossiblePasses, so hopefully running
  274. // it here does nothing. But since we need it for correctness when lowering
  275. // to NVPTX, run it here too, in case whoever built our pass pipeline didn't
  276. // call addEarlyAsPossiblePasses.
  277. const NVPTXSubtarget &ST = *getTM<NVPTXTargetMachine>().getSubtargetImpl();
  278. addPass(createNVVMReflectPass(ST.getSmVersion()));
  279. if (getOptLevel() != CodeGenOpt::None)
  280. addPass(createNVPTXImageOptimizerPass());
  281. addPass(createNVPTXAssignValidGlobalNamesPass());
  282. addPass(createGenericToNVVMPass());
  283. // NVPTXLowerArgs is required for correctness and should be run right
  284. // before the address space inference passes.
  285. addPass(createNVPTXLowerArgsPass(&getNVPTXTargetMachine()));
  286. if (getOptLevel() != CodeGenOpt::None) {
  287. addAddressSpaceInferencePasses();
  288. addStraightLineScalarOptimizationPasses();
  289. }
  290. addPass(createAtomicExpandPass());
  291. // === LSR and other generic IR passes ===
  292. TargetPassConfig::addIRPasses();
  293. // EarlyCSE is not always strong enough to clean up what LSR produces. For
  294. // example, GVN can combine
  295. //
  296. // %0 = add %a, %b
  297. // %1 = add %b, %a
  298. //
  299. // and
  300. //
  301. // %0 = shl nsw %a, 2
  302. // %1 = shl %a, 2
  303. //
  304. // but EarlyCSE can do neither of them.
  305. if (getOptLevel() != CodeGenOpt::None) {
  306. addEarlyCSEOrGVNPass();
  307. if (!DisableLoadStoreVectorizer)
  308. addPass(createLoadStoreVectorizerPass());
  309. addPass(createSROAPass());
  310. }
  311. }
  312. bool NVPTXPassConfig::addInstSelector() {
  313. const NVPTXSubtarget &ST = *getTM<NVPTXTargetMachine>().getSubtargetImpl();
  314. addPass(createLowerAggrCopies());
  315. addPass(createAllocaHoisting());
  316. addPass(createNVPTXISelDag(getNVPTXTargetMachine(), getOptLevel()));
  317. if (!ST.hasImageHandles())
  318. addPass(createNVPTXReplaceImageHandlesPass());
  319. return false;
  320. }
  321. void NVPTXPassConfig::addPreRegAlloc() {
  322. // Remove Proxy Register pseudo instructions used to keep `callseq_end` alive.
  323. addPass(createNVPTXProxyRegErasurePass());
  324. }
  325. void NVPTXPassConfig::addPostRegAlloc() {
  326. addPass(createNVPTXPrologEpilogPass());
  327. if (getOptLevel() != CodeGenOpt::None) {
  328. // NVPTXPrologEpilogPass calculates frame object offset and replace frame
  329. // index with VRFrame register. NVPTXPeephole need to be run after that and
  330. // will replace VRFrame with VRFrameLocal when possible.
  331. addPass(createNVPTXPeephole());
  332. }
  333. }
  334. FunctionPass *NVPTXPassConfig::createTargetRegisterAllocator(bool) {
  335. return nullptr; // No reg alloc
  336. }
  337. void NVPTXPassConfig::addFastRegAlloc() {
  338. addPass(&PHIEliminationID);
  339. addPass(&TwoAddressInstructionPassID);
  340. }
  341. void NVPTXPassConfig::addOptimizedRegAlloc() {
  342. addPass(&ProcessImplicitDefsID);
  343. addPass(&LiveVariablesID);
  344. addPass(&MachineLoopInfoID);
  345. addPass(&PHIEliminationID);
  346. addPass(&TwoAddressInstructionPassID);
  347. addPass(&RegisterCoalescerID);
  348. // PreRA instruction scheduling.
  349. if (addPass(&MachineSchedulerID))
  350. printAndVerify("After Machine Scheduling");
  351. addPass(&StackSlotColoringID);
  352. // FIXME: Needs physical registers
  353. //addPass(&MachineLICMID);
  354. printAndVerify("After StackSlotColoring");
  355. }
  356. void NVPTXPassConfig::addMachineSSAOptimization() {
  357. // Pre-ra tail duplication.
  358. if (addPass(&EarlyTailDuplicateID))
  359. printAndVerify("After Pre-RegAlloc TailDuplicate");
  360. // Optimize PHIs before DCE: removing dead PHI cycles may make more
  361. // instructions dead.
  362. addPass(&OptimizePHIsID);
  363. // This pass merges large allocas. StackSlotColoring is a different pass
  364. // which merges spill slots.
  365. addPass(&StackColoringID);
  366. // If the target requests it, assign local variables to stack slots relative
  367. // to one another and simplify frame index references where possible.
  368. addPass(&LocalStackSlotAllocationID);
  369. // With optimization, dead code should already be eliminated. However
  370. // there is one known exception: lowered code for arguments that are only
  371. // used by tail calls, where the tail calls reuse the incoming stack
  372. // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
  373. addPass(&DeadMachineInstructionElimID);
  374. printAndVerify("After codegen DCE pass");
  375. // Allow targets to insert passes that improve instruction level parallelism,
  376. // like if-conversion. Such passes will typically need dominator trees and
  377. // loop info, just like LICM and CSE below.
  378. if (addILPOpts())
  379. printAndVerify("After ILP optimizations");
  380. addPass(&EarlyMachineLICMID);
  381. addPass(&MachineCSEID);
  382. addPass(&MachineSinkingID);
  383. printAndVerify("After Machine LICM, CSE and Sinking passes");
  384. addPass(&PeepholeOptimizerID);
  385. printAndVerify("After codegen peephole optimization pass");
  386. }