10b57cec5SDimitry Andric //===-- PPCTargetMachine.cpp - Define TargetMachine for PowerPC -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Top-level implementation for the PowerPC target. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "PPCTargetMachine.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h" 150b57cec5SDimitry Andric #include "PPC.h" 160b57cec5SDimitry Andric #include "PPCMachineScheduler.h" 170b57cec5SDimitry Andric #include "PPCSubtarget.h" 180b57cec5SDimitry Andric #include "PPCTargetObjectFile.h" 190b57cec5SDimitry Andric #include "PPCTargetTransformInfo.h" 200b57cec5SDimitry Andric #include "TargetInfo/PowerPCTargetInfo.h" 210b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 220b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 240b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 290b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 300b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 310b57cec5SDimitry Andric #include "llvm/IR/Function.h" 320b57cec5SDimitry Andric #include "llvm/Pass.h" 330b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 340b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 350b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 360b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 370b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 380b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 390b57cec5SDimitry Andric #include <cassert> 400b57cec5SDimitry Andric #include <memory> 410b57cec5SDimitry Andric #include <string> 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric using namespace llvm; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric static cl::opt<bool> 470b57cec5SDimitry Andric EnableBranchCoalescing("enable-ppc-branch-coalesce", cl::Hidden, 480b57cec5SDimitry Andric cl::desc("enable coalescing of duplicate branches for PPC")); 490b57cec5SDimitry Andric static cl:: 500b57cec5SDimitry Andric opt<bool> DisableCTRLoops("disable-ppc-ctrloops", cl::Hidden, 510b57cec5SDimitry Andric cl::desc("Disable CTR loops for PPC")); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric static cl:: 540b57cec5SDimitry Andric opt<bool> DisablePreIncPrep("disable-ppc-preinc-prep", cl::Hidden, 550b57cec5SDimitry Andric cl::desc("Disable PPC loop preinc prep")); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric static cl::opt<bool> 580b57cec5SDimitry Andric VSXFMAMutateEarly("schedule-ppc-vsx-fma-mutation-early", 590b57cec5SDimitry Andric cl::Hidden, cl::desc("Schedule VSX FMA instruction mutation early")); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric static cl:: 620b57cec5SDimitry Andric opt<bool> DisableVSXSwapRemoval("disable-ppc-vsx-swap-removal", cl::Hidden, 630b57cec5SDimitry Andric cl::desc("Disable VSX Swap Removal for PPC")); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric static cl:: 660b57cec5SDimitry Andric opt<bool> DisableQPXLoadSplat("disable-ppc-qpx-load-splat", cl::Hidden, 670b57cec5SDimitry Andric cl::desc("Disable QPX load splat simplification")); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric static cl:: 700b57cec5SDimitry Andric opt<bool> DisableMIPeephole("disable-ppc-peephole", cl::Hidden, 710b57cec5SDimitry Andric cl::desc("Disable machine peepholes for PPC")); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric static cl::opt<bool> 740b57cec5SDimitry Andric EnableGEPOpt("ppc-gep-opt", cl::Hidden, 750b57cec5SDimitry Andric cl::desc("Enable optimizations on complex GEPs"), 760b57cec5SDimitry Andric cl::init(true)); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric static cl::opt<bool> 790b57cec5SDimitry Andric EnablePrefetch("enable-ppc-prefetching", 800b57cec5SDimitry Andric cl::desc("disable software prefetching on PPC"), 810b57cec5SDimitry Andric cl::init(false), cl::Hidden); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric static cl::opt<bool> 840b57cec5SDimitry Andric EnableExtraTOCRegDeps("enable-ppc-extra-toc-reg-deps", 850b57cec5SDimitry Andric cl::desc("Add extra TOC register dependencies"), 860b57cec5SDimitry Andric cl::init(true), cl::Hidden); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric static cl::opt<bool> 890b57cec5SDimitry Andric EnableMachineCombinerPass("ppc-machine-combiner", 900b57cec5SDimitry Andric cl::desc("Enable the machine combiner pass"), 910b57cec5SDimitry Andric cl::init(true), cl::Hidden); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric static cl::opt<bool> 940b57cec5SDimitry Andric ReduceCRLogical("ppc-reduce-cr-logicals", 950b57cec5SDimitry Andric cl::desc("Expand eligible cr-logical binary ops to branches"), 96*8bcb0991SDimitry Andric cl::init(true), cl::Hidden); 970b57cec5SDimitry Andric extern "C" void LLVMInitializePowerPCTarget() { 980b57cec5SDimitry Andric // Register the targets 990b57cec5SDimitry Andric RegisterTargetMachine<PPCTargetMachine> A(getThePPC32Target()); 1000b57cec5SDimitry Andric RegisterTargetMachine<PPCTargetMachine> B(getThePPC64Target()); 1010b57cec5SDimitry Andric RegisterTargetMachine<PPCTargetMachine> C(getThePPC64LETarget()); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric PassRegistry &PR = *PassRegistry::getPassRegistry(); 1040b57cec5SDimitry Andric #ifndef NDEBUG 1050b57cec5SDimitry Andric initializePPCCTRLoopsVerifyPass(PR); 1060b57cec5SDimitry Andric #endif 1070b57cec5SDimitry Andric initializePPCLoopPreIncPrepPass(PR); 1080b57cec5SDimitry Andric initializePPCTOCRegDepsPass(PR); 1090b57cec5SDimitry Andric initializePPCEarlyReturnPass(PR); 1100b57cec5SDimitry Andric initializePPCVSXCopyPass(PR); 1110b57cec5SDimitry Andric initializePPCVSXFMAMutatePass(PR); 1120b57cec5SDimitry Andric initializePPCVSXSwapRemovalPass(PR); 1130b57cec5SDimitry Andric initializePPCReduceCRLogicalsPass(PR); 1140b57cec5SDimitry Andric initializePPCBSelPass(PR); 1150b57cec5SDimitry Andric initializePPCBranchCoalescingPass(PR); 1160b57cec5SDimitry Andric initializePPCQPXLoadSplatPass(PR); 1170b57cec5SDimitry Andric initializePPCBoolRetToIntPass(PR); 1180b57cec5SDimitry Andric initializePPCExpandISELPass(PR); 1190b57cec5SDimitry Andric initializePPCPreEmitPeepholePass(PR); 1200b57cec5SDimitry Andric initializePPCTLSDynamicCallPass(PR); 1210b57cec5SDimitry Andric initializePPCMIPeepholePass(PR); 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric /// Return the datalayout string of a subtarget. 1250b57cec5SDimitry Andric static std::string getDataLayoutString(const Triple &T) { 1260b57cec5SDimitry Andric bool is64Bit = T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le; 1270b57cec5SDimitry Andric std::string Ret; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // Most PPC* platforms are big endian, PPC64LE is little endian. 1300b57cec5SDimitry Andric if (T.getArch() == Triple::ppc64le) 1310b57cec5SDimitry Andric Ret = "e"; 1320b57cec5SDimitry Andric else 1330b57cec5SDimitry Andric Ret = "E"; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric Ret += DataLayout::getManglingComponent(T); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric // PPC32 has 32 bit pointers. The PS3 (OS Lv2) is a PPC64 machine with 32 bit 1380b57cec5SDimitry Andric // pointers. 1390b57cec5SDimitry Andric if (!is64Bit || T.getOS() == Triple::Lv2) 1400b57cec5SDimitry Andric Ret += "-p:32:32"; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Note, the alignment values for f64 and i64 on ppc64 in Darwin 1430b57cec5SDimitry Andric // documentation are wrong; these are correct (i.e. "what gcc does"). 1440b57cec5SDimitry Andric if (is64Bit || !T.isOSDarwin()) 1450b57cec5SDimitry Andric Ret += "-i64:64"; 1460b57cec5SDimitry Andric else 1470b57cec5SDimitry Andric Ret += "-f64:32:64"; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric // PPC64 has 32 and 64 bit registers, PPC32 has only 32 bit ones. 1500b57cec5SDimitry Andric if (is64Bit) 1510b57cec5SDimitry Andric Ret += "-n32:64"; 1520b57cec5SDimitry Andric else 1530b57cec5SDimitry Andric Ret += "-n32"; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric return Ret; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric static std::string computeFSAdditions(StringRef FS, CodeGenOpt::Level OL, 1590b57cec5SDimitry Andric const Triple &TT) { 1600b57cec5SDimitry Andric std::string FullFS = FS; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // Make sure 64-bit features are available when CPUname is generic 1630b57cec5SDimitry Andric if (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le) { 1640b57cec5SDimitry Andric if (!FullFS.empty()) 1650b57cec5SDimitry Andric FullFS = "+64bit," + FullFS; 1660b57cec5SDimitry Andric else 1670b57cec5SDimitry Andric FullFS = "+64bit"; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric if (OL >= CodeGenOpt::Default) { 1710b57cec5SDimitry Andric if (!FullFS.empty()) 1720b57cec5SDimitry Andric FullFS = "+crbits," + FullFS; 1730b57cec5SDimitry Andric else 1740b57cec5SDimitry Andric FullFS = "+crbits"; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (OL != CodeGenOpt::None) { 1780b57cec5SDimitry Andric if (!FullFS.empty()) 1790b57cec5SDimitry Andric FullFS = "+invariant-function-descriptors," + FullFS; 1800b57cec5SDimitry Andric else 1810b57cec5SDimitry Andric FullFS = "+invariant-function-descriptors"; 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric return FullFS; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { 1880b57cec5SDimitry Andric if (TT.isOSDarwin()) 189*8bcb0991SDimitry Andric return std::make_unique<TargetLoweringObjectFileMachO>(); 1900b57cec5SDimitry Andric 191*8bcb0991SDimitry Andric if (TT.isOSAIX()) 192*8bcb0991SDimitry Andric return std::make_unique<TargetLoweringObjectFileXCOFF>(); 193*8bcb0991SDimitry Andric 194*8bcb0991SDimitry Andric return std::make_unique<PPC64LinuxTargetObjectFile>(); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, 1980b57cec5SDimitry Andric const TargetOptions &Options) { 1990b57cec5SDimitry Andric if (TT.isOSDarwin()) 2000b57cec5SDimitry Andric report_fatal_error("Darwin is no longer supported for PowerPC"); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric if (Options.MCOptions.getABIName().startswith("elfv1")) 2030b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv1; 2040b57cec5SDimitry Andric else if (Options.MCOptions.getABIName().startswith("elfv2")) 2050b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv2; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric assert(Options.MCOptions.getABIName().empty() && 2080b57cec5SDimitry Andric "Unknown target-abi option!"); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric if (TT.isMacOSX()) 2110b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_UNKNOWN; 2120b57cec5SDimitry Andric 213e4399d16SJustin Hibbits if (TT.isOSFreeBSD()) { 214e4399d16SJustin Hibbits switch (TT.getArch()) { 215e4399d16SJustin Hibbits case Triple::ppc64le: 216e4399d16SJustin Hibbits case Triple::ppc64: 217e4399d16SJustin Hibbits if (TT.getOSMajorVersion() >= 13) 218e4399d16SJustin Hibbits return PPCTargetMachine::PPC_ABI_ELFv2; 219e4399d16SJustin Hibbits else 220e4399d16SJustin Hibbits return PPCTargetMachine::PPC_ABI_ELFv1; 221e4399d16SJustin Hibbits case Triple::ppc: 222e4399d16SJustin Hibbits default: 223e4399d16SJustin Hibbits return PPCTargetMachine::PPC_ABI_UNKNOWN; 224e4399d16SJustin Hibbits } 225e4399d16SJustin Hibbits } 226e4399d16SJustin Hibbits 2270b57cec5SDimitry Andric switch (TT.getArch()) { 2280b57cec5SDimitry Andric case Triple::ppc64le: 2290b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv2; 2300b57cec5SDimitry Andric case Triple::ppc64: 2310b57cec5SDimitry Andric if (TT.getEnvironment() == llvm::Triple::ELFv2) 2320b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv2; 2330b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv1; 2340b57cec5SDimitry Andric default: 2350b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_UNKNOWN; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric static Reloc::Model getEffectiveRelocModel(const Triple &TT, 2400b57cec5SDimitry Andric Optional<Reloc::Model> RM) { 2410b57cec5SDimitry Andric if (RM.hasValue()) 2420b57cec5SDimitry Andric return *RM; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric // Darwin defaults to dynamic-no-pic. 2450b57cec5SDimitry Andric if (TT.isOSDarwin()) 2460b57cec5SDimitry Andric return Reloc::DynamicNoPIC; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric // Big Endian PPC is PIC by default. 2490b57cec5SDimitry Andric if (TT.getArch() == Triple::ppc64) 2500b57cec5SDimitry Andric return Reloc::PIC_; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // Rest are static by default. 2530b57cec5SDimitry Andric return Reloc::Static; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric static CodeModel::Model getEffectivePPCCodeModel(const Triple &TT, 2570b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 2580b57cec5SDimitry Andric bool JIT) { 2590b57cec5SDimitry Andric if (CM) { 2600b57cec5SDimitry Andric if (*CM == CodeModel::Tiny) 2610b57cec5SDimitry Andric report_fatal_error("Target does not support the tiny CodeModel", false); 2620b57cec5SDimitry Andric if (*CM == CodeModel::Kernel) 2630b57cec5SDimitry Andric report_fatal_error("Target does not support the kernel CodeModel", false); 2640b57cec5SDimitry Andric return *CM; 2650b57cec5SDimitry Andric } 266*8bcb0991SDimitry Andric 267*8bcb0991SDimitry Andric if (JIT) 2680b57cec5SDimitry Andric return CodeModel::Small; 269*8bcb0991SDimitry Andric if (TT.isOSAIX()) 270*8bcb0991SDimitry Andric return CodeModel::Small; 271*8bcb0991SDimitry Andric 272*8bcb0991SDimitry Andric assert(TT.isOSBinFormatELF() && "All remaining PPC OSes are ELF based."); 273*8bcb0991SDimitry Andric 274*8bcb0991SDimitry Andric if (TT.isArch32Bit()) 275*8bcb0991SDimitry Andric return CodeModel::Small; 276*8bcb0991SDimitry Andric 277*8bcb0991SDimitry Andric assert(TT.isArch64Bit() && "Unsupported PPC architecture."); 278*8bcb0991SDimitry Andric return CodeModel::Medium; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric static ScheduleDAGInstrs *createPPCMachineScheduler(MachineSchedContext *C) { 2830b57cec5SDimitry Andric const PPCSubtarget &ST = C->MF->getSubtarget<PPCSubtarget>(); 2840b57cec5SDimitry Andric ScheduleDAGMILive *DAG = 2850b57cec5SDimitry Andric new ScheduleDAGMILive(C, ST.usePPCPreRASchedStrategy() ? 286*8bcb0991SDimitry Andric std::make_unique<PPCPreRASchedStrategy>(C) : 287*8bcb0991SDimitry Andric std::make_unique<GenericScheduler>(C)); 2880b57cec5SDimitry Andric // add DAG Mutations here. 2890b57cec5SDimitry Andric DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI)); 2900b57cec5SDimitry Andric return DAG; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric static ScheduleDAGInstrs *createPPCPostMachineScheduler( 2940b57cec5SDimitry Andric MachineSchedContext *C) { 2950b57cec5SDimitry Andric const PPCSubtarget &ST = C->MF->getSubtarget<PPCSubtarget>(); 2960b57cec5SDimitry Andric ScheduleDAGMI *DAG = 2970b57cec5SDimitry Andric new ScheduleDAGMI(C, ST.usePPCPostRASchedStrategy() ? 298*8bcb0991SDimitry Andric std::make_unique<PPCPostRASchedStrategy>(C) : 299*8bcb0991SDimitry Andric std::make_unique<PostGenericScheduler>(C), true); 3000b57cec5SDimitry Andric // add DAG Mutations here. 3010b57cec5SDimitry Andric return DAG; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric // The FeatureString here is a little subtle. We are modifying the feature 3050b57cec5SDimitry Andric // string with what are (currently) non-function specific overrides as it goes 3060b57cec5SDimitry Andric // into the LLVMTargetMachine constructor and then using the stored value in the 3070b57cec5SDimitry Andric // Subtarget constructor below it. 3080b57cec5SDimitry Andric PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT, 3090b57cec5SDimitry Andric StringRef CPU, StringRef FS, 3100b57cec5SDimitry Andric const TargetOptions &Options, 3110b57cec5SDimitry Andric Optional<Reloc::Model> RM, 3120b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 3130b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 3140b57cec5SDimitry Andric : LLVMTargetMachine(T, getDataLayoutString(TT), TT, CPU, 3150b57cec5SDimitry Andric computeFSAdditions(FS, OL, TT), Options, 3160b57cec5SDimitry Andric getEffectiveRelocModel(TT, RM), 3170b57cec5SDimitry Andric getEffectivePPCCodeModel(TT, CM, JIT), OL), 3180b57cec5SDimitry Andric TLOF(createTLOF(getTargetTriple())), 3190b57cec5SDimitry Andric TargetABI(computeTargetABI(TT, Options)) { 3200b57cec5SDimitry Andric initAsmInfo(); 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric PPCTargetMachine::~PPCTargetMachine() = default; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric const PPCSubtarget * 3260b57cec5SDimitry Andric PPCTargetMachine::getSubtargetImpl(const Function &F) const { 3270b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 3280b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 3310b57cec5SDimitry Andric ? CPUAttr.getValueAsString().str() 3320b57cec5SDimitry Andric : TargetCPU; 3330b57cec5SDimitry Andric std::string FS = !FSAttr.hasAttribute(Attribute::None) 3340b57cec5SDimitry Andric ? FSAttr.getValueAsString().str() 3350b57cec5SDimitry Andric : TargetFS; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 3380b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 3390b57cec5SDimitry Andric // function before we can generate a subtarget. We also need to use 3400b57cec5SDimitry Andric // it as a key for the subtarget since that can be the only difference 3410b57cec5SDimitry Andric // between two functions. 3420b57cec5SDimitry Andric bool SoftFloat = 3430b57cec5SDimitry Andric F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 3440b57cec5SDimitry Andric // If the soft float attribute is set on the function turn on the soft float 3450b57cec5SDimitry Andric // subtarget feature. 3460b57cec5SDimitry Andric if (SoftFloat) 3470b57cec5SDimitry Andric FS += FS.empty() ? "-hard-float" : ",-hard-float"; 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 3500b57cec5SDimitry Andric if (!I) { 3510b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 3520b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 3530b57cec5SDimitry Andric // function that reside in TargetOptions. 3540b57cec5SDimitry Andric resetTargetOptions(F); 355*8bcb0991SDimitry Andric I = std::make_unique<PPCSubtarget>( 3560b57cec5SDimitry Andric TargetTriple, CPU, 3570b57cec5SDimitry Andric // FIXME: It would be good to have the subtarget additions here 3580b57cec5SDimitry Andric // not necessary. Anything that turns them on/off (overrides) ends 3590b57cec5SDimitry Andric // up being put at the end of the feature string, but the defaults 3600b57cec5SDimitry Andric // shouldn't require adding them. Fixing this means pulling Feature64Bit 3610b57cec5SDimitry Andric // out of most of the target cpus in the .td file and making it set only 3620b57cec5SDimitry Andric // as part of initialization via the TargetTriple. 3630b57cec5SDimitry Andric computeFSAdditions(FS, getOptLevel(), getTargetTriple()), *this); 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric return I.get(); 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3690b57cec5SDimitry Andric // Pass Pipeline Configuration 3700b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric namespace { 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric /// PPC Code Generator Pass Configuration Options. 3750b57cec5SDimitry Andric class PPCPassConfig : public TargetPassConfig { 3760b57cec5SDimitry Andric public: 3770b57cec5SDimitry Andric PPCPassConfig(PPCTargetMachine &TM, PassManagerBase &PM) 3780b57cec5SDimitry Andric : TargetPassConfig(TM, PM) { 3790b57cec5SDimitry Andric // At any optimization level above -O0 we use the Machine Scheduler and not 3800b57cec5SDimitry Andric // the default Post RA List Scheduler. 3810b57cec5SDimitry Andric if (TM.getOptLevel() != CodeGenOpt::None) 3820b57cec5SDimitry Andric substitutePass(&PostRASchedulerID, &PostMachineSchedulerID); 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric PPCTargetMachine &getPPCTargetMachine() const { 3860b57cec5SDimitry Andric return getTM<PPCTargetMachine>(); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void addIRPasses() override; 3900b57cec5SDimitry Andric bool addPreISel() override; 3910b57cec5SDimitry Andric bool addILPOpts() override; 3920b57cec5SDimitry Andric bool addInstSelector() override; 3930b57cec5SDimitry Andric void addMachineSSAOptimization() override; 3940b57cec5SDimitry Andric void addPreRegAlloc() override; 3950b57cec5SDimitry Andric void addPreSched2() override; 3960b57cec5SDimitry Andric void addPreEmitPass() override; 3970b57cec5SDimitry Andric ScheduleDAGInstrs * 3980b57cec5SDimitry Andric createMachineScheduler(MachineSchedContext *C) const override { 3990b57cec5SDimitry Andric return createPPCMachineScheduler(C); 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric ScheduleDAGInstrs * 4020b57cec5SDimitry Andric createPostMachineScheduler(MachineSchedContext *C) const override { 4030b57cec5SDimitry Andric return createPPCPostMachineScheduler(C); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric }; 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric } // end anonymous namespace 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) { 4100b57cec5SDimitry Andric return new PPCPassConfig(*this, PM); 4110b57cec5SDimitry Andric } 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric void PPCPassConfig::addIRPasses() { 4140b57cec5SDimitry Andric if (TM->getOptLevel() != CodeGenOpt::None) 4150b57cec5SDimitry Andric addPass(createPPCBoolRetToIntPass()); 4160b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric // For the BG/Q (or if explicitly requested), add explicit data prefetch 4190b57cec5SDimitry Andric // intrinsics. 4200b57cec5SDimitry Andric bool UsePrefetching = TM->getTargetTriple().getVendor() == Triple::BGQ && 4210b57cec5SDimitry Andric getOptLevel() != CodeGenOpt::None; 4220b57cec5SDimitry Andric if (EnablePrefetch.getNumOccurrences() > 0) 4230b57cec5SDimitry Andric UsePrefetching = EnablePrefetch; 4240b57cec5SDimitry Andric if (UsePrefetching) 4250b57cec5SDimitry Andric addPass(createLoopDataPrefetchPass()); 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric if (TM->getOptLevel() >= CodeGenOpt::Default && EnableGEPOpt) { 4280b57cec5SDimitry Andric // Call SeparateConstOffsetFromGEP pass to extract constants within indices 4290b57cec5SDimitry Andric // and lower a GEP with multiple indices to either arithmetic operations or 4300b57cec5SDimitry Andric // multiple GEPs with single index. 4310b57cec5SDimitry Andric addPass(createSeparateConstOffsetFromGEPPass(true)); 4320b57cec5SDimitry Andric // Call EarlyCSE pass to find and remove subexpressions in the lowered 4330b57cec5SDimitry Andric // result. 4340b57cec5SDimitry Andric addPass(createEarlyCSEPass()); 4350b57cec5SDimitry Andric // Do loop invariant code motion in case part of the lowered result is 4360b57cec5SDimitry Andric // invariant. 4370b57cec5SDimitry Andric addPass(createLICMPass()); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric bool PPCPassConfig::addPreISel() { 4440b57cec5SDimitry Andric if (!DisablePreIncPrep && getOptLevel() != CodeGenOpt::None) 4450b57cec5SDimitry Andric addPass(createPPCLoopPreIncPrepPass(getPPCTargetMachine())); 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None) 4480b57cec5SDimitry Andric addPass(createHardwareLoopsPass()); 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric return false; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric bool PPCPassConfig::addILPOpts() { 4540b57cec5SDimitry Andric addPass(&EarlyIfConverterID); 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric if (EnableMachineCombinerPass) 4570b57cec5SDimitry Andric addPass(&MachineCombinerID); 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric return true; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric bool PPCPassConfig::addInstSelector() { 4630b57cec5SDimitry Andric // Install an instruction selector. 4640b57cec5SDimitry Andric addPass(createPPCISelDag(getPPCTargetMachine(), getOptLevel())); 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric #ifndef NDEBUG 4670b57cec5SDimitry Andric if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None) 4680b57cec5SDimitry Andric addPass(createPPCCTRLoopsVerify()); 4690b57cec5SDimitry Andric #endif 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric addPass(createPPCVSXCopyPass()); 4720b57cec5SDimitry Andric return false; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric void PPCPassConfig::addMachineSSAOptimization() { 4760b57cec5SDimitry Andric // PPCBranchCoalescingPass need to be done before machine sinking 4770b57cec5SDimitry Andric // since it merges empty blocks. 4780b57cec5SDimitry Andric if (EnableBranchCoalescing && getOptLevel() != CodeGenOpt::None) 4790b57cec5SDimitry Andric addPass(createPPCBranchCoalescingPass()); 4800b57cec5SDimitry Andric TargetPassConfig::addMachineSSAOptimization(); 4810b57cec5SDimitry Andric // For little endian, remove where possible the vector swap instructions 4820b57cec5SDimitry Andric // introduced at code generation to normalize vector element order. 4830b57cec5SDimitry Andric if (TM->getTargetTriple().getArch() == Triple::ppc64le && 4840b57cec5SDimitry Andric !DisableVSXSwapRemoval) 4850b57cec5SDimitry Andric addPass(createPPCVSXSwapRemovalPass()); 4860b57cec5SDimitry Andric // Reduce the number of cr-logical ops. 4870b57cec5SDimitry Andric if (ReduceCRLogical && getOptLevel() != CodeGenOpt::None) 4880b57cec5SDimitry Andric addPass(createPPCReduceCRLogicalsPass()); 4890b57cec5SDimitry Andric // Target-specific peephole cleanups performed after instruction 4900b57cec5SDimitry Andric // selection. 4910b57cec5SDimitry Andric if (!DisableMIPeephole) { 4920b57cec5SDimitry Andric addPass(createPPCMIPeepholePass()); 4930b57cec5SDimitry Andric addPass(&DeadMachineInstructionElimID); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric void PPCPassConfig::addPreRegAlloc() { 4980b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 4990b57cec5SDimitry Andric initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry()); 5000b57cec5SDimitry Andric insertPass(VSXFMAMutateEarly ? &RegisterCoalescerID : &MachineSchedulerID, 5010b57cec5SDimitry Andric &PPCVSXFMAMutateID); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric // FIXME: We probably don't need to run these for -fPIE. 5050b57cec5SDimitry Andric if (getPPCTargetMachine().isPositionIndependent()) { 5060b57cec5SDimitry Andric // FIXME: LiveVariables should not be necessary here! 5070b57cec5SDimitry Andric // PPCTLSDynamicCallPass uses LiveIntervals which previously dependent on 5080b57cec5SDimitry Andric // LiveVariables. This (unnecessary) dependency has been removed now, 5090b57cec5SDimitry Andric // however a stage-2 clang build fails without LiveVariables computed here. 5100b57cec5SDimitry Andric addPass(&LiveVariablesID, false); 5110b57cec5SDimitry Andric addPass(createPPCTLSDynamicCallPass()); 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric if (EnableExtraTOCRegDeps) 5140b57cec5SDimitry Andric addPass(createPPCTOCRegDepsPass()); 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) 5170b57cec5SDimitry Andric addPass(&MachinePipelinerID); 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric void PPCPassConfig::addPreSched2() { 5210b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) { 5220b57cec5SDimitry Andric addPass(&IfConverterID); 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric // This optimization must happen after anything that might do store-to-load 5250b57cec5SDimitry Andric // forwarding. Here we're after RA (and, thus, when spills are inserted) 5260b57cec5SDimitry Andric // but before post-RA scheduling. 5270b57cec5SDimitry Andric if (!DisableQPXLoadSplat) 5280b57cec5SDimitry Andric addPass(createPPCQPXLoadSplatPass()); 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric void PPCPassConfig::addPreEmitPass() { 5330b57cec5SDimitry Andric addPass(createPPCPreEmitPeepholePass()); 5340b57cec5SDimitry Andric addPass(createPPCExpandISELPass()); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric if (getOptLevel() != CodeGenOpt::None) 5370b57cec5SDimitry Andric addPass(createPPCEarlyReturnPass(), false); 5380b57cec5SDimitry Andric // Must run branch selection immediately preceding the asm printer. 5390b57cec5SDimitry Andric addPass(createPPCBranchSelectionPass(), false); 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric TargetTransformInfo 5430b57cec5SDimitry Andric PPCTargetMachine::getTargetTransformInfo(const Function &F) { 5440b57cec5SDimitry Andric return TargetTransformInfo(PPCTTIImpl(this, F)); 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric static MachineSchedRegistry 5480b57cec5SDimitry Andric PPCPreRASchedRegistry("ppc-prera", 5490b57cec5SDimitry Andric "Run PowerPC PreRA specific scheduler", 5500b57cec5SDimitry Andric createPPCMachineScheduler); 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric static MachineSchedRegistry 5530b57cec5SDimitry Andric PPCPostRASchedRegistry("ppc-postra", 5540b57cec5SDimitry Andric "Run PowerPC PostRA specific scheduler", 5550b57cec5SDimitry Andric createPPCPostMachineScheduler); 556