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:
Nate Begeman 2005-04-18 07:48:09 +00:00
parent ea96b5edbb
commit 1cbf3abbb8

View File

@ -524,9 +524,11 @@ public:
unsigned getGlobalBaseReg(); unsigned getGlobalBaseReg();
unsigned getConstDouble(double floatVal, unsigned Result); unsigned getConstDouble(double floatVal, unsigned Result);
void MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result);
bool SelectBitfieldInsert(SDOperand OR, unsigned Result); bool SelectBitfieldInsert(SDOperand OR, unsigned Result);
unsigned FoldIfWideZeroExtend(SDOperand N); 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 SelectExpr(SDOperand N, bool Recording=false);
unsigned SelectExprFP(SDOperand N, unsigned Result); unsigned SelectExprFP(SDOperand N, unsigned Result);
void Select(SDOperand N); void Select(SDOperand N);
@ -727,22 +729,6 @@ static unsigned getCRIdxForSetCC(unsigned Condition, bool& Inv) {
return 0; 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 /// IndexedOpForOp - Return the indexed variant for each of the PowerPC load
/// and store immediate instructions. /// and store immediate instructions.
static unsigned IndexedOpForOp(unsigned Opcode) { static unsigned IndexedOpForOp(unsigned Opcode) {
@ -934,6 +920,23 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
return Result; 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 /// SelectBitfieldInsert - turn an or of two masked values into
/// the rotate left word immediate then mask insert (rlwimi) instruction. /// the rotate left word immediate then mask insert (rlwimi) instruction.
/// Returns true on success, false if the caller still needs to select OR. /// 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); 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; unsigned Result, Tmp1, Tmp2;
bool AlreadySelected = false; bool AlreadySelected = false;
static const unsigned CompareOpcodes[] = static const unsigned CompareOpcodes[] =
@ -1047,6 +1050,7 @@ unsigned ISel::SelectCC(SDOperand CC, unsigned &Opc) {
if (SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val)) { if (SetCCSDNode* SetCC = dyn_cast<SetCCSDNode>(CC.Val)) {
bool U; bool U;
Opc = getBCCForSetCC(SetCC->getCondition(), U); Opc = getBCCForSetCC(SetCC->getCondition(), U);
Idx = getCRIdxForSetCC(SetCC->getCondition(), Inv);
// Pass the optional argument U to getImmediateForOpcode for SETCC, // Pass the optional argument U to getImmediateForOpcode for SETCC,
// so that it knows whether the SETCC immediate range is signed or not. // 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 { } else {
if (PPCCRopts) if (PPCCRopts)
if (CC.getOpcode() == ISD::AND || CC.getOpcode() == ISD::OR) return SelectCCExpr(CC, Opc, Inv, Idx);
if (CC.getOperand(0).Val->hasOneUse() && // If this isn't a SetCC, then select the value and compare it against zero,
CC.getOperand(1).Val->hasOneUse()) { // treating it as if it were a boolean.
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;
}
}
Opc = PPC::BNE; Opc = PPC::BNE;
Idx = getCRIdxForSetCC(ISD::SETNE, Inv);
Tmp1 = SelectExpr(CC); Tmp1 = SelectExpr(CC);
BuildMI(BB, PPC::CMPLWI, 2, Result).addReg(Tmp1).addImm(0); BuildMI(BB, PPC::CMPLWI, 2, Result).addReg(Tmp1).addImm(0);
} }
return Result; 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 /// Check to see if the load is a constant offset from a base register
bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset) bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
{ {
@ -1138,9 +1162,10 @@ void ISel::SelectBranchCC(SDOperand N)
MachineBasicBlock *Dest = MachineBasicBlock *Dest =
cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock(); cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock();
unsigned Opc, CCReg; bool Inv;
unsigned Opc, CCReg, Idx;
Select(N.getOperand(0)); //chain 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 // Iterate to the next basic block, unless we're already at the end of the
ilist<MachineBasicBlock>::iterator It = BB, E = BB->getParent()->end(); ilist<MachineBasicBlock>::iterator It = BB, E = BB->getParent()->end();
@ -1258,9 +1283,10 @@ unsigned ISel::SelectExprFP(SDOperand N, unsigned Result)
return 0; return 0;
} }
bool Inv;
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE 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 // 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. // 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; return Result;
case ISD::AND: 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)); Tmp1 = SelectExpr(N.getOperand(0));
// FIXME: should add check in getImmediateForOpcode to return a value // 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 // 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: case ISD::OR:
if (SelectBitfieldInsert(N, Result)) if (SelectBitfieldInsert(N, Result))
return 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)); Tmp1 = SelectExpr(N.getOperand(0));
switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) { switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
default: assert(0 && "unhandled result code"); default: assert(0 && "unhandled result code");
@ -2178,30 +2222,19 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
} }
} }
bool Inv = false; bool Inv;
unsigned CCReg = SelectCC(N, Opc); unsigned CCReg = SelectCC(N, Opc, Inv, Tmp2);
unsigned IntCR = MakeReg(MVT::i32); MoveCRtoGPR(CCReg, Inv, Tmp2, Result);
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);
}
return Result; return Result;
} }
assert(0 && "Is this legal?"); assert(0 && "Is this legal?");
return 0; return 0;
case ISD::SELECT: { case ISD::SELECT: {
bool Inv;
unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE
unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE 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 // 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. // value and the MBB to hold the PHI instruction for this SetCC.