10b57cec5SDimitry Andric //===-- PPCInstrInfo.cpp - PowerPC Instruction Information ----------------===// 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 // This file contains the PowerPC implementation of the TargetInstrInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "PPCInstrInfo.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/PPCPredicates.h" 150b57cec5SDimitry Andric #include "PPC.h" 160b57cec5SDimitry Andric #include "PPCHazardRecognizers.h" 170b57cec5SDimitry Andric #include "PPCInstrBuilder.h" 180b57cec5SDimitry Andric #include "PPCMachineFunctionInfo.h" 190b57cec5SDimitry Andric #include "PPCTargetMachine.h" 200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 210b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 225ffd83dbSDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 245f757f3fSDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 25bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineCombinerPattern.h" 26e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h" 33e8d8bef9SDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h" 34e8d8bef9SDimitry Andric #include "llvm/CodeGen/RegisterPressure.h" 350b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 360b57cec5SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h" 370b57cec5SDimitry Andric #include "llvm/CodeGen/StackMaps.h" 380b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 390b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 40349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 410b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 420b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 430b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 440b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric using namespace llvm; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-instr-info" 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric #define GET_INSTRMAP_INFO 510b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR 520b57cec5SDimitry Andric #include "PPCGenInstrInfo.inc" 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric STATISTIC(NumStoreSPILLVSRRCAsVec, 550b57cec5SDimitry Andric "Number of spillvsrrc spilled to stack as vec"); 560b57cec5SDimitry Andric STATISTIC(NumStoreSPILLVSRRCAsGpr, 570b57cec5SDimitry Andric "Number of spillvsrrc spilled to stack as gpr"); 580b57cec5SDimitry Andric STATISTIC(NumGPRtoVSRSpill, "Number of gpr spills to spillvsrrc"); 590b57cec5SDimitry Andric STATISTIC(CmpIselsConverted, 600b57cec5SDimitry Andric "Number of ISELs that depend on comparison of constants converted"); 610b57cec5SDimitry Andric STATISTIC(MissedConvertibleImmediateInstrs, 620b57cec5SDimitry Andric "Number of compare-immediate instructions fed by constants"); 630b57cec5SDimitry Andric STATISTIC(NumRcRotatesConvertedToRcAnd, 640b57cec5SDimitry Andric "Number of record-form rotates converted to record-form andi"); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static cl:: 670b57cec5SDimitry Andric opt<bool> DisableCTRLoopAnal("disable-ppc-ctrloop-analysis", cl::Hidden, 680b57cec5SDimitry Andric cl::desc("Disable analysis for CTR loops")); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric static cl::opt<bool> DisableCmpOpt("disable-ppc-cmp-opt", 710b57cec5SDimitry Andric cl::desc("Disable compare instruction optimization"), cl::Hidden); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric static cl::opt<bool> VSXSelfCopyCrash("crash-on-ppc-vsx-self-copy", 740b57cec5SDimitry Andric cl::desc("Causes the backend to crash instead of generating a nop VSX copy"), 750b57cec5SDimitry Andric cl::Hidden); 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric static cl::opt<bool> 780b57cec5SDimitry Andric UseOldLatencyCalc("ppc-old-latency-calc", cl::Hidden, 790b57cec5SDimitry Andric cl::desc("Use the old (incorrect) instruction latency calculation")); 800b57cec5SDimitry Andric 81e8d8bef9SDimitry Andric static cl::opt<float> 82e8d8bef9SDimitry Andric FMARPFactor("ppc-fma-rp-factor", cl::Hidden, cl::init(1.5), 83e8d8bef9SDimitry Andric cl::desc("register pressure factor for the transformations.")); 84e8d8bef9SDimitry Andric 85e8d8bef9SDimitry Andric static cl::opt<bool> EnableFMARegPressureReduction( 86e8d8bef9SDimitry Andric "ppc-fma-rp-reduction", cl::Hidden, cl::init(true), 87e8d8bef9SDimitry Andric cl::desc("enable register pressure reduce in machine combiner pass.")); 88e8d8bef9SDimitry Andric 890b57cec5SDimitry Andric // Pin the vtable to this file. 900b57cec5SDimitry Andric void PPCInstrInfo::anchor() {} 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric PPCInstrInfo::PPCInstrInfo(PPCSubtarget &STI) 930b57cec5SDimitry Andric : PPCGenInstrInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP, 940b57cec5SDimitry Andric /* CatchRetOpcode */ -1, 950b57cec5SDimitry Andric STI.isPPC64() ? PPC::BLR8 : PPC::BLR), 960b57cec5SDimitry Andric Subtarget(STI), RI(STI.getTargetMachine()) {} 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for 990b57cec5SDimitry Andric /// this target when scheduling the DAG. 1000b57cec5SDimitry Andric ScheduleHazardRecognizer * 1010b57cec5SDimitry Andric PPCInstrInfo::CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, 1020b57cec5SDimitry Andric const ScheduleDAG *DAG) const { 1030b57cec5SDimitry Andric unsigned Directive = 104480093f4SDimitry Andric static_cast<const PPCSubtarget *>(STI)->getCPUDirective(); 1050b57cec5SDimitry Andric if (Directive == PPC::DIR_440 || Directive == PPC::DIR_A2 || 1060b57cec5SDimitry Andric Directive == PPC::DIR_E500mc || Directive == PPC::DIR_E5500) { 1070b57cec5SDimitry Andric const InstrItineraryData *II = 1080b57cec5SDimitry Andric static_cast<const PPCSubtarget *>(STI)->getInstrItineraryData(); 1090b57cec5SDimitry Andric return new ScoreboardHazardRecognizer(II, DAG); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric return TargetInstrInfo::CreateTargetHazardRecognizer(STI, DAG); 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /// CreateTargetPostRAHazardRecognizer - Return the postRA hazard recognizer 1160b57cec5SDimitry Andric /// to use for this target when scheduling the DAG. 1170b57cec5SDimitry Andric ScheduleHazardRecognizer * 1180b57cec5SDimitry Andric PPCInstrInfo::CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, 1190b57cec5SDimitry Andric const ScheduleDAG *DAG) const { 1200b57cec5SDimitry Andric unsigned Directive = 121480093f4SDimitry Andric DAG->MF.getSubtarget<PPCSubtarget>().getCPUDirective(); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric // FIXME: Leaving this as-is until we have POWER9 scheduling info 1240b57cec5SDimitry Andric if (Directive == PPC::DIR_PWR7 || Directive == PPC::DIR_PWR8) 1250b57cec5SDimitry Andric return new PPCDispatchGroupSBHazardRecognizer(II, DAG); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric // Most subtargets use a PPC970 recognizer. 1280b57cec5SDimitry Andric if (Directive != PPC::DIR_440 && Directive != PPC::DIR_A2 && 1290b57cec5SDimitry Andric Directive != PPC::DIR_E500mc && Directive != PPC::DIR_E5500) { 1300b57cec5SDimitry Andric assert(DAG->TII && "No InstrInfo?"); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric return new PPCHazardRecognizer970(*DAG); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric return new ScoreboardHazardRecognizer(II, DAG); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric unsigned PPCInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, 1390b57cec5SDimitry Andric const MachineInstr &MI, 1400b57cec5SDimitry Andric unsigned *PredCost) const { 1410b57cec5SDimitry Andric if (!ItinData || UseOldLatencyCalc) 1420b57cec5SDimitry Andric return PPCGenInstrInfo::getInstrLatency(ItinData, MI, PredCost); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // The default implementation of getInstrLatency calls getStageLatency, but 1450b57cec5SDimitry Andric // getStageLatency does not do the right thing for us. While we have 1460b57cec5SDimitry Andric // itinerary, most cores are fully pipelined, and so the itineraries only 1470b57cec5SDimitry Andric // express the first part of the pipeline, not every stage. Instead, we need 1480b57cec5SDimitry Andric // to use the listed output operand cycle number (using operand 0 here, which 1490b57cec5SDimitry Andric // is an output). 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric unsigned Latency = 1; 1520b57cec5SDimitry Andric unsigned DefClass = MI.getDesc().getSchedClass(); 1530b57cec5SDimitry Andric for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { 1540b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(i); 1550b57cec5SDimitry Andric if (!MO.isReg() || !MO.isDef() || MO.isImplicit()) 1560b57cec5SDimitry Andric continue; 1570b57cec5SDimitry Andric 1585f757f3fSDimitry Andric std::optional<unsigned> Cycle = ItinData->getOperandCycle(DefClass, i); 1595f757f3fSDimitry Andric if (!Cycle) 1600b57cec5SDimitry Andric continue; 1610b57cec5SDimitry Andric 1625f757f3fSDimitry Andric Latency = std::max(Latency, *Cycle); 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric return Latency; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1685f757f3fSDimitry Andric std::optional<unsigned> PPCInstrInfo::getOperandLatency( 1695f757f3fSDimitry Andric const InstrItineraryData *ItinData, const MachineInstr &DefMI, 1705f757f3fSDimitry Andric unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const { 1715f757f3fSDimitry Andric std::optional<unsigned> Latency = PPCGenInstrInfo::getOperandLatency( 1725f757f3fSDimitry Andric ItinData, DefMI, DefIdx, UseMI, UseIdx); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric if (!DefMI.getParent()) 1750b57cec5SDimitry Andric return Latency; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric const MachineOperand &DefMO = DefMI.getOperand(DefIdx); 1788bcb0991SDimitry Andric Register Reg = DefMO.getReg(); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric bool IsRegCR; 181bdd1243dSDimitry Andric if (Reg.isVirtual()) { 1820b57cec5SDimitry Andric const MachineRegisterInfo *MRI = 1830b57cec5SDimitry Andric &DefMI.getParent()->getParent()->getRegInfo(); 1840b57cec5SDimitry Andric IsRegCR = MRI->getRegClass(Reg)->hasSuperClassEq(&PPC::CRRCRegClass) || 1850b57cec5SDimitry Andric MRI->getRegClass(Reg)->hasSuperClassEq(&PPC::CRBITRCRegClass); 1860b57cec5SDimitry Andric } else { 1870b57cec5SDimitry Andric IsRegCR = PPC::CRRCRegClass.contains(Reg) || 1880b57cec5SDimitry Andric PPC::CRBITRCRegClass.contains(Reg); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric if (UseMI.isBranch() && IsRegCR) { 1925f757f3fSDimitry Andric if (!Latency) 1930b57cec5SDimitry Andric Latency = getInstrLatency(ItinData, DefMI); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // On some cores, there is an additional delay between writing to a condition 1960b57cec5SDimitry Andric // register, and using it from a branch. 197480093f4SDimitry Andric unsigned Directive = Subtarget.getCPUDirective(); 1980b57cec5SDimitry Andric switch (Directive) { 1990b57cec5SDimitry Andric default: break; 2000b57cec5SDimitry Andric case PPC::DIR_7400: 2010b57cec5SDimitry Andric case PPC::DIR_750: 2020b57cec5SDimitry Andric case PPC::DIR_970: 2030b57cec5SDimitry Andric case PPC::DIR_E5500: 2040b57cec5SDimitry Andric case PPC::DIR_PWR4: 2050b57cec5SDimitry Andric case PPC::DIR_PWR5: 2060b57cec5SDimitry Andric case PPC::DIR_PWR5X: 2070b57cec5SDimitry Andric case PPC::DIR_PWR6: 2080b57cec5SDimitry Andric case PPC::DIR_PWR6X: 2090b57cec5SDimitry Andric case PPC::DIR_PWR7: 2100b57cec5SDimitry Andric case PPC::DIR_PWR8: 2110b57cec5SDimitry Andric // FIXME: Is this needed for POWER9? 2125f757f3fSDimitry Andric Latency = *Latency + 2; 2130b57cec5SDimitry Andric break; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric return Latency; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2205ffd83dbSDimitry Andric void PPCInstrInfo::setSpecialOperandAttr(MachineInstr &MI, 22106c3fb27SDimitry Andric uint32_t Flags) const { 2225ffd83dbSDimitry Andric MI.setFlags(Flags); 2235ffd83dbSDimitry Andric MI.clearFlag(MachineInstr::MIFlag::NoSWrap); 2245ffd83dbSDimitry Andric MI.clearFlag(MachineInstr::MIFlag::NoUWrap); 2255ffd83dbSDimitry Andric MI.clearFlag(MachineInstr::MIFlag::IsExact); 2265ffd83dbSDimitry Andric } 2275ffd83dbSDimitry Andric 2280b57cec5SDimitry Andric // This function does not list all associative and commutative operations, but 2290b57cec5SDimitry Andric // only those worth feeding through the machine combiner in an attempt to 2300b57cec5SDimitry Andric // reduce the critical path. Mostly, this means floating-point operations, 2315ffd83dbSDimitry Andric // because they have high latencies(>=5) (compared to other operations, such as 2320b57cec5SDimitry Andric // and/or, which are also associative and commutative, but have low latencies). 233bdd1243dSDimitry Andric bool PPCInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst, 234bdd1243dSDimitry Andric bool Invert) const { 235bdd1243dSDimitry Andric if (Invert) 236bdd1243dSDimitry Andric return false; 2370b57cec5SDimitry Andric switch (Inst.getOpcode()) { 2385ffd83dbSDimitry Andric // Floating point: 2390b57cec5SDimitry Andric // FP Add: 2400b57cec5SDimitry Andric case PPC::FADD: 2410b57cec5SDimitry Andric case PPC::FADDS: 2420b57cec5SDimitry Andric // FP Multiply: 2430b57cec5SDimitry Andric case PPC::FMUL: 2440b57cec5SDimitry Andric case PPC::FMULS: 2450b57cec5SDimitry Andric // Altivec Add: 2460b57cec5SDimitry Andric case PPC::VADDFP: 2470b57cec5SDimitry Andric // VSX Add: 2480b57cec5SDimitry Andric case PPC::XSADDDP: 2490b57cec5SDimitry Andric case PPC::XVADDDP: 2500b57cec5SDimitry Andric case PPC::XVADDSP: 2510b57cec5SDimitry Andric case PPC::XSADDSP: 2520b57cec5SDimitry Andric // VSX Multiply: 2530b57cec5SDimitry Andric case PPC::XSMULDP: 2540b57cec5SDimitry Andric case PPC::XVMULDP: 2550b57cec5SDimitry Andric case PPC::XVMULSP: 2560b57cec5SDimitry Andric case PPC::XSMULSP: 2575ffd83dbSDimitry Andric return Inst.getFlag(MachineInstr::MIFlag::FmReassoc) && 2585ffd83dbSDimitry Andric Inst.getFlag(MachineInstr::MIFlag::FmNsz); 2595ffd83dbSDimitry Andric // Fixed point: 2605ffd83dbSDimitry Andric // Multiply: 2615ffd83dbSDimitry Andric case PPC::MULHD: 2625ffd83dbSDimitry Andric case PPC::MULLD: 2635ffd83dbSDimitry Andric case PPC::MULHW: 2645ffd83dbSDimitry Andric case PPC::MULLW: 2650b57cec5SDimitry Andric return true; 2660b57cec5SDimitry Andric default: 2670b57cec5SDimitry Andric return false; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2715ffd83dbSDimitry Andric #define InfoArrayIdxFMAInst 0 2725ffd83dbSDimitry Andric #define InfoArrayIdxFAddInst 1 2735ffd83dbSDimitry Andric #define InfoArrayIdxFMULInst 2 2745ffd83dbSDimitry Andric #define InfoArrayIdxAddOpIdx 3 2755ffd83dbSDimitry Andric #define InfoArrayIdxMULOpIdx 4 276e8d8bef9SDimitry Andric #define InfoArrayIdxFSubInst 5 2775ffd83dbSDimitry Andric // Array keeps info for FMA instructions: 2785ffd83dbSDimitry Andric // Index 0(InfoArrayIdxFMAInst): FMA instruction; 279e8d8bef9SDimitry Andric // Index 1(InfoArrayIdxFAddInst): ADD instruction associated with FMA; 280e8d8bef9SDimitry Andric // Index 2(InfoArrayIdxFMULInst): MUL instruction associated with FMA; 2815ffd83dbSDimitry Andric // Index 3(InfoArrayIdxAddOpIdx): ADD operand index in FMA operands; 2825ffd83dbSDimitry Andric // Index 4(InfoArrayIdxMULOpIdx): first MUL operand index in FMA operands; 283e8d8bef9SDimitry Andric // second MUL operand index is plus 1; 284e8d8bef9SDimitry Andric // Index 5(InfoArrayIdxFSubInst): SUB instruction associated with FMA. 285e8d8bef9SDimitry Andric static const uint16_t FMAOpIdxInfo[][6] = { 2865ffd83dbSDimitry Andric // FIXME: Add more FMA instructions like XSNMADDADP and so on. 287e8d8bef9SDimitry Andric {PPC::XSMADDADP, PPC::XSADDDP, PPC::XSMULDP, 1, 2, PPC::XSSUBDP}, 288e8d8bef9SDimitry Andric {PPC::XSMADDASP, PPC::XSADDSP, PPC::XSMULSP, 1, 2, PPC::XSSUBSP}, 289e8d8bef9SDimitry Andric {PPC::XVMADDADP, PPC::XVADDDP, PPC::XVMULDP, 1, 2, PPC::XVSUBDP}, 290e8d8bef9SDimitry Andric {PPC::XVMADDASP, PPC::XVADDSP, PPC::XVMULSP, 1, 2, PPC::XVSUBSP}, 291e8d8bef9SDimitry Andric {PPC::FMADD, PPC::FADD, PPC::FMUL, 3, 1, PPC::FSUB}, 292e8d8bef9SDimitry Andric {PPC::FMADDS, PPC::FADDS, PPC::FMULS, 3, 1, PPC::FSUBS}}; 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric // Check if an opcode is a FMA instruction. If it is, return the index in array 2955ffd83dbSDimitry Andric // FMAOpIdxInfo. Otherwise, return -1. 2965ffd83dbSDimitry Andric int16_t PPCInstrInfo::getFMAOpIdxInfo(unsigned Opcode) const { 297bdd1243dSDimitry Andric for (unsigned I = 0; I < std::size(FMAOpIdxInfo); I++) 2985ffd83dbSDimitry Andric if (FMAOpIdxInfo[I][InfoArrayIdxFMAInst] == Opcode) 2995ffd83dbSDimitry Andric return I; 3005ffd83dbSDimitry Andric return -1; 3015ffd83dbSDimitry Andric } 3025ffd83dbSDimitry Andric 303e8d8bef9SDimitry Andric // On PowerPC target, we have two kinds of patterns related to FMA: 304e8d8bef9SDimitry Andric // 1: Improve ILP. 3055ffd83dbSDimitry Andric // Try to reassociate FMA chains like below: 3065ffd83dbSDimitry Andric // 3075ffd83dbSDimitry Andric // Pattern 1: 3085ffd83dbSDimitry Andric // A = FADD X, Y (Leaf) 3095ffd83dbSDimitry Andric // B = FMA A, M21, M22 (Prev) 3105ffd83dbSDimitry Andric // C = FMA B, M31, M32 (Root) 3115ffd83dbSDimitry Andric // --> 3125ffd83dbSDimitry Andric // A = FMA X, M21, M22 3135ffd83dbSDimitry Andric // B = FMA Y, M31, M32 3145ffd83dbSDimitry Andric // C = FADD A, B 3155ffd83dbSDimitry Andric // 3165ffd83dbSDimitry Andric // Pattern 2: 3175ffd83dbSDimitry Andric // A = FMA X, M11, M12 (Leaf) 3185ffd83dbSDimitry Andric // B = FMA A, M21, M22 (Prev) 3195ffd83dbSDimitry Andric // C = FMA B, M31, M32 (Root) 3205ffd83dbSDimitry Andric // --> 3215ffd83dbSDimitry Andric // A = FMUL M11, M12 3225ffd83dbSDimitry Andric // B = FMA X, M21, M22 3235ffd83dbSDimitry Andric // D = FMA A, M31, M32 3245ffd83dbSDimitry Andric // C = FADD B, D 3255ffd83dbSDimitry Andric // 3265ffd83dbSDimitry Andric // breaking the dependency between A and B, allowing FMA to be executed in 3275ffd83dbSDimitry Andric // parallel (or back-to-back in a pipeline) instead of depending on each other. 328e8d8bef9SDimitry Andric // 329e8d8bef9SDimitry Andric // 2: Reduce register pressure. 330e8d8bef9SDimitry Andric // Try to reassociate FMA with FSUB and a constant like below: 331fe6060f1SDimitry Andric // C is a floating point const. 332e8d8bef9SDimitry Andric // 333e8d8bef9SDimitry Andric // Pattern 1: 334e8d8bef9SDimitry Andric // A = FSUB X, Y (Leaf) 335e8d8bef9SDimitry Andric // D = FMA B, C, A (Root) 336e8d8bef9SDimitry Andric // --> 337e8d8bef9SDimitry Andric // A = FMA B, Y, -C 338e8d8bef9SDimitry Andric // D = FMA A, X, C 339e8d8bef9SDimitry Andric // 340e8d8bef9SDimitry Andric // Pattern 2: 341e8d8bef9SDimitry Andric // A = FSUB X, Y (Leaf) 342e8d8bef9SDimitry Andric // D = FMA B, A, C (Root) 343e8d8bef9SDimitry Andric // --> 344e8d8bef9SDimitry Andric // A = FMA B, Y, -C 345e8d8bef9SDimitry Andric // D = FMA A, X, C 346e8d8bef9SDimitry Andric // 347e8d8bef9SDimitry Andric // Before the transformation, A must be assigned with different hardware 348e8d8bef9SDimitry Andric // register with D. After the transformation, A and D must be assigned with 349fe6060f1SDimitry Andric // same hardware register due to TIE attribute of FMA instructions. 350e8d8bef9SDimitry Andric // 3510fca6ea1SDimitry Andric bool PPCInstrInfo::getFMAPatterns(MachineInstr &Root, 3520fca6ea1SDimitry Andric SmallVectorImpl<unsigned> &Patterns, 353e8d8bef9SDimitry Andric bool DoRegPressureReduce) const { 3545ffd83dbSDimitry Andric MachineBasicBlock *MBB = Root.getParent(); 355e8d8bef9SDimitry Andric const MachineRegisterInfo *MRI = &MBB->getParent()->getRegInfo(); 356e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 3575ffd83dbSDimitry Andric 3585ffd83dbSDimitry Andric auto IsAllOpsVirtualReg = [](const MachineInstr &Instr) { 3595ffd83dbSDimitry Andric for (const auto &MO : Instr.explicit_operands()) 360bdd1243dSDimitry Andric if (!(MO.isReg() && MO.getReg().isVirtual())) 3615ffd83dbSDimitry Andric return false; 3625ffd83dbSDimitry Andric return true; 3635ffd83dbSDimitry Andric }; 3645ffd83dbSDimitry Andric 365e8d8bef9SDimitry Andric auto IsReassociableAddOrSub = [&](const MachineInstr &Instr, 366e8d8bef9SDimitry Andric unsigned OpType) { 367e8d8bef9SDimitry Andric if (Instr.getOpcode() != 368e8d8bef9SDimitry Andric FMAOpIdxInfo[getFMAOpIdxInfo(Root.getOpcode())][OpType]) 3695ffd83dbSDimitry Andric return false; 3705ffd83dbSDimitry Andric 3715ffd83dbSDimitry Andric // Instruction can be reassociated. 3725ffd83dbSDimitry Andric // fast math flags may prohibit reassociation. 3735ffd83dbSDimitry Andric if (!(Instr.getFlag(MachineInstr::MIFlag::FmReassoc) && 3745ffd83dbSDimitry Andric Instr.getFlag(MachineInstr::MIFlag::FmNsz))) 3755ffd83dbSDimitry Andric return false; 3765ffd83dbSDimitry Andric 3775ffd83dbSDimitry Andric // Instruction operands are virtual registers for reassociation. 3785ffd83dbSDimitry Andric if (!IsAllOpsVirtualReg(Instr)) 3795ffd83dbSDimitry Andric return false; 3805ffd83dbSDimitry Andric 381e8d8bef9SDimitry Andric // For register pressure reassociation, the FSub must have only one use as 382e8d8bef9SDimitry Andric // we want to delete the sub to save its def. 383e8d8bef9SDimitry Andric if (OpType == InfoArrayIdxFSubInst && 384e8d8bef9SDimitry Andric !MRI->hasOneNonDBGUse(Instr.getOperand(0).getReg())) 385e8d8bef9SDimitry Andric return false; 386e8d8bef9SDimitry Andric 387e8d8bef9SDimitry Andric return true; 388e8d8bef9SDimitry Andric }; 389e8d8bef9SDimitry Andric 390e8d8bef9SDimitry Andric auto IsReassociableFMA = [&](const MachineInstr &Instr, int16_t &AddOpIdx, 391e8d8bef9SDimitry Andric int16_t &MulOpIdx, bool IsLeaf) { 392e8d8bef9SDimitry Andric int16_t Idx = getFMAOpIdxInfo(Instr.getOpcode()); 393e8d8bef9SDimitry Andric if (Idx < 0) 394e8d8bef9SDimitry Andric return false; 395e8d8bef9SDimitry Andric 396e8d8bef9SDimitry Andric // Instruction can be reassociated. 397e8d8bef9SDimitry Andric // fast math flags may prohibit reassociation. 398e8d8bef9SDimitry Andric if (!(Instr.getFlag(MachineInstr::MIFlag::FmReassoc) && 399e8d8bef9SDimitry Andric Instr.getFlag(MachineInstr::MIFlag::FmNsz))) 400e8d8bef9SDimitry Andric return false; 401e8d8bef9SDimitry Andric 402e8d8bef9SDimitry Andric // Instruction operands are virtual registers for reassociation. 403e8d8bef9SDimitry Andric if (!IsAllOpsVirtualReg(Instr)) 404e8d8bef9SDimitry Andric return false; 405e8d8bef9SDimitry Andric 406e8d8bef9SDimitry Andric MulOpIdx = FMAOpIdxInfo[Idx][InfoArrayIdxMULOpIdx]; 407e8d8bef9SDimitry Andric if (IsLeaf) 4085ffd83dbSDimitry Andric return true; 4095ffd83dbSDimitry Andric 4105ffd83dbSDimitry Andric AddOpIdx = FMAOpIdxInfo[Idx][InfoArrayIdxAddOpIdx]; 4115ffd83dbSDimitry Andric 4125ffd83dbSDimitry Andric const MachineOperand &OpAdd = Instr.getOperand(AddOpIdx); 413e8d8bef9SDimitry Andric MachineInstr *MIAdd = MRI->getUniqueVRegDef(OpAdd.getReg()); 4145ffd83dbSDimitry Andric // If 'add' operand's def is not in current block, don't do ILP related opt. 4155ffd83dbSDimitry Andric if (!MIAdd || MIAdd->getParent() != MBB) 4165ffd83dbSDimitry Andric return false; 4175ffd83dbSDimitry Andric 4185ffd83dbSDimitry Andric // If this is not Leaf FMA Instr, its 'add' operand should only have one use 4195ffd83dbSDimitry Andric // as this fma will be changed later. 420e8d8bef9SDimitry Andric return IsLeaf ? true : MRI->hasOneNonDBGUse(OpAdd.getReg()); 4215ffd83dbSDimitry Andric }; 4225ffd83dbSDimitry Andric 4235ffd83dbSDimitry Andric int16_t AddOpIdx = -1; 424e8d8bef9SDimitry Andric int16_t MulOpIdx = -1; 425e8d8bef9SDimitry Andric 426e8d8bef9SDimitry Andric bool IsUsedOnceL = false; 427e8d8bef9SDimitry Andric bool IsUsedOnceR = false; 428e8d8bef9SDimitry Andric MachineInstr *MULInstrL = nullptr; 429e8d8bef9SDimitry Andric MachineInstr *MULInstrR = nullptr; 430e8d8bef9SDimitry Andric 431e8d8bef9SDimitry Andric auto IsRPReductionCandidate = [&]() { 432e8d8bef9SDimitry Andric // Currently, we only support float and double. 433e8d8bef9SDimitry Andric // FIXME: add support for other types. 434e8d8bef9SDimitry Andric unsigned Opcode = Root.getOpcode(); 435e8d8bef9SDimitry Andric if (Opcode != PPC::XSMADDASP && Opcode != PPC::XSMADDADP) 436e8d8bef9SDimitry Andric return false; 437e8d8bef9SDimitry Andric 4385ffd83dbSDimitry Andric // Root must be a valid FMA like instruction. 439e8d8bef9SDimitry Andric // Treat it as leaf as we don't care its add operand. 440e8d8bef9SDimitry Andric if (IsReassociableFMA(Root, AddOpIdx, MulOpIdx, true)) { 441e8d8bef9SDimitry Andric assert((MulOpIdx >= 0) && "mul operand index not right!"); 442e8d8bef9SDimitry Andric Register MULRegL = TRI->lookThruSingleUseCopyChain( 443e8d8bef9SDimitry Andric Root.getOperand(MulOpIdx).getReg(), MRI); 444e8d8bef9SDimitry Andric Register MULRegR = TRI->lookThruSingleUseCopyChain( 445e8d8bef9SDimitry Andric Root.getOperand(MulOpIdx + 1).getReg(), MRI); 446e8d8bef9SDimitry Andric if (!MULRegL && !MULRegR) 447e8d8bef9SDimitry Andric return false; 448e8d8bef9SDimitry Andric 449e8d8bef9SDimitry Andric if (MULRegL && !MULRegR) { 450e8d8bef9SDimitry Andric MULRegR = 451e8d8bef9SDimitry Andric TRI->lookThruCopyLike(Root.getOperand(MulOpIdx + 1).getReg(), MRI); 452e8d8bef9SDimitry Andric IsUsedOnceL = true; 453e8d8bef9SDimitry Andric } else if (!MULRegL && MULRegR) { 454e8d8bef9SDimitry Andric MULRegL = 455e8d8bef9SDimitry Andric TRI->lookThruCopyLike(Root.getOperand(MulOpIdx).getReg(), MRI); 456e8d8bef9SDimitry Andric IsUsedOnceR = true; 457e8d8bef9SDimitry Andric } else { 458e8d8bef9SDimitry Andric IsUsedOnceL = true; 459e8d8bef9SDimitry Andric IsUsedOnceR = true; 460e8d8bef9SDimitry Andric } 461e8d8bef9SDimitry Andric 462bdd1243dSDimitry Andric if (!MULRegL.isVirtual() || !MULRegR.isVirtual()) 463e8d8bef9SDimitry Andric return false; 464e8d8bef9SDimitry Andric 465e8d8bef9SDimitry Andric MULInstrL = MRI->getVRegDef(MULRegL); 466e8d8bef9SDimitry Andric MULInstrR = MRI->getVRegDef(MULRegR); 467e8d8bef9SDimitry Andric return true; 468e8d8bef9SDimitry Andric } 469e8d8bef9SDimitry Andric return false; 470e8d8bef9SDimitry Andric }; 471e8d8bef9SDimitry Andric 472e8d8bef9SDimitry Andric // Register pressure fma reassociation patterns. 473e8d8bef9SDimitry Andric if (DoRegPressureReduce && IsRPReductionCandidate()) { 474e8d8bef9SDimitry Andric assert((MULInstrL && MULInstrR) && "wrong register preduction candidate!"); 475e8d8bef9SDimitry Andric // Register pressure pattern 1 476e8d8bef9SDimitry Andric if (isLoadFromConstantPool(MULInstrL) && IsUsedOnceR && 477e8d8bef9SDimitry Andric IsReassociableAddOrSub(*MULInstrR, InfoArrayIdxFSubInst)) { 478e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "add pattern REASSOC_XY_BCA\n"); 4790fca6ea1SDimitry Andric Patterns.push_back(PPCMachineCombinerPattern::REASSOC_XY_BCA); 480e8d8bef9SDimitry Andric return true; 481e8d8bef9SDimitry Andric } 482e8d8bef9SDimitry Andric 483e8d8bef9SDimitry Andric // Register pressure pattern 2 484e8d8bef9SDimitry Andric if ((isLoadFromConstantPool(MULInstrR) && IsUsedOnceL && 485e8d8bef9SDimitry Andric IsReassociableAddOrSub(*MULInstrL, InfoArrayIdxFSubInst))) { 486e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "add pattern REASSOC_XY_BAC\n"); 4870fca6ea1SDimitry Andric Patterns.push_back(PPCMachineCombinerPattern::REASSOC_XY_BAC); 488e8d8bef9SDimitry Andric return true; 489e8d8bef9SDimitry Andric } 490e8d8bef9SDimitry Andric } 491e8d8bef9SDimitry Andric 492e8d8bef9SDimitry Andric // ILP fma reassociation patterns. 493e8d8bef9SDimitry Andric // Root must be a valid FMA like instruction. 494e8d8bef9SDimitry Andric AddOpIdx = -1; 495e8d8bef9SDimitry Andric if (!IsReassociableFMA(Root, AddOpIdx, MulOpIdx, false)) 4965ffd83dbSDimitry Andric return false; 4975ffd83dbSDimitry Andric 4985ffd83dbSDimitry Andric assert((AddOpIdx >= 0) && "add operand index not right!"); 4995ffd83dbSDimitry Andric 5005ffd83dbSDimitry Andric Register RegB = Root.getOperand(AddOpIdx).getReg(); 501e8d8bef9SDimitry Andric MachineInstr *Prev = MRI->getUniqueVRegDef(RegB); 5025ffd83dbSDimitry Andric 5035ffd83dbSDimitry Andric // Prev must be a valid FMA like instruction. 5045ffd83dbSDimitry Andric AddOpIdx = -1; 505e8d8bef9SDimitry Andric if (!IsReassociableFMA(*Prev, AddOpIdx, MulOpIdx, false)) 5065ffd83dbSDimitry Andric return false; 5075ffd83dbSDimitry Andric 5085ffd83dbSDimitry Andric assert((AddOpIdx >= 0) && "add operand index not right!"); 5095ffd83dbSDimitry Andric 5105ffd83dbSDimitry Andric Register RegA = Prev->getOperand(AddOpIdx).getReg(); 511e8d8bef9SDimitry Andric MachineInstr *Leaf = MRI->getUniqueVRegDef(RegA); 5125ffd83dbSDimitry Andric AddOpIdx = -1; 513e8d8bef9SDimitry Andric if (IsReassociableFMA(*Leaf, AddOpIdx, MulOpIdx, true)) { 5140fca6ea1SDimitry Andric Patterns.push_back(PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM); 515e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "add pattern REASSOC_XMM_AMM_BMM\n"); 5165ffd83dbSDimitry Andric return true; 5175ffd83dbSDimitry Andric } 518e8d8bef9SDimitry Andric if (IsReassociableAddOrSub(*Leaf, InfoArrayIdxFAddInst)) { 5190fca6ea1SDimitry Andric Patterns.push_back(PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM); 520e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "add pattern REASSOC_XY_AMM_BMM\n"); 5215ffd83dbSDimitry Andric return true; 5225ffd83dbSDimitry Andric } 5235ffd83dbSDimitry Andric return false; 5245ffd83dbSDimitry Andric } 5255ffd83dbSDimitry Andric 526e8d8bef9SDimitry Andric void PPCInstrInfo::finalizeInsInstrs( 5270fca6ea1SDimitry Andric MachineInstr &Root, unsigned &Pattern, 528e8d8bef9SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs) const { 529e8d8bef9SDimitry Andric assert(!InsInstrs.empty() && "Instructions set to be inserted is empty!"); 530e8d8bef9SDimitry Andric 531e8d8bef9SDimitry Andric MachineFunction *MF = Root.getMF(); 532e8d8bef9SDimitry Andric MachineRegisterInfo *MRI = &MF->getRegInfo(); 533e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 534e8d8bef9SDimitry Andric MachineConstantPool *MCP = MF->getConstantPool(); 535e8d8bef9SDimitry Andric 536e8d8bef9SDimitry Andric int16_t Idx = getFMAOpIdxInfo(Root.getOpcode()); 537e8d8bef9SDimitry Andric if (Idx < 0) 538e8d8bef9SDimitry Andric return; 539e8d8bef9SDimitry Andric 540e8d8bef9SDimitry Andric uint16_t FirstMulOpIdx = FMAOpIdxInfo[Idx][InfoArrayIdxMULOpIdx]; 541e8d8bef9SDimitry Andric 542e8d8bef9SDimitry Andric // For now we only need to fix up placeholder for register pressure reduce 543e8d8bef9SDimitry Andric // patterns. 544e8d8bef9SDimitry Andric Register ConstReg = 0; 5450fca6ea1SDimitry Andric switch (Pattern) { 5460fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BCA: 547e8d8bef9SDimitry Andric ConstReg = 548e8d8bef9SDimitry Andric TRI->lookThruCopyLike(Root.getOperand(FirstMulOpIdx).getReg(), MRI); 549e8d8bef9SDimitry Andric break; 5500fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BAC: 551e8d8bef9SDimitry Andric ConstReg = 552e8d8bef9SDimitry Andric TRI->lookThruCopyLike(Root.getOperand(FirstMulOpIdx + 1).getReg(), MRI); 553e8d8bef9SDimitry Andric break; 554e8d8bef9SDimitry Andric default: 555e8d8bef9SDimitry Andric // Not register pressure reduce patterns. 556e8d8bef9SDimitry Andric return; 557e8d8bef9SDimitry Andric } 558e8d8bef9SDimitry Andric 559e8d8bef9SDimitry Andric MachineInstr *ConstDefInstr = MRI->getVRegDef(ConstReg); 560e8d8bef9SDimitry Andric // Get const value from const pool. 561e8d8bef9SDimitry Andric const Constant *C = getConstantFromConstantPool(ConstDefInstr); 562e8d8bef9SDimitry Andric assert(isa<llvm::ConstantFP>(C) && "not a valid constant!"); 563e8d8bef9SDimitry Andric 564e8d8bef9SDimitry Andric // Get negative fp const. 565e8d8bef9SDimitry Andric APFloat F1((dyn_cast<ConstantFP>(C))->getValueAPF()); 566e8d8bef9SDimitry Andric F1.changeSign(); 567e8d8bef9SDimitry Andric Constant *NegC = ConstantFP::get(dyn_cast<ConstantFP>(C)->getContext(), F1); 568e8d8bef9SDimitry Andric Align Alignment = MF->getDataLayout().getPrefTypeAlign(C->getType()); 569e8d8bef9SDimitry Andric 570e8d8bef9SDimitry Andric // Put negative fp const into constant pool. 571e8d8bef9SDimitry Andric unsigned ConstPoolIdx = MCP->getConstantPoolIndex(NegC, Alignment); 572e8d8bef9SDimitry Andric 573e8d8bef9SDimitry Andric MachineOperand *Placeholder = nullptr; 574e8d8bef9SDimitry Andric // Record the placeholder PPC::ZERO8 we add in reassociateFMA. 575e8d8bef9SDimitry Andric for (auto *Inst : InsInstrs) { 576e8d8bef9SDimitry Andric for (MachineOperand &Operand : Inst->explicit_operands()) { 577e8d8bef9SDimitry Andric assert(Operand.isReg() && "Invalid instruction in InsInstrs!"); 578e8d8bef9SDimitry Andric if (Operand.getReg() == PPC::ZERO8) { 579e8d8bef9SDimitry Andric Placeholder = &Operand; 580e8d8bef9SDimitry Andric break; 581e8d8bef9SDimitry Andric } 582e8d8bef9SDimitry Andric } 583e8d8bef9SDimitry Andric } 584e8d8bef9SDimitry Andric 585e8d8bef9SDimitry Andric assert(Placeholder && "Placeholder does not exist!"); 586e8d8bef9SDimitry Andric 587e8d8bef9SDimitry Andric // Generate instructions to load the const fp from constant pool. 588e8d8bef9SDimitry Andric // We only support PPC64 and medium code model. 589e8d8bef9SDimitry Andric Register LoadNewConst = 590e8d8bef9SDimitry Andric generateLoadForNewConst(ConstPoolIdx, &Root, C->getType(), InsInstrs); 591e8d8bef9SDimitry Andric 592e8d8bef9SDimitry Andric // Fill the placeholder with the new load from constant pool. 593e8d8bef9SDimitry Andric Placeholder->setReg(LoadNewConst); 594e8d8bef9SDimitry Andric } 595e8d8bef9SDimitry Andric 596e8d8bef9SDimitry Andric bool PPCInstrInfo::shouldReduceRegisterPressure( 597bdd1243dSDimitry Andric const MachineBasicBlock *MBB, const RegisterClassInfo *RegClassInfo) const { 598e8d8bef9SDimitry Andric 599e8d8bef9SDimitry Andric if (!EnableFMARegPressureReduction) 600e8d8bef9SDimitry Andric return false; 601e8d8bef9SDimitry Andric 602e8d8bef9SDimitry Andric // Currently, we only enable register pressure reducing in machine combiner 603e8d8bef9SDimitry Andric // for: 1: PPC64; 2: Code Model is Medium; 3: Power9 which also has vector 604e8d8bef9SDimitry Andric // support. 605e8d8bef9SDimitry Andric // 606e8d8bef9SDimitry Andric // So we need following instructions to access a TOC entry: 607e8d8bef9SDimitry Andric // 608e8d8bef9SDimitry Andric // %6:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, %const.0 609e8d8bef9SDimitry Andric // %7:vssrc = DFLOADf32 target-flags(ppc-toc-lo) %const.0, 610e8d8bef9SDimitry Andric // killed %6:g8rc_and_g8rc_nox0, implicit $x2 :: (load 4 from constant-pool) 611e8d8bef9SDimitry Andric // 612e8d8bef9SDimitry Andric // FIXME: add more supported targets, like Small and Large code model, PPC32, 613e8d8bef9SDimitry Andric // AIX. 614e8d8bef9SDimitry Andric if (!(Subtarget.isPPC64() && Subtarget.hasP9Vector() && 615e8d8bef9SDimitry Andric Subtarget.getTargetMachine().getCodeModel() == CodeModel::Medium)) 616e8d8bef9SDimitry Andric return false; 617e8d8bef9SDimitry Andric 618e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 619bdd1243dSDimitry Andric const MachineFunction *MF = MBB->getParent(); 620bdd1243dSDimitry Andric const MachineRegisterInfo *MRI = &MF->getRegInfo(); 621e8d8bef9SDimitry Andric 622bdd1243dSDimitry Andric auto GetMBBPressure = 623bdd1243dSDimitry Andric [&](const MachineBasicBlock *MBB) -> std::vector<unsigned> { 624e8d8bef9SDimitry Andric RegionPressure Pressure; 625e8d8bef9SDimitry Andric RegPressureTracker RPTracker(Pressure); 626e8d8bef9SDimitry Andric 627e8d8bef9SDimitry Andric // Initialize the register pressure tracker. 628e8d8bef9SDimitry Andric RPTracker.init(MBB->getParent(), RegClassInfo, nullptr, MBB, MBB->end(), 629e8d8bef9SDimitry Andric /*TrackLaneMasks*/ false, /*TrackUntiedDefs=*/true); 630e8d8bef9SDimitry Andric 631bdd1243dSDimitry Andric for (const auto &MI : reverse(*MBB)) { 632e8d8bef9SDimitry Andric if (MI.isDebugValue() || MI.isDebugLabel()) 633e8d8bef9SDimitry Andric continue; 634e8d8bef9SDimitry Andric RegisterOperands RegOpers; 635e8d8bef9SDimitry Andric RegOpers.collect(MI, *TRI, *MRI, false, false); 636e8d8bef9SDimitry Andric RPTracker.recedeSkipDebugValues(); 637e8d8bef9SDimitry Andric assert(&*RPTracker.getPos() == &MI && "RPTracker sync error!"); 638e8d8bef9SDimitry Andric RPTracker.recede(RegOpers); 639e8d8bef9SDimitry Andric } 640e8d8bef9SDimitry Andric 641e8d8bef9SDimitry Andric // Close the RPTracker to finalize live ins. 642e8d8bef9SDimitry Andric RPTracker.closeRegion(); 643e8d8bef9SDimitry Andric 644e8d8bef9SDimitry Andric return RPTracker.getPressure().MaxSetPressure; 645e8d8bef9SDimitry Andric }; 646e8d8bef9SDimitry Andric 647e8d8bef9SDimitry Andric // For now we only care about float and double type fma. 648e8d8bef9SDimitry Andric unsigned VSSRCLimit = TRI->getRegPressureSetLimit( 649e8d8bef9SDimitry Andric *MBB->getParent(), PPC::RegisterPressureSets::VSSRC); 650e8d8bef9SDimitry Andric 651e8d8bef9SDimitry Andric // Only reduce register pressure when pressure is high. 652e8d8bef9SDimitry Andric return GetMBBPressure(MBB)[PPC::RegisterPressureSets::VSSRC] > 653e8d8bef9SDimitry Andric (float)VSSRCLimit * FMARPFactor; 654e8d8bef9SDimitry Andric } 655e8d8bef9SDimitry Andric 656e8d8bef9SDimitry Andric bool PPCInstrInfo::isLoadFromConstantPool(MachineInstr *I) const { 657e8d8bef9SDimitry Andric // I has only one memory operand which is load from constant pool. 658e8d8bef9SDimitry Andric if (!I->hasOneMemOperand()) 659e8d8bef9SDimitry Andric return false; 660e8d8bef9SDimitry Andric 661e8d8bef9SDimitry Andric MachineMemOperand *Op = I->memoperands()[0]; 662e8d8bef9SDimitry Andric return Op->isLoad() && Op->getPseudoValue() && 663e8d8bef9SDimitry Andric Op->getPseudoValue()->kind() == PseudoSourceValue::ConstantPool; 664e8d8bef9SDimitry Andric } 665e8d8bef9SDimitry Andric 666e8d8bef9SDimitry Andric Register PPCInstrInfo::generateLoadForNewConst( 667e8d8bef9SDimitry Andric unsigned Idx, MachineInstr *MI, Type *Ty, 668e8d8bef9SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs) const { 669e8d8bef9SDimitry Andric // Now we only support PPC64, Medium code model and P9 with vector. 670e8d8bef9SDimitry Andric // We have immutable pattern to access const pool. See function 671e8d8bef9SDimitry Andric // shouldReduceRegisterPressure. 672e8d8bef9SDimitry Andric assert((Subtarget.isPPC64() && Subtarget.hasP9Vector() && 673e8d8bef9SDimitry Andric Subtarget.getTargetMachine().getCodeModel() == CodeModel::Medium) && 674e8d8bef9SDimitry Andric "Target not supported!\n"); 675e8d8bef9SDimitry Andric 676e8d8bef9SDimitry Andric MachineFunction *MF = MI->getMF(); 677e8d8bef9SDimitry Andric MachineRegisterInfo *MRI = &MF->getRegInfo(); 678e8d8bef9SDimitry Andric 679e8d8bef9SDimitry Andric // Generate ADDIStocHA8 680e8d8bef9SDimitry Andric Register VReg1 = MRI->createVirtualRegister(&PPC::G8RC_and_G8RC_NOX0RegClass); 681e8d8bef9SDimitry Andric MachineInstrBuilder TOCOffset = 682e8d8bef9SDimitry Andric BuildMI(*MF, MI->getDebugLoc(), get(PPC::ADDIStocHA8), VReg1) 683e8d8bef9SDimitry Andric .addReg(PPC::X2) 684e8d8bef9SDimitry Andric .addConstantPoolIndex(Idx); 685e8d8bef9SDimitry Andric 686e8d8bef9SDimitry Andric assert((Ty->isFloatTy() || Ty->isDoubleTy()) && 687e8d8bef9SDimitry Andric "Only float and double are supported!"); 688e8d8bef9SDimitry Andric 689e8d8bef9SDimitry Andric unsigned LoadOpcode; 690e8d8bef9SDimitry Andric // Should be float type or double type. 691e8d8bef9SDimitry Andric if (Ty->isFloatTy()) 692e8d8bef9SDimitry Andric LoadOpcode = PPC::DFLOADf32; 693e8d8bef9SDimitry Andric else 694e8d8bef9SDimitry Andric LoadOpcode = PPC::DFLOADf64; 695e8d8bef9SDimitry Andric 696e8d8bef9SDimitry Andric const TargetRegisterClass *RC = MRI->getRegClass(MI->getOperand(0).getReg()); 697e8d8bef9SDimitry Andric Register VReg2 = MRI->createVirtualRegister(RC); 698e8d8bef9SDimitry Andric MachineMemOperand *MMO = MF->getMachineMemOperand( 699e8d8bef9SDimitry Andric MachinePointerInfo::getConstantPool(*MF), MachineMemOperand::MOLoad, 700e8d8bef9SDimitry Andric Ty->getScalarSizeInBits() / 8, MF->getDataLayout().getPrefTypeAlign(Ty)); 701e8d8bef9SDimitry Andric 702e8d8bef9SDimitry Andric // Generate Load from constant pool. 703e8d8bef9SDimitry Andric MachineInstrBuilder Load = 704e8d8bef9SDimitry Andric BuildMI(*MF, MI->getDebugLoc(), get(LoadOpcode), VReg2) 705e8d8bef9SDimitry Andric .addConstantPoolIndex(Idx) 706e8d8bef9SDimitry Andric .addReg(VReg1, getKillRegState(true)) 707e8d8bef9SDimitry Andric .addMemOperand(MMO); 708e8d8bef9SDimitry Andric 709e8d8bef9SDimitry Andric Load->getOperand(1).setTargetFlags(PPCII::MO_TOC_LO); 710e8d8bef9SDimitry Andric 711e8d8bef9SDimitry Andric // Insert the toc load instructions into InsInstrs. 712e8d8bef9SDimitry Andric InsInstrs.insert(InsInstrs.begin(), Load); 713e8d8bef9SDimitry Andric InsInstrs.insert(InsInstrs.begin(), TOCOffset); 714e8d8bef9SDimitry Andric return VReg2; 715e8d8bef9SDimitry Andric } 716e8d8bef9SDimitry Andric 717e8d8bef9SDimitry Andric // This function returns the const value in constant pool if the \p I is a load 718e8d8bef9SDimitry Andric // from constant pool. 719e8d8bef9SDimitry Andric const Constant * 720e8d8bef9SDimitry Andric PPCInstrInfo::getConstantFromConstantPool(MachineInstr *I) const { 721e8d8bef9SDimitry Andric MachineFunction *MF = I->getMF(); 722e8d8bef9SDimitry Andric MachineRegisterInfo *MRI = &MF->getRegInfo(); 723e8d8bef9SDimitry Andric MachineConstantPool *MCP = MF->getConstantPool(); 724e8d8bef9SDimitry Andric assert(I->mayLoad() && "Should be a load instruction.\n"); 725e8d8bef9SDimitry Andric for (auto MO : I->uses()) { 726e8d8bef9SDimitry Andric if (!MO.isReg()) 727e8d8bef9SDimitry Andric continue; 728e8d8bef9SDimitry Andric Register Reg = MO.getReg(); 729bdd1243dSDimitry Andric if (Reg == 0 || !Reg.isVirtual()) 730e8d8bef9SDimitry Andric continue; 731e8d8bef9SDimitry Andric // Find the toc address. 732e8d8bef9SDimitry Andric MachineInstr *DefMI = MRI->getVRegDef(Reg); 733e8d8bef9SDimitry Andric for (auto MO2 : DefMI->uses()) 734e8d8bef9SDimitry Andric if (MO2.isCPI()) 735e8d8bef9SDimitry Andric return (MCP->getConstants())[MO2.getIndex()].Val.ConstVal; 736e8d8bef9SDimitry Andric } 737e8d8bef9SDimitry Andric return nullptr; 738e8d8bef9SDimitry Andric } 739e8d8bef9SDimitry Andric 7400fca6ea1SDimitry Andric CombinerObjective PPCInstrInfo::getCombinerObjective(unsigned Pattern) const { 7410fca6ea1SDimitry Andric switch (Pattern) { 7420fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM: 7430fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM: 7440fca6ea1SDimitry Andric return CombinerObjective::MustReduceDepth; 7450fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BCA: 7460fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BAC: 7470fca6ea1SDimitry Andric return CombinerObjective::MustReduceRegisterPressure; 7480fca6ea1SDimitry Andric default: 7490fca6ea1SDimitry Andric return TargetInstrInfo::getCombinerObjective(Pattern); 7500fca6ea1SDimitry Andric } 7510fca6ea1SDimitry Andric } 7520fca6ea1SDimitry Andric 7530b57cec5SDimitry Andric bool PPCInstrInfo::getMachineCombinerPatterns( 7540fca6ea1SDimitry Andric MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns, 755e8d8bef9SDimitry Andric bool DoRegPressureReduce) const { 7560b57cec5SDimitry Andric // Using the machine combiner in this way is potentially expensive, so 7570b57cec5SDimitry Andric // restrict to when aggressive optimizations are desired. 7585f757f3fSDimitry Andric if (Subtarget.getTargetMachine().getOptLevel() != CodeGenOptLevel::Aggressive) 7590b57cec5SDimitry Andric return false; 7600b57cec5SDimitry Andric 761e8d8bef9SDimitry Andric if (getFMAPatterns(Root, Patterns, DoRegPressureReduce)) 7625ffd83dbSDimitry Andric return true; 7630b57cec5SDimitry Andric 764e8d8bef9SDimitry Andric return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns, 765e8d8bef9SDimitry Andric DoRegPressureReduce); 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric 7685ffd83dbSDimitry Andric void PPCInstrInfo::genAlternativeCodeSequence( 7690fca6ea1SDimitry Andric MachineInstr &Root, unsigned Pattern, 7705ffd83dbSDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs, 7715ffd83dbSDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs, 7725ffd83dbSDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const { 7735ffd83dbSDimitry Andric switch (Pattern) { 7740fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM: 7750fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM: 7760fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BCA: 7770fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BAC: 7785ffd83dbSDimitry Andric reassociateFMA(Root, Pattern, InsInstrs, DelInstrs, InstrIdxForVirtReg); 7795ffd83dbSDimitry Andric break; 7805ffd83dbSDimitry Andric default: 7815ffd83dbSDimitry Andric // Reassociate default patterns. 7825ffd83dbSDimitry Andric TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs, 7835ffd83dbSDimitry Andric DelInstrs, InstrIdxForVirtReg); 7845ffd83dbSDimitry Andric break; 7855ffd83dbSDimitry Andric } 7865ffd83dbSDimitry Andric } 7875ffd83dbSDimitry Andric 7885ffd83dbSDimitry Andric void PPCInstrInfo::reassociateFMA( 7890fca6ea1SDimitry Andric MachineInstr &Root, unsigned Pattern, 7905ffd83dbSDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs, 7915ffd83dbSDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs, 7925ffd83dbSDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const { 7935ffd83dbSDimitry Andric MachineFunction *MF = Root.getMF(); 7945ffd83dbSDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 795e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 7965ffd83dbSDimitry Andric MachineOperand &OpC = Root.getOperand(0); 7975ffd83dbSDimitry Andric Register RegC = OpC.getReg(); 7985ffd83dbSDimitry Andric const TargetRegisterClass *RC = MRI.getRegClass(RegC); 7995ffd83dbSDimitry Andric MRI.constrainRegClass(RegC, RC); 8005ffd83dbSDimitry Andric 8015ffd83dbSDimitry Andric unsigned FmaOp = Root.getOpcode(); 8025ffd83dbSDimitry Andric int16_t Idx = getFMAOpIdxInfo(FmaOp); 8035ffd83dbSDimitry Andric assert(Idx >= 0 && "Root must be a FMA instruction"); 8045ffd83dbSDimitry Andric 805e8d8bef9SDimitry Andric bool IsILPReassociate = 8060fca6ea1SDimitry Andric (Pattern == PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM) || 8070fca6ea1SDimitry Andric (Pattern == PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM); 808e8d8bef9SDimitry Andric 8095ffd83dbSDimitry Andric uint16_t AddOpIdx = FMAOpIdxInfo[Idx][InfoArrayIdxAddOpIdx]; 8105ffd83dbSDimitry Andric uint16_t FirstMulOpIdx = FMAOpIdxInfo[Idx][InfoArrayIdxMULOpIdx]; 811e8d8bef9SDimitry Andric 812e8d8bef9SDimitry Andric MachineInstr *Prev = nullptr; 813e8d8bef9SDimitry Andric MachineInstr *Leaf = nullptr; 814e8d8bef9SDimitry Andric switch (Pattern) { 815e8d8bef9SDimitry Andric default: 816e8d8bef9SDimitry Andric llvm_unreachable("not recognized pattern!"); 8170fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM: 8180fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM: 819e8d8bef9SDimitry Andric Prev = MRI.getUniqueVRegDef(Root.getOperand(AddOpIdx).getReg()); 820e8d8bef9SDimitry Andric Leaf = MRI.getUniqueVRegDef(Prev->getOperand(AddOpIdx).getReg()); 821e8d8bef9SDimitry Andric break; 8220fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BAC: { 823e8d8bef9SDimitry Andric Register MULReg = 824e8d8bef9SDimitry Andric TRI->lookThruCopyLike(Root.getOperand(FirstMulOpIdx).getReg(), &MRI); 825e8d8bef9SDimitry Andric Leaf = MRI.getVRegDef(MULReg); 826e8d8bef9SDimitry Andric break; 827e8d8bef9SDimitry Andric } 8280fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BCA: { 829e8d8bef9SDimitry Andric Register MULReg = TRI->lookThruCopyLike( 830e8d8bef9SDimitry Andric Root.getOperand(FirstMulOpIdx + 1).getReg(), &MRI); 831e8d8bef9SDimitry Andric Leaf = MRI.getVRegDef(MULReg); 832e8d8bef9SDimitry Andric break; 833e8d8bef9SDimitry Andric } 834e8d8bef9SDimitry Andric } 835e8d8bef9SDimitry Andric 83606c3fb27SDimitry Andric uint32_t IntersectedFlags = 0; 837e8d8bef9SDimitry Andric if (IsILPReassociate) 838e8d8bef9SDimitry Andric IntersectedFlags = Root.getFlags() & Prev->getFlags() & Leaf->getFlags(); 839e8d8bef9SDimitry Andric else 840e8d8bef9SDimitry Andric IntersectedFlags = Root.getFlags() & Leaf->getFlags(); 8415ffd83dbSDimitry Andric 8425ffd83dbSDimitry Andric auto GetOperandInfo = [&](const MachineOperand &Operand, Register &Reg, 8435ffd83dbSDimitry Andric bool &KillFlag) { 8445ffd83dbSDimitry Andric Reg = Operand.getReg(); 8455ffd83dbSDimitry Andric MRI.constrainRegClass(Reg, RC); 8465ffd83dbSDimitry Andric KillFlag = Operand.isKill(); 8475ffd83dbSDimitry Andric }; 8485ffd83dbSDimitry Andric 8495ffd83dbSDimitry Andric auto GetFMAInstrInfo = [&](const MachineInstr &Instr, Register &MulOp1, 850e8d8bef9SDimitry Andric Register &MulOp2, Register &AddOp, 851e8d8bef9SDimitry Andric bool &MulOp1KillFlag, bool &MulOp2KillFlag, 852e8d8bef9SDimitry Andric bool &AddOpKillFlag) { 8535ffd83dbSDimitry Andric GetOperandInfo(Instr.getOperand(FirstMulOpIdx), MulOp1, MulOp1KillFlag); 8545ffd83dbSDimitry Andric GetOperandInfo(Instr.getOperand(FirstMulOpIdx + 1), MulOp2, MulOp2KillFlag); 855e8d8bef9SDimitry Andric GetOperandInfo(Instr.getOperand(AddOpIdx), AddOp, AddOpKillFlag); 8565ffd83dbSDimitry Andric }; 8575ffd83dbSDimitry Andric 858e8d8bef9SDimitry Andric Register RegM11, RegM12, RegX, RegY, RegM21, RegM22, RegM31, RegM32, RegA11, 859e8d8bef9SDimitry Andric RegA21, RegB; 8605ffd83dbSDimitry Andric bool KillX = false, KillY = false, KillM11 = false, KillM12 = false, 861e8d8bef9SDimitry Andric KillM21 = false, KillM22 = false, KillM31 = false, KillM32 = false, 862e8d8bef9SDimitry Andric KillA11 = false, KillA21 = false, KillB = false; 8635ffd83dbSDimitry Andric 864e8d8bef9SDimitry Andric GetFMAInstrInfo(Root, RegM31, RegM32, RegB, KillM31, KillM32, KillB); 865e8d8bef9SDimitry Andric 866e8d8bef9SDimitry Andric if (IsILPReassociate) 867e8d8bef9SDimitry Andric GetFMAInstrInfo(*Prev, RegM21, RegM22, RegA21, KillM21, KillM22, KillA21); 8685ffd83dbSDimitry Andric 8690fca6ea1SDimitry Andric if (Pattern == PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM) { 870e8d8bef9SDimitry Andric GetFMAInstrInfo(*Leaf, RegM11, RegM12, RegA11, KillM11, KillM12, KillA11); 8715ffd83dbSDimitry Andric GetOperandInfo(Leaf->getOperand(AddOpIdx), RegX, KillX); 8720fca6ea1SDimitry Andric } else if (Pattern == PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM) { 8735ffd83dbSDimitry Andric GetOperandInfo(Leaf->getOperand(1), RegX, KillX); 8745ffd83dbSDimitry Andric GetOperandInfo(Leaf->getOperand(2), RegY, KillY); 875e8d8bef9SDimitry Andric } else { 876e8d8bef9SDimitry Andric // Get FSUB instruction info. 877e8d8bef9SDimitry Andric GetOperandInfo(Leaf->getOperand(1), RegX, KillX); 878e8d8bef9SDimitry Andric GetOperandInfo(Leaf->getOperand(2), RegY, KillY); 8795ffd83dbSDimitry Andric } 8805ffd83dbSDimitry Andric 8815ffd83dbSDimitry Andric // Create new virtual registers for the new results instead of 8825ffd83dbSDimitry Andric // recycling legacy ones because the MachineCombiner's computation of the 8835ffd83dbSDimitry Andric // critical path requires a new register definition rather than an existing 8845ffd83dbSDimitry Andric // one. 885e8d8bef9SDimitry Andric // For register pressure reassociation, we only need create one virtual 886e8d8bef9SDimitry Andric // register for the new fma. 8875ffd83dbSDimitry Andric Register NewVRA = MRI.createVirtualRegister(RC); 8885ffd83dbSDimitry Andric InstrIdxForVirtReg.insert(std::make_pair(NewVRA, 0)); 8895ffd83dbSDimitry Andric 890e8d8bef9SDimitry Andric Register NewVRB = 0; 891e8d8bef9SDimitry Andric if (IsILPReassociate) { 892e8d8bef9SDimitry Andric NewVRB = MRI.createVirtualRegister(RC); 8935ffd83dbSDimitry Andric InstrIdxForVirtReg.insert(std::make_pair(NewVRB, 1)); 894e8d8bef9SDimitry Andric } 8955ffd83dbSDimitry Andric 8965ffd83dbSDimitry Andric Register NewVRD = 0; 8970fca6ea1SDimitry Andric if (Pattern == PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM) { 8985ffd83dbSDimitry Andric NewVRD = MRI.createVirtualRegister(RC); 8995ffd83dbSDimitry Andric InstrIdxForVirtReg.insert(std::make_pair(NewVRD, 2)); 9005ffd83dbSDimitry Andric } 9015ffd83dbSDimitry Andric 9025ffd83dbSDimitry Andric auto AdjustOperandOrder = [&](MachineInstr *MI, Register RegAdd, bool KillAdd, 9035ffd83dbSDimitry Andric Register RegMul1, bool KillRegMul1, 9045ffd83dbSDimitry Andric Register RegMul2, bool KillRegMul2) { 9055ffd83dbSDimitry Andric MI->getOperand(AddOpIdx).setReg(RegAdd); 9065ffd83dbSDimitry Andric MI->getOperand(AddOpIdx).setIsKill(KillAdd); 9075ffd83dbSDimitry Andric MI->getOperand(FirstMulOpIdx).setReg(RegMul1); 9085ffd83dbSDimitry Andric MI->getOperand(FirstMulOpIdx).setIsKill(KillRegMul1); 9095ffd83dbSDimitry Andric MI->getOperand(FirstMulOpIdx + 1).setReg(RegMul2); 9105ffd83dbSDimitry Andric MI->getOperand(FirstMulOpIdx + 1).setIsKill(KillRegMul2); 9115ffd83dbSDimitry Andric }; 9125ffd83dbSDimitry Andric 913e8d8bef9SDimitry Andric MachineInstrBuilder NewARegPressure, NewCRegPressure; 914e8d8bef9SDimitry Andric switch (Pattern) { 915e8d8bef9SDimitry Andric default: 916e8d8bef9SDimitry Andric llvm_unreachable("not recognized pattern!"); 9170fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_AMM_BMM: { 9185ffd83dbSDimitry Andric // Create new instructions for insertion. 9195ffd83dbSDimitry Andric MachineInstrBuilder MINewB = 9205ffd83dbSDimitry Andric BuildMI(*MF, Prev->getDebugLoc(), get(FmaOp), NewVRB) 9215ffd83dbSDimitry Andric .addReg(RegX, getKillRegState(KillX)) 9225ffd83dbSDimitry Andric .addReg(RegM21, getKillRegState(KillM21)) 9235ffd83dbSDimitry Andric .addReg(RegM22, getKillRegState(KillM22)); 9245ffd83dbSDimitry Andric MachineInstrBuilder MINewA = 9255ffd83dbSDimitry Andric BuildMI(*MF, Root.getDebugLoc(), get(FmaOp), NewVRA) 9265ffd83dbSDimitry Andric .addReg(RegY, getKillRegState(KillY)) 9275ffd83dbSDimitry Andric .addReg(RegM31, getKillRegState(KillM31)) 9285ffd83dbSDimitry Andric .addReg(RegM32, getKillRegState(KillM32)); 9295ffd83dbSDimitry Andric // If AddOpIdx is not 1, adjust the order. 9305ffd83dbSDimitry Andric if (AddOpIdx != 1) { 9315ffd83dbSDimitry Andric AdjustOperandOrder(MINewB, RegX, KillX, RegM21, KillM21, RegM22, KillM22); 9325ffd83dbSDimitry Andric AdjustOperandOrder(MINewA, RegY, KillY, RegM31, KillM31, RegM32, KillM32); 9335ffd83dbSDimitry Andric } 9345ffd83dbSDimitry Andric 9355ffd83dbSDimitry Andric MachineInstrBuilder MINewC = 9365ffd83dbSDimitry Andric BuildMI(*MF, Root.getDebugLoc(), 9375ffd83dbSDimitry Andric get(FMAOpIdxInfo[Idx][InfoArrayIdxFAddInst]), RegC) 9385ffd83dbSDimitry Andric .addReg(NewVRB, getKillRegState(true)) 9395ffd83dbSDimitry Andric .addReg(NewVRA, getKillRegState(true)); 9405ffd83dbSDimitry Andric 9415ffd83dbSDimitry Andric // Update flags for newly created instructions. 9425ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewA, IntersectedFlags); 9435ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewB, IntersectedFlags); 9445ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewC, IntersectedFlags); 9455ffd83dbSDimitry Andric 9465ffd83dbSDimitry Andric // Record new instructions for insertion. 9475ffd83dbSDimitry Andric InsInstrs.push_back(MINewA); 9485ffd83dbSDimitry Andric InsInstrs.push_back(MINewB); 9495ffd83dbSDimitry Andric InsInstrs.push_back(MINewC); 950e8d8bef9SDimitry Andric break; 951e8d8bef9SDimitry Andric } 9520fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XMM_AMM_BMM: { 9535ffd83dbSDimitry Andric assert(NewVRD && "new FMA register not created!"); 9545ffd83dbSDimitry Andric // Create new instructions for insertion. 9555ffd83dbSDimitry Andric MachineInstrBuilder MINewA = 9565ffd83dbSDimitry Andric BuildMI(*MF, Leaf->getDebugLoc(), 9575ffd83dbSDimitry Andric get(FMAOpIdxInfo[Idx][InfoArrayIdxFMULInst]), NewVRA) 9585ffd83dbSDimitry Andric .addReg(RegM11, getKillRegState(KillM11)) 9595ffd83dbSDimitry Andric .addReg(RegM12, getKillRegState(KillM12)); 9605ffd83dbSDimitry Andric MachineInstrBuilder MINewB = 9615ffd83dbSDimitry Andric BuildMI(*MF, Prev->getDebugLoc(), get(FmaOp), NewVRB) 9625ffd83dbSDimitry Andric .addReg(RegX, getKillRegState(KillX)) 9635ffd83dbSDimitry Andric .addReg(RegM21, getKillRegState(KillM21)) 9645ffd83dbSDimitry Andric .addReg(RegM22, getKillRegState(KillM22)); 9655ffd83dbSDimitry Andric MachineInstrBuilder MINewD = 9665ffd83dbSDimitry Andric BuildMI(*MF, Root.getDebugLoc(), get(FmaOp), NewVRD) 9675ffd83dbSDimitry Andric .addReg(NewVRA, getKillRegState(true)) 9685ffd83dbSDimitry Andric .addReg(RegM31, getKillRegState(KillM31)) 9695ffd83dbSDimitry Andric .addReg(RegM32, getKillRegState(KillM32)); 9705ffd83dbSDimitry Andric // If AddOpIdx is not 1, adjust the order. 9715ffd83dbSDimitry Andric if (AddOpIdx != 1) { 9725ffd83dbSDimitry Andric AdjustOperandOrder(MINewB, RegX, KillX, RegM21, KillM21, RegM22, KillM22); 9735ffd83dbSDimitry Andric AdjustOperandOrder(MINewD, NewVRA, true, RegM31, KillM31, RegM32, 9745ffd83dbSDimitry Andric KillM32); 9755ffd83dbSDimitry Andric } 9765ffd83dbSDimitry Andric 9775ffd83dbSDimitry Andric MachineInstrBuilder MINewC = 9785ffd83dbSDimitry Andric BuildMI(*MF, Root.getDebugLoc(), 9795ffd83dbSDimitry Andric get(FMAOpIdxInfo[Idx][InfoArrayIdxFAddInst]), RegC) 9805ffd83dbSDimitry Andric .addReg(NewVRB, getKillRegState(true)) 9815ffd83dbSDimitry Andric .addReg(NewVRD, getKillRegState(true)); 9825ffd83dbSDimitry Andric 9835ffd83dbSDimitry Andric // Update flags for newly created instructions. 9845ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewA, IntersectedFlags); 9855ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewB, IntersectedFlags); 9865ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewD, IntersectedFlags); 9875ffd83dbSDimitry Andric setSpecialOperandAttr(*MINewC, IntersectedFlags); 9885ffd83dbSDimitry Andric 9895ffd83dbSDimitry Andric // Record new instructions for insertion. 9905ffd83dbSDimitry Andric InsInstrs.push_back(MINewA); 9915ffd83dbSDimitry Andric InsInstrs.push_back(MINewB); 9925ffd83dbSDimitry Andric InsInstrs.push_back(MINewD); 9935ffd83dbSDimitry Andric InsInstrs.push_back(MINewC); 994e8d8bef9SDimitry Andric break; 995e8d8bef9SDimitry Andric } 9960fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BAC: 9970fca6ea1SDimitry Andric case PPCMachineCombinerPattern::REASSOC_XY_BCA: { 998e8d8bef9SDimitry Andric Register VarReg; 999e8d8bef9SDimitry Andric bool KillVarReg = false; 10000fca6ea1SDimitry Andric if (Pattern == PPCMachineCombinerPattern::REASSOC_XY_BCA) { 1001e8d8bef9SDimitry Andric VarReg = RegM31; 1002e8d8bef9SDimitry Andric KillVarReg = KillM31; 1003e8d8bef9SDimitry Andric } else { 1004e8d8bef9SDimitry Andric VarReg = RegM32; 1005e8d8bef9SDimitry Andric KillVarReg = KillM32; 1006e8d8bef9SDimitry Andric } 1007e8d8bef9SDimitry Andric // We don't want to get negative const from memory pool too early, as the 1008e8d8bef9SDimitry Andric // created entry will not be deleted even if it has no users. Since all 1009e8d8bef9SDimitry Andric // operand of Leaf and Root are virtual register, we use zero register 1010e8d8bef9SDimitry Andric // here as a placeholder. When the InsInstrs is selected in 1011e8d8bef9SDimitry Andric // MachineCombiner, we call finalizeInsInstrs to replace the zero register 1012e8d8bef9SDimitry Andric // with a virtual register which is a load from constant pool. 1013e8d8bef9SDimitry Andric NewARegPressure = BuildMI(*MF, Root.getDebugLoc(), get(FmaOp), NewVRA) 1014e8d8bef9SDimitry Andric .addReg(RegB, getKillRegState(RegB)) 1015e8d8bef9SDimitry Andric .addReg(RegY, getKillRegState(KillY)) 1016e8d8bef9SDimitry Andric .addReg(PPC::ZERO8); 1017e8d8bef9SDimitry Andric NewCRegPressure = BuildMI(*MF, Root.getDebugLoc(), get(FmaOp), RegC) 1018e8d8bef9SDimitry Andric .addReg(NewVRA, getKillRegState(true)) 1019e8d8bef9SDimitry Andric .addReg(RegX, getKillRegState(KillX)) 1020e8d8bef9SDimitry Andric .addReg(VarReg, getKillRegState(KillVarReg)); 1021e8d8bef9SDimitry Andric // For now, we only support xsmaddadp/xsmaddasp, their add operand are 1022e8d8bef9SDimitry Andric // both at index 1, no need to adjust. 1023e8d8bef9SDimitry Andric // FIXME: when add more fma instructions support, like fma/fmas, adjust 1024e8d8bef9SDimitry Andric // the operand index here. 1025e8d8bef9SDimitry Andric break; 1026e8d8bef9SDimitry Andric } 1027e8d8bef9SDimitry Andric } 1028e8d8bef9SDimitry Andric 1029e8d8bef9SDimitry Andric if (!IsILPReassociate) { 1030e8d8bef9SDimitry Andric setSpecialOperandAttr(*NewARegPressure, IntersectedFlags); 1031e8d8bef9SDimitry Andric setSpecialOperandAttr(*NewCRegPressure, IntersectedFlags); 1032e8d8bef9SDimitry Andric 1033e8d8bef9SDimitry Andric InsInstrs.push_back(NewARegPressure); 1034e8d8bef9SDimitry Andric InsInstrs.push_back(NewCRegPressure); 10355ffd83dbSDimitry Andric } 10365ffd83dbSDimitry Andric 10375ffd83dbSDimitry Andric assert(!InsInstrs.empty() && 10385ffd83dbSDimitry Andric "Insertion instructions set should not be empty!"); 10395ffd83dbSDimitry Andric 10405ffd83dbSDimitry Andric // Record old instructions for deletion. 10415ffd83dbSDimitry Andric DelInstrs.push_back(Leaf); 1042e8d8bef9SDimitry Andric if (IsILPReassociate) 10435ffd83dbSDimitry Andric DelInstrs.push_back(Prev); 10445ffd83dbSDimitry Andric DelInstrs.push_back(&Root); 10455ffd83dbSDimitry Andric } 10465ffd83dbSDimitry Andric 10470b57cec5SDimitry Andric // Detect 32 -> 64-bit extensions where we may reuse the low sub-register. 10480b57cec5SDimitry Andric bool PPCInstrInfo::isCoalescableExtInstr(const MachineInstr &MI, 10495ffd83dbSDimitry Andric Register &SrcReg, Register &DstReg, 10500b57cec5SDimitry Andric unsigned &SubIdx) const { 10510b57cec5SDimitry Andric switch (MI.getOpcode()) { 10520b57cec5SDimitry Andric default: return false; 10530b57cec5SDimitry Andric case PPC::EXTSW: 10540b57cec5SDimitry Andric case PPC::EXTSW_32: 10550b57cec5SDimitry Andric case PPC::EXTSW_32_64: 10560b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 10570b57cec5SDimitry Andric DstReg = MI.getOperand(0).getReg(); 10580b57cec5SDimitry Andric SubIdx = PPC::sub_32; 10590b57cec5SDimitry Andric return true; 10600b57cec5SDimitry Andric } 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric 10630fca6ea1SDimitry Andric Register PPCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 10640b57cec5SDimitry Andric int &FrameIndex) const { 1065bdd1243dSDimitry Andric if (llvm::is_contained(getLoadOpcodesForSpillArray(), MI.getOpcode())) { 10660b57cec5SDimitry Andric // Check for the operands added by addFrameReference (the immediate is the 10670b57cec5SDimitry Andric // offset which defaults to 0). 10680b57cec5SDimitry Andric if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() && 10690b57cec5SDimitry Andric MI.getOperand(2).isFI()) { 10700b57cec5SDimitry Andric FrameIndex = MI.getOperand(2).getIndex(); 10710b57cec5SDimitry Andric return MI.getOperand(0).getReg(); 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric return 0; 10750b57cec5SDimitry Andric } 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric // For opcodes with the ReMaterializable flag set, this function is called to 10780b57cec5SDimitry Andric // verify the instruction is really rematable. 1079fcaf7f86SDimitry Andric bool PPCInstrInfo::isReallyTriviallyReMaterializable( 1080fcaf7f86SDimitry Andric const MachineInstr &MI) const { 10810b57cec5SDimitry Andric switch (MI.getOpcode()) { 10820b57cec5SDimitry Andric default: 1083cb14a3feSDimitry Andric // Let base implementaion decide. 10840b57cec5SDimitry Andric break; 10850b57cec5SDimitry Andric case PPC::LI: 10860b57cec5SDimitry Andric case PPC::LI8: 1087fe6060f1SDimitry Andric case PPC::PLI: 1088fe6060f1SDimitry Andric case PPC::PLI8: 10890b57cec5SDimitry Andric case PPC::LIS: 10900b57cec5SDimitry Andric case PPC::LIS8: 10910b57cec5SDimitry Andric case PPC::ADDIStocHA: 10928bcb0991SDimitry Andric case PPC::ADDIStocHA8: 10930b57cec5SDimitry Andric case PPC::ADDItocL: 10940fca6ea1SDimitry Andric case PPC::ADDItocL8: 10950b57cec5SDimitry Andric case PPC::LOAD_STACK_GUARD: 10960fca6ea1SDimitry Andric case PPC::PPCLdFixedAddr: 10970b57cec5SDimitry Andric case PPC::XXLXORz: 10980b57cec5SDimitry Andric case PPC::XXLXORspz: 10990b57cec5SDimitry Andric case PPC::XXLXORdpz: 11008bcb0991SDimitry Andric case PPC::XXLEQVOnes: 1101fe6060f1SDimitry Andric case PPC::XXSPLTI32DX: 1102349cc55cSDimitry Andric case PPC::XXSPLTIW: 1103349cc55cSDimitry Andric case PPC::XXSPLTIDP: 11040b57cec5SDimitry Andric case PPC::V_SET0B: 11050b57cec5SDimitry Andric case PPC::V_SET0H: 11060b57cec5SDimitry Andric case PPC::V_SET0: 11070b57cec5SDimitry Andric case PPC::V_SETALLONESB: 11080b57cec5SDimitry Andric case PPC::V_SETALLONESH: 11090b57cec5SDimitry Andric case PPC::V_SETALLONES: 11100b57cec5SDimitry Andric case PPC::CRSET: 11110b57cec5SDimitry Andric case PPC::CRUNSET: 1112e8d8bef9SDimitry Andric case PPC::XXSETACCZ: 1113bdd1243dSDimitry Andric case PPC::XXSETACCZW: 11140b57cec5SDimitry Andric return true; 11150b57cec5SDimitry Andric } 11165f757f3fSDimitry Andric return TargetInstrInfo::isReallyTriviallyReMaterializable(MI); 11170b57cec5SDimitry Andric } 11180b57cec5SDimitry Andric 11190fca6ea1SDimitry Andric Register PPCInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 11200b57cec5SDimitry Andric int &FrameIndex) const { 1121bdd1243dSDimitry Andric if (llvm::is_contained(getStoreOpcodesForSpillArray(), MI.getOpcode())) { 11220b57cec5SDimitry Andric if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() && 11230b57cec5SDimitry Andric MI.getOperand(2).isFI()) { 11240b57cec5SDimitry Andric FrameIndex = MI.getOperand(2).getIndex(); 11250b57cec5SDimitry Andric return MI.getOperand(0).getReg(); 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric } 11280b57cec5SDimitry Andric return 0; 11290b57cec5SDimitry Andric } 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric MachineInstr *PPCInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, 11320b57cec5SDimitry Andric unsigned OpIdx1, 11330b57cec5SDimitry Andric unsigned OpIdx2) const { 11340b57cec5SDimitry Andric MachineFunction &MF = *MI.getParent()->getParent(); 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric // Normal instructions can be commuted the obvious way. 1137480093f4SDimitry Andric if (MI.getOpcode() != PPC::RLWIMI && MI.getOpcode() != PPC::RLWIMI_rec) 11380b57cec5SDimitry Andric return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2); 11390b57cec5SDimitry Andric // Note that RLWIMI can be commuted as a 32-bit instruction, but not as a 11400b57cec5SDimitry Andric // 64-bit instruction (so we don't handle PPC::RLWIMI8 here), because 11410b57cec5SDimitry Andric // changing the relative order of the mask operands might change what happens 11420b57cec5SDimitry Andric // to the high-bits of the mask (and, thus, the result). 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric // Cannot commute if it has a non-zero rotate count. 11450b57cec5SDimitry Andric if (MI.getOperand(3).getImm() != 0) 11460b57cec5SDimitry Andric return nullptr; 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric // If we have a zero rotate count, we have: 11490b57cec5SDimitry Andric // M = mask(MB,ME) 11500b57cec5SDimitry Andric // Op0 = (Op1 & ~M) | (Op2 & M) 11510b57cec5SDimitry Andric // Change this to: 11520b57cec5SDimitry Andric // M = mask((ME+1)&31, (MB-1)&31) 11530b57cec5SDimitry Andric // Op0 = (Op2 & ~M) | (Op1 & M) 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric // Swap op1/op2 11560b57cec5SDimitry Andric assert(((OpIdx1 == 1 && OpIdx2 == 2) || (OpIdx1 == 2 && OpIdx2 == 1)) && 1157480093f4SDimitry Andric "Only the operands 1 and 2 can be swapped in RLSIMI/RLWIMI_rec."); 11580b57cec5SDimitry Andric Register Reg0 = MI.getOperand(0).getReg(); 11590b57cec5SDimitry Andric Register Reg1 = MI.getOperand(1).getReg(); 11600b57cec5SDimitry Andric Register Reg2 = MI.getOperand(2).getReg(); 11610b57cec5SDimitry Andric unsigned SubReg1 = MI.getOperand(1).getSubReg(); 11620b57cec5SDimitry Andric unsigned SubReg2 = MI.getOperand(2).getSubReg(); 11630b57cec5SDimitry Andric bool Reg1IsKill = MI.getOperand(1).isKill(); 11640b57cec5SDimitry Andric bool Reg2IsKill = MI.getOperand(2).isKill(); 11650b57cec5SDimitry Andric bool ChangeReg0 = false; 11660b57cec5SDimitry Andric // If machine instrs are no longer in two-address forms, update 11670b57cec5SDimitry Andric // destination register as well. 11680b57cec5SDimitry Andric if (Reg0 == Reg1) { 11695f757f3fSDimitry Andric // Must be two address instruction (i.e. op1 is tied to op0). 11705f757f3fSDimitry Andric assert(MI.getDesc().getOperandConstraint(1, MCOI::TIED_TO) == 0 && 11710b57cec5SDimitry Andric "Expecting a two-address instruction!"); 11720b57cec5SDimitry Andric assert(MI.getOperand(0).getSubReg() == SubReg1 && "Tied subreg mismatch"); 11730b57cec5SDimitry Andric Reg2IsKill = false; 11740b57cec5SDimitry Andric ChangeReg0 = true; 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric // Masks. 11780b57cec5SDimitry Andric unsigned MB = MI.getOperand(4).getImm(); 11790b57cec5SDimitry Andric unsigned ME = MI.getOperand(5).getImm(); 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andric // We can't commute a trivial mask (there is no way to represent an all-zero 11820b57cec5SDimitry Andric // mask). 11830b57cec5SDimitry Andric if (MB == 0 && ME == 31) 11840b57cec5SDimitry Andric return nullptr; 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric if (NewMI) { 11870b57cec5SDimitry Andric // Create a new instruction. 11880b57cec5SDimitry Andric Register Reg0 = ChangeReg0 ? Reg2 : MI.getOperand(0).getReg(); 11890b57cec5SDimitry Andric bool Reg0IsDead = MI.getOperand(0).isDead(); 11900b57cec5SDimitry Andric return BuildMI(MF, MI.getDebugLoc(), MI.getDesc()) 11910b57cec5SDimitry Andric .addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead)) 11920b57cec5SDimitry Andric .addReg(Reg2, getKillRegState(Reg2IsKill)) 11930b57cec5SDimitry Andric .addReg(Reg1, getKillRegState(Reg1IsKill)) 11940b57cec5SDimitry Andric .addImm((ME + 1) & 31) 11950b57cec5SDimitry Andric .addImm((MB - 1) & 31); 11960b57cec5SDimitry Andric } 11970b57cec5SDimitry Andric 11980b57cec5SDimitry Andric if (ChangeReg0) { 11990b57cec5SDimitry Andric MI.getOperand(0).setReg(Reg2); 12000b57cec5SDimitry Andric MI.getOperand(0).setSubReg(SubReg2); 12010b57cec5SDimitry Andric } 12020b57cec5SDimitry Andric MI.getOperand(2).setReg(Reg1); 12030b57cec5SDimitry Andric MI.getOperand(1).setReg(Reg2); 12040b57cec5SDimitry Andric MI.getOperand(2).setSubReg(SubReg1); 12050b57cec5SDimitry Andric MI.getOperand(1).setSubReg(SubReg2); 12060b57cec5SDimitry Andric MI.getOperand(2).setIsKill(Reg1IsKill); 12070b57cec5SDimitry Andric MI.getOperand(1).setIsKill(Reg2IsKill); 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric // Swap the mask around. 12100b57cec5SDimitry Andric MI.getOperand(4).setImm((ME + 1) & 31); 12110b57cec5SDimitry Andric MI.getOperand(5).setImm((MB - 1) & 31); 12120b57cec5SDimitry Andric return &MI; 12130b57cec5SDimitry Andric } 12140b57cec5SDimitry Andric 12158bcb0991SDimitry Andric bool PPCInstrInfo::findCommutedOpIndices(const MachineInstr &MI, 12168bcb0991SDimitry Andric unsigned &SrcOpIdx1, 12170b57cec5SDimitry Andric unsigned &SrcOpIdx2) const { 12180b57cec5SDimitry Andric // For VSX A-Type FMA instructions, it is the first two operands that can be 12190b57cec5SDimitry Andric // commuted, however, because the non-encoded tied input operand is listed 12200b57cec5SDimitry Andric // first, the operands to swap are actually the second and third. 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric int AltOpc = PPC::getAltVSXFMAOpcode(MI.getOpcode()); 12230b57cec5SDimitry Andric if (AltOpc == -1) 12240b57cec5SDimitry Andric return TargetInstrInfo::findCommutedOpIndices(MI, SrcOpIdx1, SrcOpIdx2); 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric // The commutable operand indices are 2 and 3. Return them in SrcOpIdx1 12270b57cec5SDimitry Andric // and SrcOpIdx2. 12280b57cec5SDimitry Andric return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3); 12290b57cec5SDimitry Andric } 12300b57cec5SDimitry Andric 12310b57cec5SDimitry Andric void PPCInstrInfo::insertNoop(MachineBasicBlock &MBB, 12320b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const { 12330b57cec5SDimitry Andric // This function is used for scheduling, and the nop wanted here is the type 12340b57cec5SDimitry Andric // that terminates dispatch groups on the POWER cores. 1235480093f4SDimitry Andric unsigned Directive = Subtarget.getCPUDirective(); 12360b57cec5SDimitry Andric unsigned Opcode; 12370b57cec5SDimitry Andric switch (Directive) { 12380b57cec5SDimitry Andric default: Opcode = PPC::NOP; break; 12390b57cec5SDimitry Andric case PPC::DIR_PWR6: Opcode = PPC::NOP_GT_PWR6; break; 12400b57cec5SDimitry Andric case PPC::DIR_PWR7: Opcode = PPC::NOP_GT_PWR7; break; 12410b57cec5SDimitry Andric case PPC::DIR_PWR8: Opcode = PPC::NOP_GT_PWR7; break; /* FIXME: Update when P8 InstrScheduling model is ready */ 12420b57cec5SDimitry Andric // FIXME: Update when POWER9 scheduling model is ready. 12430b57cec5SDimitry Andric case PPC::DIR_PWR9: Opcode = PPC::NOP_GT_PWR7; break; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric DebugLoc DL; 12470b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(Opcode)); 12480b57cec5SDimitry Andric } 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric /// Return the noop instruction to use for a noop. 1251fe6060f1SDimitry Andric MCInst PPCInstrInfo::getNop() const { 1252fe6060f1SDimitry Andric MCInst Nop; 1253fe6060f1SDimitry Andric Nop.setOpcode(PPC::NOP); 1254fe6060f1SDimitry Andric return Nop; 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric 12570b57cec5SDimitry Andric // Branch analysis. 12580b57cec5SDimitry Andric // Note: If the condition register is set to CTR or CTR8 then this is a 12590b57cec5SDimitry Andric // BDNZ (imm == 1) or BDZ (imm == 0) branch. 12600b57cec5SDimitry Andric bool PPCInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 12610b57cec5SDimitry Andric MachineBasicBlock *&TBB, 12620b57cec5SDimitry Andric MachineBasicBlock *&FBB, 12630b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 12640b57cec5SDimitry Andric bool AllowModify) const { 12650b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric // If the block has no terminators, it just falls into the block after it. 12680b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 12690b57cec5SDimitry Andric if (I == MBB.end()) 12700b57cec5SDimitry Andric return false; 12710b57cec5SDimitry Andric 12720b57cec5SDimitry Andric if (!isUnpredicatedTerminator(*I)) 12730b57cec5SDimitry Andric return false; 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric if (AllowModify) { 12760b57cec5SDimitry Andric // If the BB ends with an unconditional branch to the fallthrough BB, 12770b57cec5SDimitry Andric // we eliminate the branch instruction. 12780b57cec5SDimitry Andric if (I->getOpcode() == PPC::B && 12790b57cec5SDimitry Andric MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 12800b57cec5SDimitry Andric I->eraseFromParent(); 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric // We update iterator after deleting the last branch. 12830b57cec5SDimitry Andric I = MBB.getLastNonDebugInstr(); 12840b57cec5SDimitry Andric if (I == MBB.end() || !isUnpredicatedTerminator(*I)) 12850b57cec5SDimitry Andric return false; 12860b57cec5SDimitry Andric } 12870b57cec5SDimitry Andric } 12880b57cec5SDimitry Andric 12890b57cec5SDimitry Andric // Get the last instruction in the block. 12900b57cec5SDimitry Andric MachineInstr &LastInst = *I; 12910b57cec5SDimitry Andric 12920b57cec5SDimitry Andric // If there is only one terminator instruction, process it. 12930b57cec5SDimitry Andric if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) { 12940b57cec5SDimitry Andric if (LastInst.getOpcode() == PPC::B) { 12950b57cec5SDimitry Andric if (!LastInst.getOperand(0).isMBB()) 12960b57cec5SDimitry Andric return true; 12970b57cec5SDimitry Andric TBB = LastInst.getOperand(0).getMBB(); 12980b57cec5SDimitry Andric return false; 12990b57cec5SDimitry Andric } else if (LastInst.getOpcode() == PPC::BCC) { 13000b57cec5SDimitry Andric if (!LastInst.getOperand(2).isMBB()) 13010b57cec5SDimitry Andric return true; 13020b57cec5SDimitry Andric // Block ends with fall-through condbranch. 13030b57cec5SDimitry Andric TBB = LastInst.getOperand(2).getMBB(); 13040b57cec5SDimitry Andric Cond.push_back(LastInst.getOperand(0)); 13050b57cec5SDimitry Andric Cond.push_back(LastInst.getOperand(1)); 13060b57cec5SDimitry Andric return false; 13070b57cec5SDimitry Andric } else if (LastInst.getOpcode() == PPC::BC) { 13080b57cec5SDimitry Andric if (!LastInst.getOperand(1).isMBB()) 13090b57cec5SDimitry Andric return true; 13100b57cec5SDimitry Andric // Block ends with fall-through condbranch. 13110b57cec5SDimitry Andric TBB = LastInst.getOperand(1).getMBB(); 13120b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_SET)); 13130b57cec5SDimitry Andric Cond.push_back(LastInst.getOperand(0)); 13140b57cec5SDimitry Andric return false; 13150b57cec5SDimitry Andric } else if (LastInst.getOpcode() == PPC::BCn) { 13160b57cec5SDimitry Andric if (!LastInst.getOperand(1).isMBB()) 13170b57cec5SDimitry Andric return true; 13180b57cec5SDimitry Andric // Block ends with fall-through condbranch. 13190b57cec5SDimitry Andric TBB = LastInst.getOperand(1).getMBB(); 13200b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_UNSET)); 13210b57cec5SDimitry Andric Cond.push_back(LastInst.getOperand(0)); 13220b57cec5SDimitry Andric return false; 13230b57cec5SDimitry Andric } else if (LastInst.getOpcode() == PPC::BDNZ8 || 13240b57cec5SDimitry Andric LastInst.getOpcode() == PPC::BDNZ) { 13250b57cec5SDimitry Andric if (!LastInst.getOperand(0).isMBB()) 13260b57cec5SDimitry Andric return true; 13270b57cec5SDimitry Andric if (DisableCTRLoopAnal) 13280b57cec5SDimitry Andric return true; 13290b57cec5SDimitry Andric TBB = LastInst.getOperand(0).getMBB(); 13300b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(1)); 13310b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR, 13320b57cec5SDimitry Andric true)); 13330b57cec5SDimitry Andric return false; 13340b57cec5SDimitry Andric } else if (LastInst.getOpcode() == PPC::BDZ8 || 13350b57cec5SDimitry Andric LastInst.getOpcode() == PPC::BDZ) { 13360b57cec5SDimitry Andric if (!LastInst.getOperand(0).isMBB()) 13370b57cec5SDimitry Andric return true; 13380b57cec5SDimitry Andric if (DisableCTRLoopAnal) 13390b57cec5SDimitry Andric return true; 13400b57cec5SDimitry Andric TBB = LastInst.getOperand(0).getMBB(); 13410b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(0)); 13420b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR, 13430b57cec5SDimitry Andric true)); 13440b57cec5SDimitry Andric return false; 13450b57cec5SDimitry Andric } 13460b57cec5SDimitry Andric 13470b57cec5SDimitry Andric // Otherwise, don't know what this is. 13480b57cec5SDimitry Andric return true; 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric 13510b57cec5SDimitry Andric // Get the instruction before it if it's a terminator. 13520b57cec5SDimitry Andric MachineInstr &SecondLastInst = *I; 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andric // If there are three terminators, we don't know what sort of block this is. 13550b57cec5SDimitry Andric if (I != MBB.begin() && isUnpredicatedTerminator(*--I)) 13560b57cec5SDimitry Andric return true; 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric // If the block ends with PPC::B and PPC:BCC, handle it. 13590b57cec5SDimitry Andric if (SecondLastInst.getOpcode() == PPC::BCC && 13600b57cec5SDimitry Andric LastInst.getOpcode() == PPC::B) { 13610b57cec5SDimitry Andric if (!SecondLastInst.getOperand(2).isMBB() || 13620b57cec5SDimitry Andric !LastInst.getOperand(0).isMBB()) 13630b57cec5SDimitry Andric return true; 13640b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(2).getMBB(); 13650b57cec5SDimitry Andric Cond.push_back(SecondLastInst.getOperand(0)); 13660b57cec5SDimitry Andric Cond.push_back(SecondLastInst.getOperand(1)); 13670b57cec5SDimitry Andric FBB = LastInst.getOperand(0).getMBB(); 13680b57cec5SDimitry Andric return false; 13690b57cec5SDimitry Andric } else if (SecondLastInst.getOpcode() == PPC::BC && 13700b57cec5SDimitry Andric LastInst.getOpcode() == PPC::B) { 13710b57cec5SDimitry Andric if (!SecondLastInst.getOperand(1).isMBB() || 13720b57cec5SDimitry Andric !LastInst.getOperand(0).isMBB()) 13730b57cec5SDimitry Andric return true; 13740b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(1).getMBB(); 13750b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_SET)); 13760b57cec5SDimitry Andric Cond.push_back(SecondLastInst.getOperand(0)); 13770b57cec5SDimitry Andric FBB = LastInst.getOperand(0).getMBB(); 13780b57cec5SDimitry Andric return false; 13790b57cec5SDimitry Andric } else if (SecondLastInst.getOpcode() == PPC::BCn && 13800b57cec5SDimitry Andric LastInst.getOpcode() == PPC::B) { 13810b57cec5SDimitry Andric if (!SecondLastInst.getOperand(1).isMBB() || 13820b57cec5SDimitry Andric !LastInst.getOperand(0).isMBB()) 13830b57cec5SDimitry Andric return true; 13840b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(1).getMBB(); 13850b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(PPC::PRED_BIT_UNSET)); 13860b57cec5SDimitry Andric Cond.push_back(SecondLastInst.getOperand(0)); 13870b57cec5SDimitry Andric FBB = LastInst.getOperand(0).getMBB(); 13880b57cec5SDimitry Andric return false; 13890b57cec5SDimitry Andric } else if ((SecondLastInst.getOpcode() == PPC::BDNZ8 || 13900b57cec5SDimitry Andric SecondLastInst.getOpcode() == PPC::BDNZ) && 13910b57cec5SDimitry Andric LastInst.getOpcode() == PPC::B) { 13920b57cec5SDimitry Andric if (!SecondLastInst.getOperand(0).isMBB() || 13930b57cec5SDimitry Andric !LastInst.getOperand(0).isMBB()) 13940b57cec5SDimitry Andric return true; 13950b57cec5SDimitry Andric if (DisableCTRLoopAnal) 13960b57cec5SDimitry Andric return true; 13970b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(0).getMBB(); 13980b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(1)); 13990b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR, 14000b57cec5SDimitry Andric true)); 14010b57cec5SDimitry Andric FBB = LastInst.getOperand(0).getMBB(); 14020b57cec5SDimitry Andric return false; 14030b57cec5SDimitry Andric } else if ((SecondLastInst.getOpcode() == PPC::BDZ8 || 14040b57cec5SDimitry Andric SecondLastInst.getOpcode() == PPC::BDZ) && 14050b57cec5SDimitry Andric LastInst.getOpcode() == PPC::B) { 14060b57cec5SDimitry Andric if (!SecondLastInst.getOperand(0).isMBB() || 14070b57cec5SDimitry Andric !LastInst.getOperand(0).isMBB()) 14080b57cec5SDimitry Andric return true; 14090b57cec5SDimitry Andric if (DisableCTRLoopAnal) 14100b57cec5SDimitry Andric return true; 14110b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(0).getMBB(); 14120b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateImm(0)); 14130b57cec5SDimitry Andric Cond.push_back(MachineOperand::CreateReg(isPPC64 ? PPC::CTR8 : PPC::CTR, 14140b57cec5SDimitry Andric true)); 14150b57cec5SDimitry Andric FBB = LastInst.getOperand(0).getMBB(); 14160b57cec5SDimitry Andric return false; 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric // If the block ends with two PPC:Bs, handle it. The second one is not 14200b57cec5SDimitry Andric // executed, so remove it. 14210b57cec5SDimitry Andric if (SecondLastInst.getOpcode() == PPC::B && LastInst.getOpcode() == PPC::B) { 14220b57cec5SDimitry Andric if (!SecondLastInst.getOperand(0).isMBB()) 14230b57cec5SDimitry Andric return true; 14240b57cec5SDimitry Andric TBB = SecondLastInst.getOperand(0).getMBB(); 14250b57cec5SDimitry Andric I = LastInst; 14260b57cec5SDimitry Andric if (AllowModify) 14270b57cec5SDimitry Andric I->eraseFromParent(); 14280b57cec5SDimitry Andric return false; 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric // Otherwise, can't handle this. 14320b57cec5SDimitry Andric return true; 14330b57cec5SDimitry Andric } 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric unsigned PPCInstrInfo::removeBranch(MachineBasicBlock &MBB, 14360b57cec5SDimitry Andric int *BytesRemoved) const { 14370b57cec5SDimitry Andric assert(!BytesRemoved && "code size not handled"); 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 14400b57cec5SDimitry Andric if (I == MBB.end()) 14410b57cec5SDimitry Andric return 0; 14420b57cec5SDimitry Andric 14430b57cec5SDimitry Andric if (I->getOpcode() != PPC::B && I->getOpcode() != PPC::BCC && 14440b57cec5SDimitry Andric I->getOpcode() != PPC::BC && I->getOpcode() != PPC::BCn && 14450b57cec5SDimitry Andric I->getOpcode() != PPC::BDNZ8 && I->getOpcode() != PPC::BDNZ && 14460b57cec5SDimitry Andric I->getOpcode() != PPC::BDZ8 && I->getOpcode() != PPC::BDZ) 14470b57cec5SDimitry Andric return 0; 14480b57cec5SDimitry Andric 14490b57cec5SDimitry Andric // Remove the branch. 14500b57cec5SDimitry Andric I->eraseFromParent(); 14510b57cec5SDimitry Andric 14520b57cec5SDimitry Andric I = MBB.end(); 14530b57cec5SDimitry Andric 14540b57cec5SDimitry Andric if (I == MBB.begin()) return 1; 14550b57cec5SDimitry Andric --I; 14560b57cec5SDimitry Andric if (I->getOpcode() != PPC::BCC && 14570b57cec5SDimitry Andric I->getOpcode() != PPC::BC && I->getOpcode() != PPC::BCn && 14580b57cec5SDimitry Andric I->getOpcode() != PPC::BDNZ8 && I->getOpcode() != PPC::BDNZ && 14590b57cec5SDimitry Andric I->getOpcode() != PPC::BDZ8 && I->getOpcode() != PPC::BDZ) 14600b57cec5SDimitry Andric return 1; 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric // Remove the branch. 14630b57cec5SDimitry Andric I->eraseFromParent(); 14640b57cec5SDimitry Andric return 2; 14650b57cec5SDimitry Andric } 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric unsigned PPCInstrInfo::insertBranch(MachineBasicBlock &MBB, 14680b57cec5SDimitry Andric MachineBasicBlock *TBB, 14690b57cec5SDimitry Andric MachineBasicBlock *FBB, 14700b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 14710b57cec5SDimitry Andric const DebugLoc &DL, 14720b57cec5SDimitry Andric int *BytesAdded) const { 14730b57cec5SDimitry Andric // Shouldn't be a fall through. 14740b57cec5SDimitry Andric assert(TBB && "insertBranch must not be told to insert a fallthrough"); 14750b57cec5SDimitry Andric assert((Cond.size() == 2 || Cond.size() == 0) && 14760b57cec5SDimitry Andric "PPC branch conditions have two components!"); 14770b57cec5SDimitry Andric assert(!BytesAdded && "code size not handled"); 14780b57cec5SDimitry Andric 14790b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 14800b57cec5SDimitry Andric 14810b57cec5SDimitry Andric // One-way branch. 14820b57cec5SDimitry Andric if (!FBB) { 14830b57cec5SDimitry Andric if (Cond.empty()) // Unconditional branch 14840b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::B)).addMBB(TBB); 14850b57cec5SDimitry Andric else if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8) 14860b57cec5SDimitry Andric BuildMI(&MBB, DL, get(Cond[0].getImm() ? 14870b57cec5SDimitry Andric (isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) : 14880b57cec5SDimitry Andric (isPPC64 ? PPC::BDZ8 : PPC::BDZ))).addMBB(TBB); 14890b57cec5SDimitry Andric else if (Cond[0].getImm() == PPC::PRED_BIT_SET) 14900b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::BC)).add(Cond[1]).addMBB(TBB); 14910b57cec5SDimitry Andric else if (Cond[0].getImm() == PPC::PRED_BIT_UNSET) 14920b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::BCn)).add(Cond[1]).addMBB(TBB); 14930b57cec5SDimitry Andric else // Conditional branch 14940b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::BCC)) 14950b57cec5SDimitry Andric .addImm(Cond[0].getImm()) 14960b57cec5SDimitry Andric .add(Cond[1]) 14970b57cec5SDimitry Andric .addMBB(TBB); 14980b57cec5SDimitry Andric return 1; 14990b57cec5SDimitry Andric } 15000b57cec5SDimitry Andric 15010b57cec5SDimitry Andric // Two-way Conditional Branch. 15020b57cec5SDimitry Andric if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8) 15030b57cec5SDimitry Andric BuildMI(&MBB, DL, get(Cond[0].getImm() ? 15040b57cec5SDimitry Andric (isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) : 15050b57cec5SDimitry Andric (isPPC64 ? PPC::BDZ8 : PPC::BDZ))).addMBB(TBB); 15060b57cec5SDimitry Andric else if (Cond[0].getImm() == PPC::PRED_BIT_SET) 15070b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::BC)).add(Cond[1]).addMBB(TBB); 15080b57cec5SDimitry Andric else if (Cond[0].getImm() == PPC::PRED_BIT_UNSET) 15090b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::BCn)).add(Cond[1]).addMBB(TBB); 15100b57cec5SDimitry Andric else 15110b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::BCC)) 15120b57cec5SDimitry Andric .addImm(Cond[0].getImm()) 15130b57cec5SDimitry Andric .add(Cond[1]) 15140b57cec5SDimitry Andric .addMBB(TBB); 15150b57cec5SDimitry Andric BuildMI(&MBB, DL, get(PPC::B)).addMBB(FBB); 15160b57cec5SDimitry Andric return 2; 15170b57cec5SDimitry Andric } 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric // Select analysis. 15200b57cec5SDimitry Andric bool PPCInstrInfo::canInsertSelect(const MachineBasicBlock &MBB, 15210b57cec5SDimitry Andric ArrayRef<MachineOperand> Cond, 15225ffd83dbSDimitry Andric Register DstReg, Register TrueReg, 15235ffd83dbSDimitry Andric Register FalseReg, int &CondCycles, 15245ffd83dbSDimitry Andric int &TrueCycles, int &FalseCycles) const { 15255f757f3fSDimitry Andric if (!Subtarget.hasISEL()) 15265f757f3fSDimitry Andric return false; 15275f757f3fSDimitry Andric 15280b57cec5SDimitry Andric if (Cond.size() != 2) 15290b57cec5SDimitry Andric return false; 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric // If this is really a bdnz-like condition, then it cannot be turned into a 15320b57cec5SDimitry Andric // select. 15330b57cec5SDimitry Andric if (Cond[1].getReg() == PPC::CTR || Cond[1].getReg() == PPC::CTR8) 15340b57cec5SDimitry Andric return false; 15350b57cec5SDimitry Andric 1536349cc55cSDimitry Andric // If the conditional branch uses a physical register, then it cannot be 1537349cc55cSDimitry Andric // turned into a select. 1538bdd1243dSDimitry Andric if (Cond[1].getReg().isPhysical()) 1539349cc55cSDimitry Andric return false; 1540349cc55cSDimitry Andric 15410b57cec5SDimitry Andric // Check register classes. 15420b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 15430b57cec5SDimitry Andric const TargetRegisterClass *RC = 15440b57cec5SDimitry Andric RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg)); 15450b57cec5SDimitry Andric if (!RC) 15460b57cec5SDimitry Andric return false; 15470b57cec5SDimitry Andric 15480b57cec5SDimitry Andric // isel is for regular integer GPRs only. 15490b57cec5SDimitry Andric if (!PPC::GPRCRegClass.hasSubClassEq(RC) && 15500b57cec5SDimitry Andric !PPC::GPRC_NOR0RegClass.hasSubClassEq(RC) && 15510b57cec5SDimitry Andric !PPC::G8RCRegClass.hasSubClassEq(RC) && 15520b57cec5SDimitry Andric !PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) 15530b57cec5SDimitry Andric return false; 15540b57cec5SDimitry Andric 15550b57cec5SDimitry Andric // FIXME: These numbers are for the A2, how well they work for other cores is 15560b57cec5SDimitry Andric // an open question. On the A2, the isel instruction has a 2-cycle latency 15570b57cec5SDimitry Andric // but single-cycle throughput. These numbers are used in combination with 15580b57cec5SDimitry Andric // the MispredictPenalty setting from the active SchedMachineModel. 15590b57cec5SDimitry Andric CondCycles = 1; 15600b57cec5SDimitry Andric TrueCycles = 1; 15610b57cec5SDimitry Andric FalseCycles = 1; 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric return true; 15640b57cec5SDimitry Andric } 15650b57cec5SDimitry Andric 15660b57cec5SDimitry Andric void PPCInstrInfo::insertSelect(MachineBasicBlock &MBB, 15670b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 15685ffd83dbSDimitry Andric const DebugLoc &dl, Register DestReg, 15695ffd83dbSDimitry Andric ArrayRef<MachineOperand> Cond, Register TrueReg, 15705ffd83dbSDimitry Andric Register FalseReg) const { 15710b57cec5SDimitry Andric assert(Cond.size() == 2 && 15720b57cec5SDimitry Andric "PPC branch conditions have two components!"); 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric // Get the register classes. 15750b57cec5SDimitry Andric MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 15760b57cec5SDimitry Andric const TargetRegisterClass *RC = 15770b57cec5SDimitry Andric RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg)); 15780b57cec5SDimitry Andric assert(RC && "TrueReg and FalseReg must have overlapping register classes"); 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric bool Is64Bit = PPC::G8RCRegClass.hasSubClassEq(RC) || 15810b57cec5SDimitry Andric PPC::G8RC_NOX0RegClass.hasSubClassEq(RC); 15820b57cec5SDimitry Andric assert((Is64Bit || 15830b57cec5SDimitry Andric PPC::GPRCRegClass.hasSubClassEq(RC) || 15840b57cec5SDimitry Andric PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) && 15850b57cec5SDimitry Andric "isel is for regular integer GPRs only"); 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric unsigned OpCode = Is64Bit ? PPC::ISEL8 : PPC::ISEL; 15880b57cec5SDimitry Andric auto SelectPred = static_cast<PPC::Predicate>(Cond[0].getImm()); 15890b57cec5SDimitry Andric 15900b57cec5SDimitry Andric unsigned SubIdx = 0; 15910b57cec5SDimitry Andric bool SwapOps = false; 15920b57cec5SDimitry Andric switch (SelectPred) { 15930b57cec5SDimitry Andric case PPC::PRED_EQ: 15940b57cec5SDimitry Andric case PPC::PRED_EQ_MINUS: 15950b57cec5SDimitry Andric case PPC::PRED_EQ_PLUS: 15960b57cec5SDimitry Andric SubIdx = PPC::sub_eq; SwapOps = false; break; 15970b57cec5SDimitry Andric case PPC::PRED_NE: 15980b57cec5SDimitry Andric case PPC::PRED_NE_MINUS: 15990b57cec5SDimitry Andric case PPC::PRED_NE_PLUS: 16000b57cec5SDimitry Andric SubIdx = PPC::sub_eq; SwapOps = true; break; 16010b57cec5SDimitry Andric case PPC::PRED_LT: 16020b57cec5SDimitry Andric case PPC::PRED_LT_MINUS: 16030b57cec5SDimitry Andric case PPC::PRED_LT_PLUS: 16040b57cec5SDimitry Andric SubIdx = PPC::sub_lt; SwapOps = false; break; 16050b57cec5SDimitry Andric case PPC::PRED_GE: 16060b57cec5SDimitry Andric case PPC::PRED_GE_MINUS: 16070b57cec5SDimitry Andric case PPC::PRED_GE_PLUS: 16080b57cec5SDimitry Andric SubIdx = PPC::sub_lt; SwapOps = true; break; 16090b57cec5SDimitry Andric case PPC::PRED_GT: 16100b57cec5SDimitry Andric case PPC::PRED_GT_MINUS: 16110b57cec5SDimitry Andric case PPC::PRED_GT_PLUS: 16120b57cec5SDimitry Andric SubIdx = PPC::sub_gt; SwapOps = false; break; 16130b57cec5SDimitry Andric case PPC::PRED_LE: 16140b57cec5SDimitry Andric case PPC::PRED_LE_MINUS: 16150b57cec5SDimitry Andric case PPC::PRED_LE_PLUS: 16160b57cec5SDimitry Andric SubIdx = PPC::sub_gt; SwapOps = true; break; 16170b57cec5SDimitry Andric case PPC::PRED_UN: 16180b57cec5SDimitry Andric case PPC::PRED_UN_MINUS: 16190b57cec5SDimitry Andric case PPC::PRED_UN_PLUS: 16200b57cec5SDimitry Andric SubIdx = PPC::sub_un; SwapOps = false; break; 16210b57cec5SDimitry Andric case PPC::PRED_NU: 16220b57cec5SDimitry Andric case PPC::PRED_NU_MINUS: 16230b57cec5SDimitry Andric case PPC::PRED_NU_PLUS: 16240b57cec5SDimitry Andric SubIdx = PPC::sub_un; SwapOps = true; break; 16250b57cec5SDimitry Andric case PPC::PRED_BIT_SET: SubIdx = 0; SwapOps = false; break; 16260b57cec5SDimitry Andric case PPC::PRED_BIT_UNSET: SubIdx = 0; SwapOps = true; break; 16270b57cec5SDimitry Andric } 16280b57cec5SDimitry Andric 16295ffd83dbSDimitry Andric Register FirstReg = SwapOps ? FalseReg : TrueReg, 16300b57cec5SDimitry Andric SecondReg = SwapOps ? TrueReg : FalseReg; 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric // The first input register of isel cannot be r0. If it is a member 16330b57cec5SDimitry Andric // of a register class that can be r0, then copy it first (the 16340b57cec5SDimitry Andric // register allocator should eliminate the copy). 16350b57cec5SDimitry Andric if (MRI.getRegClass(FirstReg)->contains(PPC::R0) || 16360b57cec5SDimitry Andric MRI.getRegClass(FirstReg)->contains(PPC::X0)) { 16370b57cec5SDimitry Andric const TargetRegisterClass *FirstRC = 16380b57cec5SDimitry Andric MRI.getRegClass(FirstReg)->contains(PPC::X0) ? 16390b57cec5SDimitry Andric &PPC::G8RC_NOX0RegClass : &PPC::GPRC_NOR0RegClass; 16405ffd83dbSDimitry Andric Register OldFirstReg = FirstReg; 16410b57cec5SDimitry Andric FirstReg = MRI.createVirtualRegister(FirstRC); 16420b57cec5SDimitry Andric BuildMI(MBB, MI, dl, get(TargetOpcode::COPY), FirstReg) 16430b57cec5SDimitry Andric .addReg(OldFirstReg); 16440b57cec5SDimitry Andric } 16450b57cec5SDimitry Andric 16460b57cec5SDimitry Andric BuildMI(MBB, MI, dl, get(OpCode), DestReg) 16470b57cec5SDimitry Andric .addReg(FirstReg).addReg(SecondReg) 16480b57cec5SDimitry Andric .addReg(Cond[1].getReg(), 0, SubIdx); 16490b57cec5SDimitry Andric } 16500b57cec5SDimitry Andric 16510b57cec5SDimitry Andric static unsigned getCRBitValue(unsigned CRBit) { 16520b57cec5SDimitry Andric unsigned Ret = 4; 16530b57cec5SDimitry Andric if (CRBit == PPC::CR0LT || CRBit == PPC::CR1LT || 16540b57cec5SDimitry Andric CRBit == PPC::CR2LT || CRBit == PPC::CR3LT || 16550b57cec5SDimitry Andric CRBit == PPC::CR4LT || CRBit == PPC::CR5LT || 16560b57cec5SDimitry Andric CRBit == PPC::CR6LT || CRBit == PPC::CR7LT) 16570b57cec5SDimitry Andric Ret = 3; 16580b57cec5SDimitry Andric if (CRBit == PPC::CR0GT || CRBit == PPC::CR1GT || 16590b57cec5SDimitry Andric CRBit == PPC::CR2GT || CRBit == PPC::CR3GT || 16600b57cec5SDimitry Andric CRBit == PPC::CR4GT || CRBit == PPC::CR5GT || 16610b57cec5SDimitry Andric CRBit == PPC::CR6GT || CRBit == PPC::CR7GT) 16620b57cec5SDimitry Andric Ret = 2; 16630b57cec5SDimitry Andric if (CRBit == PPC::CR0EQ || CRBit == PPC::CR1EQ || 16640b57cec5SDimitry Andric CRBit == PPC::CR2EQ || CRBit == PPC::CR3EQ || 16650b57cec5SDimitry Andric CRBit == PPC::CR4EQ || CRBit == PPC::CR5EQ || 16660b57cec5SDimitry Andric CRBit == PPC::CR6EQ || CRBit == PPC::CR7EQ) 16670b57cec5SDimitry Andric Ret = 1; 16680b57cec5SDimitry Andric if (CRBit == PPC::CR0UN || CRBit == PPC::CR1UN || 16690b57cec5SDimitry Andric CRBit == PPC::CR2UN || CRBit == PPC::CR3UN || 16700b57cec5SDimitry Andric CRBit == PPC::CR4UN || CRBit == PPC::CR5UN || 16710b57cec5SDimitry Andric CRBit == PPC::CR6UN || CRBit == PPC::CR7UN) 16720b57cec5SDimitry Andric Ret = 0; 16730b57cec5SDimitry Andric 16740b57cec5SDimitry Andric assert(Ret != 4 && "Invalid CR bit register"); 16750b57cec5SDimitry Andric return Ret; 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric 16780b57cec5SDimitry Andric void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 16790b57cec5SDimitry Andric MachineBasicBlock::iterator I, 1680480093f4SDimitry Andric const DebugLoc &DL, MCRegister DestReg, 1681480093f4SDimitry Andric MCRegister SrcReg, bool KillSrc) const { 16820b57cec5SDimitry Andric // We can end up with self copies and similar things as a result of VSX copy 16830b57cec5SDimitry Andric // legalization. Promote them here. 16840b57cec5SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 16850b57cec5SDimitry Andric if (PPC::F8RCRegClass.contains(DestReg) && 16860b57cec5SDimitry Andric PPC::VSRCRegClass.contains(SrcReg)) { 1687480093f4SDimitry Andric MCRegister SuperReg = 16880b57cec5SDimitry Andric TRI->getMatchingSuperReg(DestReg, PPC::sub_64, &PPC::VSRCRegClass); 16890b57cec5SDimitry Andric 16900b57cec5SDimitry Andric if (VSXSelfCopyCrash && SrcReg == SuperReg) 16910b57cec5SDimitry Andric llvm_unreachable("nop VSX copy"); 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric DestReg = SuperReg; 16940b57cec5SDimitry Andric } else if (PPC::F8RCRegClass.contains(SrcReg) && 16950b57cec5SDimitry Andric PPC::VSRCRegClass.contains(DestReg)) { 1696480093f4SDimitry Andric MCRegister SuperReg = 16970b57cec5SDimitry Andric TRI->getMatchingSuperReg(SrcReg, PPC::sub_64, &PPC::VSRCRegClass); 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric if (VSXSelfCopyCrash && DestReg == SuperReg) 17000b57cec5SDimitry Andric llvm_unreachable("nop VSX copy"); 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric SrcReg = SuperReg; 17030b57cec5SDimitry Andric } 17040b57cec5SDimitry Andric 17050b57cec5SDimitry Andric // Different class register copy 17060b57cec5SDimitry Andric if (PPC::CRBITRCRegClass.contains(SrcReg) && 17070b57cec5SDimitry Andric PPC::GPRCRegClass.contains(DestReg)) { 1708480093f4SDimitry Andric MCRegister CRReg = getCRFromCRBit(SrcReg); 17090b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(PPC::MFOCRF), DestReg).addReg(CRReg); 17100b57cec5SDimitry Andric getKillRegState(KillSrc); 17110b57cec5SDimitry Andric // Rotate the CR bit in the CR fields to be the least significant bit and 17120b57cec5SDimitry Andric // then mask with 0x1 (MB = ME = 31). 17130b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(PPC::RLWINM), DestReg) 17140b57cec5SDimitry Andric .addReg(DestReg, RegState::Kill) 17150b57cec5SDimitry Andric .addImm(TRI->getEncodingValue(CRReg) * 4 + (4 - getCRBitValue(SrcReg))) 17160b57cec5SDimitry Andric .addImm(31) 17170b57cec5SDimitry Andric .addImm(31); 17180b57cec5SDimitry Andric return; 17190b57cec5SDimitry Andric } else if (PPC::CRRCRegClass.contains(SrcReg) && 1720e8d8bef9SDimitry Andric (PPC::G8RCRegClass.contains(DestReg) || 1721e8d8bef9SDimitry Andric PPC::GPRCRegClass.contains(DestReg))) { 1722e8d8bef9SDimitry Andric bool Is64Bit = PPC::G8RCRegClass.contains(DestReg); 1723e8d8bef9SDimitry Andric unsigned MvCode = Is64Bit ? PPC::MFOCRF8 : PPC::MFOCRF; 1724e8d8bef9SDimitry Andric unsigned ShCode = Is64Bit ? PPC::RLWINM8 : PPC::RLWINM; 1725e8d8bef9SDimitry Andric unsigned CRNum = TRI->getEncodingValue(SrcReg); 1726e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(MvCode), DestReg).addReg(SrcReg); 17270b57cec5SDimitry Andric getKillRegState(KillSrc); 1728e8d8bef9SDimitry Andric if (CRNum == 7) 17290b57cec5SDimitry Andric return; 1730e8d8bef9SDimitry Andric // Shift the CR bits to make the CR field in the lowest 4 bits of GRC. 1731e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(ShCode), DestReg) 1732e8d8bef9SDimitry Andric .addReg(DestReg, RegState::Kill) 1733e8d8bef9SDimitry Andric .addImm(CRNum * 4 + 4) 1734e8d8bef9SDimitry Andric .addImm(28) 1735e8d8bef9SDimitry Andric .addImm(31); 17360b57cec5SDimitry Andric return; 17370b57cec5SDimitry Andric } else if (PPC::G8RCRegClass.contains(SrcReg) && 17380b57cec5SDimitry Andric PPC::VSFRCRegClass.contains(DestReg)) { 17390b57cec5SDimitry Andric assert(Subtarget.hasDirectMove() && 17400b57cec5SDimitry Andric "Subtarget doesn't support directmove, don't know how to copy."); 17410b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(PPC::MTVSRD), DestReg).addReg(SrcReg); 17420b57cec5SDimitry Andric NumGPRtoVSRSpill++; 17430b57cec5SDimitry Andric getKillRegState(KillSrc); 17440b57cec5SDimitry Andric return; 17450b57cec5SDimitry Andric } else if (PPC::VSFRCRegClass.contains(SrcReg) && 17460b57cec5SDimitry Andric PPC::G8RCRegClass.contains(DestReg)) { 17470b57cec5SDimitry Andric assert(Subtarget.hasDirectMove() && 17480b57cec5SDimitry Andric "Subtarget doesn't support directmove, don't know how to copy."); 17490b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(PPC::MFVSRD), DestReg).addReg(SrcReg); 17500b57cec5SDimitry Andric getKillRegState(KillSrc); 17510b57cec5SDimitry Andric return; 17520b57cec5SDimitry Andric } else if (PPC::SPERCRegClass.contains(SrcReg) && 17538bcb0991SDimitry Andric PPC::GPRCRegClass.contains(DestReg)) { 17540b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(PPC::EFSCFD), DestReg).addReg(SrcReg); 17550b57cec5SDimitry Andric getKillRegState(KillSrc); 17560b57cec5SDimitry Andric return; 17578bcb0991SDimitry Andric } else if (PPC::GPRCRegClass.contains(SrcReg) && 17580b57cec5SDimitry Andric PPC::SPERCRegClass.contains(DestReg)) { 17590b57cec5SDimitry Andric BuildMI(MBB, I, DL, get(PPC::EFDCFS), DestReg).addReg(SrcReg); 17600b57cec5SDimitry Andric getKillRegState(KillSrc); 17610b57cec5SDimitry Andric return; 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric 17640b57cec5SDimitry Andric unsigned Opc; 17650b57cec5SDimitry Andric if (PPC::GPRCRegClass.contains(DestReg, SrcReg)) 17660b57cec5SDimitry Andric Opc = PPC::OR; 17670b57cec5SDimitry Andric else if (PPC::G8RCRegClass.contains(DestReg, SrcReg)) 17680b57cec5SDimitry Andric Opc = PPC::OR8; 17690b57cec5SDimitry Andric else if (PPC::F4RCRegClass.contains(DestReg, SrcReg)) 17700b57cec5SDimitry Andric Opc = PPC::FMR; 17710b57cec5SDimitry Andric else if (PPC::CRRCRegClass.contains(DestReg, SrcReg)) 17720b57cec5SDimitry Andric Opc = PPC::MCRF; 17730b57cec5SDimitry Andric else if (PPC::VRRCRegClass.contains(DestReg, SrcReg)) 17740b57cec5SDimitry Andric Opc = PPC::VOR; 17750b57cec5SDimitry Andric else if (PPC::VSRCRegClass.contains(DestReg, SrcReg)) 17760b57cec5SDimitry Andric // There are two different ways this can be done: 17770b57cec5SDimitry Andric // 1. xxlor : This has lower latency (on the P7), 2 cycles, but can only 17780b57cec5SDimitry Andric // issue in VSU pipeline 0. 17790b57cec5SDimitry Andric // 2. xmovdp/xmovsp: This has higher latency (on the P7), 6 cycles, but 17800b57cec5SDimitry Andric // can go to either pipeline. 17810b57cec5SDimitry Andric // We'll always use xxlor here, because in practically all cases where 17820b57cec5SDimitry Andric // copies are generated, they are close enough to some use that the 17830b57cec5SDimitry Andric // lower-latency form is preferable. 17840b57cec5SDimitry Andric Opc = PPC::XXLOR; 17850b57cec5SDimitry Andric else if (PPC::VSFRCRegClass.contains(DestReg, SrcReg) || 17860b57cec5SDimitry Andric PPC::VSSRCRegClass.contains(DestReg, SrcReg)) 17870b57cec5SDimitry Andric Opc = (Subtarget.hasP9Vector()) ? PPC::XSCPSGNDP : PPC::XXLORf; 1788e8d8bef9SDimitry Andric else if (Subtarget.pairedVectorMemops() && 1789e8d8bef9SDimitry Andric PPC::VSRpRCRegClass.contains(DestReg, SrcReg)) { 1790e8d8bef9SDimitry Andric if (SrcReg > PPC::VSRp15) 1791e8d8bef9SDimitry Andric SrcReg = PPC::V0 + (SrcReg - PPC::VSRp16) * 2; 1792e8d8bef9SDimitry Andric else 1793e8d8bef9SDimitry Andric SrcReg = PPC::VSL0 + (SrcReg - PPC::VSRp0) * 2; 1794e8d8bef9SDimitry Andric if (DestReg > PPC::VSRp15) 1795e8d8bef9SDimitry Andric DestReg = PPC::V0 + (DestReg - PPC::VSRp16) * 2; 1796e8d8bef9SDimitry Andric else 1797e8d8bef9SDimitry Andric DestReg = PPC::VSL0 + (DestReg - PPC::VSRp0) * 2; 1798e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(PPC::XXLOR), DestReg). 1799e8d8bef9SDimitry Andric addReg(SrcReg).addReg(SrcReg, getKillRegState(KillSrc)); 1800e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(PPC::XXLOR), DestReg + 1). 1801e8d8bef9SDimitry Andric addReg(SrcReg + 1).addReg(SrcReg + 1, getKillRegState(KillSrc)); 1802e8d8bef9SDimitry Andric return; 1803e8d8bef9SDimitry Andric } 18040b57cec5SDimitry Andric else if (PPC::CRBITRCRegClass.contains(DestReg, SrcReg)) 18050b57cec5SDimitry Andric Opc = PPC::CROR; 18060b57cec5SDimitry Andric else if (PPC::SPERCRegClass.contains(DestReg, SrcReg)) 18070b57cec5SDimitry Andric Opc = PPC::EVOR; 1808e8d8bef9SDimitry Andric else if ((PPC::ACCRCRegClass.contains(DestReg) || 1809e8d8bef9SDimitry Andric PPC::UACCRCRegClass.contains(DestReg)) && 1810e8d8bef9SDimitry Andric (PPC::ACCRCRegClass.contains(SrcReg) || 1811e8d8bef9SDimitry Andric PPC::UACCRCRegClass.contains(SrcReg))) { 1812e8d8bef9SDimitry Andric // If primed, de-prime the source register, copy the individual registers 1813e8d8bef9SDimitry Andric // and prime the destination if needed. The vector subregisters are 1814e8d8bef9SDimitry Andric // vs[(u)acc * 4] - vs[(u)acc * 4 + 3]. If the copy is not a kill and the 1815e8d8bef9SDimitry Andric // source is primed, we need to re-prime it after the copy as well. 1816e8d8bef9SDimitry Andric PPCRegisterInfo::emitAccCopyInfo(MBB, DestReg, SrcReg); 1817e8d8bef9SDimitry Andric bool DestPrimed = PPC::ACCRCRegClass.contains(DestReg); 1818e8d8bef9SDimitry Andric bool SrcPrimed = PPC::ACCRCRegClass.contains(SrcReg); 1819e8d8bef9SDimitry Andric MCRegister VSLSrcReg = 1820e8d8bef9SDimitry Andric PPC::VSL0 + (SrcReg - (SrcPrimed ? PPC::ACC0 : PPC::UACC0)) * 4; 1821e8d8bef9SDimitry Andric MCRegister VSLDestReg = 1822e8d8bef9SDimitry Andric PPC::VSL0 + (DestReg - (DestPrimed ? PPC::ACC0 : PPC::UACC0)) * 4; 1823e8d8bef9SDimitry Andric if (SrcPrimed) 1824e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(PPC::XXMFACC), SrcReg).addReg(SrcReg); 1825e8d8bef9SDimitry Andric for (unsigned Idx = 0; Idx < 4; Idx++) 1826e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(PPC::XXLOR), VSLDestReg + Idx) 1827e8d8bef9SDimitry Andric .addReg(VSLSrcReg + Idx) 1828e8d8bef9SDimitry Andric .addReg(VSLSrcReg + Idx, getKillRegState(KillSrc)); 1829e8d8bef9SDimitry Andric if (DestPrimed) 1830e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(PPC::XXMTACC), DestReg).addReg(DestReg); 1831e8d8bef9SDimitry Andric if (SrcPrimed && !KillSrc) 1832e8d8bef9SDimitry Andric BuildMI(MBB, I, DL, get(PPC::XXMTACC), SrcReg).addReg(SrcReg); 1833e8d8bef9SDimitry Andric return; 1834fe6060f1SDimitry Andric } else if (PPC::G8pRCRegClass.contains(DestReg) && 1835fe6060f1SDimitry Andric PPC::G8pRCRegClass.contains(SrcReg)) { 1836fe6060f1SDimitry Andric // TODO: Handle G8RC to G8pRC (and vice versa) copy. 1837fe6060f1SDimitry Andric unsigned DestRegIdx = DestReg - PPC::G8p0; 1838fe6060f1SDimitry Andric MCRegister DestRegSub0 = PPC::X0 + 2 * DestRegIdx; 1839fe6060f1SDimitry Andric MCRegister DestRegSub1 = PPC::X0 + 2 * DestRegIdx + 1; 1840fe6060f1SDimitry Andric unsigned SrcRegIdx = SrcReg - PPC::G8p0; 1841fe6060f1SDimitry Andric MCRegister SrcRegSub0 = PPC::X0 + 2 * SrcRegIdx; 1842fe6060f1SDimitry Andric MCRegister SrcRegSub1 = PPC::X0 + 2 * SrcRegIdx + 1; 1843fe6060f1SDimitry Andric BuildMI(MBB, I, DL, get(PPC::OR8), DestRegSub0) 1844fe6060f1SDimitry Andric .addReg(SrcRegSub0) 1845fe6060f1SDimitry Andric .addReg(SrcRegSub0, getKillRegState(KillSrc)); 1846fe6060f1SDimitry Andric BuildMI(MBB, I, DL, get(PPC::OR8), DestRegSub1) 1847fe6060f1SDimitry Andric .addReg(SrcRegSub1) 1848fe6060f1SDimitry Andric .addReg(SrcRegSub1, getKillRegState(KillSrc)); 1849fe6060f1SDimitry Andric return; 1850e8d8bef9SDimitry Andric } else 18510b57cec5SDimitry Andric llvm_unreachable("Impossible reg-to-reg copy"); 18520b57cec5SDimitry Andric 18530b57cec5SDimitry Andric const MCInstrDesc &MCID = get(Opc); 18540b57cec5SDimitry Andric if (MCID.getNumOperands() == 3) 18550b57cec5SDimitry Andric BuildMI(MBB, I, DL, MCID, DestReg) 18560b57cec5SDimitry Andric .addReg(SrcReg).addReg(SrcReg, getKillRegState(KillSrc)); 18570b57cec5SDimitry Andric else 18580b57cec5SDimitry Andric BuildMI(MBB, I, DL, MCID, DestReg).addReg(SrcReg, getKillRegState(KillSrc)); 18590b57cec5SDimitry Andric } 18600b57cec5SDimitry Andric 1861e8d8bef9SDimitry Andric unsigned PPCInstrInfo::getSpillIndex(const TargetRegisterClass *RC) const { 18620b57cec5SDimitry Andric int OpcodeIndex = 0; 18630b57cec5SDimitry Andric 18640b57cec5SDimitry Andric if (PPC::GPRCRegClass.hasSubClassEq(RC) || 18650b57cec5SDimitry Andric PPC::GPRC_NOR0RegClass.hasSubClassEq(RC)) { 18660b57cec5SDimitry Andric OpcodeIndex = SOK_Int4Spill; 18670b57cec5SDimitry Andric } else if (PPC::G8RCRegClass.hasSubClassEq(RC) || 18680b57cec5SDimitry Andric PPC::G8RC_NOX0RegClass.hasSubClassEq(RC)) { 18690b57cec5SDimitry Andric OpcodeIndex = SOK_Int8Spill; 18700b57cec5SDimitry Andric } else if (PPC::F8RCRegClass.hasSubClassEq(RC)) { 18710b57cec5SDimitry Andric OpcodeIndex = SOK_Float8Spill; 18720b57cec5SDimitry Andric } else if (PPC::F4RCRegClass.hasSubClassEq(RC)) { 18730b57cec5SDimitry Andric OpcodeIndex = SOK_Float4Spill; 18740b57cec5SDimitry Andric } else if (PPC::SPERCRegClass.hasSubClassEq(RC)) { 18750b57cec5SDimitry Andric OpcodeIndex = SOK_SPESpill; 18760b57cec5SDimitry Andric } else if (PPC::CRRCRegClass.hasSubClassEq(RC)) { 18770b57cec5SDimitry Andric OpcodeIndex = SOK_CRSpill; 18780b57cec5SDimitry Andric } else if (PPC::CRBITRCRegClass.hasSubClassEq(RC)) { 18790b57cec5SDimitry Andric OpcodeIndex = SOK_CRBitSpill; 18800b57cec5SDimitry Andric } else if (PPC::VRRCRegClass.hasSubClassEq(RC)) { 18810b57cec5SDimitry Andric OpcodeIndex = SOK_VRVectorSpill; 18820b57cec5SDimitry Andric } else if (PPC::VSRCRegClass.hasSubClassEq(RC)) { 18830b57cec5SDimitry Andric OpcodeIndex = SOK_VSXVectorSpill; 18840b57cec5SDimitry Andric } else if (PPC::VSFRCRegClass.hasSubClassEq(RC)) { 18850b57cec5SDimitry Andric OpcodeIndex = SOK_VectorFloat8Spill; 18860b57cec5SDimitry Andric } else if (PPC::VSSRCRegClass.hasSubClassEq(RC)) { 18870b57cec5SDimitry Andric OpcodeIndex = SOK_VectorFloat4Spill; 18880b57cec5SDimitry Andric } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) { 18890b57cec5SDimitry Andric OpcodeIndex = SOK_SpillToVSR; 1890e8d8bef9SDimitry Andric } else if (PPC::ACCRCRegClass.hasSubClassEq(RC)) { 1891e8d8bef9SDimitry Andric assert(Subtarget.pairedVectorMemops() && 1892e8d8bef9SDimitry Andric "Register unexpected when paired memops are disabled."); 1893e8d8bef9SDimitry Andric OpcodeIndex = SOK_AccumulatorSpill; 1894e8d8bef9SDimitry Andric } else if (PPC::UACCRCRegClass.hasSubClassEq(RC)) { 1895e8d8bef9SDimitry Andric assert(Subtarget.pairedVectorMemops() && 1896e8d8bef9SDimitry Andric "Register unexpected when paired memops are disabled."); 1897e8d8bef9SDimitry Andric OpcodeIndex = SOK_UAccumulatorSpill; 1898bdd1243dSDimitry Andric } else if (PPC::WACCRCRegClass.hasSubClassEq(RC)) { 1899bdd1243dSDimitry Andric assert(Subtarget.pairedVectorMemops() && 1900bdd1243dSDimitry Andric "Register unexpected when paired memops are disabled."); 1901bdd1243dSDimitry Andric OpcodeIndex = SOK_WAccumulatorSpill; 1902e8d8bef9SDimitry Andric } else if (PPC::VSRpRCRegClass.hasSubClassEq(RC)) { 1903e8d8bef9SDimitry Andric assert(Subtarget.pairedVectorMemops() && 1904e8d8bef9SDimitry Andric "Register unexpected when paired memops are disabled."); 1905e8d8bef9SDimitry Andric OpcodeIndex = SOK_PairedVecSpill; 1906fe6060f1SDimitry Andric } else if (PPC::G8pRCRegClass.hasSubClassEq(RC)) { 1907fe6060f1SDimitry Andric OpcodeIndex = SOK_PairedG8Spill; 19080b57cec5SDimitry Andric } else { 19090b57cec5SDimitry Andric llvm_unreachable("Unknown regclass!"); 19100b57cec5SDimitry Andric } 19115ffd83dbSDimitry Andric return OpcodeIndex; 19120b57cec5SDimitry Andric } 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric unsigned 19155ffd83dbSDimitry Andric PPCInstrInfo::getStoreOpcodeForSpill(const TargetRegisterClass *RC) const { 1916bdd1243dSDimitry Andric ArrayRef<unsigned> OpcodesForSpill = getStoreOpcodesForSpillArray(); 19175ffd83dbSDimitry Andric return OpcodesForSpill[getSpillIndex(RC)]; 19185ffd83dbSDimitry Andric } 19190b57cec5SDimitry Andric 19205ffd83dbSDimitry Andric unsigned 19215ffd83dbSDimitry Andric PPCInstrInfo::getLoadOpcodeForSpill(const TargetRegisterClass *RC) const { 1922bdd1243dSDimitry Andric ArrayRef<unsigned> OpcodesForSpill = getLoadOpcodesForSpillArray(); 19235ffd83dbSDimitry Andric return OpcodesForSpill[getSpillIndex(RC)]; 19240b57cec5SDimitry Andric } 19250b57cec5SDimitry Andric 19260b57cec5SDimitry Andric void PPCInstrInfo::StoreRegToStackSlot( 19270b57cec5SDimitry Andric MachineFunction &MF, unsigned SrcReg, bool isKill, int FrameIdx, 19280b57cec5SDimitry Andric const TargetRegisterClass *RC, 19290b57cec5SDimitry Andric SmallVectorImpl<MachineInstr *> &NewMIs) const { 19305ffd83dbSDimitry Andric unsigned Opcode = getStoreOpcodeForSpill(RC); 19310b57cec5SDimitry Andric DebugLoc DL; 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); 19340b57cec5SDimitry Andric FuncInfo->setHasSpills(); 19350b57cec5SDimitry Andric 19360b57cec5SDimitry Andric NewMIs.push_back(addFrameReference( 19370b57cec5SDimitry Andric BuildMI(MF, DL, get(Opcode)).addReg(SrcReg, getKillRegState(isKill)), 19380b57cec5SDimitry Andric FrameIdx)); 19390b57cec5SDimitry Andric 19400b57cec5SDimitry Andric if (PPC::CRRCRegClass.hasSubClassEq(RC) || 19410b57cec5SDimitry Andric PPC::CRBITRCRegClass.hasSubClassEq(RC)) 19420b57cec5SDimitry Andric FuncInfo->setSpillsCR(); 19430b57cec5SDimitry Andric 19440b57cec5SDimitry Andric if (isXFormMemOp(Opcode)) 19450b57cec5SDimitry Andric FuncInfo->setHasNonRISpills(); 19460b57cec5SDimitry Andric } 19470b57cec5SDimitry Andric 19485ffd83dbSDimitry Andric void PPCInstrInfo::storeRegToStackSlotNoUpd( 19495ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, 19505ffd83dbSDimitry Andric bool isKill, int FrameIdx, const TargetRegisterClass *RC, 19510b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 19520b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 19530b57cec5SDimitry Andric SmallVector<MachineInstr *, 4> NewMIs; 19540b57cec5SDimitry Andric 19550b57cec5SDimitry Andric StoreRegToStackSlot(MF, SrcReg, isKill, FrameIdx, RC, NewMIs); 19560b57cec5SDimitry Andric 19570fca6ea1SDimitry Andric for (MachineInstr *NewMI : NewMIs) 19580fca6ea1SDimitry Andric MBB.insert(MI, NewMI); 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 19610b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 19620b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FrameIdx), 19630b57cec5SDimitry Andric MachineMemOperand::MOStore, MFI.getObjectSize(FrameIdx), 19645ffd83dbSDimitry Andric MFI.getObjectAlign(FrameIdx)); 19650b57cec5SDimitry Andric NewMIs.back()->addMemOperand(MF, MMO); 19660b57cec5SDimitry Andric } 19670b57cec5SDimitry Andric 1968bdd1243dSDimitry Andric void PPCInstrInfo::storeRegToStackSlot( 1969bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, 1970bdd1243dSDimitry Andric bool isKill, int FrameIdx, const TargetRegisterClass *RC, 1971bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, Register VReg) const { 19725ffd83dbSDimitry Andric // We need to avoid a situation in which the value from a VRRC register is 19735ffd83dbSDimitry Andric // spilled using an Altivec instruction and reloaded into a VSRC register 19745ffd83dbSDimitry Andric // using a VSX instruction. The issue with this is that the VSX 19755ffd83dbSDimitry Andric // load/store instructions swap the doublewords in the vector and the Altivec 19765ffd83dbSDimitry Andric // ones don't. The register classes on the spill/reload may be different if 19775ffd83dbSDimitry Andric // the register is defined using an Altivec instruction and is then used by a 19785ffd83dbSDimitry Andric // VSX instruction. 19795ffd83dbSDimitry Andric RC = updatedRC(RC); 19805ffd83dbSDimitry Andric storeRegToStackSlotNoUpd(MBB, MI, SrcReg, isKill, FrameIdx, RC, TRI); 19815ffd83dbSDimitry Andric } 19825ffd83dbSDimitry Andric 19830b57cec5SDimitry Andric void PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL, 19840b57cec5SDimitry Andric unsigned DestReg, int FrameIdx, 19850b57cec5SDimitry Andric const TargetRegisterClass *RC, 19860b57cec5SDimitry Andric SmallVectorImpl<MachineInstr *> &NewMIs) 19870b57cec5SDimitry Andric const { 19885ffd83dbSDimitry Andric unsigned Opcode = getLoadOpcodeForSpill(RC); 19890b57cec5SDimitry Andric NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Opcode), DestReg), 19900b57cec5SDimitry Andric FrameIdx)); 19910b57cec5SDimitry Andric } 19920b57cec5SDimitry Andric 19935ffd83dbSDimitry Andric void PPCInstrInfo::loadRegFromStackSlotNoUpd( 19945ffd83dbSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, 19955ffd83dbSDimitry Andric int FrameIdx, const TargetRegisterClass *RC, 19960b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const { 19970b57cec5SDimitry Andric MachineFunction &MF = *MBB.getParent(); 19980b57cec5SDimitry Andric SmallVector<MachineInstr*, 4> NewMIs; 19990b57cec5SDimitry Andric DebugLoc DL; 20000b57cec5SDimitry Andric if (MI != MBB.end()) DL = MI->getDebugLoc(); 20010b57cec5SDimitry Andric 20020b57cec5SDimitry Andric LoadRegFromStackSlot(MF, DL, DestReg, FrameIdx, RC, NewMIs); 20030b57cec5SDimitry Andric 20040fca6ea1SDimitry Andric for (MachineInstr *NewMI : NewMIs) 20050fca6ea1SDimitry Andric MBB.insert(MI, NewMI); 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo(); 20080b57cec5SDimitry Andric MachineMemOperand *MMO = MF.getMachineMemOperand( 20090b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FrameIdx), 20100b57cec5SDimitry Andric MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIdx), 20115ffd83dbSDimitry Andric MFI.getObjectAlign(FrameIdx)); 20120b57cec5SDimitry Andric NewMIs.back()->addMemOperand(MF, MMO); 20130b57cec5SDimitry Andric } 20140b57cec5SDimitry Andric 20155ffd83dbSDimitry Andric void PPCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 20165ffd83dbSDimitry Andric MachineBasicBlock::iterator MI, 20175ffd83dbSDimitry Andric Register DestReg, int FrameIdx, 20185ffd83dbSDimitry Andric const TargetRegisterClass *RC, 2019bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 2020bdd1243dSDimitry Andric Register VReg) const { 20215ffd83dbSDimitry Andric // We need to avoid a situation in which the value from a VRRC register is 20225ffd83dbSDimitry Andric // spilled using an Altivec instruction and reloaded into a VSRC register 20235ffd83dbSDimitry Andric // using a VSX instruction. The issue with this is that the VSX 20245ffd83dbSDimitry Andric // load/store instructions swap the doublewords in the vector and the Altivec 20255ffd83dbSDimitry Andric // ones don't. The register classes on the spill/reload may be different if 20265ffd83dbSDimitry Andric // the register is defined using an Altivec instruction and is then used by a 20275ffd83dbSDimitry Andric // VSX instruction. 20285ffd83dbSDimitry Andric RC = updatedRC(RC); 20295ffd83dbSDimitry Andric 20305ffd83dbSDimitry Andric loadRegFromStackSlotNoUpd(MBB, MI, DestReg, FrameIdx, RC, TRI); 20315ffd83dbSDimitry Andric } 20325ffd83dbSDimitry Andric 20330b57cec5SDimitry Andric bool PPCInstrInfo:: 20340b57cec5SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { 20350b57cec5SDimitry Andric assert(Cond.size() == 2 && "Invalid PPC branch opcode!"); 20360b57cec5SDimitry Andric if (Cond[1].getReg() == PPC::CTR8 || Cond[1].getReg() == PPC::CTR) 20370b57cec5SDimitry Andric Cond[0].setImm(Cond[0].getImm() == 0 ? 1 : 0); 20380b57cec5SDimitry Andric else 20390b57cec5SDimitry Andric // Leave the CR# the same, but invert the condition. 20400b57cec5SDimitry Andric Cond[0].setImm(PPC::InvertPredicate((PPC::Predicate)Cond[0].getImm())); 20410b57cec5SDimitry Andric return false; 20420b57cec5SDimitry Andric } 20430b57cec5SDimitry Andric 20440b57cec5SDimitry Andric // For some instructions, it is legal to fold ZERO into the RA register field. 20455ffd83dbSDimitry Andric // This function performs that fold by replacing the operand with PPC::ZERO, 20465ffd83dbSDimitry Andric // it does not consider whether the load immediate zero is no longer in use. 20475ffd83dbSDimitry Andric bool PPCInstrInfo::onlyFoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, 20485ffd83dbSDimitry Andric Register Reg) const { 20490b57cec5SDimitry Andric // A zero immediate should always be loaded with a single li. 20500b57cec5SDimitry Andric unsigned DefOpc = DefMI.getOpcode(); 20510b57cec5SDimitry Andric if (DefOpc != PPC::LI && DefOpc != PPC::LI8) 20520b57cec5SDimitry Andric return false; 20530b57cec5SDimitry Andric if (!DefMI.getOperand(1).isImm()) 20540b57cec5SDimitry Andric return false; 20550b57cec5SDimitry Andric if (DefMI.getOperand(1).getImm() != 0) 20560b57cec5SDimitry Andric return false; 20570b57cec5SDimitry Andric 20580b57cec5SDimitry Andric // Note that we cannot here invert the arguments of an isel in order to fold 20590b57cec5SDimitry Andric // a ZERO into what is presented as the second argument. All we have here 20600b57cec5SDimitry Andric // is the condition bit, and that might come from a CR-logical bit operation. 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric const MCInstrDesc &UseMCID = UseMI.getDesc(); 20630b57cec5SDimitry Andric 20640b57cec5SDimitry Andric // Only fold into real machine instructions. 20650b57cec5SDimitry Andric if (UseMCID.isPseudo()) 20660b57cec5SDimitry Andric return false; 20670b57cec5SDimitry Andric 20685ffd83dbSDimitry Andric // We need to find which of the User's operands is to be folded, that will be 20695ffd83dbSDimitry Andric // the operand that matches the given register ID. 20700b57cec5SDimitry Andric unsigned UseIdx; 20710b57cec5SDimitry Andric for (UseIdx = 0; UseIdx < UseMI.getNumOperands(); ++UseIdx) 20720b57cec5SDimitry Andric if (UseMI.getOperand(UseIdx).isReg() && 20730b57cec5SDimitry Andric UseMI.getOperand(UseIdx).getReg() == Reg) 20740b57cec5SDimitry Andric break; 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric assert(UseIdx < UseMI.getNumOperands() && "Cannot find Reg in UseMI"); 20770b57cec5SDimitry Andric assert(UseIdx < UseMCID.getNumOperands() && "No operand description for Reg"); 20780b57cec5SDimitry Andric 2079bdd1243dSDimitry Andric const MCOperandInfo *UseInfo = &UseMCID.operands()[UseIdx]; 20800b57cec5SDimitry Andric 20810b57cec5SDimitry Andric // We can fold the zero if this register requires a GPRC_NOR0/G8RC_NOX0 20820b57cec5SDimitry Andric // register (which might also be specified as a pointer class kind). 20830b57cec5SDimitry Andric if (UseInfo->isLookupPtrRegClass()) { 20840b57cec5SDimitry Andric if (UseInfo->RegClass /* Kind */ != 1) 20850b57cec5SDimitry Andric return false; 20860b57cec5SDimitry Andric } else { 20870b57cec5SDimitry Andric if (UseInfo->RegClass != PPC::GPRC_NOR0RegClassID && 20880b57cec5SDimitry Andric UseInfo->RegClass != PPC::G8RC_NOX0RegClassID) 20890b57cec5SDimitry Andric return false; 20900b57cec5SDimitry Andric } 20910b57cec5SDimitry Andric 20920b57cec5SDimitry Andric // Make sure this is not tied to an output register (or otherwise 20930b57cec5SDimitry Andric // constrained). This is true for ST?UX registers, for example, which 20940b57cec5SDimitry Andric // are tied to their output registers. 20950b57cec5SDimitry Andric if (UseInfo->Constraints != 0) 20960b57cec5SDimitry Andric return false; 20970b57cec5SDimitry Andric 20985ffd83dbSDimitry Andric MCRegister ZeroReg; 20990b57cec5SDimitry Andric if (UseInfo->isLookupPtrRegClass()) { 21000b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 21010b57cec5SDimitry Andric ZeroReg = isPPC64 ? PPC::ZERO8 : PPC::ZERO; 21020b57cec5SDimitry Andric } else { 21030b57cec5SDimitry Andric ZeroReg = UseInfo->RegClass == PPC::G8RC_NOX0RegClassID ? 21040b57cec5SDimitry Andric PPC::ZERO8 : PPC::ZERO; 21050b57cec5SDimitry Andric } 21060b57cec5SDimitry Andric 2107bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Folded immediate zero for: "); 2108bdd1243dSDimitry Andric LLVM_DEBUG(UseMI.dump()); 21090b57cec5SDimitry Andric UseMI.getOperand(UseIdx).setReg(ZeroReg); 2110bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Into: "); 2111bdd1243dSDimitry Andric LLVM_DEBUG(UseMI.dump()); 21120b57cec5SDimitry Andric return true; 21130b57cec5SDimitry Andric } 21140b57cec5SDimitry Andric 21155ffd83dbSDimitry Andric // Folds zero into instructions which have a load immediate zero as an operand 21165ffd83dbSDimitry Andric // but also recognize zero as immediate zero. If the definition of the load 21175ffd83dbSDimitry Andric // has no more users it is deleted. 21180fca6ea1SDimitry Andric bool PPCInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, 21195ffd83dbSDimitry Andric Register Reg, MachineRegisterInfo *MRI) const { 21205ffd83dbSDimitry Andric bool Changed = onlyFoldImmediate(UseMI, DefMI, Reg); 21215ffd83dbSDimitry Andric if (MRI->use_nodbg_empty(Reg)) 21225ffd83dbSDimitry Andric DefMI.eraseFromParent(); 21235ffd83dbSDimitry Andric return Changed; 21245ffd83dbSDimitry Andric } 21255ffd83dbSDimitry Andric 21260b57cec5SDimitry Andric static bool MBBDefinesCTR(MachineBasicBlock &MBB) { 21274824e7fdSDimitry Andric for (MachineInstr &MI : MBB) 21280fca6ea1SDimitry Andric if (MI.definesRegister(PPC::CTR, /*TRI=*/nullptr) || 21290fca6ea1SDimitry Andric MI.definesRegister(PPC::CTR8, /*TRI=*/nullptr)) 21300b57cec5SDimitry Andric return true; 21310b57cec5SDimitry Andric return false; 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric 21340b57cec5SDimitry Andric // We should make sure that, if we're going to predicate both sides of a 21350b57cec5SDimitry Andric // condition (a diamond), that both sides don't define the counter register. We 21360b57cec5SDimitry Andric // can predicate counter-decrement-based branches, but while that predicates 21370b57cec5SDimitry Andric // the branching, it does not predicate the counter decrement. If we tried to 21380b57cec5SDimitry Andric // merge the triangle into one predicated block, we'd decrement the counter 21390b57cec5SDimitry Andric // twice. 21400b57cec5SDimitry Andric bool PPCInstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB, 21410b57cec5SDimitry Andric unsigned NumT, unsigned ExtraT, 21420b57cec5SDimitry Andric MachineBasicBlock &FMBB, 21430b57cec5SDimitry Andric unsigned NumF, unsigned ExtraF, 21440b57cec5SDimitry Andric BranchProbability Probability) const { 21450b57cec5SDimitry Andric return !(MBBDefinesCTR(TMBB) && MBBDefinesCTR(FMBB)); 21460b57cec5SDimitry Andric } 21470b57cec5SDimitry Andric 21480b57cec5SDimitry Andric 21490b57cec5SDimitry Andric bool PPCInstrInfo::isPredicated(const MachineInstr &MI) const { 21500b57cec5SDimitry Andric // The predicated branches are identified by their type, not really by the 21510b57cec5SDimitry Andric // explicit presence of a predicate. Furthermore, some of them can be 21520b57cec5SDimitry Andric // predicated more than once. Because if conversion won't try to predicate 21530b57cec5SDimitry Andric // any instruction which already claims to be predicated (by returning true 21540b57cec5SDimitry Andric // here), always return false. In doing so, we let isPredicable() be the 21550b57cec5SDimitry Andric // final word on whether not the instruction can be (further) predicated. 21560b57cec5SDimitry Andric 21570b57cec5SDimitry Andric return false; 21580b57cec5SDimitry Andric } 21590b57cec5SDimitry Andric 2160e8d8bef9SDimitry Andric bool PPCInstrInfo::isSchedulingBoundary(const MachineInstr &MI, 2161e8d8bef9SDimitry Andric const MachineBasicBlock *MBB, 2162e8d8bef9SDimitry Andric const MachineFunction &MF) const { 21637a6dacacSDimitry Andric switch (MI.getOpcode()) { 21647a6dacacSDimitry Andric default: 21657a6dacacSDimitry Andric break; 2166e8d8bef9SDimitry Andric // Set MFFS and MTFSF as scheduling boundary to avoid unexpected code motion 2167e8d8bef9SDimitry Andric // across them, since some FP operations may change content of FPSCR. 2168e8d8bef9SDimitry Andric // TODO: Model FPSCR in PPC instruction definitions and remove the workaround 21697a6dacacSDimitry Andric case PPC::MFFS: 21707a6dacacSDimitry Andric case PPC::MTFSF: 21717a6dacacSDimitry Andric case PPC::FENCE: 2172e8d8bef9SDimitry Andric return true; 21737a6dacacSDimitry Andric } 2174e8d8bef9SDimitry Andric return TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF); 2175e8d8bef9SDimitry Andric } 2176e8d8bef9SDimitry Andric 21770b57cec5SDimitry Andric bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI, 21780b57cec5SDimitry Andric ArrayRef<MachineOperand> Pred) const { 21790b57cec5SDimitry Andric unsigned OpC = MI.getOpcode(); 21800b57cec5SDimitry Andric if (OpC == PPC::BLR || OpC == PPC::BLR8) { 21810b57cec5SDimitry Andric if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR) { 21820b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 21830b57cec5SDimitry Andric MI.setDesc(get(Pred[0].getImm() ? (isPPC64 ? PPC::BDNZLR8 : PPC::BDNZLR) 21840b57cec5SDimitry Andric : (isPPC64 ? PPC::BDZLR8 : PPC::BDZLR))); 2185e8d8bef9SDimitry Andric // Need add Def and Use for CTR implicit operand. 2186e8d8bef9SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 2187e8d8bef9SDimitry Andric .addReg(Pred[1].getReg(), RegState::Implicit) 2188e8d8bef9SDimitry Andric .addReg(Pred[1].getReg(), RegState::ImplicitDefine); 21890b57cec5SDimitry Andric } else if (Pred[0].getImm() == PPC::PRED_BIT_SET) { 21900b57cec5SDimitry Andric MI.setDesc(get(PPC::BCLR)); 21910b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]); 21920b57cec5SDimitry Andric } else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) { 21930b57cec5SDimitry Andric MI.setDesc(get(PPC::BCLRn)); 21940b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]); 21950b57cec5SDimitry Andric } else { 21960b57cec5SDimitry Andric MI.setDesc(get(PPC::BCCLR)); 21970b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 21980b57cec5SDimitry Andric .addImm(Pred[0].getImm()) 21990b57cec5SDimitry Andric .add(Pred[1]); 22000b57cec5SDimitry Andric } 22010b57cec5SDimitry Andric 22020b57cec5SDimitry Andric return true; 22030b57cec5SDimitry Andric } else if (OpC == PPC::B) { 22040b57cec5SDimitry Andric if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR) { 22050b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 22060b57cec5SDimitry Andric MI.setDesc(get(Pred[0].getImm() ? (isPPC64 ? PPC::BDNZ8 : PPC::BDNZ) 22070b57cec5SDimitry Andric : (isPPC64 ? PPC::BDZ8 : PPC::BDZ))); 2208e8d8bef9SDimitry Andric // Need add Def and Use for CTR implicit operand. 2209e8d8bef9SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 2210e8d8bef9SDimitry Andric .addReg(Pred[1].getReg(), RegState::Implicit) 2211e8d8bef9SDimitry Andric .addReg(Pred[1].getReg(), RegState::ImplicitDefine); 22120b57cec5SDimitry Andric } else if (Pred[0].getImm() == PPC::PRED_BIT_SET) { 22130b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getOperand(0).getMBB(); 221481ad6265SDimitry Andric MI.removeOperand(0); 22150b57cec5SDimitry Andric 22160b57cec5SDimitry Andric MI.setDesc(get(PPC::BC)); 22170b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 22180b57cec5SDimitry Andric .add(Pred[1]) 22190b57cec5SDimitry Andric .addMBB(MBB); 22200b57cec5SDimitry Andric } else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) { 22210b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getOperand(0).getMBB(); 222281ad6265SDimitry Andric MI.removeOperand(0); 22230b57cec5SDimitry Andric 22240b57cec5SDimitry Andric MI.setDesc(get(PPC::BCn)); 22250b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 22260b57cec5SDimitry Andric .add(Pred[1]) 22270b57cec5SDimitry Andric .addMBB(MBB); 22280b57cec5SDimitry Andric } else { 22290b57cec5SDimitry Andric MachineBasicBlock *MBB = MI.getOperand(0).getMBB(); 223081ad6265SDimitry Andric MI.removeOperand(0); 22310b57cec5SDimitry Andric 22320b57cec5SDimitry Andric MI.setDesc(get(PPC::BCC)); 22330b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 22340b57cec5SDimitry Andric .addImm(Pred[0].getImm()) 22350b57cec5SDimitry Andric .add(Pred[1]) 22360b57cec5SDimitry Andric .addMBB(MBB); 22370b57cec5SDimitry Andric } 22380b57cec5SDimitry Andric 22390b57cec5SDimitry Andric return true; 22400b57cec5SDimitry Andric } else if (OpC == PPC::BCTR || OpC == PPC::BCTR8 || OpC == PPC::BCTRL || 2241349cc55cSDimitry Andric OpC == PPC::BCTRL8 || OpC == PPC::BCTRL_RM || 2242349cc55cSDimitry Andric OpC == PPC::BCTRL8_RM) { 22430b57cec5SDimitry Andric if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR) 22440b57cec5SDimitry Andric llvm_unreachable("Cannot predicate bctr[l] on the ctr register"); 22450b57cec5SDimitry Andric 2246349cc55cSDimitry Andric bool setLR = OpC == PPC::BCTRL || OpC == PPC::BCTRL8 || 2247349cc55cSDimitry Andric OpC == PPC::BCTRL_RM || OpC == PPC::BCTRL8_RM; 22480b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 22490b57cec5SDimitry Andric 22500b57cec5SDimitry Andric if (Pred[0].getImm() == PPC::PRED_BIT_SET) { 22510b57cec5SDimitry Andric MI.setDesc(get(isPPC64 ? (setLR ? PPC::BCCTRL8 : PPC::BCCTR8) 22520b57cec5SDimitry Andric : (setLR ? PPC::BCCTRL : PPC::BCCTR))); 22530b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]); 22540b57cec5SDimitry Andric } else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) { 22550b57cec5SDimitry Andric MI.setDesc(get(isPPC64 ? (setLR ? PPC::BCCTRL8n : PPC::BCCTR8n) 22560b57cec5SDimitry Andric : (setLR ? PPC::BCCTRLn : PPC::BCCTRn))); 22570b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]); 2258e8d8bef9SDimitry Andric } else { 22590b57cec5SDimitry Andric MI.setDesc(get(isPPC64 ? (setLR ? PPC::BCCCTRL8 : PPC::BCCCTR8) 22600b57cec5SDimitry Andric : (setLR ? PPC::BCCCTRL : PPC::BCCCTR))); 22610b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 22620b57cec5SDimitry Andric .addImm(Pred[0].getImm()) 22630b57cec5SDimitry Andric .add(Pred[1]); 2264e8d8bef9SDimitry Andric } 2265e8d8bef9SDimitry Andric 2266e8d8bef9SDimitry Andric // Need add Def and Use for LR implicit operand. 2267e8d8bef9SDimitry Andric if (setLR) 2268e8d8bef9SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 2269e8d8bef9SDimitry Andric .addReg(isPPC64 ? PPC::LR8 : PPC::LR, RegState::Implicit) 2270e8d8bef9SDimitry Andric .addReg(isPPC64 ? PPC::LR8 : PPC::LR, RegState::ImplicitDefine); 2271349cc55cSDimitry Andric if (OpC == PPC::BCTRL_RM || OpC == PPC::BCTRL8_RM) 2272349cc55cSDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 2273349cc55cSDimitry Andric .addReg(PPC::RM, RegState::ImplicitDefine); 2274e8d8bef9SDimitry Andric 22750b57cec5SDimitry Andric return true; 22760b57cec5SDimitry Andric } 22770b57cec5SDimitry Andric 22780b57cec5SDimitry Andric return false; 22790b57cec5SDimitry Andric } 22800b57cec5SDimitry Andric 22810b57cec5SDimitry Andric bool PPCInstrInfo::SubsumesPredicate(ArrayRef<MachineOperand> Pred1, 22820b57cec5SDimitry Andric ArrayRef<MachineOperand> Pred2) const { 22830b57cec5SDimitry Andric assert(Pred1.size() == 2 && "Invalid PPC first predicate"); 22840b57cec5SDimitry Andric assert(Pred2.size() == 2 && "Invalid PPC second predicate"); 22850b57cec5SDimitry Andric 22860b57cec5SDimitry Andric if (Pred1[1].getReg() == PPC::CTR8 || Pred1[1].getReg() == PPC::CTR) 22870b57cec5SDimitry Andric return false; 22880b57cec5SDimitry Andric if (Pred2[1].getReg() == PPC::CTR8 || Pred2[1].getReg() == PPC::CTR) 22890b57cec5SDimitry Andric return false; 22900b57cec5SDimitry Andric 22910b57cec5SDimitry Andric // P1 can only subsume P2 if they test the same condition register. 22920b57cec5SDimitry Andric if (Pred1[1].getReg() != Pred2[1].getReg()) 22930b57cec5SDimitry Andric return false; 22940b57cec5SDimitry Andric 22950b57cec5SDimitry Andric PPC::Predicate P1 = (PPC::Predicate) Pred1[0].getImm(); 22960b57cec5SDimitry Andric PPC::Predicate P2 = (PPC::Predicate) Pred2[0].getImm(); 22970b57cec5SDimitry Andric 22980b57cec5SDimitry Andric if (P1 == P2) 22990b57cec5SDimitry Andric return true; 23000b57cec5SDimitry Andric 23010b57cec5SDimitry Andric // Does P1 subsume P2, e.g. GE subsumes GT. 23020b57cec5SDimitry Andric if (P1 == PPC::PRED_LE && 23030b57cec5SDimitry Andric (P2 == PPC::PRED_LT || P2 == PPC::PRED_EQ)) 23040b57cec5SDimitry Andric return true; 23050b57cec5SDimitry Andric if (P1 == PPC::PRED_GE && 23060b57cec5SDimitry Andric (P2 == PPC::PRED_GT || P2 == PPC::PRED_EQ)) 23070b57cec5SDimitry Andric return true; 23080b57cec5SDimitry Andric 23090b57cec5SDimitry Andric return false; 23100b57cec5SDimitry Andric } 23110b57cec5SDimitry Andric 2312e8d8bef9SDimitry Andric bool PPCInstrInfo::ClobbersPredicate(MachineInstr &MI, 2313e8d8bef9SDimitry Andric std::vector<MachineOperand> &Pred, 2314e8d8bef9SDimitry Andric bool SkipDead) const { 23150b57cec5SDimitry Andric // Note: At the present time, the contents of Pred from this function is 23160b57cec5SDimitry Andric // unused by IfConversion. This implementation follows ARM by pushing the 23170b57cec5SDimitry Andric // CR-defining operand. Because the 'DZ' and 'DNZ' count as types of 23180b57cec5SDimitry Andric // predicate, instructions defining CTR or CTR8 are also included as 23190b57cec5SDimitry Andric // predicate-defining instructions. 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric const TargetRegisterClass *RCs[] = 23220b57cec5SDimitry Andric { &PPC::CRRCRegClass, &PPC::CRBITRCRegClass, 23230b57cec5SDimitry Andric &PPC::CTRRCRegClass, &PPC::CTRRC8RegClass }; 23240b57cec5SDimitry Andric 23250b57cec5SDimitry Andric bool Found = false; 23264824e7fdSDimitry Andric for (const MachineOperand &MO : MI.operands()) { 2327bdd1243dSDimitry Andric for (unsigned c = 0; c < std::size(RCs) && !Found; ++c) { 23280b57cec5SDimitry Andric const TargetRegisterClass *RC = RCs[c]; 23290b57cec5SDimitry Andric if (MO.isReg()) { 23300b57cec5SDimitry Andric if (MO.isDef() && RC->contains(MO.getReg())) { 23310b57cec5SDimitry Andric Pred.push_back(MO); 23320b57cec5SDimitry Andric Found = true; 23330b57cec5SDimitry Andric } 23340b57cec5SDimitry Andric } else if (MO.isRegMask()) { 233504eeddc0SDimitry Andric for (MCPhysReg R : *RC) 233604eeddc0SDimitry Andric if (MO.clobbersPhysReg(R)) { 23370b57cec5SDimitry Andric Pred.push_back(MO); 23380b57cec5SDimitry Andric Found = true; 23390b57cec5SDimitry Andric } 23400b57cec5SDimitry Andric } 23410b57cec5SDimitry Andric } 23420b57cec5SDimitry Andric } 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric return Found; 23450b57cec5SDimitry Andric } 23460b57cec5SDimitry Andric 23475ffd83dbSDimitry Andric bool PPCInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg, 2348349cc55cSDimitry Andric Register &SrcReg2, int64_t &Mask, 2349349cc55cSDimitry Andric int64_t &Value) const { 23500b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 23510b57cec5SDimitry Andric 23520b57cec5SDimitry Andric switch (Opc) { 23530b57cec5SDimitry Andric default: return false; 23540b57cec5SDimitry Andric case PPC::CMPWI: 23550b57cec5SDimitry Andric case PPC::CMPLWI: 23560b57cec5SDimitry Andric case PPC::CMPDI: 23570b57cec5SDimitry Andric case PPC::CMPLDI: 23580b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 23590b57cec5SDimitry Andric SrcReg2 = 0; 23600b57cec5SDimitry Andric Value = MI.getOperand(2).getImm(); 23610b57cec5SDimitry Andric Mask = 0xFFFF; 23620b57cec5SDimitry Andric return true; 23630b57cec5SDimitry Andric case PPC::CMPW: 23640b57cec5SDimitry Andric case PPC::CMPLW: 23650b57cec5SDimitry Andric case PPC::CMPD: 23660b57cec5SDimitry Andric case PPC::CMPLD: 23670b57cec5SDimitry Andric case PPC::FCMPUS: 23680b57cec5SDimitry Andric case PPC::FCMPUD: 23690b57cec5SDimitry Andric SrcReg = MI.getOperand(1).getReg(); 23700b57cec5SDimitry Andric SrcReg2 = MI.getOperand(2).getReg(); 23710b57cec5SDimitry Andric Value = 0; 23720b57cec5SDimitry Andric Mask = 0; 23730b57cec5SDimitry Andric return true; 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric } 23760b57cec5SDimitry Andric 23775ffd83dbSDimitry Andric bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, 2378349cc55cSDimitry Andric Register SrcReg2, int64_t Mask, 2379349cc55cSDimitry Andric int64_t Value, 23800b57cec5SDimitry Andric const MachineRegisterInfo *MRI) const { 23810b57cec5SDimitry Andric if (DisableCmpOpt) 23820b57cec5SDimitry Andric return false; 23830b57cec5SDimitry Andric 23840b57cec5SDimitry Andric int OpC = CmpInstr.getOpcode(); 23858bcb0991SDimitry Andric Register CRReg = CmpInstr.getOperand(0).getReg(); 23860b57cec5SDimitry Andric 23870b57cec5SDimitry Andric // FP record forms set CR1 based on the exception status bits, not a 23880b57cec5SDimitry Andric // comparison with zero. 23890b57cec5SDimitry Andric if (OpC == PPC::FCMPUS || OpC == PPC::FCMPUD) 23900b57cec5SDimitry Andric return false; 23910b57cec5SDimitry Andric 23920b57cec5SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 23930b57cec5SDimitry Andric // The record forms set the condition register based on a signed comparison 23940b57cec5SDimitry Andric // with zero (so says the ISA manual). This is not as straightforward as it 23950b57cec5SDimitry Andric // seems, however, because this is always a 64-bit comparison on PPC64, even 23960b57cec5SDimitry Andric // for instructions that are 32-bit in nature (like slw for example). 23970b57cec5SDimitry Andric // So, on PPC32, for unsigned comparisons, we can use the record forms only 23980b57cec5SDimitry Andric // for equality checks (as those don't depend on the sign). On PPC64, 23990b57cec5SDimitry Andric // we are restricted to equality for unsigned 64-bit comparisons and for 24000b57cec5SDimitry Andric // signed 32-bit comparisons the applicability is more restricted. 24010b57cec5SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 24020b57cec5SDimitry Andric bool is32BitSignedCompare = OpC == PPC::CMPWI || OpC == PPC::CMPW; 24030b57cec5SDimitry Andric bool is32BitUnsignedCompare = OpC == PPC::CMPLWI || OpC == PPC::CMPLW; 24040b57cec5SDimitry Andric bool is64BitUnsignedCompare = OpC == PPC::CMPLDI || OpC == PPC::CMPLD; 24050b57cec5SDimitry Andric 24060b57cec5SDimitry Andric // Look through copies unless that gets us to a physical register. 24075ffd83dbSDimitry Andric Register ActualSrc = TRI->lookThruCopyLike(SrcReg, MRI); 24085ffd83dbSDimitry Andric if (ActualSrc.isVirtual()) 24090b57cec5SDimitry Andric SrcReg = ActualSrc; 24100b57cec5SDimitry Andric 24110b57cec5SDimitry Andric // Get the unique definition of SrcReg. 24120b57cec5SDimitry Andric MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg); 24130b57cec5SDimitry Andric if (!MI) return false; 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric bool equalityOnly = false; 24160b57cec5SDimitry Andric bool noSub = false; 24170b57cec5SDimitry Andric if (isPPC64) { 24180b57cec5SDimitry Andric if (is32BitSignedCompare) { 2419bdd1243dSDimitry Andric // We can perform this optimization only if SrcReg is sign-extending. 2420bdd1243dSDimitry Andric if (isSignExtended(SrcReg, MRI)) 24210b57cec5SDimitry Andric noSub = true; 24220b57cec5SDimitry Andric else 24230b57cec5SDimitry Andric return false; 24240b57cec5SDimitry Andric } else if (is32BitUnsignedCompare) { 2425bdd1243dSDimitry Andric // We can perform this optimization, equality only, if SrcReg is 24260b57cec5SDimitry Andric // zero-extending. 2427bdd1243dSDimitry Andric if (isZeroExtended(SrcReg, MRI)) { 24280b57cec5SDimitry Andric noSub = true; 24290b57cec5SDimitry Andric equalityOnly = true; 24300b57cec5SDimitry Andric } else 24310b57cec5SDimitry Andric return false; 24320b57cec5SDimitry Andric } else 24330b57cec5SDimitry Andric equalityOnly = is64BitUnsignedCompare; 24340b57cec5SDimitry Andric } else 24350b57cec5SDimitry Andric equalityOnly = is32BitUnsignedCompare; 24360b57cec5SDimitry Andric 24370b57cec5SDimitry Andric if (equalityOnly) { 24380b57cec5SDimitry Andric // We need to check the uses of the condition register in order to reject 24390b57cec5SDimitry Andric // non-equality comparisons. 24400b57cec5SDimitry Andric for (MachineRegisterInfo::use_instr_iterator 24410b57cec5SDimitry Andric I = MRI->use_instr_begin(CRReg), IE = MRI->use_instr_end(); 24420b57cec5SDimitry Andric I != IE; ++I) { 24430b57cec5SDimitry Andric MachineInstr *UseMI = &*I; 24440b57cec5SDimitry Andric if (UseMI->getOpcode() == PPC::BCC) { 24450b57cec5SDimitry Andric PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm(); 24460b57cec5SDimitry Andric unsigned PredCond = PPC::getPredicateCondition(Pred); 24470b57cec5SDimitry Andric // We ignore hint bits when checking for non-equality comparisons. 24480b57cec5SDimitry Andric if (PredCond != PPC::PRED_EQ && PredCond != PPC::PRED_NE) 24490b57cec5SDimitry Andric return false; 24500b57cec5SDimitry Andric } else if (UseMI->getOpcode() == PPC::ISEL || 24510b57cec5SDimitry Andric UseMI->getOpcode() == PPC::ISEL8) { 24520b57cec5SDimitry Andric unsigned SubIdx = UseMI->getOperand(3).getSubReg(); 24530b57cec5SDimitry Andric if (SubIdx != PPC::sub_eq) 24540b57cec5SDimitry Andric return false; 24550b57cec5SDimitry Andric } else 24560b57cec5SDimitry Andric return false; 24570b57cec5SDimitry Andric } 24580b57cec5SDimitry Andric } 24590b57cec5SDimitry Andric 24600b57cec5SDimitry Andric MachineBasicBlock::iterator I = CmpInstr; 24610b57cec5SDimitry Andric 24620b57cec5SDimitry Andric // Scan forward to find the first use of the compare. 24630b57cec5SDimitry Andric for (MachineBasicBlock::iterator EL = CmpInstr.getParent()->end(); I != EL; 24640b57cec5SDimitry Andric ++I) { 24650b57cec5SDimitry Andric bool FoundUse = false; 24660b57cec5SDimitry Andric for (MachineRegisterInfo::use_instr_iterator 24670b57cec5SDimitry Andric J = MRI->use_instr_begin(CRReg), JE = MRI->use_instr_end(); 24680b57cec5SDimitry Andric J != JE; ++J) 24690b57cec5SDimitry Andric if (&*J == &*I) { 24700b57cec5SDimitry Andric FoundUse = true; 24710b57cec5SDimitry Andric break; 24720b57cec5SDimitry Andric } 24730b57cec5SDimitry Andric 24740b57cec5SDimitry Andric if (FoundUse) 24750b57cec5SDimitry Andric break; 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric 24780b57cec5SDimitry Andric SmallVector<std::pair<MachineOperand*, PPC::Predicate>, 4> PredsToUpdate; 24790b57cec5SDimitry Andric SmallVector<std::pair<MachineOperand*, unsigned>, 4> SubRegsToUpdate; 24800b57cec5SDimitry Andric 24810b57cec5SDimitry Andric // There are two possible candidates which can be changed to set CR[01]. 24820b57cec5SDimitry Andric // One is MI, the other is a SUB instruction. 24830b57cec5SDimitry Andric // For CMPrr(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1). 24840b57cec5SDimitry Andric MachineInstr *Sub = nullptr; 24850b57cec5SDimitry Andric if (SrcReg2 != 0) 24860b57cec5SDimitry Andric // MI is not a candidate for CMPrr. 24870b57cec5SDimitry Andric MI = nullptr; 24880b57cec5SDimitry Andric // FIXME: Conservatively refuse to convert an instruction which isn't in the 24890b57cec5SDimitry Andric // same BB as the comparison. This is to allow the check below to avoid calls 24900b57cec5SDimitry Andric // (and other explicit clobbers); instead we should really check for these 24910b57cec5SDimitry Andric // more explicitly (in at least a few predecessors). 24920b57cec5SDimitry Andric else if (MI->getParent() != CmpInstr.getParent()) 24930b57cec5SDimitry Andric return false; 24940b57cec5SDimitry Andric else if (Value != 0) { 24950b57cec5SDimitry Andric // The record-form instructions set CR bit based on signed comparison 24960b57cec5SDimitry Andric // against 0. We try to convert a compare against 1 or -1 into a compare 24970b57cec5SDimitry Andric // against 0 to exploit record-form instructions. For example, we change 24980b57cec5SDimitry Andric // the condition "greater than -1" into "greater than or equal to 0" 24990b57cec5SDimitry Andric // and "less than 1" into "less than or equal to 0". 25000b57cec5SDimitry Andric 25010b57cec5SDimitry Andric // Since we optimize comparison based on a specific branch condition, 25020b57cec5SDimitry Andric // we don't optimize if condition code is used by more than once. 25030b57cec5SDimitry Andric if (equalityOnly || !MRI->hasOneUse(CRReg)) 25040b57cec5SDimitry Andric return false; 25050b57cec5SDimitry Andric 25060b57cec5SDimitry Andric MachineInstr *UseMI = &*MRI->use_instr_begin(CRReg); 25070b57cec5SDimitry Andric if (UseMI->getOpcode() != PPC::BCC) 25080b57cec5SDimitry Andric return false; 25090b57cec5SDimitry Andric 25100b57cec5SDimitry Andric PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm(); 25110b57cec5SDimitry Andric unsigned PredCond = PPC::getPredicateCondition(Pred); 25120b57cec5SDimitry Andric unsigned PredHint = PPC::getPredicateHint(Pred); 25130b57cec5SDimitry Andric int16_t Immed = (int16_t)Value; 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric // When modifying the condition in the predicate, we propagate hint bits 25160b57cec5SDimitry Andric // from the original predicate to the new one. 25170b57cec5SDimitry Andric if (Immed == -1 && PredCond == PPC::PRED_GT) 25180b57cec5SDimitry Andric // We convert "greater than -1" into "greater than or equal to 0", 25190b57cec5SDimitry Andric // since we are assuming signed comparison by !equalityOnly 25200b57cec5SDimitry Andric Pred = PPC::getPredicate(PPC::PRED_GE, PredHint); 25210b57cec5SDimitry Andric else if (Immed == -1 && PredCond == PPC::PRED_LE) 25220b57cec5SDimitry Andric // We convert "less than or equal to -1" into "less than 0". 25230b57cec5SDimitry Andric Pred = PPC::getPredicate(PPC::PRED_LT, PredHint); 25240b57cec5SDimitry Andric else if (Immed == 1 && PredCond == PPC::PRED_LT) 25250b57cec5SDimitry Andric // We convert "less than 1" into "less than or equal to 0". 25260b57cec5SDimitry Andric Pred = PPC::getPredicate(PPC::PRED_LE, PredHint); 25270b57cec5SDimitry Andric else if (Immed == 1 && PredCond == PPC::PRED_GE) 25280b57cec5SDimitry Andric // We convert "greater than or equal to 1" into "greater than 0". 25290b57cec5SDimitry Andric Pred = PPC::getPredicate(PPC::PRED_GT, PredHint); 25300b57cec5SDimitry Andric else 25310b57cec5SDimitry Andric return false; 25320b57cec5SDimitry Andric 2533bdd1243dSDimitry Andric // Convert the comparison and its user to a compare against zero with the 2534bdd1243dSDimitry Andric // appropriate predicate on the branch. Zero comparison might provide 2535bdd1243dSDimitry Andric // optimization opportunities post-RA (see optimization in 2536bdd1243dSDimitry Andric // PPCPreEmitPeephole.cpp). 2537bdd1243dSDimitry Andric UseMI->getOperand(0).setImm(Pred); 2538bdd1243dSDimitry Andric CmpInstr.getOperand(2).setImm(0); 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric 25410b57cec5SDimitry Andric // Search for Sub. 25420b57cec5SDimitry Andric --I; 25430b57cec5SDimitry Andric 25440b57cec5SDimitry Andric // Get ready to iterate backward from CmpInstr. 25450b57cec5SDimitry Andric MachineBasicBlock::iterator E = MI, B = CmpInstr.getParent()->begin(); 25460b57cec5SDimitry Andric 25470b57cec5SDimitry Andric for (; I != E && !noSub; --I) { 25480b57cec5SDimitry Andric const MachineInstr &Instr = *I; 25490b57cec5SDimitry Andric unsigned IOpC = Instr.getOpcode(); 25500b57cec5SDimitry Andric 25510b57cec5SDimitry Andric if (&*I != &CmpInstr && (Instr.modifiesRegister(PPC::CR0, TRI) || 25520b57cec5SDimitry Andric Instr.readsRegister(PPC::CR0, TRI))) 25530b57cec5SDimitry Andric // This instruction modifies or uses the record condition register after 25540b57cec5SDimitry Andric // the one we want to change. While we could do this transformation, it 25550b57cec5SDimitry Andric // would likely not be profitable. This transformation removes one 25560b57cec5SDimitry Andric // instruction, and so even forcing RA to generate one move probably 25570b57cec5SDimitry Andric // makes it unprofitable. 25580b57cec5SDimitry Andric return false; 25590b57cec5SDimitry Andric 25600b57cec5SDimitry Andric // Check whether CmpInstr can be made redundant by the current instruction. 25610b57cec5SDimitry Andric if ((OpC == PPC::CMPW || OpC == PPC::CMPLW || 25620b57cec5SDimitry Andric OpC == PPC::CMPD || OpC == PPC::CMPLD) && 25630b57cec5SDimitry Andric (IOpC == PPC::SUBF || IOpC == PPC::SUBF8) && 25640b57cec5SDimitry Andric ((Instr.getOperand(1).getReg() == SrcReg && 25650b57cec5SDimitry Andric Instr.getOperand(2).getReg() == SrcReg2) || 25660b57cec5SDimitry Andric (Instr.getOperand(1).getReg() == SrcReg2 && 25670b57cec5SDimitry Andric Instr.getOperand(2).getReg() == SrcReg))) { 25680b57cec5SDimitry Andric Sub = &*I; 25690b57cec5SDimitry Andric break; 25700b57cec5SDimitry Andric } 25710b57cec5SDimitry Andric 25720b57cec5SDimitry Andric if (I == B) 25730b57cec5SDimitry Andric // The 'and' is below the comparison instruction. 25740b57cec5SDimitry Andric return false; 25750b57cec5SDimitry Andric } 25760b57cec5SDimitry Andric 25770b57cec5SDimitry Andric // Return false if no candidates exist. 25780b57cec5SDimitry Andric if (!MI && !Sub) 25790b57cec5SDimitry Andric return false; 25800b57cec5SDimitry Andric 25810b57cec5SDimitry Andric // The single candidate is called MI. 25820b57cec5SDimitry Andric if (!MI) MI = Sub; 25830b57cec5SDimitry Andric 25840b57cec5SDimitry Andric int NewOpC = -1; 25850b57cec5SDimitry Andric int MIOpC = MI->getOpcode(); 2586480093f4SDimitry Andric if (MIOpC == PPC::ANDI_rec || MIOpC == PPC::ANDI8_rec || 2587480093f4SDimitry Andric MIOpC == PPC::ANDIS_rec || MIOpC == PPC::ANDIS8_rec) 25880b57cec5SDimitry Andric NewOpC = MIOpC; 25890b57cec5SDimitry Andric else { 25900b57cec5SDimitry Andric NewOpC = PPC::getRecordFormOpcode(MIOpC); 25910b57cec5SDimitry Andric if (NewOpC == -1 && PPC::getNonRecordFormOpcode(MIOpC) != -1) 25920b57cec5SDimitry Andric NewOpC = MIOpC; 25930b57cec5SDimitry Andric } 25940b57cec5SDimitry Andric 25950b57cec5SDimitry Andric // FIXME: On the non-embedded POWER architectures, only some of the record 25960b57cec5SDimitry Andric // forms are fast, and we should use only the fast ones. 25970b57cec5SDimitry Andric 25980b57cec5SDimitry Andric // The defining instruction has a record form (or is already a record 25990b57cec5SDimitry Andric // form). It is possible, however, that we'll need to reverse the condition 26000b57cec5SDimitry Andric // code of the users. 26010b57cec5SDimitry Andric if (NewOpC == -1) 26020b57cec5SDimitry Andric return false; 26030b57cec5SDimitry Andric 2604e8d8bef9SDimitry Andric // This transformation should not be performed if `nsw` is missing and is not 2605e8d8bef9SDimitry Andric // `equalityOnly` comparison. Since if there is overflow, sub_lt, sub_gt in 2606e8d8bef9SDimitry Andric // CRReg do not reflect correct order. If `equalityOnly` is true, sub_eq in 2607e8d8bef9SDimitry Andric // CRReg can reflect if compared values are equal, this optz is still valid. 2608e8d8bef9SDimitry Andric if (!equalityOnly && (NewOpC == PPC::SUBF_rec || NewOpC == PPC::SUBF8_rec) && 2609e8d8bef9SDimitry Andric Sub && !Sub->getFlag(MachineInstr::NoSWrap)) 2610e8d8bef9SDimitry Andric return false; 2611e8d8bef9SDimitry Andric 26120b57cec5SDimitry Andric // If we have SUB(r1, r2) and CMP(r2, r1), the condition code based on CMP 26130b57cec5SDimitry Andric // needs to be updated to be based on SUB. Push the condition code 26140b57cec5SDimitry Andric // operands to OperandsToUpdate. If it is safe to remove CmpInstr, the 26150b57cec5SDimitry Andric // condition code of these operands will be modified. 26160b57cec5SDimitry Andric // Here, Value == 0 means we haven't converted comparison against 1 or -1 to 26170b57cec5SDimitry Andric // comparison against 0, which may modify predicate. 26180b57cec5SDimitry Andric bool ShouldSwap = false; 26190b57cec5SDimitry Andric if (Sub && Value == 0) { 26200b57cec5SDimitry Andric ShouldSwap = SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 && 26210b57cec5SDimitry Andric Sub->getOperand(2).getReg() == SrcReg; 26220b57cec5SDimitry Andric 26230b57cec5SDimitry Andric // The operands to subf are the opposite of sub, so only in the fixed-point 26240b57cec5SDimitry Andric // case, invert the order. 26250b57cec5SDimitry Andric ShouldSwap = !ShouldSwap; 26260b57cec5SDimitry Andric } 26270b57cec5SDimitry Andric 26280b57cec5SDimitry Andric if (ShouldSwap) 26290b57cec5SDimitry Andric for (MachineRegisterInfo::use_instr_iterator 26300b57cec5SDimitry Andric I = MRI->use_instr_begin(CRReg), IE = MRI->use_instr_end(); 26310b57cec5SDimitry Andric I != IE; ++I) { 26320b57cec5SDimitry Andric MachineInstr *UseMI = &*I; 26330b57cec5SDimitry Andric if (UseMI->getOpcode() == PPC::BCC) { 26340b57cec5SDimitry Andric PPC::Predicate Pred = (PPC::Predicate) UseMI->getOperand(0).getImm(); 26350b57cec5SDimitry Andric unsigned PredCond = PPC::getPredicateCondition(Pred); 26360b57cec5SDimitry Andric assert((!equalityOnly || 26370b57cec5SDimitry Andric PredCond == PPC::PRED_EQ || PredCond == PPC::PRED_NE) && 26380b57cec5SDimitry Andric "Invalid predicate for equality-only optimization"); 26390b57cec5SDimitry Andric (void)PredCond; // To suppress warning in release build. 26400b57cec5SDimitry Andric PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)), 26410b57cec5SDimitry Andric PPC::getSwappedPredicate(Pred))); 26420b57cec5SDimitry Andric } else if (UseMI->getOpcode() == PPC::ISEL || 26430b57cec5SDimitry Andric UseMI->getOpcode() == PPC::ISEL8) { 26440b57cec5SDimitry Andric unsigned NewSubReg = UseMI->getOperand(3).getSubReg(); 26450b57cec5SDimitry Andric assert((!equalityOnly || NewSubReg == PPC::sub_eq) && 26460b57cec5SDimitry Andric "Invalid CR bit for equality-only optimization"); 26470b57cec5SDimitry Andric 26480b57cec5SDimitry Andric if (NewSubReg == PPC::sub_lt) 26490b57cec5SDimitry Andric NewSubReg = PPC::sub_gt; 26500b57cec5SDimitry Andric else if (NewSubReg == PPC::sub_gt) 26510b57cec5SDimitry Andric NewSubReg = PPC::sub_lt; 26520b57cec5SDimitry Andric 26530b57cec5SDimitry Andric SubRegsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(3)), 26540b57cec5SDimitry Andric NewSubReg)); 26550b57cec5SDimitry Andric } else // We need to abort on a user we don't understand. 26560b57cec5SDimitry Andric return false; 26570b57cec5SDimitry Andric } 26580b57cec5SDimitry Andric assert(!(Value != 0 && ShouldSwap) && 26590b57cec5SDimitry Andric "Non-zero immediate support and ShouldSwap" 26600b57cec5SDimitry Andric "may conflict in updating predicate"); 26610b57cec5SDimitry Andric 26620b57cec5SDimitry Andric // Create a new virtual register to hold the value of the CR set by the 26630b57cec5SDimitry Andric // record-form instruction. If the instruction was not previously in 26640b57cec5SDimitry Andric // record form, then set the kill flag on the CR. 26650b57cec5SDimitry Andric CmpInstr.eraseFromParent(); 26660b57cec5SDimitry Andric 26670b57cec5SDimitry Andric MachineBasicBlock::iterator MII = MI; 26680b57cec5SDimitry Andric BuildMI(*MI->getParent(), std::next(MII), MI->getDebugLoc(), 26690b57cec5SDimitry Andric get(TargetOpcode::COPY), CRReg) 26700b57cec5SDimitry Andric .addReg(PPC::CR0, MIOpC != NewOpC ? RegState::Kill : 0); 26710b57cec5SDimitry Andric 26720b57cec5SDimitry Andric // Even if CR0 register were dead before, it is alive now since the 26730b57cec5SDimitry Andric // instruction we just built uses it. 26740b57cec5SDimitry Andric MI->clearRegisterDeads(PPC::CR0); 26750b57cec5SDimitry Andric 26760b57cec5SDimitry Andric if (MIOpC != NewOpC) { 26770b57cec5SDimitry Andric // We need to be careful here: we're replacing one instruction with 26780b57cec5SDimitry Andric // another, and we need to make sure that we get all of the right 26790b57cec5SDimitry Andric // implicit uses and defs. On the other hand, the caller may be holding 26800b57cec5SDimitry Andric // an iterator to this instruction, and so we can't delete it (this is 26810b57cec5SDimitry Andric // specifically the case if this is the instruction directly after the 26820b57cec5SDimitry Andric // compare). 26830b57cec5SDimitry Andric 26840b57cec5SDimitry Andric // Rotates are expensive instructions. If we're emitting a record-form 26850b57cec5SDimitry Andric // rotate that can just be an andi/andis, we should just emit that. 26860b57cec5SDimitry Andric if (MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINM8) { 26878bcb0991SDimitry Andric Register GPRRes = MI->getOperand(0).getReg(); 26880b57cec5SDimitry Andric int64_t SH = MI->getOperand(2).getImm(); 26890b57cec5SDimitry Andric int64_t MB = MI->getOperand(3).getImm(); 26900b57cec5SDimitry Andric int64_t ME = MI->getOperand(4).getImm(); 26910b57cec5SDimitry Andric // We can only do this if both the start and end of the mask are in the 26920b57cec5SDimitry Andric // same halfword. 26930b57cec5SDimitry Andric bool MBInLoHWord = MB >= 16; 26940b57cec5SDimitry Andric bool MEInLoHWord = ME >= 16; 26950b57cec5SDimitry Andric uint64_t Mask = ~0LLU; 26960b57cec5SDimitry Andric 26970b57cec5SDimitry Andric if (MB <= ME && MBInLoHWord == MEInLoHWord && SH == 0) { 26980b57cec5SDimitry Andric Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); 26990b57cec5SDimitry Andric // The mask value needs to shift right 16 if we're emitting andis. 27000b57cec5SDimitry Andric Mask >>= MBInLoHWord ? 0 : 16; 2701480093f4SDimitry Andric NewOpC = MIOpC == PPC::RLWINM 2702480093f4SDimitry Andric ? (MBInLoHWord ? PPC::ANDI_rec : PPC::ANDIS_rec) 2703480093f4SDimitry Andric : (MBInLoHWord ? PPC::ANDI8_rec : PPC::ANDIS8_rec); 27040b57cec5SDimitry Andric } else if (MRI->use_empty(GPRRes) && (ME == 31) && 27050b57cec5SDimitry Andric (ME - MB + 1 == SH) && (MB >= 16)) { 27060b57cec5SDimitry Andric // If we are rotating by the exact number of bits as are in the mask 27070b57cec5SDimitry Andric // and the mask is in the least significant bits of the register, 27080b57cec5SDimitry Andric // that's just an andis. (as long as the GPR result has no uses). 27090b57cec5SDimitry Andric Mask = ((1LLU << 32) - 1) & ~((1LLU << (32 - SH)) - 1); 27100b57cec5SDimitry Andric Mask >>= 16; 2711480093f4SDimitry Andric NewOpC = MIOpC == PPC::RLWINM ? PPC::ANDIS_rec : PPC::ANDIS8_rec; 27120b57cec5SDimitry Andric } 27130b57cec5SDimitry Andric // If we've set the mask, we can transform. 27140b57cec5SDimitry Andric if (Mask != ~0LLU) { 271581ad6265SDimitry Andric MI->removeOperand(4); 271681ad6265SDimitry Andric MI->removeOperand(3); 27170b57cec5SDimitry Andric MI->getOperand(2).setImm(Mask); 27180b57cec5SDimitry Andric NumRcRotatesConvertedToRcAnd++; 27190b57cec5SDimitry Andric } 27200b57cec5SDimitry Andric } else if (MIOpC == PPC::RLDICL && MI->getOperand(2).getImm() == 0) { 27210b57cec5SDimitry Andric int64_t MB = MI->getOperand(3).getImm(); 27220b57cec5SDimitry Andric if (MB >= 48) { 27230b57cec5SDimitry Andric uint64_t Mask = (1LLU << (63 - MB + 1)) - 1; 2724480093f4SDimitry Andric NewOpC = PPC::ANDI8_rec; 272581ad6265SDimitry Andric MI->removeOperand(3); 27260b57cec5SDimitry Andric MI->getOperand(2).setImm(Mask); 27270b57cec5SDimitry Andric NumRcRotatesConvertedToRcAnd++; 27280b57cec5SDimitry Andric } 27290b57cec5SDimitry Andric } 27300b57cec5SDimitry Andric 27310b57cec5SDimitry Andric const MCInstrDesc &NewDesc = get(NewOpC); 27320b57cec5SDimitry Andric MI->setDesc(NewDesc); 27330b57cec5SDimitry Andric 2734bdd1243dSDimitry Andric for (MCPhysReg ImpDef : NewDesc.implicit_defs()) { 27350fca6ea1SDimitry Andric if (!MI->definesRegister(ImpDef, /*TRI=*/nullptr)) { 27360b57cec5SDimitry Andric MI->addOperand(*MI->getParent()->getParent(), 2737bdd1243dSDimitry Andric MachineOperand::CreateReg(ImpDef, true, true)); 2738bdd1243dSDimitry Andric } 2739bdd1243dSDimitry Andric } 2740bdd1243dSDimitry Andric for (MCPhysReg ImpUse : NewDesc.implicit_uses()) { 27410fca6ea1SDimitry Andric if (!MI->readsRegister(ImpUse, /*TRI=*/nullptr)) { 27420b57cec5SDimitry Andric MI->addOperand(*MI->getParent()->getParent(), 2743bdd1243dSDimitry Andric MachineOperand::CreateReg(ImpUse, false, true)); 2744bdd1243dSDimitry Andric } 2745bdd1243dSDimitry Andric } 27460b57cec5SDimitry Andric } 27470fca6ea1SDimitry Andric assert(MI->definesRegister(PPC::CR0, /*TRI=*/nullptr) && 27480b57cec5SDimitry Andric "Record-form instruction does not define cr0?"); 27490b57cec5SDimitry Andric 27500b57cec5SDimitry Andric // Modify the condition code of operands in OperandsToUpdate. 27510b57cec5SDimitry Andric // Since we have SUB(r1, r2) and CMP(r2, r1), the condition code needs to 27520b57cec5SDimitry Andric // be changed from r2 > r1 to r1 < r2, from r2 < r1 to r1 > r2, etc. 27530b57cec5SDimitry Andric for (unsigned i = 0, e = PredsToUpdate.size(); i < e; i++) 27540b57cec5SDimitry Andric PredsToUpdate[i].first->setImm(PredsToUpdate[i].second); 27550b57cec5SDimitry Andric 27560b57cec5SDimitry Andric for (unsigned i = 0, e = SubRegsToUpdate.size(); i < e; i++) 27570b57cec5SDimitry Andric SubRegsToUpdate[i].first->setSubReg(SubRegsToUpdate[i].second); 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric return true; 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric 2762bdd1243dSDimitry Andric bool PPCInstrInfo::optimizeCmpPostRA(MachineInstr &CmpMI) const { 2763bdd1243dSDimitry Andric MachineRegisterInfo *MRI = &CmpMI.getParent()->getParent()->getRegInfo(); 2764bdd1243dSDimitry Andric if (MRI->isSSA()) 2765bdd1243dSDimitry Andric return false; 2766bdd1243dSDimitry Andric 2767bdd1243dSDimitry Andric Register SrcReg, SrcReg2; 2768bdd1243dSDimitry Andric int64_t CmpMask, CmpValue; 2769bdd1243dSDimitry Andric if (!analyzeCompare(CmpMI, SrcReg, SrcReg2, CmpMask, CmpValue)) 2770bdd1243dSDimitry Andric return false; 2771bdd1243dSDimitry Andric 2772bdd1243dSDimitry Andric // Try to optimize the comparison against 0. 2773bdd1243dSDimitry Andric if (CmpValue || !CmpMask || SrcReg2) 2774bdd1243dSDimitry Andric return false; 2775bdd1243dSDimitry Andric 2776bdd1243dSDimitry Andric // The record forms set the condition register based on a signed comparison 2777bdd1243dSDimitry Andric // with zero (see comments in optimizeCompareInstr). Since we can't do the 2778bdd1243dSDimitry Andric // equality checks in post-RA, we are more restricted on a unsigned 2779bdd1243dSDimitry Andric // comparison. 2780bdd1243dSDimitry Andric unsigned Opc = CmpMI.getOpcode(); 2781bdd1243dSDimitry Andric if (Opc == PPC::CMPLWI || Opc == PPC::CMPLDI) 2782bdd1243dSDimitry Andric return false; 2783bdd1243dSDimitry Andric 2784bdd1243dSDimitry Andric // The record forms are always based on a 64-bit comparison on PPC64 2785bdd1243dSDimitry Andric // (similary, a 32-bit comparison on PPC32), while the CMPWI is a 32-bit 2786bdd1243dSDimitry Andric // comparison. Since we can't do the equality checks in post-RA, we bail out 2787bdd1243dSDimitry Andric // the case. 2788bdd1243dSDimitry Andric if (Subtarget.isPPC64() && Opc == PPC::CMPWI) 2789bdd1243dSDimitry Andric return false; 2790bdd1243dSDimitry Andric 2791bdd1243dSDimitry Andric // CmpMI can't be deleted if it has implicit def. 2792bdd1243dSDimitry Andric if (CmpMI.hasImplicitDef()) 2793bdd1243dSDimitry Andric return false; 2794bdd1243dSDimitry Andric 2795bdd1243dSDimitry Andric bool SrcRegHasOtherUse = false; 2796bdd1243dSDimitry Andric MachineInstr *SrcMI = getDefMIPostRA(SrcReg, CmpMI, SrcRegHasOtherUse); 27970fca6ea1SDimitry Andric if (!SrcMI || !SrcMI->definesRegister(SrcReg, /*TRI=*/nullptr)) 2798bdd1243dSDimitry Andric return false; 2799bdd1243dSDimitry Andric 2800bdd1243dSDimitry Andric MachineOperand RegMO = CmpMI.getOperand(0); 2801bdd1243dSDimitry Andric Register CRReg = RegMO.getReg(); 2802bdd1243dSDimitry Andric if (CRReg != PPC::CR0) 2803bdd1243dSDimitry Andric return false; 2804bdd1243dSDimitry Andric 2805bdd1243dSDimitry Andric // Make sure there is no def/use of CRReg between SrcMI and CmpMI. 2806bdd1243dSDimitry Andric bool SeenUseOfCRReg = false; 2807bdd1243dSDimitry Andric bool IsCRRegKilled = false; 2808bdd1243dSDimitry Andric if (!isRegElgibleForForwarding(RegMO, *SrcMI, CmpMI, false, IsCRRegKilled, 2809bdd1243dSDimitry Andric SeenUseOfCRReg) || 28100fca6ea1SDimitry Andric SrcMI->definesRegister(CRReg, /*TRI=*/nullptr) || SeenUseOfCRReg) 2811bdd1243dSDimitry Andric return false; 2812bdd1243dSDimitry Andric 2813bdd1243dSDimitry Andric int SrcMIOpc = SrcMI->getOpcode(); 2814bdd1243dSDimitry Andric int NewOpC = PPC::getRecordFormOpcode(SrcMIOpc); 2815bdd1243dSDimitry Andric if (NewOpC == -1) 2816bdd1243dSDimitry Andric return false; 2817bdd1243dSDimitry Andric 2818bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Replace Instr: "); 2819bdd1243dSDimitry Andric LLVM_DEBUG(SrcMI->dump()); 2820bdd1243dSDimitry Andric 2821bdd1243dSDimitry Andric const MCInstrDesc &NewDesc = get(NewOpC); 2822bdd1243dSDimitry Andric SrcMI->setDesc(NewDesc); 2823bdd1243dSDimitry Andric MachineInstrBuilder(*SrcMI->getParent()->getParent(), SrcMI) 2824bdd1243dSDimitry Andric .addReg(CRReg, RegState::ImplicitDefine); 2825bdd1243dSDimitry Andric SrcMI->clearRegisterDeads(CRReg); 2826bdd1243dSDimitry Andric 28270fca6ea1SDimitry Andric assert(SrcMI->definesRegister(PPC::CR0, /*TRI=*/nullptr) && 2828bdd1243dSDimitry Andric "Record-form instruction does not define cr0?"); 2829bdd1243dSDimitry Andric 2830bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "with: "); 2831bdd1243dSDimitry Andric LLVM_DEBUG(SrcMI->dump()); 2832bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Delete dead instruction: "); 2833bdd1243dSDimitry Andric LLVM_DEBUG(CmpMI.dump()); 2834bdd1243dSDimitry Andric return true; 2835bdd1243dSDimitry Andric } 2836bdd1243dSDimitry Andric 2837e8d8bef9SDimitry Andric bool PPCInstrInfo::getMemOperandsWithOffsetWidth( 2838e8d8bef9SDimitry Andric const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps, 28390fca6ea1SDimitry Andric int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, 2840e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI) const { 2841e8d8bef9SDimitry Andric const MachineOperand *BaseOp; 2842e8d8bef9SDimitry Andric OffsetIsScalable = false; 2843e8d8bef9SDimitry Andric if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, Width, TRI)) 2844e8d8bef9SDimitry Andric return false; 2845e8d8bef9SDimitry Andric BaseOps.push_back(BaseOp); 2846e8d8bef9SDimitry Andric return true; 2847e8d8bef9SDimitry Andric } 2848e8d8bef9SDimitry Andric 2849e8d8bef9SDimitry Andric static bool isLdStSafeToCluster(const MachineInstr &LdSt, 2850e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI) { 2851e8d8bef9SDimitry Andric // If this is a volatile load/store, don't mess with it. 2852e8d8bef9SDimitry Andric if (LdSt.hasOrderedMemoryRef() || LdSt.getNumExplicitOperands() != 3) 2853e8d8bef9SDimitry Andric return false; 2854e8d8bef9SDimitry Andric 2855e8d8bef9SDimitry Andric if (LdSt.getOperand(2).isFI()) 2856e8d8bef9SDimitry Andric return true; 2857e8d8bef9SDimitry Andric 2858e8d8bef9SDimitry Andric assert(LdSt.getOperand(2).isReg() && "Expected a reg operand."); 2859e8d8bef9SDimitry Andric // Can't cluster if the instruction modifies the base register 2860e8d8bef9SDimitry Andric // or it is update form. e.g. ld r2,3(r2) 2861e8d8bef9SDimitry Andric if (LdSt.modifiesRegister(LdSt.getOperand(2).getReg(), TRI)) 2862e8d8bef9SDimitry Andric return false; 2863e8d8bef9SDimitry Andric 2864e8d8bef9SDimitry Andric return true; 2865e8d8bef9SDimitry Andric } 2866e8d8bef9SDimitry Andric 2867e8d8bef9SDimitry Andric // Only cluster instruction pair that have the same opcode, and they are 2868e8d8bef9SDimitry Andric // clusterable according to PowerPC specification. 2869e8d8bef9SDimitry Andric static bool isClusterableLdStOpcPair(unsigned FirstOpc, unsigned SecondOpc, 2870e8d8bef9SDimitry Andric const PPCSubtarget &Subtarget) { 2871e8d8bef9SDimitry Andric switch (FirstOpc) { 2872e8d8bef9SDimitry Andric default: 2873e8d8bef9SDimitry Andric return false; 2874e8d8bef9SDimitry Andric case PPC::STD: 2875e8d8bef9SDimitry Andric case PPC::STFD: 2876e8d8bef9SDimitry Andric case PPC::STXSD: 2877e8d8bef9SDimitry Andric case PPC::DFSTOREf64: 2878e8d8bef9SDimitry Andric return FirstOpc == SecondOpc; 2879e8d8bef9SDimitry Andric // PowerPC backend has opcode STW/STW8 for instruction "stw" to deal with 2880e8d8bef9SDimitry Andric // 32bit and 64bit instruction selection. They are clusterable pair though 2881e8d8bef9SDimitry Andric // they are different opcode. 2882e8d8bef9SDimitry Andric case PPC::STW: 2883e8d8bef9SDimitry Andric case PPC::STW8: 2884e8d8bef9SDimitry Andric return SecondOpc == PPC::STW || SecondOpc == PPC::STW8; 2885e8d8bef9SDimitry Andric } 2886e8d8bef9SDimitry Andric } 2887e8d8bef9SDimitry Andric 2888e8d8bef9SDimitry Andric bool PPCInstrInfo::shouldClusterMemOps( 28895f757f3fSDimitry Andric ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1, 28905f757f3fSDimitry Andric bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2, 28915f757f3fSDimitry Andric int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize, 2892e8d8bef9SDimitry Andric unsigned NumBytes) const { 2893e8d8bef9SDimitry Andric 2894e8d8bef9SDimitry Andric assert(BaseOps1.size() == 1 && BaseOps2.size() == 1); 2895e8d8bef9SDimitry Andric const MachineOperand &BaseOp1 = *BaseOps1.front(); 2896e8d8bef9SDimitry Andric const MachineOperand &BaseOp2 = *BaseOps2.front(); 2897e8d8bef9SDimitry Andric assert((BaseOp1.isReg() || BaseOp1.isFI()) && 2898e8d8bef9SDimitry Andric "Only base registers and frame indices are supported."); 2899e8d8bef9SDimitry Andric 29005f757f3fSDimitry Andric // ClusterSize means the number of memory operations that will have been 29015f757f3fSDimitry Andric // clustered if this hook returns true. 2902e8d8bef9SDimitry Andric // Don't cluster memory op if there are already two ops clustered at least. 29035f757f3fSDimitry Andric if (ClusterSize > 2) 2904e8d8bef9SDimitry Andric return false; 2905e8d8bef9SDimitry Andric 2906e8d8bef9SDimitry Andric // Cluster the load/store only when they have the same base 2907e8d8bef9SDimitry Andric // register or FI. 2908e8d8bef9SDimitry Andric if ((BaseOp1.isReg() != BaseOp2.isReg()) || 2909e8d8bef9SDimitry Andric (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg()) || 2910e8d8bef9SDimitry Andric (BaseOp1.isFI() && BaseOp1.getIndex() != BaseOp2.getIndex())) 2911e8d8bef9SDimitry Andric return false; 2912e8d8bef9SDimitry Andric 2913e8d8bef9SDimitry Andric // Check if the load/store are clusterable according to the PowerPC 2914e8d8bef9SDimitry Andric // specification. 2915e8d8bef9SDimitry Andric const MachineInstr &FirstLdSt = *BaseOp1.getParent(); 2916e8d8bef9SDimitry Andric const MachineInstr &SecondLdSt = *BaseOp2.getParent(); 2917e8d8bef9SDimitry Andric unsigned FirstOpc = FirstLdSt.getOpcode(); 2918e8d8bef9SDimitry Andric unsigned SecondOpc = SecondLdSt.getOpcode(); 2919e8d8bef9SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 2920e8d8bef9SDimitry Andric // Cluster the load/store only when they have the same opcode, and they are 2921e8d8bef9SDimitry Andric // clusterable opcode according to PowerPC specification. 2922e8d8bef9SDimitry Andric if (!isClusterableLdStOpcPair(FirstOpc, SecondOpc, Subtarget)) 2923e8d8bef9SDimitry Andric return false; 2924e8d8bef9SDimitry Andric 2925e8d8bef9SDimitry Andric // Can't cluster load/store that have ordered or volatile memory reference. 2926e8d8bef9SDimitry Andric if (!isLdStSafeToCluster(FirstLdSt, TRI) || 2927e8d8bef9SDimitry Andric !isLdStSafeToCluster(SecondLdSt, TRI)) 2928e8d8bef9SDimitry Andric return false; 2929e8d8bef9SDimitry Andric 2930e8d8bef9SDimitry Andric int64_t Offset1 = 0, Offset2 = 0; 29310fca6ea1SDimitry Andric LocationSize Width1 = 0, Width2 = 0; 2932e8d8bef9SDimitry Andric const MachineOperand *Base1 = nullptr, *Base2 = nullptr; 2933e8d8bef9SDimitry Andric if (!getMemOperandWithOffsetWidth(FirstLdSt, Base1, Offset1, Width1, TRI) || 2934e8d8bef9SDimitry Andric !getMemOperandWithOffsetWidth(SecondLdSt, Base2, Offset2, Width2, TRI) || 2935e8d8bef9SDimitry Andric Width1 != Width2) 2936e8d8bef9SDimitry Andric return false; 2937e8d8bef9SDimitry Andric 2938e8d8bef9SDimitry Andric assert(Base1 == &BaseOp1 && Base2 == &BaseOp2 && 2939e8d8bef9SDimitry Andric "getMemOperandWithOffsetWidth return incorrect base op"); 2940e8d8bef9SDimitry Andric // The caller should already have ordered FirstMemOp/SecondMemOp by offset. 2941e8d8bef9SDimitry Andric assert(Offset1 <= Offset2 && "Caller should have ordered offsets."); 29420fca6ea1SDimitry Andric return Offset1 + (int64_t)Width1.getValue() == Offset2; 2943e8d8bef9SDimitry Andric } 2944e8d8bef9SDimitry Andric 29450b57cec5SDimitry Andric /// GetInstSize - Return the number of bytes of code the specified 29460b57cec5SDimitry Andric /// instruction may be. This returns the maximum number of bytes. 29470b57cec5SDimitry Andric /// 29480b57cec5SDimitry Andric unsigned PPCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { 29490b57cec5SDimitry Andric unsigned Opcode = MI.getOpcode(); 29500b57cec5SDimitry Andric 29510b57cec5SDimitry Andric if (Opcode == PPC::INLINEASM || Opcode == PPC::INLINEASM_BR) { 29520b57cec5SDimitry Andric const MachineFunction *MF = MI.getParent()->getParent(); 29530b57cec5SDimitry Andric const char *AsmStr = MI.getOperand(0).getSymbolName(); 29540b57cec5SDimitry Andric return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); 29550b57cec5SDimitry Andric } else if (Opcode == TargetOpcode::STACKMAP) { 29560b57cec5SDimitry Andric StackMapOpers Opers(&MI); 29570b57cec5SDimitry Andric return Opers.getNumPatchBytes(); 29580b57cec5SDimitry Andric } else if (Opcode == TargetOpcode::PATCHPOINT) { 29590b57cec5SDimitry Andric PatchPointOpers Opers(&MI); 29600b57cec5SDimitry Andric return Opers.getNumPatchBytes(); 29610b57cec5SDimitry Andric } else { 29620b57cec5SDimitry Andric return get(Opcode).getSize(); 29630b57cec5SDimitry Andric } 29640b57cec5SDimitry Andric } 29650b57cec5SDimitry Andric 29660b57cec5SDimitry Andric std::pair<unsigned, unsigned> 29670b57cec5SDimitry Andric PPCInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 29685f757f3fSDimitry Andric // PPC always uses a direct mask. 29695f757f3fSDimitry Andric return std::make_pair(TF, 0u); 29700b57cec5SDimitry Andric } 29710b57cec5SDimitry Andric 29720b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 29730b57cec5SDimitry Andric PPCInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 29740b57cec5SDimitry Andric using namespace PPCII; 29750b57cec5SDimitry Andric static const std::pair<unsigned, const char *> TargetFlags[] = { 29760b57cec5SDimitry Andric {MO_PLT, "ppc-plt"}, 29770b57cec5SDimitry Andric {MO_PIC_FLAG, "ppc-pic"}, 29785ffd83dbSDimitry Andric {MO_PCREL_FLAG, "ppc-pcrel"}, 2979e8d8bef9SDimitry Andric {MO_GOT_FLAG, "ppc-got"}, 2980e8d8bef9SDimitry Andric {MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"}, 2981e8d8bef9SDimitry Andric {MO_TLSGD_FLAG, "ppc-tlsgd"}, 2982e8d8bef9SDimitry Andric {MO_TPREL_FLAG, "ppc-tprel"}, 29830fca6ea1SDimitry Andric {MO_TLSLDM_FLAG, "ppc-tlsldm"}, 29845f757f3fSDimitry Andric {MO_TLSLD_FLAG, "ppc-tlsld"}, 2985fe6060f1SDimitry Andric {MO_TLSGDM_FLAG, "ppc-tlsgdm"}, 2986e8d8bef9SDimitry Andric {MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"}, 2987e8d8bef9SDimitry Andric {MO_GOT_TLSLD_PCREL_FLAG, "ppc-got-tlsld-pcrel"}, 29885f757f3fSDimitry Andric {MO_GOT_TPREL_PCREL_FLAG, "ppc-got-tprel-pcrel"}, 29895f757f3fSDimitry Andric {MO_LO, "ppc-lo"}, 29905f757f3fSDimitry Andric {MO_HA, "ppc-ha"}, 29915f757f3fSDimitry Andric {MO_TPREL_LO, "ppc-tprel-lo"}, 29925f757f3fSDimitry Andric {MO_TPREL_HA, "ppc-tprel-ha"}, 29935f757f3fSDimitry Andric {MO_DTPREL_LO, "ppc-dtprel-lo"}, 29945f757f3fSDimitry Andric {MO_TLSLD_LO, "ppc-tlsld-lo"}, 29955f757f3fSDimitry Andric {MO_TOC_LO, "ppc-toc-lo"}, 29965f757f3fSDimitry Andric {MO_TLS, "ppc-tls"}, 29975f757f3fSDimitry Andric {MO_PIC_HA_FLAG, "ppc-ha-pic"}, 29985f757f3fSDimitry Andric {MO_PIC_LO_FLAG, "ppc-lo-pic"}, 29995f757f3fSDimitry Andric {MO_TPREL_PCREL_FLAG, "ppc-tprel-pcrel"}, 30005f757f3fSDimitry Andric {MO_TLS_PCREL_FLAG, "ppc-tls-pcrel"}, 30015f757f3fSDimitry Andric {MO_GOT_PCREL_FLAG, "ppc-got-pcrel"}, 30025f757f3fSDimitry Andric }; 3003bdd1243dSDimitry Andric return ArrayRef(TargetFlags); 30040b57cec5SDimitry Andric } 30050b57cec5SDimitry Andric 30060b57cec5SDimitry Andric // Expand VSX Memory Pseudo instruction to either a VSX or a FP instruction. 30070b57cec5SDimitry Andric // The VSX versions have the advantage of a full 64-register target whereas 30080b57cec5SDimitry Andric // the FP ones have the advantage of lower latency and higher throughput. So 30090b57cec5SDimitry Andric // what we are after is using the faster instructions in low register pressure 30100b57cec5SDimitry Andric // situations and using the larger register file in high register pressure 30110b57cec5SDimitry Andric // situations. 30120b57cec5SDimitry Andric bool PPCInstrInfo::expandVSXMemPseudo(MachineInstr &MI) const { 30130b57cec5SDimitry Andric unsigned UpperOpcode, LowerOpcode; 30140b57cec5SDimitry Andric switch (MI.getOpcode()) { 30150b57cec5SDimitry Andric case PPC::DFLOADf32: 30160b57cec5SDimitry Andric UpperOpcode = PPC::LXSSP; 30170b57cec5SDimitry Andric LowerOpcode = PPC::LFS; 30180b57cec5SDimitry Andric break; 30190b57cec5SDimitry Andric case PPC::DFLOADf64: 30200b57cec5SDimitry Andric UpperOpcode = PPC::LXSD; 30210b57cec5SDimitry Andric LowerOpcode = PPC::LFD; 30220b57cec5SDimitry Andric break; 30230b57cec5SDimitry Andric case PPC::DFSTOREf32: 30240b57cec5SDimitry Andric UpperOpcode = PPC::STXSSP; 30250b57cec5SDimitry Andric LowerOpcode = PPC::STFS; 30260b57cec5SDimitry Andric break; 30270b57cec5SDimitry Andric case PPC::DFSTOREf64: 30280b57cec5SDimitry Andric UpperOpcode = PPC::STXSD; 30290b57cec5SDimitry Andric LowerOpcode = PPC::STFD; 30300b57cec5SDimitry Andric break; 30310b57cec5SDimitry Andric case PPC::XFLOADf32: 30320b57cec5SDimitry Andric UpperOpcode = PPC::LXSSPX; 30330b57cec5SDimitry Andric LowerOpcode = PPC::LFSX; 30340b57cec5SDimitry Andric break; 30350b57cec5SDimitry Andric case PPC::XFLOADf64: 30360b57cec5SDimitry Andric UpperOpcode = PPC::LXSDX; 30370b57cec5SDimitry Andric LowerOpcode = PPC::LFDX; 30380b57cec5SDimitry Andric break; 30390b57cec5SDimitry Andric case PPC::XFSTOREf32: 30400b57cec5SDimitry Andric UpperOpcode = PPC::STXSSPX; 30410b57cec5SDimitry Andric LowerOpcode = PPC::STFSX; 30420b57cec5SDimitry Andric break; 30430b57cec5SDimitry Andric case PPC::XFSTOREf64: 30440b57cec5SDimitry Andric UpperOpcode = PPC::STXSDX; 30450b57cec5SDimitry Andric LowerOpcode = PPC::STFDX; 30460b57cec5SDimitry Andric break; 30470b57cec5SDimitry Andric case PPC::LIWAX: 30480b57cec5SDimitry Andric UpperOpcode = PPC::LXSIWAX; 30490b57cec5SDimitry Andric LowerOpcode = PPC::LFIWAX; 30500b57cec5SDimitry Andric break; 30510b57cec5SDimitry Andric case PPC::LIWZX: 30520b57cec5SDimitry Andric UpperOpcode = PPC::LXSIWZX; 30530b57cec5SDimitry Andric LowerOpcode = PPC::LFIWZX; 30540b57cec5SDimitry Andric break; 30550b57cec5SDimitry Andric case PPC::STIWX: 30560b57cec5SDimitry Andric UpperOpcode = PPC::STXSIWX; 30570b57cec5SDimitry Andric LowerOpcode = PPC::STFIWX; 30580b57cec5SDimitry Andric break; 30590b57cec5SDimitry Andric default: 30600b57cec5SDimitry Andric llvm_unreachable("Unknown Operation!"); 30610b57cec5SDimitry Andric } 30620b57cec5SDimitry Andric 30638bcb0991SDimitry Andric Register TargetReg = MI.getOperand(0).getReg(); 30640b57cec5SDimitry Andric unsigned Opcode; 30650b57cec5SDimitry Andric if ((TargetReg >= PPC::F0 && TargetReg <= PPC::F31) || 30660b57cec5SDimitry Andric (TargetReg >= PPC::VSL0 && TargetReg <= PPC::VSL31)) 30670b57cec5SDimitry Andric Opcode = LowerOpcode; 30680b57cec5SDimitry Andric else 30690b57cec5SDimitry Andric Opcode = UpperOpcode; 30700b57cec5SDimitry Andric MI.setDesc(get(Opcode)); 30710b57cec5SDimitry Andric return true; 30720b57cec5SDimitry Andric } 30730b57cec5SDimitry Andric 30740b57cec5SDimitry Andric static bool isAnImmediateOperand(const MachineOperand &MO) { 30750b57cec5SDimitry Andric return MO.isCPI() || MO.isGlobal() || MO.isImm(); 30760b57cec5SDimitry Andric } 30770b57cec5SDimitry Andric 30780b57cec5SDimitry Andric bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 30790b57cec5SDimitry Andric auto &MBB = *MI.getParent(); 30800b57cec5SDimitry Andric auto DL = MI.getDebugLoc(); 30810b57cec5SDimitry Andric 30820b57cec5SDimitry Andric switch (MI.getOpcode()) { 3083e8d8bef9SDimitry Andric case PPC::BUILD_UACC: { 3084e8d8bef9SDimitry Andric MCRegister ACC = MI.getOperand(0).getReg(); 3085e8d8bef9SDimitry Andric MCRegister UACC = MI.getOperand(1).getReg(); 3086e8d8bef9SDimitry Andric if (ACC - PPC::ACC0 != UACC - PPC::UACC0) { 3087e8d8bef9SDimitry Andric MCRegister SrcVSR = PPC::VSL0 + (UACC - PPC::UACC0) * 4; 3088e8d8bef9SDimitry Andric MCRegister DstVSR = PPC::VSL0 + (ACC - PPC::ACC0) * 4; 3089e8d8bef9SDimitry Andric // FIXME: This can easily be improved to look up to the top of the MBB 3090e8d8bef9SDimitry Andric // to see if the inputs are XXLOR's. If they are and SrcReg is killed, 3091e8d8bef9SDimitry Andric // we can just re-target any such XXLOR's to DstVSR + offset. 3092e8d8bef9SDimitry Andric for (int VecNo = 0; VecNo < 4; VecNo++) 3093e8d8bef9SDimitry Andric BuildMI(MBB, MI, DL, get(PPC::XXLOR), DstVSR + VecNo) 3094e8d8bef9SDimitry Andric .addReg(SrcVSR + VecNo) 3095e8d8bef9SDimitry Andric .addReg(SrcVSR + VecNo); 3096e8d8bef9SDimitry Andric } 3097349cc55cSDimitry Andric // BUILD_UACC is expanded to 4 copies of the underlying vsx registers. 3098e8d8bef9SDimitry Andric // So after building the 4 copies, we can replace the BUILD_UACC instruction 3099e8d8bef9SDimitry Andric // with a NOP. 3100bdd1243dSDimitry Andric [[fallthrough]]; 3101e8d8bef9SDimitry Andric } 3102e8d8bef9SDimitry Andric case PPC::KILL_PAIR: { 3103e8d8bef9SDimitry Andric MI.setDesc(get(PPC::UNENCODED_NOP)); 310481ad6265SDimitry Andric MI.removeOperand(1); 310581ad6265SDimitry Andric MI.removeOperand(0); 3106e8d8bef9SDimitry Andric return true; 3107e8d8bef9SDimitry Andric } 31080b57cec5SDimitry Andric case TargetOpcode::LOAD_STACK_GUARD: { 31090b57cec5SDimitry Andric assert(Subtarget.isTargetLinux() && 31100b57cec5SDimitry Andric "Only Linux target is expected to contain LOAD_STACK_GUARD"); 31110b57cec5SDimitry Andric const int64_t Offset = Subtarget.isPPC64() ? -0x7010 : -0x7008; 31120b57cec5SDimitry Andric const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2; 31130b57cec5SDimitry Andric MI.setDesc(get(Subtarget.isPPC64() ? PPC::LD : PPC::LWZ)); 31140b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 31150b57cec5SDimitry Andric .addImm(Offset) 31160b57cec5SDimitry Andric .addReg(Reg); 31170b57cec5SDimitry Andric return true; 31180b57cec5SDimitry Andric } 31190fca6ea1SDimitry Andric case PPC::PPCLdFixedAddr: { 31200fca6ea1SDimitry Andric assert(Subtarget.getTargetTriple().isOSGlibc() && 31210fca6ea1SDimitry Andric "Only targets with Glibc expected to contain PPCLdFixedAddr"); 31220fca6ea1SDimitry Andric int64_t Offset = 0; 31230fca6ea1SDimitry Andric const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2; 31240fca6ea1SDimitry Andric MI.setDesc(get(PPC::LWZ)); 31250fca6ea1SDimitry Andric uint64_t FAType = MI.getOperand(1).getImm(); 31260fca6ea1SDimitry Andric #undef PPC_LNX_FEATURE 31270fca6ea1SDimitry Andric #undef PPC_CPU 31280fca6ea1SDimitry Andric #define PPC_LNX_DEFINE_OFFSETS 31290fca6ea1SDimitry Andric #include "llvm/TargetParser/PPCTargetParser.def" 31300fca6ea1SDimitry Andric bool IsLE = Subtarget.isLittleEndian(); 31310fca6ea1SDimitry Andric bool Is64 = Subtarget.isPPC64(); 31320fca6ea1SDimitry Andric if (FAType == PPC_FAWORD_HWCAP) { 31330fca6ea1SDimitry Andric if (IsLE) 31340fca6ea1SDimitry Andric Offset = Is64 ? PPC_HWCAP_OFFSET_LE64 : PPC_HWCAP_OFFSET_LE32; 31350fca6ea1SDimitry Andric else 31360fca6ea1SDimitry Andric Offset = Is64 ? PPC_HWCAP_OFFSET_BE64 : PPC_HWCAP_OFFSET_BE32; 31370fca6ea1SDimitry Andric } else if (FAType == PPC_FAWORD_HWCAP2) { 31380fca6ea1SDimitry Andric if (IsLE) 31390fca6ea1SDimitry Andric Offset = Is64 ? PPC_HWCAP2_OFFSET_LE64 : PPC_HWCAP2_OFFSET_LE32; 31400fca6ea1SDimitry Andric else 31410fca6ea1SDimitry Andric Offset = Is64 ? PPC_HWCAP2_OFFSET_BE64 : PPC_HWCAP2_OFFSET_BE32; 31420fca6ea1SDimitry Andric } else if (FAType == PPC_FAWORD_CPUID) { 31430fca6ea1SDimitry Andric if (IsLE) 31440fca6ea1SDimitry Andric Offset = Is64 ? PPC_CPUID_OFFSET_LE64 : PPC_CPUID_OFFSET_LE32; 31450fca6ea1SDimitry Andric else 31460fca6ea1SDimitry Andric Offset = Is64 ? PPC_CPUID_OFFSET_BE64 : PPC_CPUID_OFFSET_BE32; 31470fca6ea1SDimitry Andric } 31480fca6ea1SDimitry Andric assert(Offset && "Do not know the offset for this fixed addr load"); 31490fca6ea1SDimitry Andric MI.removeOperand(1); 31500fca6ea1SDimitry Andric Subtarget.getTargetMachine().setGlibcHWCAPAccess(); 31510fca6ea1SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 31520fca6ea1SDimitry Andric .addImm(Offset) 31530fca6ea1SDimitry Andric .addReg(Reg); 31540fca6ea1SDimitry Andric return true; 31550fca6ea1SDimitry Andric #define PPC_TGT_PARSER_UNDEF_MACROS 31560fca6ea1SDimitry Andric #include "llvm/TargetParser/PPCTargetParser.def" 31570fca6ea1SDimitry Andric #undef PPC_TGT_PARSER_UNDEF_MACROS 31580fca6ea1SDimitry Andric } 31590b57cec5SDimitry Andric case PPC::DFLOADf32: 31600b57cec5SDimitry Andric case PPC::DFLOADf64: 31610b57cec5SDimitry Andric case PPC::DFSTOREf32: 31620b57cec5SDimitry Andric case PPC::DFSTOREf64: { 31630b57cec5SDimitry Andric assert(Subtarget.hasP9Vector() && 31640b57cec5SDimitry Andric "Invalid D-Form Pseudo-ops on Pre-P9 target."); 31650b57cec5SDimitry Andric assert(MI.getOperand(2).isReg() && 31660b57cec5SDimitry Andric isAnImmediateOperand(MI.getOperand(1)) && 31670b57cec5SDimitry Andric "D-form op must have register and immediate operands"); 31680b57cec5SDimitry Andric return expandVSXMemPseudo(MI); 31690b57cec5SDimitry Andric } 31700b57cec5SDimitry Andric case PPC::XFLOADf32: 31710b57cec5SDimitry Andric case PPC::XFSTOREf32: 31720b57cec5SDimitry Andric case PPC::LIWAX: 31730b57cec5SDimitry Andric case PPC::LIWZX: 31740b57cec5SDimitry Andric case PPC::STIWX: { 31750b57cec5SDimitry Andric assert(Subtarget.hasP8Vector() && 31760b57cec5SDimitry Andric "Invalid X-Form Pseudo-ops on Pre-P8 target."); 31770b57cec5SDimitry Andric assert(MI.getOperand(2).isReg() && MI.getOperand(1).isReg() && 31780b57cec5SDimitry Andric "X-form op must have register and register operands"); 31790b57cec5SDimitry Andric return expandVSXMemPseudo(MI); 31800b57cec5SDimitry Andric } 31810b57cec5SDimitry Andric case PPC::XFLOADf64: 31820b57cec5SDimitry Andric case PPC::XFSTOREf64: { 31830b57cec5SDimitry Andric assert(Subtarget.hasVSX() && 31840b57cec5SDimitry Andric "Invalid X-Form Pseudo-ops on target that has no VSX."); 31850b57cec5SDimitry Andric assert(MI.getOperand(2).isReg() && MI.getOperand(1).isReg() && 31860b57cec5SDimitry Andric "X-form op must have register and register operands"); 31870b57cec5SDimitry Andric return expandVSXMemPseudo(MI); 31880b57cec5SDimitry Andric } 31890b57cec5SDimitry Andric case PPC::SPILLTOVSR_LD: { 31908bcb0991SDimitry Andric Register TargetReg = MI.getOperand(0).getReg(); 31910b57cec5SDimitry Andric if (PPC::VSFRCRegClass.contains(TargetReg)) { 31920b57cec5SDimitry Andric MI.setDesc(get(PPC::DFLOADf64)); 31930b57cec5SDimitry Andric return expandPostRAPseudo(MI); 31940b57cec5SDimitry Andric } 31950b57cec5SDimitry Andric else 31960b57cec5SDimitry Andric MI.setDesc(get(PPC::LD)); 31970b57cec5SDimitry Andric return true; 31980b57cec5SDimitry Andric } 31990b57cec5SDimitry Andric case PPC::SPILLTOVSR_ST: { 32008bcb0991SDimitry Andric Register SrcReg = MI.getOperand(0).getReg(); 32010b57cec5SDimitry Andric if (PPC::VSFRCRegClass.contains(SrcReg)) { 32020b57cec5SDimitry Andric NumStoreSPILLVSRRCAsVec++; 32030b57cec5SDimitry Andric MI.setDesc(get(PPC::DFSTOREf64)); 32040b57cec5SDimitry Andric return expandPostRAPseudo(MI); 32050b57cec5SDimitry Andric } else { 32060b57cec5SDimitry Andric NumStoreSPILLVSRRCAsGpr++; 32070b57cec5SDimitry Andric MI.setDesc(get(PPC::STD)); 32080b57cec5SDimitry Andric } 32090b57cec5SDimitry Andric return true; 32100b57cec5SDimitry Andric } 32110b57cec5SDimitry Andric case PPC::SPILLTOVSR_LDX: { 32128bcb0991SDimitry Andric Register TargetReg = MI.getOperand(0).getReg(); 32130b57cec5SDimitry Andric if (PPC::VSFRCRegClass.contains(TargetReg)) 32140b57cec5SDimitry Andric MI.setDesc(get(PPC::LXSDX)); 32150b57cec5SDimitry Andric else 32160b57cec5SDimitry Andric MI.setDesc(get(PPC::LDX)); 32170b57cec5SDimitry Andric return true; 32180b57cec5SDimitry Andric } 32190b57cec5SDimitry Andric case PPC::SPILLTOVSR_STX: { 32208bcb0991SDimitry Andric Register SrcReg = MI.getOperand(0).getReg(); 32210b57cec5SDimitry Andric if (PPC::VSFRCRegClass.contains(SrcReg)) { 32220b57cec5SDimitry Andric NumStoreSPILLVSRRCAsVec++; 32230b57cec5SDimitry Andric MI.setDesc(get(PPC::STXSDX)); 32240b57cec5SDimitry Andric } else { 32250b57cec5SDimitry Andric NumStoreSPILLVSRRCAsGpr++; 32260b57cec5SDimitry Andric MI.setDesc(get(PPC::STDX)); 32270b57cec5SDimitry Andric } 32280b57cec5SDimitry Andric return true; 32290b57cec5SDimitry Andric } 32300b57cec5SDimitry Andric 3231349cc55cSDimitry Andric // FIXME: Maybe we can expand it in 'PowerPC Expand Atomic' pass. 3232cb14a3feSDimitry Andric case PPC::CFENCE: 32330b57cec5SDimitry Andric case PPC::CFENCE8: { 32340b57cec5SDimitry Andric auto Val = MI.getOperand(0).getReg(); 3235cb14a3feSDimitry Andric unsigned CmpOp = Subtarget.isPPC64() ? PPC::CMPD : PPC::CMPW; 3236cb14a3feSDimitry Andric BuildMI(MBB, MI, DL, get(CmpOp), PPC::CR7).addReg(Val).addReg(Val); 32370b57cec5SDimitry Andric BuildMI(MBB, MI, DL, get(PPC::CTRL_DEP)) 32380b57cec5SDimitry Andric .addImm(PPC::PRED_NE_MINUS) 32390b57cec5SDimitry Andric .addReg(PPC::CR7) 32400b57cec5SDimitry Andric .addImm(1); 32410b57cec5SDimitry Andric MI.setDesc(get(PPC::ISYNC)); 324281ad6265SDimitry Andric MI.removeOperand(0); 32430b57cec5SDimitry Andric return true; 32440b57cec5SDimitry Andric } 32450b57cec5SDimitry Andric } 32460b57cec5SDimitry Andric return false; 32470b57cec5SDimitry Andric } 32480b57cec5SDimitry Andric 32490b57cec5SDimitry Andric // Essentially a compile-time implementation of a compare->isel sequence. 32500b57cec5SDimitry Andric // It takes two constants to compare, along with the true/false registers 32510b57cec5SDimitry Andric // and the comparison type (as a subreg to a CR field) and returns one 32520b57cec5SDimitry Andric // of the true/false registers, depending on the comparison results. 32530b57cec5SDimitry Andric static unsigned selectReg(int64_t Imm1, int64_t Imm2, unsigned CompareOpc, 32540b57cec5SDimitry Andric unsigned TrueReg, unsigned FalseReg, 32550b57cec5SDimitry Andric unsigned CRSubReg) { 32560b57cec5SDimitry Andric // Signed comparisons. The immediates are assumed to be sign-extended. 32570b57cec5SDimitry Andric if (CompareOpc == PPC::CMPWI || CompareOpc == PPC::CMPDI) { 32580b57cec5SDimitry Andric switch (CRSubReg) { 32590b57cec5SDimitry Andric default: llvm_unreachable("Unknown integer comparison type."); 32600b57cec5SDimitry Andric case PPC::sub_lt: 32610b57cec5SDimitry Andric return Imm1 < Imm2 ? TrueReg : FalseReg; 32620b57cec5SDimitry Andric case PPC::sub_gt: 32630b57cec5SDimitry Andric return Imm1 > Imm2 ? TrueReg : FalseReg; 32640b57cec5SDimitry Andric case PPC::sub_eq: 32650b57cec5SDimitry Andric return Imm1 == Imm2 ? TrueReg : FalseReg; 32660b57cec5SDimitry Andric } 32670b57cec5SDimitry Andric } 32680b57cec5SDimitry Andric // Unsigned comparisons. 32690b57cec5SDimitry Andric else if (CompareOpc == PPC::CMPLWI || CompareOpc == PPC::CMPLDI) { 32700b57cec5SDimitry Andric switch (CRSubReg) { 32710b57cec5SDimitry Andric default: llvm_unreachable("Unknown integer comparison type."); 32720b57cec5SDimitry Andric case PPC::sub_lt: 32730b57cec5SDimitry Andric return (uint64_t)Imm1 < (uint64_t)Imm2 ? TrueReg : FalseReg; 32740b57cec5SDimitry Andric case PPC::sub_gt: 32750b57cec5SDimitry Andric return (uint64_t)Imm1 > (uint64_t)Imm2 ? TrueReg : FalseReg; 32760b57cec5SDimitry Andric case PPC::sub_eq: 32770b57cec5SDimitry Andric return Imm1 == Imm2 ? TrueReg : FalseReg; 32780b57cec5SDimitry Andric } 32790b57cec5SDimitry Andric } 32800b57cec5SDimitry Andric return PPC::NoRegister; 32810b57cec5SDimitry Andric } 32820b57cec5SDimitry Andric 32830b57cec5SDimitry Andric void PPCInstrInfo::replaceInstrOperandWithImm(MachineInstr &MI, 32840b57cec5SDimitry Andric unsigned OpNo, 32850b57cec5SDimitry Andric int64_t Imm) const { 32860b57cec5SDimitry Andric assert(MI.getOperand(OpNo).isReg() && "Operand must be a REG"); 32870b57cec5SDimitry Andric // Replace the REG with the Immediate. 32888bcb0991SDimitry Andric Register InUseReg = MI.getOperand(OpNo).getReg(); 32890b57cec5SDimitry Andric MI.getOperand(OpNo).ChangeToImmediate(Imm); 32900b57cec5SDimitry Andric 32910b57cec5SDimitry Andric // We need to make sure that the MI didn't have any implicit use 3292fe6060f1SDimitry Andric // of this REG any more. We don't call MI.implicit_operands().empty() to 3293fe6060f1SDimitry Andric // return early, since MI's MCID might be changed in calling context, as a 3294fe6060f1SDimitry Andric // result its number of explicit operands may be changed, thus the begin of 3295fe6060f1SDimitry Andric // implicit operand is changed. 32960b57cec5SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 32970fca6ea1SDimitry Andric int UseOpIdx = MI.findRegisterUseOperandIdx(InUseReg, TRI, false); 32980b57cec5SDimitry Andric if (UseOpIdx >= 0) { 32990b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(UseOpIdx); 33000b57cec5SDimitry Andric if (MO.isImplicit()) 33010b57cec5SDimitry Andric // The operands must always be in the following order: 33020b57cec5SDimitry Andric // - explicit reg defs, 33030b57cec5SDimitry Andric // - other explicit operands (reg uses, immediates, etc.), 33040b57cec5SDimitry Andric // - implicit reg defs 33050b57cec5SDimitry Andric // - implicit reg uses 33060b57cec5SDimitry Andric // Therefore, removing the implicit operand won't change the explicit 33070b57cec5SDimitry Andric // operands layout. 330881ad6265SDimitry Andric MI.removeOperand(UseOpIdx); 33090b57cec5SDimitry Andric } 33100b57cec5SDimitry Andric } 33110b57cec5SDimitry Andric 33120b57cec5SDimitry Andric // Replace an instruction with one that materializes a constant (and sets 33130b57cec5SDimitry Andric // CR0 if the original instruction was a record-form instruction). 33140b57cec5SDimitry Andric void PPCInstrInfo::replaceInstrWithLI(MachineInstr &MI, 33150b57cec5SDimitry Andric const LoadImmediateInfo &LII) const { 33160b57cec5SDimitry Andric // Remove existing operands. 33170b57cec5SDimitry Andric int OperandToKeep = LII.SetCR ? 1 : 0; 33180b57cec5SDimitry Andric for (int i = MI.getNumOperands() - 1; i > OperandToKeep; i--) 331981ad6265SDimitry Andric MI.removeOperand(i); 33200b57cec5SDimitry Andric 33210b57cec5SDimitry Andric // Replace the instruction. 33220b57cec5SDimitry Andric if (LII.SetCR) { 3323480093f4SDimitry Andric MI.setDesc(get(LII.Is64Bit ? PPC::ANDI8_rec : PPC::ANDI_rec)); 33240b57cec5SDimitry Andric // Set the immediate. 33250b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 33260b57cec5SDimitry Andric .addImm(LII.Imm).addReg(PPC::CR0, RegState::ImplicitDefine); 33270b57cec5SDimitry Andric return; 33280b57cec5SDimitry Andric } 33290b57cec5SDimitry Andric else 33300b57cec5SDimitry Andric MI.setDesc(get(LII.Is64Bit ? PPC::LI8 : PPC::LI)); 33310b57cec5SDimitry Andric 33320b57cec5SDimitry Andric // Set the immediate. 33330b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI) 33340b57cec5SDimitry Andric .addImm(LII.Imm); 33350b57cec5SDimitry Andric } 33360b57cec5SDimitry Andric 33378bcb0991SDimitry Andric MachineInstr *PPCInstrInfo::getDefMIPostRA(unsigned Reg, MachineInstr &MI, 33388bcb0991SDimitry Andric bool &SeenIntermediateUse) const { 33398bcb0991SDimitry Andric assert(!MI.getParent()->getParent()->getRegInfo().isSSA() && 33408bcb0991SDimitry Andric "Should be called after register allocation."); 33418bcb0991SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 33428bcb0991SDimitry Andric MachineBasicBlock::reverse_iterator E = MI.getParent()->rend(), It = MI; 33438bcb0991SDimitry Andric It++; 33448bcb0991SDimitry Andric SeenIntermediateUse = false; 33458bcb0991SDimitry Andric for (; It != E; ++It) { 33468bcb0991SDimitry Andric if (It->modifiesRegister(Reg, TRI)) 33478bcb0991SDimitry Andric return &*It; 33488bcb0991SDimitry Andric if (It->readsRegister(Reg, TRI)) 33498bcb0991SDimitry Andric SeenIntermediateUse = true; 33508bcb0991SDimitry Andric } 33518bcb0991SDimitry Andric return nullptr; 33528bcb0991SDimitry Andric } 33538bcb0991SDimitry Andric 335481ad6265SDimitry Andric void PPCInstrInfo::materializeImmPostRA(MachineBasicBlock &MBB, 335581ad6265SDimitry Andric MachineBasicBlock::iterator MBBI, 335681ad6265SDimitry Andric const DebugLoc &DL, Register Reg, 335781ad6265SDimitry Andric int64_t Imm) const { 335881ad6265SDimitry Andric assert(!MBB.getParent()->getRegInfo().isSSA() && 335981ad6265SDimitry Andric "Register should be in non-SSA form after RA"); 336081ad6265SDimitry Andric bool isPPC64 = Subtarget.isPPC64(); 336181ad6265SDimitry Andric // FIXME: Materialization here is not optimal. 336281ad6265SDimitry Andric // For some special bit patterns we can use less instructions. 336381ad6265SDimitry Andric // See `selectI64ImmDirect` in PPCISelDAGToDAG.cpp. 336481ad6265SDimitry Andric if (isInt<16>(Imm)) { 336581ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(isPPC64 ? PPC::LI8 : PPC::LI), Reg).addImm(Imm); 336681ad6265SDimitry Andric } else if (isInt<32>(Imm)) { 336781ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(isPPC64 ? PPC::LIS8 : PPC::LIS), Reg) 336881ad6265SDimitry Andric .addImm(Imm >> 16); 336981ad6265SDimitry Andric if (Imm & 0xFFFF) 337081ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(isPPC64 ? PPC::ORI8 : PPC::ORI), Reg) 337181ad6265SDimitry Andric .addReg(Reg, RegState::Kill) 337281ad6265SDimitry Andric .addImm(Imm & 0xFFFF); 337381ad6265SDimitry Andric } else { 337481ad6265SDimitry Andric assert(isPPC64 && "Materializing 64-bit immediate to single register is " 337581ad6265SDimitry Andric "only supported in PPC64"); 337681ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(PPC::LIS8), Reg).addImm(Imm >> 48); 337781ad6265SDimitry Andric if ((Imm >> 32) & 0xFFFF) 337881ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(PPC::ORI8), Reg) 337981ad6265SDimitry Andric .addReg(Reg, RegState::Kill) 338081ad6265SDimitry Andric .addImm((Imm >> 32) & 0xFFFF); 338181ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(PPC::RLDICR), Reg) 338281ad6265SDimitry Andric .addReg(Reg, RegState::Kill) 338381ad6265SDimitry Andric .addImm(32) 338481ad6265SDimitry Andric .addImm(31); 338581ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(PPC::ORIS8), Reg) 338681ad6265SDimitry Andric .addReg(Reg, RegState::Kill) 338781ad6265SDimitry Andric .addImm((Imm >> 16) & 0xFFFF); 338881ad6265SDimitry Andric if (Imm & 0xFFFF) 338981ad6265SDimitry Andric BuildMI(MBB, MBBI, DL, get(PPC::ORI8), Reg) 339081ad6265SDimitry Andric .addReg(Reg, RegState::Kill) 339181ad6265SDimitry Andric .addImm(Imm & 0xFFFF); 339281ad6265SDimitry Andric } 339381ad6265SDimitry Andric } 339481ad6265SDimitry Andric 33950b57cec5SDimitry Andric MachineInstr *PPCInstrInfo::getForwardingDefMI( 33960b57cec5SDimitry Andric MachineInstr &MI, 33970b57cec5SDimitry Andric unsigned &OpNoForForwarding, 33980b57cec5SDimitry Andric bool &SeenIntermediateUse) const { 33990b57cec5SDimitry Andric OpNoForForwarding = ~0U; 34000b57cec5SDimitry Andric MachineInstr *DefMI = nullptr; 34010b57cec5SDimitry Andric MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo(); 34020b57cec5SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 34030b57cec5SDimitry Andric // If we're in SSA, get the defs through the MRI. Otherwise, only look 34045ffd83dbSDimitry Andric // within the basic block to see if the register is defined using an 34055ffd83dbSDimitry Andric // LI/LI8/ADDI/ADDI8. 34060b57cec5SDimitry Andric if (MRI->isSSA()) { 34070b57cec5SDimitry Andric for (int i = 1, e = MI.getNumOperands(); i < e; i++) { 34080b57cec5SDimitry Andric if (!MI.getOperand(i).isReg()) 34090b57cec5SDimitry Andric continue; 34108bcb0991SDimitry Andric Register Reg = MI.getOperand(i).getReg(); 3411bdd1243dSDimitry Andric if (!Reg.isVirtual()) 34120b57cec5SDimitry Andric continue; 341304eeddc0SDimitry Andric Register TrueReg = TRI->lookThruCopyLike(Reg, MRI); 3414bdd1243dSDimitry Andric if (TrueReg.isVirtual()) { 3415bdd1243dSDimitry Andric MachineInstr *DefMIForTrueReg = MRI->getVRegDef(TrueReg); 3416bdd1243dSDimitry Andric if (DefMIForTrueReg->getOpcode() == PPC::LI || 3417bdd1243dSDimitry Andric DefMIForTrueReg->getOpcode() == PPC::LI8 || 3418bdd1243dSDimitry Andric DefMIForTrueReg->getOpcode() == PPC::ADDI || 3419bdd1243dSDimitry Andric DefMIForTrueReg->getOpcode() == PPC::ADDI8) { 34200b57cec5SDimitry Andric OpNoForForwarding = i; 3421bdd1243dSDimitry Andric DefMI = DefMIForTrueReg; 34225ffd83dbSDimitry Andric // The ADDI and LI operand maybe exist in one instruction at same 34235ffd83dbSDimitry Andric // time. we prefer to fold LI operand as LI only has one Imm operand 34245ffd83dbSDimitry Andric // and is more possible to be converted. So if current DefMI is 34255ffd83dbSDimitry Andric // ADDI/ADDI8, we continue to find possible LI/LI8. 34265ffd83dbSDimitry Andric if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8) 34270b57cec5SDimitry Andric break; 34280b57cec5SDimitry Andric } 34290b57cec5SDimitry Andric } 34300b57cec5SDimitry Andric } 34310b57cec5SDimitry Andric } else { 34320b57cec5SDimitry Andric // Looking back through the definition for each operand could be expensive, 34330b57cec5SDimitry Andric // so exit early if this isn't an instruction that either has an immediate 34340b57cec5SDimitry Andric // form or is already an immediate form that we can handle. 34350b57cec5SDimitry Andric ImmInstrInfo III; 34360b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 34370b57cec5SDimitry Andric bool ConvertibleImmForm = 3438480093f4SDimitry Andric Opc == PPC::CMPWI || Opc == PPC::CMPLWI || Opc == PPC::CMPDI || 3439480093f4SDimitry Andric Opc == PPC::CMPLDI || Opc == PPC::ADDI || Opc == PPC::ADDI8 || 3440480093f4SDimitry Andric Opc == PPC::ORI || Opc == PPC::ORI8 || Opc == PPC::XORI || 3441480093f4SDimitry Andric Opc == PPC::XORI8 || Opc == PPC::RLDICL || Opc == PPC::RLDICL_rec || 34420b57cec5SDimitry Andric Opc == PPC::RLDICL_32 || Opc == PPC::RLDICL_32_64 || 3443480093f4SDimitry Andric Opc == PPC::RLWINM || Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8 || 3444480093f4SDimitry Andric Opc == PPC::RLWINM8_rec; 34458bcb0991SDimitry Andric bool IsVFReg = (MI.getNumOperands() && MI.getOperand(0).isReg()) 34465f757f3fSDimitry Andric ? PPC::isVFRegister(MI.getOperand(0).getReg()) 34478bcb0991SDimitry Andric : false; 34488bcb0991SDimitry Andric if (!ConvertibleImmForm && !instrHasImmForm(Opc, IsVFReg, III, true)) 34490b57cec5SDimitry Andric return nullptr; 34500b57cec5SDimitry Andric 34510b57cec5SDimitry Andric // Don't convert or %X, %Y, %Y since that's just a register move. 34520b57cec5SDimitry Andric if ((Opc == PPC::OR || Opc == PPC::OR8) && 34530b57cec5SDimitry Andric MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) 34540b57cec5SDimitry Andric return nullptr; 34550b57cec5SDimitry Andric for (int i = 1, e = MI.getNumOperands(); i < e; i++) { 34560b57cec5SDimitry Andric MachineOperand &MO = MI.getOperand(i); 34570b57cec5SDimitry Andric SeenIntermediateUse = false; 34580b57cec5SDimitry Andric if (MO.isReg() && MO.isUse() && !MO.isImplicit()) { 34598bcb0991SDimitry Andric Register Reg = MI.getOperand(i).getReg(); 34608bcb0991SDimitry Andric // If we see another use of this reg between the def and the MI, 3461bdd1243dSDimitry Andric // we want to flag it so the def isn't deleted. 34628bcb0991SDimitry Andric MachineInstr *DefMI = getDefMIPostRA(Reg, MI, SeenIntermediateUse); 34638bcb0991SDimitry Andric if (DefMI) { 34640b57cec5SDimitry Andric // Is this register defined by some form of add-immediate (including 34650b57cec5SDimitry Andric // load-immediate) within this basic block? 34668bcb0991SDimitry Andric switch (DefMI->getOpcode()) { 34678bcb0991SDimitry Andric default: 34688bcb0991SDimitry Andric break; 34690b57cec5SDimitry Andric case PPC::LI: 34700b57cec5SDimitry Andric case PPC::LI8: 34710fca6ea1SDimitry Andric case PPC::ADDItocL8: 34720b57cec5SDimitry Andric case PPC::ADDI: 34730b57cec5SDimitry Andric case PPC::ADDI8: 34740b57cec5SDimitry Andric OpNoForForwarding = i; 34758bcb0991SDimitry Andric return DefMI; 34760b57cec5SDimitry Andric } 34770b57cec5SDimitry Andric } 34780b57cec5SDimitry Andric } 34790b57cec5SDimitry Andric } 34800b57cec5SDimitry Andric } 34810b57cec5SDimitry Andric return OpNoForForwarding == ~0U ? nullptr : DefMI; 34820b57cec5SDimitry Andric } 34830b57cec5SDimitry Andric 34845ffd83dbSDimitry Andric unsigned PPCInstrInfo::getSpillTarget() const { 3485e8d8bef9SDimitry Andric // With P10, we may need to spill paired vector registers or accumulator 3486e8d8bef9SDimitry Andric // registers. MMA implies paired vectors, so we can just check that. 3487e8d8bef9SDimitry Andric bool IsP10Variant = Subtarget.isISA3_1() || Subtarget.pairedVectorMemops(); 3488*36b606aeSDimitry Andric // P11 uses the P10 target. 3489bdd1243dSDimitry Andric return Subtarget.isISAFuture() ? 3 : IsP10Variant ? 3490bdd1243dSDimitry Andric 2 : Subtarget.hasP9Vector() ? 3491bdd1243dSDimitry Andric 1 : 0; 34925ffd83dbSDimitry Andric } 34930b57cec5SDimitry Andric 3494bdd1243dSDimitry Andric ArrayRef<unsigned> PPCInstrInfo::getStoreOpcodesForSpillArray() const { 3495bdd1243dSDimitry Andric return {StoreSpillOpcodesArray[getSpillTarget()], SOK_LastOpcodeSpill}; 34960b57cec5SDimitry Andric } 34970b57cec5SDimitry Andric 3498bdd1243dSDimitry Andric ArrayRef<unsigned> PPCInstrInfo::getLoadOpcodesForSpillArray() const { 3499bdd1243dSDimitry Andric return {LoadSpillOpcodesArray[getSpillTarget()], SOK_LastOpcodeSpill}; 35000b57cec5SDimitry Andric } 35010b57cec5SDimitry Andric 3502480093f4SDimitry Andric // This opt tries to convert the following imm form to an index form to save an 3503480093f4SDimitry Andric // add for stack variables. 3504480093f4SDimitry Andric // Return false if no such pattern found. 3505480093f4SDimitry Andric // 3506480093f4SDimitry Andric // ADDI instr: ToBeChangedReg = ADDI FrameBaseReg, OffsetAddi 3507480093f4SDimitry Andric // ADD instr: ToBeDeletedReg = ADD ToBeChangedReg(killed), ScaleReg 3508480093f4SDimitry Andric // Imm instr: Reg = op OffsetImm, ToBeDeletedReg(killed) 3509480093f4SDimitry Andric // 3510480093f4SDimitry Andric // can be converted to: 3511480093f4SDimitry Andric // 3512480093f4SDimitry Andric // new ADDI instr: ToBeChangedReg = ADDI FrameBaseReg, (OffsetAddi + OffsetImm) 3513480093f4SDimitry Andric // Index instr: Reg = opx ScaleReg, ToBeChangedReg(killed) 3514480093f4SDimitry Andric // 3515480093f4SDimitry Andric // In order to eliminate ADD instr, make sure that: 3516480093f4SDimitry Andric // 1: (OffsetAddi + OffsetImm) must be int16 since this offset will be used in 3517480093f4SDimitry Andric // new ADDI instr and ADDI can only take int16 Imm. 3518480093f4SDimitry Andric // 2: ToBeChangedReg must be killed in ADD instr and there is no other use 3519480093f4SDimitry Andric // between ADDI and ADD instr since its original def in ADDI will be changed 3520480093f4SDimitry Andric // in new ADDI instr. And also there should be no new def for it between 3521480093f4SDimitry Andric // ADD and Imm instr as ToBeChangedReg will be used in Index instr. 3522480093f4SDimitry Andric // 3: ToBeDeletedReg must be killed in Imm instr and there is no other use 3523480093f4SDimitry Andric // between ADD and Imm instr since ADD instr will be eliminated. 3524480093f4SDimitry Andric // 4: ScaleReg must not be redefined between ADD and Imm instr since it will be 3525480093f4SDimitry Andric // moved to Index instr. 3526480093f4SDimitry Andric bool PPCInstrInfo::foldFrameOffset(MachineInstr &MI) const { 3527480093f4SDimitry Andric MachineFunction *MF = MI.getParent()->getParent(); 3528480093f4SDimitry Andric MachineRegisterInfo *MRI = &MF->getRegInfo(); 3529480093f4SDimitry Andric bool PostRA = !MRI->isSSA(); 3530480093f4SDimitry Andric // Do this opt after PEI which is after RA. The reason is stack slot expansion 3531480093f4SDimitry Andric // in PEI may expose such opportunities since in PEI, stack slot offsets to 3532480093f4SDimitry Andric // frame base(OffsetAddi) are determined. 3533480093f4SDimitry Andric if (!PostRA) 3534480093f4SDimitry Andric return false; 3535480093f4SDimitry Andric unsigned ToBeDeletedReg = 0; 3536480093f4SDimitry Andric int64_t OffsetImm = 0; 3537480093f4SDimitry Andric unsigned XFormOpcode = 0; 3538480093f4SDimitry Andric ImmInstrInfo III; 3539480093f4SDimitry Andric 3540480093f4SDimitry Andric // Check if Imm instr meets requirement. 3541480093f4SDimitry Andric if (!isImmInstrEligibleForFolding(MI, ToBeDeletedReg, XFormOpcode, OffsetImm, 3542480093f4SDimitry Andric III)) 3543480093f4SDimitry Andric return false; 3544480093f4SDimitry Andric 3545480093f4SDimitry Andric bool OtherIntermediateUse = false; 3546480093f4SDimitry Andric MachineInstr *ADDMI = getDefMIPostRA(ToBeDeletedReg, MI, OtherIntermediateUse); 3547480093f4SDimitry Andric 3548480093f4SDimitry Andric // Exit if there is other use between ADD and Imm instr or no def found. 3549480093f4SDimitry Andric if (OtherIntermediateUse || !ADDMI) 3550480093f4SDimitry Andric return false; 3551480093f4SDimitry Andric 3552480093f4SDimitry Andric // Check if ADD instr meets requirement. 3553480093f4SDimitry Andric if (!isADDInstrEligibleForFolding(*ADDMI)) 3554480093f4SDimitry Andric return false; 3555480093f4SDimitry Andric 3556480093f4SDimitry Andric unsigned ScaleRegIdx = 0; 3557480093f4SDimitry Andric int64_t OffsetAddi = 0; 3558480093f4SDimitry Andric MachineInstr *ADDIMI = nullptr; 3559480093f4SDimitry Andric 3560480093f4SDimitry Andric // Check if there is a valid ToBeChangedReg in ADDMI. 3561480093f4SDimitry Andric // 1: It must be killed. 3562480093f4SDimitry Andric // 2: Its definition must be a valid ADDIMI. 3563480093f4SDimitry Andric // 3: It must satify int16 offset requirement. 3564480093f4SDimitry Andric if (isValidToBeChangedReg(ADDMI, 1, ADDIMI, OffsetAddi, OffsetImm)) 3565480093f4SDimitry Andric ScaleRegIdx = 2; 3566480093f4SDimitry Andric else if (isValidToBeChangedReg(ADDMI, 2, ADDIMI, OffsetAddi, OffsetImm)) 3567480093f4SDimitry Andric ScaleRegIdx = 1; 3568480093f4SDimitry Andric else 3569480093f4SDimitry Andric return false; 3570480093f4SDimitry Andric 3571480093f4SDimitry Andric assert(ADDIMI && "There should be ADDIMI for valid ToBeChangedReg."); 357204eeddc0SDimitry Andric Register ToBeChangedReg = ADDIMI->getOperand(0).getReg(); 357304eeddc0SDimitry Andric Register ScaleReg = ADDMI->getOperand(ScaleRegIdx).getReg(); 3574480093f4SDimitry Andric auto NewDefFor = [&](unsigned Reg, MachineBasicBlock::iterator Start, 3575480093f4SDimitry Andric MachineBasicBlock::iterator End) { 3576480093f4SDimitry Andric for (auto It = ++Start; It != End; It++) 3577480093f4SDimitry Andric if (It->modifiesRegister(Reg, &getRegisterInfo())) 3578480093f4SDimitry Andric return true; 3579480093f4SDimitry Andric return false; 3580480093f4SDimitry Andric }; 35815ffd83dbSDimitry Andric 35825ffd83dbSDimitry Andric // We are trying to replace the ImmOpNo with ScaleReg. Give up if it is 35835ffd83dbSDimitry Andric // treated as special zero when ScaleReg is R0/X0 register. 35845ffd83dbSDimitry Andric if (III.ZeroIsSpecialOrig == III.ImmOpNo && 35855ffd83dbSDimitry Andric (ScaleReg == PPC::R0 || ScaleReg == PPC::X0)) 35865ffd83dbSDimitry Andric return false; 35875ffd83dbSDimitry Andric 3588480093f4SDimitry Andric // Make sure no other def for ToBeChangedReg and ScaleReg between ADD Instr 3589480093f4SDimitry Andric // and Imm Instr. 3590480093f4SDimitry Andric if (NewDefFor(ToBeChangedReg, *ADDMI, MI) || NewDefFor(ScaleReg, *ADDMI, MI)) 3591480093f4SDimitry Andric return false; 3592480093f4SDimitry Andric 3593480093f4SDimitry Andric // Now start to do the transformation. 3594480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "Replace instruction: " 3595480093f4SDimitry Andric << "\n"); 3596480093f4SDimitry Andric LLVM_DEBUG(ADDIMI->dump()); 3597480093f4SDimitry Andric LLVM_DEBUG(ADDMI->dump()); 3598480093f4SDimitry Andric LLVM_DEBUG(MI.dump()); 3599480093f4SDimitry Andric LLVM_DEBUG(dbgs() << "with: " 3600480093f4SDimitry Andric << "\n"); 3601480093f4SDimitry Andric 3602480093f4SDimitry Andric // Update ADDI instr. 3603480093f4SDimitry Andric ADDIMI->getOperand(2).setImm(OffsetAddi + OffsetImm); 3604480093f4SDimitry Andric 3605480093f4SDimitry Andric // Update Imm instr. 3606480093f4SDimitry Andric MI.setDesc(get(XFormOpcode)); 3607480093f4SDimitry Andric MI.getOperand(III.ImmOpNo) 3608480093f4SDimitry Andric .ChangeToRegister(ScaleReg, false, false, 3609480093f4SDimitry Andric ADDMI->getOperand(ScaleRegIdx).isKill()); 3610480093f4SDimitry Andric 3611480093f4SDimitry Andric MI.getOperand(III.OpNoForForwarding) 3612480093f4SDimitry Andric .ChangeToRegister(ToBeChangedReg, false, false, true); 3613480093f4SDimitry Andric 3614480093f4SDimitry Andric // Eliminate ADD instr. 3615480093f4SDimitry Andric ADDMI->eraseFromParent(); 3616480093f4SDimitry Andric 3617480093f4SDimitry Andric LLVM_DEBUG(ADDIMI->dump()); 3618480093f4SDimitry Andric LLVM_DEBUG(MI.dump()); 3619480093f4SDimitry Andric 3620480093f4SDimitry Andric return true; 3621480093f4SDimitry Andric } 3622480093f4SDimitry Andric 3623480093f4SDimitry Andric bool PPCInstrInfo::isADDIInstrEligibleForFolding(MachineInstr &ADDIMI, 3624480093f4SDimitry Andric int64_t &Imm) const { 3625480093f4SDimitry Andric unsigned Opc = ADDIMI.getOpcode(); 3626480093f4SDimitry Andric 3627480093f4SDimitry Andric // Exit if the instruction is not ADDI. 3628480093f4SDimitry Andric if (Opc != PPC::ADDI && Opc != PPC::ADDI8) 3629480093f4SDimitry Andric return false; 3630480093f4SDimitry Andric 36310946e70aSDimitry Andric // The operand may not necessarily be an immediate - it could be a relocation. 36320946e70aSDimitry Andric if (!ADDIMI.getOperand(2).isImm()) 36330946e70aSDimitry Andric return false; 36340946e70aSDimitry Andric 3635480093f4SDimitry Andric Imm = ADDIMI.getOperand(2).getImm(); 3636480093f4SDimitry Andric 3637480093f4SDimitry Andric return true; 3638480093f4SDimitry Andric } 3639480093f4SDimitry Andric 3640480093f4SDimitry Andric bool PPCInstrInfo::isADDInstrEligibleForFolding(MachineInstr &ADDMI) const { 3641480093f4SDimitry Andric unsigned Opc = ADDMI.getOpcode(); 3642480093f4SDimitry Andric 3643480093f4SDimitry Andric // Exit if the instruction is not ADD. 3644480093f4SDimitry Andric return Opc == PPC::ADD4 || Opc == PPC::ADD8; 3645480093f4SDimitry Andric } 3646480093f4SDimitry Andric 3647480093f4SDimitry Andric bool PPCInstrInfo::isImmInstrEligibleForFolding(MachineInstr &MI, 3648480093f4SDimitry Andric unsigned &ToBeDeletedReg, 3649480093f4SDimitry Andric unsigned &XFormOpcode, 3650480093f4SDimitry Andric int64_t &OffsetImm, 3651480093f4SDimitry Andric ImmInstrInfo &III) const { 3652480093f4SDimitry Andric // Only handle load/store. 3653480093f4SDimitry Andric if (!MI.mayLoadOrStore()) 3654480093f4SDimitry Andric return false; 3655480093f4SDimitry Andric 3656480093f4SDimitry Andric unsigned Opc = MI.getOpcode(); 3657480093f4SDimitry Andric 3658480093f4SDimitry Andric XFormOpcode = RI.getMappedIdxOpcForImmOpc(Opc); 3659480093f4SDimitry Andric 3660480093f4SDimitry Andric // Exit if instruction has no index form. 3661480093f4SDimitry Andric if (XFormOpcode == PPC::INSTRUCTION_LIST_END) 3662480093f4SDimitry Andric return false; 3663480093f4SDimitry Andric 3664480093f4SDimitry Andric // TODO: sync the logic between instrHasImmForm() and ImmToIdxMap. 36655f757f3fSDimitry Andric if (!instrHasImmForm(XFormOpcode, 36665f757f3fSDimitry Andric PPC::isVFRegister(MI.getOperand(0).getReg()), III, true)) 3667480093f4SDimitry Andric return false; 3668480093f4SDimitry Andric 3669480093f4SDimitry Andric if (!III.IsSummingOperands) 3670480093f4SDimitry Andric return false; 3671480093f4SDimitry Andric 3672480093f4SDimitry Andric MachineOperand ImmOperand = MI.getOperand(III.ImmOpNo); 3673480093f4SDimitry Andric MachineOperand RegOperand = MI.getOperand(III.OpNoForForwarding); 3674480093f4SDimitry Andric // Only support imm operands, not relocation slots or others. 3675480093f4SDimitry Andric if (!ImmOperand.isImm()) 3676480093f4SDimitry Andric return false; 3677480093f4SDimitry Andric 3678480093f4SDimitry Andric assert(RegOperand.isReg() && "Instruction format is not right"); 3679480093f4SDimitry Andric 3680480093f4SDimitry Andric // There are other use for ToBeDeletedReg after Imm instr, can not delete it. 3681480093f4SDimitry Andric if (!RegOperand.isKill()) 3682480093f4SDimitry Andric return false; 3683480093f4SDimitry Andric 3684480093f4SDimitry Andric ToBeDeletedReg = RegOperand.getReg(); 3685480093f4SDimitry Andric OffsetImm = ImmOperand.getImm(); 3686480093f4SDimitry Andric 3687480093f4SDimitry Andric return true; 3688480093f4SDimitry Andric } 3689480093f4SDimitry Andric 3690480093f4SDimitry Andric bool PPCInstrInfo::isValidToBeChangedReg(MachineInstr *ADDMI, unsigned Index, 3691480093f4SDimitry Andric MachineInstr *&ADDIMI, 3692480093f4SDimitry Andric int64_t &OffsetAddi, 3693480093f4SDimitry Andric int64_t OffsetImm) const { 3694480093f4SDimitry Andric assert((Index == 1 || Index == 2) && "Invalid operand index for add."); 3695480093f4SDimitry Andric MachineOperand &MO = ADDMI->getOperand(Index); 3696480093f4SDimitry Andric 3697480093f4SDimitry Andric if (!MO.isKill()) 3698480093f4SDimitry Andric return false; 3699480093f4SDimitry Andric 3700480093f4SDimitry Andric bool OtherIntermediateUse = false; 3701480093f4SDimitry Andric 3702480093f4SDimitry Andric ADDIMI = getDefMIPostRA(MO.getReg(), *ADDMI, OtherIntermediateUse); 3703480093f4SDimitry Andric // Currently handle only one "add + Imminstr" pair case, exit if other 3704480093f4SDimitry Andric // intermediate use for ToBeChangedReg found. 3705480093f4SDimitry Andric // TODO: handle the cases where there are other "add + Imminstr" pairs 3706480093f4SDimitry Andric // with same offset in Imminstr which is like: 3707480093f4SDimitry Andric // 3708480093f4SDimitry Andric // ADDI instr: ToBeChangedReg = ADDI FrameBaseReg, OffsetAddi 3709480093f4SDimitry Andric // ADD instr1: ToBeDeletedReg1 = ADD ToBeChangedReg, ScaleReg1 3710480093f4SDimitry Andric // Imm instr1: Reg1 = op1 OffsetImm, ToBeDeletedReg1(killed) 3711480093f4SDimitry Andric // ADD instr2: ToBeDeletedReg2 = ADD ToBeChangedReg(killed), ScaleReg2 3712480093f4SDimitry Andric // Imm instr2: Reg2 = op2 OffsetImm, ToBeDeletedReg2(killed) 3713480093f4SDimitry Andric // 3714480093f4SDimitry Andric // can be converted to: 3715480093f4SDimitry Andric // 3716480093f4SDimitry Andric // new ADDI instr: ToBeChangedReg = ADDI FrameBaseReg, 3717480093f4SDimitry Andric // (OffsetAddi + OffsetImm) 3718480093f4SDimitry Andric // Index instr1: Reg1 = opx1 ScaleReg1, ToBeChangedReg 3719480093f4SDimitry Andric // Index instr2: Reg2 = opx2 ScaleReg2, ToBeChangedReg(killed) 3720480093f4SDimitry Andric 3721480093f4SDimitry Andric if (OtherIntermediateUse || !ADDIMI) 3722480093f4SDimitry Andric return false; 3723480093f4SDimitry Andric // Check if ADDI instr meets requirement. 3724480093f4SDimitry Andric if (!isADDIInstrEligibleForFolding(*ADDIMI, OffsetAddi)) 3725480093f4SDimitry Andric return false; 3726480093f4SDimitry Andric 3727480093f4SDimitry Andric if (isInt<16>(OffsetAddi + OffsetImm)) 3728480093f4SDimitry Andric return true; 3729480093f4SDimitry Andric return false; 3730480093f4SDimitry Andric } 3731480093f4SDimitry Andric 37320b57cec5SDimitry Andric // If this instruction has an immediate form and one of its operands is a 37330b57cec5SDimitry Andric // result of a load-immediate or an add-immediate, convert it to 37340b57cec5SDimitry Andric // the immediate form if the constant is in range. 37350b57cec5SDimitry Andric bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI, 37365f757f3fSDimitry Andric SmallSet<Register, 4> &RegsToUpdate, 37370b57cec5SDimitry Andric MachineInstr **KilledDef) const { 37380b57cec5SDimitry Andric MachineFunction *MF = MI.getParent()->getParent(); 37390b57cec5SDimitry Andric MachineRegisterInfo *MRI = &MF->getRegInfo(); 37400b57cec5SDimitry Andric bool PostRA = !MRI->isSSA(); 37410b57cec5SDimitry Andric bool SeenIntermediateUse = true; 37420b57cec5SDimitry Andric unsigned ForwardingOperand = ~0U; 37430b57cec5SDimitry Andric MachineInstr *DefMI = getForwardingDefMI(MI, ForwardingOperand, 37440b57cec5SDimitry Andric SeenIntermediateUse); 37450b57cec5SDimitry Andric if (!DefMI) 37460b57cec5SDimitry Andric return false; 37470b57cec5SDimitry Andric assert(ForwardingOperand < MI.getNumOperands() && 37480b57cec5SDimitry Andric "The forwarding operand needs to be valid at this point"); 37490b57cec5SDimitry Andric bool IsForwardingOperandKilled = MI.getOperand(ForwardingOperand).isKill(); 37500b57cec5SDimitry Andric bool KillFwdDefMI = !SeenIntermediateUse && IsForwardingOperandKilled; 37510b57cec5SDimitry Andric if (KilledDef && KillFwdDefMI) 37520b57cec5SDimitry Andric *KilledDef = DefMI; 37530b57cec5SDimitry Andric 37545f757f3fSDimitry Andric // Conservatively add defs from DefMI and defs/uses from MI to the set of 37555f757f3fSDimitry Andric // registers that need their kill flags updated. 37565f757f3fSDimitry Andric for (const MachineOperand &MO : DefMI->operands()) 37575f757f3fSDimitry Andric if (MO.isReg() && MO.isDef()) 37585f757f3fSDimitry Andric RegsToUpdate.insert(MO.getReg()); 37595f757f3fSDimitry Andric for (const MachineOperand &MO : MI.operands()) 37605f757f3fSDimitry Andric if (MO.isReg()) 37615f757f3fSDimitry Andric RegsToUpdate.insert(MO.getReg()); 37625f757f3fSDimitry Andric 37635ffd83dbSDimitry Andric // If this is a imm instruction and its register operands is produced by ADDI, 37645ffd83dbSDimitry Andric // put the imm into imm inst directly. 37655ffd83dbSDimitry Andric if (RI.getMappedIdxOpcForImmOpc(MI.getOpcode()) != 37665ffd83dbSDimitry Andric PPC::INSTRUCTION_LIST_END && 37675ffd83dbSDimitry Andric transformToNewImmFormFedByAdd(MI, *DefMI, ForwardingOperand)) 37685ffd83dbSDimitry Andric return true; 37695ffd83dbSDimitry Andric 37700b57cec5SDimitry Andric ImmInstrInfo III; 37718bcb0991SDimitry Andric bool IsVFReg = MI.getOperand(0).isReg() 37725f757f3fSDimitry Andric ? PPC::isVFRegister(MI.getOperand(0).getReg()) 37738bcb0991SDimitry Andric : false; 37748bcb0991SDimitry Andric bool HasImmForm = instrHasImmForm(MI.getOpcode(), IsVFReg, III, PostRA); 37750b57cec5SDimitry Andric // If this is a reg+reg instruction that has a reg+imm form, 37760b57cec5SDimitry Andric // and one of the operands is produced by an add-immediate, 37770b57cec5SDimitry Andric // try to convert it. 37780b57cec5SDimitry Andric if (HasImmForm && 37790b57cec5SDimitry Andric transformToImmFormFedByAdd(MI, III, ForwardingOperand, *DefMI, 37800b57cec5SDimitry Andric KillFwdDefMI)) 37810b57cec5SDimitry Andric return true; 37820b57cec5SDimitry Andric 37830b57cec5SDimitry Andric // If this is a reg+reg instruction that has a reg+imm form, 37840b57cec5SDimitry Andric // and one of the operands is produced by LI, convert it now. 37855ffd83dbSDimitry Andric if (HasImmForm && 37865ffd83dbSDimitry Andric transformToImmFormFedByLI(MI, III, ForwardingOperand, *DefMI)) 37870b57cec5SDimitry Andric return true; 37880b57cec5SDimitry Andric 37895ffd83dbSDimitry Andric // If this is not a reg+reg, but the DefMI is LI/LI8, check if its user MI 37905ffd83dbSDimitry Andric // can be simpified to LI. 37915ffd83dbSDimitry Andric if (!HasImmForm && simplifyToLI(MI, *DefMI, ForwardingOperand, KilledDef)) 37920b57cec5SDimitry Andric return true; 37935ffd83dbSDimitry Andric 37940b57cec5SDimitry Andric return false; 37950b57cec5SDimitry Andric } 37960b57cec5SDimitry Andric 3797e8d8bef9SDimitry Andric bool PPCInstrInfo::combineRLWINM(MachineInstr &MI, 3798e8d8bef9SDimitry Andric MachineInstr **ToErase) const { 3799e8d8bef9SDimitry Andric MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo(); 380004eeddc0SDimitry Andric Register FoldingReg = MI.getOperand(1).getReg(); 3801bdd1243dSDimitry Andric if (!FoldingReg.isVirtual()) 3802e8d8bef9SDimitry Andric return false; 3803e8d8bef9SDimitry Andric MachineInstr *SrcMI = MRI->getVRegDef(FoldingReg); 3804e8d8bef9SDimitry Andric if (SrcMI->getOpcode() != PPC::RLWINM && 3805e8d8bef9SDimitry Andric SrcMI->getOpcode() != PPC::RLWINM_rec && 3806e8d8bef9SDimitry Andric SrcMI->getOpcode() != PPC::RLWINM8 && 3807e8d8bef9SDimitry Andric SrcMI->getOpcode() != PPC::RLWINM8_rec) 3808e8d8bef9SDimitry Andric return false; 3809e8d8bef9SDimitry Andric assert((MI.getOperand(2).isImm() && MI.getOperand(3).isImm() && 3810e8d8bef9SDimitry Andric MI.getOperand(4).isImm() && SrcMI->getOperand(2).isImm() && 3811e8d8bef9SDimitry Andric SrcMI->getOperand(3).isImm() && SrcMI->getOperand(4).isImm()) && 3812e8d8bef9SDimitry Andric "Invalid PPC::RLWINM Instruction!"); 3813e8d8bef9SDimitry Andric uint64_t SHSrc = SrcMI->getOperand(2).getImm(); 3814e8d8bef9SDimitry Andric uint64_t SHMI = MI.getOperand(2).getImm(); 3815e8d8bef9SDimitry Andric uint64_t MBSrc = SrcMI->getOperand(3).getImm(); 3816e8d8bef9SDimitry Andric uint64_t MBMI = MI.getOperand(3).getImm(); 3817e8d8bef9SDimitry Andric uint64_t MESrc = SrcMI->getOperand(4).getImm(); 3818e8d8bef9SDimitry Andric uint64_t MEMI = MI.getOperand(4).getImm(); 3819e8d8bef9SDimitry Andric 3820e8d8bef9SDimitry Andric assert((MEMI < 32 && MESrc < 32 && MBMI < 32 && MBSrc < 32) && 3821e8d8bef9SDimitry Andric "Invalid PPC::RLWINM Instruction!"); 3822e8d8bef9SDimitry Andric // If MBMI is bigger than MEMI, we always can not get run of ones. 3823e8d8bef9SDimitry Andric // RotatedSrcMask non-wrap: 3824e8d8bef9SDimitry Andric // 0........31|32........63 3825e8d8bef9SDimitry Andric // RotatedSrcMask: B---E B---E 3826e8d8bef9SDimitry Andric // MaskMI: -----------|--E B------ 3827e8d8bef9SDimitry Andric // Result: ----- --- (Bad candidate) 3828e8d8bef9SDimitry Andric // 3829e8d8bef9SDimitry Andric // RotatedSrcMask wrap: 3830e8d8bef9SDimitry Andric // 0........31|32........63 3831e8d8bef9SDimitry Andric // RotatedSrcMask: --E B----|--E B---- 3832e8d8bef9SDimitry Andric // MaskMI: -----------|--E B------ 3833e8d8bef9SDimitry Andric // Result: --- -----|--- ----- (Bad candidate) 3834e8d8bef9SDimitry Andric // 3835e8d8bef9SDimitry Andric // One special case is RotatedSrcMask is a full set mask. 3836e8d8bef9SDimitry Andric // RotatedSrcMask full: 3837e8d8bef9SDimitry Andric // 0........31|32........63 3838e8d8bef9SDimitry Andric // RotatedSrcMask: ------EB---|-------EB--- 3839e8d8bef9SDimitry Andric // MaskMI: -----------|--E B------ 3840e8d8bef9SDimitry Andric // Result: -----------|--- ------- (Good candidate) 3841e8d8bef9SDimitry Andric 3842e8d8bef9SDimitry Andric // Mark special case. 3843e8d8bef9SDimitry Andric bool SrcMaskFull = (MBSrc - MESrc == 1) || (MBSrc == 0 && MESrc == 31); 3844e8d8bef9SDimitry Andric 3845e8d8bef9SDimitry Andric // For other MBMI > MEMI cases, just return. 3846e8d8bef9SDimitry Andric if ((MBMI > MEMI) && !SrcMaskFull) 3847e8d8bef9SDimitry Andric return false; 3848e8d8bef9SDimitry Andric 3849e8d8bef9SDimitry Andric // Handle MBMI <= MEMI cases. 3850e8d8bef9SDimitry Andric APInt MaskMI = APInt::getBitsSetWithWrap(32, 32 - MEMI - 1, 32 - MBMI); 3851e8d8bef9SDimitry Andric // In MI, we only need low 32 bits of SrcMI, just consider about low 32 3852e8d8bef9SDimitry Andric // bit of SrcMI mask. Note that in APInt, lowerest bit is at index 0, 3853e8d8bef9SDimitry Andric // while in PowerPC ISA, lowerest bit is at index 63. 3854e8d8bef9SDimitry Andric APInt MaskSrc = APInt::getBitsSetWithWrap(32, 32 - MESrc - 1, 32 - MBSrc); 3855e8d8bef9SDimitry Andric 3856e8d8bef9SDimitry Andric APInt RotatedSrcMask = MaskSrc.rotl(SHMI); 3857e8d8bef9SDimitry Andric APInt FinalMask = RotatedSrcMask & MaskMI; 3858e8d8bef9SDimitry Andric uint32_t NewMB, NewME; 3859e8d8bef9SDimitry Andric bool Simplified = false; 3860e8d8bef9SDimitry Andric 3861e8d8bef9SDimitry Andric // If final mask is 0, MI result should be 0 too. 3862349cc55cSDimitry Andric if (FinalMask.isZero()) { 3863e8d8bef9SDimitry Andric bool Is64Bit = 3864e8d8bef9SDimitry Andric (MI.getOpcode() == PPC::RLWINM8 || MI.getOpcode() == PPC::RLWINM8_rec); 3865e8d8bef9SDimitry Andric Simplified = true; 3866e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "Replace Instr: "); 3867e8d8bef9SDimitry Andric LLVM_DEBUG(MI.dump()); 3868e8d8bef9SDimitry Andric 3869e8d8bef9SDimitry Andric if (MI.getOpcode() == PPC::RLWINM || MI.getOpcode() == PPC::RLWINM8) { 3870e8d8bef9SDimitry Andric // Replace MI with "LI 0" 387181ad6265SDimitry Andric MI.removeOperand(4); 387281ad6265SDimitry Andric MI.removeOperand(3); 387381ad6265SDimitry Andric MI.removeOperand(2); 3874e8d8bef9SDimitry Andric MI.getOperand(1).ChangeToImmediate(0); 3875e8d8bef9SDimitry Andric MI.setDesc(get(Is64Bit ? PPC::LI8 : PPC::LI)); 3876e8d8bef9SDimitry Andric } else { 3877e8d8bef9SDimitry Andric // Replace MI with "ANDI_rec reg, 0" 387881ad6265SDimitry Andric MI.removeOperand(4); 387981ad6265SDimitry Andric MI.removeOperand(3); 3880e8d8bef9SDimitry Andric MI.getOperand(2).setImm(0); 3881e8d8bef9SDimitry Andric MI.setDesc(get(Is64Bit ? PPC::ANDI8_rec : PPC::ANDI_rec)); 3882e8d8bef9SDimitry Andric MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); 3883e8d8bef9SDimitry Andric if (SrcMI->getOperand(1).isKill()) { 3884e8d8bef9SDimitry Andric MI.getOperand(1).setIsKill(true); 3885e8d8bef9SDimitry Andric SrcMI->getOperand(1).setIsKill(false); 3886e8d8bef9SDimitry Andric } else 3887e8d8bef9SDimitry Andric // About to replace MI.getOperand(1), clear its kill flag. 3888e8d8bef9SDimitry Andric MI.getOperand(1).setIsKill(false); 3889e8d8bef9SDimitry Andric } 3890e8d8bef9SDimitry Andric 3891e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "With: "); 3892e8d8bef9SDimitry Andric LLVM_DEBUG(MI.dump()); 3893e8d8bef9SDimitry Andric 3894e8d8bef9SDimitry Andric } else if ((isRunOfOnes((unsigned)(FinalMask.getZExtValue()), NewMB, NewME) && 3895e8d8bef9SDimitry Andric NewMB <= NewME) || 3896e8d8bef9SDimitry Andric SrcMaskFull) { 3897e8d8bef9SDimitry Andric // Here we only handle MBMI <= MEMI case, so NewMB must be no bigger 3898e8d8bef9SDimitry Andric // than NewME. Otherwise we get a 64 bit value after folding, but MI 3899e8d8bef9SDimitry Andric // return a 32 bit value. 3900e8d8bef9SDimitry Andric Simplified = true; 3901e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "Converting Instr: "); 3902e8d8bef9SDimitry Andric LLVM_DEBUG(MI.dump()); 3903e8d8bef9SDimitry Andric 3904e8d8bef9SDimitry Andric uint16_t NewSH = (SHSrc + SHMI) % 32; 3905e8d8bef9SDimitry Andric MI.getOperand(2).setImm(NewSH); 3906e8d8bef9SDimitry Andric // If SrcMI mask is full, no need to update MBMI and MEMI. 3907e8d8bef9SDimitry Andric if (!SrcMaskFull) { 3908e8d8bef9SDimitry Andric MI.getOperand(3).setImm(NewMB); 3909e8d8bef9SDimitry Andric MI.getOperand(4).setImm(NewME); 3910e8d8bef9SDimitry Andric } 3911e8d8bef9SDimitry Andric MI.getOperand(1).setReg(SrcMI->getOperand(1).getReg()); 3912e8d8bef9SDimitry Andric if (SrcMI->getOperand(1).isKill()) { 3913e8d8bef9SDimitry Andric MI.getOperand(1).setIsKill(true); 3914e8d8bef9SDimitry Andric SrcMI->getOperand(1).setIsKill(false); 3915e8d8bef9SDimitry Andric } else 3916e8d8bef9SDimitry Andric // About to replace MI.getOperand(1), clear its kill flag. 3917e8d8bef9SDimitry Andric MI.getOperand(1).setIsKill(false); 3918e8d8bef9SDimitry Andric 3919e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "To: "); 3920e8d8bef9SDimitry Andric LLVM_DEBUG(MI.dump()); 3921e8d8bef9SDimitry Andric } 3922e8d8bef9SDimitry Andric if (Simplified & MRI->use_nodbg_empty(FoldingReg) && 3923e8d8bef9SDimitry Andric !SrcMI->hasImplicitDef()) { 3924e8d8bef9SDimitry Andric // If FoldingReg has no non-debug use and it has no implicit def (it 3925e8d8bef9SDimitry Andric // is not RLWINMO or RLWINM8o), it's safe to delete its def SrcMI. 3926e8d8bef9SDimitry Andric // Otherwise keep it. 3927e8d8bef9SDimitry Andric *ToErase = SrcMI; 3928e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "Delete dead instruction: "); 3929e8d8bef9SDimitry Andric LLVM_DEBUG(SrcMI->dump()); 3930e8d8bef9SDimitry Andric } 3931e8d8bef9SDimitry Andric return Simplified; 3932e8d8bef9SDimitry Andric } 3933e8d8bef9SDimitry Andric 39348bcb0991SDimitry Andric bool PPCInstrInfo::instrHasImmForm(unsigned Opc, bool IsVFReg, 39350b57cec5SDimitry Andric ImmInstrInfo &III, bool PostRA) const { 39360b57cec5SDimitry Andric // The vast majority of the instructions would need their operand 2 replaced 39370b57cec5SDimitry Andric // with an immediate when switching to the reg+imm form. A marked exception 39380b57cec5SDimitry Andric // are the update form loads/stores for which a constant operand 2 would need 39390b57cec5SDimitry Andric // to turn into a displacement and move operand 1 to the operand 2 position. 39400b57cec5SDimitry Andric III.ImmOpNo = 2; 39410b57cec5SDimitry Andric III.OpNoForForwarding = 2; 39420b57cec5SDimitry Andric III.ImmWidth = 16; 39430b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 1; 39440b57cec5SDimitry Andric III.TruncateImmTo = 0; 39450b57cec5SDimitry Andric III.IsSummingOperands = false; 39460b57cec5SDimitry Andric switch (Opc) { 39470b57cec5SDimitry Andric default: return false; 39480b57cec5SDimitry Andric case PPC::ADD4: 39490b57cec5SDimitry Andric case PPC::ADD8: 39500b57cec5SDimitry Andric III.SignedImm = true; 39510b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 39520b57cec5SDimitry Andric III.ZeroIsSpecialNew = 1; 39530b57cec5SDimitry Andric III.IsCommutative = true; 39540b57cec5SDimitry Andric III.IsSummingOperands = true; 39550b57cec5SDimitry Andric III.ImmOpcode = Opc == PPC::ADD4 ? PPC::ADDI : PPC::ADDI8; 39560b57cec5SDimitry Andric break; 39570b57cec5SDimitry Andric case PPC::ADDC: 39580b57cec5SDimitry Andric case PPC::ADDC8: 39590b57cec5SDimitry Andric III.SignedImm = true; 39600b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 39610b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 39620b57cec5SDimitry Andric III.IsCommutative = true; 39630b57cec5SDimitry Andric III.IsSummingOperands = true; 39640b57cec5SDimitry Andric III.ImmOpcode = Opc == PPC::ADDC ? PPC::ADDIC : PPC::ADDIC8; 39650b57cec5SDimitry Andric break; 3966480093f4SDimitry Andric case PPC::ADDC_rec: 39670b57cec5SDimitry Andric III.SignedImm = true; 39680b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 39690b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 39700b57cec5SDimitry Andric III.IsCommutative = true; 39710b57cec5SDimitry Andric III.IsSummingOperands = true; 3972480093f4SDimitry Andric III.ImmOpcode = PPC::ADDIC_rec; 39730b57cec5SDimitry Andric break; 39740b57cec5SDimitry Andric case PPC::SUBFC: 39750b57cec5SDimitry Andric case PPC::SUBFC8: 39760b57cec5SDimitry Andric III.SignedImm = true; 39770b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 39780b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 39790b57cec5SDimitry Andric III.IsCommutative = false; 39800b57cec5SDimitry Andric III.ImmOpcode = Opc == PPC::SUBFC ? PPC::SUBFIC : PPC::SUBFIC8; 39810b57cec5SDimitry Andric break; 39820b57cec5SDimitry Andric case PPC::CMPW: 39830b57cec5SDimitry Andric case PPC::CMPD: 39840b57cec5SDimitry Andric III.SignedImm = true; 39850b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 39860b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 39870b57cec5SDimitry Andric III.IsCommutative = false; 39880b57cec5SDimitry Andric III.ImmOpcode = Opc == PPC::CMPW ? PPC::CMPWI : PPC::CMPDI; 39890b57cec5SDimitry Andric break; 39900b57cec5SDimitry Andric case PPC::CMPLW: 39910b57cec5SDimitry Andric case PPC::CMPLD: 39920b57cec5SDimitry Andric III.SignedImm = false; 39930b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 39940b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 39950b57cec5SDimitry Andric III.IsCommutative = false; 39960b57cec5SDimitry Andric III.ImmOpcode = Opc == PPC::CMPLW ? PPC::CMPLWI : PPC::CMPLDI; 39970b57cec5SDimitry Andric break; 3998480093f4SDimitry Andric case PPC::AND_rec: 3999480093f4SDimitry Andric case PPC::AND8_rec: 40000b57cec5SDimitry Andric case PPC::OR: 40010b57cec5SDimitry Andric case PPC::OR8: 40020b57cec5SDimitry Andric case PPC::XOR: 40030b57cec5SDimitry Andric case PPC::XOR8: 40040b57cec5SDimitry Andric III.SignedImm = false; 40050b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 40060b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 40070b57cec5SDimitry Andric III.IsCommutative = true; 40080b57cec5SDimitry Andric switch(Opc) { 40090b57cec5SDimitry Andric default: llvm_unreachable("Unknown opcode"); 4010480093f4SDimitry Andric case PPC::AND_rec: 4011480093f4SDimitry Andric III.ImmOpcode = PPC::ANDI_rec; 4012480093f4SDimitry Andric break; 4013480093f4SDimitry Andric case PPC::AND8_rec: 4014480093f4SDimitry Andric III.ImmOpcode = PPC::ANDI8_rec; 4015480093f4SDimitry Andric break; 40160b57cec5SDimitry Andric case PPC::OR: III.ImmOpcode = PPC::ORI; break; 40170b57cec5SDimitry Andric case PPC::OR8: III.ImmOpcode = PPC::ORI8; break; 40180b57cec5SDimitry Andric case PPC::XOR: III.ImmOpcode = PPC::XORI; break; 40190b57cec5SDimitry Andric case PPC::XOR8: III.ImmOpcode = PPC::XORI8; break; 40200b57cec5SDimitry Andric } 40210b57cec5SDimitry Andric break; 40220b57cec5SDimitry Andric case PPC::RLWNM: 40230b57cec5SDimitry Andric case PPC::RLWNM8: 4024480093f4SDimitry Andric case PPC::RLWNM_rec: 4025480093f4SDimitry Andric case PPC::RLWNM8_rec: 40260b57cec5SDimitry Andric case PPC::SLW: 40270b57cec5SDimitry Andric case PPC::SLW8: 4028480093f4SDimitry Andric case PPC::SLW_rec: 4029480093f4SDimitry Andric case PPC::SLW8_rec: 40300b57cec5SDimitry Andric case PPC::SRW: 40310b57cec5SDimitry Andric case PPC::SRW8: 4032480093f4SDimitry Andric case PPC::SRW_rec: 4033480093f4SDimitry Andric case PPC::SRW8_rec: 40340b57cec5SDimitry Andric case PPC::SRAW: 4035480093f4SDimitry Andric case PPC::SRAW_rec: 40360b57cec5SDimitry Andric III.SignedImm = false; 40370b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 40380b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 40390b57cec5SDimitry Andric III.IsCommutative = false; 40400b57cec5SDimitry Andric // This isn't actually true, but the instructions ignore any of the 40410b57cec5SDimitry Andric // upper bits, so any immediate loaded with an LI is acceptable. 40420b57cec5SDimitry Andric // This does not apply to shift right algebraic because a value 40430b57cec5SDimitry Andric // out of range will produce a -1/0. 40440b57cec5SDimitry Andric III.ImmWidth = 16; 4045480093f4SDimitry Andric if (Opc == PPC::RLWNM || Opc == PPC::RLWNM8 || Opc == PPC::RLWNM_rec || 4046480093f4SDimitry Andric Opc == PPC::RLWNM8_rec) 40470b57cec5SDimitry Andric III.TruncateImmTo = 5; 40480b57cec5SDimitry Andric else 40490b57cec5SDimitry Andric III.TruncateImmTo = 6; 40500b57cec5SDimitry Andric switch(Opc) { 40510b57cec5SDimitry Andric default: llvm_unreachable("Unknown opcode"); 40520b57cec5SDimitry Andric case PPC::RLWNM: III.ImmOpcode = PPC::RLWINM; break; 40530b57cec5SDimitry Andric case PPC::RLWNM8: III.ImmOpcode = PPC::RLWINM8; break; 4054480093f4SDimitry Andric case PPC::RLWNM_rec: 4055480093f4SDimitry Andric III.ImmOpcode = PPC::RLWINM_rec; 4056480093f4SDimitry Andric break; 4057480093f4SDimitry Andric case PPC::RLWNM8_rec: 4058480093f4SDimitry Andric III.ImmOpcode = PPC::RLWINM8_rec; 4059480093f4SDimitry Andric break; 40600b57cec5SDimitry Andric case PPC::SLW: III.ImmOpcode = PPC::RLWINM; break; 40610b57cec5SDimitry Andric case PPC::SLW8: III.ImmOpcode = PPC::RLWINM8; break; 4062480093f4SDimitry Andric case PPC::SLW_rec: 4063480093f4SDimitry Andric III.ImmOpcode = PPC::RLWINM_rec; 4064480093f4SDimitry Andric break; 4065480093f4SDimitry Andric case PPC::SLW8_rec: 4066480093f4SDimitry Andric III.ImmOpcode = PPC::RLWINM8_rec; 4067480093f4SDimitry Andric break; 40680b57cec5SDimitry Andric case PPC::SRW: III.ImmOpcode = PPC::RLWINM; break; 40690b57cec5SDimitry Andric case PPC::SRW8: III.ImmOpcode = PPC::RLWINM8; break; 4070480093f4SDimitry Andric case PPC::SRW_rec: 4071480093f4SDimitry Andric III.ImmOpcode = PPC::RLWINM_rec; 4072480093f4SDimitry Andric break; 4073480093f4SDimitry Andric case PPC::SRW8_rec: 4074480093f4SDimitry Andric III.ImmOpcode = PPC::RLWINM8_rec; 4075480093f4SDimitry Andric break; 40760b57cec5SDimitry Andric case PPC::SRAW: 40770b57cec5SDimitry Andric III.ImmWidth = 5; 40780b57cec5SDimitry Andric III.TruncateImmTo = 0; 40790b57cec5SDimitry Andric III.ImmOpcode = PPC::SRAWI; 40800b57cec5SDimitry Andric break; 4081480093f4SDimitry Andric case PPC::SRAW_rec: 40820b57cec5SDimitry Andric III.ImmWidth = 5; 40830b57cec5SDimitry Andric III.TruncateImmTo = 0; 4084480093f4SDimitry Andric III.ImmOpcode = PPC::SRAWI_rec; 40850b57cec5SDimitry Andric break; 40860b57cec5SDimitry Andric } 40870b57cec5SDimitry Andric break; 40880b57cec5SDimitry Andric case PPC::RLDCL: 4089480093f4SDimitry Andric case PPC::RLDCL_rec: 40900b57cec5SDimitry Andric case PPC::RLDCR: 4091480093f4SDimitry Andric case PPC::RLDCR_rec: 40920b57cec5SDimitry Andric case PPC::SLD: 4093480093f4SDimitry Andric case PPC::SLD_rec: 40940b57cec5SDimitry Andric case PPC::SRD: 4095480093f4SDimitry Andric case PPC::SRD_rec: 40960b57cec5SDimitry Andric case PPC::SRAD: 4097480093f4SDimitry Andric case PPC::SRAD_rec: 40980b57cec5SDimitry Andric III.SignedImm = false; 40990b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 0; 41000b57cec5SDimitry Andric III.ZeroIsSpecialNew = 0; 41010b57cec5SDimitry Andric III.IsCommutative = false; 41020b57cec5SDimitry Andric // This isn't actually true, but the instructions ignore any of the 41030b57cec5SDimitry Andric // upper bits, so any immediate loaded with an LI is acceptable. 41040b57cec5SDimitry Andric // This does not apply to shift right algebraic because a value 41050b57cec5SDimitry Andric // out of range will produce a -1/0. 41060b57cec5SDimitry Andric III.ImmWidth = 16; 4107480093f4SDimitry Andric if (Opc == PPC::RLDCL || Opc == PPC::RLDCL_rec || Opc == PPC::RLDCR || 4108480093f4SDimitry Andric Opc == PPC::RLDCR_rec) 41090b57cec5SDimitry Andric III.TruncateImmTo = 6; 41100b57cec5SDimitry Andric else 41110b57cec5SDimitry Andric III.TruncateImmTo = 7; 41120b57cec5SDimitry Andric switch(Opc) { 41130b57cec5SDimitry Andric default: llvm_unreachable("Unknown opcode"); 41140b57cec5SDimitry Andric case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break; 4115480093f4SDimitry Andric case PPC::RLDCL_rec: 4116480093f4SDimitry Andric III.ImmOpcode = PPC::RLDICL_rec; 4117480093f4SDimitry Andric break; 41180b57cec5SDimitry Andric case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break; 4119480093f4SDimitry Andric case PPC::RLDCR_rec: 4120480093f4SDimitry Andric III.ImmOpcode = PPC::RLDICR_rec; 4121480093f4SDimitry Andric break; 41220b57cec5SDimitry Andric case PPC::SLD: III.ImmOpcode = PPC::RLDICR; break; 4123480093f4SDimitry Andric case PPC::SLD_rec: 4124480093f4SDimitry Andric III.ImmOpcode = PPC::RLDICR_rec; 4125480093f4SDimitry Andric break; 41260b57cec5SDimitry Andric case PPC::SRD: III.ImmOpcode = PPC::RLDICL; break; 4127480093f4SDimitry Andric case PPC::SRD_rec: 4128480093f4SDimitry Andric III.ImmOpcode = PPC::RLDICL_rec; 4129480093f4SDimitry Andric break; 41300b57cec5SDimitry Andric case PPC::SRAD: 41310b57cec5SDimitry Andric III.ImmWidth = 6; 41320b57cec5SDimitry Andric III.TruncateImmTo = 0; 41330b57cec5SDimitry Andric III.ImmOpcode = PPC::SRADI; 41340b57cec5SDimitry Andric break; 4135480093f4SDimitry Andric case PPC::SRAD_rec: 41360b57cec5SDimitry Andric III.ImmWidth = 6; 41370b57cec5SDimitry Andric III.TruncateImmTo = 0; 4138480093f4SDimitry Andric III.ImmOpcode = PPC::SRADI_rec; 41390b57cec5SDimitry Andric break; 41400b57cec5SDimitry Andric } 41410b57cec5SDimitry Andric break; 41420b57cec5SDimitry Andric // Loads and stores: 41430b57cec5SDimitry Andric case PPC::LBZX: 41440b57cec5SDimitry Andric case PPC::LBZX8: 41450b57cec5SDimitry Andric case PPC::LHZX: 41460b57cec5SDimitry Andric case PPC::LHZX8: 41470b57cec5SDimitry Andric case PPC::LHAX: 41480b57cec5SDimitry Andric case PPC::LHAX8: 41490b57cec5SDimitry Andric case PPC::LWZX: 41500b57cec5SDimitry Andric case PPC::LWZX8: 41510b57cec5SDimitry Andric case PPC::LWAX: 41520b57cec5SDimitry Andric case PPC::LDX: 41530b57cec5SDimitry Andric case PPC::LFSX: 41540b57cec5SDimitry Andric case PPC::LFDX: 41550b57cec5SDimitry Andric case PPC::STBX: 41560b57cec5SDimitry Andric case PPC::STBX8: 41570b57cec5SDimitry Andric case PPC::STHX: 41580b57cec5SDimitry Andric case PPC::STHX8: 41590b57cec5SDimitry Andric case PPC::STWX: 41600b57cec5SDimitry Andric case PPC::STWX8: 41610b57cec5SDimitry Andric case PPC::STDX: 41620b57cec5SDimitry Andric case PPC::STFSX: 41630b57cec5SDimitry Andric case PPC::STFDX: 41640b57cec5SDimitry Andric III.SignedImm = true; 41650b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 1; 41660b57cec5SDimitry Andric III.ZeroIsSpecialNew = 2; 41670b57cec5SDimitry Andric III.IsCommutative = true; 41680b57cec5SDimitry Andric III.IsSummingOperands = true; 41690b57cec5SDimitry Andric III.ImmOpNo = 1; 41700b57cec5SDimitry Andric III.OpNoForForwarding = 2; 41710b57cec5SDimitry Andric switch(Opc) { 41720b57cec5SDimitry Andric default: llvm_unreachable("Unknown opcode"); 41730b57cec5SDimitry Andric case PPC::LBZX: III.ImmOpcode = PPC::LBZ; break; 41740b57cec5SDimitry Andric case PPC::LBZX8: III.ImmOpcode = PPC::LBZ8; break; 41750b57cec5SDimitry Andric case PPC::LHZX: III.ImmOpcode = PPC::LHZ; break; 41760b57cec5SDimitry Andric case PPC::LHZX8: III.ImmOpcode = PPC::LHZ8; break; 41770b57cec5SDimitry Andric case PPC::LHAX: III.ImmOpcode = PPC::LHA; break; 41780b57cec5SDimitry Andric case PPC::LHAX8: III.ImmOpcode = PPC::LHA8; break; 41790b57cec5SDimitry Andric case PPC::LWZX: III.ImmOpcode = PPC::LWZ; break; 41800b57cec5SDimitry Andric case PPC::LWZX8: III.ImmOpcode = PPC::LWZ8; break; 41810b57cec5SDimitry Andric case PPC::LWAX: 41820b57cec5SDimitry Andric III.ImmOpcode = PPC::LWA; 41830b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 4; 41840b57cec5SDimitry Andric break; 41850b57cec5SDimitry Andric case PPC::LDX: III.ImmOpcode = PPC::LD; III.ImmMustBeMultipleOf = 4; break; 41860b57cec5SDimitry Andric case PPC::LFSX: III.ImmOpcode = PPC::LFS; break; 41870b57cec5SDimitry Andric case PPC::LFDX: III.ImmOpcode = PPC::LFD; break; 41880b57cec5SDimitry Andric case PPC::STBX: III.ImmOpcode = PPC::STB; break; 41890b57cec5SDimitry Andric case PPC::STBX8: III.ImmOpcode = PPC::STB8; break; 41900b57cec5SDimitry Andric case PPC::STHX: III.ImmOpcode = PPC::STH; break; 41910b57cec5SDimitry Andric case PPC::STHX8: III.ImmOpcode = PPC::STH8; break; 41920b57cec5SDimitry Andric case PPC::STWX: III.ImmOpcode = PPC::STW; break; 41930b57cec5SDimitry Andric case PPC::STWX8: III.ImmOpcode = PPC::STW8; break; 41940b57cec5SDimitry Andric case PPC::STDX: 41950b57cec5SDimitry Andric III.ImmOpcode = PPC::STD; 41960b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 4; 41970b57cec5SDimitry Andric break; 41980b57cec5SDimitry Andric case PPC::STFSX: III.ImmOpcode = PPC::STFS; break; 41990b57cec5SDimitry Andric case PPC::STFDX: III.ImmOpcode = PPC::STFD; break; 42000b57cec5SDimitry Andric } 42010b57cec5SDimitry Andric break; 42020b57cec5SDimitry Andric case PPC::LBZUX: 42030b57cec5SDimitry Andric case PPC::LBZUX8: 42040b57cec5SDimitry Andric case PPC::LHZUX: 42050b57cec5SDimitry Andric case PPC::LHZUX8: 42060b57cec5SDimitry Andric case PPC::LHAUX: 42070b57cec5SDimitry Andric case PPC::LHAUX8: 42080b57cec5SDimitry Andric case PPC::LWZUX: 42090b57cec5SDimitry Andric case PPC::LWZUX8: 42100b57cec5SDimitry Andric case PPC::LDUX: 42110b57cec5SDimitry Andric case PPC::LFSUX: 42120b57cec5SDimitry Andric case PPC::LFDUX: 42130b57cec5SDimitry Andric case PPC::STBUX: 42140b57cec5SDimitry Andric case PPC::STBUX8: 42150b57cec5SDimitry Andric case PPC::STHUX: 42160b57cec5SDimitry Andric case PPC::STHUX8: 42170b57cec5SDimitry Andric case PPC::STWUX: 42180b57cec5SDimitry Andric case PPC::STWUX8: 42190b57cec5SDimitry Andric case PPC::STDUX: 42200b57cec5SDimitry Andric case PPC::STFSUX: 42210b57cec5SDimitry Andric case PPC::STFDUX: 42220b57cec5SDimitry Andric III.SignedImm = true; 42230b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 2; 42240b57cec5SDimitry Andric III.ZeroIsSpecialNew = 3; 42250b57cec5SDimitry Andric III.IsCommutative = false; 42260b57cec5SDimitry Andric III.IsSummingOperands = true; 42270b57cec5SDimitry Andric III.ImmOpNo = 2; 42280b57cec5SDimitry Andric III.OpNoForForwarding = 3; 42290b57cec5SDimitry Andric switch(Opc) { 42300b57cec5SDimitry Andric default: llvm_unreachable("Unknown opcode"); 42310b57cec5SDimitry Andric case PPC::LBZUX: III.ImmOpcode = PPC::LBZU; break; 42320b57cec5SDimitry Andric case PPC::LBZUX8: III.ImmOpcode = PPC::LBZU8; break; 42330b57cec5SDimitry Andric case PPC::LHZUX: III.ImmOpcode = PPC::LHZU; break; 42340b57cec5SDimitry Andric case PPC::LHZUX8: III.ImmOpcode = PPC::LHZU8; break; 42350b57cec5SDimitry Andric case PPC::LHAUX: III.ImmOpcode = PPC::LHAU; break; 42360b57cec5SDimitry Andric case PPC::LHAUX8: III.ImmOpcode = PPC::LHAU8; break; 42370b57cec5SDimitry Andric case PPC::LWZUX: III.ImmOpcode = PPC::LWZU; break; 42380b57cec5SDimitry Andric case PPC::LWZUX8: III.ImmOpcode = PPC::LWZU8; break; 42390b57cec5SDimitry Andric case PPC::LDUX: 42400b57cec5SDimitry Andric III.ImmOpcode = PPC::LDU; 42410b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 4; 42420b57cec5SDimitry Andric break; 42430b57cec5SDimitry Andric case PPC::LFSUX: III.ImmOpcode = PPC::LFSU; break; 42440b57cec5SDimitry Andric case PPC::LFDUX: III.ImmOpcode = PPC::LFDU; break; 42450b57cec5SDimitry Andric case PPC::STBUX: III.ImmOpcode = PPC::STBU; break; 42460b57cec5SDimitry Andric case PPC::STBUX8: III.ImmOpcode = PPC::STBU8; break; 42470b57cec5SDimitry Andric case PPC::STHUX: III.ImmOpcode = PPC::STHU; break; 42480b57cec5SDimitry Andric case PPC::STHUX8: III.ImmOpcode = PPC::STHU8; break; 42490b57cec5SDimitry Andric case PPC::STWUX: III.ImmOpcode = PPC::STWU; break; 42500b57cec5SDimitry Andric case PPC::STWUX8: III.ImmOpcode = PPC::STWU8; break; 42510b57cec5SDimitry Andric case PPC::STDUX: 42520b57cec5SDimitry Andric III.ImmOpcode = PPC::STDU; 42530b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 4; 42540b57cec5SDimitry Andric break; 42550b57cec5SDimitry Andric case PPC::STFSUX: III.ImmOpcode = PPC::STFSU; break; 42560b57cec5SDimitry Andric case PPC::STFDUX: III.ImmOpcode = PPC::STFDU; break; 42570b57cec5SDimitry Andric } 42580b57cec5SDimitry Andric break; 42590b57cec5SDimitry Andric // Power9 and up only. For some of these, the X-Form version has access to all 42600b57cec5SDimitry Andric // 64 VSR's whereas the D-Form only has access to the VR's. We replace those 42610b57cec5SDimitry Andric // with pseudo-ops pre-ra and for post-ra, we check that the register loaded 42620b57cec5SDimitry Andric // into or stored from is one of the VR registers. 42630b57cec5SDimitry Andric case PPC::LXVX: 42640b57cec5SDimitry Andric case PPC::LXSSPX: 42650b57cec5SDimitry Andric case PPC::LXSDX: 42660b57cec5SDimitry Andric case PPC::STXVX: 42670b57cec5SDimitry Andric case PPC::STXSSPX: 42680b57cec5SDimitry Andric case PPC::STXSDX: 42690b57cec5SDimitry Andric case PPC::XFLOADf32: 42700b57cec5SDimitry Andric case PPC::XFLOADf64: 42710b57cec5SDimitry Andric case PPC::XFSTOREf32: 42720b57cec5SDimitry Andric case PPC::XFSTOREf64: 42730b57cec5SDimitry Andric if (!Subtarget.hasP9Vector()) 42740b57cec5SDimitry Andric return false; 42750b57cec5SDimitry Andric III.SignedImm = true; 42760b57cec5SDimitry Andric III.ZeroIsSpecialOrig = 1; 42770b57cec5SDimitry Andric III.ZeroIsSpecialNew = 2; 42780b57cec5SDimitry Andric III.IsCommutative = true; 42790b57cec5SDimitry Andric III.IsSummingOperands = true; 42800b57cec5SDimitry Andric III.ImmOpNo = 1; 42810b57cec5SDimitry Andric III.OpNoForForwarding = 2; 42820b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 4; 42830b57cec5SDimitry Andric switch(Opc) { 42840b57cec5SDimitry Andric default: llvm_unreachable("Unknown opcode"); 42850b57cec5SDimitry Andric case PPC::LXVX: 42860b57cec5SDimitry Andric III.ImmOpcode = PPC::LXV; 42870b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 16; 42880b57cec5SDimitry Andric break; 42890b57cec5SDimitry Andric case PPC::LXSSPX: 42900b57cec5SDimitry Andric if (PostRA) { 42918bcb0991SDimitry Andric if (IsVFReg) 42920b57cec5SDimitry Andric III.ImmOpcode = PPC::LXSSP; 42930b57cec5SDimitry Andric else { 42940b57cec5SDimitry Andric III.ImmOpcode = PPC::LFS; 42950b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 1; 42960b57cec5SDimitry Andric } 42970b57cec5SDimitry Andric break; 42980b57cec5SDimitry Andric } 4299bdd1243dSDimitry Andric [[fallthrough]]; 43000b57cec5SDimitry Andric case PPC::XFLOADf32: 43010b57cec5SDimitry Andric III.ImmOpcode = PPC::DFLOADf32; 43020b57cec5SDimitry Andric break; 43030b57cec5SDimitry Andric case PPC::LXSDX: 43040b57cec5SDimitry Andric if (PostRA) { 43058bcb0991SDimitry Andric if (IsVFReg) 43060b57cec5SDimitry Andric III.ImmOpcode = PPC::LXSD; 43070b57cec5SDimitry Andric else { 43080b57cec5SDimitry Andric III.ImmOpcode = PPC::LFD; 43090b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 1; 43100b57cec5SDimitry Andric } 43110b57cec5SDimitry Andric break; 43120b57cec5SDimitry Andric } 4313bdd1243dSDimitry Andric [[fallthrough]]; 43140b57cec5SDimitry Andric case PPC::XFLOADf64: 43150b57cec5SDimitry Andric III.ImmOpcode = PPC::DFLOADf64; 43160b57cec5SDimitry Andric break; 43170b57cec5SDimitry Andric case PPC::STXVX: 43180b57cec5SDimitry Andric III.ImmOpcode = PPC::STXV; 43190b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 16; 43200b57cec5SDimitry Andric break; 43210b57cec5SDimitry Andric case PPC::STXSSPX: 43220b57cec5SDimitry Andric if (PostRA) { 43238bcb0991SDimitry Andric if (IsVFReg) 43240b57cec5SDimitry Andric III.ImmOpcode = PPC::STXSSP; 43250b57cec5SDimitry Andric else { 43260b57cec5SDimitry Andric III.ImmOpcode = PPC::STFS; 43270b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 1; 43280b57cec5SDimitry Andric } 43290b57cec5SDimitry Andric break; 43300b57cec5SDimitry Andric } 4331bdd1243dSDimitry Andric [[fallthrough]]; 43320b57cec5SDimitry Andric case PPC::XFSTOREf32: 43330b57cec5SDimitry Andric III.ImmOpcode = PPC::DFSTOREf32; 43340b57cec5SDimitry Andric break; 43350b57cec5SDimitry Andric case PPC::STXSDX: 43360b57cec5SDimitry Andric if (PostRA) { 43378bcb0991SDimitry Andric if (IsVFReg) 43380b57cec5SDimitry Andric III.ImmOpcode = PPC::STXSD; 43390b57cec5SDimitry Andric else { 43400b57cec5SDimitry Andric III.ImmOpcode = PPC::STFD; 43410b57cec5SDimitry Andric III.ImmMustBeMultipleOf = 1; 43420b57cec5SDimitry Andric } 43430b57cec5SDimitry Andric break; 43440b57cec5SDimitry Andric } 4345bdd1243dSDimitry Andric [[fallthrough]]; 43460b57cec5SDimitry Andric case PPC::XFSTOREf64: 43470b57cec5SDimitry Andric III.ImmOpcode = PPC::DFSTOREf64; 43480b57cec5SDimitry Andric break; 43490b57cec5SDimitry Andric } 43500b57cec5SDimitry Andric break; 43510b57cec5SDimitry Andric } 43520b57cec5SDimitry Andric return true; 43530b57cec5SDimitry Andric } 43540b57cec5SDimitry Andric 43550b57cec5SDimitry Andric // Utility function for swaping two arbitrary operands of an instruction. 43560b57cec5SDimitry Andric static void swapMIOperands(MachineInstr &MI, unsigned Op1, unsigned Op2) { 43570b57cec5SDimitry Andric assert(Op1 != Op2 && "Cannot swap operand with itself."); 43580b57cec5SDimitry Andric 43590b57cec5SDimitry Andric unsigned MaxOp = std::max(Op1, Op2); 43600b57cec5SDimitry Andric unsigned MinOp = std::min(Op1, Op2); 43610b57cec5SDimitry Andric MachineOperand MOp1 = MI.getOperand(MinOp); 43620b57cec5SDimitry Andric MachineOperand MOp2 = MI.getOperand(MaxOp); 436381ad6265SDimitry Andric MI.removeOperand(std::max(Op1, Op2)); 436481ad6265SDimitry Andric MI.removeOperand(std::min(Op1, Op2)); 43650b57cec5SDimitry Andric 43660b57cec5SDimitry Andric // If the operands we are swapping are the two at the end (the common case) 43670b57cec5SDimitry Andric // we can just remove both and add them in the opposite order. 43680b57cec5SDimitry Andric if (MaxOp - MinOp == 1 && MI.getNumOperands() == MinOp) { 43690b57cec5SDimitry Andric MI.addOperand(MOp2); 43700b57cec5SDimitry Andric MI.addOperand(MOp1); 43710b57cec5SDimitry Andric } else { 43720b57cec5SDimitry Andric // Store all operands in a temporary vector, remove them and re-add in the 43730b57cec5SDimitry Andric // right order. 43740b57cec5SDimitry Andric SmallVector<MachineOperand, 2> MOps; 43750b57cec5SDimitry Andric unsigned TotalOps = MI.getNumOperands() + 2; // We've already removed 2 ops. 43760b57cec5SDimitry Andric for (unsigned i = MI.getNumOperands() - 1; i >= MinOp; i--) { 43770b57cec5SDimitry Andric MOps.push_back(MI.getOperand(i)); 437881ad6265SDimitry Andric MI.removeOperand(i); 43790b57cec5SDimitry Andric } 43800b57cec5SDimitry Andric // MOp2 needs to be added next. 43810b57cec5SDimitry Andric MI.addOperand(MOp2); 43820b57cec5SDimitry Andric // Now add the rest. 43830b57cec5SDimitry Andric for (unsigned i = MI.getNumOperands(); i < TotalOps; i++) { 43840b57cec5SDimitry Andric if (i == MaxOp) 43850b57cec5SDimitry Andric MI.addOperand(MOp1); 43860b57cec5SDimitry Andric else { 43870b57cec5SDimitry Andric MI.addOperand(MOps.back()); 43880b57cec5SDimitry Andric MOps.pop_back(); 43890b57cec5SDimitry Andric } 43900b57cec5SDimitry Andric } 43910b57cec5SDimitry Andric } 43920b57cec5SDimitry Andric } 43930b57cec5SDimitry Andric 43940b57cec5SDimitry Andric // Check if the 'MI' that has the index OpNoForForwarding 43950b57cec5SDimitry Andric // meets the requirement described in the ImmInstrInfo. 43960b57cec5SDimitry Andric bool PPCInstrInfo::isUseMIElgibleForForwarding(MachineInstr &MI, 43970b57cec5SDimitry Andric const ImmInstrInfo &III, 43980b57cec5SDimitry Andric unsigned OpNoForForwarding 43990b57cec5SDimitry Andric ) const { 44000b57cec5SDimitry Andric // As the algorithm of checking for PPC::ZERO/PPC::ZERO8 44010b57cec5SDimitry Andric // would not work pre-RA, we can only do the check post RA. 44020b57cec5SDimitry Andric MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 44030b57cec5SDimitry Andric if (MRI.isSSA()) 44040b57cec5SDimitry Andric return false; 44050b57cec5SDimitry Andric 44060b57cec5SDimitry Andric // Cannot do the transform if MI isn't summing the operands. 44070b57cec5SDimitry Andric if (!III.IsSummingOperands) 44080b57cec5SDimitry Andric return false; 44090b57cec5SDimitry Andric 44100b57cec5SDimitry Andric // The instruction we are trying to replace must have the ZeroIsSpecialOrig set. 44110b57cec5SDimitry Andric if (!III.ZeroIsSpecialOrig) 44120b57cec5SDimitry Andric return false; 44130b57cec5SDimitry Andric 44140b57cec5SDimitry Andric // We cannot do the transform if the operand we are trying to replace 44150b57cec5SDimitry Andric // isn't the same as the operand the instruction allows. 44160b57cec5SDimitry Andric if (OpNoForForwarding != III.OpNoForForwarding) 44170b57cec5SDimitry Andric return false; 44180b57cec5SDimitry Andric 44190b57cec5SDimitry Andric // Check if the instruction we are trying to transform really has 44200b57cec5SDimitry Andric // the special zero register as its operand. 44210b57cec5SDimitry Andric if (MI.getOperand(III.ZeroIsSpecialOrig).getReg() != PPC::ZERO && 44220b57cec5SDimitry Andric MI.getOperand(III.ZeroIsSpecialOrig).getReg() != PPC::ZERO8) 44230b57cec5SDimitry Andric return false; 44240b57cec5SDimitry Andric 44250b57cec5SDimitry Andric // This machine instruction is convertible if it is, 44260b57cec5SDimitry Andric // 1. summing the operands. 44270b57cec5SDimitry Andric // 2. one of the operands is special zero register. 44280b57cec5SDimitry Andric // 3. the operand we are trying to replace is allowed by the MI. 44290b57cec5SDimitry Andric return true; 44300b57cec5SDimitry Andric } 44310b57cec5SDimitry Andric 44320b57cec5SDimitry Andric // Check if the DefMI is the add inst and set the ImmMO and RegMO 44330b57cec5SDimitry Andric // accordingly. 44340b57cec5SDimitry Andric bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI, 44350b57cec5SDimitry Andric const ImmInstrInfo &III, 44360b57cec5SDimitry Andric MachineOperand *&ImmMO, 44370b57cec5SDimitry Andric MachineOperand *&RegMO) const { 44380b57cec5SDimitry Andric unsigned Opc = DefMI.getOpcode(); 44390fca6ea1SDimitry Andric if (Opc != PPC::ADDItocL8 && Opc != PPC::ADDI && Opc != PPC::ADDI8) 44400fca6ea1SDimitry Andric return false; 44410fca6ea1SDimitry Andric 44420fca6ea1SDimitry Andric // Skip the optimization of transformTo[NewImm|Imm]FormFedByAdd for ADDItocL8 44430fca6ea1SDimitry Andric // on AIX which is used for toc-data access. TODO: Follow up to see if it can 44440fca6ea1SDimitry Andric // apply for AIX toc-data as well. 44450fca6ea1SDimitry Andric if (Opc == PPC::ADDItocL8 && Subtarget.isAIX()) 44460b57cec5SDimitry Andric return false; 44470b57cec5SDimitry Andric 44480b57cec5SDimitry Andric assert(DefMI.getNumOperands() >= 3 && 44490b57cec5SDimitry Andric "Add inst must have at least three operands"); 44500b57cec5SDimitry Andric RegMO = &DefMI.getOperand(1); 44510b57cec5SDimitry Andric ImmMO = &DefMI.getOperand(2); 44520b57cec5SDimitry Andric 44535ffd83dbSDimitry Andric // Before RA, ADDI first operand could be a frame index. 44545ffd83dbSDimitry Andric if (!RegMO->isReg()) 44555ffd83dbSDimitry Andric return false; 44565ffd83dbSDimitry Andric 44570b57cec5SDimitry Andric // This DefMI is elgible for forwarding if it is: 44580b57cec5SDimitry Andric // 1. add inst 44590b57cec5SDimitry Andric // 2. one of the operands is Imm/CPI/Global. 44600b57cec5SDimitry Andric return isAnImmediateOperand(*ImmMO); 44610b57cec5SDimitry Andric } 44620b57cec5SDimitry Andric 44630b57cec5SDimitry Andric bool PPCInstrInfo::isRegElgibleForForwarding( 44640b57cec5SDimitry Andric const MachineOperand &RegMO, const MachineInstr &DefMI, 44650b57cec5SDimitry Andric const MachineInstr &MI, bool KillDefMI, 4466bdd1243dSDimitry Andric bool &IsFwdFeederRegKilled, bool &SeenIntermediateUse) const { 44670b57cec5SDimitry Andric // x = addi y, imm 44680b57cec5SDimitry Andric // ... 44690b57cec5SDimitry Andric // z = lfdx 0, x -> z = lfd imm(y) 44700b57cec5SDimitry Andric // The Reg "y" can be forwarded to the MI(z) only when there is no DEF 44710b57cec5SDimitry Andric // of "y" between the DEF of "x" and "z". 44720b57cec5SDimitry Andric // The query is only valid post RA. 44730b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 44740b57cec5SDimitry Andric if (MRI.isSSA()) 44750b57cec5SDimitry Andric return false; 44760b57cec5SDimitry Andric 44778bcb0991SDimitry Andric Register Reg = RegMO.getReg(); 44780b57cec5SDimitry Andric 44790b57cec5SDimitry Andric // Walking the inst in reverse(MI-->DefMI) to get the last DEF of the Reg. 44800b57cec5SDimitry Andric MachineBasicBlock::const_reverse_iterator It = MI; 44810b57cec5SDimitry Andric MachineBasicBlock::const_reverse_iterator E = MI.getParent()->rend(); 44820b57cec5SDimitry Andric It++; 44830b57cec5SDimitry Andric for (; It != E; ++It) { 44840b57cec5SDimitry Andric if (It->modifiesRegister(Reg, &getRegisterInfo()) && (&*It) != &DefMI) 44850b57cec5SDimitry Andric return false; 44860b57cec5SDimitry Andric else if (It->killsRegister(Reg, &getRegisterInfo()) && (&*It) != &DefMI) 44870b57cec5SDimitry Andric IsFwdFeederRegKilled = true; 4488bdd1243dSDimitry Andric if (It->readsRegister(Reg, &getRegisterInfo()) && (&*It) != &DefMI) 4489bdd1243dSDimitry Andric SeenIntermediateUse = true; 44900b57cec5SDimitry Andric // Made it to DefMI without encountering a clobber. 44910b57cec5SDimitry Andric if ((&*It) == &DefMI) 44920b57cec5SDimitry Andric break; 44930b57cec5SDimitry Andric } 44940b57cec5SDimitry Andric assert((&*It) == &DefMI && "DefMI is missing"); 44950b57cec5SDimitry Andric 44960b57cec5SDimitry Andric // If DefMI also defines the register to be forwarded, we can only forward it 44970b57cec5SDimitry Andric // if DefMI is being erased. 44980b57cec5SDimitry Andric if (DefMI.modifiesRegister(Reg, &getRegisterInfo())) 44990b57cec5SDimitry Andric return KillDefMI; 45000b57cec5SDimitry Andric 45010b57cec5SDimitry Andric return true; 45020b57cec5SDimitry Andric } 45030b57cec5SDimitry Andric 45040b57cec5SDimitry Andric bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO, 45050b57cec5SDimitry Andric const MachineInstr &DefMI, 45060b57cec5SDimitry Andric const ImmInstrInfo &III, 45075ffd83dbSDimitry Andric int64_t &Imm, 45085ffd83dbSDimitry Andric int64_t BaseImm) const { 45090b57cec5SDimitry Andric assert(isAnImmediateOperand(ImmMO) && "ImmMO is NOT an immediate"); 45100fca6ea1SDimitry Andric if (DefMI.getOpcode() == PPC::ADDItocL8) { 45110fca6ea1SDimitry Andric // The operand for ADDItocL8 is CPI, which isn't imm at compiling time, 45120b57cec5SDimitry Andric // However, we know that, it is 16-bit width, and has the alignment of 4. 45130b57cec5SDimitry Andric // Check if the instruction met the requirement. 45140b57cec5SDimitry Andric if (III.ImmMustBeMultipleOf > 4 || 45150b57cec5SDimitry Andric III.TruncateImmTo || III.ImmWidth != 16) 45160b57cec5SDimitry Andric return false; 45170b57cec5SDimitry Andric 45180b57cec5SDimitry Andric // Going from XForm to DForm loads means that the displacement needs to be 45190b57cec5SDimitry Andric // not just an immediate but also a multiple of 4, or 16 depending on the 45200b57cec5SDimitry Andric // load. A DForm load cannot be represented if it is a multiple of say 2. 45210b57cec5SDimitry Andric // XForm loads do not have this restriction. 45225ffd83dbSDimitry Andric if (ImmMO.isGlobal()) { 45230fca6ea1SDimitry Andric const DataLayout &DL = ImmMO.getGlobal()->getDataLayout(); 45245ffd83dbSDimitry Andric if (ImmMO.getGlobal()->getPointerAlignment(DL) < III.ImmMustBeMultipleOf) 45250b57cec5SDimitry Andric return false; 45265ffd83dbSDimitry Andric } 45270b57cec5SDimitry Andric 45280b57cec5SDimitry Andric return true; 45290b57cec5SDimitry Andric } 45300b57cec5SDimitry Andric 45310b57cec5SDimitry Andric if (ImmMO.isImm()) { 45320b57cec5SDimitry Andric // It is Imm, we need to check if the Imm fit the range. 45330b57cec5SDimitry Andric // Sign-extend to 64-bits. 45345ffd83dbSDimitry Andric // DefMI may be folded with another imm form instruction, the result Imm is 45355ffd83dbSDimitry Andric // the sum of Imm of DefMI and BaseImm which is from imm form instruction. 4536fe6060f1SDimitry Andric APInt ActualValue(64, ImmMO.getImm() + BaseImm, true); 4537fe6060f1SDimitry Andric if (III.SignedImm && !ActualValue.isSignedIntN(III.ImmWidth)) 4538fe6060f1SDimitry Andric return false; 4539fe6060f1SDimitry Andric if (!III.SignedImm && !ActualValue.isIntN(III.ImmWidth)) 4540fe6060f1SDimitry Andric return false; 45415ffd83dbSDimitry Andric Imm = SignExtend64<16>(ImmMO.getImm() + BaseImm); 45420b57cec5SDimitry Andric 45430b57cec5SDimitry Andric if (Imm % III.ImmMustBeMultipleOf) 45440b57cec5SDimitry Andric return false; 45450b57cec5SDimitry Andric if (III.TruncateImmTo) 45460b57cec5SDimitry Andric Imm &= ((1 << III.TruncateImmTo) - 1); 45470b57cec5SDimitry Andric } 45480b57cec5SDimitry Andric else 45490b57cec5SDimitry Andric return false; 45500b57cec5SDimitry Andric 45510b57cec5SDimitry Andric // This ImmMO is forwarded if it meets the requriement describle 45520b57cec5SDimitry Andric // in ImmInstrInfo 45530b57cec5SDimitry Andric return true; 45540b57cec5SDimitry Andric } 45550b57cec5SDimitry Andric 45565ffd83dbSDimitry Andric bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI, 45575ffd83dbSDimitry Andric unsigned OpNoForForwarding, 45585ffd83dbSDimitry Andric MachineInstr **KilledDef) const { 45595ffd83dbSDimitry Andric if ((DefMI.getOpcode() != PPC::LI && DefMI.getOpcode() != PPC::LI8) || 45605ffd83dbSDimitry Andric !DefMI.getOperand(1).isImm()) 45615ffd83dbSDimitry Andric return false; 45625ffd83dbSDimitry Andric 45635ffd83dbSDimitry Andric MachineFunction *MF = MI.getParent()->getParent(); 45645ffd83dbSDimitry Andric MachineRegisterInfo *MRI = &MF->getRegInfo(); 45655ffd83dbSDimitry Andric bool PostRA = !MRI->isSSA(); 45665ffd83dbSDimitry Andric 45675ffd83dbSDimitry Andric int64_t Immediate = DefMI.getOperand(1).getImm(); 45685ffd83dbSDimitry Andric // Sign-extend to 64-bits. 45695ffd83dbSDimitry Andric int64_t SExtImm = SignExtend64<16>(Immediate); 45705ffd83dbSDimitry Andric 45715ffd83dbSDimitry Andric bool ReplaceWithLI = false; 45725ffd83dbSDimitry Andric bool Is64BitLI = false; 45735ffd83dbSDimitry Andric int64_t NewImm = 0; 45745ffd83dbSDimitry Andric bool SetCR = false; 45755ffd83dbSDimitry Andric unsigned Opc = MI.getOpcode(); 45765ffd83dbSDimitry Andric switch (Opc) { 45775ffd83dbSDimitry Andric default: 45785ffd83dbSDimitry Andric return false; 45795ffd83dbSDimitry Andric 45805ffd83dbSDimitry Andric // FIXME: Any branches conditional on such a comparison can be made 45815ffd83dbSDimitry Andric // unconditional. At this time, this happens too infrequently to be worth 45825ffd83dbSDimitry Andric // the implementation effort, but if that ever changes, we could convert 45835ffd83dbSDimitry Andric // such a pattern here. 45845ffd83dbSDimitry Andric case PPC::CMPWI: 45855ffd83dbSDimitry Andric case PPC::CMPLWI: 45865ffd83dbSDimitry Andric case PPC::CMPDI: 45875ffd83dbSDimitry Andric case PPC::CMPLDI: { 45885ffd83dbSDimitry Andric // Doing this post-RA would require dataflow analysis to reliably find uses 45895ffd83dbSDimitry Andric // of the CR register set by the compare. 45905ffd83dbSDimitry Andric // No need to fixup killed/dead flag since this transformation is only valid 45915ffd83dbSDimitry Andric // before RA. 45925ffd83dbSDimitry Andric if (PostRA) 45935ffd83dbSDimitry Andric return false; 45945ffd83dbSDimitry Andric // If a compare-immediate is fed by an immediate and is itself an input of 45955ffd83dbSDimitry Andric // an ISEL (the most common case) into a COPY of the correct register. 45965ffd83dbSDimitry Andric bool Changed = false; 45975ffd83dbSDimitry Andric Register DefReg = MI.getOperand(0).getReg(); 45985ffd83dbSDimitry Andric int64_t Comparand = MI.getOperand(2).getImm(); 45995ffd83dbSDimitry Andric int64_t SExtComparand = ((uint64_t)Comparand & ~0x7FFFuLL) != 0 46005ffd83dbSDimitry Andric ? (Comparand | 0xFFFFFFFFFFFF0000) 46015ffd83dbSDimitry Andric : Comparand; 46025ffd83dbSDimitry Andric 46035ffd83dbSDimitry Andric for (auto &CompareUseMI : MRI->use_instructions(DefReg)) { 46045ffd83dbSDimitry Andric unsigned UseOpc = CompareUseMI.getOpcode(); 46055ffd83dbSDimitry Andric if (UseOpc != PPC::ISEL && UseOpc != PPC::ISEL8) 46065ffd83dbSDimitry Andric continue; 46075ffd83dbSDimitry Andric unsigned CRSubReg = CompareUseMI.getOperand(3).getSubReg(); 46085ffd83dbSDimitry Andric Register TrueReg = CompareUseMI.getOperand(1).getReg(); 46095ffd83dbSDimitry Andric Register FalseReg = CompareUseMI.getOperand(2).getReg(); 46105ffd83dbSDimitry Andric unsigned RegToCopy = 46115ffd83dbSDimitry Andric selectReg(SExtImm, SExtComparand, Opc, TrueReg, FalseReg, CRSubReg); 46125ffd83dbSDimitry Andric if (RegToCopy == PPC::NoRegister) 46135ffd83dbSDimitry Andric continue; 46145ffd83dbSDimitry Andric // Can't use PPC::COPY to copy PPC::ZERO[8]. Convert it to LI[8] 0. 46155ffd83dbSDimitry Andric if (RegToCopy == PPC::ZERO || RegToCopy == PPC::ZERO8) { 46165ffd83dbSDimitry Andric CompareUseMI.setDesc(get(UseOpc == PPC::ISEL8 ? PPC::LI8 : PPC::LI)); 46175ffd83dbSDimitry Andric replaceInstrOperandWithImm(CompareUseMI, 1, 0); 461881ad6265SDimitry Andric CompareUseMI.removeOperand(3); 461981ad6265SDimitry Andric CompareUseMI.removeOperand(2); 46205ffd83dbSDimitry Andric continue; 46215ffd83dbSDimitry Andric } 46225ffd83dbSDimitry Andric LLVM_DEBUG( 46235ffd83dbSDimitry Andric dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); 46245ffd83dbSDimitry Andric LLVM_DEBUG(DefMI.dump(); MI.dump(); CompareUseMI.dump()); 46255ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Is converted to:\n"); 46265ffd83dbSDimitry Andric // Convert to copy and remove unneeded operands. 46275ffd83dbSDimitry Andric CompareUseMI.setDesc(get(PPC::COPY)); 462881ad6265SDimitry Andric CompareUseMI.removeOperand(3); 462981ad6265SDimitry Andric CompareUseMI.removeOperand(RegToCopy == TrueReg ? 2 : 1); 46305ffd83dbSDimitry Andric CmpIselsConverted++; 46315ffd83dbSDimitry Andric Changed = true; 46325ffd83dbSDimitry Andric LLVM_DEBUG(CompareUseMI.dump()); 46335ffd83dbSDimitry Andric } 46345ffd83dbSDimitry Andric if (Changed) 46355ffd83dbSDimitry Andric return true; 46365ffd83dbSDimitry Andric // This may end up incremented multiple times since this function is called 46375ffd83dbSDimitry Andric // during a fixed-point transformation, but it is only meant to indicate the 46385ffd83dbSDimitry Andric // presence of this opportunity. 46395ffd83dbSDimitry Andric MissedConvertibleImmediateInstrs++; 46405ffd83dbSDimitry Andric return false; 46415ffd83dbSDimitry Andric } 46425ffd83dbSDimitry Andric 46435ffd83dbSDimitry Andric // Immediate forms - may simply be convertable to an LI. 46445ffd83dbSDimitry Andric case PPC::ADDI: 46455ffd83dbSDimitry Andric case PPC::ADDI8: { 46465ffd83dbSDimitry Andric // Does the sum fit in a 16-bit signed field? 46475ffd83dbSDimitry Andric int64_t Addend = MI.getOperand(2).getImm(); 46485ffd83dbSDimitry Andric if (isInt<16>(Addend + SExtImm)) { 46495ffd83dbSDimitry Andric ReplaceWithLI = true; 46505ffd83dbSDimitry Andric Is64BitLI = Opc == PPC::ADDI8; 46515ffd83dbSDimitry Andric NewImm = Addend + SExtImm; 46525ffd83dbSDimitry Andric break; 46535ffd83dbSDimitry Andric } 46545ffd83dbSDimitry Andric return false; 46555ffd83dbSDimitry Andric } 4656e8d8bef9SDimitry Andric case PPC::SUBFIC: 4657e8d8bef9SDimitry Andric case PPC::SUBFIC8: { 4658e8d8bef9SDimitry Andric // Only transform this if the CARRY implicit operand is dead. 4659e8d8bef9SDimitry Andric if (MI.getNumOperands() > 3 && !MI.getOperand(3).isDead()) 4660e8d8bef9SDimitry Andric return false; 4661e8d8bef9SDimitry Andric int64_t Minuend = MI.getOperand(2).getImm(); 4662e8d8bef9SDimitry Andric if (isInt<16>(Minuend - SExtImm)) { 4663e8d8bef9SDimitry Andric ReplaceWithLI = true; 4664e8d8bef9SDimitry Andric Is64BitLI = Opc == PPC::SUBFIC8; 4665e8d8bef9SDimitry Andric NewImm = Minuend - SExtImm; 4666e8d8bef9SDimitry Andric break; 4667e8d8bef9SDimitry Andric } 4668e8d8bef9SDimitry Andric return false; 4669e8d8bef9SDimitry Andric } 46705ffd83dbSDimitry Andric case PPC::RLDICL: 46715ffd83dbSDimitry Andric case PPC::RLDICL_rec: 46725ffd83dbSDimitry Andric case PPC::RLDICL_32: 46735ffd83dbSDimitry Andric case PPC::RLDICL_32_64: { 46745ffd83dbSDimitry Andric // Use APInt's rotate function. 46755ffd83dbSDimitry Andric int64_t SH = MI.getOperand(2).getImm(); 46765ffd83dbSDimitry Andric int64_t MB = MI.getOperand(3).getImm(); 46775ffd83dbSDimitry Andric APInt InVal((Opc == PPC::RLDICL || Opc == PPC::RLDICL_rec) ? 64 : 32, 46785ffd83dbSDimitry Andric SExtImm, true); 46795ffd83dbSDimitry Andric InVal = InVal.rotl(SH); 46805ffd83dbSDimitry Andric uint64_t Mask = MB == 0 ? -1LLU : (1LLU << (63 - MB + 1)) - 1; 46815ffd83dbSDimitry Andric InVal &= Mask; 46825ffd83dbSDimitry Andric // Can't replace negative values with an LI as that will sign-extend 46835ffd83dbSDimitry Andric // and not clear the left bits. If we're setting the CR bit, we will use 46845ffd83dbSDimitry Andric // ANDI_rec which won't sign extend, so that's safe. 46855ffd83dbSDimitry Andric if (isUInt<15>(InVal.getSExtValue()) || 46865ffd83dbSDimitry Andric (Opc == PPC::RLDICL_rec && isUInt<16>(InVal.getSExtValue()))) { 46875ffd83dbSDimitry Andric ReplaceWithLI = true; 46885ffd83dbSDimitry Andric Is64BitLI = Opc != PPC::RLDICL_32; 46895ffd83dbSDimitry Andric NewImm = InVal.getSExtValue(); 46905ffd83dbSDimitry Andric SetCR = Opc == PPC::RLDICL_rec; 46915ffd83dbSDimitry Andric break; 46925ffd83dbSDimitry Andric } 46935ffd83dbSDimitry Andric return false; 46945ffd83dbSDimitry Andric } 46955ffd83dbSDimitry Andric case PPC::RLWINM: 46965ffd83dbSDimitry Andric case PPC::RLWINM8: 46975ffd83dbSDimitry Andric case PPC::RLWINM_rec: 46985ffd83dbSDimitry Andric case PPC::RLWINM8_rec: { 46995ffd83dbSDimitry Andric int64_t SH = MI.getOperand(2).getImm(); 47005ffd83dbSDimitry Andric int64_t MB = MI.getOperand(3).getImm(); 47015ffd83dbSDimitry Andric int64_t ME = MI.getOperand(4).getImm(); 47025ffd83dbSDimitry Andric APInt InVal(32, SExtImm, true); 47035ffd83dbSDimitry Andric InVal = InVal.rotl(SH); 47045ffd83dbSDimitry Andric APInt Mask = APInt::getBitsSetWithWrap(32, 32 - ME - 1, 32 - MB); 47055ffd83dbSDimitry Andric InVal &= Mask; 47065ffd83dbSDimitry Andric // Can't replace negative values with an LI as that will sign-extend 47075ffd83dbSDimitry Andric // and not clear the left bits. If we're setting the CR bit, we will use 47085ffd83dbSDimitry Andric // ANDI_rec which won't sign extend, so that's safe. 47095ffd83dbSDimitry Andric bool ValueFits = isUInt<15>(InVal.getSExtValue()); 47105ffd83dbSDimitry Andric ValueFits |= ((Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8_rec) && 47115ffd83dbSDimitry Andric isUInt<16>(InVal.getSExtValue())); 47125ffd83dbSDimitry Andric if (ValueFits) { 47135ffd83dbSDimitry Andric ReplaceWithLI = true; 47145ffd83dbSDimitry Andric Is64BitLI = Opc == PPC::RLWINM8 || Opc == PPC::RLWINM8_rec; 47155ffd83dbSDimitry Andric NewImm = InVal.getSExtValue(); 47165ffd83dbSDimitry Andric SetCR = Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8_rec; 47175ffd83dbSDimitry Andric break; 47185ffd83dbSDimitry Andric } 47195ffd83dbSDimitry Andric return false; 47205ffd83dbSDimitry Andric } 47215ffd83dbSDimitry Andric case PPC::ORI: 47225ffd83dbSDimitry Andric case PPC::ORI8: 47235ffd83dbSDimitry Andric case PPC::XORI: 47245ffd83dbSDimitry Andric case PPC::XORI8: { 47255ffd83dbSDimitry Andric int64_t LogicalImm = MI.getOperand(2).getImm(); 47265ffd83dbSDimitry Andric int64_t Result = 0; 47275ffd83dbSDimitry Andric if (Opc == PPC::ORI || Opc == PPC::ORI8) 47285ffd83dbSDimitry Andric Result = LogicalImm | SExtImm; 47295ffd83dbSDimitry Andric else 47305ffd83dbSDimitry Andric Result = LogicalImm ^ SExtImm; 47315ffd83dbSDimitry Andric if (isInt<16>(Result)) { 47325ffd83dbSDimitry Andric ReplaceWithLI = true; 47335ffd83dbSDimitry Andric Is64BitLI = Opc == PPC::ORI8 || Opc == PPC::XORI8; 47345ffd83dbSDimitry Andric NewImm = Result; 47355ffd83dbSDimitry Andric break; 47365ffd83dbSDimitry Andric } 47375ffd83dbSDimitry Andric return false; 47385ffd83dbSDimitry Andric } 47395ffd83dbSDimitry Andric } 47405ffd83dbSDimitry Andric 47415ffd83dbSDimitry Andric if (ReplaceWithLI) { 47425ffd83dbSDimitry Andric // We need to be careful with CR-setting instructions we're replacing. 47435ffd83dbSDimitry Andric if (SetCR) { 47445ffd83dbSDimitry Andric // We don't know anything about uses when we're out of SSA, so only 47455ffd83dbSDimitry Andric // replace if the new immediate will be reproduced. 47465ffd83dbSDimitry Andric bool ImmChanged = (SExtImm & NewImm) != NewImm; 47475ffd83dbSDimitry Andric if (PostRA && ImmChanged) 47485ffd83dbSDimitry Andric return false; 47495ffd83dbSDimitry Andric 47505ffd83dbSDimitry Andric if (!PostRA) { 47515ffd83dbSDimitry Andric // If the defining load-immediate has no other uses, we can just replace 47525ffd83dbSDimitry Andric // the immediate with the new immediate. 47535ffd83dbSDimitry Andric if (MRI->hasOneUse(DefMI.getOperand(0).getReg())) 47545ffd83dbSDimitry Andric DefMI.getOperand(1).setImm(NewImm); 47555ffd83dbSDimitry Andric 47565ffd83dbSDimitry Andric // If we're not using the GPR result of the CR-setting instruction, we 47575ffd83dbSDimitry Andric // just need to and with zero/non-zero depending on the new immediate. 47585ffd83dbSDimitry Andric else if (MRI->use_empty(MI.getOperand(0).getReg())) { 47595ffd83dbSDimitry Andric if (NewImm) { 47605ffd83dbSDimitry Andric assert(Immediate && "Transformation converted zero to non-zero?"); 47615ffd83dbSDimitry Andric NewImm = Immediate; 47625ffd83dbSDimitry Andric } 47635ffd83dbSDimitry Andric } else if (ImmChanged) 47645ffd83dbSDimitry Andric return false; 47655ffd83dbSDimitry Andric } 47665ffd83dbSDimitry Andric } 47675ffd83dbSDimitry Andric 4768bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Replacing constant instruction:\n"); 47695ffd83dbSDimitry Andric LLVM_DEBUG(MI.dump()); 47705ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Fed by:\n"); 47715ffd83dbSDimitry Andric LLVM_DEBUG(DefMI.dump()); 47725ffd83dbSDimitry Andric LoadImmediateInfo LII; 47735ffd83dbSDimitry Andric LII.Imm = NewImm; 47745ffd83dbSDimitry Andric LII.Is64Bit = Is64BitLI; 47755ffd83dbSDimitry Andric LII.SetCR = SetCR; 47765ffd83dbSDimitry Andric // If we're setting the CR, the original load-immediate must be kept (as an 47775ffd83dbSDimitry Andric // operand to ANDI_rec/ANDI8_rec). 47785ffd83dbSDimitry Andric if (KilledDef && SetCR) 47795ffd83dbSDimitry Andric *KilledDef = nullptr; 47805ffd83dbSDimitry Andric replaceInstrWithLI(MI, LII); 47815ffd83dbSDimitry Andric 47825f757f3fSDimitry Andric if (PostRA) 47835f757f3fSDimitry Andric recomputeLivenessFlags(*MI.getParent()); 47845ffd83dbSDimitry Andric 47855ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "With:\n"); 47865ffd83dbSDimitry Andric LLVM_DEBUG(MI.dump()); 47875ffd83dbSDimitry Andric return true; 47885ffd83dbSDimitry Andric } 47895ffd83dbSDimitry Andric return false; 47905ffd83dbSDimitry Andric } 47915ffd83dbSDimitry Andric 47925ffd83dbSDimitry Andric bool PPCInstrInfo::transformToNewImmFormFedByAdd( 47935ffd83dbSDimitry Andric MachineInstr &MI, MachineInstr &DefMI, unsigned OpNoForForwarding) const { 47945ffd83dbSDimitry Andric MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo(); 47955ffd83dbSDimitry Andric bool PostRA = !MRI->isSSA(); 47965ffd83dbSDimitry Andric // FIXME: extend this to post-ra. Need to do some change in getForwardingDefMI 47975ffd83dbSDimitry Andric // for post-ra. 47985ffd83dbSDimitry Andric if (PostRA) 47995ffd83dbSDimitry Andric return false; 48005ffd83dbSDimitry Andric 48015ffd83dbSDimitry Andric // Only handle load/store. 48025ffd83dbSDimitry Andric if (!MI.mayLoadOrStore()) 48035ffd83dbSDimitry Andric return false; 48045ffd83dbSDimitry Andric 48055ffd83dbSDimitry Andric unsigned XFormOpcode = RI.getMappedIdxOpcForImmOpc(MI.getOpcode()); 48065ffd83dbSDimitry Andric 48075ffd83dbSDimitry Andric assert((XFormOpcode != PPC::INSTRUCTION_LIST_END) && 48085ffd83dbSDimitry Andric "MI must have x-form opcode"); 48095ffd83dbSDimitry Andric 48105ffd83dbSDimitry Andric // get Imm Form info. 48115ffd83dbSDimitry Andric ImmInstrInfo III; 48125ffd83dbSDimitry Andric bool IsVFReg = MI.getOperand(0).isReg() 48135f757f3fSDimitry Andric ? PPC::isVFRegister(MI.getOperand(0).getReg()) 48145ffd83dbSDimitry Andric : false; 48155ffd83dbSDimitry Andric 48165ffd83dbSDimitry Andric if (!instrHasImmForm(XFormOpcode, IsVFReg, III, PostRA)) 48175ffd83dbSDimitry Andric return false; 48185ffd83dbSDimitry Andric 48195ffd83dbSDimitry Andric if (!III.IsSummingOperands) 48205ffd83dbSDimitry Andric return false; 48215ffd83dbSDimitry Andric 48225ffd83dbSDimitry Andric if (OpNoForForwarding != III.OpNoForForwarding) 48235ffd83dbSDimitry Andric return false; 48245ffd83dbSDimitry Andric 48255ffd83dbSDimitry Andric MachineOperand ImmOperandMI = MI.getOperand(III.ImmOpNo); 48265ffd83dbSDimitry Andric if (!ImmOperandMI.isImm()) 48275ffd83dbSDimitry Andric return false; 48285ffd83dbSDimitry Andric 48295ffd83dbSDimitry Andric // Check DefMI. 48305ffd83dbSDimitry Andric MachineOperand *ImmMO = nullptr; 48315ffd83dbSDimitry Andric MachineOperand *RegMO = nullptr; 48325ffd83dbSDimitry Andric if (!isDefMIElgibleForForwarding(DefMI, III, ImmMO, RegMO)) 48335ffd83dbSDimitry Andric return false; 48345ffd83dbSDimitry Andric assert(ImmMO && RegMO && "Imm and Reg operand must have been set"); 48355ffd83dbSDimitry Andric 48365ffd83dbSDimitry Andric // Check Imm. 48375ffd83dbSDimitry Andric // Set ImmBase from imm instruction as base and get new Imm inside 48385ffd83dbSDimitry Andric // isImmElgibleForForwarding. 48395ffd83dbSDimitry Andric int64_t ImmBase = ImmOperandMI.getImm(); 48405ffd83dbSDimitry Andric int64_t Imm = 0; 48415ffd83dbSDimitry Andric if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm, ImmBase)) 48425ffd83dbSDimitry Andric return false; 48435ffd83dbSDimitry Andric 48445ffd83dbSDimitry Andric // Do the transform 4845bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Replacing existing reg+imm instruction:\n"); 48465ffd83dbSDimitry Andric LLVM_DEBUG(MI.dump()); 48475ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Fed by:\n"); 48485ffd83dbSDimitry Andric LLVM_DEBUG(DefMI.dump()); 48495ffd83dbSDimitry Andric 48505ffd83dbSDimitry Andric MI.getOperand(III.OpNoForForwarding).setReg(RegMO->getReg()); 48515ffd83dbSDimitry Andric MI.getOperand(III.ImmOpNo).setImm(Imm); 48525ffd83dbSDimitry Andric 48535ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "With:\n"); 48545ffd83dbSDimitry Andric LLVM_DEBUG(MI.dump()); 48555ffd83dbSDimitry Andric return true; 48565ffd83dbSDimitry Andric } 48575ffd83dbSDimitry Andric 48580b57cec5SDimitry Andric // If an X-Form instruction is fed by an add-immediate and one of its operands 48590b57cec5SDimitry Andric // is the literal zero, attempt to forward the source of the add-immediate to 48600b57cec5SDimitry Andric // the corresponding D-Form instruction with the displacement coming from 48610b57cec5SDimitry Andric // the immediate being added. 48620b57cec5SDimitry Andric bool PPCInstrInfo::transformToImmFormFedByAdd( 48630b57cec5SDimitry Andric MachineInstr &MI, const ImmInstrInfo &III, unsigned OpNoForForwarding, 48640b57cec5SDimitry Andric MachineInstr &DefMI, bool KillDefMI) const { 48650b57cec5SDimitry Andric // RegMO ImmMO 48660b57cec5SDimitry Andric // | | 48670b57cec5SDimitry Andric // x = addi reg, imm <----- DefMI 48680b57cec5SDimitry Andric // y = op 0 , x <----- MI 48690b57cec5SDimitry Andric // | 48700b57cec5SDimitry Andric // OpNoForForwarding 48710b57cec5SDimitry Andric // Check if the MI meet the requirement described in the III. 48720b57cec5SDimitry Andric if (!isUseMIElgibleForForwarding(MI, III, OpNoForForwarding)) 48730b57cec5SDimitry Andric return false; 48740b57cec5SDimitry Andric 48750b57cec5SDimitry Andric // Check if the DefMI meet the requirement 48760b57cec5SDimitry Andric // described in the III. If yes, set the ImmMO and RegMO accordingly. 48770b57cec5SDimitry Andric MachineOperand *ImmMO = nullptr; 48780b57cec5SDimitry Andric MachineOperand *RegMO = nullptr; 48790b57cec5SDimitry Andric if (!isDefMIElgibleForForwarding(DefMI, III, ImmMO, RegMO)) 48800b57cec5SDimitry Andric return false; 48810b57cec5SDimitry Andric assert(ImmMO && RegMO && "Imm and Reg operand must have been set"); 48820b57cec5SDimitry Andric 48830b57cec5SDimitry Andric // As we get the Imm operand now, we need to check if the ImmMO meet 48840b57cec5SDimitry Andric // the requirement described in the III. If yes set the Imm. 48850b57cec5SDimitry Andric int64_t Imm = 0; 48860b57cec5SDimitry Andric if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm)) 48870b57cec5SDimitry Andric return false; 48880b57cec5SDimitry Andric 48890b57cec5SDimitry Andric bool IsFwdFeederRegKilled = false; 4890bdd1243dSDimitry Andric bool SeenIntermediateUse = false; 48910b57cec5SDimitry Andric // Check if the RegMO can be forwarded to MI. 48920b57cec5SDimitry Andric if (!isRegElgibleForForwarding(*RegMO, DefMI, MI, KillDefMI, 4893bdd1243dSDimitry Andric IsFwdFeederRegKilled, SeenIntermediateUse)) 48940b57cec5SDimitry Andric return false; 48950b57cec5SDimitry Andric 48960b57cec5SDimitry Andric MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 48970b57cec5SDimitry Andric bool PostRA = !MRI.isSSA(); 48980b57cec5SDimitry Andric 48990b57cec5SDimitry Andric // We know that, the MI and DefMI both meet the pattern, and 49000b57cec5SDimitry Andric // the Imm also meet the requirement with the new Imm-form. 49010b57cec5SDimitry Andric // It is safe to do the transformation now. 4902bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Replacing indexed instruction:\n"); 49030b57cec5SDimitry Andric LLVM_DEBUG(MI.dump()); 49040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Fed by:\n"); 49050b57cec5SDimitry Andric LLVM_DEBUG(DefMI.dump()); 49060b57cec5SDimitry Andric 49070b57cec5SDimitry Andric // Update the base reg first. 49080b57cec5SDimitry Andric MI.getOperand(III.OpNoForForwarding).ChangeToRegister(RegMO->getReg(), 49090b57cec5SDimitry Andric false, false, 49100b57cec5SDimitry Andric RegMO->isKill()); 49110b57cec5SDimitry Andric 49120b57cec5SDimitry Andric // Then, update the imm. 49130b57cec5SDimitry Andric if (ImmMO->isImm()) { 49140b57cec5SDimitry Andric // If the ImmMO is Imm, change the operand that has ZERO to that Imm 49150b57cec5SDimitry Andric // directly. 49160b57cec5SDimitry Andric replaceInstrOperandWithImm(MI, III.ZeroIsSpecialOrig, Imm); 49170b57cec5SDimitry Andric } 49180b57cec5SDimitry Andric else { 49190b57cec5SDimitry Andric // Otherwise, it is Constant Pool Index(CPI) or Global, 49200b57cec5SDimitry Andric // which is relocation in fact. We need to replace the special zero 49210b57cec5SDimitry Andric // register with ImmMO. 49220b57cec5SDimitry Andric // Before that, we need to fixup the target flags for imm. 49230b57cec5SDimitry Andric // For some reason, we miss to set the flag for the ImmMO if it is CPI. 49240fca6ea1SDimitry Andric if (DefMI.getOpcode() == PPC::ADDItocL8) 49250b57cec5SDimitry Andric ImmMO->setTargetFlags(PPCII::MO_TOC_LO); 49260b57cec5SDimitry Andric 49270b57cec5SDimitry Andric // MI didn't have the interface such as MI.setOperand(i) though 49280b57cec5SDimitry Andric // it has MI.getOperand(i). To repalce the ZERO MachineOperand with 49290b57cec5SDimitry Andric // ImmMO, we need to remove ZERO operand and all the operands behind it, 49300b57cec5SDimitry Andric // and, add the ImmMO, then, move back all the operands behind ZERO. 49310b57cec5SDimitry Andric SmallVector<MachineOperand, 2> MOps; 49320b57cec5SDimitry Andric for (unsigned i = MI.getNumOperands() - 1; i >= III.ZeroIsSpecialOrig; i--) { 49330b57cec5SDimitry Andric MOps.push_back(MI.getOperand(i)); 493481ad6265SDimitry Andric MI.removeOperand(i); 49350b57cec5SDimitry Andric } 49360b57cec5SDimitry Andric 49370b57cec5SDimitry Andric // Remove the last MO in the list, which is ZERO operand in fact. 49380b57cec5SDimitry Andric MOps.pop_back(); 49390b57cec5SDimitry Andric // Add the imm operand. 49400b57cec5SDimitry Andric MI.addOperand(*ImmMO); 49410b57cec5SDimitry Andric // Now add the rest back. 49420b57cec5SDimitry Andric for (auto &MO : MOps) 49430b57cec5SDimitry Andric MI.addOperand(MO); 49440b57cec5SDimitry Andric } 49450b57cec5SDimitry Andric 49460b57cec5SDimitry Andric // Update the opcode. 49470b57cec5SDimitry Andric MI.setDesc(get(III.ImmOpcode)); 49480b57cec5SDimitry Andric 49495f757f3fSDimitry Andric if (PostRA) 49505f757f3fSDimitry Andric recomputeLivenessFlags(*MI.getParent()); 49510b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "With:\n"); 49520b57cec5SDimitry Andric LLVM_DEBUG(MI.dump()); 49530b57cec5SDimitry Andric 49540b57cec5SDimitry Andric return true; 49550b57cec5SDimitry Andric } 49560b57cec5SDimitry Andric 49570b57cec5SDimitry Andric bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI, 49580b57cec5SDimitry Andric const ImmInstrInfo &III, 49590b57cec5SDimitry Andric unsigned ConstantOpNo, 49605ffd83dbSDimitry Andric MachineInstr &DefMI) const { 49615ffd83dbSDimitry Andric // DefMI must be LI or LI8. 49625ffd83dbSDimitry Andric if ((DefMI.getOpcode() != PPC::LI && DefMI.getOpcode() != PPC::LI8) || 49635ffd83dbSDimitry Andric !DefMI.getOperand(1).isImm()) 49645ffd83dbSDimitry Andric return false; 49655ffd83dbSDimitry Andric 49665ffd83dbSDimitry Andric // Get Imm operand and Sign-extend to 64-bits. 49675ffd83dbSDimitry Andric int64_t Imm = SignExtend64<16>(DefMI.getOperand(1).getImm()); 49685ffd83dbSDimitry Andric 49690b57cec5SDimitry Andric MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); 49700b57cec5SDimitry Andric bool PostRA = !MRI.isSSA(); 49710b57cec5SDimitry Andric // Exit early if we can't convert this. 49720b57cec5SDimitry Andric if ((ConstantOpNo != III.OpNoForForwarding) && !III.IsCommutative) 49730b57cec5SDimitry Andric return false; 49740b57cec5SDimitry Andric if (Imm % III.ImmMustBeMultipleOf) 49750b57cec5SDimitry Andric return false; 49760b57cec5SDimitry Andric if (III.TruncateImmTo) 49770b57cec5SDimitry Andric Imm &= ((1 << III.TruncateImmTo) - 1); 49780b57cec5SDimitry Andric if (III.SignedImm) { 49790b57cec5SDimitry Andric APInt ActualValue(64, Imm, true); 49800b57cec5SDimitry Andric if (!ActualValue.isSignedIntN(III.ImmWidth)) 49810b57cec5SDimitry Andric return false; 49820b57cec5SDimitry Andric } else { 49830b57cec5SDimitry Andric uint64_t UnsignedMax = (1 << III.ImmWidth) - 1; 49840b57cec5SDimitry Andric if ((uint64_t)Imm > UnsignedMax) 49850b57cec5SDimitry Andric return false; 49860b57cec5SDimitry Andric } 49870b57cec5SDimitry Andric 49880b57cec5SDimitry Andric // If we're post-RA, the instructions don't agree on whether register zero is 49890b57cec5SDimitry Andric // special, we can transform this as long as the register operand that will 49900b57cec5SDimitry Andric // end up in the location where zero is special isn't R0. 49910b57cec5SDimitry Andric if (PostRA && III.ZeroIsSpecialOrig != III.ZeroIsSpecialNew) { 49920b57cec5SDimitry Andric unsigned PosForOrigZero = III.ZeroIsSpecialOrig ? III.ZeroIsSpecialOrig : 49930b57cec5SDimitry Andric III.ZeroIsSpecialNew + 1; 49948bcb0991SDimitry Andric Register OrigZeroReg = MI.getOperand(PosForOrigZero).getReg(); 49958bcb0991SDimitry Andric Register NewZeroReg = MI.getOperand(III.ZeroIsSpecialNew).getReg(); 49960b57cec5SDimitry Andric // If R0 is in the operand where zero is special for the new instruction, 49970b57cec5SDimitry Andric // it is unsafe to transform if the constant operand isn't that operand. 49980b57cec5SDimitry Andric if ((NewZeroReg == PPC::R0 || NewZeroReg == PPC::X0) && 49990b57cec5SDimitry Andric ConstantOpNo != III.ZeroIsSpecialNew) 50000b57cec5SDimitry Andric return false; 50010b57cec5SDimitry Andric if ((OrigZeroReg == PPC::R0 || OrigZeroReg == PPC::X0) && 50020b57cec5SDimitry Andric ConstantOpNo != PosForOrigZero) 50030b57cec5SDimitry Andric return false; 50040b57cec5SDimitry Andric } 50050b57cec5SDimitry Andric 50060b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 5007480093f4SDimitry Andric bool SpecialShift32 = Opc == PPC::SLW || Opc == PPC::SLW_rec || 5008480093f4SDimitry Andric Opc == PPC::SRW || Opc == PPC::SRW_rec || 5009480093f4SDimitry Andric Opc == PPC::SLW8 || Opc == PPC::SLW8_rec || 5010480093f4SDimitry Andric Opc == PPC::SRW8 || Opc == PPC::SRW8_rec; 5011480093f4SDimitry Andric bool SpecialShift64 = Opc == PPC::SLD || Opc == PPC::SLD_rec || 5012480093f4SDimitry Andric Opc == PPC::SRD || Opc == PPC::SRD_rec; 5013480093f4SDimitry Andric bool SetCR = Opc == PPC::SLW_rec || Opc == PPC::SRW_rec || 5014480093f4SDimitry Andric Opc == PPC::SLD_rec || Opc == PPC::SRD_rec; 5015480093f4SDimitry Andric bool RightShift = Opc == PPC::SRW || Opc == PPC::SRW_rec || Opc == PPC::SRD || 5016480093f4SDimitry Andric Opc == PPC::SRD_rec; 50170b57cec5SDimitry Andric 5018bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Replacing reg+reg instruction: "); 5019bdd1243dSDimitry Andric LLVM_DEBUG(MI.dump()); 5020bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Fed by load-immediate: "); 5021bdd1243dSDimitry Andric LLVM_DEBUG(DefMI.dump()); 50220b57cec5SDimitry Andric MI.setDesc(get(III.ImmOpcode)); 50230b57cec5SDimitry Andric if (ConstantOpNo == III.OpNoForForwarding) { 50240b57cec5SDimitry Andric // Converting shifts to immediate form is a bit tricky since they may do 50250b57cec5SDimitry Andric // one of three things: 50260b57cec5SDimitry Andric // 1. If the shift amount is between OpSize and 2*OpSize, the result is zero 50270b57cec5SDimitry Andric // 2. If the shift amount is zero, the result is unchanged (save for maybe 50280b57cec5SDimitry Andric // setting CR0) 50290b57cec5SDimitry Andric // 3. If the shift amount is in [1, OpSize), it's just a shift 50300b57cec5SDimitry Andric if (SpecialShift32 || SpecialShift64) { 50310b57cec5SDimitry Andric LoadImmediateInfo LII; 50320b57cec5SDimitry Andric LII.Imm = 0; 50330b57cec5SDimitry Andric LII.SetCR = SetCR; 50340b57cec5SDimitry Andric LII.Is64Bit = SpecialShift64; 50350b57cec5SDimitry Andric uint64_t ShAmt = Imm & (SpecialShift32 ? 0x1F : 0x3F); 50360b57cec5SDimitry Andric if (Imm & (SpecialShift32 ? 0x20 : 0x40)) 50370b57cec5SDimitry Andric replaceInstrWithLI(MI, LII); 50380b57cec5SDimitry Andric // Shifts by zero don't change the value. If we don't need to set CR0, 50390b57cec5SDimitry Andric // just convert this to a COPY. Can't do this post-RA since we've already 50400b57cec5SDimitry Andric // cleaned up the copies. 50410b57cec5SDimitry Andric else if (!SetCR && ShAmt == 0 && !PostRA) { 504281ad6265SDimitry Andric MI.removeOperand(2); 50430b57cec5SDimitry Andric MI.setDesc(get(PPC::COPY)); 50440b57cec5SDimitry Andric } else { 50450b57cec5SDimitry Andric // The 32 bit and 64 bit instructions are quite different. 50460b57cec5SDimitry Andric if (SpecialShift32) { 50478bcb0991SDimitry Andric // Left shifts use (N, 0, 31-N). 50488bcb0991SDimitry Andric // Right shifts use (32-N, N, 31) if 0 < N < 32. 50498bcb0991SDimitry Andric // use (0, 0, 31) if N == 0. 50508bcb0991SDimitry Andric uint64_t SH = ShAmt == 0 ? 0 : RightShift ? 32 - ShAmt : ShAmt; 50510b57cec5SDimitry Andric uint64_t MB = RightShift ? ShAmt : 0; 50520b57cec5SDimitry Andric uint64_t ME = RightShift ? 31 : 31 - ShAmt; 50530b57cec5SDimitry Andric replaceInstrOperandWithImm(MI, III.OpNoForForwarding, SH); 50540b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(MB) 50550b57cec5SDimitry Andric .addImm(ME); 50560b57cec5SDimitry Andric } else { 50578bcb0991SDimitry Andric // Left shifts use (N, 63-N). 50588bcb0991SDimitry Andric // Right shifts use (64-N, N) if 0 < N < 64. 50598bcb0991SDimitry Andric // use (0, 0) if N == 0. 50608bcb0991SDimitry Andric uint64_t SH = ShAmt == 0 ? 0 : RightShift ? 64 - ShAmt : ShAmt; 50610b57cec5SDimitry Andric uint64_t ME = RightShift ? ShAmt : 63 - ShAmt; 50620b57cec5SDimitry Andric replaceInstrOperandWithImm(MI, III.OpNoForForwarding, SH); 50630b57cec5SDimitry Andric MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(ME); 50640b57cec5SDimitry Andric } 50650b57cec5SDimitry Andric } 50660b57cec5SDimitry Andric } else 50670b57cec5SDimitry Andric replaceInstrOperandWithImm(MI, ConstantOpNo, Imm); 50680b57cec5SDimitry Andric } 50690b57cec5SDimitry Andric // Convert commutative instructions (switch the operands and convert the 50700b57cec5SDimitry Andric // desired one to an immediate. 50710b57cec5SDimitry Andric else if (III.IsCommutative) { 50720b57cec5SDimitry Andric replaceInstrOperandWithImm(MI, ConstantOpNo, Imm); 50730b57cec5SDimitry Andric swapMIOperands(MI, ConstantOpNo, III.OpNoForForwarding); 50740b57cec5SDimitry Andric } else 50750b57cec5SDimitry Andric llvm_unreachable("Should have exited early!"); 50760b57cec5SDimitry Andric 50770b57cec5SDimitry Andric // For instructions for which the constant register replaces a different 50780b57cec5SDimitry Andric // operand than where the immediate goes, we need to swap them. 50790b57cec5SDimitry Andric if (III.OpNoForForwarding != III.ImmOpNo) 50800b57cec5SDimitry Andric swapMIOperands(MI, III.OpNoForForwarding, III.ImmOpNo); 50810b57cec5SDimitry Andric 50820b57cec5SDimitry Andric // If the special R0/X0 register index are different for original instruction 50830b57cec5SDimitry Andric // and new instruction, we need to fix up the register class in new 50840b57cec5SDimitry Andric // instruction. 50850b57cec5SDimitry Andric if (!PostRA && III.ZeroIsSpecialOrig != III.ZeroIsSpecialNew) { 50860b57cec5SDimitry Andric if (III.ZeroIsSpecialNew) { 50870b57cec5SDimitry Andric // If operand at III.ZeroIsSpecialNew is physical reg(eg: ZERO/ZERO8), no 50880b57cec5SDimitry Andric // need to fix up register class. 50898bcb0991SDimitry Andric Register RegToModify = MI.getOperand(III.ZeroIsSpecialNew).getReg(); 5090bdd1243dSDimitry Andric if (RegToModify.isVirtual()) { 50910b57cec5SDimitry Andric const TargetRegisterClass *NewRC = 50920b57cec5SDimitry Andric MRI.getRegClass(RegToModify)->hasSuperClassEq(&PPC::GPRCRegClass) ? 50930b57cec5SDimitry Andric &PPC::GPRC_and_GPRC_NOR0RegClass : &PPC::G8RC_and_G8RC_NOX0RegClass; 50940b57cec5SDimitry Andric MRI.setRegClass(RegToModify, NewRC); 50950b57cec5SDimitry Andric } 50960b57cec5SDimitry Andric } 50970b57cec5SDimitry Andric } 50980b57cec5SDimitry Andric 50995f757f3fSDimitry Andric if (PostRA) 51005f757f3fSDimitry Andric recomputeLivenessFlags(*MI.getParent()); 5101bdd1243dSDimitry Andric 5102bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "With: "); 5103bdd1243dSDimitry Andric LLVM_DEBUG(MI.dump()); 5104bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 51050b57cec5SDimitry Andric return true; 51060b57cec5SDimitry Andric } 51070b57cec5SDimitry Andric 51080b57cec5SDimitry Andric const TargetRegisterClass * 51090b57cec5SDimitry Andric PPCInstrInfo::updatedRC(const TargetRegisterClass *RC) const { 51100b57cec5SDimitry Andric if (Subtarget.hasVSX() && RC == &PPC::VRRCRegClass) 51110b57cec5SDimitry Andric return &PPC::VSRCRegClass; 51120b57cec5SDimitry Andric return RC; 51130b57cec5SDimitry Andric } 51140b57cec5SDimitry Andric 51150b57cec5SDimitry Andric int PPCInstrInfo::getRecordFormOpcode(unsigned Opcode) { 51160b57cec5SDimitry Andric return PPC::getRecordFormOpcode(Opcode); 51170b57cec5SDimitry Andric } 51180b57cec5SDimitry Andric 5119bdd1243dSDimitry Andric static bool isOpZeroOfSubwordPreincLoad(int Opcode) { 5120bdd1243dSDimitry Andric return (Opcode == PPC::LBZU || Opcode == PPC::LBZUX || Opcode == PPC::LBZU8 || 5121bdd1243dSDimitry Andric Opcode == PPC::LBZUX8 || Opcode == PPC::LHZU || 5122bdd1243dSDimitry Andric Opcode == PPC::LHZUX || Opcode == PPC::LHZU8 || 5123bdd1243dSDimitry Andric Opcode == PPC::LHZUX8); 5124bdd1243dSDimitry Andric } 5125bdd1243dSDimitry Andric 5126bdd1243dSDimitry Andric // This function checks for sign extension from 32 bits to 64 bits. 5127bdd1243dSDimitry Andric static bool definedBySignExtendingOp(const unsigned Reg, 5128bdd1243dSDimitry Andric const MachineRegisterInfo *MRI) { 5129bdd1243dSDimitry Andric if (!Register::isVirtualRegister(Reg)) 5130bdd1243dSDimitry Andric return false; 5131bdd1243dSDimitry Andric 5132bdd1243dSDimitry Andric MachineInstr *MI = MRI->getVRegDef(Reg); 5133bdd1243dSDimitry Andric if (!MI) 5134bdd1243dSDimitry Andric return false; 5135bdd1243dSDimitry Andric 5136bdd1243dSDimitry Andric int Opcode = MI->getOpcode(); 5137bdd1243dSDimitry Andric const PPCInstrInfo *TII = 5138bdd1243dSDimitry Andric MI->getMF()->getSubtarget<PPCSubtarget>().getInstrInfo(); 5139bdd1243dSDimitry Andric if (TII->isSExt32To64(Opcode)) 51400b57cec5SDimitry Andric return true; 51410b57cec5SDimitry Andric 5142bdd1243dSDimitry Andric // The first def of LBZU/LHZU is sign extended. 5143bdd1243dSDimitry Andric if (isOpZeroOfSubwordPreincLoad(Opcode) && MI->getOperand(0).getReg() == Reg) 51440b57cec5SDimitry Andric return true; 51450b57cec5SDimitry Andric 5146bdd1243dSDimitry Andric // RLDICL generates sign-extended output if it clears at least 5147bdd1243dSDimitry Andric // 33 bits from the left (MSB). 5148bdd1243dSDimitry Andric if (Opcode == PPC::RLDICL && MI->getOperand(3).getImm() >= 33) 5149bdd1243dSDimitry Andric return true; 5150bdd1243dSDimitry Andric 5151bdd1243dSDimitry Andric // If at least one bit from left in a lower word is masked out, 5152bdd1243dSDimitry Andric // all of 0 to 32-th bits of the output are cleared. 5153bdd1243dSDimitry Andric // Hence the output is already sign extended. 5154480093f4SDimitry Andric if ((Opcode == PPC::RLWINM || Opcode == PPC::RLWINM_rec || 5155480093f4SDimitry Andric Opcode == PPC::RLWNM || Opcode == PPC::RLWNM_rec) && 5156bdd1243dSDimitry Andric MI->getOperand(3).getImm() > 0 && 5157bdd1243dSDimitry Andric MI->getOperand(3).getImm() <= MI->getOperand(4).getImm()) 51580b57cec5SDimitry Andric return true; 51590b57cec5SDimitry Andric 5160bdd1243dSDimitry Andric // If the most significant bit of immediate in ANDIS is zero, 5161bdd1243dSDimitry Andric // all of 0 to 32-th bits are cleared. 5162bdd1243dSDimitry Andric if (Opcode == PPC::ANDIS_rec || Opcode == PPC::ANDIS8_rec) { 5163bdd1243dSDimitry Andric uint16_t Imm = MI->getOperand(2).getImm(); 5164bdd1243dSDimitry Andric if ((Imm & 0x8000) == 0) 5165bdd1243dSDimitry Andric return true; 5166bdd1243dSDimitry Andric } 5167bdd1243dSDimitry Andric 51680b57cec5SDimitry Andric return false; 51690b57cec5SDimitry Andric } 51700b57cec5SDimitry Andric 5171bdd1243dSDimitry Andric // This function checks the machine instruction that defines the input register 5172bdd1243dSDimitry Andric // Reg. If that machine instruction always outputs a value that has only zeros 5173bdd1243dSDimitry Andric // in the higher 32 bits then this function will return true. 5174bdd1243dSDimitry Andric static bool definedByZeroExtendingOp(const unsigned Reg, 5175bdd1243dSDimitry Andric const MachineRegisterInfo *MRI) { 5176bdd1243dSDimitry Andric if (!Register::isVirtualRegister(Reg)) 5177bdd1243dSDimitry Andric return false; 5178bdd1243dSDimitry Andric 5179bdd1243dSDimitry Andric MachineInstr *MI = MRI->getVRegDef(Reg); 5180bdd1243dSDimitry Andric if (!MI) 5181bdd1243dSDimitry Andric return false; 5182bdd1243dSDimitry Andric 5183bdd1243dSDimitry Andric int Opcode = MI->getOpcode(); 5184bdd1243dSDimitry Andric const PPCInstrInfo *TII = 5185bdd1243dSDimitry Andric MI->getMF()->getSubtarget<PPCSubtarget>().getInstrInfo(); 5186bdd1243dSDimitry Andric if (TII->isZExt32To64(Opcode)) 5187bdd1243dSDimitry Andric return true; 5188bdd1243dSDimitry Andric 5189bdd1243dSDimitry Andric // The first def of LBZU/LHZU/LWZU are zero extended. 5190bdd1243dSDimitry Andric if ((isOpZeroOfSubwordPreincLoad(Opcode) || Opcode == PPC::LWZU || 5191bdd1243dSDimitry Andric Opcode == PPC::LWZUX || Opcode == PPC::LWZU8 || Opcode == PPC::LWZUX8) && 5192bdd1243dSDimitry Andric MI->getOperand(0).getReg() == Reg) 5193bdd1243dSDimitry Andric return true; 5194bdd1243dSDimitry Andric 51950b57cec5SDimitry Andric // The 16-bit immediate is sign-extended in li/lis. 51960b57cec5SDimitry Andric // If the most significant bit is zero, all higher bits are zero. 51970b57cec5SDimitry Andric if (Opcode == PPC::LI || Opcode == PPC::LI8 || 51980b57cec5SDimitry Andric Opcode == PPC::LIS || Opcode == PPC::LIS8) { 5199bdd1243dSDimitry Andric int64_t Imm = MI->getOperand(1).getImm(); 52000b57cec5SDimitry Andric if (((uint64_t)Imm & ~0x7FFFuLL) == 0) 52010b57cec5SDimitry Andric return true; 52020b57cec5SDimitry Andric } 52030b57cec5SDimitry Andric 52040b57cec5SDimitry Andric // We have some variations of rotate-and-mask instructions 52050b57cec5SDimitry Andric // that clear higher 32-bits. 5206480093f4SDimitry Andric if ((Opcode == PPC::RLDICL || Opcode == PPC::RLDICL_rec || 5207480093f4SDimitry Andric Opcode == PPC::RLDCL || Opcode == PPC::RLDCL_rec || 52080b57cec5SDimitry Andric Opcode == PPC::RLDICL_32_64) && 5209bdd1243dSDimitry Andric MI->getOperand(3).getImm() >= 32) 52100b57cec5SDimitry Andric return true; 52110b57cec5SDimitry Andric 5212480093f4SDimitry Andric if ((Opcode == PPC::RLDIC || Opcode == PPC::RLDIC_rec) && 5213bdd1243dSDimitry Andric MI->getOperand(3).getImm() >= 32 && 5214bdd1243dSDimitry Andric MI->getOperand(3).getImm() <= 63 - MI->getOperand(2).getImm()) 52150b57cec5SDimitry Andric return true; 52160b57cec5SDimitry Andric 5217480093f4SDimitry Andric if ((Opcode == PPC::RLWINM || Opcode == PPC::RLWINM_rec || 5218480093f4SDimitry Andric Opcode == PPC::RLWNM || Opcode == PPC::RLWNM_rec || 52190b57cec5SDimitry Andric Opcode == PPC::RLWINM8 || Opcode == PPC::RLWNM8) && 5220bdd1243dSDimitry Andric MI->getOperand(3).getImm() <= MI->getOperand(4).getImm()) 52210b57cec5SDimitry Andric return true; 52220b57cec5SDimitry Andric 52230b57cec5SDimitry Andric return false; 52240b57cec5SDimitry Andric } 52250b57cec5SDimitry Andric 52260b57cec5SDimitry Andric // This function returns true if the input MachineInstr is a TOC save 52270b57cec5SDimitry Andric // instruction. 52280b57cec5SDimitry Andric bool PPCInstrInfo::isTOCSaveMI(const MachineInstr &MI) const { 52290b57cec5SDimitry Andric if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isReg()) 52300b57cec5SDimitry Andric return false; 52310b57cec5SDimitry Andric unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset(); 52320b57cec5SDimitry Andric unsigned StackOffset = MI.getOperand(1).getImm(); 52338bcb0991SDimitry Andric Register StackReg = MI.getOperand(2).getReg(); 5234fe6060f1SDimitry Andric Register SPReg = Subtarget.isPPC64() ? PPC::X1 : PPC::R1; 5235fe6060f1SDimitry Andric if (StackReg == SPReg && StackOffset == TOCSaveOffset) 52360b57cec5SDimitry Andric return true; 52370b57cec5SDimitry Andric 52380b57cec5SDimitry Andric return false; 52390b57cec5SDimitry Andric } 52400b57cec5SDimitry Andric 52410b57cec5SDimitry Andric // We limit the max depth to track incoming values of PHIs or binary ops 52420b57cec5SDimitry Andric // (e.g. AND) to avoid excessive cost. 5243bdd1243dSDimitry Andric const unsigned MAX_BINOP_DEPTH = 1; 5244bdd1243dSDimitry Andric // The isSignOrZeroExtended function is recursive. The parameter BinOpDepth 5245bdd1243dSDimitry Andric // does not count all of the recursions. The parameter BinOpDepth is incremented 5246bdd1243dSDimitry Andric // only when isSignOrZeroExtended calls itself more than once. This is done to 5247bdd1243dSDimitry Andric // prevent expontential recursion. There is no parameter to track linear 5248bdd1243dSDimitry Andric // recursion. 5249bdd1243dSDimitry Andric std::pair<bool, bool> 5250bdd1243dSDimitry Andric PPCInstrInfo::isSignOrZeroExtended(const unsigned Reg, 5251bdd1243dSDimitry Andric const unsigned BinOpDepth, 5252bdd1243dSDimitry Andric const MachineRegisterInfo *MRI) const { 5253bdd1243dSDimitry Andric if (!Register::isVirtualRegister(Reg)) 5254bdd1243dSDimitry Andric return std::pair<bool, bool>(false, false); 52550b57cec5SDimitry Andric 5256bdd1243dSDimitry Andric MachineInstr *MI = MRI->getVRegDef(Reg); 5257bdd1243dSDimitry Andric if (!MI) 5258bdd1243dSDimitry Andric return std::pair<bool, bool>(false, false); 52590b57cec5SDimitry Andric 5260bdd1243dSDimitry Andric bool IsSExt = definedBySignExtendingOp(Reg, MRI); 5261bdd1243dSDimitry Andric bool IsZExt = definedByZeroExtendingOp(Reg, MRI); 52620b57cec5SDimitry Andric 5263bdd1243dSDimitry Andric // If we know the instruction always returns sign- and zero-extended result, 5264bdd1243dSDimitry Andric // return here. 5265bdd1243dSDimitry Andric if (IsSExt && IsZExt) 5266bdd1243dSDimitry Andric return std::pair<bool, bool>(IsSExt, IsZExt); 5267bdd1243dSDimitry Andric 5268bdd1243dSDimitry Andric switch (MI->getOpcode()) { 52690b57cec5SDimitry Andric case PPC::COPY: { 5270bdd1243dSDimitry Andric Register SrcReg = MI->getOperand(1).getReg(); 52710b57cec5SDimitry Andric 52720b57cec5SDimitry Andric // In both ELFv1 and v2 ABI, method parameters and the return value 52730b57cec5SDimitry Andric // are sign- or zero-extended. 5274bdd1243dSDimitry Andric const MachineFunction *MF = MI->getMF(); 5275bdd1243dSDimitry Andric 5276bdd1243dSDimitry Andric if (!MF->getSubtarget<PPCSubtarget>().isSVR4ABI()) { 5277bdd1243dSDimitry Andric // If this is a copy from another register, we recursively check source. 5278bdd1243dSDimitry Andric auto SrcExt = isSignOrZeroExtended(SrcReg, BinOpDepth, MRI); 5279bdd1243dSDimitry Andric return std::pair<bool, bool>(SrcExt.first || IsSExt, 5280bdd1243dSDimitry Andric SrcExt.second || IsZExt); 5281bdd1243dSDimitry Andric } 5282bdd1243dSDimitry Andric 5283bdd1243dSDimitry Andric // From here on everything is SVR4ABI 52840b57cec5SDimitry Andric const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>(); 52850b57cec5SDimitry Andric // We check the ZExt/SExt flags for a method parameter. 5286bdd1243dSDimitry Andric if (MI->getParent()->getBasicBlock() == 52870b57cec5SDimitry Andric &MF->getFunction().getEntryBlock()) { 5288bdd1243dSDimitry Andric Register VReg = MI->getOperand(0).getReg(); 5289bdd1243dSDimitry Andric if (MF->getRegInfo().isLiveIn(VReg)) { 5290bdd1243dSDimitry Andric IsSExt |= FuncInfo->isLiveInSExt(VReg); 5291bdd1243dSDimitry Andric IsZExt |= FuncInfo->isLiveInZExt(VReg); 5292bdd1243dSDimitry Andric return std::pair<bool, bool>(IsSExt, IsZExt); 5293bdd1243dSDimitry Andric } 5294bdd1243dSDimitry Andric } 5295bdd1243dSDimitry Andric 5296bdd1243dSDimitry Andric if (SrcReg != PPC::X3) { 5297bdd1243dSDimitry Andric // If this is a copy from another register, we recursively check source. 5298bdd1243dSDimitry Andric auto SrcExt = isSignOrZeroExtended(SrcReg, BinOpDepth, MRI); 5299bdd1243dSDimitry Andric return std::pair<bool, bool>(SrcExt.first || IsSExt, 5300bdd1243dSDimitry Andric SrcExt.second || IsZExt); 53010b57cec5SDimitry Andric } 53020b57cec5SDimitry Andric 53030b57cec5SDimitry Andric // For a method return value, we check the ZExt/SExt flags in attribute. 53040b57cec5SDimitry Andric // We assume the following code sequence for method call. 53050b57cec5SDimitry Andric // ADJCALLSTACKDOWN 32, implicit dead %r1, implicit %r1 53060b57cec5SDimitry Andric // BL8_NOP @func,... 53070b57cec5SDimitry Andric // ADJCALLSTACKUP 32, 0, implicit dead %r1, implicit %r1 53080b57cec5SDimitry Andric // %5 = COPY %x3; G8RC:%5 5309bdd1243dSDimitry Andric const MachineBasicBlock *MBB = MI->getParent(); 5310bdd1243dSDimitry Andric std::pair<bool, bool> IsExtendPair = std::pair<bool, bool>(IsSExt, IsZExt); 53110b57cec5SDimitry Andric MachineBasicBlock::const_instr_iterator II = 5312bdd1243dSDimitry Andric MachineBasicBlock::const_instr_iterator(MI); 5313bdd1243dSDimitry Andric if (II == MBB->instr_begin() || (--II)->getOpcode() != PPC::ADJCALLSTACKUP) 5314bdd1243dSDimitry Andric return IsExtendPair; 5315bdd1243dSDimitry Andric 53160b57cec5SDimitry Andric const MachineInstr &CallMI = *(--II); 5317bdd1243dSDimitry Andric if (!CallMI.isCall() || !CallMI.getOperand(0).isGlobal()) 5318bdd1243dSDimitry Andric return IsExtendPair; 5319bdd1243dSDimitry Andric 53200b57cec5SDimitry Andric const Function *CalleeFn = 5321bdd1243dSDimitry Andric dyn_cast_if_present<Function>(CallMI.getOperand(0).getGlobal()); 53220b57cec5SDimitry Andric if (!CalleeFn) 5323bdd1243dSDimitry Andric return IsExtendPair; 5324bdd1243dSDimitry Andric const IntegerType *IntTy = dyn_cast<IntegerType>(CalleeFn->getReturnType()); 5325bdd1243dSDimitry Andric if (IntTy && IntTy->getBitWidth() <= 32) { 5326349cc55cSDimitry Andric const AttributeSet &Attrs = CalleeFn->getAttributes().getRetAttrs(); 5327bdd1243dSDimitry Andric IsSExt |= Attrs.hasAttribute(Attribute::SExt); 5328bdd1243dSDimitry Andric IsZExt |= Attrs.hasAttribute(Attribute::ZExt); 5329bdd1243dSDimitry Andric return std::pair<bool, bool>(IsSExt, IsZExt); 53300b57cec5SDimitry Andric } 53310b57cec5SDimitry Andric 5332bdd1243dSDimitry Andric return IsExtendPair; 53330b57cec5SDimitry Andric } 53340b57cec5SDimitry Andric 5335bdd1243dSDimitry Andric // OR, XOR with 16-bit immediate does not change the upper 48 bits. 53360b57cec5SDimitry Andric // So, we track the operand register as we do for register copy. 5337bdd1243dSDimitry Andric case PPC::ORI: 5338bdd1243dSDimitry Andric case PPC::XORI: 5339bdd1243dSDimitry Andric case PPC::ORI8: 5340bdd1243dSDimitry Andric case PPC::XORI8: { 5341bdd1243dSDimitry Andric Register SrcReg = MI->getOperand(1).getReg(); 5342bdd1243dSDimitry Andric auto SrcExt = isSignOrZeroExtended(SrcReg, BinOpDepth, MRI); 5343bdd1243dSDimitry Andric return std::pair<bool, bool>(SrcExt.first || IsSExt, 5344bdd1243dSDimitry Andric SrcExt.second || IsZExt); 5345bdd1243dSDimitry Andric } 53460b57cec5SDimitry Andric 5347bdd1243dSDimitry Andric // OR, XOR with shifted 16-bit immediate does not change the upper 5348bdd1243dSDimitry Andric // 32 bits. So, we track the operand register for zero extension. 5349bdd1243dSDimitry Andric // For sign extension when the MSB of the immediate is zero, we also 5350bdd1243dSDimitry Andric // track the operand register since the upper 33 bits are unchanged. 5351bdd1243dSDimitry Andric case PPC::ORIS: 5352bdd1243dSDimitry Andric case PPC::XORIS: 5353bdd1243dSDimitry Andric case PPC::ORIS8: 5354bdd1243dSDimitry Andric case PPC::XORIS8: { 5355bdd1243dSDimitry Andric Register SrcReg = MI->getOperand(1).getReg(); 5356bdd1243dSDimitry Andric auto SrcExt = isSignOrZeroExtended(SrcReg, BinOpDepth, MRI); 5357bdd1243dSDimitry Andric uint16_t Imm = MI->getOperand(2).getImm(); 5358bdd1243dSDimitry Andric if (Imm & 0x8000) 5359bdd1243dSDimitry Andric return std::pair<bool, bool>(false, SrcExt.second || IsZExt); 5360bdd1243dSDimitry Andric else 5361bdd1243dSDimitry Andric return std::pair<bool, bool>(SrcExt.first || IsSExt, 5362bdd1243dSDimitry Andric SrcExt.second || IsZExt); 53630b57cec5SDimitry Andric } 53640b57cec5SDimitry Andric 53650b57cec5SDimitry Andric // If all incoming values are sign-/zero-extended, 53660b57cec5SDimitry Andric // the output of OR, ISEL or PHI is also sign-/zero-extended. 53670b57cec5SDimitry Andric case PPC::OR: 53680b57cec5SDimitry Andric case PPC::OR8: 53690b57cec5SDimitry Andric case PPC::ISEL: 53700b57cec5SDimitry Andric case PPC::PHI: { 5371bdd1243dSDimitry Andric if (BinOpDepth >= MAX_BINOP_DEPTH) 5372bdd1243dSDimitry Andric return std::pair<bool, bool>(false, false); 53730b57cec5SDimitry Andric 53740b57cec5SDimitry Andric // The input registers for PHI are operand 1, 3, ... 53750b57cec5SDimitry Andric // The input registers for others are operand 1 and 2. 5376bdd1243dSDimitry Andric unsigned OperandEnd = 3, OperandStride = 1; 5377bdd1243dSDimitry Andric if (MI->getOpcode() == PPC::PHI) { 5378bdd1243dSDimitry Andric OperandEnd = MI->getNumOperands(); 5379bdd1243dSDimitry Andric OperandStride = 2; 53800b57cec5SDimitry Andric } 53810b57cec5SDimitry Andric 5382bdd1243dSDimitry Andric IsSExt = true; 5383bdd1243dSDimitry Andric IsZExt = true; 5384bdd1243dSDimitry Andric for (unsigned I = 1; I != OperandEnd; I += OperandStride) { 5385bdd1243dSDimitry Andric if (!MI->getOperand(I).isReg()) 5386bdd1243dSDimitry Andric return std::pair<bool, bool>(false, false); 5387bdd1243dSDimitry Andric 5388bdd1243dSDimitry Andric Register SrcReg = MI->getOperand(I).getReg(); 5389bdd1243dSDimitry Andric auto SrcExt = isSignOrZeroExtended(SrcReg, BinOpDepth + 1, MRI); 5390bdd1243dSDimitry Andric IsSExt &= SrcExt.first; 5391bdd1243dSDimitry Andric IsZExt &= SrcExt.second; 53920b57cec5SDimitry Andric } 5393bdd1243dSDimitry Andric return std::pair<bool, bool>(IsSExt, IsZExt); 53940b57cec5SDimitry Andric } 53950b57cec5SDimitry Andric 53960b57cec5SDimitry Andric // If at least one of the incoming values of an AND is zero extended 53970b57cec5SDimitry Andric // then the output is also zero-extended. If both of the incoming values 53980b57cec5SDimitry Andric // are sign-extended then the output is also sign extended. 53990b57cec5SDimitry Andric case PPC::AND: 54000b57cec5SDimitry Andric case PPC::AND8: { 5401bdd1243dSDimitry Andric if (BinOpDepth >= MAX_BINOP_DEPTH) 5402bdd1243dSDimitry Andric return std::pair<bool, bool>(false, false); 54030b57cec5SDimitry Andric 5404bdd1243dSDimitry Andric Register SrcReg1 = MI->getOperand(1).getReg(); 5405bdd1243dSDimitry Andric Register SrcReg2 = MI->getOperand(2).getReg(); 5406bdd1243dSDimitry Andric auto Src1Ext = isSignOrZeroExtended(SrcReg1, BinOpDepth + 1, MRI); 5407bdd1243dSDimitry Andric auto Src2Ext = isSignOrZeroExtended(SrcReg2, BinOpDepth + 1, MRI); 5408bdd1243dSDimitry Andric return std::pair<bool, bool>(Src1Ext.first && Src2Ext.first, 5409bdd1243dSDimitry Andric Src1Ext.second || Src2Ext.second); 54100b57cec5SDimitry Andric } 54110b57cec5SDimitry Andric 54120b57cec5SDimitry Andric default: 54130b57cec5SDimitry Andric break; 54140b57cec5SDimitry Andric } 5415bdd1243dSDimitry Andric return std::pair<bool, bool>(IsSExt, IsZExt); 54160b57cec5SDimitry Andric } 54170b57cec5SDimitry Andric 54180b57cec5SDimitry Andric bool PPCInstrInfo::isBDNZ(unsigned Opcode) const { 54190b57cec5SDimitry Andric return (Opcode == (Subtarget.isPPC64() ? PPC::BDNZ8 : PPC::BDNZ)); 54200b57cec5SDimitry Andric } 54210b57cec5SDimitry Andric 54228bcb0991SDimitry Andric namespace { 54238bcb0991SDimitry Andric class PPCPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo { 54248bcb0991SDimitry Andric MachineInstr *Loop, *EndLoop, *LoopCount; 54258bcb0991SDimitry Andric MachineFunction *MF; 54268bcb0991SDimitry Andric const TargetInstrInfo *TII; 54278bcb0991SDimitry Andric int64_t TripCount; 54288bcb0991SDimitry Andric 54298bcb0991SDimitry Andric public: 54308bcb0991SDimitry Andric PPCPipelinerLoopInfo(MachineInstr *Loop, MachineInstr *EndLoop, 54318bcb0991SDimitry Andric MachineInstr *LoopCount) 54328bcb0991SDimitry Andric : Loop(Loop), EndLoop(EndLoop), LoopCount(LoopCount), 54338bcb0991SDimitry Andric MF(Loop->getParent()->getParent()), 54348bcb0991SDimitry Andric TII(MF->getSubtarget().getInstrInfo()) { 54358bcb0991SDimitry Andric // Inspect the Loop instruction up-front, as it may be deleted when we call 54368bcb0991SDimitry Andric // createTripCountGreaterCondition. 54378bcb0991SDimitry Andric if (LoopCount->getOpcode() == PPC::LI8 || LoopCount->getOpcode() == PPC::LI) 54388bcb0991SDimitry Andric TripCount = LoopCount->getOperand(1).getImm(); 54398bcb0991SDimitry Andric else 54408bcb0991SDimitry Andric TripCount = -1; 54410b57cec5SDimitry Andric } 54420b57cec5SDimitry Andric 54438bcb0991SDimitry Andric bool shouldIgnoreForPipelining(const MachineInstr *MI) const override { 54448bcb0991SDimitry Andric // Only ignore the terminator. 54458bcb0991SDimitry Andric return MI == EndLoop; 54468bcb0991SDimitry Andric } 54478bcb0991SDimitry Andric 5448bdd1243dSDimitry Andric std::optional<bool> createTripCountGreaterCondition( 5449bdd1243dSDimitry Andric int TC, MachineBasicBlock &MBB, 54508bcb0991SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) override { 54518bcb0991SDimitry Andric if (TripCount == -1) { 54528bcb0991SDimitry Andric // Since BDZ/BDZ8 that we will insert will also decrease the ctr by 1, 54538bcb0991SDimitry Andric // so we don't need to generate any thing here. 54548bcb0991SDimitry Andric Cond.push_back(MachineOperand::CreateImm(0)); 54558bcb0991SDimitry Andric Cond.push_back(MachineOperand::CreateReg( 54568bcb0991SDimitry Andric MF->getSubtarget<PPCSubtarget>().isPPC64() ? PPC::CTR8 : PPC::CTR, 54578bcb0991SDimitry Andric true)); 54588bcb0991SDimitry Andric return {}; 54598bcb0991SDimitry Andric } 54608bcb0991SDimitry Andric 54618bcb0991SDimitry Andric return TripCount > TC; 54628bcb0991SDimitry Andric } 54638bcb0991SDimitry Andric 54648bcb0991SDimitry Andric void setPreheader(MachineBasicBlock *NewPreheader) override { 54658bcb0991SDimitry Andric // Do nothing. We want the LOOP setup instruction to stay in the *old* 54668bcb0991SDimitry Andric // preheader, so we can use BDZ in the prologs to adapt the loop trip count. 54678bcb0991SDimitry Andric } 54688bcb0991SDimitry Andric 54698bcb0991SDimitry Andric void adjustTripCount(int TripCountAdjust) override { 54708bcb0991SDimitry Andric // If the loop trip count is a compile-time value, then just change the 54718bcb0991SDimitry Andric // value. 54728bcb0991SDimitry Andric if (LoopCount->getOpcode() == PPC::LI8 || 54738bcb0991SDimitry Andric LoopCount->getOpcode() == PPC::LI) { 54748bcb0991SDimitry Andric int64_t TripCount = LoopCount->getOperand(1).getImm() + TripCountAdjust; 54758bcb0991SDimitry Andric LoopCount->getOperand(1).setImm(TripCount); 54768bcb0991SDimitry Andric return; 54778bcb0991SDimitry Andric } 54788bcb0991SDimitry Andric 54798bcb0991SDimitry Andric // Since BDZ/BDZ8 that we will insert will also decrease the ctr by 1, 54808bcb0991SDimitry Andric // so we don't need to generate any thing here. 54818bcb0991SDimitry Andric } 54828bcb0991SDimitry Andric 54838bcb0991SDimitry Andric void disposed() override { 54848bcb0991SDimitry Andric Loop->eraseFromParent(); 54858bcb0991SDimitry Andric // Ensure the loop setup instruction is deleted too. 54868bcb0991SDimitry Andric LoopCount->eraseFromParent(); 54878bcb0991SDimitry Andric } 54888bcb0991SDimitry Andric }; 54898bcb0991SDimitry Andric } // namespace 54908bcb0991SDimitry Andric 54918bcb0991SDimitry Andric std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo> 54928bcb0991SDimitry Andric PPCInstrInfo::analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const { 54938bcb0991SDimitry Andric // We really "analyze" only hardware loops right now. 54948bcb0991SDimitry Andric MachineBasicBlock::iterator I = LoopBB->getFirstTerminator(); 54958bcb0991SDimitry Andric MachineBasicBlock *Preheader = *LoopBB->pred_begin(); 54968bcb0991SDimitry Andric if (Preheader == LoopBB) 54978bcb0991SDimitry Andric Preheader = *std::next(LoopBB->pred_begin()); 54988bcb0991SDimitry Andric MachineFunction *MF = Preheader->getParent(); 54998bcb0991SDimitry Andric 55008bcb0991SDimitry Andric if (I != LoopBB->end() && isBDNZ(I->getOpcode())) { 55018bcb0991SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> Visited; 55028bcb0991SDimitry Andric if (MachineInstr *LoopInst = findLoopInstr(*Preheader, Visited)) { 55038bcb0991SDimitry Andric Register LoopCountReg = LoopInst->getOperand(0).getReg(); 55048bcb0991SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 55058bcb0991SDimitry Andric MachineInstr *LoopCount = MRI.getUniqueVRegDef(LoopCountReg); 55068bcb0991SDimitry Andric return std::make_unique<PPCPipelinerLoopInfo>(LoopInst, &*I, LoopCount); 55078bcb0991SDimitry Andric } 55088bcb0991SDimitry Andric } 55098bcb0991SDimitry Andric return nullptr; 55108bcb0991SDimitry Andric } 55118bcb0991SDimitry Andric 55128bcb0991SDimitry Andric MachineInstr *PPCInstrInfo::findLoopInstr( 55138bcb0991SDimitry Andric MachineBasicBlock &PreHeader, 55148bcb0991SDimitry Andric SmallPtrSet<MachineBasicBlock *, 8> &Visited) const { 55150b57cec5SDimitry Andric 55160b57cec5SDimitry Andric unsigned LOOPi = (Subtarget.isPPC64() ? PPC::MTCTR8loop : PPC::MTCTRloop); 55170b57cec5SDimitry Andric 55180b57cec5SDimitry Andric // The loop set-up instruction should be in preheader 55190b57cec5SDimitry Andric for (auto &I : PreHeader.instrs()) 55200b57cec5SDimitry Andric if (I.getOpcode() == LOOPi) 55210b57cec5SDimitry Andric return &I; 55220b57cec5SDimitry Andric return nullptr; 55230b57cec5SDimitry Andric } 55240b57cec5SDimitry Andric 55250b57cec5SDimitry Andric // Return true if get the base operand, byte offset of an instruction and the 55260b57cec5SDimitry Andric // memory width. Width is the size of memory that is being loaded/stored. 55270b57cec5SDimitry Andric bool PPCInstrInfo::getMemOperandWithOffsetWidth( 5528480093f4SDimitry Andric const MachineInstr &LdSt, const MachineOperand *&BaseReg, int64_t &Offset, 55290fca6ea1SDimitry Andric LocationSize &Width, const TargetRegisterInfo *TRI) const { 5530e8d8bef9SDimitry Andric if (!LdSt.mayLoadOrStore() || LdSt.getNumExplicitOperands() != 3) 5531480093f4SDimitry Andric return false; 55320b57cec5SDimitry Andric 55330b57cec5SDimitry Andric // Handle only loads/stores with base register followed by immediate offset. 5534e8d8bef9SDimitry Andric if (!LdSt.getOperand(1).isImm() || 5535e8d8bef9SDimitry Andric (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI())) 55360b57cec5SDimitry Andric return false; 5537e8d8bef9SDimitry Andric if (!LdSt.getOperand(1).isImm() || 5538e8d8bef9SDimitry Andric (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI())) 55390b57cec5SDimitry Andric return false; 55400b57cec5SDimitry Andric 55410b57cec5SDimitry Andric if (!LdSt.hasOneMemOperand()) 55420b57cec5SDimitry Andric return false; 55430b57cec5SDimitry Andric 55440b57cec5SDimitry Andric Width = (*LdSt.memoperands_begin())->getSize(); 55450b57cec5SDimitry Andric Offset = LdSt.getOperand(1).getImm(); 55460b57cec5SDimitry Andric BaseReg = &LdSt.getOperand(2); 55470b57cec5SDimitry Andric return true; 55480b57cec5SDimitry Andric } 55490b57cec5SDimitry Andric 55500b57cec5SDimitry Andric bool PPCInstrInfo::areMemAccessesTriviallyDisjoint( 55518bcb0991SDimitry Andric const MachineInstr &MIa, const MachineInstr &MIb) const { 55520b57cec5SDimitry Andric assert(MIa.mayLoadOrStore() && "MIa must be a load or store."); 55530b57cec5SDimitry Andric assert(MIb.mayLoadOrStore() && "MIb must be a load or store."); 55540b57cec5SDimitry Andric 55550b57cec5SDimitry Andric if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() || 55560b57cec5SDimitry Andric MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef()) 55570b57cec5SDimitry Andric return false; 55580b57cec5SDimitry Andric 55590b57cec5SDimitry Andric // Retrieve the base register, offset from the base register and width. Width 55600b57cec5SDimitry Andric // is the size of memory that is being loaded/stored (e.g. 1, 2, 4). If 55610b57cec5SDimitry Andric // base registers are identical, and the offset of a lower memory access + 55620b57cec5SDimitry Andric // the width doesn't overlap the offset of a higher memory access, 55630b57cec5SDimitry Andric // then the memory accesses are different. 55640b57cec5SDimitry Andric const TargetRegisterInfo *TRI = &getRegisterInfo(); 55650b57cec5SDimitry Andric const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr; 55660b57cec5SDimitry Andric int64_t OffsetA = 0, OffsetB = 0; 55670fca6ea1SDimitry Andric LocationSize WidthA = 0, WidthB = 0; 55680b57cec5SDimitry Andric if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, WidthA, TRI) && 55690b57cec5SDimitry Andric getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, WidthB, TRI)) { 55700b57cec5SDimitry Andric if (BaseOpA->isIdenticalTo(*BaseOpB)) { 55710b57cec5SDimitry Andric int LowOffset = std::min(OffsetA, OffsetB); 55720b57cec5SDimitry Andric int HighOffset = std::max(OffsetA, OffsetB); 55730fca6ea1SDimitry Andric LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB; 55740fca6ea1SDimitry Andric if (LowWidth.hasValue() && 55750fca6ea1SDimitry Andric LowOffset + (int)LowWidth.getValue() <= HighOffset) 55760b57cec5SDimitry Andric return true; 55770b57cec5SDimitry Andric } 55780b57cec5SDimitry Andric } 55790b57cec5SDimitry Andric return false; 55800b57cec5SDimitry Andric } 5581