2468 lines · cpp
1//===-- AMDGPUTargetMachine.cpp - TargetMachine for hw codegen targets-----===//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/// \file10/// This file contains both AMDGPU target machine and the CodeGen pass builder.11/// The AMDGPU target machine contains all of the hardware specific information12/// needed to emit code for SI+ GPUs in the legacy pass manager pipeline. The13/// CodeGen pass builder handles the pass pipeline for new pass manager.14//15//===----------------------------------------------------------------------===//16 17#include "AMDGPUTargetMachine.h"18#include "AMDGPU.h"19#include "AMDGPUAliasAnalysis.h"20#include "AMDGPUBarrierLatency.h"21#include "AMDGPUCtorDtorLowering.h"22#include "AMDGPUExportClustering.h"23#include "AMDGPUExportKernelRuntimeHandles.h"24#include "AMDGPUIGroupLP.h"25#include "AMDGPUISelDAGToDAG.h"26#include "AMDGPULowerVGPREncoding.h"27#include "AMDGPUMacroFusion.h"28#include "AMDGPUPerfHintAnalysis.h"29#include "AMDGPUPreloadKernArgProlog.h"30#include "AMDGPUPrepareAGPRAlloc.h"31#include "AMDGPURemoveIncompatibleFunctions.h"32#include "AMDGPUReserveWWMRegs.h"33#include "AMDGPUResourceUsageAnalysis.h"34#include "AMDGPUSplitModule.h"35#include "AMDGPUTargetObjectFile.h"36#include "AMDGPUTargetTransformInfo.h"37#include "AMDGPUUnifyDivergentExitNodes.h"38#include "AMDGPUWaitSGPRHazards.h"39#include "GCNDPPCombine.h"40#include "GCNIterativeScheduler.h"41#include "GCNNSAReassign.h"42#include "GCNPreRALongBranchReg.h"43#include "GCNPreRAOptimizations.h"44#include "GCNRewritePartialRegUses.h"45#include "GCNSchedStrategy.h"46#include "GCNVOPDUtils.h"47#include "R600.h"48#include "R600TargetMachine.h"49#include "SIFixSGPRCopies.h"50#include "SIFixVGPRCopies.h"51#include "SIFoldOperands.h"52#include "SIFormMemoryClauses.h"53#include "SILoadStoreOptimizer.h"54#include "SILowerControlFlow.h"55#include "SILowerSGPRSpills.h"56#include "SILowerWWMCopies.h"57#include "SIMachineFunctionInfo.h"58#include "SIMachineScheduler.h"59#include "SIOptimizeExecMasking.h"60#include "SIOptimizeExecMaskingPreRA.h"61#include "SIOptimizeVGPRLiveRange.h"62#include "SIPeepholeSDWA.h"63#include "SIPostRABundler.h"64#include "SIPreAllocateWWMRegs.h"65#include "SIShrinkInstructions.h"66#include "SIWholeQuadMode.h"67#include "TargetInfo/AMDGPUTargetInfo.h"68#include "Utils/AMDGPUBaseInfo.h"69#include "llvm/Analysis/CGSCCPassManager.h"70#include "llvm/Analysis/CallGraphSCCPass.h"71#include "llvm/Analysis/KernelInfo.h"72#include "llvm/Analysis/UniformityAnalysis.h"73#include "llvm/CodeGen/AtomicExpand.h"74#include "llvm/CodeGen/BranchRelaxation.h"75#include "llvm/CodeGen/DeadMachineInstructionElim.h"76#include "llvm/CodeGen/GlobalISel/CSEInfo.h"77#include "llvm/CodeGen/GlobalISel/IRTranslator.h"78#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"79#include "llvm/CodeGen/GlobalISel/Legalizer.h"80#include "llvm/CodeGen/GlobalISel/Localizer.h"81#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"82#include "llvm/CodeGen/MIRParser/MIParser.h"83#include "llvm/CodeGen/MachineCSE.h"84#include "llvm/CodeGen/MachineLICM.h"85#include "llvm/CodeGen/MachineScheduler.h"86#include "llvm/CodeGen/Passes.h"87#include "llvm/CodeGen/PostRAHazardRecognizer.h"88#include "llvm/CodeGen/RegAllocRegistry.h"89#include "llvm/CodeGen/TargetPassConfig.h"90#include "llvm/IR/IntrinsicsAMDGPU.h"91#include "llvm/IR/PassManager.h"92#include "llvm/IR/PatternMatch.h"93#include "llvm/InitializePasses.h"94#include "llvm/MC/TargetRegistry.h"95#include "llvm/Passes/CodeGenPassBuilder.h"96#include "llvm/Passes/PassBuilder.h"97#include "llvm/Support/Compiler.h"98#include "llvm/Support/FormatVariadic.h"99#include "llvm/Transforms/HipStdPar/HipStdPar.h"100#include "llvm/Transforms/IPO.h"101#include "llvm/Transforms/IPO/AlwaysInliner.h"102#include "llvm/Transforms/IPO/ExpandVariadics.h"103#include "llvm/Transforms/IPO/GlobalDCE.h"104#include "llvm/Transforms/IPO/Internalize.h"105#include "llvm/Transforms/Scalar.h"106#include "llvm/Transforms/Scalar/EarlyCSE.h"107#include "llvm/Transforms/Scalar/FlattenCFG.h"108#include "llvm/Transforms/Scalar/GVN.h"109#include "llvm/Transforms/Scalar/InferAddressSpaces.h"110#include "llvm/Transforms/Scalar/LICM.h"111#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"112#include "llvm/Transforms/Scalar/LoopPassManager.h"113#include "llvm/Transforms/Scalar/NaryReassociate.h"114#include "llvm/Transforms/Scalar/SeparateConstOffsetFromGEP.h"115#include "llvm/Transforms/Scalar/Sink.h"116#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"117#include "llvm/Transforms/Scalar/StructurizeCFG.h"118#include "llvm/Transforms/Utils.h"119#include "llvm/Transforms/Utils/FixIrreducible.h"120#include "llvm/Transforms/Utils/LCSSA.h"121#include "llvm/Transforms/Utils/LowerSwitch.h"122#include "llvm/Transforms/Utils/SimplifyLibCalls.h"123#include "llvm/Transforms/Utils/UnifyLoopExits.h"124#include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h"125#include <optional>126 127using namespace llvm;128using namespace llvm::PatternMatch;129 130namespace {131//===----------------------------------------------------------------------===//132// AMDGPU CodeGen Pass Builder interface.133//===----------------------------------------------------------------------===//134 135class AMDGPUCodeGenPassBuilder136 : public CodeGenPassBuilder<AMDGPUCodeGenPassBuilder, GCNTargetMachine> {137 using Base = CodeGenPassBuilder<AMDGPUCodeGenPassBuilder, GCNTargetMachine>;138 139public:140 AMDGPUCodeGenPassBuilder(GCNTargetMachine &TM,141 const CGPassBuilderOption &Opts,142 PassInstrumentationCallbacks *PIC);143 144 void addIRPasses(AddIRPass &) const;145 void addCodeGenPrepare(AddIRPass &) const;146 void addPreISel(AddIRPass &addPass) const;147 void addILPOpts(AddMachinePass &) const;148 void addAsmPrinter(AddMachinePass &, CreateMCStreamer) const;149 Error addInstSelector(AddMachinePass &) const;150 void addPreRewrite(AddMachinePass &) const;151 void addMachineSSAOptimization(AddMachinePass &) const;152 void addPostRegAlloc(AddMachinePass &) const;153 void addPreEmitPass(AddMachinePass &) const;154 void addPreEmitRegAlloc(AddMachinePass &) const;155 Error addRegAssignmentOptimized(AddMachinePass &) const;156 void addPreRegAlloc(AddMachinePass &) const;157 void addOptimizedRegAlloc(AddMachinePass &) const;158 void addPreSched2(AddMachinePass &) const;159 160 /// Check if a pass is enabled given \p Opt option. The option always161 /// overrides defaults if explicitly used. Otherwise its default will be used162 /// given that a pass shall work at an optimization \p Level minimum.163 bool isPassEnabled(const cl::opt<bool> &Opt,164 CodeGenOptLevel Level = CodeGenOptLevel::Default) const;165 void addEarlyCSEOrGVNPass(AddIRPass &) const;166 void addStraightLineScalarOptimizationPasses(AddIRPass &) const;167};168 169class SGPRRegisterRegAlloc : public RegisterRegAllocBase<SGPRRegisterRegAlloc> {170public:171 SGPRRegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C)172 : RegisterRegAllocBase(N, D, C) {}173};174 175class VGPRRegisterRegAlloc : public RegisterRegAllocBase<VGPRRegisterRegAlloc> {176public:177 VGPRRegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C)178 : RegisterRegAllocBase(N, D, C) {}179};180 181class WWMRegisterRegAlloc : public RegisterRegAllocBase<WWMRegisterRegAlloc> {182public:183 WWMRegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C)184 : RegisterRegAllocBase(N, D, C) {}185};186 187static bool onlyAllocateSGPRs(const TargetRegisterInfo &TRI,188 const MachineRegisterInfo &MRI,189 const Register Reg) {190 const TargetRegisterClass *RC = MRI.getRegClass(Reg);191 return static_cast<const SIRegisterInfo &>(TRI).isSGPRClass(RC);192}193 194static bool onlyAllocateVGPRs(const TargetRegisterInfo &TRI,195 const MachineRegisterInfo &MRI,196 const Register Reg) {197 const TargetRegisterClass *RC = MRI.getRegClass(Reg);198 return !static_cast<const SIRegisterInfo &>(TRI).isSGPRClass(RC);199}200 201static bool onlyAllocateWWMRegs(const TargetRegisterInfo &TRI,202 const MachineRegisterInfo &MRI,203 const Register Reg) {204 const SIMachineFunctionInfo *MFI =205 MRI.getMF().getInfo<SIMachineFunctionInfo>();206 const TargetRegisterClass *RC = MRI.getRegClass(Reg);207 return !static_cast<const SIRegisterInfo &>(TRI).isSGPRClass(RC) &&208 MFI->checkFlag(Reg, AMDGPU::VirtRegFlag::WWM_REG);209}210 211/// -{sgpr|wwm|vgpr}-regalloc=... command line option.212static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }213 214/// A dummy default pass factory indicates whether the register allocator is215/// overridden on the command line.216static llvm::once_flag InitializeDefaultSGPRRegisterAllocatorFlag;217static llvm::once_flag InitializeDefaultVGPRRegisterAllocatorFlag;218static llvm::once_flag InitializeDefaultWWMRegisterAllocatorFlag;219 220static SGPRRegisterRegAlloc221defaultSGPRRegAlloc("default",222 "pick SGPR register allocator based on -O option",223 useDefaultRegisterAllocator);224 225static cl::opt<SGPRRegisterRegAlloc::FunctionPassCtor, false,226 RegisterPassParser<SGPRRegisterRegAlloc>>227SGPRRegAlloc("sgpr-regalloc", cl::Hidden, cl::init(&useDefaultRegisterAllocator),228 cl::desc("Register allocator to use for SGPRs"));229 230static cl::opt<VGPRRegisterRegAlloc::FunctionPassCtor, false,231 RegisterPassParser<VGPRRegisterRegAlloc>>232VGPRRegAlloc("vgpr-regalloc", cl::Hidden, cl::init(&useDefaultRegisterAllocator),233 cl::desc("Register allocator to use for VGPRs"));234 235static cl::opt<WWMRegisterRegAlloc::FunctionPassCtor, false,236 RegisterPassParser<WWMRegisterRegAlloc>>237 WWMRegAlloc("wwm-regalloc", cl::Hidden,238 cl::init(&useDefaultRegisterAllocator),239 cl::desc("Register allocator to use for WWM registers"));240 241static void initializeDefaultSGPRRegisterAllocatorOnce() {242 RegisterRegAlloc::FunctionPassCtor Ctor = SGPRRegisterRegAlloc::getDefault();243 244 if (!Ctor) {245 Ctor = SGPRRegAlloc;246 SGPRRegisterRegAlloc::setDefault(SGPRRegAlloc);247 }248}249 250static void initializeDefaultVGPRRegisterAllocatorOnce() {251 RegisterRegAlloc::FunctionPassCtor Ctor = VGPRRegisterRegAlloc::getDefault();252 253 if (!Ctor) {254 Ctor = VGPRRegAlloc;255 VGPRRegisterRegAlloc::setDefault(VGPRRegAlloc);256 }257}258 259static void initializeDefaultWWMRegisterAllocatorOnce() {260 RegisterRegAlloc::FunctionPassCtor Ctor = WWMRegisterRegAlloc::getDefault();261 262 if (!Ctor) {263 Ctor = WWMRegAlloc;264 WWMRegisterRegAlloc::setDefault(WWMRegAlloc);265 }266}267 268static FunctionPass *createBasicSGPRRegisterAllocator() {269 return createBasicRegisterAllocator(onlyAllocateSGPRs);270}271 272static FunctionPass *createGreedySGPRRegisterAllocator() {273 return createGreedyRegisterAllocator(onlyAllocateSGPRs);274}275 276static FunctionPass *createFastSGPRRegisterAllocator() {277 return createFastRegisterAllocator(onlyAllocateSGPRs, false);278}279 280static FunctionPass *createBasicVGPRRegisterAllocator() {281 return createBasicRegisterAllocator(onlyAllocateVGPRs);282}283 284static FunctionPass *createGreedyVGPRRegisterAllocator() {285 return createGreedyRegisterAllocator(onlyAllocateVGPRs);286}287 288static FunctionPass *createFastVGPRRegisterAllocator() {289 return createFastRegisterAllocator(onlyAllocateVGPRs, true);290}291 292static FunctionPass *createBasicWWMRegisterAllocator() {293 return createBasicRegisterAllocator(onlyAllocateWWMRegs);294}295 296static FunctionPass *createGreedyWWMRegisterAllocator() {297 return createGreedyRegisterAllocator(onlyAllocateWWMRegs);298}299 300static FunctionPass *createFastWWMRegisterAllocator() {301 return createFastRegisterAllocator(onlyAllocateWWMRegs, false);302}303 304static SGPRRegisterRegAlloc basicRegAllocSGPR(305 "basic", "basic register allocator", createBasicSGPRRegisterAllocator);306static SGPRRegisterRegAlloc greedyRegAllocSGPR(307 "greedy", "greedy register allocator", createGreedySGPRRegisterAllocator);308 309static SGPRRegisterRegAlloc fastRegAllocSGPR(310 "fast", "fast register allocator", createFastSGPRRegisterAllocator);311 312 313static VGPRRegisterRegAlloc basicRegAllocVGPR(314 "basic", "basic register allocator", createBasicVGPRRegisterAllocator);315static VGPRRegisterRegAlloc greedyRegAllocVGPR(316 "greedy", "greedy register allocator", createGreedyVGPRRegisterAllocator);317 318static VGPRRegisterRegAlloc fastRegAllocVGPR(319 "fast", "fast register allocator", createFastVGPRRegisterAllocator);320static WWMRegisterRegAlloc basicRegAllocWWMReg("basic",321 "basic register allocator",322 createBasicWWMRegisterAllocator);323static WWMRegisterRegAlloc324 greedyRegAllocWWMReg("greedy", "greedy register allocator",325 createGreedyWWMRegisterAllocator);326static WWMRegisterRegAlloc fastRegAllocWWMReg("fast", "fast register allocator",327 createFastWWMRegisterAllocator);328 329static bool isLTOPreLink(ThinOrFullLTOPhase Phase) {330 return Phase == ThinOrFullLTOPhase::FullLTOPreLink ||331 Phase == ThinOrFullLTOPhase::ThinLTOPreLink;332}333} // anonymous namespace334 335static cl::opt<bool>336EnableEarlyIfConversion("amdgpu-early-ifcvt", cl::Hidden,337 cl::desc("Run early if-conversion"),338 cl::init(false));339 340static cl::opt<bool>341OptExecMaskPreRA("amdgpu-opt-exec-mask-pre-ra", cl::Hidden,342 cl::desc("Run pre-RA exec mask optimizations"),343 cl::init(true));344 345static cl::opt<bool>346 LowerCtorDtor("amdgpu-lower-global-ctor-dtor",347 cl::desc("Lower GPU ctor / dtors to globals on the device."),348 cl::init(true), cl::Hidden);349 350// Option to disable vectorizer for tests.351static cl::opt<bool> EnableLoadStoreVectorizer(352 "amdgpu-load-store-vectorizer",353 cl::desc("Enable load store vectorizer"),354 cl::init(true),355 cl::Hidden);356 357// Option to control global loads scalarization358static cl::opt<bool> ScalarizeGlobal(359 "amdgpu-scalarize-global-loads",360 cl::desc("Enable global load scalarization"),361 cl::init(true),362 cl::Hidden);363 364// Option to run internalize pass.365static cl::opt<bool> InternalizeSymbols(366 "amdgpu-internalize-symbols",367 cl::desc("Enable elimination of non-kernel functions and unused globals"),368 cl::init(false),369 cl::Hidden);370 371// Option to inline all early.372static cl::opt<bool> EarlyInlineAll(373 "amdgpu-early-inline-all",374 cl::desc("Inline all functions early"),375 cl::init(false),376 cl::Hidden);377 378static cl::opt<bool> RemoveIncompatibleFunctions(379 "amdgpu-enable-remove-incompatible-functions", cl::Hidden,380 cl::desc("Enable removal of functions when they"381 "use features not supported by the target GPU"),382 cl::init(true));383 384static cl::opt<bool> EnableSDWAPeephole(385 "amdgpu-sdwa-peephole",386 cl::desc("Enable SDWA peepholer"),387 cl::init(true));388 389static cl::opt<bool> EnableDPPCombine(390 "amdgpu-dpp-combine",391 cl::desc("Enable DPP combiner"),392 cl::init(true));393 394// Enable address space based alias analysis395static cl::opt<bool> EnableAMDGPUAliasAnalysis("enable-amdgpu-aa", cl::Hidden,396 cl::desc("Enable AMDGPU Alias Analysis"),397 cl::init(true));398 399// Enable lib calls simplifications400static cl::opt<bool> EnableLibCallSimplify(401 "amdgpu-simplify-libcall",402 cl::desc("Enable amdgpu library simplifications"),403 cl::init(true),404 cl::Hidden);405 406static cl::opt<bool> EnableLowerKernelArguments(407 "amdgpu-ir-lower-kernel-arguments",408 cl::desc("Lower kernel argument loads in IR pass"),409 cl::init(true),410 cl::Hidden);411 412static cl::opt<bool> EnableRegReassign(413 "amdgpu-reassign-regs",414 cl::desc("Enable register reassign optimizations on gfx10+"),415 cl::init(true),416 cl::Hidden);417 418static cl::opt<bool> OptVGPRLiveRange(419 "amdgpu-opt-vgpr-liverange",420 cl::desc("Enable VGPR liverange optimizations for if-else structure"),421 cl::init(true), cl::Hidden);422 423static cl::opt<ScanOptions> AMDGPUAtomicOptimizerStrategy(424 "amdgpu-atomic-optimizer-strategy",425 cl::desc("Select DPP or Iterative strategy for scan"),426 cl::init(ScanOptions::Iterative),427 cl::values(428 clEnumValN(ScanOptions::DPP, "DPP", "Use DPP operations for scan"),429 clEnumValN(ScanOptions::Iterative, "Iterative",430 "Use Iterative approach for scan"),431 clEnumValN(ScanOptions::None, "None", "Disable atomic optimizer")));432 433// Enable Mode register optimization434static cl::opt<bool> EnableSIModeRegisterPass(435 "amdgpu-mode-register",436 cl::desc("Enable mode register pass"),437 cl::init(true),438 cl::Hidden);439 440// Enable GFX11+ s_delay_alu insertion441static cl::opt<bool>442 EnableInsertDelayAlu("amdgpu-enable-delay-alu",443 cl::desc("Enable s_delay_alu insertion"),444 cl::init(true), cl::Hidden);445 446// Enable GFX11+ VOPD447static cl::opt<bool>448 EnableVOPD("amdgpu-enable-vopd",449 cl::desc("Enable VOPD, dual issue of VALU in wave32"),450 cl::init(true), cl::Hidden);451 452// Option is used in lit tests to prevent deadcoding of patterns inspected.453static cl::opt<bool>454EnableDCEInRA("amdgpu-dce-in-ra",455 cl::init(true), cl::Hidden,456 cl::desc("Enable machine DCE inside regalloc"));457 458static cl::opt<bool> EnableSetWavePriority("amdgpu-set-wave-priority",459 cl::desc("Adjust wave priority"),460 cl::init(false), cl::Hidden);461 462static cl::opt<bool> EnableScalarIRPasses(463 "amdgpu-scalar-ir-passes",464 cl::desc("Enable scalar IR passes"),465 cl::init(true),466 cl::Hidden);467 468static cl::opt<bool> EnableLowerExecSync(469 "amdgpu-enable-lower-exec-sync",470 cl::desc("Enable lowering of execution synchronization."), cl::init(true),471 cl::Hidden);472 473static cl::opt<bool>474 EnableSwLowerLDS("amdgpu-enable-sw-lower-lds",475 cl::desc("Enable lowering of lds to global memory pass "476 "and asan instrument resulting IR."),477 cl::init(true), cl::Hidden);478 479static cl::opt<bool, true> EnableLowerModuleLDS(480 "amdgpu-enable-lower-module-lds", cl::desc("Enable lower module lds pass"),481 cl::location(AMDGPUTargetMachine::EnableLowerModuleLDS), cl::init(true),482 cl::Hidden);483 484static cl::opt<bool> EnablePreRAOptimizations(485 "amdgpu-enable-pre-ra-optimizations",486 cl::desc("Enable Pre-RA optimizations pass"), cl::init(true),487 cl::Hidden);488 489static cl::opt<bool> EnablePromoteKernelArguments(490 "amdgpu-enable-promote-kernel-arguments",491 cl::desc("Enable promotion of flat kernel pointer arguments to global"),492 cl::Hidden, cl::init(true));493 494static cl::opt<bool> EnableImageIntrinsicOptimizer(495 "amdgpu-enable-image-intrinsic-optimizer",496 cl::desc("Enable image intrinsic optimizer pass"), cl::init(true),497 cl::Hidden);498 499static cl::opt<bool>500 EnableLoopPrefetch("amdgpu-loop-prefetch",501 cl::desc("Enable loop data prefetch on AMDGPU"),502 cl::Hidden, cl::init(false));503 504static cl::opt<std::string>505 AMDGPUSchedStrategy("amdgpu-sched-strategy",506 cl::desc("Select custom AMDGPU scheduling strategy."),507 cl::Hidden, cl::init(""));508 509static cl::opt<bool> EnableRewritePartialRegUses(510 "amdgpu-enable-rewrite-partial-reg-uses",511 cl::desc("Enable rewrite partial reg uses pass"), cl::init(true),512 cl::Hidden);513 514static cl::opt<bool> EnableHipStdPar(515 "amdgpu-enable-hipstdpar",516 cl::desc("Enable HIP Standard Parallelism Offload support"), cl::init(false),517 cl::Hidden);518 519static cl::opt<bool>520 EnableAMDGPUAttributor("amdgpu-attributor-enable",521 cl::desc("Enable AMDGPUAttributorPass"),522 cl::init(true), cl::Hidden);523 524static cl::opt<bool> NewRegBankSelect(525 "new-reg-bank-select",526 cl::desc("Run amdgpu-regbankselect and amdgpu-regbanklegalize instead of "527 "regbankselect"),528 cl::init(false), cl::Hidden);529 530static cl::opt<bool> HasClosedWorldAssumption(531 "amdgpu-link-time-closed-world",532 cl::desc("Whether has closed-world assumption at link time"),533 cl::init(false), cl::Hidden);534 535static cl::opt<bool> EnableUniformIntrinsicCombine(536 "amdgpu-enable-uniform-intrinsic-combine",537 cl::desc("Enable/Disable the Uniform Intrinsic Combine Pass"),538 cl::init(true), cl::Hidden);539 540extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUTarget() {541 // Register the target542 RegisterTargetMachine<R600TargetMachine> X(getTheR600Target());543 RegisterTargetMachine<GCNTargetMachine> Y(getTheGCNTarget());544 545 PassRegistry *PR = PassRegistry::getPassRegistry();546 initializeR600ClauseMergePassPass(*PR);547 initializeR600ControlFlowFinalizerPass(*PR);548 initializeR600PacketizerPass(*PR);549 initializeR600ExpandSpecialInstrsPassPass(*PR);550 initializeR600VectorRegMergerPass(*PR);551 initializeR600EmitClauseMarkersPass(*PR);552 initializeR600MachineCFGStructurizerPass(*PR);553 initializeGlobalISel(*PR);554 initializeAMDGPUAsmPrinterPass(*PR);555 initializeAMDGPUDAGToDAGISelLegacyPass(*PR);556 initializeAMDGPUPrepareAGPRAllocLegacyPass(*PR);557 initializeGCNDPPCombineLegacyPass(*PR);558 initializeSILowerI1CopiesLegacyPass(*PR);559 initializeAMDGPUGlobalISelDivergenceLoweringPass(*PR);560 initializeAMDGPURegBankSelectPass(*PR);561 initializeAMDGPURegBankLegalizePass(*PR);562 initializeSILowerWWMCopiesLegacyPass(*PR);563 initializeAMDGPUMarkLastScratchLoadLegacyPass(*PR);564 initializeSILowerSGPRSpillsLegacyPass(*PR);565 initializeSIFixSGPRCopiesLegacyPass(*PR);566 initializeSIFixVGPRCopiesLegacyPass(*PR);567 initializeSIFoldOperandsLegacyPass(*PR);568 initializeSIPeepholeSDWALegacyPass(*PR);569 initializeSIShrinkInstructionsLegacyPass(*PR);570 initializeSIOptimizeExecMaskingPreRALegacyPass(*PR);571 initializeSIOptimizeVGPRLiveRangeLegacyPass(*PR);572 initializeSILoadStoreOptimizerLegacyPass(*PR);573 initializeAMDGPUCtorDtorLoweringLegacyPass(*PR);574 initializeAMDGPUAlwaysInlinePass(*PR);575 initializeAMDGPULowerExecSyncLegacyPass(*PR);576 initializeAMDGPUSwLowerLDSLegacyPass(*PR);577 initializeAMDGPUAnnotateUniformValuesLegacyPass(*PR);578 initializeAMDGPUArgumentUsageInfoPass(*PR);579 initializeAMDGPUAtomicOptimizerPass(*PR);580 initializeAMDGPULowerKernelArgumentsPass(*PR);581 initializeAMDGPUPromoteKernelArgumentsPass(*PR);582 initializeAMDGPULowerKernelAttributesPass(*PR);583 initializeAMDGPUExportKernelRuntimeHandlesLegacyPass(*PR);584 initializeAMDGPUPostLegalizerCombinerPass(*PR);585 initializeAMDGPUPreLegalizerCombinerPass(*PR);586 initializeAMDGPURegBankCombinerPass(*PR);587 initializeAMDGPUPromoteAllocaPass(*PR);588 initializeAMDGPUCodeGenPreparePass(*PR);589 initializeAMDGPULateCodeGenPrepareLegacyPass(*PR);590 initializeAMDGPURemoveIncompatibleFunctionsLegacyPass(*PR);591 initializeAMDGPULowerModuleLDSLegacyPass(*PR);592 initializeAMDGPULowerBufferFatPointersPass(*PR);593 initializeAMDGPULowerIntrinsicsLegacyPass(*PR);594 initializeAMDGPUReserveWWMRegsLegacyPass(*PR);595 initializeAMDGPURewriteAGPRCopyMFMALegacyPass(*PR);596 initializeAMDGPURewriteOutArgumentsPass(*PR);597 initializeAMDGPURewriteUndefForPHILegacyPass(*PR);598 initializeSIAnnotateControlFlowLegacyPass(*PR);599 initializeAMDGPUInsertDelayAluLegacyPass(*PR);600 initializeAMDGPULowerVGPREncodingLegacyPass(*PR);601 initializeSIInsertHardClausesLegacyPass(*PR);602 initializeSIInsertWaitcntsLegacyPass(*PR);603 initializeSIModeRegisterLegacyPass(*PR);604 initializeSIWholeQuadModeLegacyPass(*PR);605 initializeSILowerControlFlowLegacyPass(*PR);606 initializeSIPreEmitPeepholeLegacyPass(*PR);607 initializeSILateBranchLoweringLegacyPass(*PR);608 initializeSIMemoryLegalizerLegacyPass(*PR);609 initializeSIOptimizeExecMaskingLegacyPass(*PR);610 initializeSIPreAllocateWWMRegsLegacyPass(*PR);611 initializeSIFormMemoryClausesLegacyPass(*PR);612 initializeSIPostRABundlerLegacyPass(*PR);613 initializeGCNCreateVOPDLegacyPass(*PR);614 initializeAMDGPUUnifyDivergentExitNodesPass(*PR);615 initializeAMDGPUAAWrapperPassPass(*PR);616 initializeAMDGPUExternalAAWrapperPass(*PR);617 initializeAMDGPUImageIntrinsicOptimizerPass(*PR);618 initializeAMDGPUPrintfRuntimeBindingPass(*PR);619 initializeAMDGPUResourceUsageAnalysisWrapperPassPass(*PR);620 initializeGCNNSAReassignLegacyPass(*PR);621 initializeGCNPreRAOptimizationsLegacyPass(*PR);622 initializeGCNPreRALongBranchRegLegacyPass(*PR);623 initializeGCNRewritePartialRegUsesLegacyPass(*PR);624 initializeGCNRegPressurePrinterPass(*PR);625 initializeAMDGPUPreloadKernArgPrologLegacyPass(*PR);626 initializeAMDGPUWaitSGPRHazardsLegacyPass(*PR);627 initializeAMDGPUPreloadKernelArgumentsLegacyPass(*PR);628 initializeAMDGPUUniformIntrinsicCombineLegacyPass(*PR);629}630 631static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {632 return std::make_unique<AMDGPUTargetObjectFile>();633}634 635static ScheduleDAGInstrs *createSIMachineScheduler(MachineSchedContext *C) {636 return new SIScheduleDAGMI(C);637}638 639static ScheduleDAGInstrs *640createGCNMaxOccupancyMachineScheduler(MachineSchedContext *C) {641 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();642 ScheduleDAGMILive *DAG =643 new GCNScheduleDAGMILive(C, std::make_unique<GCNMaxOccupancySchedStrategy>(C));644 DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI));645 if (ST.shouldClusterStores())646 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));647 DAG->addMutation(createIGroupLPDAGMutation(AMDGPU::SchedulingPhase::Initial));648 DAG->addMutation(createAMDGPUMacroFusionDAGMutation());649 DAG->addMutation(createAMDGPUExportClusteringDAGMutation());650 DAG->addMutation(createAMDGPUBarrierLatencyDAGMutation(C->MF));651 return DAG;652}653 654static ScheduleDAGInstrs *655createGCNMaxILPMachineScheduler(MachineSchedContext *C) {656 ScheduleDAGMILive *DAG =657 new GCNScheduleDAGMILive(C, std::make_unique<GCNMaxILPSchedStrategy>(C));658 DAG->addMutation(createIGroupLPDAGMutation(AMDGPU::SchedulingPhase::Initial));659 return DAG;660}661 662static ScheduleDAGInstrs *663createGCNMaxMemoryClauseMachineScheduler(MachineSchedContext *C) {664 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();665 ScheduleDAGMILive *DAG = new GCNScheduleDAGMILive(666 C, std::make_unique<GCNMaxMemoryClauseSchedStrategy>(C));667 DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI));668 if (ST.shouldClusterStores())669 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));670 DAG->addMutation(createAMDGPUExportClusteringDAGMutation());671 DAG->addMutation(createAMDGPUBarrierLatencyDAGMutation(C->MF));672 return DAG;673}674 675static ScheduleDAGInstrs *676createIterativeGCNMaxOccupancyMachineScheduler(MachineSchedContext *C) {677 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();678 auto *DAG = new GCNIterativeScheduler(679 C, GCNIterativeScheduler::SCHEDULE_LEGACYMAXOCCUPANCY);680 DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI));681 if (ST.shouldClusterStores())682 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));683 DAG->addMutation(createIGroupLPDAGMutation(AMDGPU::SchedulingPhase::Initial));684 return DAG;685}686 687static ScheduleDAGInstrs *createMinRegScheduler(MachineSchedContext *C) {688 auto *DAG = new GCNIterativeScheduler(689 C, GCNIterativeScheduler::SCHEDULE_MINREGFORCED);690 DAG->addMutation(createIGroupLPDAGMutation(AMDGPU::SchedulingPhase::Initial));691 return DAG;692}693 694static ScheduleDAGInstrs *695createIterativeILPMachineScheduler(MachineSchedContext *C) {696 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();697 auto *DAG = new GCNIterativeScheduler(C, GCNIterativeScheduler::SCHEDULE_ILP);698 DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI));699 if (ST.shouldClusterStores())700 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));701 DAG->addMutation(createAMDGPUMacroFusionDAGMutation());702 DAG->addMutation(createIGroupLPDAGMutation(AMDGPU::SchedulingPhase::Initial));703 return DAG;704}705 706static MachineSchedRegistry707SISchedRegistry("si", "Run SI's custom scheduler",708 createSIMachineScheduler);709 710static MachineSchedRegistry711GCNMaxOccupancySchedRegistry("gcn-max-occupancy",712 "Run GCN scheduler to maximize occupancy",713 createGCNMaxOccupancyMachineScheduler);714 715static MachineSchedRegistry716 GCNMaxILPSchedRegistry("gcn-max-ilp", "Run GCN scheduler to maximize ilp",717 createGCNMaxILPMachineScheduler);718 719static MachineSchedRegistry GCNMaxMemoryClauseSchedRegistry(720 "gcn-max-memory-clause", "Run GCN scheduler to maximize memory clause",721 createGCNMaxMemoryClauseMachineScheduler);722 723static MachineSchedRegistry IterativeGCNMaxOccupancySchedRegistry(724 "gcn-iterative-max-occupancy-experimental",725 "Run GCN scheduler to maximize occupancy (experimental)",726 createIterativeGCNMaxOccupancyMachineScheduler);727 728static MachineSchedRegistry GCNMinRegSchedRegistry(729 "gcn-iterative-minreg",730 "Run GCN iterative scheduler for minimal register usage (experimental)",731 createMinRegScheduler);732 733static MachineSchedRegistry GCNILPSchedRegistry(734 "gcn-iterative-ilp",735 "Run GCN iterative scheduler for ILP scheduling (experimental)",736 createIterativeILPMachineScheduler);737 738LLVM_READNONE739static StringRef getGPUOrDefault(const Triple &TT, StringRef GPU) {740 if (!GPU.empty())741 return GPU;742 743 // Need to default to a target with flat support for HSA.744 if (TT.isAMDGCN())745 return TT.getOS() == Triple::AMDHSA ? "generic-hsa" : "generic";746 747 return "r600";748}749 750static Reloc::Model getEffectiveRelocModel() {751 // The AMDGPU toolchain only supports generating shared objects, so we752 // must always use PIC.753 return Reloc::PIC_;754}755 756AMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, const Triple &TT,757 StringRef CPU, StringRef FS,758 const TargetOptions &Options,759 std::optional<Reloc::Model> RM,760 std::optional<CodeModel::Model> CM,761 CodeGenOptLevel OptLevel)762 : CodeGenTargetMachineImpl(763 T, TT.computeDataLayout(), TT, getGPUOrDefault(TT, CPU), FS, Options,764 getEffectiveRelocModel(), getEffectiveCodeModel(CM, CodeModel::Small),765 OptLevel),766 TLOF(createTLOF(getTargetTriple())) {767 initAsmInfo();768 if (TT.isAMDGCN()) {769 if (getMCSubtargetInfo()->checkFeatures("+wavefrontsize64"))770 MRI.reset(llvm::createGCNMCRegisterInfo(AMDGPUDwarfFlavour::Wave64));771 else if (getMCSubtargetInfo()->checkFeatures("+wavefrontsize32"))772 MRI.reset(llvm::createGCNMCRegisterInfo(AMDGPUDwarfFlavour::Wave32));773 }774}775 776bool AMDGPUTargetMachine::EnableFunctionCalls = false;777bool AMDGPUTargetMachine::EnableLowerModuleLDS = true;778 779AMDGPUTargetMachine::~AMDGPUTargetMachine() = default;780 781StringRef AMDGPUTargetMachine::getGPUName(const Function &F) const {782 Attribute GPUAttr = F.getFnAttribute("target-cpu");783 return GPUAttr.isValid() ? GPUAttr.getValueAsString() : getTargetCPU();784}785 786StringRef AMDGPUTargetMachine::getFeatureString(const Function &F) const {787 Attribute FSAttr = F.getFnAttribute("target-features");788 789 return FSAttr.isValid() ? FSAttr.getValueAsString()790 : getTargetFeatureString();791}792 793llvm::ScheduleDAGInstrs *794AMDGPUTargetMachine::createMachineScheduler(MachineSchedContext *C) const {795 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();796 ScheduleDAGMILive *DAG = createSchedLive(C);797 DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI));798 if (ST.shouldClusterStores())799 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));800 return DAG;801}802 803/// Predicate for Internalize pass.804static bool mustPreserveGV(const GlobalValue &GV) {805 if (const Function *F = dyn_cast<Function>(&GV))806 return F->isDeclaration() || F->getName().starts_with("__asan_") ||807 F->getName().starts_with("__sanitizer_") ||808 AMDGPU::isEntryFunctionCC(F->getCallingConv());809 810 GV.removeDeadConstantUsers();811 return !GV.use_empty();812}813 814void AMDGPUTargetMachine::registerDefaultAliasAnalyses(AAManager &AAM) {815 AAM.registerFunctionAnalysis<AMDGPUAA>();816}817 818static Expected<ScanOptions>819parseAMDGPUAtomicOptimizerStrategy(StringRef Params) {820 if (Params.empty())821 return ScanOptions::Iterative;822 Params.consume_front("strategy=");823 auto Result = StringSwitch<std::optional<ScanOptions>>(Params)824 .Case("dpp", ScanOptions::DPP)825 .Cases({"iterative", ""}, ScanOptions::Iterative)826 .Case("none", ScanOptions::None)827 .Default(std::nullopt);828 if (Result)829 return *Result;830 return make_error<StringError>("invalid parameter", inconvertibleErrorCode());831}832 833Expected<AMDGPUAttributorOptions>834parseAMDGPUAttributorPassOptions(StringRef Params) {835 AMDGPUAttributorOptions Result;836 while (!Params.empty()) {837 StringRef ParamName;838 std::tie(ParamName, Params) = Params.split(';');839 if (ParamName == "closed-world") {840 Result.IsClosedWorld = true;841 } else {842 return make_error<StringError>(843 formatv("invalid AMDGPUAttributor pass parameter '{0}' ", ParamName)844 .str(),845 inconvertibleErrorCode());846 }847 }848 return Result;849}850 851void AMDGPUTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {852 853#define GET_PASS_REGISTRY "AMDGPUPassRegistry.def"854#include "llvm/Passes/TargetPassRegistry.inc"855 856 PB.registerScalarOptimizerLateEPCallback(857 [](FunctionPassManager &FPM, OptimizationLevel Level) {858 if (Level == OptimizationLevel::O0)859 return;860 861 FPM.addPass(InferAddressSpacesPass());862 });863 864 PB.registerVectorizerEndEPCallback(865 [](FunctionPassManager &FPM, OptimizationLevel Level) {866 if (Level == OptimizationLevel::O0)867 return;868 869 FPM.addPass(InferAddressSpacesPass());870 });871 872 PB.registerPipelineEarlySimplificationEPCallback(873 [](ModulePassManager &PM, OptimizationLevel Level,874 ThinOrFullLTOPhase Phase) {875 if (!isLTOPreLink(Phase)) {876 // When we are not using -fgpu-rdc, we can run accelerator code877 // selection relatively early, but still after linking to prevent878 // eager removal of potentially reachable symbols.879 if (EnableHipStdPar) {880 PM.addPass(HipStdParMathFixupPass());881 PM.addPass(HipStdParAcceleratorCodeSelectionPass());882 }883 PM.addPass(AMDGPUPrintfRuntimeBindingPass());884 }885 886 if (Level == OptimizationLevel::O0)887 return;888 889 // We don't want to run internalization at per-module stage.890 if (InternalizeSymbols && !isLTOPreLink(Phase)) {891 PM.addPass(InternalizePass(mustPreserveGV));892 PM.addPass(GlobalDCEPass());893 }894 895 if (EarlyInlineAll && !EnableFunctionCalls)896 PM.addPass(AMDGPUAlwaysInlinePass());897 });898 899 PB.registerPeepholeEPCallback(900 [](FunctionPassManager &FPM, OptimizationLevel Level) {901 if (Level == OptimizationLevel::O0)902 return;903 904 FPM.addPass(AMDGPUUseNativeCallsPass());905 if (EnableLibCallSimplify)906 FPM.addPass(AMDGPUSimplifyLibCallsPass());907 908 if (EnableUniformIntrinsicCombine)909 FPM.addPass(AMDGPUUniformIntrinsicCombinePass());910 });911 912 PB.registerCGSCCOptimizerLateEPCallback(913 [this](CGSCCPassManager &PM, OptimizationLevel Level) {914 if (Level == OptimizationLevel::O0)915 return;916 917 FunctionPassManager FPM;918 919 // Add promote kernel arguments pass to the opt pipeline right before920 // infer address spaces which is needed to do actual address space921 // rewriting.922 if (Level.getSpeedupLevel() > OptimizationLevel::O1.getSpeedupLevel() &&923 EnablePromoteKernelArguments)924 FPM.addPass(AMDGPUPromoteKernelArgumentsPass());925 926 // Add infer address spaces pass to the opt pipeline after inlining927 // but before SROA to increase SROA opportunities.928 FPM.addPass(InferAddressSpacesPass());929 930 // This should run after inlining to have any chance of doing931 // anything, and before other cleanup optimizations.932 FPM.addPass(AMDGPULowerKernelAttributesPass());933 934 if (Level != OptimizationLevel::O0) {935 // Promote alloca to vector before SROA and loop unroll. If we936 // manage to eliminate allocas before unroll we may choose to unroll937 // less.938 FPM.addPass(AMDGPUPromoteAllocaToVectorPass(*this));939 }940 941 PM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM)));942 });943 944 // FIXME: Why is AMDGPUAttributor not in CGSCC?945 PB.registerOptimizerLastEPCallback([this](ModulePassManager &MPM,946 OptimizationLevel Level,947 ThinOrFullLTOPhase Phase) {948 if (Level != OptimizationLevel::O0) {949 if (!isLTOPreLink(Phase)) {950 if (EnableAMDGPUAttributor && getTargetTriple().isAMDGCN()) {951 AMDGPUAttributorOptions Opts;952 MPM.addPass(AMDGPUAttributorPass(*this, Opts, Phase));953 }954 }955 }956 });957 958 PB.registerFullLinkTimeOptimizationLastEPCallback(959 [this](ModulePassManager &PM, OptimizationLevel Level) {960 // When we are using -fgpu-rdc, we can only run accelerator code961 // selection after linking to prevent, otherwise we end up removing962 // potentially reachable symbols that were exported as external in other963 // modules.964 if (EnableHipStdPar) {965 PM.addPass(HipStdParMathFixupPass());966 PM.addPass(HipStdParAcceleratorCodeSelectionPass());967 }968 // We want to support the -lto-partitions=N option as "best effort".969 // For that, we need to lower LDS earlier in the pipeline before the970 // module is partitioned for codegen.971 if (EnableLowerExecSync)972 PM.addPass(AMDGPULowerExecSyncPass());973 if (EnableSwLowerLDS)974 PM.addPass(AMDGPUSwLowerLDSPass(*this));975 if (EnableLowerModuleLDS)976 PM.addPass(AMDGPULowerModuleLDSPass(*this));977 if (Level != OptimizationLevel::O0) {978 // We only want to run this with O2 or higher since inliner and SROA979 // don't run in O1.980 if (Level != OptimizationLevel::O1) {981 PM.addPass(982 createModuleToFunctionPassAdaptor(InferAddressSpacesPass()));983 }984 // Do we really need internalization in LTO?985 if (InternalizeSymbols) {986 PM.addPass(InternalizePass(mustPreserveGV));987 PM.addPass(GlobalDCEPass());988 }989 if (EnableAMDGPUAttributor && getTargetTriple().isAMDGCN()) {990 AMDGPUAttributorOptions Opt;991 if (HasClosedWorldAssumption)992 Opt.IsClosedWorld = true;993 PM.addPass(AMDGPUAttributorPass(994 *this, Opt, ThinOrFullLTOPhase::FullLTOPostLink));995 }996 }997 if (!NoKernelInfoEndLTO) {998 FunctionPassManager FPM;999 FPM.addPass(KernelInfoPrinter(this));1000 PM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));1001 }1002 });1003 1004 PB.registerRegClassFilterParsingCallback(1005 [](StringRef FilterName) -> RegAllocFilterFunc {1006 if (FilterName == "sgpr")1007 return onlyAllocateSGPRs;1008 if (FilterName == "vgpr")1009 return onlyAllocateVGPRs;1010 if (FilterName == "wwm")1011 return onlyAllocateWWMRegs;1012 return nullptr;1013 });1014}1015 1016int64_t AMDGPUTargetMachine::getNullPointerValue(unsigned AddrSpace) {1017 return (AddrSpace == AMDGPUAS::LOCAL_ADDRESS ||1018 AddrSpace == AMDGPUAS::PRIVATE_ADDRESS ||1019 AddrSpace == AMDGPUAS::REGION_ADDRESS)1020 ? -11021 : 0;1022}1023 1024bool AMDGPUTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS,1025 unsigned DestAS) const {1026 return AMDGPU::isFlatGlobalAddrSpace(SrcAS) &&1027 AMDGPU::isFlatGlobalAddrSpace(DestAS);1028}1029 1030unsigned AMDGPUTargetMachine::getAssumedAddrSpace(const Value *V) const {1031 if (auto *Arg = dyn_cast<Argument>(V);1032 Arg &&1033 AMDGPU::isModuleEntryFunctionCC(Arg->getParent()->getCallingConv()) &&1034 !Arg->hasByRefAttr())1035 return AMDGPUAS::GLOBAL_ADDRESS;1036 1037 const auto *LD = dyn_cast<LoadInst>(V);1038 if (!LD) // TODO: Handle invariant load like constant.1039 return AMDGPUAS::UNKNOWN_ADDRESS_SPACE;1040 1041 // It must be a generic pointer loaded.1042 assert(V->getType()->getPointerAddressSpace() == AMDGPUAS::FLAT_ADDRESS);1043 1044 const auto *Ptr = LD->getPointerOperand();1045 if (Ptr->getType()->getPointerAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS)1046 return AMDGPUAS::UNKNOWN_ADDRESS_SPACE;1047 // For a generic pointer loaded from the constant memory, it could be assumed1048 // as a global pointer since the constant memory is only populated on the1049 // host side. As implied by the offload programming model, only global1050 // pointers could be referenced on the host side.1051 return AMDGPUAS::GLOBAL_ADDRESS;1052}1053 1054std::pair<const Value *, unsigned>1055AMDGPUTargetMachine::getPredicatedAddrSpace(const Value *V) const {1056 if (auto *II = dyn_cast<IntrinsicInst>(V)) {1057 switch (II->getIntrinsicID()) {1058 case Intrinsic::amdgcn_is_shared:1059 return std::pair(II->getArgOperand(0), AMDGPUAS::LOCAL_ADDRESS);1060 case Intrinsic::amdgcn_is_private:1061 return std::pair(II->getArgOperand(0), AMDGPUAS::PRIVATE_ADDRESS);1062 default:1063 break;1064 }1065 return std::pair(nullptr, -1);1066 }1067 // Check the global pointer predication based on1068 // (!is_share(p) && !is_private(p)). Note that logic 'and' is commutative and1069 // the order of 'is_shared' and 'is_private' is not significant.1070 Value *Ptr;1071 if (match(1072 const_cast<Value *>(V),1073 m_c_And(m_Not(m_Intrinsic<Intrinsic::amdgcn_is_shared>(m_Value(Ptr))),1074 m_Not(m_Intrinsic<Intrinsic::amdgcn_is_private>(1075 m_Deferred(Ptr))))))1076 return std::pair(Ptr, AMDGPUAS::GLOBAL_ADDRESS);1077 1078 return std::pair(nullptr, -1);1079}1080 1081unsigned1082AMDGPUTargetMachine::getAddressSpaceForPseudoSourceKind(unsigned Kind) const {1083 switch (Kind) {1084 case PseudoSourceValue::Stack:1085 case PseudoSourceValue::FixedStack:1086 return AMDGPUAS::PRIVATE_ADDRESS;1087 case PseudoSourceValue::ConstantPool:1088 case PseudoSourceValue::GOT:1089 case PseudoSourceValue::JumpTable:1090 case PseudoSourceValue::GlobalValueCallEntry:1091 case PseudoSourceValue::ExternalSymbolCallEntry:1092 return AMDGPUAS::CONSTANT_ADDRESS;1093 }1094 return AMDGPUAS::FLAT_ADDRESS;1095}1096 1097bool AMDGPUTargetMachine::splitModule(1098 Module &M, unsigned NumParts,1099 function_ref<void(std::unique_ptr<Module> MPart)> ModuleCallback) {1100 // FIXME(?): Would be better to use an already existing Analysis/PassManager,1101 // but all current users of this API don't have one ready and would need to1102 // create one anyway. Let's hide the boilerplate for now to keep it simple.1103 1104 LoopAnalysisManager LAM;1105 FunctionAnalysisManager FAM;1106 CGSCCAnalysisManager CGAM;1107 ModuleAnalysisManager MAM;1108 1109 PassBuilder PB(this);1110 PB.registerModuleAnalyses(MAM);1111 PB.registerFunctionAnalyses(FAM);1112 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);1113 1114 ModulePassManager MPM;1115 MPM.addPass(AMDGPUSplitModulePass(NumParts, ModuleCallback));1116 MPM.run(M, MAM);1117 return true;1118}1119 1120//===----------------------------------------------------------------------===//1121// GCN Target Machine (SI+)1122//===----------------------------------------------------------------------===//1123 1124GCNTargetMachine::GCNTargetMachine(const Target &T, const Triple &TT,1125 StringRef CPU, StringRef FS,1126 const TargetOptions &Options,1127 std::optional<Reloc::Model> RM,1128 std::optional<CodeModel::Model> CM,1129 CodeGenOptLevel OL, bool JIT)1130 : AMDGPUTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL) {}1131 1132const TargetSubtargetInfo *1133GCNTargetMachine::getSubtargetImpl(const Function &F) const {1134 StringRef GPU = getGPUName(F);1135 StringRef FS = getFeatureString(F);1136 1137 SmallString<128> SubtargetKey(GPU);1138 SubtargetKey.append(FS);1139 1140 auto &I = SubtargetMap[SubtargetKey];1141 if (!I) {1142 // This needs to be done before we create a new subtarget since any1143 // creation will depend on the TM and the code generation flags on the1144 // function that reside in TargetOptions.1145 resetTargetOptions(F);1146 I = std::make_unique<GCNSubtarget>(TargetTriple, GPU, FS, *this);1147 }1148 1149 I->setScalarizeGlobalBehavior(ScalarizeGlobal);1150 1151 return I.get();1152}1153 1154TargetTransformInfo1155GCNTargetMachine::getTargetTransformInfo(const Function &F) const {1156 return TargetTransformInfo(std::make_unique<GCNTTIImpl>(this, F));1157}1158 1159Error GCNTargetMachine::buildCodeGenPipeline(1160 ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,1161 CodeGenFileType FileType, const CGPassBuilderOption &Opts,1162 PassInstrumentationCallbacks *PIC) {1163 AMDGPUCodeGenPassBuilder CGPB(*this, Opts, PIC);1164 return CGPB.buildPipeline(MPM, Out, DwoOut, FileType);1165}1166 1167ScheduleDAGInstrs *1168GCNTargetMachine::createMachineScheduler(MachineSchedContext *C) const {1169 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();1170 if (ST.enableSIScheduler())1171 return createSIMachineScheduler(C);1172 1173 Attribute SchedStrategyAttr =1174 C->MF->getFunction().getFnAttribute("amdgpu-sched-strategy");1175 StringRef SchedStrategy = SchedStrategyAttr.isValid()1176 ? SchedStrategyAttr.getValueAsString()1177 : AMDGPUSchedStrategy;1178 1179 if (SchedStrategy == "max-ilp")1180 return createGCNMaxILPMachineScheduler(C);1181 1182 if (SchedStrategy == "max-memory-clause")1183 return createGCNMaxMemoryClauseMachineScheduler(C);1184 1185 if (SchedStrategy == "iterative-ilp")1186 return createIterativeILPMachineScheduler(C);1187 1188 if (SchedStrategy == "iterative-minreg")1189 return createMinRegScheduler(C);1190 1191 if (SchedStrategy == "iterative-maxocc")1192 return createIterativeGCNMaxOccupancyMachineScheduler(C);1193 1194 return createGCNMaxOccupancyMachineScheduler(C);1195}1196 1197ScheduleDAGInstrs *1198GCNTargetMachine::createPostMachineScheduler(MachineSchedContext *C) const {1199 ScheduleDAGMI *DAG =1200 new GCNPostScheduleDAGMILive(C, std::make_unique<PostGenericScheduler>(C),1201 /*RemoveKillFlags=*/true);1202 const GCNSubtarget &ST = C->MF->getSubtarget<GCNSubtarget>();1203 DAG->addMutation(createLoadClusterDAGMutation(DAG->TII, DAG->TRI));1204 if (ST.shouldClusterStores())1205 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));1206 DAG->addMutation(createIGroupLPDAGMutation(AMDGPU::SchedulingPhase::PostRA));1207 if ((EnableVOPD.getNumOccurrences() ||1208 getOptLevel() >= CodeGenOptLevel::Less) &&1209 EnableVOPD)1210 DAG->addMutation(createVOPDPairingMutation());1211 DAG->addMutation(createAMDGPUExportClusteringDAGMutation());1212 DAG->addMutation(createAMDGPUBarrierLatencyDAGMutation(C->MF));1213 return DAG;1214}1215//===----------------------------------------------------------------------===//1216// AMDGPU Legacy Pass Setup1217//===----------------------------------------------------------------------===//1218 1219std::unique_ptr<CSEConfigBase> llvm::AMDGPUPassConfig::getCSEConfig() const {1220 return getStandardCSEConfigForOpt(TM->getOptLevel());1221}1222 1223namespace {1224 1225class GCNPassConfig final : public AMDGPUPassConfig {1226public:1227 GCNPassConfig(TargetMachine &TM, PassManagerBase &PM)1228 : AMDGPUPassConfig(TM, PM) {1229 substitutePass(&PostRASchedulerID, &PostMachineSchedulerID);1230 }1231 1232 GCNTargetMachine &getGCNTargetMachine() const {1233 return getTM<GCNTargetMachine>();1234 }1235 1236 bool addPreISel() override;1237 void addMachineSSAOptimization() override;1238 bool addILPOpts() override;1239 bool addInstSelector() override;1240 bool addIRTranslator() override;1241 void addPreLegalizeMachineIR() override;1242 bool addLegalizeMachineIR() override;1243 void addPreRegBankSelect() override;1244 bool addRegBankSelect() override;1245 void addPreGlobalInstructionSelect() override;1246 bool addGlobalInstructionSelect() override;1247 void addPreRegAlloc() override;1248 void addFastRegAlloc() override;1249 void addOptimizedRegAlloc() override;1250 1251 FunctionPass *createSGPRAllocPass(bool Optimized);1252 FunctionPass *createVGPRAllocPass(bool Optimized);1253 FunctionPass *createWWMRegAllocPass(bool Optimized);1254 FunctionPass *createRegAllocPass(bool Optimized) override;1255 1256 bool addRegAssignAndRewriteFast() override;1257 bool addRegAssignAndRewriteOptimized() override;1258 1259 bool addPreRewrite() override;1260 void addPostRegAlloc() override;1261 void addPreSched2() override;1262 void addPreEmitPass() override;1263 void addPostBBSections() override;1264};1265 1266} // end anonymous namespace1267 1268AMDGPUPassConfig::AMDGPUPassConfig(TargetMachine &TM, PassManagerBase &PM)1269 : TargetPassConfig(TM, PM) {1270 // Exceptions and StackMaps are not supported, so these passes will never do1271 // anything.1272 disablePass(&StackMapLivenessID);1273 disablePass(&FuncletLayoutID);1274 // Garbage collection is not supported.1275 disablePass(&GCLoweringID);1276 disablePass(&ShadowStackGCLoweringID);1277}1278 1279void AMDGPUPassConfig::addEarlyCSEOrGVNPass() {1280 if (getOptLevel() == CodeGenOptLevel::Aggressive)1281 addPass(createGVNPass());1282 else1283 addPass(createEarlyCSEPass());1284}1285 1286void AMDGPUPassConfig::addStraightLineScalarOptimizationPasses() {1287 if (isPassEnabled(EnableLoopPrefetch, CodeGenOptLevel::Aggressive))1288 addPass(createLoopDataPrefetchPass());1289 addPass(createSeparateConstOffsetFromGEPPass());1290 // ReassociateGEPs exposes more opportunities for SLSR. See1291 // the example in reassociate-geps-and-slsr.ll.1292 addPass(createStraightLineStrengthReducePass());1293 // SeparateConstOffsetFromGEP and SLSR creates common expressions which GVN or1294 // EarlyCSE can reuse.1295 addEarlyCSEOrGVNPass();1296 // Run NaryReassociate after EarlyCSE/GVN to be more effective.1297 addPass(createNaryReassociatePass());1298 // NaryReassociate on GEPs creates redundant common expressions, so run1299 // EarlyCSE after it.1300 addPass(createEarlyCSEPass());1301}1302 1303void AMDGPUPassConfig::addIRPasses() {1304 const AMDGPUTargetMachine &TM = getAMDGPUTargetMachine();1305 1306 if (RemoveIncompatibleFunctions && TM.getTargetTriple().isAMDGCN())1307 addPass(createAMDGPURemoveIncompatibleFunctionsPass(&TM));1308 1309 // There is no reason to run these.1310 disablePass(&StackMapLivenessID);1311 disablePass(&FuncletLayoutID);1312 disablePass(&PatchableFunctionID);1313 1314 addPass(createAMDGPUPrintfRuntimeBinding());1315 if (LowerCtorDtor)1316 addPass(createAMDGPUCtorDtorLoweringLegacyPass());1317 1318 if (TM.getTargetTriple().isAMDGCN() &&1319 isPassEnabled(EnableImageIntrinsicOptimizer))1320 addPass(createAMDGPUImageIntrinsicOptimizerPass(&TM));1321 1322 if (EnableUniformIntrinsicCombine)1323 addPass(createAMDGPUUniformIntrinsicCombineLegacyPass());1324 1325 // This can be disabled by passing ::Disable here or on the command line1326 // with --expand-variadics-override=disable.1327 addPass(createExpandVariadicsPass(ExpandVariadicsMode::Lowering));1328 1329 // Function calls are not supported, so make sure we inline everything.1330 addPass(createAMDGPUAlwaysInlinePass());1331 addPass(createAlwaysInlinerLegacyPass());1332 1333 // Handle uses of OpenCL image2d_t, image3d_t and sampler_t arguments.1334 if (TM.getTargetTriple().getArch() == Triple::r600)1335 addPass(createR600OpenCLImageTypeLoweringPass());1336 1337 // Make enqueued block runtime handles externally visible.1338 addPass(createAMDGPUExportKernelRuntimeHandlesLegacyPass());1339 1340 // Lower special LDS accesses.1341 if (EnableLowerExecSync)1342 addPass(createAMDGPULowerExecSyncLegacyPass());1343 1344 // Lower LDS accesses to global memory pass if address sanitizer is enabled.1345 if (EnableSwLowerLDS)1346 addPass(createAMDGPUSwLowerLDSLegacyPass(&TM));1347 1348 // Runs before PromoteAlloca so the latter can account for function uses1349 if (EnableLowerModuleLDS) {1350 addPass(createAMDGPULowerModuleLDSLegacyPass(&TM));1351 }1352 1353 // Run atomic optimizer before Atomic Expand1354 if ((TM.getTargetTriple().isAMDGCN()) &&1355 (TM.getOptLevel() >= CodeGenOptLevel::Less) &&1356 (AMDGPUAtomicOptimizerStrategy != ScanOptions::None)) {1357 addPass(createAMDGPUAtomicOptimizerPass(AMDGPUAtomicOptimizerStrategy));1358 }1359 1360 addPass(createAtomicExpandLegacyPass());1361 1362 if (TM.getOptLevel() > CodeGenOptLevel::None) {1363 addPass(createAMDGPUPromoteAlloca());1364 1365 if (isPassEnabled(EnableScalarIRPasses))1366 addStraightLineScalarOptimizationPasses();1367 1368 if (EnableAMDGPUAliasAnalysis) {1369 addPass(createAMDGPUAAWrapperPass());1370 addPass(createExternalAAWrapperPass([](Pass &P, Function &,1371 AAResults &AAR) {1372 if (auto *WrapperPass = P.getAnalysisIfAvailable<AMDGPUAAWrapperPass>())1373 AAR.addAAResult(WrapperPass->getResult());1374 }));1375 }1376 1377 if (TM.getTargetTriple().isAMDGCN()) {1378 // TODO: May want to move later or split into an early and late one.1379 addPass(createAMDGPUCodeGenPreparePass());1380 }1381 1382 // Try to hoist loop invariant parts of divisions AMDGPUCodeGenPrepare may1383 // have expanded.1384 if (TM.getOptLevel() > CodeGenOptLevel::Less)1385 addPass(createLICMPass());1386 }1387 1388 TargetPassConfig::addIRPasses();1389 1390 // EarlyCSE is not always strong enough to clean up what LSR produces. For1391 // example, GVN can combine1392 //1393 // %0 = add %a, %b1394 // %1 = add %b, %a1395 //1396 // and1397 //1398 // %0 = shl nsw %a, 21399 // %1 = shl %a, 21400 //1401 // but EarlyCSE can do neither of them.1402 if (isPassEnabled(EnableScalarIRPasses))1403 addEarlyCSEOrGVNPass();1404}1405 1406void AMDGPUPassConfig::addCodeGenPrepare() {1407 if (TM->getTargetTriple().isAMDGCN() &&1408 TM->getOptLevel() > CodeGenOptLevel::None)1409 addPass(createAMDGPUPreloadKernelArgumentsLegacyPass(TM));1410 1411 if (TM->getTargetTriple().isAMDGCN() && EnableLowerKernelArguments)1412 addPass(createAMDGPULowerKernelArgumentsPass());1413 1414 TargetPassConfig::addCodeGenPrepare();1415 1416 if (isPassEnabled(EnableLoadStoreVectorizer))1417 addPass(createLoadStoreVectorizerPass());1418 1419 if (TM->getTargetTriple().isAMDGCN()) {1420 // This lowering has been placed after codegenprepare to take advantage of1421 // address mode matching (which is why it isn't put with the LDS lowerings).1422 // It could be placed anywhere before uniformity annotations (an analysis1423 // that it changes by splitting up fat pointers into their components)1424 // but has been put before switch lowering and CFG flattening so that those1425 // passes can run on the more optimized control flow this pass creates in1426 // many cases.1427 addPass(createAMDGPULowerBufferFatPointersPass());1428 addPass(createAMDGPULowerIntrinsicsLegacyPass());1429 }1430 1431 // LowerSwitch pass may introduce unreachable blocks that can1432 // cause unexpected behavior for subsequent passes. Placing it1433 // here seems better that these blocks would get cleaned up by1434 // UnreachableBlockElim inserted next in the pass flow.1435 addPass(createLowerSwitchPass());1436}1437 1438bool AMDGPUPassConfig::addPreISel() {1439 if (TM->getOptLevel() > CodeGenOptLevel::None)1440 addPass(createFlattenCFGPass());1441 return false;1442}1443 1444bool AMDGPUPassConfig::addInstSelector() {1445 addPass(createAMDGPUISelDag(getAMDGPUTargetMachine(), getOptLevel()));1446 return false;1447}1448 1449bool AMDGPUPassConfig::addGCPasses() {1450 // Do nothing. GC is not supported.1451 return false;1452}1453 1454//===----------------------------------------------------------------------===//1455// GCN Legacy Pass Setup1456//===----------------------------------------------------------------------===//1457 1458bool GCNPassConfig::addPreISel() {1459 AMDGPUPassConfig::addPreISel();1460 1461 if (TM->getOptLevel() > CodeGenOptLevel::None)1462 addPass(createSinkingPass());1463 1464 if (TM->getOptLevel() > CodeGenOptLevel::None)1465 addPass(createAMDGPULateCodeGenPrepareLegacyPass());1466 1467 // Merge divergent exit nodes. StructurizeCFG won't recognize the multi-exit1468 // regions formed by them.1469 addPass(&AMDGPUUnifyDivergentExitNodesID);1470 addPass(createFixIrreduciblePass());1471 addPass(createUnifyLoopExitsPass());1472 addPass(createStructurizeCFGPass(false)); // true -> SkipUniformRegions1473 1474 addPass(createAMDGPUAnnotateUniformValuesLegacy());1475 addPass(createSIAnnotateControlFlowLegacyPass());1476 // TODO: Move this right after structurizeCFG to avoid extra divergence1477 // analysis. This depends on stopping SIAnnotateControlFlow from making1478 // control flow modifications.1479 addPass(createAMDGPURewriteUndefForPHILegacyPass());1480 1481 // SDAG requires LCSSA, GlobalISel does not. Disable LCSSA for -global-isel1482 // with -new-reg-bank-select and without any of the fallback options.1483 if (!getCGPassBuilderOption().EnableGlobalISelOption ||1484 !isGlobalISelAbortEnabled() || !NewRegBankSelect)1485 addPass(createLCSSAPass());1486 1487 if (TM->getOptLevel() > CodeGenOptLevel::Less)1488 addPass(&AMDGPUPerfHintAnalysisLegacyID);1489 1490 return false;1491}1492 1493void GCNPassConfig::addMachineSSAOptimization() {1494 TargetPassConfig::addMachineSSAOptimization();1495 1496 // We want to fold operands after PeepholeOptimizer has run (or as part of1497 // it), because it will eliminate extra copies making it easier to fold the1498 // real source operand. We want to eliminate dead instructions after, so that1499 // we see fewer uses of the copies. We then need to clean up the dead1500 // instructions leftover after the operands are folded as well.1501 //1502 // XXX - Can we get away without running DeadMachineInstructionElim again?1503 addPass(&SIFoldOperandsLegacyID);1504 if (EnableDPPCombine)1505 addPass(&GCNDPPCombineLegacyID);1506 addPass(&SILoadStoreOptimizerLegacyID);1507 if (isPassEnabled(EnableSDWAPeephole)) {1508 addPass(&SIPeepholeSDWALegacyID);1509 addPass(&EarlyMachineLICMID);1510 addPass(&MachineCSELegacyID);1511 addPass(&SIFoldOperandsLegacyID);1512 }1513 addPass(&DeadMachineInstructionElimID);1514 addPass(createSIShrinkInstructionsLegacyPass());1515}1516 1517bool GCNPassConfig::addILPOpts() {1518 if (EnableEarlyIfConversion)1519 addPass(&EarlyIfConverterLegacyID);1520 1521 TargetPassConfig::addILPOpts();1522 return false;1523}1524 1525bool GCNPassConfig::addInstSelector() {1526 AMDGPUPassConfig::addInstSelector();1527 addPass(&SIFixSGPRCopiesLegacyID);1528 addPass(createSILowerI1CopiesLegacyPass());1529 return false;1530}1531 1532bool GCNPassConfig::addIRTranslator() {1533 addPass(new IRTranslator(getOptLevel()));1534 return false;1535}1536 1537void GCNPassConfig::addPreLegalizeMachineIR() {1538 bool IsOptNone = getOptLevel() == CodeGenOptLevel::None;1539 addPass(createAMDGPUPreLegalizeCombiner(IsOptNone));1540 addPass(new Localizer());1541}1542 1543bool GCNPassConfig::addLegalizeMachineIR() {1544 addPass(new Legalizer());1545 return false;1546}1547 1548void GCNPassConfig::addPreRegBankSelect() {1549 bool IsOptNone = getOptLevel() == CodeGenOptLevel::None;1550 addPass(createAMDGPUPostLegalizeCombiner(IsOptNone));1551 addPass(createAMDGPUGlobalISelDivergenceLoweringPass());1552}1553 1554bool GCNPassConfig::addRegBankSelect() {1555 if (NewRegBankSelect) {1556 addPass(createAMDGPURegBankSelectPass());1557 addPass(createAMDGPURegBankLegalizePass());1558 } else {1559 addPass(new RegBankSelect());1560 }1561 return false;1562}1563 1564void GCNPassConfig::addPreGlobalInstructionSelect() {1565 bool IsOptNone = getOptLevel() == CodeGenOptLevel::None;1566 addPass(createAMDGPURegBankCombiner(IsOptNone));1567}1568 1569bool GCNPassConfig::addGlobalInstructionSelect() {1570 addPass(new InstructionSelect(getOptLevel()));1571 return false;1572}1573 1574void GCNPassConfig::addFastRegAlloc() {1575 // FIXME: We have to disable the verifier here because of PHIElimination +1576 // TwoAddressInstructions disabling it.1577 1578 // This must be run immediately after phi elimination and before1579 // TwoAddressInstructions, otherwise the processing of the tied operand of1580 // SI_ELSE will introduce a copy of the tied operand source after the else.1581 insertPass(&PHIEliminationID, &SILowerControlFlowLegacyID);1582 1583 insertPass(&TwoAddressInstructionPassID, &SIWholeQuadModeID);1584 1585 TargetPassConfig::addFastRegAlloc();1586}1587 1588void GCNPassConfig::addPreRegAlloc() {1589 if (getOptLevel() != CodeGenOptLevel::None)1590 addPass(&AMDGPUPrepareAGPRAllocLegacyID);1591}1592 1593void GCNPassConfig::addOptimizedRegAlloc() {1594 if (EnableDCEInRA)1595 insertPass(&DetectDeadLanesID, &DeadMachineInstructionElimID);1596 1597 // FIXME: when an instruction has a Killed operand, and the instruction is1598 // inside a bundle, seems only the BUNDLE instruction appears as the Kills of1599 // the register in LiveVariables, this would trigger a failure in verifier,1600 // we should fix it and enable the verifier.1601 if (OptVGPRLiveRange)1602 insertPass(&LiveVariablesID, &SIOptimizeVGPRLiveRangeLegacyID);1603 1604 // This must be run immediately after phi elimination and before1605 // TwoAddressInstructions, otherwise the processing of the tied operand of1606 // SI_ELSE will introduce a copy of the tied operand source after the else.1607 insertPass(&PHIEliminationID, &SILowerControlFlowLegacyID);1608 1609 if (EnableRewritePartialRegUses)1610 insertPass(&RenameIndependentSubregsID, &GCNRewritePartialRegUsesID);1611 1612 if (isPassEnabled(EnablePreRAOptimizations))1613 insertPass(&MachineSchedulerID, &GCNPreRAOptimizationsID);1614 1615 // Allow the scheduler to run before SIWholeQuadMode inserts exec manipulation1616 // instructions that cause scheduling barriers.1617 insertPass(&MachineSchedulerID, &SIWholeQuadModeID);1618 1619 if (OptExecMaskPreRA)1620 insertPass(&MachineSchedulerID, &SIOptimizeExecMaskingPreRAID);1621 1622 // This is not an essential optimization and it has a noticeable impact on1623 // compilation time, so we only enable it from O2.1624 if (TM->getOptLevel() > CodeGenOptLevel::Less)1625 insertPass(&MachineSchedulerID, &SIFormMemoryClausesID);1626 1627 TargetPassConfig::addOptimizedRegAlloc();1628}1629 1630bool GCNPassConfig::addPreRewrite() {1631 if (EnableRegReassign)1632 addPass(&GCNNSAReassignID);1633 1634 addPass(&AMDGPURewriteAGPRCopyMFMALegacyID);1635 return true;1636}1637 1638FunctionPass *GCNPassConfig::createSGPRAllocPass(bool Optimized) {1639 // Initialize the global default.1640 llvm::call_once(InitializeDefaultSGPRRegisterAllocatorFlag,1641 initializeDefaultSGPRRegisterAllocatorOnce);1642 1643 RegisterRegAlloc::FunctionPassCtor Ctor = SGPRRegisterRegAlloc::getDefault();1644 if (Ctor != useDefaultRegisterAllocator)1645 return Ctor();1646 1647 if (Optimized)1648 return createGreedyRegisterAllocator(onlyAllocateSGPRs);1649 1650 return createFastRegisterAllocator(onlyAllocateSGPRs, false);1651}1652 1653FunctionPass *GCNPassConfig::createVGPRAllocPass(bool Optimized) {1654 // Initialize the global default.1655 llvm::call_once(InitializeDefaultVGPRRegisterAllocatorFlag,1656 initializeDefaultVGPRRegisterAllocatorOnce);1657 1658 RegisterRegAlloc::FunctionPassCtor Ctor = VGPRRegisterRegAlloc::getDefault();1659 if (Ctor != useDefaultRegisterAllocator)1660 return Ctor();1661 1662 if (Optimized)1663 return createGreedyVGPRRegisterAllocator();1664 1665 return createFastVGPRRegisterAllocator();1666}1667 1668FunctionPass *GCNPassConfig::createWWMRegAllocPass(bool Optimized) {1669 // Initialize the global default.1670 llvm::call_once(InitializeDefaultWWMRegisterAllocatorFlag,1671 initializeDefaultWWMRegisterAllocatorOnce);1672 1673 RegisterRegAlloc::FunctionPassCtor Ctor = WWMRegisterRegAlloc::getDefault();1674 if (Ctor != useDefaultRegisterAllocator)1675 return Ctor();1676 1677 if (Optimized)1678 return createGreedyWWMRegisterAllocator();1679 1680 return createFastWWMRegisterAllocator();1681}1682 1683FunctionPass *GCNPassConfig::createRegAllocPass(bool Optimized) {1684 llvm_unreachable("should not be used");1685}1686 1687static const char RegAllocOptNotSupportedMessage[] =1688 "-regalloc not supported with amdgcn. Use -sgpr-regalloc, -wwm-regalloc, "1689 "and -vgpr-regalloc";1690 1691bool GCNPassConfig::addRegAssignAndRewriteFast() {1692 if (!usingDefaultRegAlloc())1693 reportFatalUsageError(RegAllocOptNotSupportedMessage);1694 1695 addPass(&GCNPreRALongBranchRegID);1696 1697 addPass(createSGPRAllocPass(false));1698 1699 // Equivalent of PEI for SGPRs.1700 addPass(&SILowerSGPRSpillsLegacyID);1701 1702 // To Allocate wwm registers used in whole quad mode operations (for shaders).1703 addPass(&SIPreAllocateWWMRegsLegacyID);1704 1705 // For allocating other wwm register operands.1706 addPass(createWWMRegAllocPass(false));1707 1708 addPass(&SILowerWWMCopiesLegacyID);1709 addPass(&AMDGPUReserveWWMRegsLegacyID);1710 1711 // For allocating per-thread VGPRs.1712 addPass(createVGPRAllocPass(false));1713 1714 return true;1715}1716 1717bool GCNPassConfig::addRegAssignAndRewriteOptimized() {1718 if (!usingDefaultRegAlloc())1719 reportFatalUsageError(RegAllocOptNotSupportedMessage);1720 1721 addPass(&GCNPreRALongBranchRegID);1722 1723 addPass(createSGPRAllocPass(true));1724 1725 // Commit allocated register changes. This is mostly necessary because too1726 // many things rely on the use lists of the physical registers, such as the1727 // verifier. This is only necessary with allocators which use LiveIntervals,1728 // since FastRegAlloc does the replacements itself.1729 addPass(createVirtRegRewriter(false));1730 1731 // At this point, the sgpr-regalloc has been done and it is good to have the1732 // stack slot coloring to try to optimize the SGPR spill stack indices before1733 // attempting the custom SGPR spill lowering.1734 addPass(&StackSlotColoringID);1735 1736 // Equivalent of PEI for SGPRs.1737 addPass(&SILowerSGPRSpillsLegacyID);1738 1739 // To Allocate wwm registers used in whole quad mode operations (for shaders).1740 addPass(&SIPreAllocateWWMRegsLegacyID);1741 1742 // For allocating other whole wave mode registers.1743 addPass(createWWMRegAllocPass(true));1744 addPass(&SILowerWWMCopiesLegacyID);1745 addPass(createVirtRegRewriter(false));1746 addPass(&AMDGPUReserveWWMRegsLegacyID);1747 1748 // For allocating per-thread VGPRs.1749 addPass(createVGPRAllocPass(true));1750 1751 addPreRewrite();1752 addPass(&VirtRegRewriterID);1753 1754 addPass(&AMDGPUMarkLastScratchLoadID);1755 1756 return true;1757}1758 1759void GCNPassConfig::addPostRegAlloc() {1760 addPass(&SIFixVGPRCopiesID);1761 if (getOptLevel() > CodeGenOptLevel::None)1762 addPass(&SIOptimizeExecMaskingLegacyID);1763 TargetPassConfig::addPostRegAlloc();1764}1765 1766void GCNPassConfig::addPreSched2() {1767 if (TM->getOptLevel() > CodeGenOptLevel::None)1768 addPass(createSIShrinkInstructionsLegacyPass());1769 addPass(&SIPostRABundlerLegacyID);1770}1771 1772void GCNPassConfig::addPreEmitPass() {1773 if (isPassEnabled(EnableVOPD, CodeGenOptLevel::Less))1774 addPass(&GCNCreateVOPDID);1775 addPass(createSIMemoryLegalizerPass());1776 addPass(createSIInsertWaitcntsPass());1777 1778 addPass(createSIModeRegisterPass());1779 1780 if (getOptLevel() > CodeGenOptLevel::None)1781 addPass(&SIInsertHardClausesID);1782 1783 addPass(&SILateBranchLoweringPassID);1784 if (isPassEnabled(EnableSetWavePriority, CodeGenOptLevel::Less))1785 addPass(createAMDGPUSetWavePriorityPass());1786 if (getOptLevel() > CodeGenOptLevel::None)1787 addPass(&SIPreEmitPeepholeID);1788 // The hazard recognizer that runs as part of the post-ra scheduler does not1789 // guarantee to be able handle all hazards correctly. This is because if there1790 // are multiple scheduling regions in a basic block, the regions are scheduled1791 // bottom up, so when we begin to schedule a region we don't know what1792 // instructions were emitted directly before it.1793 //1794 // Here we add a stand-alone hazard recognizer pass which can handle all1795 // cases.1796 addPass(&PostRAHazardRecognizerID);1797 1798 addPass(&AMDGPUWaitSGPRHazardsLegacyID);1799 1800 addPass(&AMDGPULowerVGPREncodingLegacyID);1801 1802 if (isPassEnabled(EnableInsertDelayAlu, CodeGenOptLevel::Less))1803 addPass(&AMDGPUInsertDelayAluID);1804 1805 addPass(&BranchRelaxationPassID);1806}1807 1808void GCNPassConfig::addPostBBSections() {1809 // We run this later to avoid passes like livedebugvalues and BBSections1810 // having to deal with the apparent multi-entry functions we may generate.1811 addPass(createAMDGPUPreloadKernArgPrologLegacyPass());1812}1813 1814TargetPassConfig *GCNTargetMachine::createPassConfig(PassManagerBase &PM) {1815 return new GCNPassConfig(*this, PM);1816}1817 1818void GCNTargetMachine::registerMachineRegisterInfoCallback(1819 MachineFunction &MF) const {1820 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();1821 MF.getRegInfo().addDelegate(MFI);1822}1823 1824MachineFunctionInfo *GCNTargetMachine::createMachineFunctionInfo(1825 BumpPtrAllocator &Allocator, const Function &F,1826 const TargetSubtargetInfo *STI) const {1827 return SIMachineFunctionInfo::create<SIMachineFunctionInfo>(1828 Allocator, F, static_cast<const GCNSubtarget *>(STI));1829}1830 1831yaml::MachineFunctionInfo *GCNTargetMachine::createDefaultFuncInfoYAML() const {1832 return new yaml::SIMachineFunctionInfo();1833}1834 1835yaml::MachineFunctionInfo *1836GCNTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {1837 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();1838 return new yaml::SIMachineFunctionInfo(1839 *MFI, *MF.getSubtarget<GCNSubtarget>().getRegisterInfo(), MF);1840}1841 1842bool GCNTargetMachine::parseMachineFunctionInfo(1843 const yaml::MachineFunctionInfo &MFI_, PerFunctionMIParsingState &PFS,1844 SMDiagnostic &Error, SMRange &SourceRange) const {1845 const yaml::SIMachineFunctionInfo &YamlMFI =1846 static_cast<const yaml::SIMachineFunctionInfo &>(MFI_);1847 MachineFunction &MF = PFS.MF;1848 SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();1849 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();1850 1851 if (MFI->initializeBaseYamlFields(YamlMFI, MF, PFS, Error, SourceRange))1852 return true;1853 1854 if (MFI->Occupancy == 0) {1855 // Fixup the subtarget dependent default value.1856 MFI->Occupancy = ST.getOccupancyWithWorkGroupSizes(MF).second;1857 }1858 1859 auto parseRegister = [&](const yaml::StringValue &RegName, Register &RegVal) {1860 Register TempReg;1861 if (parseNamedRegisterReference(PFS, TempReg, RegName.Value, Error)) {1862 SourceRange = RegName.SourceRange;1863 return true;1864 }1865 RegVal = TempReg;1866 1867 return false;1868 };1869 1870 auto parseOptionalRegister = [&](const yaml::StringValue &RegName,1871 Register &RegVal) {1872 return !RegName.Value.empty() && parseRegister(RegName, RegVal);1873 };1874 1875 if (parseOptionalRegister(YamlMFI.VGPRForAGPRCopy, MFI->VGPRForAGPRCopy))1876 return true;1877 1878 if (parseOptionalRegister(YamlMFI.SGPRForEXECCopy, MFI->SGPRForEXECCopy))1879 return true;1880 1881 if (parseOptionalRegister(YamlMFI.LongBranchReservedReg,1882 MFI->LongBranchReservedReg))1883 return true;1884 1885 auto diagnoseRegisterClass = [&](const yaml::StringValue &RegName) {1886 // Create a diagnostic for a the register string literal.1887 const MemoryBuffer &Buffer =1888 *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());1889 Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1,1890 RegName.Value.size(), SourceMgr::DK_Error,1891 "incorrect register class for field", RegName.Value,1892 {}, {});1893 SourceRange = RegName.SourceRange;1894 return true;1895 };1896 1897 if (parseRegister(YamlMFI.ScratchRSrcReg, MFI->ScratchRSrcReg) ||1898 parseRegister(YamlMFI.FrameOffsetReg, MFI->FrameOffsetReg) ||1899 parseRegister(YamlMFI.StackPtrOffsetReg, MFI->StackPtrOffsetReg))1900 return true;1901 1902 if (MFI->ScratchRSrcReg != AMDGPU::PRIVATE_RSRC_REG &&1903 !AMDGPU::SGPR_128RegClass.contains(MFI->ScratchRSrcReg)) {1904 return diagnoseRegisterClass(YamlMFI.ScratchRSrcReg);1905 }1906 1907 if (MFI->FrameOffsetReg != AMDGPU::FP_REG &&1908 !AMDGPU::SGPR_32RegClass.contains(MFI->FrameOffsetReg)) {1909 return diagnoseRegisterClass(YamlMFI.FrameOffsetReg);1910 }1911 1912 if (MFI->StackPtrOffsetReg != AMDGPU::SP_REG &&1913 !AMDGPU::SGPR_32RegClass.contains(MFI->StackPtrOffsetReg)) {1914 return diagnoseRegisterClass(YamlMFI.StackPtrOffsetReg);1915 }1916 1917 for (const auto &YamlReg : YamlMFI.WWMReservedRegs) {1918 Register ParsedReg;1919 if (parseRegister(YamlReg, ParsedReg))1920 return true;1921 1922 MFI->reserveWWMRegister(ParsedReg);1923 }1924 1925 for (const auto &[_, Info] : PFS.VRegInfosNamed) {1926 MFI->setFlag(Info->VReg, Info->Flags);1927 }1928 for (const auto &[_, Info] : PFS.VRegInfos) {1929 MFI->setFlag(Info->VReg, Info->Flags);1930 }1931 1932 for (const auto &YamlRegStr : YamlMFI.SpillPhysVGPRS) {1933 Register ParsedReg;1934 if (parseRegister(YamlRegStr, ParsedReg))1935 return true;1936 MFI->SpillPhysVGPRs.push_back(ParsedReg);1937 }1938 1939 auto parseAndCheckArgument = [&](const std::optional<yaml::SIArgument> &A,1940 const TargetRegisterClass &RC,1941 ArgDescriptor &Arg, unsigned UserSGPRs,1942 unsigned SystemSGPRs) {1943 // Skip parsing if it's not present.1944 if (!A)1945 return false;1946 1947 if (A->IsRegister) {1948 Register Reg;1949 if (parseNamedRegisterReference(PFS, Reg, A->RegisterName.Value, Error)) {1950 SourceRange = A->RegisterName.SourceRange;1951 return true;1952 }1953 if (!RC.contains(Reg))1954 return diagnoseRegisterClass(A->RegisterName);1955 Arg = ArgDescriptor::createRegister(Reg);1956 } else1957 Arg = ArgDescriptor::createStack(A->StackOffset);1958 // Check and apply the optional mask.1959 if (A->Mask)1960 Arg = ArgDescriptor::createArg(Arg, *A->Mask);1961 1962 MFI->NumUserSGPRs += UserSGPRs;1963 MFI->NumSystemSGPRs += SystemSGPRs;1964 return false;1965 };1966 1967 if (YamlMFI.ArgInfo &&1968 (parseAndCheckArgument(YamlMFI.ArgInfo->PrivateSegmentBuffer,1969 AMDGPU::SGPR_128RegClass,1970 MFI->ArgInfo.PrivateSegmentBuffer, 4, 0) ||1971 parseAndCheckArgument(YamlMFI.ArgInfo->DispatchPtr,1972 AMDGPU::SReg_64RegClass, MFI->ArgInfo.DispatchPtr,1973 2, 0) ||1974 parseAndCheckArgument(YamlMFI.ArgInfo->QueuePtr, AMDGPU::SReg_64RegClass,1975 MFI->ArgInfo.QueuePtr, 2, 0) ||1976 parseAndCheckArgument(YamlMFI.ArgInfo->KernargSegmentPtr,1977 AMDGPU::SReg_64RegClass,1978 MFI->ArgInfo.KernargSegmentPtr, 2, 0) ||1979 parseAndCheckArgument(YamlMFI.ArgInfo->DispatchID,1980 AMDGPU::SReg_64RegClass, MFI->ArgInfo.DispatchID,1981 2, 0) ||1982 parseAndCheckArgument(YamlMFI.ArgInfo->FlatScratchInit,1983 AMDGPU::SReg_64RegClass,1984 MFI->ArgInfo.FlatScratchInit, 2, 0) ||1985 parseAndCheckArgument(YamlMFI.ArgInfo->PrivateSegmentSize,1986 AMDGPU::SGPR_32RegClass,1987 MFI->ArgInfo.PrivateSegmentSize, 0, 0) ||1988 parseAndCheckArgument(YamlMFI.ArgInfo->LDSKernelId,1989 AMDGPU::SGPR_32RegClass,1990 MFI->ArgInfo.LDSKernelId, 0, 1) ||1991 parseAndCheckArgument(YamlMFI.ArgInfo->WorkGroupIDX,1992 AMDGPU::SGPR_32RegClass, MFI->ArgInfo.WorkGroupIDX,1993 0, 1) ||1994 parseAndCheckArgument(YamlMFI.ArgInfo->WorkGroupIDY,1995 AMDGPU::SGPR_32RegClass, MFI->ArgInfo.WorkGroupIDY,1996 0, 1) ||1997 parseAndCheckArgument(YamlMFI.ArgInfo->WorkGroupIDZ,1998 AMDGPU::SGPR_32RegClass, MFI->ArgInfo.WorkGroupIDZ,1999 0, 1) ||2000 parseAndCheckArgument(YamlMFI.ArgInfo->WorkGroupInfo,2001 AMDGPU::SGPR_32RegClass,2002 MFI->ArgInfo.WorkGroupInfo, 0, 1) ||2003 parseAndCheckArgument(YamlMFI.ArgInfo->PrivateSegmentWaveByteOffset,2004 AMDGPU::SGPR_32RegClass,2005 MFI->ArgInfo.PrivateSegmentWaveByteOffset, 0, 1) ||2006 parseAndCheckArgument(YamlMFI.ArgInfo->ImplicitArgPtr,2007 AMDGPU::SReg_64RegClass,2008 MFI->ArgInfo.ImplicitArgPtr, 0, 0) ||2009 parseAndCheckArgument(YamlMFI.ArgInfo->ImplicitBufferPtr,2010 AMDGPU::SReg_64RegClass,2011 MFI->ArgInfo.ImplicitBufferPtr, 2, 0) ||2012 parseAndCheckArgument(YamlMFI.ArgInfo->WorkItemIDX,2013 AMDGPU::VGPR_32RegClass,2014 MFI->ArgInfo.WorkItemIDX, 0, 0) ||2015 parseAndCheckArgument(YamlMFI.ArgInfo->WorkItemIDY,2016 AMDGPU::VGPR_32RegClass,2017 MFI->ArgInfo.WorkItemIDY, 0, 0) ||2018 parseAndCheckArgument(YamlMFI.ArgInfo->WorkItemIDZ,2019 AMDGPU::VGPR_32RegClass,2020 MFI->ArgInfo.WorkItemIDZ, 0, 0)))2021 return true;2022 2023 // Parse FirstKernArgPreloadReg separately, since it's a Register,2024 // not ArgDescriptor.2025 if (YamlMFI.ArgInfo && YamlMFI.ArgInfo->FirstKernArgPreloadReg) {2026 const yaml::SIArgument &A = *YamlMFI.ArgInfo->FirstKernArgPreloadReg;2027 2028 if (!A.IsRegister) {2029 // For stack arguments, we don't have RegisterName.SourceRange,2030 // but we should have some location info from the YAML parser2031 const MemoryBuffer &Buffer =2032 *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());2033 // Create a minimal valid source range2034 SMLoc Loc = SMLoc::getFromPointer(Buffer.getBufferStart());2035 SMRange Range(Loc, Loc);2036 2037 Error = SMDiagnostic(2038 *PFS.SM, Loc, Buffer.getBufferIdentifier(), 1, 0, SourceMgr::DK_Error,2039 "firstKernArgPreloadReg must be a register, not a stack location", "",2040 {}, {});2041 2042 SourceRange = Range;2043 return true;2044 }2045 2046 Register Reg;2047 if (parseNamedRegisterReference(PFS, Reg, A.RegisterName.Value, Error)) {2048 SourceRange = A.RegisterName.SourceRange;2049 return true;2050 }2051 2052 if (!AMDGPU::SGPR_32RegClass.contains(Reg))2053 return diagnoseRegisterClass(A.RegisterName);2054 2055 MFI->ArgInfo.FirstKernArgPreloadReg = Reg;2056 MFI->NumUserSGPRs += YamlMFI.NumKernargPreloadSGPRs;2057 }2058 2059 if (ST.hasIEEEMode())2060 MFI->Mode.IEEE = YamlMFI.Mode.IEEE;2061 if (ST.hasDX10ClampMode())2062 MFI->Mode.DX10Clamp = YamlMFI.Mode.DX10Clamp;2063 2064 // FIXME: Move proper support for denormal-fp-math into base MachineFunction2065 MFI->Mode.FP32Denormals.Input = YamlMFI.Mode.FP32InputDenormals2066 ? DenormalMode::IEEE2067 : DenormalMode::PreserveSign;2068 MFI->Mode.FP32Denormals.Output = YamlMFI.Mode.FP32OutputDenormals2069 ? DenormalMode::IEEE2070 : DenormalMode::PreserveSign;2071 2072 MFI->Mode.FP64FP16Denormals.Input = YamlMFI.Mode.FP64FP16InputDenormals2073 ? DenormalMode::IEEE2074 : DenormalMode::PreserveSign;2075 MFI->Mode.FP64FP16Denormals.Output = YamlMFI.Mode.FP64FP16OutputDenormals2076 ? DenormalMode::IEEE2077 : DenormalMode::PreserveSign;2078 2079 if (YamlMFI.HasInitWholeWave)2080 MFI->setInitWholeWave();2081 2082 return false;2083}2084 2085//===----------------------------------------------------------------------===//2086// AMDGPU CodeGen Pass Builder interface.2087//===----------------------------------------------------------------------===//2088 2089AMDGPUCodeGenPassBuilder::AMDGPUCodeGenPassBuilder(2090 GCNTargetMachine &TM, const CGPassBuilderOption &Opts,2091 PassInstrumentationCallbacks *PIC)2092 : CodeGenPassBuilder(TM, Opts, PIC) {2093 Opt.MISchedPostRA = true;2094 Opt.RequiresCodeGenSCCOrder = true;2095 // Exceptions and StackMaps are not supported, so these passes will never do2096 // anything.2097 // Garbage collection is not supported.2098 disablePass<StackMapLivenessPass, FuncletLayoutPass,2099 ShadowStackGCLoweringPass>();2100}2101 2102void AMDGPUCodeGenPassBuilder::addIRPasses(AddIRPass &addPass) const {2103 if (RemoveIncompatibleFunctions && TM.getTargetTriple().isAMDGCN())2104 addPass(AMDGPURemoveIncompatibleFunctionsPass(TM));2105 2106 addPass(AMDGPUPrintfRuntimeBindingPass());2107 if (LowerCtorDtor)2108 addPass(AMDGPUCtorDtorLoweringPass());2109 2110 if (isPassEnabled(EnableImageIntrinsicOptimizer))2111 addPass(AMDGPUImageIntrinsicOptimizerPass(TM));2112 2113 if (EnableUniformIntrinsicCombine)2114 addPass(AMDGPUUniformIntrinsicCombinePass());2115 // This can be disabled by passing ::Disable here or on the command line2116 // with --expand-variadics-override=disable.2117 addPass(ExpandVariadicsPass(ExpandVariadicsMode::Lowering));2118 2119 addPass(AMDGPUAlwaysInlinePass());2120 addPass(AlwaysInlinerPass());2121 2122 addPass(AMDGPUExportKernelRuntimeHandlesPass());2123 2124 if (EnableLowerExecSync)2125 addPass(AMDGPULowerExecSyncPass());2126 2127 if (EnableSwLowerLDS)2128 addPass(AMDGPUSwLowerLDSPass(TM));2129 2130 // Runs before PromoteAlloca so the latter can account for function uses2131 if (EnableLowerModuleLDS)2132 addPass(AMDGPULowerModuleLDSPass(TM));2133 2134 // Run atomic optimizer before Atomic Expand2135 if (TM.getOptLevel() >= CodeGenOptLevel::Less &&2136 (AMDGPUAtomicOptimizerStrategy != ScanOptions::None))2137 addPass(AMDGPUAtomicOptimizerPass(TM, AMDGPUAtomicOptimizerStrategy));2138 2139 addPass(AtomicExpandPass(TM));2140 2141 if (TM.getOptLevel() > CodeGenOptLevel::None) {2142 addPass(AMDGPUPromoteAllocaPass(TM));2143 if (isPassEnabled(EnableScalarIRPasses))2144 addStraightLineScalarOptimizationPasses(addPass);2145 2146 // TODO: Handle EnableAMDGPUAliasAnalysis2147 2148 // TODO: May want to move later or split into an early and late one.2149 addPass(AMDGPUCodeGenPreparePass(TM));2150 2151 // Try to hoist loop invariant parts of divisions AMDGPUCodeGenPrepare may2152 // have expanded.2153 if (TM.getOptLevel() > CodeGenOptLevel::Less) {2154 addPass(createFunctionToLoopPassAdaptor(LICMPass(LICMOptions()),2155 /*UseMemorySSA=*/true));2156 }2157 }2158 2159 Base::addIRPasses(addPass);2160 2161 // EarlyCSE is not always strong enough to clean up what LSR produces. For2162 // example, GVN can combine2163 //2164 // %0 = add %a, %b2165 // %1 = add %b, %a2166 //2167 // and2168 //2169 // %0 = shl nsw %a, 22170 // %1 = shl %a, 22171 //2172 // but EarlyCSE can do neither of them.2173 if (isPassEnabled(EnableScalarIRPasses))2174 addEarlyCSEOrGVNPass(addPass);2175}2176 2177void AMDGPUCodeGenPassBuilder::addCodeGenPrepare(AddIRPass &addPass) const {2178 if (TM.getOptLevel() > CodeGenOptLevel::None)2179 addPass(AMDGPUPreloadKernelArgumentsPass(TM));2180 2181 if (EnableLowerKernelArguments)2182 addPass(AMDGPULowerKernelArgumentsPass(TM));2183 2184 Base::addCodeGenPrepare(addPass);2185 2186 if (isPassEnabled(EnableLoadStoreVectorizer))2187 addPass(LoadStoreVectorizerPass());2188 2189 // This lowering has been placed after codegenprepare to take advantage of2190 // address mode matching (which is why it isn't put with the LDS lowerings).2191 // It could be placed anywhere before uniformity annotations (an analysis2192 // that it changes by splitting up fat pointers into their components)2193 // but has been put before switch lowering and CFG flattening so that those2194 // passes can run on the more optimized control flow this pass creates in2195 // many cases.2196 addPass(AMDGPULowerBufferFatPointersPass(TM));2197 addPass.requireCGSCCOrder();2198 2199 addPass(AMDGPULowerIntrinsicsPass(TM));2200 2201 // LowerSwitch pass may introduce unreachable blocks that can cause unexpected2202 // behavior for subsequent passes. Placing it here seems better that these2203 // blocks would get cleaned up by UnreachableBlockElim inserted next in the2204 // pass flow.2205 addPass(LowerSwitchPass());2206}2207 2208void AMDGPUCodeGenPassBuilder::addPreISel(AddIRPass &addPass) const {2209 2210 if (TM.getOptLevel() > CodeGenOptLevel::None) {2211 addPass(FlattenCFGPass());2212 addPass(SinkingPass());2213 addPass(AMDGPULateCodeGenPreparePass(TM));2214 }2215 2216 // Merge divergent exit nodes. StructurizeCFG won't recognize the multi-exit2217 // regions formed by them.2218 2219 addPass(AMDGPUUnifyDivergentExitNodesPass());2220 addPass(FixIrreduciblePass());2221 addPass(UnifyLoopExitsPass());2222 addPass(StructurizeCFGPass(/*SkipUniformRegions=*/false));2223 2224 addPass(AMDGPUAnnotateUniformValuesPass());2225 2226 addPass(SIAnnotateControlFlowPass(TM));2227 2228 // TODO: Move this right after structurizeCFG to avoid extra divergence2229 // analysis. This depends on stopping SIAnnotateControlFlow from making2230 // control flow modifications.2231 addPass(AMDGPURewriteUndefForPHIPass());2232 2233 if (!getCGPassBuilderOption().EnableGlobalISelOption ||2234 !isGlobalISelAbortEnabled() || !NewRegBankSelect)2235 addPass(LCSSAPass());2236 2237 if (TM.getOptLevel() > CodeGenOptLevel::Less)2238 addPass(AMDGPUPerfHintAnalysisPass(TM));2239 2240 // FIXME: Why isn't this queried as required from AMDGPUISelDAGToDAG, and why2241 // isn't this in addInstSelector?2242 addPass(RequireAnalysisPass<UniformityInfoAnalysis, Function>(),2243 /*Force=*/true);2244}2245 2246void AMDGPUCodeGenPassBuilder::addILPOpts(AddMachinePass &addPass) const {2247 if (EnableEarlyIfConversion)2248 addPass(EarlyIfConverterPass());2249 2250 Base::addILPOpts(addPass);2251}2252 2253void AMDGPUCodeGenPassBuilder::addAsmPrinter(AddMachinePass &addPass,2254 CreateMCStreamer) const {2255 // TODO: Add AsmPrinter.2256}2257 2258Error AMDGPUCodeGenPassBuilder::addInstSelector(AddMachinePass &addPass) const {2259 addPass(AMDGPUISelDAGToDAGPass(TM));2260 addPass(SIFixSGPRCopiesPass());2261 addPass(SILowerI1CopiesPass());2262 return Error::success();2263}2264 2265void AMDGPUCodeGenPassBuilder::addPreRewrite(AddMachinePass &addPass) const {2266 if (EnableRegReassign) {2267 addPass(GCNNSAReassignPass());2268 }2269}2270 2271void AMDGPUCodeGenPassBuilder::addMachineSSAOptimization(2272 AddMachinePass &addPass) const {2273 Base::addMachineSSAOptimization(addPass);2274 2275 addPass(SIFoldOperandsPass());2276 if (EnableDPPCombine) {2277 addPass(GCNDPPCombinePass());2278 }2279 addPass(SILoadStoreOptimizerPass());2280 if (isPassEnabled(EnableSDWAPeephole)) {2281 addPass(SIPeepholeSDWAPass());2282 addPass(EarlyMachineLICMPass());2283 addPass(MachineCSEPass());2284 addPass(SIFoldOperandsPass());2285 }2286 addPass(DeadMachineInstructionElimPass());2287 addPass(SIShrinkInstructionsPass());2288}2289 2290void AMDGPUCodeGenPassBuilder::addOptimizedRegAlloc(2291 AddMachinePass &addPass) const {2292 if (EnableDCEInRA)2293 insertPass<DetectDeadLanesPass>(DeadMachineInstructionElimPass());2294 2295 // FIXME: when an instruction has a Killed operand, and the instruction is2296 // inside a bundle, seems only the BUNDLE instruction appears as the Kills of2297 // the register in LiveVariables, this would trigger a failure in verifier,2298 // we should fix it and enable the verifier.2299 if (OptVGPRLiveRange)2300 insertPass<RequireAnalysisPass<LiveVariablesAnalysis, MachineFunction>>(2301 SIOptimizeVGPRLiveRangePass());2302 2303 // This must be run immediately after phi elimination and before2304 // TwoAddressInstructions, otherwise the processing of the tied operand of2305 // SI_ELSE will introduce a copy of the tied operand source after the else.2306 insertPass<PHIEliminationPass>(SILowerControlFlowPass());2307 2308 if (EnableRewritePartialRegUses)2309 insertPass<RenameIndependentSubregsPass>(GCNRewritePartialRegUsesPass());2310 2311 if (isPassEnabled(EnablePreRAOptimizations))2312 insertPass<MachineSchedulerPass>(GCNPreRAOptimizationsPass());2313 2314 // Allow the scheduler to run before SIWholeQuadMode inserts exec manipulation2315 // instructions that cause scheduling barriers.2316 insertPass<MachineSchedulerPass>(SIWholeQuadModePass());2317 2318 if (OptExecMaskPreRA)2319 insertPass<MachineSchedulerPass>(SIOptimizeExecMaskingPreRAPass());2320 2321 // This is not an essential optimization and it has a noticeable impact on2322 // compilation time, so we only enable it from O2.2323 if (TM.getOptLevel() > CodeGenOptLevel::Less)2324 insertPass<MachineSchedulerPass>(SIFormMemoryClausesPass());2325 2326 Base::addOptimizedRegAlloc(addPass);2327}2328 2329void AMDGPUCodeGenPassBuilder::addPreRegAlloc(AddMachinePass &addPass) const {2330 if (getOptLevel() != CodeGenOptLevel::None)2331 addPass(AMDGPUPrepareAGPRAllocPass());2332}2333 2334Error AMDGPUCodeGenPassBuilder::addRegAssignmentOptimized(2335 AddMachinePass &addPass) const {2336 // TODO: Check --regalloc-npm option2337 2338 addPass(GCNPreRALongBranchRegPass());2339 2340 addPass(RAGreedyPass({onlyAllocateSGPRs, "sgpr"}));2341 2342 // Commit allocated register changes. This is mostly necessary because too2343 // many things rely on the use lists of the physical registers, such as the2344 // verifier. This is only necessary with allocators which use LiveIntervals,2345 // since FastRegAlloc does the replacements itself.2346 addPass(VirtRegRewriterPass(false));2347 2348 // At this point, the sgpr-regalloc has been done and it is good to have the2349 // stack slot coloring to try to optimize the SGPR spill stack indices before2350 // attempting the custom SGPR spill lowering.2351 addPass(StackSlotColoringPass());2352 2353 // Equivalent of PEI for SGPRs.2354 addPass(SILowerSGPRSpillsPass());2355 2356 // To Allocate wwm registers used in whole quad mode operations (for shaders).2357 addPass(SIPreAllocateWWMRegsPass());2358 2359 // For allocating other wwm register operands.2360 addPass(RAGreedyPass({onlyAllocateWWMRegs, "wwm"}));2361 addPass(SILowerWWMCopiesPass());2362 addPass(VirtRegRewriterPass(false));2363 addPass(AMDGPUReserveWWMRegsPass());2364 2365 // For allocating per-thread VGPRs.2366 addPass(RAGreedyPass({onlyAllocateVGPRs, "vgpr"}));2367 2368 2369 addPreRewrite(addPass);2370 addPass(VirtRegRewriterPass(true));2371 2372 addPass(AMDGPUMarkLastScratchLoadPass());2373 return Error::success();2374}2375 2376void AMDGPUCodeGenPassBuilder::addPostRegAlloc(AddMachinePass &addPass) const {2377 addPass(SIFixVGPRCopiesPass());2378 if (TM.getOptLevel() > CodeGenOptLevel::None)2379 addPass(SIOptimizeExecMaskingPass());2380 Base::addPostRegAlloc(addPass);2381}2382 2383void AMDGPUCodeGenPassBuilder::addPreSched2(AddMachinePass &addPass) const {2384 if (TM.getOptLevel() > CodeGenOptLevel::None)2385 addPass(SIShrinkInstructionsPass());2386 addPass(SIPostRABundlerPass());2387}2388 2389void AMDGPUCodeGenPassBuilder::addPreEmitPass(AddMachinePass &addPass) const {2390 if (isPassEnabled(EnableVOPD, CodeGenOptLevel::Less)) {2391 addPass(GCNCreateVOPDPass());2392 }2393 2394 addPass(SIMemoryLegalizerPass());2395 addPass(SIInsertWaitcntsPass());2396 2397 // TODO: addPass(SIModeRegisterPass());2398 2399 if (TM.getOptLevel() > CodeGenOptLevel::None) {2400 // TODO: addPass(SIInsertHardClausesPass());2401 }2402 2403 addPass(SILateBranchLoweringPass());2404 2405 if (isPassEnabled(EnableSetWavePriority, CodeGenOptLevel::Less))2406 addPass(AMDGPUSetWavePriorityPass());2407 2408 if (TM.getOptLevel() > CodeGenOptLevel::None)2409 addPass(SIPreEmitPeepholePass());2410 2411 // The hazard recognizer that runs as part of the post-ra scheduler does not2412 // guarantee to be able handle all hazards correctly. This is because if there2413 // are multiple scheduling regions in a basic block, the regions are scheduled2414 // bottom up, so when we begin to schedule a region we don't know what2415 // instructions were emitted directly before it.2416 //2417 // Here we add a stand-alone hazard recognizer pass which can handle all2418 // cases.2419 addPass(PostRAHazardRecognizerPass());2420 addPass(AMDGPUWaitSGPRHazardsPass());2421 addPass(AMDGPULowerVGPREncodingPass());2422 2423 if (isPassEnabled(EnableInsertDelayAlu, CodeGenOptLevel::Less)) {2424 addPass(AMDGPUInsertDelayAluPass());2425 }2426 2427 addPass(BranchRelaxationPass());2428}2429 2430bool AMDGPUCodeGenPassBuilder::isPassEnabled(const cl::opt<bool> &Opt,2431 CodeGenOptLevel Level) const {2432 if (Opt.getNumOccurrences())2433 return Opt;2434 if (TM.getOptLevel() < Level)2435 return false;2436 return Opt;2437}2438 2439void AMDGPUCodeGenPassBuilder::addEarlyCSEOrGVNPass(AddIRPass &addPass) const {2440 if (TM.getOptLevel() == CodeGenOptLevel::Aggressive)2441 addPass(GVNPass());2442 else2443 addPass(EarlyCSEPass());2444}2445 2446void AMDGPUCodeGenPassBuilder::addStraightLineScalarOptimizationPasses(2447 AddIRPass &addPass) const {2448 if (isPassEnabled(EnableLoopPrefetch, CodeGenOptLevel::Aggressive))2449 addPass(LoopDataPrefetchPass());2450 2451 addPass(SeparateConstOffsetFromGEPPass());2452 2453 // ReassociateGEPs exposes more opportunities for SLSR. See2454 // the example in reassociate-geps-and-slsr.ll.2455 addPass(StraightLineStrengthReducePass());2456 2457 // SeparateConstOffsetFromGEP and SLSR creates common expressions which GVN or2458 // EarlyCSE can reuse.2459 addEarlyCSEOrGVNPass(addPass);2460 2461 // Run NaryReassociate after EarlyCSE/GVN to be more effective.2462 addPass(NaryReassociatePass());2463 2464 // NaryReassociate on GEPs creates redundant common expressions, so run2465 // EarlyCSE after it.2466 addPass(EarlyCSEPass());2467}2468