brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.9 KiB · 4ff489d Raw
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