|
| 1 | +//===-- AIEBaseTargetMachine.cpp - AIE Target Machine -----------*- C++ -*-===// |
| 2 | +// |
| 3 | +// This file is licensed 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 | +// (c) Copyright 2024 Advanced Micro Devices, Inc. or its affiliates |
| 8 | +// |
| 9 | +//===----------------------------------------------------------------------===// |
| 10 | +// |
| 11 | +// This file contains common implementation of TargetMachine and |
| 12 | +// TargetPassConfig code between AIE versions. |
| 13 | +// |
| 14 | +//===----------------------------------------------------------------------===// |
| 15 | + |
| 16 | +#include "AIEBaseTargetMachine.h" |
| 17 | +#include "AIE.h" |
| 18 | +#include "AIEBaseAliasAnalysis.h" |
| 19 | +#include "AIEMachineFunctionInfo.h" |
| 20 | +#include "AIEMachineScheduler.h" |
| 21 | +#include "AIETargetObjectFile.h" |
| 22 | +#include "TargetInfo/AIETargetInfo.h" |
| 23 | +#include "llvm/ADT/STLExtras.h" |
| 24 | +#include "llvm/CodeGen/CSEConfigBase.h" |
| 25 | +#include "llvm/CodeGen/GlobalISel/CSEInfo.h" |
| 26 | +#include "llvm/CodeGen/GlobalISel/IRTranslator.h" |
| 27 | +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" |
| 28 | +#include "llvm/CodeGen/GlobalISel/Legalizer.h" |
| 29 | +#include "llvm/CodeGen/GlobalISel/RegBankSelect.h" |
| 30 | +#include "llvm/CodeGen/MIRParser/MIParser.h" |
| 31 | +#include "llvm/CodeGen/Passes.h" |
| 32 | +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
| 33 | +#include "llvm/CodeGen/TargetPassConfig.h" |
| 34 | +#include "llvm/IR/LegacyPassManager.h" |
| 35 | +#include "llvm/InitializePasses.h" |
| 36 | +#include "llvm/MC/TargetRegistry.h" |
| 37 | +#include "llvm/PassRegistry.h" |
| 38 | +#include "llvm/Passes/PassBuilder.h" |
| 39 | +#include "llvm/Support/CodeGen.h" |
| 40 | +#include "llvm/Support/FormattedStream.h" |
| 41 | +#include "llvm/Target/TargetMachine.h" |
| 42 | +#include "llvm/Target/TargetOptions.h" |
| 43 | +#include "llvm/Transforms/IPO/GlobalDCE.h" |
| 44 | +#include "llvm/Transforms/IPO/Internalize.h" |
| 45 | +#include "llvm/Transforms/Scalar.h" |
| 46 | + |
| 47 | +using namespace llvm; |
| 48 | + |
| 49 | +static cl::opt<bool> |
| 50 | + EnableCustomAliasAnalysisOpt("aie-enable-alias-analysis", |
| 51 | + cl::desc("Enable AIE alias analysis pass"), |
| 52 | + cl::init(true), cl::Hidden); |
| 53 | + |
| 54 | +static cl::opt<bool> |
| 55 | + EnableTailMergingOpt("aie-enable-tail-merge", |
| 56 | + cl::desc("Enable tail merging for AIE."), |
| 57 | + cl::init(false), cl::Hidden); |
| 58 | + |
| 59 | +// Option to run internalize pass. |
| 60 | +static cl::opt<bool> InternalizeSymbols( |
| 61 | + "aie-internalize-symbols", |
| 62 | + cl::desc("Enable elimination of non-kernel functions and unused globals"), |
| 63 | + cl::init(false), cl::Hidden); |
| 64 | + |
| 65 | +// Option to skip the functions we don't want to internalize. |
| 66 | +static cl::list<std::string> |
| 67 | + FunctionSkipList("aie-internalize-skip-functions", |
| 68 | + cl::desc("List of function names to skip internalization"), |
| 69 | + cl::Hidden, cl::list_init<std::string>({"main"}), |
| 70 | + cl::CommaSeparated); |
| 71 | + |
| 72 | +static StringRef computeDataLayout(const Triple &TT) { |
| 73 | + return "e-m:e-p:20:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-" |
| 74 | + "f64:32-a:0:32-n32"; |
| 75 | +} |
| 76 | + |
| 77 | +static Reloc::Model getEffectiveRelocModel(const Triple &TT, |
| 78 | + std::optional<Reloc::Model> RM) { |
| 79 | + if (!RM.has_value()) |
| 80 | + return Reloc::Static; |
| 81 | + // AIE does not support PIC code. If PIC code is asked for then just ignore |
| 82 | + // it. The main user of this is compiling the builtin library, which asks for |
| 83 | + // PIC. |
| 84 | + if (*RM == Reloc::PIC_) |
| 85 | + return Reloc::Static; |
| 86 | + return *RM; |
| 87 | +} |
| 88 | + |
| 89 | +AIEBaseTargetMachine::AIEBaseTargetMachine(const Target &T, const Triple &TT, |
| 90 | + StringRef CPU, StringRef FS, |
| 91 | + const TargetOptions &Options, |
| 92 | + std::optional<Reloc::Model> RM, |
| 93 | + std::optional<CodeModel::Model> CM, |
| 94 | + CodeGenOptLevel OL, bool JIT) |
| 95 | + : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, |
| 96 | + getEffectiveRelocModel(TT, RM), |
| 97 | + getEffectiveCodeModel(CM, CodeModel::Small), OL), |
| 98 | + TLOF(std::make_unique<AIEELFTargetObjectFile>()) { |
| 99 | + initAsmInfo(); |
| 100 | + EnableCustomAliasAnalysis = EnableCustomAliasAnalysisOpt; |
| 101 | +} |
| 102 | + |
| 103 | +yaml::MachineFunctionInfo * |
| 104 | +AIEBaseTargetMachine::createDefaultFuncInfoYAML() const { |
| 105 | + return new yaml::AIEMachineFunctionInfo(); |
| 106 | +} |
| 107 | + |
| 108 | +yaml::MachineFunctionInfo * |
| 109 | +AIEBaseTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const { |
| 110 | + const auto *MFI = MF.getInfo<AIEMachineFunctionInfo>(); |
| 111 | + return new yaml::AIEMachineFunctionInfo(*MFI); |
| 112 | +} |
| 113 | + |
| 114 | +bool AIEBaseTargetMachine::parseMachineFunctionInfo( |
| 115 | + const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS, |
| 116 | + SMDiagnostic &Error, SMRange &SourceRange) const { |
| 117 | + const auto &YamlMFI = |
| 118 | + reinterpret_cast<const yaml::AIEMachineFunctionInfo &>(MFI); |
| 119 | + MachineFunction &MF = PFS.MF; |
| 120 | + MF.getInfo<AIEMachineFunctionInfo>()->initializeBaseYamlFields(YamlMFI); |
| 121 | + return false; |
| 122 | +} |
| 123 | + |
| 124 | +MachineFunctionInfo *AIEBaseTargetMachine::createMachineFunctionInfo( |
| 125 | + BumpPtrAllocator &Allocator, const Function &F, |
| 126 | + const TargetSubtargetInfo *STI) const { |
| 127 | + return new (Allocator.Allocate<AIEMachineFunctionInfo>()) |
| 128 | + AIEMachineFunctionInfo(F, STI, *this); |
| 129 | +} |
| 130 | + |
| 131 | +bool AIEBaseTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS, |
| 132 | + unsigned DestAS) const { |
| 133 | + // AIE address space is used for bank annotation only. |
| 134 | + // aie-addrspace-flattening pass retyped pointer with a AS to default AS. |
| 135 | + return true; |
| 136 | +} |
| 137 | + |
| 138 | +void AIEBaseTargetMachine::registerDefaultAliasAnalyses(AAManager &AAM) { |
| 139 | + if (EnableCustomAliasAnalysis) |
| 140 | + AAM.registerFunctionAnalysis<AIEBaseAA>(); |
| 141 | +} |
| 142 | + |
| 143 | +/// Predicate for Internalize pass. |
| 144 | +/// Preserve functions that can be an entry point or that have uses within the |
| 145 | +/// Module. |
| 146 | +static bool mustPreserveGV(const GlobalValue &GV) { |
| 147 | + if (const Function *F = dyn_cast<Function>(&GV)) { |
| 148 | + bool Skip = llvm::any_of(FunctionSkipList, [&](const std::string &Name) { |
| 149 | + return F->getName().equals(Name); |
| 150 | + }); |
| 151 | + return F->isDeclaration() || Skip; |
| 152 | + } |
| 153 | + |
| 154 | + GV.removeDeadConstantUsers(); |
| 155 | + return !GV.use_empty(); |
| 156 | +} |
| 157 | + |
| 158 | +void AIEBaseTargetMachine::registerPassBuilderCallbacks( |
| 159 | + PassBuilder &PB, bool PopulateClassToPassNames) { |
| 160 | + if (EnableCustomAliasAnalysis) { |
| 161 | + PB.registerAnalysisRegistrationCallback([](FunctionAnalysisManager &FAM) { |
| 162 | + FAM.registerPass([&] { return AIEBaseAA(); }); |
| 163 | + }); |
| 164 | + PB.registerParseAACallback([](StringRef AAName, AAManager &AAM) { |
| 165 | + if (AAName == "aie-aa") { |
| 166 | + AAM.registerFunctionAnalysis<AIEBaseAA>(); |
| 167 | + return true; |
| 168 | + } |
| 169 | + return false; |
| 170 | + }); |
| 171 | + } |
| 172 | + |
| 173 | + if (InternalizeSymbols) { |
| 174 | + PB.registerPipelineEarlySimplificationEPCallback( |
| 175 | + [](ModulePassManager &PM, OptimizationLevel) { |
| 176 | + if (InternalizeSymbols) { |
| 177 | + PM.addPass(InternalizePass(mustPreserveGV)); |
| 178 | + PM.addPass(GlobalDCEPass()); |
| 179 | + } |
| 180 | + }); |
| 181 | + } |
| 182 | +} |
| 183 | + |
| 184 | +AIEBasePassConfig::AIEBasePassConfig(LLVMTargetMachine &TM, PassManagerBase &PM) |
| 185 | + : TargetPassConfig(TM, PM) { |
| 186 | + EnableTailMerge = EnableTailMergingOpt; |
| 187 | + EnableCustomAliasAnalysis = EnableCustomAliasAnalysisOpt; |
| 188 | +} |
| 189 | + |
| 190 | +void AIEBasePassConfig::addIRPasses() { |
| 191 | + // Always expand atomic operations, we don't deal with atomicrmw or cmpxchg |
| 192 | + // ourselves. |
| 193 | + addPass(createAtomicExpandLegacyPass()); |
| 194 | + |
| 195 | + if (TM->getOptLevel() > CodeGenOptLevel::None) { |
| 196 | + if (EnableCustomAliasAnalysis) { |
| 197 | + addPass(createAIEBaseAAWrapperPass()); |
| 198 | + addPass( |
| 199 | + createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) { |
| 200 | + if (auto *WrapperPass = |
| 201 | + P.getAnalysisIfAvailable<AIEBaseAAWrapperPass>()) |
| 202 | + AAR.addAAResult(WrapperPass->getResult()); |
| 203 | + })); |
| 204 | + } |
| 205 | + } |
| 206 | + if (TM->getOptLevel() > CodeGenOptLevel::None) |
| 207 | + addPass(createInferAddressSpacesPass()); |
| 208 | + TargetPassConfig::addIRPasses(); |
| 209 | +} |
| 210 | + |
| 211 | +void AIEBasePassConfig::addMachineLateOptimization() { |
| 212 | + TargetPassConfig::addMachineLateOptimization(); |
| 213 | + // Run MachineCopyPropagation again, but take into account |
| 214 | + // architecture-specific mov operations using isMoveReg (see isCopyInstrImpl |
| 215 | + // hook) |
| 216 | + addPass(createMachineCopyPropagationPass(true)); |
| 217 | +} |
| 218 | + |
| 219 | +bool AIEBasePassConfig::addIRTranslator() { |
| 220 | + addPass(new IRTranslator(getOptLevel())); |
| 221 | + return false; |
| 222 | +} |
| 223 | + |
| 224 | +bool AIEBasePassConfig::addLegalizeMachineIR() { |
| 225 | + addPass(new Legalizer()); |
| 226 | + return false; |
| 227 | +} |
| 228 | + |
| 229 | +bool AIEBasePassConfig::addRegBankSelect() { |
| 230 | + addPass(new RegBankSelect()); |
| 231 | + return false; |
| 232 | +} |
| 233 | + |
| 234 | +bool AIEBasePassConfig::addGlobalInstructionSelect() { |
| 235 | + addPass(new InstructionSelect(getOptLevel())); |
| 236 | + return false; |
| 237 | +} |
| 238 | + |
| 239 | +bool AIEBasePassConfig::addInstSelector() { return false; } |
| 240 | + |
| 241 | +void AIEBasePassConfig::addPreEmitPass() {} |
| 242 | + |
| 243 | +void AIEBasePassConfig::addPreEmitPass2() {} |
| 244 | + |
| 245 | +void AIEBasePassConfig::addPreRegAlloc() {} |
| 246 | + |
| 247 | +void AIEBasePassConfig::addPreSched2() { |
| 248 | + // PostRAScheduler is required to insert NoOps for correctness. |
| 249 | + // We always run it, independently of the Opt level. |
| 250 | + addPass(&PostRASchedulerID); |
| 251 | + // After scheduling, create the bundles from the BundleWithPred flags |
| 252 | + addPass(&FinalizeMachineBundlesID); |
| 253 | +} |
| 254 | + |
| 255 | +ScheduleDAGInstrs * |
| 256 | +AIEBasePassConfig::createPostMachineScheduler(MachineSchedContext *C) const { |
| 257 | + ScheduleDAGMI *DAG = |
| 258 | + new AIEScheduleDAGMI(C, std::make_unique<AIEPostRASchedStrategy>(C), |
| 259 | + /* RemoveKillFlags=*/true); |
| 260 | + for (auto &Mutation : |
| 261 | + AIEBaseSubtarget::getPostRAMutationsImpl(TM->getTargetTriple())) |
| 262 | + DAG->addMutation(std::move(Mutation)); |
| 263 | + return DAG; |
| 264 | +} |
| 265 | + |
| 266 | +ScheduleDAGInstrs * |
| 267 | +AIEBasePassConfig::createMachineScheduler(MachineSchedContext *C) const { |
| 268 | + ScheduleDAGMILive *DAG = |
| 269 | + new AIEScheduleDAGMILive(C, std::make_unique<AIEPreRASchedStrategy>(C)); |
| 270 | + DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI)); |
| 271 | + |
| 272 | + for (auto &Mutation : |
| 273 | + AIEBaseSubtarget::getPreRAMutationsImpl(TM->getTargetTriple())) |
| 274 | + DAG->addMutation(std::move(Mutation)); |
| 275 | + return DAG; |
| 276 | +} |
| 277 | + |
| 278 | +std::unique_ptr<CSEConfigBase> AIEBasePassConfig::getCSEConfig() const { |
| 279 | + // We don't want CSE to run at -O0, as it introduces constrained register |
| 280 | + // operands (r27) that RegAllocFast is not able to resolve. |
| 281 | + if (TM->getOptLevel() == CodeGenOptLevel::None) |
| 282 | + return std::make_unique<CSEConfigBase>(); |
| 283 | + return getStandardCSEConfigForOpt(TM->getOptLevel()); |
| 284 | +} |
0 commit comments