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" 16bdd1243dSDimitry Andric #include "PPCMachineFunctionInfo.h" 170b57cec5SDimitry Andric #include "PPCMachineScheduler.h" 185ffd83dbSDimitry Andric #include "PPCMacroFusion.h" 190b57cec5SDimitry Andric #include "PPCSubtarget.h" 200b57cec5SDimitry Andric #include "PPCTargetObjectFile.h" 210b57cec5SDimitry Andric #include "PPCTargetTransformInfo.h" 220b57cec5SDimitry Andric #include "TargetInfo/PowerPCTargetInfo.h" 230b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 240b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 26e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 27e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 2881ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 29e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h" 30e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/Localizer.h" 31e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 32e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 340b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 350b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 360b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 370b57cec5SDimitry Andric #include "llvm/IR/Function.h" 38e8d8bef9SDimitry Andric #include "llvm/InitializePasses.h" 39349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 400b57cec5SDimitry Andric #include "llvm/Pass.h" 410b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 420b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 430b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 440b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 4506c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 460b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 470b57cec5SDimitry Andric #include <cassert> 480b57cec5SDimitry Andric #include <memory> 49bdd1243dSDimitry Andric #include <optional> 500b57cec5SDimitry Andric #include <string> 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric using namespace llvm; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric static cl::opt<bool> 560b57cec5SDimitry Andric EnableBranchCoalescing("enable-ppc-branch-coalesce", cl::Hidden, 570b57cec5SDimitry Andric cl::desc("enable coalescing of duplicate branches for PPC")); 580b57cec5SDimitry Andric static cl:: 590b57cec5SDimitry Andric opt<bool> DisableCTRLoops("disable-ppc-ctrloops", cl::Hidden, 600b57cec5SDimitry Andric cl::desc("Disable CTR loops for PPC")); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric static cl:: 63480093f4SDimitry Andric opt<bool> DisableInstrFormPrep("disable-ppc-instr-form-prep", cl::Hidden, 64480093f4SDimitry Andric cl::desc("Disable PPC loop instr form prep")); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static cl::opt<bool> 670b57cec5SDimitry Andric VSXFMAMutateEarly("schedule-ppc-vsx-fma-mutation-early", 680b57cec5SDimitry Andric cl::Hidden, cl::desc("Schedule VSX FMA instruction mutation early")); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric static cl:: 710b57cec5SDimitry Andric opt<bool> DisableVSXSwapRemoval("disable-ppc-vsx-swap-removal", cl::Hidden, 720b57cec5SDimitry Andric cl::desc("Disable VSX Swap Removal for PPC")); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric static cl:: 750b57cec5SDimitry Andric opt<bool> DisableMIPeephole("disable-ppc-peephole", cl::Hidden, 760b57cec5SDimitry Andric cl::desc("Disable machine peepholes for PPC")); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric static cl::opt<bool> 790b57cec5SDimitry Andric EnableGEPOpt("ppc-gep-opt", cl::Hidden, 800b57cec5SDimitry Andric cl::desc("Enable optimizations on complex GEPs"), 810b57cec5SDimitry Andric cl::init(true)); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric static cl::opt<bool> 840b57cec5SDimitry Andric EnablePrefetch("enable-ppc-prefetching", 85480093f4SDimitry Andric cl::desc("enable software prefetching on PPC"), 860b57cec5SDimitry Andric cl::init(false), cl::Hidden); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric static cl::opt<bool> 890b57cec5SDimitry Andric EnableExtraTOCRegDeps("enable-ppc-extra-toc-reg-deps", 900b57cec5SDimitry Andric cl::desc("Add extra TOC register dependencies"), 910b57cec5SDimitry Andric cl::init(true), cl::Hidden); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric static cl::opt<bool> 940b57cec5SDimitry Andric EnableMachineCombinerPass("ppc-machine-combiner", 950b57cec5SDimitry Andric cl::desc("Enable the machine combiner pass"), 960b57cec5SDimitry Andric cl::init(true), cl::Hidden); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric static cl::opt<bool> 990b57cec5SDimitry Andric ReduceCRLogical("ppc-reduce-cr-logicals", 1000b57cec5SDimitry Andric cl::desc("Expand eligible cr-logical binary ops to branches"), 1018bcb0991SDimitry Andric cl::init(true), cl::Hidden); 10281ad6265SDimitry Andric 103*5f757f3fSDimitry Andric static cl::opt<bool> MergeStringPool( 104*5f757f3fSDimitry Andric "ppc-merge-string-pool", 105*5f757f3fSDimitry Andric cl::desc("Merge all of the strings in a module into one pool"), 106*5f757f3fSDimitry Andric cl::init(true), cl::Hidden); 107*5f757f3fSDimitry Andric 10881ad6265SDimitry Andric static cl::opt<bool> EnablePPCGenScalarMASSEntries( 10981ad6265SDimitry Andric "enable-ppc-gen-scalar-mass", cl::init(false), 11081ad6265SDimitry Andric cl::desc("Enable lowering math functions to their corresponding MASS " 11181ad6265SDimitry Andric "(scalar) entries"), 11281ad6265SDimitry Andric cl::Hidden); 11381ad6265SDimitry Andric 114480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTarget() { 1150b57cec5SDimitry Andric // Register the targets 1160b57cec5SDimitry Andric RegisterTargetMachine<PPCTargetMachine> A(getThePPC32Target()); 117e8d8bef9SDimitry Andric RegisterTargetMachine<PPCTargetMachine> B(getThePPC32LETarget()); 118e8d8bef9SDimitry Andric RegisterTargetMachine<PPCTargetMachine> C(getThePPC64Target()); 119e8d8bef9SDimitry Andric RegisterTargetMachine<PPCTargetMachine> D(getThePPC64LETarget()); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric PassRegistry &PR = *PassRegistry::getPassRegistry(); 1220b57cec5SDimitry Andric #ifndef NDEBUG 1230b57cec5SDimitry Andric initializePPCCTRLoopsVerifyPass(PR); 1240b57cec5SDimitry Andric #endif 125480093f4SDimitry Andric initializePPCLoopInstrFormPrepPass(PR); 1260b57cec5SDimitry Andric initializePPCTOCRegDepsPass(PR); 1270b57cec5SDimitry Andric initializePPCEarlyReturnPass(PR); 1280b57cec5SDimitry Andric initializePPCVSXCopyPass(PR); 1290b57cec5SDimitry Andric initializePPCVSXFMAMutatePass(PR); 1300b57cec5SDimitry Andric initializePPCVSXSwapRemovalPass(PR); 1310b57cec5SDimitry Andric initializePPCReduceCRLogicalsPass(PR); 1320b57cec5SDimitry Andric initializePPCBSelPass(PR); 1330b57cec5SDimitry Andric initializePPCBranchCoalescingPass(PR); 1340b57cec5SDimitry Andric initializePPCBoolRetToIntPass(PR); 1350b57cec5SDimitry Andric initializePPCExpandISELPass(PR); 1360b57cec5SDimitry Andric initializePPCPreEmitPeepholePass(PR); 1370b57cec5SDimitry Andric initializePPCTLSDynamicCallPass(PR); 1380b57cec5SDimitry Andric initializePPCMIPeepholePass(PR); 139480093f4SDimitry Andric initializePPCLowerMASSVEntriesPass(PR); 14081ad6265SDimitry Andric initializePPCGenScalarMASSEntriesPass(PR); 141fe6060f1SDimitry Andric initializePPCExpandAtomicPseudoPass(PR); 142e8d8bef9SDimitry Andric initializeGlobalISel(PR); 14381ad6265SDimitry Andric initializePPCCTRLoopsPass(PR); 144bdd1243dSDimitry Andric initializePPCDAGToDAGISelPass(PR); 145*5f757f3fSDimitry Andric initializePPCMergeStringPoolPass(PR); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 148fe6060f1SDimitry Andric static bool isLittleEndianTriple(const Triple &T) { 149fe6060f1SDimitry Andric return T.getArch() == Triple::ppc64le || T.getArch() == Triple::ppcle; 150fe6060f1SDimitry Andric } 151fe6060f1SDimitry Andric 1520b57cec5SDimitry Andric /// Return the datalayout string of a subtarget. 1530b57cec5SDimitry Andric static std::string getDataLayoutString(const Triple &T) { 1540b57cec5SDimitry Andric bool is64Bit = T.getArch() == Triple::ppc64 || T.getArch() == Triple::ppc64le; 1550b57cec5SDimitry Andric std::string Ret; 1560b57cec5SDimitry Andric 157e8d8bef9SDimitry Andric // Most PPC* platforms are big endian, PPC(64)LE is little endian. 158fe6060f1SDimitry Andric if (isLittleEndianTriple(T)) 1590b57cec5SDimitry Andric Ret = "e"; 1600b57cec5SDimitry Andric else 1610b57cec5SDimitry Andric Ret = "E"; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric Ret += DataLayout::getManglingComponent(T); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // PPC32 has 32 bit pointers. The PS3 (OS Lv2) is a PPC64 machine with 32 bit 1660b57cec5SDimitry Andric // pointers. 1670b57cec5SDimitry Andric if (!is64Bit || T.getOS() == Triple::Lv2) 1680b57cec5SDimitry Andric Ret += "-p:32:32"; 1690b57cec5SDimitry Andric 17006c3fb27SDimitry Andric // If the target ABI uses function descriptors, then the alignment of function 17106c3fb27SDimitry Andric // pointers depends on the alignment used to emit the descriptor. Otherwise, 17206c3fb27SDimitry Andric // function pointers are aligned to 32 bits because the instructions must be. 17306c3fb27SDimitry Andric if ((T.getArch() == Triple::ppc64 && !T.isPPC64ELFv2ABI())) { 17406c3fb27SDimitry Andric Ret += "-Fi64"; 17506c3fb27SDimitry Andric } else if (T.isOSAIX()) { 17606c3fb27SDimitry Andric Ret += is64Bit ? "-Fi64" : "-Fi32"; 17706c3fb27SDimitry Andric } else { 17806c3fb27SDimitry Andric Ret += "-Fn32"; 17906c3fb27SDimitry Andric } 18006c3fb27SDimitry Andric 1810b57cec5SDimitry Andric // Note, the alignment values for f64 and i64 on ppc64 in Darwin 1820b57cec5SDimitry Andric // documentation are wrong; these are correct (i.e. "what gcc does"). 1830b57cec5SDimitry Andric Ret += "-i64:64"; 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // PPC64 has 32 and 64 bit registers, PPC32 has only 32 bit ones. 1860b57cec5SDimitry Andric if (is64Bit) 1870b57cec5SDimitry Andric Ret += "-n32:64"; 1880b57cec5SDimitry Andric else 1890b57cec5SDimitry Andric Ret += "-n32"; 1900b57cec5SDimitry Andric 191e8d8bef9SDimitry Andric // Specify the vector alignment explicitly. For v256i1 and v512i1, the 192e8d8bef9SDimitry Andric // calculated alignment would be 256*alignment(i1) and 512*alignment(i1), 193e8d8bef9SDimitry Andric // which is 256 and 512 bytes - way over aligned. 194fe6060f1SDimitry Andric if (is64Bit && (T.isOSAIX() || T.isOSLinux())) 195fe6060f1SDimitry Andric Ret += "-S128-v256:256:256-v512:512:512"; 196e8d8bef9SDimitry Andric 1970b57cec5SDimitry Andric return Ret; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 200*5f757f3fSDimitry Andric static std::string computeFSAdditions(StringRef FS, CodeGenOptLevel OL, 2010b57cec5SDimitry Andric const Triple &TT) { 2025ffd83dbSDimitry Andric std::string FullFS = std::string(FS); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // Make sure 64-bit features are available when CPUname is generic 2050b57cec5SDimitry Andric if (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le) { 2060b57cec5SDimitry Andric if (!FullFS.empty()) 2070b57cec5SDimitry Andric FullFS = "+64bit," + FullFS; 2080b57cec5SDimitry Andric else 2090b57cec5SDimitry Andric FullFS = "+64bit"; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 212*5f757f3fSDimitry Andric if (OL >= CodeGenOptLevel::Default) { 2130b57cec5SDimitry Andric if (!FullFS.empty()) 2140b57cec5SDimitry Andric FullFS = "+crbits," + FullFS; 2150b57cec5SDimitry Andric else 2160b57cec5SDimitry Andric FullFS = "+crbits"; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 219*5f757f3fSDimitry Andric if (OL != CodeGenOptLevel::None) { 2200b57cec5SDimitry Andric if (!FullFS.empty()) 2210b57cec5SDimitry Andric FullFS = "+invariant-function-descriptors," + FullFS; 2220b57cec5SDimitry Andric else 2230b57cec5SDimitry Andric FullFS = "+invariant-function-descriptors"; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 226e8d8bef9SDimitry Andric if (TT.isOSAIX()) { 227e8d8bef9SDimitry Andric if (!FullFS.empty()) 228e8d8bef9SDimitry Andric FullFS = "+aix," + FullFS; 229e8d8bef9SDimitry Andric else 230e8d8bef9SDimitry Andric FullFS = "+aix"; 231e8d8bef9SDimitry Andric } 232e8d8bef9SDimitry Andric 2330b57cec5SDimitry Andric return FullFS; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { 2378bcb0991SDimitry Andric if (TT.isOSAIX()) 2388bcb0991SDimitry Andric return std::make_unique<TargetLoweringObjectFileXCOFF>(); 2398bcb0991SDimitry Andric 2408bcb0991SDimitry Andric return std::make_unique<PPC64LinuxTargetObjectFile>(); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, 2440b57cec5SDimitry Andric const TargetOptions &Options) { 245*5f757f3fSDimitry Andric if (Options.MCOptions.getABIName().starts_with("elfv1")) 2460b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv1; 247*5f757f3fSDimitry Andric else if (Options.MCOptions.getABIName().starts_with("elfv2")) 2480b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv2; 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric assert(Options.MCOptions.getABIName().empty() && 2510b57cec5SDimitry Andric "Unknown target-abi option!"); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric switch (TT.getArch()) { 2540b57cec5SDimitry Andric case Triple::ppc64le: 2550b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv2; 2560b57cec5SDimitry Andric case Triple::ppc64: 2571ac55f4cSDimitry Andric if (TT.isPPC64ELFv2ABI()) 258bdd1243dSDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv2; 259bdd1243dSDimitry Andric else 2600b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_ELFv1; 2610b57cec5SDimitry Andric default: 2620b57cec5SDimitry Andric return PPCTargetMachine::PPC_ABI_UNKNOWN; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric static Reloc::Model getEffectiveRelocModel(const Triple &TT, 267bdd1243dSDimitry Andric std::optional<Reloc::Model> RM) { 268*5f757f3fSDimitry Andric if (TT.isOSAIX() && RM && *RM != Reloc::PIC_) 269*5f757f3fSDimitry Andric report_fatal_error("invalid relocation model, AIX only supports PIC", 270*5f757f3fSDimitry Andric false); 2715ffd83dbSDimitry Andric 27281ad6265SDimitry Andric if (RM) 2730b57cec5SDimitry Andric return *RM; 2740b57cec5SDimitry Andric 2755ffd83dbSDimitry Andric // Big Endian PPC and AIX default to PIC. 2765ffd83dbSDimitry Andric if (TT.getArch() == Triple::ppc64 || TT.isOSAIX()) 2770b57cec5SDimitry Andric return Reloc::PIC_; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Rest are static by default. 2800b57cec5SDimitry Andric return Reloc::Static; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 283bdd1243dSDimitry Andric static CodeModel::Model 284bdd1243dSDimitry Andric getEffectivePPCCodeModel(const Triple &TT, std::optional<CodeModel::Model> CM, 2850b57cec5SDimitry Andric bool JIT) { 2860b57cec5SDimitry Andric if (CM) { 2870b57cec5SDimitry Andric if (*CM == CodeModel::Tiny) 2880b57cec5SDimitry Andric report_fatal_error("Target does not support the tiny CodeModel", false); 2890b57cec5SDimitry Andric if (*CM == CodeModel::Kernel) 2900b57cec5SDimitry Andric report_fatal_error("Target does not support the kernel CodeModel", false); 2910b57cec5SDimitry Andric return *CM; 2920b57cec5SDimitry Andric } 2938bcb0991SDimitry Andric 2948bcb0991SDimitry Andric if (JIT) 2950b57cec5SDimitry Andric return CodeModel::Small; 2968bcb0991SDimitry Andric if (TT.isOSAIX()) 2978bcb0991SDimitry Andric return CodeModel::Small; 2988bcb0991SDimitry Andric 2998bcb0991SDimitry Andric assert(TT.isOSBinFormatELF() && "All remaining PPC OSes are ELF based."); 3008bcb0991SDimitry Andric 3018bcb0991SDimitry Andric if (TT.isArch32Bit()) 3028bcb0991SDimitry Andric return CodeModel::Small; 3038bcb0991SDimitry Andric 3048bcb0991SDimitry Andric assert(TT.isArch64Bit() && "Unsupported PPC architecture."); 3058bcb0991SDimitry Andric return CodeModel::Medium; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric static ScheduleDAGInstrs *createPPCMachineScheduler(MachineSchedContext *C) { 3100b57cec5SDimitry Andric const PPCSubtarget &ST = C->MF->getSubtarget<PPCSubtarget>(); 3110b57cec5SDimitry Andric ScheduleDAGMILive *DAG = 3120b57cec5SDimitry Andric new ScheduleDAGMILive(C, ST.usePPCPreRASchedStrategy() ? 3138bcb0991SDimitry Andric std::make_unique<PPCPreRASchedStrategy>(C) : 3148bcb0991SDimitry Andric std::make_unique<GenericScheduler>(C)); 3150b57cec5SDimitry Andric // add DAG Mutations here. 3160b57cec5SDimitry Andric DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI)); 317e8d8bef9SDimitry Andric if (ST.hasStoreFusion()) 318e8d8bef9SDimitry Andric DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI)); 3195ffd83dbSDimitry Andric if (ST.hasFusion()) 3205ffd83dbSDimitry Andric DAG->addMutation(createPowerPCMacroFusionDAGMutation()); 3215ffd83dbSDimitry Andric 3220b57cec5SDimitry Andric return DAG; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric static ScheduleDAGInstrs *createPPCPostMachineScheduler( 3260b57cec5SDimitry Andric MachineSchedContext *C) { 3270b57cec5SDimitry Andric const PPCSubtarget &ST = C->MF->getSubtarget<PPCSubtarget>(); 3280b57cec5SDimitry Andric ScheduleDAGMI *DAG = 3290b57cec5SDimitry Andric new ScheduleDAGMI(C, ST.usePPCPostRASchedStrategy() ? 3308bcb0991SDimitry Andric std::make_unique<PPCPostRASchedStrategy>(C) : 3318bcb0991SDimitry Andric std::make_unique<PostGenericScheduler>(C), true); 3320b57cec5SDimitry Andric // add DAG Mutations here. 333e8d8bef9SDimitry Andric if (ST.hasStoreFusion()) 334e8d8bef9SDimitry Andric DAG->addMutation(createStoreClusterDAGMutation(DAG->TII, DAG->TRI)); 3355ffd83dbSDimitry Andric if (ST.hasFusion()) 3365ffd83dbSDimitry Andric DAG->addMutation(createPowerPCMacroFusionDAGMutation()); 3370b57cec5SDimitry Andric return DAG; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // The FeatureString here is a little subtle. We are modifying the feature 3410b57cec5SDimitry Andric // string with what are (currently) non-function specific overrides as it goes 3420b57cec5SDimitry Andric // into the LLVMTargetMachine constructor and then using the stored value in the 3430b57cec5SDimitry Andric // Subtarget constructor below it. 3440b57cec5SDimitry Andric PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT, 3450b57cec5SDimitry Andric StringRef CPU, StringRef FS, 3460b57cec5SDimitry Andric const TargetOptions &Options, 347bdd1243dSDimitry Andric std::optional<Reloc::Model> RM, 348bdd1243dSDimitry Andric std::optional<CodeModel::Model> CM, 349*5f757f3fSDimitry Andric CodeGenOptLevel OL, bool JIT) 3500b57cec5SDimitry Andric : LLVMTargetMachine(T, getDataLayoutString(TT), TT, CPU, 3510b57cec5SDimitry Andric computeFSAdditions(FS, OL, TT), Options, 3520b57cec5SDimitry Andric getEffectiveRelocModel(TT, RM), 3530b57cec5SDimitry Andric getEffectivePPCCodeModel(TT, CM, JIT), OL), 3540b57cec5SDimitry Andric TLOF(createTLOF(getTargetTriple())), 355fe6060f1SDimitry Andric TargetABI(computeTargetABI(TT, Options)), 356fe6060f1SDimitry Andric Endianness(isLittleEndianTriple(TT) ? Endian::LITTLE : Endian::BIG) { 3570b57cec5SDimitry Andric initAsmInfo(); 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric PPCTargetMachine::~PPCTargetMachine() = default; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric const PPCSubtarget * 3630b57cec5SDimitry Andric PPCTargetMachine::getSubtargetImpl(const Function &F) const { 3640b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 365bdd1243dSDimitry Andric Attribute TuneAttr = F.getFnAttribute("tune-cpu"); 3660b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 3670b57cec5SDimitry Andric 368e8d8bef9SDimitry Andric std::string CPU = 369e8d8bef9SDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 370bdd1243dSDimitry Andric std::string TuneCPU = 371bdd1243dSDimitry Andric TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU; 372e8d8bef9SDimitry Andric std::string FS = 373e8d8bef9SDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 3760b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 3770b57cec5SDimitry Andric // function before we can generate a subtarget. We also need to use 3780b57cec5SDimitry Andric // it as a key for the subtarget since that can be the only difference 3790b57cec5SDimitry Andric // between two functions. 380fe6060f1SDimitry Andric bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool(); 3810b57cec5SDimitry Andric // If the soft float attribute is set on the function turn on the soft float 3820b57cec5SDimitry Andric // subtarget feature. 3830b57cec5SDimitry Andric if (SoftFloat) 3840b57cec5SDimitry Andric FS += FS.empty() ? "-hard-float" : ",-hard-float"; 3850b57cec5SDimitry Andric 386bdd1243dSDimitry Andric auto &I = SubtargetMap[CPU + TuneCPU + FS]; 3870b57cec5SDimitry Andric if (!I) { 3880b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 3890b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 3900b57cec5SDimitry Andric // function that reside in TargetOptions. 3910b57cec5SDimitry Andric resetTargetOptions(F); 3928bcb0991SDimitry Andric I = std::make_unique<PPCSubtarget>( 393bdd1243dSDimitry Andric TargetTriple, CPU, TuneCPU, 3940b57cec5SDimitry Andric // FIXME: It would be good to have the subtarget additions here 3950b57cec5SDimitry Andric // not necessary. Anything that turns them on/off (overrides) ends 3960b57cec5SDimitry Andric // up being put at the end of the feature string, but the defaults 3970b57cec5SDimitry Andric // shouldn't require adding them. Fixing this means pulling Feature64Bit 3980b57cec5SDimitry Andric // out of most of the target cpus in the .td file and making it set only 3990b57cec5SDimitry Andric // as part of initialization via the TargetTriple. 4000b57cec5SDimitry Andric computeFSAdditions(FS, getOptLevel(), getTargetTriple()), *this); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric return I.get(); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4060b57cec5SDimitry Andric // Pass Pipeline Configuration 4070b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric namespace { 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric /// PPC Code Generator Pass Configuration Options. 4120b57cec5SDimitry Andric class PPCPassConfig : public TargetPassConfig { 4130b57cec5SDimitry Andric public: 4140b57cec5SDimitry Andric PPCPassConfig(PPCTargetMachine &TM, PassManagerBase &PM) 4150b57cec5SDimitry Andric : TargetPassConfig(TM, PM) { 4160b57cec5SDimitry Andric // At any optimization level above -O0 we use the Machine Scheduler and not 4170b57cec5SDimitry Andric // the default Post RA List Scheduler. 418*5f757f3fSDimitry Andric if (TM.getOptLevel() != CodeGenOptLevel::None) 4190b57cec5SDimitry Andric substitutePass(&PostRASchedulerID, &PostMachineSchedulerID); 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric PPCTargetMachine &getPPCTargetMachine() const { 4230b57cec5SDimitry Andric return getTM<PPCTargetMachine>(); 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric void addIRPasses() override; 4270b57cec5SDimitry Andric bool addPreISel() override; 4280b57cec5SDimitry Andric bool addILPOpts() override; 4290b57cec5SDimitry Andric bool addInstSelector() override; 4300b57cec5SDimitry Andric void addMachineSSAOptimization() override; 4310b57cec5SDimitry Andric void addPreRegAlloc() override; 4320b57cec5SDimitry Andric void addPreSched2() override; 4330b57cec5SDimitry Andric void addPreEmitPass() override; 434fe6060f1SDimitry Andric void addPreEmitPass2() override; 435e8d8bef9SDimitry Andric // GlobalISEL 436e8d8bef9SDimitry Andric bool addIRTranslator() override; 437e8d8bef9SDimitry Andric bool addLegalizeMachineIR() override; 438e8d8bef9SDimitry Andric bool addRegBankSelect() override; 439e8d8bef9SDimitry Andric bool addGlobalInstructionSelect() override; 440e8d8bef9SDimitry Andric 4410b57cec5SDimitry Andric ScheduleDAGInstrs * 4420b57cec5SDimitry Andric createMachineScheduler(MachineSchedContext *C) const override { 4430b57cec5SDimitry Andric return createPPCMachineScheduler(C); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric ScheduleDAGInstrs * 4460b57cec5SDimitry Andric createPostMachineScheduler(MachineSchedContext *C) const override { 4470b57cec5SDimitry Andric return createPPCPostMachineScheduler(C); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric }; 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric } // end anonymous namespace 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) { 4540b57cec5SDimitry Andric return new PPCPassConfig(*this, PM); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric void PPCPassConfig::addIRPasses() { 458*5f757f3fSDimitry Andric if (TM->getOptLevel() != CodeGenOptLevel::None) 4590b57cec5SDimitry Andric addPass(createPPCBoolRetToIntPass()); 4600b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 4610b57cec5SDimitry Andric 462480093f4SDimitry Andric // Lower generic MASSV routines to PowerPC subtarget-specific entries. 463480093f4SDimitry Andric addPass(createPPCLowerMASSVEntriesPass()); 464480093f4SDimitry Andric 46581ad6265SDimitry Andric // Generate PowerPC target-specific entries for scalar math functions 46681ad6265SDimitry Andric // that are available in IBM MASS (scalar) library. 467*5f757f3fSDimitry Andric if (TM->getOptLevel() == CodeGenOptLevel::Aggressive && 46881ad6265SDimitry Andric EnablePPCGenScalarMASSEntries) { 46981ad6265SDimitry Andric TM->Options.PPCGenScalarMASSEntries = EnablePPCGenScalarMASSEntries; 47081ad6265SDimitry Andric addPass(createPPCGenScalarMASSEntriesPass()); 47181ad6265SDimitry Andric } 47281ad6265SDimitry Andric 473e8d8bef9SDimitry Andric // If explicitly requested, add explicit data prefetch intrinsics. 4740b57cec5SDimitry Andric if (EnablePrefetch.getNumOccurrences() > 0) 4750b57cec5SDimitry Andric addPass(createLoopDataPrefetchPass()); 4760b57cec5SDimitry Andric 477*5f757f3fSDimitry Andric if (TM->getOptLevel() >= CodeGenOptLevel::Default && EnableGEPOpt) { 4780b57cec5SDimitry Andric // Call SeparateConstOffsetFromGEP pass to extract constants within indices 4790b57cec5SDimitry Andric // and lower a GEP with multiple indices to either arithmetic operations or 4800b57cec5SDimitry Andric // multiple GEPs with single index. 4810b57cec5SDimitry Andric addPass(createSeparateConstOffsetFromGEPPass(true)); 4820b57cec5SDimitry Andric // Call EarlyCSE pass to find and remove subexpressions in the lowered 4830b57cec5SDimitry Andric // result. 4840b57cec5SDimitry Andric addPass(createEarlyCSEPass()); 4850b57cec5SDimitry Andric // Do loop invariant code motion in case part of the lowered result is 4860b57cec5SDimitry Andric // invariant. 4870b57cec5SDimitry Andric addPass(createLICMPass()); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric bool PPCPassConfig::addPreISel() { 494*5f757f3fSDimitry Andric if (MergeStringPool && getOptLevel() != CodeGenOptLevel::None) 495*5f757f3fSDimitry Andric addPass(createPPCMergeStringPoolPass()); 496*5f757f3fSDimitry Andric 497*5f757f3fSDimitry Andric if (!DisableInstrFormPrep && getOptLevel() != CodeGenOptLevel::None) 498480093f4SDimitry Andric addPass(createPPCLoopInstrFormPrepPass(getPPCTargetMachine())); 4990b57cec5SDimitry Andric 500*5f757f3fSDimitry Andric if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None) 50106c3fb27SDimitry Andric addPass(createHardwareLoopsLegacyPass()); 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric return false; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric bool PPCPassConfig::addILPOpts() { 5070b57cec5SDimitry Andric addPass(&EarlyIfConverterID); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric if (EnableMachineCombinerPass) 5100b57cec5SDimitry Andric addPass(&MachineCombinerID); 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric return true; 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric bool PPCPassConfig::addInstSelector() { 5160b57cec5SDimitry Andric // Install an instruction selector. 5170b57cec5SDimitry Andric addPass(createPPCISelDag(getPPCTargetMachine(), getOptLevel())); 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric #ifndef NDEBUG 520*5f757f3fSDimitry Andric if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None) 5210b57cec5SDimitry Andric addPass(createPPCCTRLoopsVerify()); 5220b57cec5SDimitry Andric #endif 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric addPass(createPPCVSXCopyPass()); 5250b57cec5SDimitry Andric return false; 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric void PPCPassConfig::addMachineSSAOptimization() { 529bdd1243dSDimitry Andric // Run CTR loops pass before any cfg modification pass to prevent the 530bdd1243dSDimitry Andric // canonical form of hardware loop from being destroied. 531*5f757f3fSDimitry Andric if (!DisableCTRLoops && getOptLevel() != CodeGenOptLevel::None) 532bdd1243dSDimitry Andric addPass(createPPCCTRLoopsPass()); 533bdd1243dSDimitry Andric 5340b57cec5SDimitry Andric // PPCBranchCoalescingPass need to be done before machine sinking 5350b57cec5SDimitry Andric // since it merges empty blocks. 536*5f757f3fSDimitry Andric if (EnableBranchCoalescing && getOptLevel() != CodeGenOptLevel::None) 5370b57cec5SDimitry Andric addPass(createPPCBranchCoalescingPass()); 5380b57cec5SDimitry Andric TargetPassConfig::addMachineSSAOptimization(); 5390b57cec5SDimitry Andric // For little endian, remove where possible the vector swap instructions 5400b57cec5SDimitry Andric // introduced at code generation to normalize vector element order. 5410b57cec5SDimitry Andric if (TM->getTargetTriple().getArch() == Triple::ppc64le && 5420b57cec5SDimitry Andric !DisableVSXSwapRemoval) 5430b57cec5SDimitry Andric addPass(createPPCVSXSwapRemovalPass()); 5440b57cec5SDimitry Andric // Reduce the number of cr-logical ops. 545*5f757f3fSDimitry Andric if (ReduceCRLogical && getOptLevel() != CodeGenOptLevel::None) 5460b57cec5SDimitry Andric addPass(createPPCReduceCRLogicalsPass()); 5470b57cec5SDimitry Andric // Target-specific peephole cleanups performed after instruction 5480b57cec5SDimitry Andric // selection. 5490b57cec5SDimitry Andric if (!DisableMIPeephole) { 5500b57cec5SDimitry Andric addPass(createPPCMIPeepholePass()); 5510b57cec5SDimitry Andric addPass(&DeadMachineInstructionElimID); 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric void PPCPassConfig::addPreRegAlloc() { 556*5f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) { 5570b57cec5SDimitry Andric initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry()); 5580b57cec5SDimitry Andric insertPass(VSXFMAMutateEarly ? &RegisterCoalescerID : &MachineSchedulerID, 5590b57cec5SDimitry Andric &PPCVSXFMAMutateID); 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // FIXME: We probably don't need to run these for -fPIE. 5630b57cec5SDimitry Andric if (getPPCTargetMachine().isPositionIndependent()) { 5640b57cec5SDimitry Andric // FIXME: LiveVariables should not be necessary here! 5650b57cec5SDimitry Andric // PPCTLSDynamicCallPass uses LiveIntervals which previously dependent on 5660b57cec5SDimitry Andric // LiveVariables. This (unnecessary) dependency has been removed now, 5670b57cec5SDimitry Andric // however a stage-2 clang build fails without LiveVariables computed here. 5685ffd83dbSDimitry Andric addPass(&LiveVariablesID); 5690b57cec5SDimitry Andric addPass(createPPCTLSDynamicCallPass()); 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric if (EnableExtraTOCRegDeps) 5720b57cec5SDimitry Andric addPass(createPPCTOCRegDepsPass()); 5730b57cec5SDimitry Andric 574*5f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) 5750b57cec5SDimitry Andric addPass(&MachinePipelinerID); 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric void PPCPassConfig::addPreSched2() { 579*5f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) 5800b57cec5SDimitry Andric addPass(&IfConverterID); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric void PPCPassConfig::addPreEmitPass() { 5840b57cec5SDimitry Andric addPass(createPPCPreEmitPeepholePass()); 5850b57cec5SDimitry Andric addPass(createPPCExpandISELPass()); 5860b57cec5SDimitry Andric 587*5f757f3fSDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) 5885ffd83dbSDimitry Andric addPass(createPPCEarlyReturnPass()); 589fe6060f1SDimitry Andric } 590fe6060f1SDimitry Andric 591fe6060f1SDimitry Andric void PPCPassConfig::addPreEmitPass2() { 592fe6060f1SDimitry Andric // Schedule the expansion of AMOs at the last possible moment, avoiding the 593fe6060f1SDimitry Andric // possibility for other passes to break the requirements for forward 594fe6060f1SDimitry Andric // progress in the LL/SC block. 595fe6060f1SDimitry Andric addPass(createPPCExpandAtomicPseudoPass()); 5960b57cec5SDimitry Andric // Must run branch selection immediately preceding the asm printer. 5975ffd83dbSDimitry Andric addPass(createPPCBranchSelectionPass()); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric TargetTransformInfo 60181ad6265SDimitry Andric PPCTargetMachine::getTargetTransformInfo(const Function &F) const { 6020b57cec5SDimitry Andric return TargetTransformInfo(PPCTTIImpl(this, F)); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 605fe6060f1SDimitry Andric bool PPCTargetMachine::isLittleEndian() const { 606fe6060f1SDimitry Andric assert(Endianness != Endian::NOT_DETECTED && 607fe6060f1SDimitry Andric "Unable to determine endianness"); 608fe6060f1SDimitry Andric return Endianness == Endian::LITTLE; 609fe6060f1SDimitry Andric } 610fe6060f1SDimitry Andric 611bdd1243dSDimitry Andric MachineFunctionInfo *PPCTargetMachine::createMachineFunctionInfo( 612bdd1243dSDimitry Andric BumpPtrAllocator &Allocator, const Function &F, 613bdd1243dSDimitry Andric const TargetSubtargetInfo *STI) const { 614bdd1243dSDimitry Andric return PPCFunctionInfo::create<PPCFunctionInfo>(Allocator, F, STI); 615bdd1243dSDimitry Andric } 616bdd1243dSDimitry Andric 6170b57cec5SDimitry Andric static MachineSchedRegistry 6180b57cec5SDimitry Andric PPCPreRASchedRegistry("ppc-prera", 6190b57cec5SDimitry Andric "Run PowerPC PreRA specific scheduler", 6200b57cec5SDimitry Andric createPPCMachineScheduler); 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric static MachineSchedRegistry 6230b57cec5SDimitry Andric PPCPostRASchedRegistry("ppc-postra", 6240b57cec5SDimitry Andric "Run PowerPC PostRA specific scheduler", 6250b57cec5SDimitry Andric createPPCPostMachineScheduler); 626e8d8bef9SDimitry Andric 627e8d8bef9SDimitry Andric // Global ISEL 628e8d8bef9SDimitry Andric bool PPCPassConfig::addIRTranslator() { 629e8d8bef9SDimitry Andric addPass(new IRTranslator()); 630e8d8bef9SDimitry Andric return false; 631e8d8bef9SDimitry Andric } 632e8d8bef9SDimitry Andric 633e8d8bef9SDimitry Andric bool PPCPassConfig::addLegalizeMachineIR() { 634e8d8bef9SDimitry Andric addPass(new Legalizer()); 635e8d8bef9SDimitry Andric return false; 636e8d8bef9SDimitry Andric } 637e8d8bef9SDimitry Andric 638e8d8bef9SDimitry Andric bool PPCPassConfig::addRegBankSelect() { 639e8d8bef9SDimitry Andric addPass(new RegBankSelect()); 640e8d8bef9SDimitry Andric return false; 641e8d8bef9SDimitry Andric } 642e8d8bef9SDimitry Andric 643e8d8bef9SDimitry Andric bool PPCPassConfig::addGlobalInstructionSelect() { 644fe6060f1SDimitry Andric addPass(new InstructionSelect(getOptLevel())); 645e8d8bef9SDimitry Andric return false; 646e8d8bef9SDimitry Andric } 647