forked from OSchip/llvm-project
- 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:
parent
88e1b97f16
commit
3b0f5e4d61
|
@ -409,6 +409,28 @@ public:
|
|||
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
|
||||
/// method returns the ValueType to promote to.
|
||||
MVT getTypeToPromoteTo(unsigned Op, MVT VT) const {
|
||||
|
@ -903,6 +925,16 @@ protected:
|
|||
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
|
||||
/// 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
|
||||
|
@ -1437,6 +1469,11 @@ private:
|
|||
/// (FP_EXTEND and FP_ROUND).
|
||||
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;
|
||||
|
||||
std::vector<APFloat> LegalFPImmediates;
|
||||
|
|
|
@ -193,6 +193,11 @@ private:
|
|||
SmallPtrSet<SDNode*, 32> &NodesLeadingTo);
|
||||
|
||||
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 &Hi);
|
||||
|
@ -1886,10 +1891,10 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||
Tmp3 = Node->getOperand(3); // RHS
|
||||
Tmp4 = Node->getOperand(1); // CC
|
||||
|
||||
LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
|
||||
LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4);
|
||||
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 result against zero to select between true and false values.
|
||||
if (Tmp3.getNode() == 0) {
|
||||
|
@ -2772,9 +2777,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||
Tmp4 = LegalizeOp(Node->getOperand(3)); // False
|
||||
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 result against zero to select between true and false values.
|
||||
if (Tmp2.getNode() == 0) {
|
||||
|
@ -2798,7 +2803,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||
Tmp1 = Node->getOperand(0);
|
||||
Tmp2 = Node->getOperand(1);
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// 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.
|
||||
|
|
|
@ -406,6 +406,7 @@ TargetLowering::TargetLowering(TargetMachine &tm)
|
|||
memset(TruncStoreActions, 0, sizeof(TruncStoreActions));
|
||||
memset(IndexedModeActions, 0, sizeof(IndexedModeActions));
|
||||
memset(ConvertActions, 0, sizeof(ConvertActions));
|
||||
memset(CondCodeActions, 0, sizeof(CondCodeActions));
|
||||
|
||||
// Set default actions for various operations.
|
||||
for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) {
|
||||
|
|
|
@ -92,7 +92,15 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
|||
setTruncStoreAction(MVT::i64, MVT::i8 , Expand);
|
||||
setTruncStoreAction(MVT::i32, MVT::i16, 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
|
||||
// operation.
|
||||
|
@ -4883,26 +4891,8 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) {
|
|||
DAG.getConstant(X86CC, MVT::i8), Cond);
|
||||
}
|
||||
|
||||
assert(isFP && "Illegal integer SetCC!");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
assert(0 && "Illegal SetCC!");
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue