summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCInstrInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCInstrInfo.cpp')
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp1417
1 files changed, 1338 insertions, 79 deletions
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index e74ba38c351f..ffb5cc8757f2 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -20,7 +20,7 @@
#include "PPCTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/CodeGen/LiveIntervalAnalysis.h"
+#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -46,6 +46,16 @@ using namespace llvm;
#define GET_INSTRINFO_CTOR_DTOR
#include "PPCGenInstrInfo.inc"
+STATISTIC(NumStoreSPILLVSRRCAsVec,
+ "Number of spillvsrrc spilled to stack as vec");
+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<bool> DisableCTRLoopAnal("disable-ppc-ctrloop-analysis", cl::Hidden,
cl::desc("Disable analysis for CTR loops"));
@@ -254,6 +264,7 @@ bool PPCInstrInfo::isCoalescableExtInstr(const MachineInstr &MI,
switch (MI.getOpcode()) {
default: return false;
case PPC::EXTSW:
+ case PPC::EXTSW_32:
case PPC::EXTSW_32_64:
SrcReg = MI.getOperand(1).getReg();
DstReg = MI.getOperand(0).getReg();
@@ -275,11 +286,12 @@ unsigned PPCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
case PPC::RESTORE_CRBIT:
case PPC::LVX:
case PPC::LXVD2X:
- case PPC::LXVX:
+ case PPC::LXV:
case PPC::QVLFDX:
case PPC::QVLFSXs:
case PPC::QVLFDXb:
case PPC::RESTORE_VRSAVE:
+ case PPC::SPILLTOVSR_LD:
// Check for the operands added by addFrameReference (the immediate is the
// offset which defaults to 0).
if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() &&
@@ -328,11 +340,12 @@ unsigned PPCInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
case PPC::SPILL_CRBIT:
case PPC::STVX:
case PPC::STXVD2X:
- case PPC::STXVX:
+ case PPC::STXV:
case PPC::QVSTFDX:
case PPC::QVSTFSXs:
case PPC::QVSTFDXb:
case PPC::SPILL_VRSAVE:
+ case PPC::SPILLTOVSR_ST:
// Check for the operands added by addFrameReference (the immediate is the
// offset which defaults to 0).
if (MI.getOperand(1).isImm() && !MI.getOperand(1).getImm() &&
@@ -486,6 +499,20 @@ bool PPCInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
if (!isUnpredicatedTerminator(*I))
return false;
+ if (AllowModify) {
+ // If the BB ends with an unconditional branch to the fallthrough BB,
+ // we eliminate the branch instruction.
+ if (I->getOpcode() == PPC::B &&
+ MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
+ I->eraseFromParent();
+
+ // We update iterator after deleting the last branch.
+ I = MBB.getLastNonDebugInstr();
+ if (I == MBB.end() || !isUnpredicatedTerminator(*I))
+ return false;
+ }
+ }
+
// Get the last instruction in the block.
MachineInstr &LastInst = *I;
@@ -917,7 +944,18 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
BuildMI(MBB, I, DL, get(PPC::MFOCRF), DestReg).addReg(SrcReg);
getKillRegState(KillSrc);
return;
- }
+ } else if (PPC::G8RCRegClass.contains(SrcReg) &&
+ PPC::VSFRCRegClass.contains(DestReg)) {
+ BuildMI(MBB, I, DL, get(PPC::MTVSRD), DestReg).addReg(SrcReg);
+ NumGPRtoVSRSpill++;
+ getKillRegState(KillSrc);
+ return;
+ } else if (PPC::VSFRCRegClass.contains(SrcReg) &&
+ PPC::G8RCRegClass.contains(DestReg)) {
+ BuildMI(MBB, I, DL, get(PPC::MFVSRD), DestReg).addReg(SrcReg);
+ getKillRegState(KillSrc);
+ return;
+ }
unsigned Opc;
if (PPC::GPRCRegClass.contains(DestReg, SrcReg))
@@ -1015,7 +1053,7 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
FrameIdx));
NonRI = true;
} else if (PPC::VSRCRegClass.hasSubClassEq(RC)) {
- unsigned Op = Subtarget.hasP9Vector() ? PPC::STXVX : PPC::STXVD2X;
+ unsigned Op = Subtarget.hasP9Vector() ? PPC::STXV : PPC::STXVD2X;
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Op))
.addReg(SrcReg,
getKillRegState(isKill)),
@@ -1061,6 +1099,11 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
getKillRegState(isKill)),
FrameIdx));
NonRI = true;
+ } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) {
+ NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILLTOVSR_ST))
+ .addReg(SrcReg,
+ getKillRegState(isKill)),
+ FrameIdx));
} else {
llvm_unreachable("Unknown regclass!");
}
@@ -1148,7 +1191,7 @@ bool PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL,
FrameIdx));
NonRI = true;
} else if (PPC::VSRCRegClass.hasSubClassEq(RC)) {
- unsigned Op = Subtarget.hasP9Vector() ? PPC::LXVX : PPC::LXVD2X;
+ unsigned Op = Subtarget.hasP9Vector() ? PPC::LXV : PPC::LXVD2X;
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(Op), DestReg),
FrameIdx));
NonRI = true;
@@ -1182,6 +1225,9 @@ bool PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, const DebugLoc &DL,
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::QVLFDXb), DestReg),
FrameIdx));
NonRI = true;
+ } else if (PPC::SPILLTOVSRRCRegClass.hasSubClassEq(RC)) {
+ NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILLTOVSR_LD),
+ DestReg), FrameIdx));
} else {
llvm_unreachable("Unknown regclass!");
}
@@ -1592,37 +1638,20 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
// Get the unique definition of SrcReg.
MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
if (!MI) return false;
- int MIOpC = MI->getOpcode();
bool equalityOnly = false;
bool noSub = false;
if (isPPC64) {
if (is32BitSignedCompare) {
// We can perform this optimization only if MI is sign-extending.
- if (MIOpC == PPC::SRAW || MIOpC == PPC::SRAWo ||
- MIOpC == PPC::SRAWI || MIOpC == PPC::SRAWIo ||
- MIOpC == PPC::EXTSB || MIOpC == PPC::EXTSBo ||
- MIOpC == PPC::EXTSH || MIOpC == PPC::EXTSHo ||
- MIOpC == PPC::EXTSW || MIOpC == PPC::EXTSWo) {
+ if (isSignExtended(*MI))
noSub = true;
- } else
+ else
return false;
} else if (is32BitUnsignedCompare) {
- // 32-bit rotate and mask instructions are zero extending only if MB <= ME
- bool isZeroExtendingRotate =
- (MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINMo ||
- MIOpC == PPC::RLWNM || MIOpC == PPC::RLWNMo)
- && MI->getOperand(3).getImm() <= MI->getOperand(4).getImm();
-
// We can perform this optimization, equality only, if MI is
// zero-extending.
- // FIXME: Other possible target instructions include ANDISo and
- // RLWINM aliases, such as ROTRWI, EXTLWI, SLWI and SRWI.
- if (MIOpC == PPC::CNTLZW || MIOpC == PPC::CNTLZWo ||
- MIOpC == PPC::SLW || MIOpC == PPC::SLWo ||
- MIOpC == PPC::SRW || MIOpC == PPC::SRWo ||
- MIOpC == PPC::ANDIo ||
- isZeroExtendingRotate) {
+ if (isZeroExtended(*MI)) {
noSub = true;
equalityOnly = true;
} else
@@ -1640,8 +1669,10 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
I != IE; ++I) {
MachineInstr *UseMI = &*I;
if (UseMI->getOpcode() == PPC::BCC) {
- unsigned Pred = UseMI->getOperand(0).getImm();
- if (Pred != PPC::PRED_EQ && Pred != PPC::PRED_NE)
+ PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm();
+ unsigned PredCond = PPC::getPredicateCondition(Pred);
+ // We ignore hint bits when checking for non-equality comparisons.
+ if (PredCond != PPC::PRED_EQ && PredCond != PPC::PRED_NE)
return false;
} else if (UseMI->getOpcode() == PPC::ISEL ||
UseMI->getOpcode() == PPC::ISEL8) {
@@ -1688,34 +1719,47 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
else if (MI->getParent() != CmpInstr.getParent())
return false;
else if (Value != 0) {
- // The record-form instructions set CR bit based on signed comparison against 0.
- // We try to convert a compare against 1 or -1 into a compare against 0.
- bool Success = false;
- if (!equalityOnly && MRI->hasOneUse(CRReg)) {
- MachineInstr *UseMI = &*MRI->use_instr_begin(CRReg);
- if (UseMI->getOpcode() == PPC::BCC) {
- PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm();
- int16_t Immed = (int16_t)Value;
-
- if (Immed == -1 && Pred == PPC::PRED_GT) {
- // We convert "greater than -1" into "greater than or equal to 0",
- // since we are assuming signed comparison by !equalityOnly
- PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
- PPC::PRED_GE));
- Success = true;
- }
- else if (Immed == 1 && Pred == PPC::PRED_LT) {
- // We convert "less than 1" into "less than or equal to 0".
- PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
- PPC::PRED_LE));
- Success = true;
- }
- }
- }
+ // The record-form instructions set CR bit based on signed comparison
+ // against 0. We try to convert a compare against 1 or -1 into a compare
+ // against 0 to exploit record-form instructions. For example, we change
+ // the condition "greater than -1" into "greater than or equal to 0"
+ // and "less than 1" into "less than or equal to 0".
+
+ // Since we optimize comparison based on a specific branch condition,
+ // we don't optimize if condition code is used by more than once.
+ if (equalityOnly || !MRI->hasOneUse(CRReg))
+ return false;
+
+ MachineInstr *UseMI = &*MRI->use_instr_begin(CRReg);
+ if (UseMI->getOpcode() != PPC::BCC)
+ return false;
- // PPC does not have a record-form SUBri.
- if (!Success)
+ PPC::Predicate Pred = (PPC::Predicate)UseMI->getOperand(0).getImm();
+ PPC::Predicate NewPred = Pred;
+ unsigned PredCond = PPC::getPredicateCondition(Pred);
+ unsigned PredHint = PPC::getPredicateHint(Pred);
+ int16_t Immed = (int16_t)Value;
+
+ // When modyfing the condition in the predicate, we propagate hint bits
+ // from the original predicate to the new one.
+ if (Immed == -1 && PredCond == PPC::PRED_GT)
+ // We convert "greater than -1" into "greater than or equal to 0",
+ // since we are assuming signed comparison by !equalityOnly
+ NewPred = PPC::getPredicate(PPC::PRED_GE, PredHint);
+ else if (Immed == -1 && PredCond == PPC::PRED_LE)
+ // We convert "less than or equal to -1" into "less than 0".
+ NewPred = PPC::getPredicate(PPC::PRED_LT, PredHint);
+ else if (Immed == 1 && PredCond == PPC::PRED_LT)
+ // We convert "less than 1" into "less than or equal to 0".
+ NewPred = PPC::getPredicate(PPC::PRED_LE, PredHint);
+ else if (Immed == 1 && PredCond == PPC::PRED_GE)
+ // We convert "greater than or equal to 1" into "greater than 0".
+ NewPred = PPC::getPredicate(PPC::PRED_GT, PredHint);
+ else
return false;
+
+ PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
+ NewPred));
}
// Search for Sub.
@@ -1763,7 +1807,7 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
if (!MI) MI = Sub;
int NewOpC = -1;
- MIOpC = MI->getOpcode();
+ int MIOpC = MI->getOpcode();
if (MIOpC == PPC::ANDIo || MIOpC == PPC::ANDIo8)
NewOpC = MIOpC;
else {
@@ -1804,9 +1848,11 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
MachineInstr *UseMI = &*I;
if (UseMI->getOpcode() == PPC::BCC) {
PPC::Predicate Pred = (PPC::Predicate) UseMI->getOperand(0).getImm();
+ unsigned PredCond = PPC::getPredicateCondition(Pred);
assert((!equalityOnly ||
- Pred == PPC::PRED_EQ || Pred == PPC::PRED_NE) &&
+ PredCond == PPC::PRED_EQ || PredCond == PPC::PRED_NE) &&
"Invalid predicate for equality-only optimization");
+ (void)PredCond; // To suppress warning in release build.
PredsToUpdate.push_back(std::make_pair(&(UseMI->getOperand(0)),
PPC::getSwappedPredicate(Pred)));
} else if (UseMI->getOpcode() == PPC::ISEL ||
@@ -1935,29 +1981,13 @@ PPCInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
return makeArrayRef(TargetFlags);
}
-bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
- auto &MBB = *MI.getParent();
- auto DL = MI.getDebugLoc();
- switch (MI.getOpcode()) {
- case TargetOpcode::LOAD_STACK_GUARD: {
- assert(Subtarget.isTargetLinux() &&
- "Only Linux target is expected to contain LOAD_STACK_GUARD");
- const int64_t Offset = Subtarget.isPPC64() ? -0x7010 : -0x7008;
- const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2;
- MI.setDesc(get(Subtarget.isPPC64() ? PPC::LD : PPC::LWZ));
- MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addImm(Offset)
- .addReg(Reg);
- return true;
- }
- case PPC::DFLOADf32:
- case PPC::DFLOADf64:
- case PPC::DFSTOREf32:
- case PPC::DFSTOREf64: {
- assert(Subtarget.hasP9Vector() &&
- "Invalid D-Form Pseudo-ops on non-P9 target.");
- assert(MI.getOperand(2).isReg() && MI.getOperand(1).isImm() &&
- "D-form op must have register and immediate operands");
+// Expand VSX Memory Pseudo instruction to either a VSX or a FP instruction.
+// The VSX versions have the advantage of a full 64-register target whereas
+// the FP ones have the advantage of lower latency and higher throughput. So
+// what we are after is using the faster instructions in low register pressure
+// situations and using the larger register file in high register pressure
+// situations.
+bool PPCInstrInfo::expandVSXMemPseudo(MachineInstr &MI) const {
unsigned UpperOpcode, LowerOpcode;
switch (MI.getOpcode()) {
case PPC::DFLOADf32:
@@ -1976,7 +2006,38 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
UpperOpcode = PPC::STXSD;
LowerOpcode = PPC::STFD;
break;
+ case PPC::XFLOADf32:
+ UpperOpcode = PPC::LXSSPX;
+ LowerOpcode = PPC::LFSX;
+ break;
+ case PPC::XFLOADf64:
+ UpperOpcode = PPC::LXSDX;
+ LowerOpcode = PPC::LFDX;
+ break;
+ case PPC::XFSTOREf32:
+ UpperOpcode = PPC::STXSSPX;
+ LowerOpcode = PPC::STFSX;
+ break;
+ case PPC::XFSTOREf64:
+ UpperOpcode = PPC::STXSDX;
+ LowerOpcode = PPC::STFDX;
+ break;
+ case PPC::LIWAX:
+ UpperOpcode = PPC::LXSIWAX;
+ LowerOpcode = PPC::LFIWAX;
+ break;
+ case PPC::LIWZX:
+ UpperOpcode = PPC::LXSIWZX;
+ LowerOpcode = PPC::LFIWZX;
+ break;
+ case PPC::STIWX:
+ UpperOpcode = PPC::STXSIWX;
+ LowerOpcode = PPC::STFIWX;
+ break;
+ default:
+ llvm_unreachable("Unknown Operation!");
}
+
unsigned TargetReg = MI.getOperand(0).getReg();
unsigned Opcode;
if ((TargetReg >= PPC::F0 && TargetReg <= PPC::F31) ||
@@ -1986,7 +2047,95 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
Opcode = UpperOpcode;
MI.setDesc(get(Opcode));
return true;
+}
+
+bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+ auto &MBB = *MI.getParent();
+ auto DL = MI.getDebugLoc();
+
+ switch (MI.getOpcode()) {
+ case TargetOpcode::LOAD_STACK_GUARD: {
+ assert(Subtarget.isTargetLinux() &&
+ "Only Linux target is expected to contain LOAD_STACK_GUARD");
+ const int64_t Offset = Subtarget.isPPC64() ? -0x7010 : -0x7008;
+ const unsigned Reg = Subtarget.isPPC64() ? PPC::X13 : PPC::R2;
+ MI.setDesc(get(Subtarget.isPPC64() ? PPC::LD : PPC::LWZ));
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI)
+ .addImm(Offset)
+ .addReg(Reg);
+ return true;
}
+ case PPC::DFLOADf32:
+ case PPC::DFLOADf64:
+ case PPC::DFSTOREf32:
+ case PPC::DFSTOREf64: {
+ assert(Subtarget.hasP9Vector() &&
+ "Invalid D-Form Pseudo-ops on Pre-P9 target.");
+ assert(MI.getOperand(2).isReg() && MI.getOperand(1).isImm() &&
+ "D-form op must have register and immediate operands");
+ return expandVSXMemPseudo(MI);
+ }
+ case PPC::XFLOADf32:
+ case PPC::XFSTOREf32:
+ case PPC::LIWAX:
+ case PPC::LIWZX:
+ case PPC::STIWX: {
+ assert(Subtarget.hasP8Vector() &&
+ "Invalid X-Form Pseudo-ops on Pre-P8 target.");
+ assert(MI.getOperand(2).isReg() && MI.getOperand(1).isReg() &&
+ "X-form op must have register and register operands");
+ return expandVSXMemPseudo(MI);
+ }
+ case PPC::XFLOADf64:
+ case PPC::XFSTOREf64: {
+ assert(Subtarget.hasVSX() &&
+ "Invalid X-Form Pseudo-ops on target that has no VSX.");
+ assert(MI.getOperand(2).isReg() && MI.getOperand(1).isReg() &&
+ "X-form op must have register and register operands");
+ return expandVSXMemPseudo(MI);
+ }
+ case PPC::SPILLTOVSR_LD: {
+ unsigned TargetReg = MI.getOperand(0).getReg();
+ if (PPC::VSFRCRegClass.contains(TargetReg)) {
+ MI.setDesc(get(PPC::DFLOADf64));
+ return expandPostRAPseudo(MI);
+ }
+ else
+ MI.setDesc(get(PPC::LD));
+ return true;
+ }
+ case PPC::SPILLTOVSR_ST: {
+ unsigned SrcReg = MI.getOperand(0).getReg();
+ if (PPC::VSFRCRegClass.contains(SrcReg)) {
+ NumStoreSPILLVSRRCAsVec++;
+ MI.setDesc(get(PPC::DFSTOREf64));
+ return expandPostRAPseudo(MI);
+ } else {
+ NumStoreSPILLVSRRCAsGpr++;
+ MI.setDesc(get(PPC::STD));
+ }
+ return true;
+ }
+ case PPC::SPILLTOVSR_LDX: {
+ unsigned TargetReg = MI.getOperand(0).getReg();
+ if (PPC::VSFRCRegClass.contains(TargetReg))
+ MI.setDesc(get(PPC::LXSDX));
+ else
+ MI.setDesc(get(PPC::LDX));
+ return true;
+ }
+ case PPC::SPILLTOVSR_STX: {
+ unsigned SrcReg = MI.getOperand(0).getReg();
+ if (PPC::VSFRCRegClass.contains(SrcReg)) {
+ NumStoreSPILLVSRRCAsVec++;
+ MI.setDesc(get(PPC::STXSDX));
+ } else {
+ NumStoreSPILLVSRRCAsGpr++;
+ MI.setDesc(get(PPC::STDX));
+ }
+ return true;
+ }
+
case PPC::CFENCE8: {
auto Val = MI.getOperand(0).getReg();
BuildMI(MBB, MI, DL, get(PPC::CMPD), PPC::CR7).addReg(Val).addReg(Val);
@@ -2002,6 +2151,829 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
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 PPC::NoRegister;
+}
+
+// Replace an instruction with one that materializes a constant (and sets
+// CR0 if the original instruction was a record-form instruction).
+void PPCInstrInfo::replaceInstrWithLI(MachineInstr &MI,
+ const LoadImmediateInfo &LII) const {
+ // Remove existing operands.
+ int OperandToKeep = LII.SetCR ? 1 : 0;
+ for (int i = MI.getNumOperands() - 1; i > OperandToKeep; i--)
+ MI.RemoveOperand(i);
+
+ // Replace the instruction.
+ if (LII.SetCR) {
+ MI.setDesc(get(LII.Is64Bit ? PPC::ANDIo8 : PPC::ANDIo));
+ // Set the immediate.
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI)
+ .addImm(LII.Imm).addReg(PPC::CR0, RegState::ImplicitDefine);
+ return;
+ }
+ else
+ MI.setDesc(get(LII.Is64Bit ? PPC::LI8 : PPC::LI));
+
+ // Set the immediate.
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI)
+ .addImm(LII.Imm);
+}
+
+MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI,
+ unsigned &ConstOp,
+ bool &SeenIntermediateUse) const {
+ ConstOp = ~0U;
+ MachineInstr *DefMI = nullptr;
+ MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo();
+ // If we'ere in SSA, get the defs through the MRI. Otherwise, only look
+ // within the basic block to see if the register is defined using an LI/LI8.
+ if (MRI->isSSA()) {
+ 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) {
+ ConstOp = i;
+ break;
+ }
+ }
+ }
+ } else {
+ // Looking back through the definition for each operand could be expensive,
+ // so exit early if this isn't an instruction that either has an immediate
+ // form or is already an immediate form that we can handle.
+ ImmInstrInfo III;
+ unsigned Opc = MI.getOpcode();
+ bool ConvertibleImmForm =
+ Opc == PPC::CMPWI || Opc == PPC::CMPLWI ||
+ Opc == PPC::CMPDI || Opc == PPC::CMPLDI ||
+ Opc == PPC::ADDI || Opc == PPC::ADDI8 ||
+ Opc == PPC::ORI || Opc == PPC::ORI8 ||
+ Opc == PPC::XORI || Opc == PPC::XORI8 ||
+ Opc == PPC::RLDICL || Opc == PPC::RLDICLo ||
+ Opc == PPC::RLDICL_32 || Opc == PPC::RLDICL_32_64 ||
+ Opc == PPC::RLWINM || Opc == PPC::RLWINMo ||
+ Opc == PPC::RLWINM8 || Opc == PPC::RLWINM8o;
+ if (!instrHasImmForm(MI, III) && !ConvertibleImmForm)
+ return nullptr;
+
+ // Don't convert or %X, %Y, %Y since that's just a register move.
+ if ((Opc == PPC::OR || Opc == PPC::OR8) &&
+ MI.getOperand(1).getReg() == MI.getOperand(2).getReg())
+ return nullptr;
+ for (int i = 1, e = MI.getNumOperands(); i < e; i++) {
+ MachineOperand &MO = MI.getOperand(i);
+ SeenIntermediateUse = false;
+ if (MO.isReg() && MO.isUse() && !MO.isImplicit()) {
+ MachineBasicBlock::reverse_iterator E = MI.getParent()->rend(), It = MI;
+ It++;
+ unsigned Reg = MI.getOperand(i).getReg();
+ // MachineInstr::readsRegister only returns true if the machine
+ // instruction reads the exact register or its super-register. It
+ // does not consider uses of sub-registers which seems like strange
+ // behaviour. Nonetheless, if we end up with a 64-bit register here,
+ // get the corresponding 32-bit register to check.
+ if (PPC::G8RCRegClass.contains(Reg))
+ Reg = Reg - PPC::X0 + PPC::R0;
+
+ // Is this register defined by a load-immediate in this block?
+ for ( ; It != E; ++It) {
+ if (It->modifiesRegister(Reg, &getRegisterInfo())) {
+ if (It->getOpcode() == PPC::LI || It->getOpcode() == PPC::LI8) {
+ ConstOp = i;
+ return &*It;
+ } else
+ break;
+ } else if (It->readsRegister(Reg, &getRegisterInfo()))
+ // If we see another use of this reg between the def and the MI,
+ // we want to flat it so the def isn't deleted.
+ SeenIntermediateUse = true;
+ }
+ }
+ }
+ }
+ return ConstOp == ~0U ? nullptr : DefMI;
+}
+
+// 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,
+ MachineInstr **KilledDef) const {
+ MachineFunction *MF = MI.getParent()->getParent();
+ MachineRegisterInfo *MRI = &MF->getRegInfo();
+ bool PostRA = !MRI->isSSA();
+ bool SeenIntermediateUse = true;
+ unsigned ConstantOperand = ~0U;
+ MachineInstr *DefMI = getConstantDefMI(MI, ConstantOperand,
+ SeenIntermediateUse);
+ if (!DefMI || !DefMI->getOperand(1).isImm())
+ return false;
+ assert(ConstantOperand < MI.getNumOperands() &&
+ "The constant operand needs to be valid at this point");
+
+ int64_t Immediate = DefMI->getOperand(1).getImm();
+ // Sign-extend to 64-bits.
+ int64_t SExtImm = ((uint64_t)Immediate & ~0x7FFFuLL) != 0 ?
+ (Immediate | 0xFFFFFFFFFFFF0000) : Immediate;
+
+ if (KilledDef && MI.getOperand(ConstantOperand).isKill() &&
+ !SeenIntermediateUse)
+ *KilledDef = DefMI;
+
+ // If this is a reg+reg instruction that has a reg+imm form, convert it now.
+ ImmInstrInfo III;
+ if (instrHasImmForm(MI, III))
+ return transformToImmForm(MI, III, ConstantOperand, 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.
+ 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;
+ 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);
+ 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));
+ CompareUseMI.getOperand(1).ChangeToImmediate(0);
+ CompareUseMI.RemoveOperand(3);
+ CompareUseMI.RemoveOperand(2);
+ continue;
+ }
+ DEBUG(dbgs() << "Found LI -> CMPI -> ISEL, replacing with a copy.\n");
+ DEBUG(DefMI->dump(); MI.dump(); CompareUseMI.dump());
+ 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;
+ 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::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 we're setting the CR bit, we will use
+ // ANDIo which won't sign extend, so that's safe.
+ if (isUInt<15>(InVal.getSExtValue()) ||
+ (Opc == PPC::RLDICLo && isUInt<16>(InVal.getSExtValue()))) {
+ ReplaceWithLI = true;
+ Is64BitLI = Opc != PPC::RLDICL_32;
+ NewImm = InVal.getSExtValue();
+ SetCR = Opc == PPC::RLDICLo;
+ break;
+ }
+ return false;
+ }
+ case PPC::RLWINM:
+ case PPC::RLWINM8:
+ case PPC::RLWINMo:
+ case PPC::RLWINM8o: {
+ 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 = ((1 << (32 - MB)) - 1) & ~((1 << (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
+ // ANDIo which won't sign extend, so that's safe.
+ bool ValueFits = isUInt<15>(InVal.getSExtValue());
+ ValueFits |= ((Opc == PPC::RLWINMo || Opc == PPC::RLWINM8o) &&
+ isUInt<16>(InVal.getSExtValue()));
+ if (ValueFits) {
+ ReplaceWithLI = true;
+ Is64BitLI = Opc == PPC::RLWINM8 || Opc == PPC::RLWINM8o;
+ NewImm = InVal.getSExtValue();
+ SetCR = Opc == PPC::RLWINMo || Opc == PPC::RLWINM8o;
+ 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) {
+ DEBUG(dbgs() << "Replacing instruction:\n");
+ DEBUG(MI.dump());
+ DEBUG(dbgs() << "Fed by:\n");
+ 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 ANDIo/ANDI8o).
+ if (KilledDef && SetCR)
+ *KilledDef = nullptr;
+ replaceInstrWithLI(MI, LII);
+ DEBUG(dbgs() << "With:\n");
+ DEBUG(MI.dump());
+ return true;
+ }
+ return false;
+}
+
+bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
+ ImmInstrInfo &III) const {
+ unsigned Opc = MI.getOpcode();
+ // The vast majority of the instructions would need their operand 2 replaced
+ // with an immediate when switching to the reg+imm form. A marked exception
+ // are the update form loads/stores for which a constant operand 2 would need
+ // to turn into a displacement and move operand 1 to the operand 2 position.
+ III.ImmOpNo = 2;
+ III.ConstantOpNo = 2;
+ III.ImmWidth = 16;
+ III.ImmMustBeMultipleOf = 1;
+ switch (Opc) {
+ default: return false;
+ case PPC::ADD4:
+ case PPC::ADD8:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 1;
+ III.IsCommutative = true;
+ III.ImmOpcode = Opc == PPC::ADD4 ? PPC::ADDI : PPC::ADDI8;
+ break;
+ case PPC::ADDC:
+ case PPC::ADDC8:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = true;
+ III.ImmOpcode = Opc == PPC::ADDC ? PPC::ADDIC : PPC::ADDIC8;
+ break;
+ case PPC::ADDCo:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = true;
+ III.ImmOpcode = PPC::ADDICo;
+ break;
+ case PPC::SUBFC:
+ case PPC::SUBFC8:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = false;
+ III.ImmOpcode = Opc == PPC::SUBFC ? PPC::SUBFIC : PPC::SUBFIC8;
+ break;
+ case PPC::CMPW:
+ case PPC::CMPD:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = false;
+ III.ImmOpcode = Opc == PPC::CMPW ? PPC::CMPWI : PPC::CMPDI;
+ break;
+ case PPC::CMPLW:
+ case PPC::CMPLD:
+ III.SignedImm = false;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = false;
+ III.ImmOpcode = Opc == PPC::CMPLW ? PPC::CMPLWI : PPC::CMPLDI;
+ break;
+ case PPC::ANDo:
+ case PPC::AND8o:
+ case PPC::OR:
+ case PPC::OR8:
+ case PPC::XOR:
+ case PPC::XOR8:
+ III.SignedImm = false;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = true;
+ switch(Opc) {
+ default: llvm_unreachable("Unknown opcode");
+ case PPC::ANDo: III.ImmOpcode = PPC::ANDIo; break;
+ case PPC::AND8o: III.ImmOpcode = PPC::ANDIo8; break;
+ case PPC::OR: III.ImmOpcode = PPC::ORI; break;
+ case PPC::OR8: III.ImmOpcode = PPC::ORI8; break;
+ case PPC::XOR: III.ImmOpcode = PPC::XORI; break;
+ case PPC::XOR8: III.ImmOpcode = PPC::XORI8; break;
+ }
+ break;
+ case PPC::RLWNM:
+ case PPC::RLWNM8:
+ case PPC::RLWNMo:
+ case PPC::RLWNM8o:
+ case PPC::RLDCL:
+ case PPC::RLDCLo:
+ case PPC::RLDCR:
+ case PPC::RLDCRo:
+ case PPC::SLW:
+ case PPC::SLW8:
+ case PPC::SLWo:
+ case PPC::SLW8o:
+ case PPC::SRW:
+ case PPC::SRW8:
+ case PPC::SRWo:
+ case PPC::SRW8o:
+ case PPC::SRAW:
+ case PPC::SRAWo:
+ case PPC::SLD:
+ case PPC::SLDo:
+ case PPC::SRD:
+ case PPC::SRDo:
+ case PPC::SRAD:
+ case PPC::SRADo:
+ III.SignedImm = false;
+ III.ZeroIsSpecialOrig = 0;
+ III.ZeroIsSpecialNew = 0;
+ III.IsCommutative = false;
+ // This isn't actually true, but the instructions ignore any of the
+ // upper bits, so any immediate loaded with an LI is acceptable.
+ III.ImmWidth = 16;
+ switch(Opc) {
+ default: llvm_unreachable("Unknown opcode");
+ case PPC::RLWNM: III.ImmOpcode = PPC::RLWINM; break;
+ case PPC::RLWNM8: III.ImmOpcode = PPC::RLWINM8; break;
+ case PPC::RLWNMo: III.ImmOpcode = PPC::RLWINMo; break;
+ case PPC::RLWNM8o: III.ImmOpcode = PPC::RLWINM8o; break;
+ case PPC::RLDCL: III.ImmOpcode = PPC::RLDICL; break;
+ case PPC::RLDCLo: III.ImmOpcode = PPC::RLDICLo; break;
+ case PPC::RLDCR: III.ImmOpcode = PPC::RLDICR; break;
+ case PPC::RLDCRo: III.ImmOpcode = PPC::RLDICRo; break;
+ case PPC::SLW: III.ImmOpcode = PPC::RLWINM; break;
+ case PPC::SLW8: III.ImmOpcode = PPC::RLWINM8; break;
+ case PPC::SLWo: III.ImmOpcode = PPC::RLWINMo; break;
+ case PPC::SLW8o: III.ImmOpcode = PPC::RLWINM8o; break;
+ case PPC::SRW: III.ImmOpcode = PPC::RLWINM; break;
+ case PPC::SRW8: III.ImmOpcode = PPC::RLWINM8; break;
+ case PPC::SRWo: III.ImmOpcode = PPC::RLWINMo; break;
+ case PPC::SRW8o: III.ImmOpcode = PPC::RLWINM8o; break;
+ case PPC::SRAW: III.ImmOpcode = PPC::SRAWI; break;
+ case PPC::SRAWo: III.ImmOpcode = PPC::SRAWIo; break;
+ case PPC::SLD: III.ImmOpcode = PPC::RLDICR; break;
+ case PPC::SLDo: III.ImmOpcode = PPC::RLDICRo; break;
+ case PPC::SRD: III.ImmOpcode = PPC::RLDICL; break;
+ case PPC::SRDo: III.ImmOpcode = PPC::RLDICLo; break;
+ case PPC::SRAD: III.ImmOpcode = PPC::SRADI; break;
+ case PPC::SRADo: III.ImmOpcode = PPC::SRADIo; break;
+ }
+ break;
+ // Loads and stores:
+ case PPC::LBZX:
+ case PPC::LBZX8:
+ case PPC::LHZX:
+ case PPC::LHZX8:
+ case PPC::LHAX:
+ case PPC::LHAX8:
+ case PPC::LWZX:
+ case PPC::LWZX8:
+ case PPC::LWAX:
+ case PPC::LDX:
+ case PPC::LFSX:
+ case PPC::LFDX:
+ case PPC::STBX:
+ case PPC::STBX8:
+ case PPC::STHX:
+ case PPC::STHX8:
+ case PPC::STWX:
+ case PPC::STWX8:
+ case PPC::STDX:
+ case PPC::STFSX:
+ case PPC::STFDX:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 1;
+ III.ZeroIsSpecialNew = 2;
+ III.IsCommutative = true;
+ III.ImmOpNo = 1;
+ III.ConstantOpNo = 2;
+ switch(Opc) {
+ default: llvm_unreachable("Unknown opcode");
+ case PPC::LBZX: III.ImmOpcode = PPC::LBZ; break;
+ case PPC::LBZX8: III.ImmOpcode = PPC::LBZ8; break;
+ case PPC::LHZX: III.ImmOpcode = PPC::LHZ; break;
+ case PPC::LHZX8: III.ImmOpcode = PPC::LHZ8; break;
+ case PPC::LHAX: III.ImmOpcode = PPC::LHA; break;
+ case PPC::LHAX8: III.ImmOpcode = PPC::LHA8; break;
+ case PPC::LWZX: III.ImmOpcode = PPC::LWZ; break;
+ case PPC::LWZX8: III.ImmOpcode = PPC::LWZ8; break;
+ case PPC::LWAX:
+ III.ImmOpcode = PPC::LWA;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::LDX: III.ImmOpcode = PPC::LD; III.ImmMustBeMultipleOf = 4; break;
+ case PPC::LFSX: III.ImmOpcode = PPC::LFS; break;
+ case PPC::LFDX: III.ImmOpcode = PPC::LFD; break;
+ case PPC::STBX: III.ImmOpcode = PPC::STB; break;
+ case PPC::STBX8: III.ImmOpcode = PPC::STB8; break;
+ case PPC::STHX: III.ImmOpcode = PPC::STH; break;
+ case PPC::STHX8: III.ImmOpcode = PPC::STH8; break;
+ case PPC::STWX: III.ImmOpcode = PPC::STW; break;
+ case PPC::STWX8: III.ImmOpcode = PPC::STW8; break;
+ case PPC::STDX:
+ III.ImmOpcode = PPC::STD;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::STFSX: III.ImmOpcode = PPC::STFS; break;
+ case PPC::STFDX: III.ImmOpcode = PPC::STFD; break;
+ }
+ break;
+ case PPC::LBZUX:
+ case PPC::LBZUX8:
+ case PPC::LHZUX:
+ case PPC::LHZUX8:
+ case PPC::LHAUX:
+ case PPC::LHAUX8:
+ case PPC::LWZUX:
+ case PPC::LWZUX8:
+ case PPC::LDUX:
+ case PPC::LFSUX:
+ case PPC::LFDUX:
+ case PPC::STBUX:
+ case PPC::STBUX8:
+ case PPC::STHUX:
+ case PPC::STHUX8:
+ case PPC::STWUX:
+ case PPC::STWUX8:
+ case PPC::STDUX:
+ case PPC::STFSUX:
+ case PPC::STFDUX:
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 2;
+ III.ZeroIsSpecialNew = 3;
+ III.IsCommutative = false;
+ III.ImmOpNo = 2;
+ III.ConstantOpNo = 3;
+ switch(Opc) {
+ default: llvm_unreachable("Unknown opcode");
+ case PPC::LBZUX: III.ImmOpcode = PPC::LBZU; break;
+ case PPC::LBZUX8: III.ImmOpcode = PPC::LBZU8; break;
+ case PPC::LHZUX: III.ImmOpcode = PPC::LHZU; break;
+ case PPC::LHZUX8: III.ImmOpcode = PPC::LHZU8; break;
+ case PPC::LHAUX: III.ImmOpcode = PPC::LHAU; break;
+ case PPC::LHAUX8: III.ImmOpcode = PPC::LHAU8; break;
+ case PPC::LWZUX: III.ImmOpcode = PPC::LWZU; break;
+ case PPC::LWZUX8: III.ImmOpcode = PPC::LWZU8; break;
+ case PPC::LDUX:
+ III.ImmOpcode = PPC::LDU;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::LFSUX: III.ImmOpcode = PPC::LFSU; break;
+ case PPC::LFDUX: III.ImmOpcode = PPC::LFDU; break;
+ case PPC::STBUX: III.ImmOpcode = PPC::STBU; break;
+ case PPC::STBUX8: III.ImmOpcode = PPC::STBU8; break;
+ case PPC::STHUX: III.ImmOpcode = PPC::STHU; break;
+ case PPC::STHUX8: III.ImmOpcode = PPC::STHU8; break;
+ case PPC::STWUX: III.ImmOpcode = PPC::STWU; break;
+ case PPC::STWUX8: III.ImmOpcode = PPC::STWU8; break;
+ case PPC::STDUX:
+ III.ImmOpcode = PPC::STDU;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::STFSUX: III.ImmOpcode = PPC::STFSU; break;
+ case PPC::STFDUX: III.ImmOpcode = PPC::STFDU; break;
+ }
+ break;
+ // Power9 only.
+ case PPC::LXVX:
+ case PPC::LXSSPX:
+ case PPC::LXSDX:
+ case PPC::STXVX:
+ case PPC::STXSSPX:
+ case PPC::STXSDX:
+ if (!Subtarget.hasP9Vector())
+ return false;
+ III.SignedImm = true;
+ III.ZeroIsSpecialOrig = 1;
+ III.ZeroIsSpecialNew = 2;
+ III.IsCommutative = true;
+ III.ImmOpNo = 1;
+ III.ConstantOpNo = 2;
+ switch(Opc) {
+ default: llvm_unreachable("Unknown opcode");
+ case PPC::LXVX:
+ III.ImmOpcode = PPC::LXV;
+ III.ImmMustBeMultipleOf = 16;
+ break;
+ case PPC::LXSSPX:
+ III.ImmOpcode = PPC::LXSSP;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::LXSDX:
+ III.ImmOpcode = PPC::LXSD;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::STXVX:
+ III.ImmOpcode = PPC::STXV;
+ III.ImmMustBeMultipleOf = 16;
+ break;
+ case PPC::STXSSPX:
+ III.ImmOpcode = PPC::STXSSP;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ case PPC::STXSDX:
+ III.ImmOpcode = PPC::STXSD;
+ III.ImmMustBeMultipleOf = 4;
+ break;
+ }
+ break;
+ }
+ return true;
+}
+
+// Utility function for swaping two arbitrary operands of an instruction.
+static void swapMIOperands(MachineInstr &MI, unsigned Op1, unsigned Op2) {
+ assert(Op1 != Op2 && "Cannot swap operand with itself.");
+
+ unsigned MaxOp = std::max(Op1, Op2);
+ unsigned MinOp = std::min(Op1, Op2);
+ MachineOperand MOp1 = MI.getOperand(MinOp);
+ MachineOperand MOp2 = MI.getOperand(MaxOp);
+ MI.RemoveOperand(std::max(Op1, Op2));
+ MI.RemoveOperand(std::min(Op1, Op2));
+
+ // If the operands we are swapping are the two at the end (the common case)
+ // we can just remove both and add them in the opposite order.
+ if (MaxOp - MinOp == 1 && MI.getNumOperands() == MinOp) {
+ MI.addOperand(MOp2);
+ MI.addOperand(MOp1);
+ } else {
+ // Store all operands in a temporary vector, remove them and re-add in the
+ // right order.
+ SmallVector<MachineOperand, 2> MOps;
+ unsigned TotalOps = MI.getNumOperands() + 2; // We've already removed 2 ops.
+ for (unsigned i = MI.getNumOperands() - 1; i >= MinOp; i--) {
+ MOps.push_back(MI.getOperand(i));
+ MI.RemoveOperand(i);
+ }
+ // MOp2 needs to be added next.
+ MI.addOperand(MOp2);
+ // Now add the rest.
+ for (unsigned i = MI.getNumOperands(); i < TotalOps; i++) {
+ if (i == MaxOp)
+ MI.addOperand(MOp1);
+ else {
+ MI.addOperand(MOps.back());
+ MOps.pop_back();
+ }
+ }
+ }
+}
+
+bool PPCInstrInfo::transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III,
+ unsigned ConstantOpNo,
+ int64_t Imm) const {
+ MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+ bool PostRA = !MRI.isSSA();
+ // Exit early if we can't convert this.
+ if ((ConstantOpNo != III.ConstantOpNo) && !III.IsCommutative)
+ return false;
+ if (Imm % III.ImmMustBeMultipleOf)
+ return false;
+ if (III.SignedImm) {
+ APInt ActualValue(64, Imm, true);
+ if (!ActualValue.isSignedIntN(III.ImmWidth))
+ return false;
+ } else {
+ uint64_t UnsignedMax = (1 << III.ImmWidth) - 1;
+ if ((uint64_t)Imm > UnsignedMax)
+ return false;
+ }
+
+ // If we're post-RA, the instructions don't agree on whether register zero is
+ // special, we can transform this as long as the register operand that will
+ // end up in the location where zero is special isn't R0.
+ if (PostRA && III.ZeroIsSpecialOrig != III.ZeroIsSpecialNew) {
+ unsigned PosForOrigZero = III.ZeroIsSpecialOrig ? III.ZeroIsSpecialOrig :
+ III.ZeroIsSpecialNew + 1;
+ unsigned OrigZeroReg = MI.getOperand(PosForOrigZero).getReg();
+ unsigned NewZeroReg = MI.getOperand(III.ZeroIsSpecialNew).getReg();
+ // If R0 is in the operand where zero is special for the new instruction,
+ // it is unsafe to transform if the constant operand isn't that operand.
+ if ((NewZeroReg == PPC::R0 || NewZeroReg == PPC::X0) &&
+ ConstantOpNo != III.ZeroIsSpecialNew)
+ return false;
+ if ((OrigZeroReg == PPC::R0 || OrigZeroReg == PPC::X0) &&
+ ConstantOpNo != PosForOrigZero)
+ return false;
+ }
+
+ unsigned Opc = MI.getOpcode();
+ bool SpecialShift32 =
+ Opc == PPC::SLW || Opc == PPC::SLWo || Opc == PPC::SRW || Opc == PPC::SRWo;
+ bool SpecialShift64 =
+ Opc == PPC::SLD || Opc == PPC::SLDo || Opc == PPC::SRD || Opc == PPC::SRDo;
+ bool SetCR = Opc == PPC::SLWo || Opc == PPC::SRWo ||
+ Opc == PPC::SLDo || Opc == PPC::SRDo;
+ bool RightShift =
+ Opc == PPC::SRW || Opc == PPC::SRWo || Opc == PPC::SRD || Opc == PPC::SRDo;
+
+ MI.setDesc(get(III.ImmOpcode));
+ if (ConstantOpNo == III.ConstantOpNo) {
+ // Converting shifts to immediate form is a bit tricky since they may do
+ // one of three things:
+ // 1. If the shift amount is between OpSize and 2*OpSize, the result is zero
+ // 2. If the shift amount is zero, the result is unchanged (save for maybe
+ // setting CR0)
+ // 3. If the shift amount is in [1, OpSize), it's just a shift
+ if (SpecialShift32 || SpecialShift64) {
+ LoadImmediateInfo LII;
+ LII.Imm = 0;
+ LII.SetCR = SetCR;
+ LII.Is64Bit = SpecialShift64;
+ uint64_t ShAmt = Imm & (SpecialShift32 ? 0x1F : 0x3F);
+ if (Imm & (SpecialShift32 ? 0x20 : 0x40))
+ replaceInstrWithLI(MI, LII);
+ // Shifts by zero don't change the value. If we don't need to set CR0,
+ // just convert this to a COPY. Can't do this post-RA since we've already
+ // cleaned up the copies.
+ else if (!SetCR && ShAmt == 0 && !PostRA) {
+ MI.RemoveOperand(2);
+ MI.setDesc(get(PPC::COPY));
+ } else {
+ // The 32 bit and 64 bit instructions are quite different.
+ if (SpecialShift32) {
+ // Left shifts use (N, 0, 31-N), right shifts use (32-N, N, 31).
+ uint64_t SH = RightShift ? 32 - ShAmt : ShAmt;
+ uint64_t MB = RightShift ? ShAmt : 0;
+ uint64_t ME = RightShift ? 31 : 31 - ShAmt;
+ MI.getOperand(III.ConstantOpNo).ChangeToImmediate(SH);
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(MB)
+ .addImm(ME);
+ } else {
+ // Left shifts use (N, 63-N), right shifts use (64-N, N).
+ uint64_t SH = RightShift ? 64 - ShAmt : ShAmt;
+ uint64_t ME = RightShift ? ShAmt : 63 - ShAmt;
+ MI.getOperand(III.ConstantOpNo).ChangeToImmediate(SH);
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(ME);
+ }
+ }
+ } else
+ MI.getOperand(ConstantOpNo).ChangeToImmediate(Imm);
+ }
+ // Convert commutative instructions (switch the operands and convert the
+ // desired one to an immediate.
+ else if (III.IsCommutative) {
+ MI.getOperand(ConstantOpNo).ChangeToImmediate(Imm);
+ swapMIOperands(MI, ConstantOpNo, III.ConstantOpNo);
+ } else
+ llvm_unreachable("Should have exited early!");
+
+ // For instructions for which the constant register replaces a different
+ // operand than where the immediate goes, we need to swap them.
+ if (III.ConstantOpNo != III.ImmOpNo)
+ swapMIOperands(MI, III.ConstantOpNo, III.ImmOpNo);
+
+ // If the R0/X0 register is special for the original instruction and not for
+ // the new instruction (or vice versa), we need to fix up the register class.
+ if (!PostRA && III.ZeroIsSpecialOrig != III.ZeroIsSpecialNew) {
+ if (!III.ZeroIsSpecialOrig) {
+ unsigned RegToModify = MI.getOperand(III.ZeroIsSpecialNew).getReg();
+ const TargetRegisterClass *NewRC =
+ MRI.getRegClass(RegToModify)->hasSuperClassEq(&PPC::GPRCRegClass) ?
+ &PPC::GPRC_and_GPRC_NOR0RegClass : &PPC::G8RC_and_G8RC_NOX0RegClass;
+ MRI.setRegClass(RegToModify, NewRC);
+ }
+ }
+ return true;
+}
+
const TargetRegisterClass *
PPCInstrInfo::updatedRC(const TargetRegisterClass *RC) const {
if (Subtarget.hasVSX() && RC == &PPC::VRRCRegClass)
@@ -2012,3 +2984,290 @@ PPCInstrInfo::updatedRC(const TargetRegisterClass *RC) const {
int PPCInstrInfo::getRecordFormOpcode(unsigned Opcode) {
return PPC::getRecordFormOpcode(Opcode);
}
+
+// This function returns true if the machine instruction
+// always outputs a value by sign-extending a 32 bit value,
+// i.e. 0 to 31-th bits are same as 32-th bit.
+static bool isSignExtendingOp(const MachineInstr &MI) {
+ int Opcode = MI.getOpcode();
+ if (Opcode == PPC::LI || Opcode == PPC::LI8 ||
+ Opcode == PPC::LIS || Opcode == PPC::LIS8 ||
+ Opcode == PPC::SRAW || Opcode == PPC::SRAWo ||
+ Opcode == PPC::SRAWI || Opcode == PPC::SRAWIo ||
+ Opcode == PPC::LWA || Opcode == PPC::LWAX ||
+ Opcode == PPC::LWA_32 || Opcode == PPC::LWAX_32 ||
+ Opcode == PPC::LHA || Opcode == PPC::LHAX ||
+ Opcode == PPC::LHA8 || Opcode == PPC::LHAX8 ||
+ Opcode == PPC::LBZ || Opcode == PPC::LBZX ||
+ Opcode == PPC::LBZ8 || Opcode == PPC::LBZX8 ||
+ Opcode == PPC::LBZU || Opcode == PPC::LBZUX ||
+ Opcode == PPC::LBZU8 || Opcode == PPC::LBZUX8 ||
+ Opcode == PPC::LHZ || Opcode == PPC::LHZX ||
+ Opcode == PPC::LHZ8 || Opcode == PPC::LHZX8 ||
+ Opcode == PPC::LHZU || Opcode == PPC::LHZUX ||
+ Opcode == PPC::LHZU8 || Opcode == PPC::LHZUX8 ||
+ Opcode == PPC::EXTSB || Opcode == PPC::EXTSBo ||
+ Opcode == PPC::EXTSH || Opcode == PPC::EXTSHo ||
+ Opcode == PPC::EXTSB8 || Opcode == PPC::EXTSH8 ||
+ Opcode == PPC::EXTSW || Opcode == PPC::EXTSWo ||
+ Opcode == PPC::EXTSH8_32_64 || Opcode == PPC::EXTSW_32_64 ||
+ Opcode == PPC::EXTSB8_32_64)
+ return true;
+
+ if (Opcode == PPC::RLDICL && MI.getOperand(3).getImm() >= 33)
+ return true;
+
+ if ((Opcode == PPC::RLWINM || Opcode == PPC::RLWINMo ||
+ Opcode == PPC::RLWNM || Opcode == PPC::RLWNMo) &&
+ MI.getOperand(3).getImm() > 0 &&
+ MI.getOperand(3).getImm() <= MI.getOperand(4).getImm())
+ return true;
+
+ return false;
+}
+
+// This function returns true if the machine instruction
+// always outputs zeros in higher 32 bits.
+static bool isZeroExtendingOp(const MachineInstr &MI) {
+ int Opcode = MI.getOpcode();
+ // The 16-bit immediate is sign-extended in li/lis.
+ // If the most significant bit is zero, all higher bits are zero.
+ if (Opcode == PPC::LI || Opcode == PPC::LI8 ||
+ Opcode == PPC::LIS || Opcode == PPC::LIS8) {
+ int64_t Imm = MI.getOperand(1).getImm();
+ if (((uint64_t)Imm & ~0x7FFFuLL) == 0)
+ return true;
+ }
+
+ // We have some variations of rotate-and-mask instructions
+ // that clear higher 32-bits.
+ if ((Opcode == PPC::RLDICL || Opcode == PPC::RLDICLo ||
+ Opcode == PPC::RLDCL || Opcode == PPC::RLDCLo ||
+ Opcode == PPC::RLDICL_32_64) &&
+ MI.getOperand(3).getImm() >= 32)
+ return true;
+
+ if ((Opcode == PPC::RLDIC || Opcode == PPC::RLDICo) &&
+ MI.getOperand(3).getImm() >= 32 &&
+ MI.getOperand(3).getImm() <= 63 - MI.getOperand(2).getImm())
+ return true;
+
+ if ((Opcode == PPC::RLWINM || Opcode == PPC::RLWINMo ||
+ Opcode == PPC::RLWNM || Opcode == PPC::RLWNMo ||
+ Opcode == PPC::RLWINM8 || Opcode == PPC::RLWNM8) &&
+ MI.getOperand(3).getImm() <= MI.getOperand(4).getImm())
+ return true;
+
+ // There are other instructions that clear higher 32-bits.
+ if (Opcode == PPC::CNTLZW || Opcode == PPC::CNTLZWo ||
+ Opcode == PPC::CNTTZW || Opcode == PPC::CNTTZWo ||
+ Opcode == PPC::CNTLZW8 || Opcode == PPC::CNTTZW8 ||
+ Opcode == PPC::CNTLZD || Opcode == PPC::CNTLZDo ||
+ Opcode == PPC::CNTTZD || Opcode == PPC::CNTTZDo ||
+ Opcode == PPC::POPCNTD || Opcode == PPC::POPCNTW ||
+ Opcode == PPC::SLW || Opcode == PPC::SLWo ||
+ Opcode == PPC::SRW || Opcode == PPC::SRWo ||
+ Opcode == PPC::SLW8 || Opcode == PPC::SRW8 ||
+ Opcode == PPC::SLWI || Opcode == PPC::SLWIo ||
+ Opcode == PPC::SRWI || Opcode == PPC::SRWIo ||
+ Opcode == PPC::LWZ || Opcode == PPC::LWZX ||
+ Opcode == PPC::LWZU || Opcode == PPC::LWZUX ||
+ Opcode == PPC::LWBRX || Opcode == PPC::LHBRX ||
+ Opcode == PPC::LHZ || Opcode == PPC::LHZX ||
+ Opcode == PPC::LHZU || Opcode == PPC::LHZUX ||
+ Opcode == PPC::LBZ || Opcode == PPC::LBZX ||
+ Opcode == PPC::LBZU || Opcode == PPC::LBZUX ||
+ Opcode == PPC::LWZ8 || Opcode == PPC::LWZX8 ||
+ Opcode == PPC::LWZU8 || Opcode == PPC::LWZUX8 ||
+ Opcode == PPC::LWBRX8 || Opcode == PPC::LHBRX8 ||
+ Opcode == PPC::LHZ8 || Opcode == PPC::LHZX8 ||
+ Opcode == PPC::LHZU8 || Opcode == PPC::LHZUX8 ||
+ Opcode == PPC::LBZ8 || Opcode == PPC::LBZX8 ||
+ Opcode == PPC::LBZU8 || Opcode == PPC::LBZUX8 ||
+ Opcode == PPC::ANDIo || Opcode == PPC::ANDISo ||
+ Opcode == PPC::ROTRWI || Opcode == PPC::ROTRWIo ||
+ Opcode == PPC::EXTLWI || Opcode == PPC::EXTLWIo ||
+ Opcode == PPC::MFVSRWZ)
+ return true;
+
+ return false;
+}
+
+// This function returns true if the input MachineInstr is a TOC save
+// instruction.
+bool PPCInstrInfo::isTOCSaveMI(const MachineInstr &MI) const {
+ if (!MI.getOperand(1).isImm() || !MI.getOperand(2).isReg())
+ return false;
+ unsigned TOCSaveOffset = Subtarget.getFrameLowering()->getTOCSaveOffset();
+ unsigned StackOffset = MI.getOperand(1).getImm();
+ unsigned StackReg = MI.getOperand(2).getReg();
+ if (StackReg == PPC::X1 && StackOffset == TOCSaveOffset)
+ return true;
+
+ return false;
+}
+
+// We limit the max depth to track incoming values of PHIs or binary ops
+// (e.g. AND) to avoid exsessive cost.
+const unsigned MAX_DEPTH = 1;
+
+bool
+PPCInstrInfo::isSignOrZeroExtended(const MachineInstr &MI, bool SignExt,
+ const unsigned Depth) const {
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const MachineRegisterInfo *MRI = &MF->getRegInfo();
+
+ // If we know this instruction returns sign- or zero-extended result,
+ // return true.
+ if (SignExt ? isSignExtendingOp(MI):
+ isZeroExtendingOp(MI))
+ return true;
+
+ switch (MI.getOpcode()) {
+ case PPC::COPY: {
+ unsigned SrcReg = MI.getOperand(1).getReg();
+
+ // In both ELFv1 and v2 ABI, method parameters and the return value
+ // are sign- or zero-extended.
+ if (MF->getSubtarget<PPCSubtarget>().isSVR4ABI()) {
+ const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>();
+ // We check the ZExt/SExt flags for a method parameter.
+ if (MI.getParent()->getBasicBlock() ==
+ &MF->getFunction().getEntryBlock()) {
+ unsigned VReg = MI.getOperand(0).getReg();
+ if (MF->getRegInfo().isLiveIn(VReg))
+ return SignExt ? FuncInfo->isLiveInSExt(VReg) :
+ FuncInfo->isLiveInZExt(VReg);
+ }
+
+ // For a method return value, we check the ZExt/SExt flags in attribute.
+ // We assume the following code sequence for method call.
+ // ADJCALLSTACKDOWN 32, implicit dead %r1, implicit %r1
+ // BL8_NOP @func,...
+ // ADJCALLSTACKUP 32, 0, implicit dead %r1, implicit %r1
+ // %5 = COPY %x3; G8RC:%5
+ if (SrcReg == PPC::X3) {
+ const MachineBasicBlock *MBB = MI.getParent();
+ MachineBasicBlock::const_instr_iterator II =
+ MachineBasicBlock::const_instr_iterator(&MI);
+ if (II != MBB->instr_begin() &&
+ (--II)->getOpcode() == PPC::ADJCALLSTACKUP) {
+ const MachineInstr &CallMI = *(--II);
+ if (CallMI.isCall() && CallMI.getOperand(0).isGlobal()) {
+ const Function *CalleeFn =
+ dyn_cast<Function>(CallMI.getOperand(0).getGlobal());
+ if (!CalleeFn)
+ return false;
+ const IntegerType *IntTy =
+ dyn_cast<IntegerType>(CalleeFn->getReturnType());
+ const AttributeSet &Attrs =
+ CalleeFn->getAttributes().getRetAttributes();
+ if (IntTy && IntTy->getBitWidth() <= 32)
+ return Attrs.hasAttribute(SignExt ? Attribute::SExt :
+ Attribute::ZExt);
+ }
+ }
+ }
+ }
+
+ // If this is a copy from another register, we recursively check source.
+ if (!TargetRegisterInfo::isVirtualRegister(SrcReg))
+ return false;
+ const MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
+ if (SrcMI != NULL)
+ return isSignOrZeroExtended(*SrcMI, SignExt, Depth);
+
+ return false;
+ }
+
+ case PPC::ANDIo:
+ case PPC::ANDISo:
+ case PPC::ORI:
+ case PPC::ORIS:
+ case PPC::XORI:
+ case PPC::XORIS:
+ case PPC::ANDIo8:
+ case PPC::ANDISo8:
+ case PPC::ORI8:
+ case PPC::ORIS8:
+ case PPC::XORI8:
+ case PPC::XORIS8: {
+ // logical operation with 16-bit immediate does not change the upper bits.
+ // So, we track the operand register as we do for register copy.
+ unsigned SrcReg = MI.getOperand(1).getReg();
+ if (!TargetRegisterInfo::isVirtualRegister(SrcReg))
+ return false;
+ const MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
+ if (SrcMI != NULL)
+ return isSignOrZeroExtended(*SrcMI, SignExt, Depth);
+
+ return false;
+ }
+
+ // If all incoming values are sign-/zero-extended,
+ // the output of OR, ISEL or PHI is also sign-/zero-extended.
+ case PPC::OR:
+ case PPC::OR8:
+ case PPC::ISEL:
+ case PPC::PHI: {
+ if (Depth >= MAX_DEPTH)
+ return false;
+
+ // The input registers for PHI are operand 1, 3, ...
+ // The input registers for others are operand 1 and 2.
+ unsigned E = 3, D = 1;
+ if (MI.getOpcode() == PPC::PHI) {
+ E = MI.getNumOperands();
+ D = 2;
+ }
+
+ for (unsigned I = 1; I != E; I += D) {
+ if (MI.getOperand(I).isReg()) {
+ unsigned SrcReg = MI.getOperand(I).getReg();
+ if (!TargetRegisterInfo::isVirtualRegister(SrcReg))
+ return false;
+ const MachineInstr *SrcMI = MRI->getVRegDef(SrcReg);
+ if (SrcMI == NULL || !isSignOrZeroExtended(*SrcMI, SignExt, Depth+1))
+ return false;
+ }
+ else
+ return false;
+ }
+ return true;
+ }
+
+ // If at least one of the incoming values of an AND is zero extended
+ // then the output is also zero-extended. If both of the incoming values
+ // are sign-extended then the output is also sign extended.
+ case PPC::AND:
+ case PPC::AND8: {
+ if (Depth >= MAX_DEPTH)
+ return false;
+
+ assert(MI.getOperand(1).isReg() && MI.getOperand(2).isReg());
+
+ unsigned SrcReg1 = MI.getOperand(1).getReg();
+ unsigned SrcReg2 = MI.getOperand(2).getReg();
+
+ if (!TargetRegisterInfo::isVirtualRegister(SrcReg1) ||
+ !TargetRegisterInfo::isVirtualRegister(SrcReg2))
+ return false;
+
+ const MachineInstr *MISrc1 = MRI->getVRegDef(SrcReg1);
+ const MachineInstr *MISrc2 = MRI->getVRegDef(SrcReg2);
+ if (!MISrc1 || !MISrc2)
+ return false;
+
+ if(SignExt)
+ return isSignOrZeroExtended(*MISrc1, SignExt, Depth+1) &&
+ isSignOrZeroExtended(*MISrc2, SignExt, Depth+1);
+ else
+ return isSignOrZeroExtended(*MISrc1, SignExt, Depth+1) ||
+ isSignOrZeroExtended(*MISrc2, SignExt, Depth+1);
+ }
+
+ default:
+ break;
+ }
+ return false;
+}