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.cpp559
1 files changed, 471 insertions, 88 deletions
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index 0930f7d3b8d7d..d754ce2990d20 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -987,7 +987,7 @@ void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Opc = PPC::XXLOR;
else if (PPC::VSFRCRegClass.contains(DestReg, SrcReg) ||
PPC::VSSRCRegClass.contains(DestReg, SrcReg))
- Opc = PPC::XXLORf;
+ Opc = (Subtarget.hasP9Vector()) ? PPC::XSCPSGNDP : PPC::XXLORf;
else if (PPC::QFRCRegClass.contains(DestReg, SrcReg))
Opc = PPC::QVFMR;
else if (PPC::QSRCRegClass.contains(DestReg, SrcReg))
@@ -1429,17 +1429,15 @@ bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI,
: (isPPC64 ? PPC::BDZLR8 : PPC::BDZLR)));
} else if (Pred[0].getImm() == PPC::PRED_BIT_SET) {
MI.setDesc(get(PPC::BCLR));
- MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addReg(Pred[1].getReg());
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]);
} else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) {
MI.setDesc(get(PPC::BCLRn));
- MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addReg(Pred[1].getReg());
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]);
} else {
MI.setDesc(get(PPC::BCCLR));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
.addImm(Pred[0].getImm())
- .addReg(Pred[1].getReg());
+ .add(Pred[1]);
}
return true;
@@ -1454,7 +1452,7 @@ bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI,
MI.setDesc(get(PPC::BC));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addReg(Pred[1].getReg())
+ .add(Pred[1])
.addMBB(MBB);
} else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) {
MachineBasicBlock *MBB = MI.getOperand(0).getMBB();
@@ -1462,7 +1460,7 @@ bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI,
MI.setDesc(get(PPC::BCn));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addReg(Pred[1].getReg())
+ .add(Pred[1])
.addMBB(MBB);
} else {
MachineBasicBlock *MBB = MI.getOperand(0).getMBB();
@@ -1471,13 +1469,13 @@ bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI,
MI.setDesc(get(PPC::BCC));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
.addImm(Pred[0].getImm())
- .addReg(Pred[1].getReg())
+ .add(Pred[1])
.addMBB(MBB);
}
return true;
- } else if (OpC == PPC::BCTR || OpC == PPC::BCTR8 ||
- OpC == PPC::BCTRL || OpC == PPC::BCTRL8) {
+ } else if (OpC == PPC::BCTR || OpC == PPC::BCTR8 || OpC == PPC::BCTRL ||
+ OpC == PPC::BCTRL8) {
if (Pred[1].getReg() == PPC::CTR8 || Pred[1].getReg() == PPC::CTR)
llvm_unreachable("Cannot predicate bctr[l] on the ctr register");
@@ -1487,14 +1485,12 @@ bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI,
if (Pred[0].getImm() == PPC::PRED_BIT_SET) {
MI.setDesc(get(isPPC64 ? (setLR ? PPC::BCCTRL8 : PPC::BCCTR8)
: (setLR ? PPC::BCCTRL : PPC::BCCTR)));
- MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addReg(Pred[1].getReg());
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]);
return true;
} else if (Pred[0].getImm() == PPC::PRED_BIT_UNSET) {
MI.setDesc(get(isPPC64 ? (setLR ? PPC::BCCTRL8n : PPC::BCCTR8n)
: (setLR ? PPC::BCCTRLn : PPC::BCCTRn)));
- MachineInstrBuilder(*MI.getParent()->getParent(), MI)
- .addReg(Pred[1].getReg());
+ MachineInstrBuilder(*MI.getParent()->getParent(), MI).add(Pred[1]);
return true;
}
@@ -1502,7 +1498,7 @@ bool PPCInstrInfo::PredicateInstruction(MachineInstr &MI,
: (setLR ? PPC::BCCCTRL : PPC::BCCCTR)));
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
.addImm(Pred[0].getImm())
- .addReg(Pred[1].getReg());
+ .add(Pred[1]);
return true;
}
@@ -1822,7 +1818,8 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
int NewOpC = -1;
int MIOpC = MI->getOpcode();
- if (MIOpC == PPC::ANDIo || MIOpC == PPC::ANDIo8)
+ if (MIOpC == PPC::ANDIo || MIOpC == PPC::ANDIo8 ||
+ MIOpC == PPC::ANDISo || MIOpC == PPC::ANDISo8)
NewOpC = MIOpC;
else {
NewOpC = PPC::getRecordFormOpcode(MIOpC);
@@ -1912,14 +1909,36 @@ bool PPCInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg,
// compare).
// Rotates are expensive instructions. If we're emitting a record-form
- // rotate that can just be an andi, we should just emit the andi.
- if ((MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINM8) &&
- MI->getOperand(2).getImm() == 0) {
+ // rotate that can just be an andi/andis, we should just emit that.
+ if (MIOpC == PPC::RLWINM || MIOpC == PPC::RLWINM8) {
+ unsigned GPRRes = MI->getOperand(0).getReg();
+ int64_t SH = MI->getOperand(2).getImm();
int64_t MB = MI->getOperand(3).getImm();
int64_t ME = MI->getOperand(4).getImm();
- if (MB < ME && MB >= 16) {
- uint64_t Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1);
- NewOpC = MIOpC == PPC::RLWINM ? PPC::ANDIo : PPC::ANDIo8;
+ // We can only do this if both the start and end of the mask are in the
+ // same halfword.
+ bool MBInLoHWord = MB >= 16;
+ bool MEInLoHWord = ME >= 16;
+ uint64_t Mask = ~0LLU;
+
+ if (MB <= ME && MBInLoHWord == MEInLoHWord && SH == 0) {
+ Mask = ((1LLU << (32 - MB)) - 1) & ~((1LLU << (31 - ME)) - 1);
+ // The mask value needs to shift right 16 if we're emitting andis.
+ Mask >>= MBInLoHWord ? 0 : 16;
+ NewOpC = MIOpC == PPC::RLWINM ?
+ (MBInLoHWord ? PPC::ANDIo : PPC::ANDISo) :
+ (MBInLoHWord ? PPC::ANDIo8 :PPC::ANDISo8);
+ } else if (MRI->use_empty(GPRRes) && (ME == 31) &&
+ (ME - MB + 1 == SH) && (MB >= 16)) {
+ // If we are rotating by the exact number of bits as are in the mask
+ // and the mask is in the least significant bits of the register,
+ // that's just an andis. (as long as the GPR result has no uses).
+ Mask = ((1LLU << 32) - 1) & ~((1LLU << (32 - SH)) - 1);
+ Mask >>= 16;
+ NewOpC = MIOpC == PPC::RLWINM ? PPC::ANDISo :PPC::ANDISo8;
+ }
+ // If we've set the mask, we can transform.
+ if (Mask != ~0LLU) {
MI->RemoveOperand(4);
MI->RemoveOperand(3);
MI->getOperand(2).setImm(Mask);
@@ -2088,11 +2107,9 @@ bool PPCInstrInfo::expandVSXMemPseudo(MachineInstr &MI) const {
return true;
}
-#ifndef NDEBUG
static bool isAnImmediateOperand(const MachineOperand &MO) {
return MO.isCPI() || MO.isGlobal() || MO.isImm();
}
-#endif
bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
auto &MBB = *MI.getParent();
@@ -2231,6 +2248,35 @@ static unsigned selectReg(int64_t Imm1, int64_t Imm2, unsigned CompareOpc,
return PPC::NoRegister;
}
+void PPCInstrInfo::replaceInstrOperandWithImm(MachineInstr &MI,
+ unsigned OpNo,
+ int64_t Imm) const {
+ assert(MI.getOperand(OpNo).isReg() && "Operand must be a REG");
+ // Replace the REG with the Immediate.
+ unsigned InUseReg = MI.getOperand(OpNo).getReg();
+ MI.getOperand(OpNo).ChangeToImmediate(Imm);
+
+ if (empty(MI.implicit_operands()))
+ return;
+
+ // We need to make sure that the MI didn't have any implicit use
+ // of this REG any more.
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
+ int UseOpIdx = MI.findRegisterUseOperandIdx(InUseReg, false, TRI);
+ if (UseOpIdx >= 0) {
+ MachineOperand &MO = MI.getOperand(UseOpIdx);
+ if (MO.isImplicit())
+ // The operands must always be in the following order:
+ // - explicit reg defs,
+ // - other explicit operands (reg uses, immediates, etc.),
+ // - implicit reg defs
+ // - implicit reg uses
+ // Therefore, removing the implicit operand won't change the explicit
+ // operands layout.
+ MI.RemoveOperand(UseOpIdx);
+ }
+}
+
// 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,
@@ -2256,10 +2302,11 @@ void PPCInstrInfo::replaceInstrWithLI(MachineInstr &MI,
.addImm(LII.Imm);
}
-MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI,
- unsigned &ConstOp,
- bool &SeenIntermediateUse) const {
- ConstOp = ~0U;
+MachineInstr *PPCInstrInfo::getForwardingDefMI(
+ MachineInstr &MI,
+ unsigned &OpNoForForwarding,
+ bool &SeenIntermediateUse) const {
+ OpNoForForwarding = ~0U;
MachineInstr *DefMI = nullptr;
MachineRegisterInfo *MRI = &MI.getParent()->getParent()->getRegInfo();
const TargetRegisterInfo *TRI = &getRegisterInfo();
@@ -2276,7 +2323,7 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI,
if (TargetRegisterInfo::isVirtualRegister(TrueReg)) {
DefMI = MRI->getVRegDef(TrueReg);
if (DefMI->getOpcode() == PPC::LI || DefMI->getOpcode() == PPC::LI8) {
- ConstOp = i;
+ OpNoForForwarding = i;
break;
}
}
@@ -2297,7 +2344,7 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI,
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)
+ if (!instrHasImmForm(MI, III, true) && !ConvertibleImmForm)
return nullptr;
// Don't convert or %X, %Y, %Y since that's just a register move.
@@ -2319,15 +2366,22 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI,
if (PPC::G8RCRegClass.contains(Reg))
Reg = Reg - PPC::X0 + PPC::R0;
- // Is this register defined by a load-immediate in this block?
+ // Is this register defined by some form of add-immediate (including
+ // load-immediate) within this basic block?
for ( ; It != E; ++It) {
if (It->modifiesRegister(Reg, &getRegisterInfo())) {
- if (It->getOpcode() == PPC::LI || It->getOpcode() == PPC::LI8) {
- ConstOp = i;
+ switch (It->getOpcode()) {
+ default: break;
+ case PPC::LI:
+ case PPC::LI8:
+ case PPC::ADDItocL:
+ case PPC::ADDI:
+ case PPC::ADDI8:
+ OpNoForForwarding = i;
return &*It;
- } else
- break;
- } else if (It->readsRegister(Reg, &getRegisterInfo()))
+ }
+ 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;
@@ -2335,7 +2389,7 @@ MachineInstr *PPCInstrInfo::getConstantDefMI(MachineInstr &MI,
}
}
}
- return ConstOp == ~0U ? nullptr : DefMI;
+ return OpNoForForwarding == ~0U ? nullptr : DefMI;
}
const unsigned *PPCInstrInfo::getStoreOpcodesForSpillArray() const {
@@ -2371,35 +2425,48 @@ const unsigned *PPCInstrInfo::getLoadOpcodesForSpillArray() const {
}
// 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.
+// result of a load-immediate or an add-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())
+ unsigned ForwardingOperand = ~0U;
+ MachineInstr *DefMI = getForwardingDefMI(MI, ForwardingOperand,
+ SeenIntermediateUse);
+ if (!DefMI)
+ return false;
+ assert(ForwardingOperand < MI.getNumOperands() &&
+ "The forwarding operand needs to be valid at this point");
+ bool KillFwdDefMI = !SeenIntermediateUse &&
+ MI.getOperand(ForwardingOperand).isKill();
+ if (KilledDef && KillFwdDefMI)
+ *KilledDef = DefMI;
+
+ ImmInstrInfo III;
+ bool HasImmForm = instrHasImmForm(MI, III, PostRA);
+ // If this is a reg+reg instruction that has a reg+imm form,
+ // and one of the operands is produced by an add-immediate,
+ // try to convert it.
+ if (HasImmForm && transformToImmFormFedByAdd(MI, III, ForwardingOperand,
+ *DefMI, KillFwdDefMI))
+ return true;
+
+ if ((DefMI->getOpcode() != PPC::LI && DefMI->getOpcode() != PPC::LI8) ||
+ !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);
+ // 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, SExtImm);
bool ReplaceWithLI = false;
bool Is64BitLI = false;
@@ -2443,7 +2510,7 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI,
// 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);
+ replaceInstrOperandWithImm(CompareUseMI, 1, 0);
CompareUseMI.RemoveOperand(3);
CompareUseMI.RemoveOperand(2);
continue;
@@ -2602,18 +2669,23 @@ bool PPCInstrInfo::convertToImmediateForm(MachineInstr &MI,
return false;
}
+static bool isVFReg(unsigned Reg) {
+ return PPC::VFRCRegClass.contains(Reg);
+}
+
bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
- ImmInstrInfo &III) const {
+ ImmInstrInfo &III, bool PostRA) 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.OpNoForForwarding = 2;
III.ImmWidth = 16;
III.ImmMustBeMultipleOf = 1;
III.TruncateImmTo = 0;
+ III.IsSummingOperands = false;
switch (Opc) {
default: return false;
case PPC::ADD4:
@@ -2622,6 +2694,7 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
III.ZeroIsSpecialOrig = 0;
III.ZeroIsSpecialNew = 1;
III.IsCommutative = true;
+ III.IsSummingOperands = true;
III.ImmOpcode = Opc == PPC::ADD4 ? PPC::ADDI : PPC::ADDI8;
break;
case PPC::ADDC:
@@ -2630,6 +2703,7 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
III.ZeroIsSpecialOrig = 0;
III.ZeroIsSpecialNew = 0;
III.IsCommutative = true;
+ III.IsSummingOperands = true;
III.ImmOpcode = Opc == PPC::ADDC ? PPC::ADDIC : PPC::ADDIC8;
break;
case PPC::ADDCo:
@@ -2637,6 +2711,7 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
III.ZeroIsSpecialOrig = 0;
III.ZeroIsSpecialNew = 0;
III.IsCommutative = true;
+ III.IsSummingOperands = true;
III.ImmOpcode = PPC::ADDICo;
break;
case PPC::SUBFC:
@@ -2809,8 +2884,9 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
III.ZeroIsSpecialOrig = 1;
III.ZeroIsSpecialNew = 2;
III.IsCommutative = true;
+ III.IsSummingOperands = true;
III.ImmOpNo = 1;
- III.ConstantOpNo = 2;
+ III.OpNoForForwarding = 2;
switch(Opc) {
default: llvm_unreachable("Unknown opcode");
case PPC::LBZX: III.ImmOpcode = PPC::LBZ; break;
@@ -2866,8 +2942,9 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
III.ZeroIsSpecialOrig = 2;
III.ZeroIsSpecialNew = 3;
III.IsCommutative = false;
+ III.IsSummingOperands = true;
III.ImmOpNo = 2;
- III.ConstantOpNo = 3;
+ III.OpNoForForwarding = 3;
switch(Opc) {
default: llvm_unreachable("Unknown opcode");
case PPC::LBZUX: III.ImmOpcode = PPC::LBZU; break;
@@ -2898,21 +2975,30 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
case PPC::STFDUX: III.ImmOpcode = PPC::STFDU; break;
}
break;
- // Power9 only.
+ // Power9 and up only. For some of these, the X-Form version has access to all
+ // 64 VSR's whereas the D-Form only has access to the VR's. We replace those
+ // with pseudo-ops pre-ra and for post-ra, we check that the register loaded
+ // into or stored from is one of the VR registers.
case PPC::LXVX:
case PPC::LXSSPX:
case PPC::LXSDX:
case PPC::STXVX:
case PPC::STXSSPX:
case PPC::STXSDX:
+ case PPC::XFLOADf32:
+ case PPC::XFLOADf64:
+ case PPC::XFSTOREf32:
+ case PPC::XFSTOREf64:
if (!Subtarget.hasP9Vector())
return false;
III.SignedImm = true;
III.ZeroIsSpecialOrig = 1;
III.ZeroIsSpecialNew = 2;
III.IsCommutative = true;
+ III.IsSummingOperands = true;
III.ImmOpNo = 1;
- III.ConstantOpNo = 2;
+ III.OpNoForForwarding = 2;
+ III.ImmMustBeMultipleOf = 4;
switch(Opc) {
default: llvm_unreachable("Unknown opcode");
case PPC::LXVX:
@@ -2920,24 +3006,64 @@ bool PPCInstrInfo::instrHasImmForm(const MachineInstr &MI,
III.ImmMustBeMultipleOf = 16;
break;
case PPC::LXSSPX:
- III.ImmOpcode = PPC::LXSSP;
- III.ImmMustBeMultipleOf = 4;
+ if (PostRA) {
+ if (isVFReg(MI.getOperand(0).getReg()))
+ III.ImmOpcode = PPC::LXSSP;
+ else {
+ III.ImmOpcode = PPC::LFS;
+ III.ImmMustBeMultipleOf = 1;
+ }
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case PPC::XFLOADf32:
+ III.ImmOpcode = PPC::DFLOADf32;
break;
case PPC::LXSDX:
- III.ImmOpcode = PPC::LXSD;
- III.ImmMustBeMultipleOf = 4;
+ if (PostRA) {
+ if (isVFReg(MI.getOperand(0).getReg()))
+ III.ImmOpcode = PPC::LXSD;
+ else {
+ III.ImmOpcode = PPC::LFD;
+ III.ImmMustBeMultipleOf = 1;
+ }
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case PPC::XFLOADf64:
+ III.ImmOpcode = PPC::DFLOADf64;
break;
case PPC::STXVX:
III.ImmOpcode = PPC::STXV;
III.ImmMustBeMultipleOf = 16;
break;
case PPC::STXSSPX:
- III.ImmOpcode = PPC::STXSSP;
- III.ImmMustBeMultipleOf = 4;
+ if (PostRA) {
+ if (isVFReg(MI.getOperand(0).getReg()))
+ III.ImmOpcode = PPC::STXSSP;
+ else {
+ III.ImmOpcode = PPC::STFS;
+ III.ImmMustBeMultipleOf = 1;
+ }
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case PPC::XFSTOREf32:
+ III.ImmOpcode = PPC::DFSTOREf32;
break;
case PPC::STXSDX:
- III.ImmOpcode = PPC::STXSD;
- III.ImmMustBeMultipleOf = 4;
+ if (PostRA) {
+ if (isVFReg(MI.getOperand(0).getReg()))
+ III.ImmOpcode = PPC::STXSD;
+ else {
+ III.ImmOpcode = PPC::STFD;
+ III.ImmMustBeMultipleOf = 1;
+ }
+ break;
+ }
+ LLVM_FALLTHROUGH;
+ case PPC::XFSTOREf64:
+ III.ImmOpcode = PPC::DFSTOREf64;
break;
}
break;
@@ -2984,13 +3110,264 @@ static void swapMIOperands(MachineInstr &MI, unsigned Op1, unsigned Op2) {
}
}
-bool PPCInstrInfo::transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III,
- unsigned ConstantOpNo,
- int64_t Imm) const {
+// Check if the 'MI' that has the index OpNoForForwarding
+// meets the requirement described in the ImmInstrInfo.
+bool PPCInstrInfo::isUseMIElgibleForForwarding(MachineInstr &MI,
+ const ImmInstrInfo &III,
+ unsigned OpNoForForwarding
+ ) const {
+ // As the algorithm of checking for PPC::ZERO/PPC::ZERO8
+ // would not work pre-RA, we can only do the check post RA.
+ MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+ if (MRI.isSSA())
+ return false;
+
+ // Cannot do the transform if MI isn't summing the operands.
+ if (!III.IsSummingOperands)
+ return false;
+
+ // The instruction we are trying to replace must have the ZeroIsSpecialOrig set.
+ if (!III.ZeroIsSpecialOrig)
+ return false;
+
+ // We cannot do the transform if the operand we are trying to replace
+ // isn't the same as the operand the instruction allows.
+ if (OpNoForForwarding != III.OpNoForForwarding)
+ return false;
+
+ // Check if the instruction we are trying to transform really has
+ // the special zero register as its operand.
+ if (MI.getOperand(III.ZeroIsSpecialOrig).getReg() != PPC::ZERO &&
+ MI.getOperand(III.ZeroIsSpecialOrig).getReg() != PPC::ZERO8)
+ return false;
+
+ // This machine instruction is convertible if it is,
+ // 1. summing the operands.
+ // 2. one of the operands is special zero register.
+ // 3. the operand we are trying to replace is allowed by the MI.
+ return true;
+}
+
+// Check if the DefMI is the add inst and set the ImmMO and RegMO
+// accordingly.
+bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI,
+ const ImmInstrInfo &III,
+ MachineOperand *&ImmMO,
+ MachineOperand *&RegMO) const {
+ unsigned Opc = DefMI.getOpcode();
+ if (Opc != PPC::ADDItocL && Opc != PPC::ADDI && Opc != PPC::ADDI8)
+ return false;
+
+ assert(DefMI.getNumOperands() >= 3 &&
+ "Add inst must have at least three operands");
+ RegMO = &DefMI.getOperand(1);
+ ImmMO = &DefMI.getOperand(2);
+
+ // This DefMI is elgible for forwarding if it is:
+ // 1. add inst
+ // 2. one of the operands is Imm/CPI/Global.
+ return isAnImmediateOperand(*ImmMO);
+}
+
+bool PPCInstrInfo::isRegElgibleForForwarding(const MachineOperand &RegMO,
+ const MachineInstr &DefMI,
+ const MachineInstr &MI,
+ bool KillDefMI
+ ) const {
+ // x = addi y, imm
+ // ...
+ // z = lfdx 0, x -> z = lfd imm(y)
+ // The Reg "y" can be forwarded to the MI(z) only when there is no DEF
+ // of "y" between the DEF of "x" and "z".
+ // The query is only valid post RA.
+ const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+ if (MRI.isSSA())
+ return false;
+
+ // 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.
+ unsigned Reg = RegMO.getReg();
+ if (PPC::G8RCRegClass.contains(Reg))
+ Reg = Reg - PPC::X0 + PPC::R0;
+
+ // Walking the inst in reverse(MI-->DefMI) to get the last DEF of the Reg.
+ MachineBasicBlock::const_reverse_iterator It = MI;
+ MachineBasicBlock::const_reverse_iterator E = MI.getParent()->rend();
+ It++;
+ for (; It != E; ++It) {
+ if (It->modifiesRegister(Reg, &getRegisterInfo()) && (&*It) != &DefMI)
+ return false;
+ // Made it to DefMI without encountering a clobber.
+ if ((&*It) == &DefMI)
+ break;
+ }
+ assert((&*It) == &DefMI && "DefMI is missing");
+
+ // If DefMI also uses the register to be forwarded, we can only forward it
+ // if DefMI is being erased.
+ if (DefMI.readsRegister(Reg, &getRegisterInfo()))
+ return KillDefMI;
+
+ return true;
+}
+
+bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO,
+ const MachineInstr &DefMI,
+ const ImmInstrInfo &III,
+ int64_t &Imm) const {
+ assert(isAnImmediateOperand(ImmMO) && "ImmMO is NOT an immediate");
+ if (DefMI.getOpcode() == PPC::ADDItocL) {
+ // The operand for ADDItocL is CPI, which isn't imm at compiling time,
+ // However, we know that, it is 16-bit width, and has the alignment of 4.
+ // Check if the instruction met the requirement.
+ if (III.ImmMustBeMultipleOf > 4 ||
+ III.TruncateImmTo || III.ImmWidth != 16)
+ return false;
+
+ // Going from XForm to DForm loads means that the displacement needs to be
+ // not just an immediate but also a multiple of 4, or 16 depending on the
+ // load. A DForm load cannot be represented if it is a multiple of say 2.
+ // XForm loads do not have this restriction.
+ if (ImmMO.isGlobal() &&
+ ImmMO.getGlobal()->getAlignment() < III.ImmMustBeMultipleOf)
+ return false;
+
+ return true;
+ }
+
+ if (ImmMO.isImm()) {
+ // It is Imm, we need to check if the Imm fit the range.
+ int64_t Immediate = ImmMO.getImm();
+ // Sign-extend to 64-bits.
+ Imm = ((uint64_t)Immediate & ~0x7FFFuLL) != 0 ?
+ (Immediate | 0xFFFFFFFFFFFF0000) : Immediate;
+
+ if (Imm % III.ImmMustBeMultipleOf)
+ return false;
+ if (III.TruncateImmTo)
+ Imm &= ((1 << III.TruncateImmTo) - 1);
+ 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;
+ }
+ }
+ else
+ return false;
+
+ // This ImmMO is forwarded if it meets the requriement describle
+ // in ImmInstrInfo
+ return true;
+}
+
+// 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
+// the immediate being added.
+bool PPCInstrInfo::transformToImmFormFedByAdd(MachineInstr &MI,
+ const ImmInstrInfo &III,
+ unsigned OpNoForForwarding,
+ MachineInstr &DefMI,
+ bool KillDefMI) const {
+ // RegMO ImmMO
+ // | |
+ // x = addi reg, imm <----- DefMI
+ // y = op 0 , x <----- MI
+ // |
+ // OpNoForForwarding
+ // Check if the MI meet the requirement described in the III.
+ if (!isUseMIElgibleForForwarding(MI, III, OpNoForForwarding))
+ return false;
+
+ // Check if the DefMI meet the requirement
+ // described in the III. If yes, set the ImmMO and RegMO accordingly.
+ MachineOperand *ImmMO = nullptr;
+ MachineOperand *RegMO = nullptr;
+ if (!isDefMIElgibleForForwarding(DefMI, III, ImmMO, RegMO))
+ return false;
+ assert(ImmMO && RegMO && "Imm and Reg operand must have been set");
+
+ // As we get the Imm operand now, we need to check if the ImmMO meet
+ // the requirement described in the III. If yes set the Imm.
+ int64_t Imm = 0;
+ if (!isImmElgibleForForwarding(*ImmMO, DefMI, III, Imm))
+ return false;
+
+ // Check if the RegMO can be forwarded to MI.
+ if (!isRegElgibleForForwarding(*RegMO, DefMI, MI, KillDefMI))
+ return false;
+
+ // We know that, the MI and DefMI both meet the pattern, and
+ // the Imm also meet the requirement with the new Imm-form.
+ // It is safe to do the transformation now.
+ LLVM_DEBUG(dbgs() << "Replacing instruction:\n");
+ LLVM_DEBUG(MI.dump());
+ LLVM_DEBUG(dbgs() << "Fed by:\n");
+ LLVM_DEBUG(DefMI.dump());
+
+ // Update the base reg first.
+ MI.getOperand(III.OpNoForForwarding).ChangeToRegister(RegMO->getReg(),
+ false, false,
+ RegMO->isKill());
+
+ // Then, update the imm.
+ if (ImmMO->isImm()) {
+ // If the ImmMO is Imm, change the operand that has ZERO to that Imm
+ // directly.
+ replaceInstrOperandWithImm(MI, III.ZeroIsSpecialOrig, Imm);
+ }
+ else {
+ // Otherwise, it is Constant Pool Index(CPI) or Global,
+ // which is relocation in fact. We need to replace the special zero
+ // register with ImmMO.
+ // Before that, we need to fixup the target flags for imm.
+ // For some reason, we miss to set the flag for the ImmMO if it is CPI.
+ if (DefMI.getOpcode() == PPC::ADDItocL)
+ ImmMO->setTargetFlags(PPCII::MO_TOC_LO);
+
+ // MI didn't have the interface such as MI.setOperand(i) though
+ // it has MI.getOperand(i). To repalce the ZERO MachineOperand with
+ // ImmMO, we need to remove ZERO operand and all the operands behind it,
+ // and, add the ImmMO, then, move back all the operands behind ZERO.
+ SmallVector<MachineOperand, 2> MOps;
+ for (unsigned i = MI.getNumOperands() - 1; i >= III.ZeroIsSpecialOrig; i--) {
+ MOps.push_back(MI.getOperand(i));
+ MI.RemoveOperand(i);
+ }
+
+ // Remove the last MO in the list, which is ZERO operand in fact.
+ MOps.pop_back();
+ // Add the imm operand.
+ MI.addOperand(*ImmMO);
+ // Now add the rest back.
+ for (auto &MO : MOps)
+ MI.addOperand(MO);
+ }
+
+ // Update the opcode.
+ MI.setDesc(get(III.ImmOpcode));
+
+ LLVM_DEBUG(dbgs() << "With:\n");
+ LLVM_DEBUG(MI.dump());
+
+ return true;
+}
+
+bool PPCInstrInfo::transformToImmFormFedByLI(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)
+ if ((ConstantOpNo != III.OpNoForForwarding) && !III.IsCommutative)
return false;
if (Imm % III.ImmMustBeMultipleOf)
return false;
@@ -3035,7 +3412,7 @@ bool PPCInstrInfo::transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III,
Opc == PPC::SRW || Opc == PPC::SRWo || Opc == PPC::SRD || Opc == PPC::SRDo;
MI.setDesc(get(III.ImmOpcode));
- if (ConstantOpNo == III.ConstantOpNo) {
+ if (ConstantOpNo == III.OpNoForForwarding) {
// 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
@@ -3063,42 +3440,47 @@ bool PPCInstrInfo::transformToImmForm(MachineInstr &MI, const ImmInstrInfo &III,
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);
+ replaceInstrOperandWithImm(MI, III.OpNoForForwarding, 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);
+ replaceInstrOperandWithImm(MI, III.OpNoForForwarding, SH);
MachineInstrBuilder(*MI.getParent()->getParent(), MI).addImm(ME);
}
}
} else
- MI.getOperand(ConstantOpNo).ChangeToImmediate(Imm);
+ replaceInstrOperandWithImm(MI, ConstantOpNo, 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);
+ replaceInstrOperandWithImm(MI, ConstantOpNo, Imm);
+ swapMIOperands(MI, ConstantOpNo, III.OpNoForForwarding);
} 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 (III.OpNoForForwarding != III.ImmOpNo)
+ swapMIOperands(MI, III.OpNoForForwarding, 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 the special R0/X0 register index are different for original instruction
+ // and new instruction, we need to fix up the register class in new
+ // instruction.
if (!PostRA && III.ZeroIsSpecialOrig != III.ZeroIsSpecialNew) {
- if (!III.ZeroIsSpecialOrig) {
+ if (III.ZeroIsSpecialNew) {
+ // If operand at III.ZeroIsSpecialNew is physical reg(eg: ZERO/ZERO8), no
+ // need to fix up register class.
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);
+ if (TargetRegisterInfo::isVirtualRegister(RegToModify)) {
+ 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;
@@ -3140,6 +3522,7 @@ static bool isSignExtendingOp(const MachineInstr &MI) {
Opcode == PPC::EXTSH || Opcode == PPC::EXTSHo ||
Opcode == PPC::EXTSB8 || Opcode == PPC::EXTSH8 ||
Opcode == PPC::EXTSW || Opcode == PPC::EXTSWo ||
+ Opcode == PPC::SETB || Opcode == PPC::SETB8 ||
Opcode == PPC::EXTSH8_32_64 || Opcode == PPC::EXTSW_32_64 ||
Opcode == PPC::EXTSB8_32_64)
return true;