diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -187,13 +187,17 @@ const TargetRegisterClass *RC, SmallVectorImpl &NewMIs) const; - // If the inst has imm-form and one of its operand is produced by a LI, - // put the imm into the inst directly and remove the LI if possible. + // Replace the instruction with single LI if possible. \p DefMI must be LI or + // LI8. + bool simplifyToLI(MachineInstr &MI, MachineInstr &DefMI, + unsigned OpNoForForwarding, MachineInstr **KilledDef) const; + // If the inst is x-form and has imm-form and one of its operand is produced + // by a LI, put the imm into the inst directly and remove the LI if possible. bool transformToImmFormFedByLI(MachineInstr &MI, const ImmInstrInfo &III, - unsigned ConstantOpNo, MachineInstr &DefMI, - int64_t Imm) const; - // If the inst has imm-form and one of its operand is produced by an - // add-immediate, try to transform it when possible. + unsigned ConstantOpNo, + MachineInstr &DefMI) const; + // If the inst is x-form and has imm-form and one of its operand is produced + // by an add-immediate, try to transform it when possible. bool transformToImmFormFedByAdd(MachineInstr &MI, const ImmInstrInfo &III, unsigned ConstantOpNo, MachineInstr &DefMI, bool KillDefMI) const; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -2643,7 +2643,6 @@ "The forwarding operand needs to be valid at this point"); bool IsForwardingOperandKilled = MI.getOperand(ForwardingOperand).isKill(); bool KillFwdDefMI = !SeenIntermediateUse && IsForwardingOperandKilled; - Register ForwardingOperandReg = MI.getOperand(ForwardingOperand).getReg(); if (KilledDef && KillFwdDefMI) *KilledDef = DefMI; @@ -2660,228 +2659,17 @@ KillFwdDefMI)) return true; - if ((DefMI->getOpcode() != PPC::LI && DefMI->getOpcode() != PPC::LI8) || - !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; - // If this is a reg+reg instruction that has a reg+imm form, // and one of the operands is produced by LI, convert it now. - if (HasImmForm) - return transformToImmFormFedByLI(MI, III, ForwardingOperand, *DefMI, SExtImm); - - 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: { - // Doing this post-RA would require dataflow analysis to reliably find uses - // of the CR register set by the compare. - // No need to fixup killed/dead flag since this transformation is only valid - // before RA. - if (PostRA) - return false; - // 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. - bool Changed = false; - Register 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(); - Register TrueReg = CompareUseMI.getOperand(1).getReg(); - Register FalseReg = CompareUseMI.getOperand(2).getReg(); - unsigned RegToCopy = selectReg(SExtImm, SExtComparand, Opc, TrueReg, - FalseReg, CRSubReg); - if (RegToCopy == PPC::NoRegister) - continue; - // Can't use PPC::COPY to copy PPC::ZERO[8]. Convert it to LI[8] 0. - if (RegToCopy == PPC::ZERO || RegToCopy == PPC::ZERO8) { - CompareUseMI.setDesc(get(UseOpc == PPC::ISEL8 ? PPC::LI8 : PPC::LI)); - replaceInstrOperandWithImm(CompareUseMI, 1, 0); - CompareUseMI.RemoveOperand(3); - CompareUseMI.RemoveOperand(2); - continue; - } - LLVM_DEBUG( - dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); - LLVM_DEBUG(DefMI->dump(); MI.dump(); CompareUseMI.dump()); - LLVM_DEBUG(dbgs() << "Is converted to:\n"); - // Convert to copy and remove unneeded operands. - CompareUseMI.setDesc(get(PPC::COPY)); - CompareUseMI.RemoveOperand(3); - CompareUseMI.RemoveOperand(RegToCopy == TrueReg ? 2 : 1); - CmpIselsConverted++; - Changed = true; - LLVM_DEBUG(CompareUseMI.dump()); - } - if (Changed) - 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; - } - return false; - } - case PPC::RLDICL: - case PPC::RLDICL_rec: - 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 || Opc == PPC::RLDICL_rec) ? 64 : 32, - SExtImm, true); - InVal = InVal.rotl(SH); - uint64_t Mask = MB == 0 ? -1LLU : (1LLU << (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 we're setting the CR bit, we will use - // ANDI_rec which won't sign extend, so that's safe. - if (isUInt<15>(InVal.getSExtValue()) || - (Opc == PPC::RLDICL_rec && isUInt<16>(InVal.getSExtValue()))) { - ReplaceWithLI = true; - Is64BitLI = Opc != PPC::RLDICL_32; - NewImm = InVal.getSExtValue(); - SetCR = Opc == PPC::RLDICL_rec; - break; - } - return false; - } - case PPC::RLWINM: - case PPC::RLWINM8: - case PPC::RLWINM_rec: - case PPC::RLWINM8_rec: { - int64_t SH = MI.getOperand(2).getImm(); - int64_t MB = MI.getOperand(3).getImm(); - int64_t ME = MI.getOperand(4).getImm(); - APInt InVal(32, SExtImm, true); - InVal = InVal.rotl(SH); - // Set the bits ( MB + 32 ) to ( ME + 32 ). - uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); - InVal &= Mask; - // Can't replace negative values with an LI as that will sign-extend - // and not clear the left bits. If we're setting the CR bit, we will use - // ANDI_rec which won't sign extend, so that's safe. - bool ValueFits = isUInt<15>(InVal.getSExtValue()); - ValueFits |= ((Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8_rec) && - isUInt<16>(InVal.getSExtValue())); - if (ValueFits) { - ReplaceWithLI = true; - Is64BitLI = Opc == PPC::RLWINM8 || Opc == PPC::RLWINM8_rec; - NewImm = InVal.getSExtValue(); - SetCR = Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8_rec; - 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; - } - } - - if (ReplaceWithLI) { - // We need to be careful with CR-setting instructions we're replacing. - if (SetCR) { - // We don't know anything about uses when we're out of SSA, so only - // replace if the new immediate will be reproduced. - bool ImmChanged = (SExtImm & NewImm) != NewImm; - if (PostRA && ImmChanged) - return false; - - if (!PostRA) { - // If the defining load-immediate has no other uses, we can just replace - // the immediate with the new immediate. - if (MRI->hasOneUse(DefMI->getOperand(0).getReg())) - DefMI->getOperand(1).setImm(NewImm); - - // If we're not using the GPR result of the CR-setting instruction, we - // just need to and with zero/non-zero depending on the new immediate. - else if (MRI->use_empty(MI.getOperand(0).getReg())) { - if (NewImm) { - assert(Immediate && "Transformation converted zero to non-zero?"); - NewImm = Immediate; - } - } - else if (ImmChanged) - return false; - } - } - - LLVM_DEBUG(dbgs() << "Replacing instruction:\n"); - LLVM_DEBUG(MI.dump()); - LLVM_DEBUG(dbgs() << "Fed by:\n"); - LLVM_DEBUG(DefMI->dump()); - LoadImmediateInfo LII; - LII.Imm = NewImm; - LII.Is64Bit = Is64BitLI; - LII.SetCR = SetCR; - // If we're setting the CR, the original load-immediate must be kept (as an - // operand to ANDI_rec/ANDI8_rec). - if (KilledDef && SetCR) - *KilledDef = nullptr; - replaceInstrWithLI(MI, LII); - - // Fixup killed/dead flag after transformation. - // Pattern: - // ForwardingOperandReg = LI imm1 - // y = op2 imm2, ForwardingOperandReg(killed) - if (IsForwardingOperandKilled) - fixupIsDeadOrKill(*DefMI, MI, ForwardingOperandReg); + if (HasImmForm && + transformToImmFormFedByLI(MI, III, ForwardingOperand, *DefMI)) + return true; - LLVM_DEBUG(dbgs() << "With:\n"); - LLVM_DEBUG(MI.dump()); + // If this is not a reg+reg, but the DefMI is LI/LI8, check if its user MI + // can be simpified to LI. + if (!HasImmForm && simplifyToLI(MI, *DefMI, ForwardingOperand, KilledDef)) return true; - } + return false; } @@ -3496,6 +3284,236 @@ return true; } +bool PPCInstrInfo::simplifyToLI(MachineInstr &MI, MachineInstr &DefMI, + unsigned OpNoForForwarding, + MachineInstr **KilledDef) const { + if ((DefMI.getOpcode() != PPC::LI && DefMI.getOpcode() != PPC::LI8) || + !DefMI.getOperand(1).isImm()) + return false; + + MachineFunction *MF = MI.getParent()->getParent(); + MachineRegisterInfo *MRI = &MF->getRegInfo(); + bool PostRA = !MRI->isSSA(); + + int64_t Immediate = DefMI.getOperand(1).getImm(); + // Sign-extend to 64-bits. + int64_t SExtImm = SignExtend64<16>(Immediate); + + bool IsForwardingOperandKilled = MI.getOperand(OpNoForForwarding).isKill(); + Register ForwardingOperandReg = MI.getOperand(OpNoForForwarding).getReg(); + + 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: { + // Doing this post-RA would require dataflow analysis to reliably find uses + // of the CR register set by the compare. + // No need to fixup killed/dead flag since this transformation is only valid + // before RA. + if (PostRA) + return false; + // 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. + bool Changed = false; + Register 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(); + Register TrueReg = CompareUseMI.getOperand(1).getReg(); + Register FalseReg = CompareUseMI.getOperand(2).getReg(); + unsigned RegToCopy = + selectReg(SExtImm, SExtComparand, Opc, TrueReg, FalseReg, CRSubReg); + if (RegToCopy == PPC::NoRegister) + continue; + // Can't use PPC::COPY to copy PPC::ZERO[8]. Convert it to LI[8] 0. + if (RegToCopy == PPC::ZERO || RegToCopy == PPC::ZERO8) { + CompareUseMI.setDesc(get(UseOpc == PPC::ISEL8 ? PPC::LI8 : PPC::LI)); + replaceInstrOperandWithImm(CompareUseMI, 1, 0); + CompareUseMI.RemoveOperand(3); + CompareUseMI.RemoveOperand(2); + continue; + } + LLVM_DEBUG( + dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n"); + LLVM_DEBUG(DefMI.dump(); MI.dump(); CompareUseMI.dump()); + LLVM_DEBUG(dbgs() << "Is converted to:\n"); + // Convert to copy and remove unneeded operands. + CompareUseMI.setDesc(get(PPC::COPY)); + CompareUseMI.RemoveOperand(3); + CompareUseMI.RemoveOperand(RegToCopy == TrueReg ? 2 : 1); + CmpIselsConverted++; + Changed = true; + LLVM_DEBUG(CompareUseMI.dump()); + } + if (Changed) + 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; + } + return false; + } + case PPC::RLDICL: + case PPC::RLDICL_rec: + 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 || Opc == PPC::RLDICL_rec) ? 64 : 32, + SExtImm, true); + InVal = InVal.rotl(SH); + uint64_t Mask = MB == 0 ? -1LLU : (1LLU << (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 we're setting the CR bit, we will use + // ANDI_rec which won't sign extend, so that's safe. + if (isUInt<15>(InVal.getSExtValue()) || + (Opc == PPC::RLDICL_rec && isUInt<16>(InVal.getSExtValue()))) { + ReplaceWithLI = true; + Is64BitLI = Opc != PPC::RLDICL_32; + NewImm = InVal.getSExtValue(); + SetCR = Opc == PPC::RLDICL_rec; + break; + } + return false; + } + case PPC::RLWINM: + case PPC::RLWINM8: + case PPC::RLWINM_rec: + case PPC::RLWINM8_rec: { + int64_t SH = MI.getOperand(2).getImm(); + int64_t MB = MI.getOperand(3).getImm(); + int64_t ME = MI.getOperand(4).getImm(); + APInt InVal(32, SExtImm, true); + InVal = InVal.rotl(SH); + // Set the bits ( MB + 32 ) to ( ME + 32 ). + uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1); + InVal &= Mask; + // Can't replace negative values with an LI as that will sign-extend + // and not clear the left bits. If we're setting the CR bit, we will use + // ANDI_rec which won't sign extend, so that's safe. + bool ValueFits = isUInt<15>(InVal.getSExtValue()); + ValueFits |= ((Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8_rec) && + isUInt<16>(InVal.getSExtValue())); + if (ValueFits) { + ReplaceWithLI = true; + Is64BitLI = Opc == PPC::RLWINM8 || Opc == PPC::RLWINM8_rec; + NewImm = InVal.getSExtValue(); + SetCR = Opc == PPC::RLWINM_rec || Opc == PPC::RLWINM8_rec; + 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; + } + } + + if (ReplaceWithLI) { + // We need to be careful with CR-setting instructions we're replacing. + if (SetCR) { + // We don't know anything about uses when we're out of SSA, so only + // replace if the new immediate will be reproduced. + bool ImmChanged = (SExtImm & NewImm) != NewImm; + if (PostRA && ImmChanged) + return false; + + if (!PostRA) { + // If the defining load-immediate has no other uses, we can just replace + // the immediate with the new immediate. + if (MRI->hasOneUse(DefMI.getOperand(0).getReg())) + DefMI.getOperand(1).setImm(NewImm); + + // If we're not using the GPR result of the CR-setting instruction, we + // just need to and with zero/non-zero depending on the new immediate. + else if (MRI->use_empty(MI.getOperand(0).getReg())) { + if (NewImm) { + assert(Immediate && "Transformation converted zero to non-zero?"); + NewImm = Immediate; + } + } else if (ImmChanged) + return false; + } + } + + LLVM_DEBUG(dbgs() << "Replacing instruction:\n"); + LLVM_DEBUG(MI.dump()); + LLVM_DEBUG(dbgs() << "Fed by:\n"); + LLVM_DEBUG(DefMI.dump()); + LoadImmediateInfo LII; + LII.Imm = NewImm; + LII.Is64Bit = Is64BitLI; + LII.SetCR = SetCR; + // If we're setting the CR, the original load-immediate must be kept (as an + // operand to ANDI_rec/ANDI8_rec). + if (KilledDef && SetCR) + *KilledDef = nullptr; + replaceInstrWithLI(MI, LII); + + // Fixup killed/dead flag after transformation. + // Pattern: + // ForwardingOperandReg = LI imm1 + // y = op2 imm2, ForwardingOperandReg(killed) + if (IsForwardingOperandKilled) + fixupIsDeadOrKill(DefMI, MI, ForwardingOperandReg); + + LLVM_DEBUG(dbgs() << "With:\n"); + LLVM_DEBUG(MI.dump()); + return true; + } + return false; +} + // If an X-Form instruction is fed by an add-immediate and one of its operands // is the literal zero, attempt to forward the source of the add-immediate to // the corresponding D-Form instruction with the displacement coming from @@ -3615,8 +3633,15 @@ bool PPCInstrInfo::transformToImmFormFedByLI(MachineInstr &MI, const ImmInstrInfo &III, unsigned ConstantOpNo, - MachineInstr &DefMI, - int64_t Imm) const { + MachineInstr &DefMI) const { + // DefMI must be LI or LI8. + if ((DefMI.getOpcode() != PPC::LI && DefMI.getOpcode() != PPC::LI8) || + !DefMI.getOperand(1).isImm()) + return false; + + // Get Imm operand and Sign-extend to 64-bits. + int64_t Imm = SignExtend64<16>(DefMI.getOperand(1).getImm()); + MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); bool PostRA = !MRI.isSSA(); // Exit early if we can't convert this.