mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 15:39:06 +00:00
Next round of PPC CR optimizations. For the following code:
int %bar(float %a, float %b, float %c, float %d) { entry: %tmp.1 = setlt float %a, %d %tmp.2 = setlt float %b, %d %or = or bool %tmp.1, %tmp.2 %tmp.3 = setgt float %c, %d %tmp.4 = or bool %or, %tmp.3 %tmp.5 = and bool %tmp.4, true %retval = cast bool %tmp.5 to int ret int %retval } We now emit: _bar: .LBB_bar_0: ; entry fcmpu cr0, f1, f4 fcmpu cr1, f2, f4 cror 0, 0, 4 fcmpu cr1, f3, f4 cror 28, 0, 5 mfcr r2 rlwinm r3, r2, 29, 31, 31 blr Instead of: _bar: .LBB_bar_0: ; entry fcmpu cr7, f1, f4 mfcr r2 rlwinm r2, r2, 29, 31, 31 fcmpu cr7, f2, f4 mfcr r3 rlwinm r3, r3, 29, 31, 31 or r2, r2, r3 fcmpu cr7, f3, f4 mfcr r3 rlwinm r3, r3, 30, 31, 31 or r3, r2, r3 blr git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21321 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ea96b5edbb
commit
1cbf3abbb8
@ -524,9 +524,11 @@ public:
|
||||
|
||||
unsigned getGlobalBaseReg();
|
||||
unsigned getConstDouble(double floatVal, unsigned Result);
|
||||
void MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result);
|
||||
bool SelectBitfieldInsert(SDOperand OR, unsigned Result);
|
||||
unsigned FoldIfWideZeroExtend(SDOperand N);
|
||||
unsigned SelectCC(SDOperand CC, unsigned &Opc);
|
||||
unsigned SelectCC(SDOperand CC, unsigned &Opc, bool &Inv, unsigned &Idx);
|
||||
unsigned SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv, unsigned &Idx);
|
||||
unsigned SelectExpr(SDOperand N, bool Recording=false);
|
||||
unsigned SelectExprFP(SDOperand N, unsigned Result);
|
||||
void Select(SDOperand N);
|
||||
@ -727,22 +729,6 @@ static unsigned getCRIdxForSetCC(unsigned Condition, bool& Inv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getCRIdxForBCC - Return the index of the condition register field
|
||||
/// associated with the PowerPC branch instruction, and whether or not the field
|
||||
/// is treated as inverted. That is, lt = 0; ge = 0 inverted.
|
||||
static unsigned getCRIdxForBCC(unsigned Condition, bool& Inv) {
|
||||
switch (Condition) {
|
||||
default: assert(0 && "Unknown condition!"); abort();
|
||||
case PPC::BLT: Inv = false; return 29; // 28 -> 31, rol 29
|
||||
case PPC::BGE: Inv = true; return 29; // 28 -> 31, rol 29
|
||||
case PPC::BGT: Inv = false; return 30; // 29 -> 31, rol 30
|
||||
case PPC::BLE: Inv = true; return 30; // 29 -> 31, rol 30
|
||||
case PPC::BEQ: Inv = false; return 31; // 30 -> 31, rol 31
|
||||
case PPC::BNE: Inv = true; return 31; // 30 -> 31, rol 31
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// IndexedOpForOp - Return the indexed variant for each of the PowerPC load
|
||||
/// and store immediate instructions.
|
||||
static unsigned IndexedOpForOp(unsigned Opcode) {
|
||||
@ -934,6 +920,23 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// MoveCRtoGPR - Move CCReg[Idx] to the least significant bit of Result. If
|
||||
/// Inv is true, then invert the result.
|
||||
void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
|
||||
unsigned IntCR = MakeReg(MVT::i32);
|
||||
BuildMI(BB, PPC::MCRF, 1, PPC::CR7).addReg(CCReg);
|
||||
BuildMI(BB, PPC::MFCR, 1, IntCR).addReg(PPC::CR7);
|
||||
if (Inv) {
|
||||
unsigned Tmp1 = MakeReg(MVT::i32);
|
||||
BuildMI(BB, PPC::RLWINM, 4, Tmp1).addReg(IntCR).addImm(32-(3-Idx))
|
||||
.addImm(31).addImm(31);
|
||||
BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp1).addImm(1);
|
||||
} else {
|
||||
BuildMI(BB, PPC::RLWINM, 4, Result).addReg(IntCR).addImm(32-(3-Idx))
|
||||
.addImm(31).addImm(31);
|
||||
}
|
||||
}
|
||||
|
||||
/// SelectBitfieldInsert - turn an or of two masked values into
|
||||
/// the rotate left word immediate then mask insert (rlwimi) instruction.
|
||||
/// Returns true on success, false if the caller still needs to select OR.
|
||||
@ -1033,7 +1036,7 @@ unsigned ISel::FoldIfWideZeroExtend(SDOperand N) {
|
||||
return SelectExpr(N);
|
||||
}
|
||||
|
||||
unsigned ISel::SelectCC(SDOperand CC, unsigned &Opc) {
|
||||
unsigned ISel::SelectCC(SDOperand CC, unsigned& Opc, bool &Inv, unsigned& Idx) {
|
||||
unsigned Result, Tmp1, Tmp2;
|
||||
bool AlreadySelected = false;
|
||||
static const unsigned CompareOpcodes[] =
|
||||
@ -1047,6 +1050,7 @@ unsigned ISel::SelectCC(SDOperand CC, unsigned &Opc) {
|
||||
if (SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val)) {
|
||||
bool U;
|
||||
Opc = getBCCForSetCC(SetCC->getCondition(), U);
|
||||
Idx = getCRIdxForSetCC(SetCC->getCondition(), Inv);
|
||||
|
||||
// Pass the optional argument U to getImmediateForOpcode for SETCC,
|
||||
// so that it knows whether the SETCC immediate range is signed or not.
|
||||
@ -1083,38 +1087,58 @@ unsigned ISel::SelectCC(SDOperand CC, unsigned &Opc) {
|
||||
}
|
||||
} else {
|
||||
if (PPCCRopts)
|
||||
if (CC.getOpcode() == ISD::AND || CC.getOpcode() == ISD::OR)
|
||||
if (CC.getOperand(0).Val->hasOneUse() &&
|
||||
CC.getOperand(1).Val->hasOneUse()) {
|
||||
SetCCSDNode* Op0CC = dyn_cast<SetCCSDNode>(CC.getOperand(0).Val);
|
||||
SetCCSDNode* Op1CC = dyn_cast<SetCCSDNode>(CC.getOperand(1).Val);
|
||||
if (Op0CC && Op1CC) {
|
||||
++MultiBranch;
|
||||
bool Inv0, Inv1;
|
||||
unsigned Opc1;
|
||||
unsigned Idx0 = getCRIdxForSetCC(Op0CC->getCondition(), Inv0);
|
||||
unsigned Idx1 = getCRIdxForSetCC(Op1CC->getCondition(), Inv1);
|
||||
unsigned CROpc = getCROpForSetCC(CC.getOpcode(), Inv0, Inv1);
|
||||
Tmp1 = SelectCC(CC.getOperand(0), Opc);
|
||||
Tmp2 = SelectCC(CC.getOperand(1), Opc1);
|
||||
if (Inv0 && !Inv1) {
|
||||
std::swap(Tmp1, Tmp2);
|
||||
std::swap(Idx0, Idx1);
|
||||
Opc = Opc1;
|
||||
}
|
||||
if (Inv0 && Inv1) Opc = PPC32InstrInfo::invertPPCBranchOpcode(Opc);
|
||||
BuildMI(BB, CROpc, 5, Result).addImm(Idx0).addReg(Tmp1).addImm(Idx0)
|
||||
.addReg(Tmp2).addImm(Idx1);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
return SelectCCExpr(CC, Opc, Inv, Idx);
|
||||
// If this isn't a SetCC, then select the value and compare it against zero,
|
||||
// treating it as if it were a boolean.
|
||||
Opc = PPC::BNE;
|
||||
Idx = getCRIdxForSetCC(ISD::SETNE, Inv);
|
||||
Tmp1 = SelectExpr(CC);
|
||||
BuildMI(BB, PPC::CMPLWI, 2, Result).addReg(Tmp1).addImm(0);
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
|
||||
unsigned &Idx) {
|
||||
bool Inv0, Inv1;
|
||||
unsigned Idx0, Idx1, CROpc, Opc1, Tmp1, Tmp2;
|
||||
|
||||
// Allocate a condition register for this expression
|
||||
unsigned Result = RegMap->createVirtualRegister(PPC32::CRRCRegisterClass);
|
||||
|
||||
// Check for the operations we support:
|
||||
switch(N.getOpcode()) {
|
||||
default:
|
||||
Opc = PPC::BNE;
|
||||
Idx = getCRIdxForSetCC(ISD::SETNE, Inv);
|
||||
Tmp1 = SelectExpr(N);
|
||||
BuildMI(BB, PPC::CMPLWI, 2, Result).addReg(Tmp1).addImm(0);
|
||||
break;
|
||||
case ISD::OR:
|
||||
case ISD::AND:
|
||||
++MultiBranch;
|
||||
Tmp1 = SelectCCExpr(N.getOperand(0), Opc, Inv0, Idx0);
|
||||
Tmp2 = SelectCCExpr(N.getOperand(1), Opc1, Inv1, Idx1);
|
||||
CROpc = getCROpForSetCC(N.getOpcode(), Inv0, Inv1);
|
||||
if (Inv0 && !Inv1) {
|
||||
std::swap(Tmp1, Tmp2);
|
||||
std::swap(Idx0, Idx1);
|
||||
Opc = Opc1;
|
||||
}
|
||||
if (Inv0 && Inv1) Opc = PPC32InstrInfo::invertPPCBranchOpcode(Opc);
|
||||
BuildMI(BB, CROpc, 5, Result).addImm(Idx0).addReg(Tmp1).addImm(Idx0)
|
||||
.addReg(Tmp2).addImm(Idx1);
|
||||
Inv = false;
|
||||
Idx = Idx0;
|
||||
break;
|
||||
case ISD::SETCC:
|
||||
Tmp1 = SelectCC(N, Opc, Inv, Idx);
|
||||
Result = Tmp1;
|
||||
break;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Check to see if the load is a constant offset from a base register
|
||||
bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
|
||||
{
|
||||
@ -1138,9 +1162,10 @@ void ISel::SelectBranchCC(SDOperand N)
|
||||
MachineBasicBlock *Dest =
|
||||
cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
|
||||
|
||||
unsigned Opc, CCReg;
|
||||
bool Inv;
|
||||
unsigned Opc, CCReg, Idx;
|
||||
Select(N.getOperand(0)); //chain
|
||||
CCReg = SelectCC(N.getOperand(1), Opc);
|
||||
CCReg = SelectCC(N.getOperand(1), Opc, Inv, Idx);
|
||||
|
||||
// Iterate to the next basic block, unless we're already at the end of the
|
||||
ilist<MachineBasicBlock>::iterator It = BB, E = BB->getParent()->end();
|
||||
@ -1258,9 +1283,10 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Inv;
|
||||
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
|
||||
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
|
||||
unsigned CCReg = SelectCC(N.getOperand(0), Opc);
|
||||
unsigned CCReg = SelectCC(N.getOperand(0), Opc, Inv, Tmp3);
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
@ -1796,6 +1822,15 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
return Result;
|
||||
|
||||
case ISD::AND:
|
||||
if (PPCCRopts) {
|
||||
if (N.getOperand(0).getOpcode() == ISD::SETCC ||
|
||||
N.getOperand(1).getOpcode() == ISD::SETCC) {
|
||||
bool Inv;
|
||||
Tmp1 = SelectCCExpr(N, Opc, Inv, Tmp2);
|
||||
MoveCRtoGPR(Tmp1, Inv, Tmp2, Result);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
// FIXME: should add check in getImmediateForOpcode to return a value
|
||||
// indicating the immediate is a run of set bits so we can emit a bitfield
|
||||
@ -1827,6 +1862,15 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
case ISD::OR:
|
||||
if (SelectBitfieldInsert(N, Result))
|
||||
return Result;
|
||||
if (PPCCRopts) {
|
||||
if (N.getOperand(0).getOpcode() == ISD::SETCC ||
|
||||
N.getOperand(1).getOpcode() == ISD::SETCC) {
|
||||
bool Inv;
|
||||
Tmp1 = SelectCCExpr(N, Opc, Inv, Tmp2);
|
||||
MoveCRtoGPR(Tmp1, Inv, Tmp2, Result);
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
Tmp1 = SelectExpr(N.getOperand(0));
|
||||
switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
|
||||
default: assert(0 && "unhandled result code");
|
||||
@ -2178,30 +2222,19 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Inv = false;
|
||||
unsigned CCReg = SelectCC(N, Opc);
|
||||
unsigned IntCR = MakeReg(MVT::i32);
|
||||
unsigned ShAmt = getCRIdxForBCC(Opc, Inv);
|
||||
BuildMI(BB, PPC::MCRF, 1, PPC::CR7).addReg(CCReg);
|
||||
BuildMI(BB, PPC::MFCR, 1, IntCR).addReg(PPC::CR7);
|
||||
if (Inv) {
|
||||
Tmp1 = MakeReg(MVT::i32);
|
||||
BuildMI(BB, PPC::RLWINM, 4, Tmp1).addReg(IntCR).addImm(ShAmt)
|
||||
.addImm(31).addImm(31);
|
||||
BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp1).addImm(1);
|
||||
} else {
|
||||
BuildMI(BB, PPC::RLWINM, 4, Result).addReg(IntCR).addImm(ShAmt)
|
||||
.addImm(31).addImm(31);
|
||||
}
|
||||
bool Inv;
|
||||
unsigned CCReg = SelectCC(N, Opc, Inv, Tmp2);
|
||||
MoveCRtoGPR(CCReg, Inv, Tmp2, Result);
|
||||
return Result;
|
||||
}
|
||||
assert(0 && "Is this legal?");
|
||||
return 0;
|
||||
|
||||
case ISD::SELECT: {
|
||||
bool Inv;
|
||||
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
|
||||
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE
|
||||
unsigned CCReg = SelectCC(N.getOperand(0), Opc);
|
||||
unsigned CCReg = SelectCC(N.getOperand(0), Opc, Inv, Tmp3);
|
||||
|
||||
// Create an iterator with which to insert the MBB for copying the false
|
||||
// value and the MBB to hold the PHI instruction for this SetCC.
|
||||
|
Loading…
Reference in New Issue
Block a user