- Add target lowering hooks that specify which setcc conditions are illegal,

i.e. conditions that cannot be checked with a single instruction. For example,
SETONE and SETUEQ on x86.
- Teach legalizer to implement *illegal* setcc as a and / or of a number of
legal setcc nodes. For now, only implement FP conditions. e.g. SETONE is
implemented as SETO & SETNE, SETUEQ is SETUO | SETEQ.
- Move x86 target over.

llvm-svn: 57542
This commit is contained in:
Evan Cheng 2008-10-15 02:05:31 +00:00
parent 88e1b97f16
commit 3b0f5e4d61
5 changed files with 114 additions and 26 deletions

View File

@ -409,6 +409,28 @@ public:
getConvertAction(FromVT, ToVT) == Custom); getConvertAction(FromVT, ToVT) == Custom);
} }
/// getCondCodeAction - Return how the condition code should be treated:
/// either it is legal, needs to be expanded to some other code sequence,
/// or the target has a custom expander for it.
LegalizeAction
getCondCodeAction(ISD::CondCode CC, MVT VT) const {
assert((unsigned)CC < array_lengthof(CondCodeActions) &&
(unsigned)VT.getSimpleVT() < sizeof(CondCodeActions[0])*4 &&
"Table isn't big enough!");
LegalizeAction Action = (LegalizeAction)
((CondCodeActions[CC] >> (2*VT.getSimpleVT())) & 3);
assert(Action != Promote && "Can't promote condition code!");
return Action;
}
/// isCondCodeLegal - Return true if the specified condition code is legal
/// on this target.
bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const {
return getCondCodeAction(CC, VT) == Legal ||
getCondCodeAction(CC, VT) == Custom;
}
/// getTypeToPromoteTo - If the action for this operation is to promote, this /// getTypeToPromoteTo - If the action for this operation is to promote, this
/// method returns the ValueType to promote to. /// method returns the ValueType to promote to.
MVT getTypeToPromoteTo(unsigned Op, MVT VT) const { MVT getTypeToPromoteTo(unsigned Op, MVT VT) const {
@ -903,6 +925,16 @@ protected:
ToVT.getSimpleVT()*2; ToVT.getSimpleVT()*2;
} }
/// setCondCodeAction - Indicate that the specified condition code is or isn't
/// supported on the target and indicate what to do about it.
void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action) {
assert((unsigned)VT.getSimpleVT() < sizeof(CondCodeActions[0])*4 &&
(unsigned)CC < array_lengthof(CondCodeActions) &&
"Table isn't big enough!");
CondCodeActions[(unsigned)CC] &= ~(uint64_t(3UL) << VT.getSimpleVT()*2);
CondCodeActions[(unsigned)CC] |= (uint64_t)Action << VT.getSimpleVT()*2;
}
/// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the /// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the
/// promotion code defaults to trying a larger integer/fp until it can find /// promotion code defaults to trying a larger integer/fp until it can find
/// one that works. If that default is insufficient, this method can be used /// one that works. If that default is insufficient, this method can be used
@ -1437,6 +1469,11 @@ private:
/// (FP_EXTEND and FP_ROUND). /// (FP_EXTEND and FP_ROUND).
uint64_t ConvertActions[MVT::LAST_VALUETYPE]; uint64_t ConvertActions[MVT::LAST_VALUETYPE];
/// CondCodeActions - For each condition code (ISD::CondCode) keep a
/// LegalizeAction that indicates how instruction selection should
/// deal with the condition code.
uint64_t CondCodeActions[ISD::SETCC_INVALID];
ValueTypeActionImpl ValueTypeActions; ValueTypeActionImpl ValueTypeActions;
std::vector<APFloat> LegalFPImmediates; std::vector<APFloat> LegalFPImmediates;

View File

@ -193,6 +193,11 @@ private:
SmallPtrSet<SDNode*, 32> &NodesLeadingTo); SmallPtrSet<SDNode*, 32> &NodesLeadingTo);
void LegalizeSetCCOperands(SDValue &LHS, SDValue &RHS, SDValue &CC); void LegalizeSetCCOperands(SDValue &LHS, SDValue &RHS, SDValue &CC);
void LegalizeSetCCCondCode(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC);
void LegalizeSetCC(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC) {
LegalizeSetCCOperands(LHS, RHS, CC);
LegalizeSetCCCondCode(VT, LHS, RHS, CC);
}
SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned, SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned,
SDValue &Hi); SDValue &Hi);
@ -1886,10 +1891,10 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
Tmp3 = Node->getOperand(3); // RHS Tmp3 = Node->getOperand(3); // RHS
Tmp4 = Node->getOperand(1); // CC Tmp4 = Node->getOperand(1); // CC
LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4); LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4);
LastCALLSEQ_END = DAG.getEntryNode(); LastCALLSEQ_END = DAG.getEntryNode();
// If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, // If we didn't get both a LHS and RHS back from LegalizeSetCC,
// the LHS is a legal SETCC itself. In this case, we need to compare // the LHS is a legal SETCC itself. In this case, we need to compare
// the result against zero to select between true and false values. // the result against zero to select between true and false values.
if (Tmp3.getNode() == 0) { if (Tmp3.getNode() == 0) {
@ -2772,9 +2777,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
Tmp4 = LegalizeOp(Node->getOperand(3)); // False Tmp4 = LegalizeOp(Node->getOperand(3)); // False
SDValue CC = Node->getOperand(4); SDValue CC = Node->getOperand(4);
LegalizeSetCCOperands(Tmp1, Tmp2, CC); LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, CC);
// If we didn't get both a LHS and RHS back from LegalizeSetCCOperands, // If we didn't get both a LHS and RHS back from LegalizeSetCC,
// the LHS is a legal SETCC itself. In this case, we need to compare // the LHS is a legal SETCC itself. In this case, we need to compare
// the result against zero to select between true and false values. // the result against zero to select between true and false values.
if (Tmp2.getNode() == 0) { if (Tmp2.getNode() == 0) {
@ -2798,7 +2803,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
Tmp1 = Node->getOperand(0); Tmp1 = Node->getOperand(0);
Tmp2 = Node->getOperand(1); Tmp2 = Node->getOperand(1);
Tmp3 = Node->getOperand(2); Tmp3 = Node->getOperand(2);
LegalizeSetCCOperands(Tmp1, Tmp2, Tmp3); LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, Tmp3);
// If we had to Expand the SetCC operands into a SELECT node, then it may // If we had to Expand the SetCC operands into a SELECT node, then it may
// not always be possible to return a true LHS & RHS. In this case, just // not always be possible to return a true LHS & RHS. In this case, just
@ -4877,6 +4882,50 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDValue &LHS,
RHS = Tmp2; RHS = Tmp2;
} }
/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and
/// condition code CC on the current target. This routine assumes LHS and rHS
/// have already been legalized by LegalizeSetCCOperands. It expands SETCC with
/// illegal condition code into AND / OR of multiple SETCC values.
void SelectionDAGLegalize::LegalizeSetCCCondCode(MVT VT,
SDValue &LHS, SDValue &RHS,
SDValue &CC) {
MVT OpVT = LHS.getValueType();
ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
switch (TLI.getCondCodeAction(CCCode, OpVT)) {
default: assert(0 && "Unknown condition code action!");
case TargetLowering::Legal:
// Nothing to do.
break;
case TargetLowering::Expand: {
ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID;
unsigned Opc = 0;
switch (CCCode) {
default: assert(0 && "Don't know how to expand this condition!"); abort();
case ISD::SETOEQ: CC1 = ISD::SETO; CC2 = ISD::SETEQ; Opc = ISD::AND; break;
case ISD::SETOGT: CC1 = ISD::SETO; CC2 = ISD::SETGT; Opc = ISD::AND; break;
case ISD::SETOGE: CC1 = ISD::SETO; CC2 = ISD::SETGE; Opc = ISD::AND; break;
case ISD::SETOLT: CC1 = ISD::SETO; CC2 = ISD::SETLT; Opc = ISD::AND; break;
case ISD::SETOLE: CC1 = ISD::SETO; CC2 = ISD::SETLE; Opc = ISD::AND; break;
case ISD::SETONE: CC1 = ISD::SETO; CC2 = ISD::SETNE; Opc = ISD::AND; break;
case ISD::SETUEQ: CC1 = ISD::SETUO; CC2 = ISD::SETEQ; Opc = ISD::OR; break;
case ISD::SETUGT: CC1 = ISD::SETUO; CC2 = ISD::SETGT; Opc = ISD::OR; break;
case ISD::SETUGE: CC1 = ISD::SETUO; CC2 = ISD::SETGE; Opc = ISD::OR; break;
case ISD::SETULT: CC1 = ISD::SETUO; CC2 = ISD::SETLT; Opc = ISD::OR; break;
case ISD::SETULE: CC1 = ISD::SETUO; CC2 = ISD::SETLE; Opc = ISD::OR; break;
case ISD::SETUNE: CC1 = ISD::SETUO; CC2 = ISD::SETNE; Opc = ISD::OR; break;
// FIXME: Implement more expansions.
}
SDValue SetCC1 = DAG.getSetCC(VT, LHS, RHS, CC1);
SDValue SetCC2 = DAG.getSetCC(VT, LHS, RHS, CC2);
LHS = DAG.getNode(Opc, VT, SetCC1, SetCC2);
RHS = SDValue();
CC = SDValue();
break;
}
}
}
/// EmitStackConvert - Emit a store/load combination to the stack. This stores /// EmitStackConvert - Emit a store/load combination to the stack. This stores
/// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does /// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does
/// a load from the stack slot to DestVT, extending it if needed. /// a load from the stack slot to DestVT, extending it if needed.

View File

@ -406,6 +406,7 @@ TargetLowering::TargetLowering(TargetMachine &tm)
memset(TruncStoreActions, 0, sizeof(TruncStoreActions)); memset(TruncStoreActions, 0, sizeof(TruncStoreActions));
memset(IndexedModeActions, 0, sizeof(IndexedModeActions)); memset(IndexedModeActions, 0, sizeof(IndexedModeActions));
memset(ConvertActions, 0, sizeof(ConvertActions)); memset(ConvertActions, 0, sizeof(ConvertActions));
memset(CondCodeActions, 0, sizeof(CondCodeActions));
// Set default actions for various operations. // Set default actions for various operations.
for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) { for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) {

View File

@ -92,7 +92,15 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setTruncStoreAction(MVT::i64, MVT::i8 , Expand); setTruncStoreAction(MVT::i64, MVT::i8 , Expand);
setTruncStoreAction(MVT::i32, MVT::i16, Expand); setTruncStoreAction(MVT::i32, MVT::i16, Expand);
setTruncStoreAction(MVT::i32, MVT::i8 , Expand); setTruncStoreAction(MVT::i32, MVT::i8 , Expand);
setTruncStoreAction(MVT::i16, MVT::i8, Expand); setTruncStoreAction(MVT::i16, MVT::i8, Expand);
// SETOEQ and SETUNE require checking two conditions.
setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
setCondCodeAction(ISD::SETOEQ, MVT::f80, Expand);
setCondCodeAction(ISD::SETUNE, MVT::f32, Expand);
setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
setCondCodeAction(ISD::SETUNE, MVT::f80, Expand);
// Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this // Promote all UINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have this
// operation. // operation.
@ -4883,26 +4891,8 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
DAG.getConstant(X86CC, MVT::i8), Cond); DAG.getConstant(X86CC, MVT::i8), Cond);
} }
assert(isFP && "Illegal integer SetCC!"); assert(0 && "Illegal SetCC!");
return SDValue();
Cond = DAG.getNode(X86ISD::CMP, MVT::i32, Op0, Op1);
switch (SetCCOpcode) {
default: assert(false && "Illegal floating point SetCC!");
case ISD::SETOEQ: { // !PF & ZF
SDValue Tmp1 = DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(X86::COND_NP, MVT::i8), Cond);
SDValue Tmp2 = DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(X86::COND_E, MVT::i8), Cond);
return DAG.getNode(ISD::AND, MVT::i8, Tmp1, Tmp2);
}
case ISD::SETUNE: { // PF | !ZF
SDValue Tmp1 = DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(X86::COND_P, MVT::i8), Cond);
SDValue Tmp2 = DAG.getNode(X86ISD::SETCC, MVT::i8,
DAG.getConstant(X86::COND_NE, MVT::i8), Cond);
return DAG.getNode(ISD::OR, MVT::i8, Tmp1, Tmp2);
}
}
} }
SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) { SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) {

View File

@ -0,0 +1,11 @@
; RUN: llvm-as < %s | llc -march=x86 | grep set | count 2
; RUN: llvm-as < %s | llc -march=x86 | grep and
define zeroext i8 @t(double %x) nounwind readnone {
entry:
%0 = fptosi double %x to i32 ; <i32> [#uses=1]
%1 = sitofp i32 %0 to double ; <double> [#uses=1]
%2 = fcmp oeq double %1, %x ; <i1> [#uses=1]
%retval12 = zext i1 %2 to i8 ; <i8> [#uses=1]
ret i8 %retval12
}