Index: lib/Target/PowerPC/PPC.h =================================================================== --- lib/Target/PowerPC/PPC.h +++ lib/Target/PowerPC/PPC.h @@ -59,6 +59,7 @@ void initializePPCBoolRetToIntPass(PassRegistry&); void initializePPCExpandISELPass(PassRegistry &); void initializePPCTLSDynamicCallPass(PassRegistry &); + void initializePPCMIPeepholePass(PassRegistry&); extern char &PPCVSXFMAMutateID; namespace PPCII { Index: lib/Target/PowerPC/PPCInstrInfo.h =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.h +++ lib/Target/PowerPC/PPCInstrInfo.h @@ -293,6 +293,16 @@ } const TargetRegisterClass *updatedRC(const TargetRegisterClass *RC) const; static int getRecordFormOpcode(unsigned Opcode); + + bool convertToImmediateForm(MachineInstr &MI) const; + + // This is used to find the "true" source register for n + // Machine instruction. Returns the original SrcReg unless it is the target + // of a copy-like operation, in which case we chain backwards through all + // such operations to the ultimate source register. If a + // physical register is encountered, we stop the search. + static unsigned lookThruCopyLike(unsigned SrcReg, + const MachineRegisterInfo *MRI); }; } Index: lib/Target/PowerPC/PPCInstrInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.cpp +++ lib/Target/PowerPC/PPCInstrInfo.cpp @@ -51,6 +51,10 @@ STATISTIC(NumStoreSPILLVSRRCAsGpr, "Number of spillvsrrc spilled to stack as gpr"); STATISTIC(NumGPRtoVSRSpill, "Number of gpr spills to spillvsrrc"); +STATISTIC(CmpIselsConverted, + "Number of ISELs that depend on comparison of constants converted"); +STATISTIC(MissedConvertibleImmediateInstrs, + "Number of compare-immediate instructions fed by constants"); static cl:: opt DisableCTRLoopAnal("disable-ppc-ctrloop-analysis", cl::Hidden, @@ -2093,6 +2097,411 @@ return false; } +unsigned PPCInstrInfo::lookThruCopyLike(unsigned SrcReg, + const MachineRegisterInfo *MRI) { + while (true) { + MachineInstr *MI = MRI->getVRegDef(SrcReg); + if (!MI->isCopyLike()) + return SrcReg; + + unsigned CopySrcReg; + if (MI->isCopy()) + CopySrcReg = MI->getOperand(1).getReg(); + else { + assert(MI->isSubregToReg() && "Bad opcode for lookThruCopyLike"); + CopySrcReg = MI->getOperand(2).getReg(); + } + + if (!TargetRegisterInfo::isVirtualRegister(CopySrcReg)) + return CopySrcReg; + + SrcReg = CopySrcReg; + } +} + +// Essentially a compile-time implementation of a compare->isel sequence. +// It takes two constants to compare, along with the true/false registers +// and the comparison type (as a subreg to a CR field) and returns one +// of the true/false registers, depending on the comparison results. +static unsigned selectReg(int64_t Imm1, int64_t Imm2, unsigned CompareOpc, + unsigned TrueReg, unsigned FalseReg, + unsigned CRSubReg) { + // Signed comparisons. The immediates are assumed to be sign-extended. + if (CompareOpc == PPC::CMPWI || CompareOpc == PPC::CMPDI) { + switch (CRSubReg) { + default: llvm_unreachable("Unknown integer comparison type."); + case PPC::sub_lt: + return Imm1 < Imm2 ? TrueReg : FalseReg; + case PPC::sub_gt: + return Imm1 > Imm2 ? TrueReg : FalseReg; + case PPC::sub_eq: + return Imm1 == Imm2 ? TrueReg : FalseReg; + } + } + // Unsigned comparisons. + else if (CompareOpc == PPC::CMPLWI || CompareOpc == PPC::CMPLDI) { + switch (CRSubReg) { + default: llvm_unreachable("Unknown integer comparison type."); + case PPC::sub_lt: + return (uint64_t)Imm1 < (uint64_t)Imm2 ? TrueReg : FalseReg; + case PPC::sub_gt: + return (uint64_t)Imm1 > (uint64_t)Imm2 ? TrueReg : FalseReg; + case PPC::sub_eq: + return Imm1 == Imm2 ? TrueReg : FalseReg; + } + } + return 0; +} + +// If this instruction has an immediate form and one of its operands is a +// result of a load-immediate, convert it to the immediate form if the constant +// is in range. +bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI) const { + MachineFunction *MF = MI.getParent()->getParent(); + MachineRegisterInfo *MRI = &MF->getRegInfo(); + MachineInstr *DefMI = nullptr; + unsigned ConstantOperand = ~0U; + for (int i = 1, e = MI.getNumOperands(); i < e; i++) { + if (!MI.getOperand(i).isReg()) + continue; + unsigned Reg = MI.getOperand(i).getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + unsigned TrueReg = lookThruCopyLike(Reg, MRI); + if (TargetRegisterInfo::isVirtualRegister(TrueReg)) { + DefMI = MRI->getVRegDef(TrueReg); + if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8) { + ConstantOperand = i; + break; + } + } + } + if (ConstantOperand == ~0U || !DefMI->getOperand(1).isImm()) + return false; + + int64_t Immediate = DefMI->getOperand(1).getImm(); + // Sign-extend to 64-bits. + int64_t SExtImm = ((uint64_t)Immediate & ~0x7FFFuLL) != 0 ? + (Immediate | 0xFFFFFFFFFFFF0000) : Immediate; + + bool ReplaceWithLI = false; + bool Is64BitLI = false; + int64_t NewImm = 0; + bool SetCR = false; + unsigned Opc = MI.getOpcode(); + switch (Opc) { + default: return false; + + // FIXME: Any branches conditional on such a comparison can be made + // unconditional. At this time, this happens too infrequently to be worth + // the implementation effort, but if that ever changes, we could convert + // such a pattern here. + case PPC::CMPWI: + case PPC::CMPLWI: + case PPC::CMPDI: + case PPC::CMPLDI: { + // If a compare-immediate is fed by an immediate and is itself an input of + // an ISEL (the most common case) into a COPY of the correct register. + unsigned DefReg = MI.getOperand(0).getReg(); + int64_t Comparand = MI.getOperand(2).getImm(); + int64_t SExtComparand = ((uint64_t)Comparand & ~0x7FFFuLL) != 0 ? + (Comparand | 0xFFFFFFFFFFFF0000) : Comparand; + + for (auto &CompareUseMI : MRI->use_instructions(DefReg)) { + unsigned UseOpc = CompareUseMI.getOpcode(); + if (UseOpc != PPC::ISEL && UseOpc != PPC::ISEL8) + continue; + unsigned CRSubReg = CompareUseMI.getOperand(3).getSubReg(); + unsigned TrueReg = CompareUseMI.getOperand(1).getReg(); + unsigned FalseReg = CompareUseMI.getOperand(2).getReg(); + unsigned RegToCopy = selectReg(SExtImm, SExtComparand, Opc, TrueReg, + FalseReg, CRSubReg); + // Convert to copy and remove unneeded operands. + if (RegToCopy == TrueReg) { + DEBUG(dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); + DEBUG(DefMI->dump(); MI.dump(); CompareUseMI.dump()); + DEBUG(dbgs() << "Is converted to:\n"); + CompareUseMI.setDesc(get(PPC::COPY)); + CompareUseMI.RemoveOperand(3); + CompareUseMI.RemoveOperand(2); + DEBUG(CompareUseMI.dump()); + CmpIselsConverted++; + return true; + } + else if (RegToCopy == FalseReg) { + DEBUG(dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); + DEBUG(DefMI->dump(); MI.dump(); CompareUseMI.dump()); + DEBUG(dbgs() << "Is converted to:\n"); + CompareUseMI.setDesc(get(PPC::COPY)); + CompareUseMI.RemoveOperand(3); + CompareUseMI.RemoveOperand(1); + DEBUG(CompareUseMI.dump()); + CmpIselsConverted++; + return true; + } + } + // This may end up incremented multiple times since this function is called + // during a fixed-point transformation, but it is only meant to indicate the + // presence of this opportunity. + MissedConvertibleImmediateInstrs++; + return false; + } + + // Immediate forms - may simply be convertable to an LI. + case PPC::ADDI: + case PPC::ADDI8: { + // Does the sum fit in a 16-bit signed field? + int64_t Addend = MI.getOperand(2).getImm(); + if (isInt<16>(Addend + SExtImm)) { + ReplaceWithLI = true; + Is64BitLI = Opc == PPC::ADDI8; + NewImm = Addend + SExtImm; + break; + } + } + case PPC::RLDICL: + case PPC::RLDICLo: + case PPC::RLDICL_32: + case PPC::RLDICL_32_64: { + // Use APInt's rotate function. + int64_t SH = MI.getOperand(2).getImm(); + int64_t MB = MI.getOperand(3).getImm(); + APInt InVal(Opc == PPC::RLDICL ? 64 : 32, SExtImm, true); + InVal = InVal.rotl(SH); + uint64_t Mask = (1LU << (63 - MB + 1)) - 1; + InVal &= Mask; + // Can't replace negative values with an LI as that will sign-extend + // and not clear the left bits. + if (isUInt<16>(InVal.getSExtValue())) { + ReplaceWithLI = true; + Is64BitLI = Opc != PPC::RLDICL_32; + NewImm = InVal.getSExtValue(); + SetCR = Opc == PPC::RLDICLo; + break; + } + return false; + } + case PPC::ORI: + case PPC::ORI8: + case PPC::XORI: + case PPC::XORI8: { + int64_t LogicalImm = MI.getOperand(2).getImm(); + int64_t Result = 0; + if (Opc == PPC::ORI || Opc == PPC::ORI8) + Result = LogicalImm | SExtImm; + else + Result = LogicalImm ^ SExtImm; + if (isInt<16>(Result)) { + ReplaceWithLI = true; + Is64BitLI = Opc == PPC::ORI8 || Opc == PPC::XORI8; + NewImm = Result; + break; + } + return false; + } + + // Additions - commutable. + case PPC::ADD4: + case PPC::ADD8: { + DEBUG(dbgs() << "Converted reg/reg instruction:\n"); + DEBUG(MI.dump()); + MachineOperand Op1 = MI.getOperand(1); + MachineOperand Op2 = MI.getOperand(2); + MI.setDesc(get(Opc == PPC::ADD4 ? PPC::ADDI : PPC::ADDI8)); + MI.RemoveOperand(2); + MI.RemoveOperand(1); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .add(ConstantOperand == 1 ? Op2 : Op1) + .addImm(Immediate); + MRI->setRegClass(MI.getOperand(1).getReg(), + Opc == PPC::ADD4 ? &PPC::GPRC_and_GPRC_NOR0RegClass : + &PPC::G8RC_and_G8RC_NOX0RegClass); + DEBUG(dbgs() << "To reg/imm instruction:\n"); + DEBUG(MI.dump()); + return true; + } + // Subtraction, compares - non-commutable. + case PPC::SUBFC: + case PPC::SUBFC8: { + if (ConstantOperand != 2) + return false; + unsigned NewOpc = Opc == PPC::SUBFC ? PPC::SUBFIC : PPC::SUBFIC8; + DEBUG(dbgs() << "Converted:\n"); + DEBUG(MI.dump()); + DEBUG(dbgs() << "Fed by:\n"); + DEBUG(DefMI->dump()); + MI.RemoveOperand(2); + MI.setDesc(get(NewOpc)); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .addImm(Immediate); + DEBUG(dbgs() << "To:\n"); + DEBUG(MI.dump()); + return true; + } + case PPC::CMPLW: + case PPC::CMPLD: + if (!isUInt<16>(SExtImm)) + return false; + LLVM_FALLTHROUGH; + case PPC::CMPW: + case PPC::CMPD: { + if (ConstantOperand != 2) + return false; + unsigned NewOpc = Opc == PPC::CMPLW ? PPC::CMPLWI : + Opc == PPC::CMPLD ? PPC::CMPLDI : + Opc == PPC::CMPW ? PPC::CMPWI : PPC::CMPDI; + DEBUG(dbgs() << "Converted:\n"); + DEBUG(MI.dump()); + DEBUG(dbgs() << "Fed by:\n"); + DEBUG(DefMI->dump()); + MI.RemoveOperand(2); + MI.setDesc(get(NewOpc)); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .addImm(Immediate); + DEBUG(dbgs() << "To:\n"); + DEBUG(MI.dump()); + return true; + } + + case PPC::SLD: + case PPC::SLDo: { + if (ConstantOperand == 2) { + DEBUG(dbgs() << "Converted:\n"); + DEBUG(MI.dump()); + DEBUG(dbgs() << "Fed by:\n"); + DEBUG(DefMI->dump()); + MI.RemoveOperand(2); + uint64_t SH = Immediate & 0x3F; + uint64_t ME = 63 - SH; + + // According to the ISA, shifting by 64-127 is zero. It is important to + // keep in mind that only bits 57-63 are considered. So the result is zero + // if bit 57 is set in the shift register. + if (SExtImm & 0x40) { + ReplaceWithLI = true; + Is64BitLI = true; + NewImm = 0; + SetCR = Opc == PPC::SLDo; + break; + } + // Shifting by zero is redundant (but still needed if it sets CR0). + if (SH == 0 && Opc == PPC::SLD) + MI.setDesc(get(PPC::COPY)); + else { + MI.setDesc(get(Opc == PPC::SLD ? PPC::RLDICR : PPC::RLDICRo)); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .addImm(SH).addImm(ME); + } + DEBUG(dbgs() << "To:\n"); + DEBUG(MI.dump()); + return true; + } + break; + } + case PPC::SRD: + case PPC::SRDo: + if (ConstantOperand == 2) { + DEBUG(dbgs() << "Converted:\n"); + DEBUG(MI.dump()); + DEBUG(dbgs() << "Fed by:\n"); + DEBUG(DefMI->dump()); + MI.RemoveOperand(2); + uint64_t MB = Immediate & 0x3F; + uint64_t SH = 64 - MB; + + // According to the ISA, shifting by 64-127 is zero. It is important to + // keep in mind that only bits 57-63 are considered. So the result is zero + // if bit 57 is set in the shift register. + if (SExtImm & 0x40) { + ReplaceWithLI = true; + Is64BitLI = true; + NewImm = 0; + SetCR = Opc == PPC::SRDo; + break; + } + // Shifting by zero is redundant (but still needed if it sets CR0). + if (SH == 64 && Opc == PPC::SRD) + MI.setDesc(get(PPC::COPY)); + else { + MI.setDesc(get(Opc == PPC::SRD ? PPC::RLDICL : PPC::RLDICLo)); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .addImm(SH).addImm(MB); + } + DEBUG(dbgs() << "To:\n"); + DEBUG(MI.dump()); + return true; + } + break; + case PPC::ANDo: + case PPC::AND8o: + case PPC::OR: + case PPC::OR8: + case PPC::XOR: + case PPC::XOR8: { + unsigned ImmOpc = 0; + switch (Opc) { + case PPC::ANDo: + ImmOpc = PPC::ANDIo; + break; + case PPC::AND8o: + ImmOpc = PPC::ANDIo8; + break; + case PPC::OR: + ImmOpc = PPC::ORI; + break; + case PPC::OR8: + ImmOpc = PPC::ORI8; + break; + case PPC::XOR: + ImmOpc = PPC::XORI; + break; + case PPC::XOR8: + ImmOpc = PPC::XORI8; + break; + } + if (((uint64_t)Immediate & ~0x7FFFuLL) == 0) { + DEBUG(dbgs() << "Converted reg/reg instruction:\n"); + DEBUG(MI.dump()); + MachineOperand Op1 = MI.getOperand(1); + MachineOperand Op2 = MI.getOperand(2); + MI.setDesc(get(ImmOpc)); + MI.RemoveOperand(2); + MI.RemoveOperand(1); + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .add(ConstantOperand == 1 ? Op2 : Op1) + .addImm(Immediate); + DEBUG(dbgs() << "To reg/imm instruction:\n"); + DEBUG(MI.dump()); + return true; + } + } + } + + if (ReplaceWithLI) { + DEBUG(dbgs() << "Replacing instruction:\n"); + DEBUG(MI.dump()); + DEBUG(dbgs() << "Fed by:\n"); + DEBUG(DefMI->dump()); + // Remove existing operands. + int OperandToKeep = SetCR ? 1 : 0; + for (int i = MI.getNumOperands() - 1; i > OperandToKeep; i--) + MI.RemoveOperand(i); + + // Replace the instruction. + if (SetCR) + MI.setDesc(get(Is64BitLI ? PPC::ANDIo8 : PPC::ANDIo)); + else + MI.setDesc(get(Is64BitLI ? PPC::LI8 : PPC::LI)); + + // Set the immediate. + MachineInstrBuilder(*MI.getParent()->getParent(), MI) + .addImm(NewImm); + DEBUG(dbgs() << "With:\n"); + DEBUG(MI.dump()); + return true; + } + return false; +} const TargetRegisterClass * PPCInstrInfo::updatedRC(const TargetRegisterClass *RC) const { if (Subtarget.hasVSX() && RC == &PPC::VRRCRegClass) Index: lib/Target/PowerPC/PPCMIPeephole.cpp =================================================================== --- lib/Target/PowerPC/PPCMIPeephole.cpp +++ lib/Target/PowerPC/PPCMIPeephole.cpp @@ -36,11 +36,18 @@ #define DEBUG_TYPE "ppc-mi-peepholes" STATISTIC(NumOptADDLIs, "Number of optimized ADD instruction fed by LI"); - -namespace llvm { - void initializePPCMIPeepholePass(PassRegistry&); -} - +STATISTIC(NumConvertedToImmediateForm, + "Number of instructions converted to their immediate form"); +STATISTIC(NumFunctionsEnteredInMIPeephole, + "Number of functions entered in PPC MI Peepholes"); +STATISTIC(NumFixedPointIterations, + "Number of fixed-point iterations converting reg-reg instructions " + "to reg-imm ones"); + +static cl::opt +FixedPointRegToImm("ppc-reg-to-imm-fixed-point", cl::Hidden, cl::init(true), + cl::desc("Iterate to a fixed point when attempting to " + "convert reg-reg instructions to reg-imm")); namespace { struct PPCMIPeephole : public MachineFunctionPass { @@ -66,10 +73,6 @@ // Perform peepholes. bool eliminateRedundantCompare(void); - // Find the "true" register represented by SrcReg (following chains - // of copies and subreg_to_reg operations). - unsigned lookThruCopyLike(unsigned SrcReg); - public: void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -115,6 +118,33 @@ bool Simplified = false; MachineInstr* ToErase = nullptr; + NumFunctionsEnteredInMIPeephole++; + // Fixed-point conversion of reg/reg instructions fed by load-immediate + // into reg/imm instructions. FIXME: This is expensive, control it with + // an option. + bool SomethingChanged = false; + do { + NumFixedPointIterations++; + SomethingChanged = false; + for (MachineBasicBlock &MBB : *MF) { + for (MachineInstr &MI : MBB) { + if (MI.isDebugValue()) + continue; + + if (TII->convertToImmediateForm(MI)) { + // We don't erase anything in case the def has other uses. Let DCE + // remove it if it can be removed. + DEBUG(dbgs() << "Converted instruction to imm form: "); + DEBUG(MI.dump()); + NumConvertedToImmediateForm++; + SomethingChanged = true; + Simplified = true; + continue; + } + } + } + } while (SomethingChanged && FixedPointRegToImm); + for (MachineBasicBlock &MBB : *MF) { for (MachineInstr &MI : MBB) { @@ -149,8 +179,10 @@ // XXPERMDI t, SUBREG_TO_REG(s), SUBREG_TO_REG(s), immed. // We have to look through chains of COPY and SUBREG_TO_REG // to find the real source values for comparison. - unsigned TrueReg1 = lookThruCopyLike(MI.getOperand(1).getReg()); - unsigned TrueReg2 = lookThruCopyLike(MI.getOperand(2).getReg()); + unsigned TrueReg1 = + TII->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); + unsigned TrueReg2 = + TII->lookThruCopyLike(MI.getOperand(2).getReg(), MRI); if (TrueReg1 == TrueReg2 && TargetRegisterInfo::isVirtualRegister(TrueReg1)) { @@ -164,7 +196,8 @@ auto isConversionOfLoadAndSplat = [=]() -> bool { if (DefOpc != PPC::XVCVDPSXDS && DefOpc != PPC::XVCVDPUXDS) return false; - unsigned DefReg = lookThruCopyLike(DefMI->getOperand(1).getReg()); + unsigned DefReg = + TII->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); if (TargetRegisterInfo::isVirtualRegister(DefReg)) { MachineInstr *LoadMI = MRI->getVRegDef(DefReg); if (LoadMI && LoadMI->getOpcode() == PPC::LXVDSX) @@ -190,10 +223,10 @@ // can replace it with a copy. if (DefOpc == PPC::XXPERMDI) { unsigned FeedImmed = DefMI->getOperand(3).getImm(); - unsigned FeedReg1 - = lookThruCopyLike(DefMI->getOperand(1).getReg()); - unsigned FeedReg2 - = lookThruCopyLike(DefMI->getOperand(2).getReg()); + unsigned FeedReg1 = + TII->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); + unsigned FeedReg2 = + TII->lookThruCopyLike(DefMI->getOperand(2).getReg(), MRI); if ((FeedImmed == 0 || FeedImmed == 3) && FeedReg1 == FeedReg2) { DEBUG(dbgs() @@ -251,7 +284,8 @@ case PPC::XXSPLTW: { unsigned MyOpcode = MI.getOpcode(); unsigned OpNo = MyOpcode == PPC::XXSPLTW ? 1 : 2; - unsigned TrueReg = lookThruCopyLike(MI.getOperand(OpNo).getReg()); + unsigned TrueReg = + TII->lookThruCopyLike(MI.getOperand(OpNo).getReg(), MRI); if (!TargetRegisterInfo::isVirtualRegister(TrueReg)) break; MachineInstr *DefMI = MRI->getVRegDef(TrueReg); @@ -313,7 +347,8 @@ } case PPC::XVCVDPSP: { // If this is a DP->SP conversion fed by an FRSP, the FRSP is redundant. - unsigned TrueReg = lookThruCopyLike(MI.getOperand(1).getReg()); + unsigned TrueReg = + TII->lookThruCopyLike(MI.getOperand(1).getReg(), MRI); if (!TargetRegisterInfo::isVirtualRegister(TrueReg)) break; MachineInstr *DefMI = MRI->getVRegDef(TrueReg); @@ -321,8 +356,10 @@ // This can occur when building a vector of single precision or integer // values. if (DefMI && DefMI->getOpcode() == PPC::XXPERMDI) { - unsigned DefsReg1 = lookThruCopyLike(DefMI->getOperand(1).getReg()); - unsigned DefsReg2 = lookThruCopyLike(DefMI->getOperand(2).getReg()); + unsigned DefsReg1 = + TII->lookThruCopyLike(DefMI->getOperand(1).getReg(), MRI); + unsigned DefsReg2 = + TII->lookThruCopyLike(DefMI->getOperand(2).getReg(), MRI); if (!TargetRegisterInfo::isVirtualRegister(DefsReg1) || !TargetRegisterInfo::isVirtualRegister(DefsReg2)) break; @@ -930,36 +967,6 @@ return Simplified; } -// This is used to find the "true" source register for an -// XXPERMDI instruction, since MachineCSE does not handle the -// "copy-like" operations (Copy and SubregToReg). Returns -// the original SrcReg unless it is the target of a copy-like -// operation, in which case we chain backwards through all -// such operations to the ultimate source register. If a -// physical register is encountered, we stop the search. -unsigned PPCMIPeephole::lookThruCopyLike(unsigned SrcReg) { - - while (true) { - - MachineInstr *MI = MRI->getVRegDef(SrcReg); - if (!MI->isCopyLike()) - return SrcReg; - - unsigned CopySrcReg; - if (MI->isCopy()) - CopySrcReg = MI->getOperand(1).getReg(); - else { - assert(MI->isSubregToReg() && "bad opcode for lookThruCopyLike"); - CopySrcReg = MI->getOperand(2).getReg(); - } - - if (!TargetRegisterInfo::isVirtualRegister(CopySrcReg)) - return CopySrcReg; - - SrcReg = CopySrcReg; - } -} - } // end default namespace INITIALIZE_PASS_BEGIN(PPCMIPeephole, DEBUG_TYPE, Index: lib/Target/PowerPC/PPCTargetMachine.cpp =================================================================== --- lib/Target/PowerPC/PPCTargetMachine.cpp +++ lib/Target/PowerPC/PPCTargetMachine.cpp @@ -98,6 +98,7 @@ initializePPCBoolRetToIntPass(PR); initializePPCExpandISELPass(PR); initializePPCTLSDynamicCallPass(PR); + initializePPCMIPeepholePass(PR); } /// Return the datalayout string of a subtarget. Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-add.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-add.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-add.mir @@ -0,0 +1,82 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define signext i32 @test(i32 signext %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %add = add i32 %a, 422 + %add1 = add i32 %add, %b + ret i32 %add1 + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: gprc } + - { id: 4, class: gprc_and_gprc_nor0 } + - { id: 5, class: gprc } + - { id: 6, class: gprc } + - { id: 7, class: gprc } + - { id: 8, class: gprc } + - { id: 9, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = COPY %x4 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = COPY %0.sub_32 + %4 = LI 422 + %5 = ADD4 killed %3, killed %2 + %6 = ADD4 killed %5, %4 + ; CHECK: %6 = ADDI killed %5, 422 + %7 = ADDI killed %4, 333 + ; CHECK: %7 = LI 755 + %8 = ADD4 killed %6, killed %7 + ; CHECK: %8 = ADDI killed %6, 755 + %9 = EXTSW_32_64 killed %8 + %x3 = COPY %9 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-and.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-and.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-and.mir @@ -0,0 +1,137 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i64 %b) local_unnamed_addr #0 { + entry: + %and = and i64 %b, %a + %tobool = icmp ne i64 %and, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define zeroext i32 @test3(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr #0 { + entry: + %and = and i32 %b, %a + %tobool = icmp ne i32 %and, 0 + %cond = select i1 %tobool, i32 778, i32 223 + ret i32 %cond + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } + - { id: 3, class: crrc } + - { id: 4, class: g8rc_and_g8rc_nox0 } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 263 + %0 = COPY %x3 + %2 = AND8o %1, %0, implicit-def %cr0 + ; CHECK: %2 = ANDIo8 %0, 263, implicit-def %cr0 + %3 = COPY killed %cr0 + %4 = LI8 223 + %5 = LI8 778 + %6 = ISEL8 %4, %5, %3.sub_eq + %x3 = COPY %6 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test3 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: gprc } + - { id: 4, class: gprc } + - { id: 5, class: crrc } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc_and_g8rc_nox0 } + - { id: 8, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 511 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = COPY %0.sub_32 + %4 = ANDo %2, %3, implicit-def %cr0 + ; CHECK: %4 = ANDIo %3, 511, implicit-def %cr0 + %5 = COPY killed %cr0 + %6 = LI8 223 + %7 = LI8 778 + %8 = ISEL8 %6, %7, %5.sub_eq + %x3 = COPY %8 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-cmp.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-cmp.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-cmp.mir @@ -0,0 +1,247 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %conv = sext i32 %b to i64 + %cmp = icmp ult i64 %conv, %a + %conv2 = select i1 %cmp, i64 778, i64 223 + ret i64 %conv2 + } + + ; Function Attrs: norecurse nounwind readnone + define zeroext i32 @test2(i32 zeroext %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %cmp = icmp ugt i32 %a, %b + %cond = select i1 %cmp, i32 778, i32 223 + ret i32 %cond + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test3(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %conv = sext i32 %b to i64 + %cmp = icmp slt i64 %conv, %a + %conv2 = select i1 %cmp, i64 778, i64 223 + ret i64 %conv2 + } + + ; Function Attrs: norecurse nounwind readnone + define signext i32 @test4(i32 signext %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %cmp = icmp sgt i32 %a, %b + %cond = select i1 %cmp, i32 778, i32 223 + ret i32 %cond + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: crrc } + - { id: 3, class: g8rc_and_g8rc_nox0 } + - { id: 4, class: g8rc_and_g8rc_nox0 } + - { id: 5, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = COPY %x4 + %0 = LI8 433 + %2 = CMPLD %1, %0 + ; CHECK: %2 = CMPLDI %1, 433 + %3 = LI8 223 + %4 = LI8 778 + %5 = ISEL8 %4, %3, %2.sub_lt + %x3 = COPY %5 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test2 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: gprc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = COPY %x4 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = LI 332 + %4 = CMPLW killed %2, killed %3 + ; CHECK: %4 = CMPLWI killed %2, 332 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %6, %5, %4.sub_gt + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test3 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: crrc } + - { id: 3, class: g8rc_and_g8rc_nox0 } + - { id: 4, class: g8rc_and_g8rc_nox0 } + - { id: 5, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = COPY %x4 + %0 = LI8 443 + %2 = CMPD %1, %0 + ; CHECK: %2 = CMPDI %1, 443 + %3 = LI8 223 + %4 = LI8 778 + %5 = ISEL8 %4, %3, %2.sub_lt + %x3 = COPY %5 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test4 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: gprc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = COPY %x4 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = LI 332 + %4 = CMPW killed %2, killed %3 + ; CHECK: %4 = CMPWI killed %2, 332 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %6, %5, %4.sub_gt + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-or-xor.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-or-xor.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-or-xor.mir @@ -0,0 +1,113 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i64 %b) local_unnamed_addr #0 { + entry: + %or = or i64 %b, %a + ret i64 %or + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test2(i64 %a, i64 %b) local_unnamed_addr #0 { + entry: + %xor = xor i64 %b, %a + ret i64 %xor + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 44 + %0 = COPY %x3 + %2 = OR8 %1, %0 + ; CHECK: %2 = ORI8 %0, 44 + %x3 = COPY %2 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test2 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 44 + %0 = COPY %x3 + %2 = XOR8 %1, %0 + ; CHECK: %2 = XORI8 %0, 44 + %x3 = COPY %2 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-ori.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-ori.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-ori.mir @@ -0,0 +1,63 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %or = or i64 %a, 13 + ret i64 %or + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3 + + %0 = LI8 224 + %2 = ORI8 %0, 14 + ; CHECK: %2 = LI8 238 + %x3 = COPY %2 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-rldicl.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-rldicl.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-rldicl.mir @@ -0,0 +1,63 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %shr = lshr i64 %a, 13 + ret i64 %shr + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3 + + %0 = LI8 22543 + %2 = RLDICL %0, 51, 13 + ; CHECK: %2 = LI8 2 + %x3 = COPY %2 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-sld.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-sld.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-sld.mir @@ -0,0 +1,353 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + %tobool = icmp ne i64 %shl, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test2(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + ret i64 %shl + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test3(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + %tobool = icmp ne i64 %shl, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test4(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + ret i64 %shl + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test5(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + %tobool = icmp ne i64 %shl, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test6(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shl = shl i64 %a, %sh_prom + ret i64 %shl + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 6 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SLDo %0, killed %2, implicit-def %cr0 + ; CHECK: %3 = RLDICRo %0, 6, 57, implicit-def %cr0 + %4 = COPY killed %cr0 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %5, %6, %4.sub_eq + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test2 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 9 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SLD %0, killed %2 + ; CHECK: %3 = RLDICR %0, 9, 54 + %x3 = COPY %3 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test3 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 113 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SLDo %0, killed %2, implicit-def %cr0 + ; CHECK: %3 = ANDIo8 %0, 0 + %4 = COPY killed %cr0 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %5, %6, %4.sub_eq + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test4 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 113 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SLD %0, killed %2 + ; CHECK: %3 = LI8 0 + %x3 = COPY %3 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test5 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 0 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SLDo %0, killed %2, implicit-def %cr0 + ; CHECK: %3 = RLDICRo %0, 0, 63, implicit-def %cr0 + %4 = COPY killed %cr0 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %5, %6, %4.sub_eq + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test6 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 0 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SLD %0, killed %2 + ; CHECK: %3 = COPY %0 + %x3 = COPY %3 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-srd.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-srd.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-srd.mir @@ -0,0 +1,353 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + %tobool = icmp ne i64 %shr, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test2(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + ret i64 %shr + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test3(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + %tobool = icmp ne i64 %shr, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test4(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + ret i64 %shr + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test5(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + %tobool = icmp ne i64 %shr, 0 + %conv = select i1 %tobool, i64 778, i64 223 + ret i64 %conv + } + + ; Function Attrs: norecurse nounwind readnone + define i64 @test6(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %sh_prom = zext i32 %b to i64 + %shr = lshr i64 %a, %sh_prom + ret i64 %shr + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 6 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SRDo %0, killed %2, implicit-def %cr0 + ; CHECK: %3 = RLDICLo %0, 58, 6, implicit-def %cr0 + %4 = COPY killed %cr0 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %5, %6, %4.sub_eq + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test2 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 9 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SRD %0, killed %2 + ; CHECK: %3 = RLDICL %0, 55, 9 + %x3 = COPY %3 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test3 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 113 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SRDo %0, killed %2, implicit-def %cr0 + ; CHECK: %3 = ANDIo8 %0, 0 + %4 = COPY killed %cr0 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %5, %6, %4.sub_eq + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test4 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 113 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SRD %0, killed %2 + ; CHECK: %3 = LI8 0 + %x3 = COPY %3 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test5 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } + - { id: 4, class: crrc } + - { id: 5, class: g8rc_and_g8rc_nox0 } + - { id: 6, class: g8rc_and_g8rc_nox0 } + - { id: 7, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 0 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SRDo %0, killed %2, implicit-def %cr0 + ; CHECK: %3 = RLDICLo %0, 64, 0, implicit-def %cr0 + %4 = COPY killed %cr0 + %5 = LI8 223 + %6 = LI8 778 + %7 = ISEL8 %5, %6, %4.sub_eq + %x3 = COPY %7 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... +--- +name: test6 +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: gprc } + - { id: 3, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } + - { reg: '%x4', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3, %x4 + + %1 = LI8 0 + %0 = COPY %x3 + %2 = COPY %1.sub_32 + %3 = SRD %0, killed %2 + ; CHECK: %3 = COPY %0 + %x3 = COPY %3 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-subfc.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-subfc.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-subfc.mir @@ -0,0 +1,70 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %cmp = icmp ugt i64 %a, 13 + %conv1 = zext i1 %cmp to i64 + ret i64 %conv1 + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } + - { id: 3, class: g8rc } + - { id: 4, class: g8rc } + - { id: 5, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3 + + %0 = COPY %x3 + %2 = LI8 13 + %3 = SUBFC8 %0, %2, implicit-def %carry + ; CHECK: %3 = SUBFIC8 %0, 13, implicit-def %carry + %4 = SUBFE8 %2, %2, implicit-def dead %carry, implicit %carry + %5 = NEG8 killed %4 + %x3 = COPY %5 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/fold-constants-into-imm-instrs-xori.mir =================================================================== --- test/CodeGen/PowerPC/fold-constants-into-imm-instrs-xori.mir +++ test/CodeGen/PowerPC/fold-constants-into-imm-instrs-xori.mir @@ -0,0 +1,63 @@ +# RUN: llc -run-pass ppc-mi-peepholes -o - %s | FileCheck %s + +--- | + ; ModuleID = 't.ll' + source_filename = "t.c" + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + ; Function Attrs: norecurse nounwind readnone + define i64 @test(i64 %a, i32 signext %b) local_unnamed_addr #0 { + entry: + %xor = xor i64 %a, 13 + ret i64 %xor + } + + attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="ppc64le" "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+htm,+power8-vector,+vsx,-power9-vector,-qpx" "unsafe-fp-math"="false" "use-soft-float"="false" } + + !llvm.module.flags = !{!0} + !llvm.ident = !{!1} + + !0 = !{i32 1, !"PIC Level", i32 2} + !1 = !{!"clang version 5.0.0 (git@github.ibm.com:llvm/clang.git 5e5be8ed354acb606e083cee2ff9c9e096099ff2) (llvm/llvm.git c5a7ad098a8772950f4005869a14354e7f233ab3)"} + +... +--- +name: test +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: g8rc } + - { id: 1, class: g8rc } + - { id: 2, class: g8rc } +liveins: + - { reg: '%x3', virtual-reg: '%0' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +body: | + bb.0.entry: + liveins: %x3 + + %0 = LI8 224 + %2 = XORI8 %0, 13 + ; CHECK: %2 = LI8 237 + %x3 = COPY %2 + BLR8 implicit %lr8, implicit %rm, implicit %x3 + +... Index: test/CodeGen/PowerPC/simplifyConstCmpToISEL.ll =================================================================== --- test/CodeGen/PowerPC/simplifyConstCmpToISEL.ll +++ test/CodeGen/PowerPC/simplifyConstCmpToISEL.ll @@ -0,0 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=powerpc64le-unknown-unknown -mcpu=pwr8 \ +; RUN: -verify-machineinstrs | FileCheck %s +define void @test(i32 zeroext %parts) { +; CHECK-LABEL: test: +; CHECK: # BB#0: # %cond.end.i +; CHECK-NEXT: cmplwi 0, 3, 1 +; CHECK-NEXT: bnelr+ 0 +; CHECK-NEXT: # BB#1: # %test2.exit.us.unr-lcssa +; CHECK-NEXT: ld 3, 0(3) +; CHECK-NEXT: std 3, 0(3) +entry: + br label %cond.end.i + +cond.end.i: ; preds = %entry + %cmp18.i = icmp eq i32 %parts, 1 + br i1 %cmp18.i, label %while.body.lr.ph.i.us.preheader, label %test3.exit.split + +while.body.lr.ph.i.us.preheader: ; preds = %cond.end.i + %0 = icmp eq i32 %parts, 1 + br label %for.body.i62.us.preheader + +for.body.i62.us.preheader: ; preds = %while.body.lr.ph.i.us.preheader + br i1 %0, label %test2.exit.us.unr-lcssa, label %for.body.i62.us.preheader.new + +for.body.i62.us.preheader.new: ; preds = %for.body.i62.us.preheader + br label %for.body.i62.us + +for.body.i62.us: ; preds = %if.end.i.us.1, %for.body.i62.us.preheader.new + %niter = phi i64 [ undef, %for.body.i62.us.preheader.new ], [ %niter.nsub.1, %if.end.i.us.1 ] + %cmp8.i.us.1 = icmp uge i64 undef, 0 + br label %if.end.i.us.1 + +test2.exit.us.unr-lcssa: ; preds = %if.end.i.us.1, %for.body.i62.us.preheader + %c.addr.036.i.us.unr = phi i64 [ 0, %for.body.i62.us.preheader ], [ %c.addr.1.i.us.1, %if.end.i.us.1 ] + %1 = load i64, i64* undef, align 8 + %tobool.i61.us.epil = icmp eq i64 %c.addr.036.i.us.unr, 0 + %add.neg.i.us.epil.pn = select i1 %tobool.i61.us.epil, i64 %1, i64 0 + %storemerge269 = sub i64 %add.neg.i.us.epil.pn, 0 + store i64 %storemerge269, i64* undef, align 8 + unreachable + +test3.exit.split: ; preds = %cond.end.i + ret void + +if.end.i.us.1: ; preds = %for.body.i62.us + %c.addr.1.i.us.1 = zext i1 %cmp8.i.us.1 to i64 + %niter.nsub.1 = add i64 %niter, -2 + %niter.ncmp.1 = icmp eq i64 %niter.nsub.1, 0 + br i1 %niter.ncmp.1, label %test2.exit.us.unr-lcssa, label %for.body.i62.us +} Index: test/CodeGen/PowerPC/variable_elem_vec_extracts.ll =================================================================== --- test/CodeGen/PowerPC/variable_elem_vec_extracts.ll +++ test/CodeGen/PowerPC/variable_elem_vec_extracts.ll @@ -70,8 +70,7 @@ ; CHECK-LABEL: @getf ; CHECK-P7-LABEL: @getf ; CHECK-BE-LABEL: @getf -; CHECK: li [[IMMREG:[0-9]+]], 3 -; CHECK: xor [[TRUNCREG:[0-9]+]], [[IMMREG]], 5 +; CHECK: xori [[TRUNCREG:[0-9]+]], 5, 3 ; CHECK: lvsl [[SHMSKREG:[0-9]+]], 0, [[TRUNCREG]] ; CHECK: vperm {{[0-9]+}}, 2, 2, [[SHMSKREG]] ; CHECK: xscvspdpn 1,