602 lines · cpp
1//===-- PPCTargetMachine.cpp - Define TargetMachine for PowerPC -----------===//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// Top-level implementation for the PowerPC target.10//11//===----------------------------------------------------------------------===//12 13#include "PPCTargetMachine.h"14#include "MCTargetDesc/PPCMCTargetDesc.h"15#include "PPC.h"16#include "PPCMachineFunctionInfo.h"17#include "PPCMachineScheduler.h"18#include "PPCMacroFusion.h"19#include "PPCSubtarget.h"20#include "PPCTargetObjectFile.h"21#include "PPCTargetTransformInfo.h"22#include "TargetInfo/PowerPCTargetInfo.h"23#include "llvm/ADT/StringRef.h"24#include "llvm/Analysis/TargetTransformInfo.h"25#include "llvm/CodeGen/GlobalISel/IRTranslator.h"26#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"27#include "llvm/CodeGen/GlobalISel/Legalizer.h"28#include "llvm/CodeGen/GlobalISel/Localizer.h"29#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"30#include "llvm/CodeGen/MachineScheduler.h"31#include "llvm/CodeGen/Passes.h"32#include "llvm/CodeGen/TargetPassConfig.h"33#include "llvm/IR/Attributes.h"34#include "llvm/IR/DataLayout.h"35#include "llvm/IR/Function.h"36#include "llvm/InitializePasses.h"37#include "llvm/MC/TargetRegistry.h"38#include "llvm/Pass.h"39#include "llvm/Support/CodeGen.h"40#include "llvm/Support/CommandLine.h"41#include "llvm/Support/Compiler.h"42#include "llvm/Target/TargetLoweringObjectFile.h"43#include "llvm/Target/TargetOptions.h"44#include "llvm/TargetParser/Triple.h"45#include "llvm/Transforms/Scalar.h"46#include <cassert>47#include <memory>48#include <optional>49#include <string>50 51using namespace llvm;52 53 54static cl::opt<bool>55 EnableBranchCoalescing("enable-ppc-branch-coalesce", cl::Hidden,56 cl::desc("enable coalescing of duplicate branches for PPC"));57static cl::58opt<bool> DisableCTRLoops("disable-ppc-ctrloops", cl::Hidden,59 cl::desc("Disable CTR loops for PPC"));60 61static cl::62opt<bool> DisableInstrFormPrep("disable-ppc-instr-form-prep", cl::Hidden,63 cl::desc("Disable PPC loop instr form prep"));64 65static cl::opt<bool>66VSXFMAMutateEarly("schedule-ppc-vsx-fma-mutation-early",67 cl::Hidden, cl::desc("Schedule VSX FMA instruction mutation early"));68 69static cl::70opt<bool> DisableVSXSwapRemoval("disable-ppc-vsx-swap-removal", cl::Hidden,71 cl::desc("Disable VSX Swap Removal for PPC"));72 73static cl::74opt<bool> DisableMIPeephole("disable-ppc-peephole", cl::Hidden,75 cl::desc("Disable machine peepholes for PPC"));76 77static cl::opt<bool>78EnableGEPOpt("ppc-gep-opt", cl::Hidden,79 cl::desc("Enable optimizations on complex GEPs"),80 cl::init(true));81 82static cl::opt<bool>83EnablePrefetch("enable-ppc-prefetching",84 cl::desc("enable software prefetching on PPC"),85 cl::init(false), cl::Hidden);86 87static cl::opt<bool>88EnableExtraTOCRegDeps("enable-ppc-extra-toc-reg-deps",89 cl::desc("Add extra TOC register dependencies"),90 cl::init(true), cl::Hidden);91 92static cl::opt<bool>93EnableMachineCombinerPass("ppc-machine-combiner",94 cl::desc("Enable the machine combiner pass"),95 cl::init(true), cl::Hidden);96 97static cl::opt<bool>98 ReduceCRLogical("ppc-reduce-cr-logicals",99 cl::desc("Expand eligible cr-logical binary ops to branches"),100 cl::init(true), cl::Hidden);101 102static cl::opt<bool> EnablePPCGenScalarMASSEntries(103 "enable-ppc-gen-scalar-mass", cl::init(false),104 cl::desc("Enable lowering math functions to their corresponding MASS "105 "(scalar) entries"),106 cl::Hidden);107 108static cl::opt<bool>109 EnableGlobalMerge("ppc-global-merge", cl::Hidden, cl::init(false),110 cl::desc("Enable the global merge pass"));111 112static cl::opt<unsigned>113 GlobalMergeMaxOffset("ppc-global-merge-max-offset", cl::Hidden,114 cl::init(0x7fff),115 cl::desc("Maximum global merge offset"));116 117extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void118LLVMInitializePowerPCTarget() {119 // Register the targets120 RegisterTargetMachine<PPCTargetMachine> A(getThePPC32Target());121 RegisterTargetMachine<PPCTargetMachine> B(getThePPC32LETarget());122 RegisterTargetMachine<PPCTargetMachine> C(getThePPC64Target());123 RegisterTargetMachine<PPCTargetMachine> D(getThePPC64LETarget());124 125 PassRegistry &PR = *PassRegistry::getPassRegistry();126#ifndef NDEBUG127 initializePPCCTRLoopsVerifyPass(PR);128#endif129 initializePPCLoopInstrFormPrepPass(PR);130 initializePPCTOCRegDepsPass(PR);131 initializePPCEarlyReturnPass(PR);132 initializePPCVSXWACCCopyPass(PR);133 initializePPCVSXFMAMutatePass(PR);134 initializePPCVSXSwapRemovalPass(PR);135 initializePPCReduceCRLogicalsPass(PR);136 initializePPCBSelPass(PR);137 initializePPCBranchCoalescingPass(PR);138 initializePPCBoolRetToIntPass(PR);139 initializePPCPreEmitPeepholePass(PR);140 initializePPCTLSDynamicCallPass(PR);141 initializePPCMIPeepholePass(PR);142 initializePPCLowerMASSVEntriesPass(PR);143 initializePPCGenScalarMASSEntriesPass(PR);144 initializePPCExpandAtomicPseudoPass(PR);145 initializeGlobalISel(PR);146 initializePPCCTRLoopsPass(PR);147 initializePPCDAGToDAGISelLegacyPass(PR);148 initializePPCLinuxAsmPrinterPass(PR);149 initializePPCAIXAsmPrinterPass(PR);150}151 152static std::string computeFSAdditions(StringRef FS, CodeGenOptLevel OL,153 const Triple &TT) {154 std::string FullFS = std::string(FS);155 156 // Make sure 64-bit features are available when CPUname is generic157 if (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le) {158 if (!FullFS.empty())159 FullFS = "+64bit," + FullFS;160 else161 FullFS = "+64bit";162 }163 164 if (OL >= CodeGenOptLevel::Default) {165 if (!FullFS.empty())166 FullFS = "+crbits," + FullFS;167 else168 FullFS = "+crbits";169 }170 171 if (OL != CodeGenOptLevel::None) {172 if (!FullFS.empty())173 FullFS = "+invariant-function-descriptors," + FullFS;174 else175 FullFS = "+invariant-function-descriptors";176 }177 178 if (TT.isOSAIX()) {179 if (!FullFS.empty())180 FullFS = "+aix," + FullFS;181 else182 FullFS = "+aix";183 }184 185 return FullFS;186}187 188static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {189 if (TT.isOSAIX())190 return std::make_unique<TargetLoweringObjectFileXCOFF>();191 192 return std::make_unique<PPC64LinuxTargetObjectFile>();193}194 195static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT,196 const TargetOptions &Options) {197 if (Options.MCOptions.getABIName().starts_with("elfv1"))198 return PPCTargetMachine::PPC_ABI_ELFv1;199 else if (Options.MCOptions.getABIName().starts_with("elfv2"))200 return PPCTargetMachine::PPC_ABI_ELFv2;201 202 assert(Options.MCOptions.getABIName().empty() &&203 "Unknown target-abi option!");204 205 switch (TT.getArch()) {206 case Triple::ppc64le:207 return PPCTargetMachine::PPC_ABI_ELFv2;208 case Triple::ppc64:209 if (TT.isPPC64ELFv2ABI())210 return PPCTargetMachine::PPC_ABI_ELFv2;211 else212 return PPCTargetMachine::PPC_ABI_ELFv1;213 default:214 return PPCTargetMachine::PPC_ABI_UNKNOWN;215 }216}217 218static Reloc::Model getEffectiveRelocModel(const Triple &TT,219 std::optional<Reloc::Model> RM) {220 if (TT.isOSAIX() && RM && *RM != Reloc::PIC_)221 report_fatal_error("invalid relocation model, AIX only supports PIC",222 false);223 224 if (RM)225 return *RM;226 227 // Big Endian PPC and AIX default to PIC.228 if (TT.getArch() == Triple::ppc64 || TT.isOSAIX())229 return Reloc::PIC_;230 231 // Rest are static by default.232 return Reloc::Static;233}234 235static CodeModel::Model236getEffectivePPCCodeModel(const Triple &TT, std::optional<CodeModel::Model> CM,237 bool JIT) {238 if (CM) {239 if (*CM == CodeModel::Tiny)240 report_fatal_error("Target does not support the tiny CodeModel", false);241 if (*CM == CodeModel::Kernel)242 report_fatal_error("Target does not support the kernel CodeModel", false);243 return *CM;244 }245 246 if (JIT)247 return CodeModel::Small;248 if (TT.isOSAIX())249 return CodeModel::Small;250 251 assert(TT.isOSBinFormatELF() && "All remaining PPC OSes are ELF based.");252 253 if (TT.isArch32Bit())254 return CodeModel::Small;255 256 assert(TT.isArch64Bit() && "Unsupported PPC architecture.");257 return CodeModel::Medium;258}259 260 261static ScheduleDAGInstrs *createPPCMachineScheduler(MachineSchedContext *C) {262 const PPCSubtarget &ST = C->MF->getSubtarget<PPCSubtarget>();263 ScheduleDAGMILive *DAG = ST.usePPCPreRASchedStrategy()264 ? createSchedLive<PPCPreRASchedStrategy>(C)265 : createSchedLive<GenericScheduler>(C);266 // add DAG Mutations here.267 if (ST.hasStoreFusion())268 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));269 if (ST.hasFusion())270 DAG->addMutation(createPowerPCMacroFusionDAGMutation());271 272 return DAG;273}274 275static ScheduleDAGInstrs *276createPPCPostMachineScheduler(MachineSchedContext *C) {277 const PPCSubtarget &ST = C->MF->getSubtarget<PPCSubtarget>();278 ScheduleDAGMI *DAG = ST.usePPCPostRASchedStrategy()279 ? createSchedPostRA<PPCPostRASchedStrategy>(C)280 : createSchedPostRA<PostGenericScheduler>(C);281 // add DAG Mutations here.282 if (ST.hasStoreFusion())283 DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI));284 if (ST.hasFusion())285 DAG->addMutation(createPowerPCMacroFusionDAGMutation());286 return DAG;287}288 289// The FeatureString here is a little subtle. We are modifying the feature290// string with what are (currently) non-function specific overrides as it goes291// into the CodeGenTargetMachineImpl constructor and then using the stored value292// in the Subtarget constructor below it.293PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT,294 StringRef CPU, StringRef FS,295 const TargetOptions &Options,296 std::optional<Reloc::Model> RM,297 std::optional<CodeModel::Model> CM,298 CodeGenOptLevel OL, bool JIT)299 : CodeGenTargetMachineImpl(T,300 TT.computeDataLayout(Options.MCOptions.ABIName),301 TT, CPU, computeFSAdditions(FS, OL, TT), Options,302 getEffectiveRelocModel(TT, RM),303 getEffectivePPCCodeModel(TT, CM, JIT), OL),304 TLOF(createTLOF(getTargetTriple())),305 TargetABI(computeTargetABI(TT, Options)),306 Endianness(TT.isLittleEndian() ? Endian::LITTLE : Endian::BIG) {307 initAsmInfo();308}309 310PPCTargetMachine::~PPCTargetMachine() = default;311 312const PPCSubtarget *313PPCTargetMachine::getSubtargetImpl(const Function &F) const {314 Attribute CPUAttr = F.getFnAttribute("target-cpu");315 Attribute TuneAttr = F.getFnAttribute("tune-cpu");316 Attribute FSAttr = F.getFnAttribute("target-features");317 318 std::string CPU =319 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;320 std::string TuneCPU =321 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;322 std::string FS =323 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;324 325 // FIXME: This is related to the code below to reset the target options,326 // we need to know whether or not the soft float flag is set on the327 // function before we can generate a subtarget. We also need to use328 // it as a key for the subtarget since that can be the only difference329 // between two functions.330 bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();331 // If the soft float attribute is set on the function turn on the soft float332 // subtarget feature.333 if (SoftFloat)334 FS += FS.empty() ? "-hard-float" : ",-hard-float";335 336 auto &I = SubtargetMap[CPU + TuneCPU + FS];337 if (!I) {338 // This needs to be done before we create a new subtarget since any339 // creation will depend on the TM and the code generation flags on the340 // function that reside in TargetOptions.341 resetTargetOptions(F);342 I = std::make_unique<PPCSubtarget>(343 TargetTriple, CPU, TuneCPU,344 // FIXME: It would be good to have the subtarget additions here345 // not necessary. Anything that turns them on/off (overrides) ends346 // up being put at the end of the feature string, but the defaults347 // shouldn't require adding them. Fixing this means pulling Feature64Bit348 // out of most of the target cpus in the .td file and making it set only349 // as part of initialization via the TargetTriple.350 computeFSAdditions(FS, getOptLevel(), getTargetTriple()), *this);351 }352 return I.get();353}354 355ScheduleDAGInstrs *356PPCTargetMachine::createMachineScheduler(MachineSchedContext *C) const {357 return createPPCMachineScheduler(C);358}359 360ScheduleDAGInstrs *361PPCTargetMachine::createPostMachineScheduler(MachineSchedContext *C) const {362 return createPPCPostMachineScheduler(C);363}364 365//===----------------------------------------------------------------------===//366// Pass Pipeline Configuration367//===----------------------------------------------------------------------===//368 369namespace {370 371/// PPC Code Generator Pass Configuration Options.372class PPCPassConfig : public TargetPassConfig {373public:374 PPCPassConfig(PPCTargetMachine &TM, PassManagerBase &PM)375 : TargetPassConfig(TM, PM) {376 // At any optimization level above -O0 we use the Machine Scheduler and not377 // the default Post RA List Scheduler.378 if (TM.getOptLevel() != CodeGenOptLevel::None)379 substitutePass(&PostRASchedulerID, &PostMachineSchedulerID);380 }381 382 PPCTargetMachine &getPPCTargetMachine() const {383 return getTM<PPCTargetMachine>();384 }385 386 void addIRPasses() override;387 bool addPreISel() override;388 bool addILPOpts() override;389 bool addInstSelector() override;390 void addMachineSSAOptimization() override;391 void addPreRegAlloc() override;392 void addPreSched2() override;393 void addPreEmitPass() override;394 void addPreEmitPass2() override;395 // GlobalISEL396 bool addIRTranslator() override;397 bool addLegalizeMachineIR() override;398 bool addRegBankSelect() override;399 bool addGlobalInstructionSelect() override;400};401 402} // end anonymous namespace403 404TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) {405 return new PPCPassConfig(*this, PM);406}407 408void PPCPassConfig::addIRPasses() {409 if (TM->getOptLevel() != CodeGenOptLevel::None)410 addPass(createPPCBoolRetToIntPass());411 addPass(createAtomicExpandLegacyPass());412 413 // Lower generic MASSV routines to PowerPC subtarget-specific entries.414 addPass(createPPCLowerMASSVEntriesPass());415 416 // Generate PowerPC target-specific entries for scalar math functions417 // that are available in IBM MASS (scalar) library.418 if (TM->getOptLevel() == CodeGenOptLevel::Aggressive &&419 EnablePPCGenScalarMASSEntries) {420 TM->Options.PPCGenScalarMASSEntries = EnablePPCGenScalarMASSEntries;421 addPass(createPPCGenScalarMASSEntriesPass());422 }423 424 // If explicitly requested, add explicit data prefetch intrinsics.425 if (EnablePrefetch.getNumOccurrences() > 0)426 addPass(createLoopDataPrefetchPass());427 428 if (TM->getOptLevel() >= CodeGenOptLevel::Default && EnableGEPOpt) {429 // Call SeparateConstOffsetFromGEP pass to extract constants within indices430 // and lower a GEP with multiple indices to either arithmetic operations or431 // multiple GEPs with single index.432 addPass(createSeparateConstOffsetFromGEPPass(true));433 // Call EarlyCSE pass to find and remove subexpressions in the lowered434 // result.435 addPass(createEarlyCSEPass());436 // Do loop invariant code motion in case part of the lowered result is437 // invariant.438 addPass(createLICMPass());439 }440 441 TargetPassConfig::addIRPasses();442}443 444bool PPCPassConfig::addPreISel() {445 // The GlobalMerge pass is intended to be on by default on AIX.446 // Specifying the command line option overrides the AIX default.447 if ((EnableGlobalMerge.getNumOccurrences() > 0)448 ? EnableGlobalMerge449 : getOptLevel() != CodeGenOptLevel::None)450 addPass(createGlobalMergePass(TM, GlobalMergeMaxOffset, false, false, true,451 true));452 453 if (!DisableInstrFormPrep && getOptLevel() != CodeGenOptLevel::None)454 addPass(createPPCLoopInstrFormPrepPass(getPPCTargetMachine()));455 456 if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None)457 addPass(createHardwareLoopsLegacyPass());458 459 return false;460}461 462bool PPCPassConfig::addILPOpts() {463 addPass(&EarlyIfConverterLegacyID);464 465 if (EnableMachineCombinerPass)466 addPass(&MachineCombinerID);467 468 return true;469}470 471bool PPCPassConfig::addInstSelector() {472 // Install an instruction selector.473 addPass(createPPCISelDag(getPPCTargetMachine(), getOptLevel()));474 475#ifndef NDEBUG476 if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None)477 addPass(createPPCCTRLoopsVerify());478#endif479 480 addPass(createPPCVSXWACCCopyPass());481 return false;482}483 484void PPCPassConfig::addMachineSSAOptimization() {485 // Run CTR loops pass before any cfg modification pass to prevent the486 // canonical form of hardware loop from being destroied.487 if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None)488 addPass(createPPCCTRLoopsPass());489 490 // PPCBranchCoalescingPass need to be done before machine sinking491 // since it merges empty blocks.492 if (EnableBranchCoalescing && getOptLevel() != CodeGenOptLevel::None)493 addPass(createPPCBranchCoalescingPass());494 TargetPassConfig::addMachineSSAOptimization();495 // For little endian, remove where possible the vector swap instructions496 // introduced at code generation to normalize vector element order.497 if (TM->getTargetTriple().getArch() == Triple::ppc64le &&498 !DisableVSXSwapRemoval)499 addPass(createPPCVSXSwapRemovalPass());500 // Reduce the number of cr-logical ops.501 if (ReduceCRLogical && getOptLevel() != CodeGenOptLevel::None)502 addPass(createPPCReduceCRLogicalsPass());503 // Target-specific peephole cleanups performed after instruction504 // selection.505 if (!DisableMIPeephole) {506 addPass(createPPCMIPeepholePass());507 addPass(&DeadMachineInstructionElimID);508 }509}510 511void PPCPassConfig::addPreRegAlloc() {512 if (getOptLevel() != CodeGenOptLevel::None) {513 insertPass(VSXFMAMutateEarly ? &TwoAddressInstructionPassID514 : &MachineSchedulerID,515 &PPCVSXFMAMutateID);516 }517 518 // FIXME: We probably don't need to run these for -fPIE.519 if (getPPCTargetMachine().isPositionIndependent()) {520 // FIXME: LiveVariables should not be necessary here!521 // PPCTLSDynamicCallPass uses LiveIntervals which previously dependent on522 // LiveVariables. This (unnecessary) dependency has been removed now,523 // however a stage-2 clang build fails without LiveVariables computed here.524 addPass(&LiveVariablesID);525 addPass(createPPCTLSDynamicCallPass());526 }527 if (EnableExtraTOCRegDeps)528 addPass(createPPCTOCRegDepsPass());529 530 if (getOptLevel() != CodeGenOptLevel::None)531 addPass(&MachinePipelinerID);532}533 534void PPCPassConfig::addPreSched2() {535 if (getOptLevel() != CodeGenOptLevel::None)536 addPass(&IfConverterID);537}538 539void PPCPassConfig::addPreEmitPass() {540 addPass(createPPCPreEmitPeepholePass());541 542 if (getOptLevel() != CodeGenOptLevel::None)543 addPass(createPPCEarlyReturnPass());544}545 546void PPCPassConfig::addPreEmitPass2() {547 // Schedule the expansion of AMOs at the last possible moment, avoiding the548 // possibility for other passes to break the requirements for forward549 // progress in the LL/SC block.550 addPass(createPPCExpandAtomicPseudoPass());551 // Must run branch selection immediately preceding the asm printer.552 addPass(createPPCBranchSelectionPass());553}554 555TargetTransformInfo556PPCTargetMachine::getTargetTransformInfo(const Function &F) const {557 return TargetTransformInfo(std::make_unique<PPCTTIImpl>(this, F));558}559 560bool PPCTargetMachine::isLittleEndian() const {561 assert(Endianness != Endian::NOT_DETECTED &&562 "Unable to determine endianness");563 return Endianness == Endian::LITTLE;564}565 566MachineFunctionInfo *PPCTargetMachine::createMachineFunctionInfo(567 BumpPtrAllocator &Allocator, const Function &F,568 const TargetSubtargetInfo *STI) const {569 return PPCFunctionInfo::create<PPCFunctionInfo>(Allocator, F, STI);570}571 572static MachineSchedRegistry573PPCPreRASchedRegistry("ppc-prera",574 "Run PowerPC PreRA specific scheduler",575 createPPCMachineScheduler);576 577static MachineSchedRegistry578PPCPostRASchedRegistry("ppc-postra",579 "Run PowerPC PostRA specific scheduler",580 createPPCPostMachineScheduler);581 582// Global ISEL583bool PPCPassConfig::addIRTranslator() {584 addPass(new IRTranslator());585 return false;586}587 588bool PPCPassConfig::addLegalizeMachineIR() {589 addPass(new Legalizer());590 return false;591}592 593bool PPCPassConfig::addRegBankSelect() {594 addPass(new RegBankSelect());595 return false;596}597 598bool PPCPassConfig::addGlobalInstructionSelect() {599 addPass(new InstructionSelect(getOptLevel()));600 return false;601}602