Fix some of the stuff in the PPC README file, and clean up legalization

of the SELECT_CC, BR_CC, and BRTWOWAY_CC nodes.

llvm-svn: 25875
This commit is contained in:
Nate Begeman 2006-02-01 07:19:44 +00:00
parent 3da1bb520e
commit 7e7f439f85
7 changed files with 300 additions and 275 deletions

View File

@ -1081,6 +1081,16 @@ SDOperand DAGCombiner::visitOR(SDNode *N) {
WorkList.push_back(ORNode.Val); WorkList.push_back(ORNode.Val);
return DAG.getNode(ISD::ZERO_EXTEND, VT, ORNode); return DAG.getNode(ISD::ZERO_EXTEND, VT, ORNode);
} }
// fold (or (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (or x, y))
if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) ||
(N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL) ||
(N0.getOpcode() == ISD::SRA && N1.getOpcode() == ISD::SRA)) &&
N0.getOperand(1) == N1.getOperand(1)) {
SDOperand ORNode = DAG.getNode(ISD::OR, N0.getOperand(0).getValueType(),
N0.getOperand(0), N1.getOperand(0));
WorkList.push_back(ORNode.Val);
return DAG.getNode(N0.getOpcode(), VT, ORNode, N0.getOperand(1));
}
// canonicalize shl to left side in a shl/srl pair, to match rotate // canonicalize shl to left side in a shl/srl pair, to match rotate
if (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SHL) if (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SHL)
std::swap(N0, N1); std::swap(N0, N1);
@ -1196,6 +1206,16 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) {
WorkList.push_back(XORNode.Val); WorkList.push_back(XORNode.Val);
return DAG.getNode(ISD::ZERO_EXTEND, VT, XORNode); return DAG.getNode(ISD::ZERO_EXTEND, VT, XORNode);
} }
// fold (xor (shl/srl/sra x), (shl/srl/sra y)) -> (shl/srl/sra (xor x, y))
if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) ||
(N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL) ||
(N0.getOpcode() == ISD::SRA && N1.getOpcode() == ISD::SRA)) &&
N0.getOperand(1) == N1.getOperand(1)) {
SDOperand XORNode = DAG.getNode(ISD::XOR, N0.getOperand(0).getValueType(),
N0.getOperand(0), N1.getOperand(0));
WorkList.push_back(XORNode.Val);
return DAG.getNode(N0.getOpcode(), VT, XORNode, N0.getOperand(1));
}
return SDOperand(); return SDOperand();
} }
@ -1396,14 +1416,20 @@ SDOperand DAGCombiner::visitSELECT(SDNode *N) {
// fold X ? Y : X --> X ? Y : 0 --> X & Y // fold X ? Y : X --> X ? Y : 0 --> X & Y
if (MVT::i1 == VT && N0 == N2) if (MVT::i1 == VT && N0 == N2)
return DAG.getNode(ISD::AND, VT, N0, N1); return DAG.getNode(ISD::AND, VT, N0, N1);
// If we can fold this based on the true/false value, do so. // If we can fold this based on the true/false value, do so.
if (SimplifySelectOps(N, N1, N2)) if (SimplifySelectOps(N, N1, N2))
return SDOperand(); return SDOperand();
// fold selects based on a setcc into other things, such as min/max/abs // fold selects based on a setcc into other things, such as min/max/abs
if (N0.getOpcode() == ISD::SETCC) if (N0.getOpcode() == ISD::SETCC)
return SimplifySelect(N0, N1, N2); // FIXME:
// Check against MVT::Other for SELECT_CC, which is a workaround for targets
// having to say they don't support SELECT_CC on every type the DAG knows
// about, since there is no way to mark an opcode illegal at all value types
if (TLI.isOperationLegal(ISD::SELECT_CC, MVT::Other))
return DAG.getNode(ISD::SELECT_CC, VT, N0.getOperand(0), N0.getOperand(1),
N1, N2, N0.getOperand(2));
else
return SimplifySelect(N0, N1, N2);
return SDOperand(); return SDOperand();
} }
@ -1927,6 +1953,13 @@ SDOperand DAGCombiner::visitBRCOND(SDNode *N) {
// unconditional branch // unconditional branch
if (N1C && N1C->getValue() == 1) if (N1C && N1C->getValue() == 1)
return DAG.getNode(ISD::BR, MVT::Other, Chain, N2); return DAG.getNode(ISD::BR, MVT::Other, Chain, N2);
// fold a brcond with a setcc condition into a BR_CC node if BR_CC is legal
// on the target.
if (N1.getOpcode() == ISD::SETCC &&
TLI.isOperationLegal(ISD::BR_CC, MVT::Other)) {
return DAG.getNode(ISD::BR_CC, MVT::Other, Chain, N1.getOperand(2),
N1.getOperand(0), N1.getOperand(1), N2);
}
return SDOperand(); return SDOperand();
} }
@ -1943,6 +1976,19 @@ SDOperand DAGCombiner::visitBRCONDTWOWAY(SDNode *N) {
// unconditional branch to false mbb // unconditional branch to false mbb
if (N1C && N1C->isNullValue()) if (N1C && N1C->isNullValue())
return DAG.getNode(ISD::BR, MVT::Other, Chain, N3); return DAG.getNode(ISD::BR, MVT::Other, Chain, N3);
// fold a brcondtwoway with a setcc condition into a BRTWOWAY_CC node if
// BRTWOWAY_CC is legal on the target.
if (N1.getOpcode() == ISD::SETCC &&
TLI.isOperationLegal(ISD::BRTWOWAY_CC, MVT::Other)) {
std::vector<SDOperand> Ops;
Ops.push_back(Chain);
Ops.push_back(N1.getOperand(2));
Ops.push_back(N1.getOperand(0));
Ops.push_back(N1.getOperand(1));
Ops.push_back(N2);
Ops.push_back(N3);
return DAG.getNode(ISD::BRTWOWAY_CC, MVT::Other, Ops);
}
return SDOperand(); return SDOperand();
} }

View File

@ -106,6 +106,8 @@ private:
void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi); void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);
SDOperand PromoteOp(SDOperand O); SDOperand PromoteOp(SDOperand O);
void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
SDOperand ExpandLibCall(const char *Name, SDNode *Node, SDOperand ExpandLibCall(const char *Name, SDNode *Node,
SDOperand &Hi); SDOperand &Hi);
SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
@ -717,33 +719,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break; break;
case ISD::BR_CC: case ISD::BR_CC:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
if (!isTypeLegal(Node->getOperand(2).getValueType())) { Tmp2 = Node->getOperand(2); // LHS
Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), Tmp3 = Node->getOperand(3); // RHS
Node->getOperand(2), // LHS Tmp4 = Node->getOperand(1); // CC
Node->getOperand(3), // RHS
Node->getOperand(1))); LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
// If we get a SETCC back from legalizing the SETCC node we just
// created, then use its LHS, RHS, and CC directly in creating a new // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands,
// node. Otherwise, select between the true and false value based on // the LHS is a legal SETCC itself. In this case, we need to compare
// comparing the result of the legalized with zero. // the result against zero to select between true and false values.
if (Tmp2.getOpcode() == ISD::SETCC) { if (Tmp3.Val == 0) {
Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Tmp2.getOperand(2), Tmp3 = DAG.getConstant(0, Tmp2.getValueType());
Tmp2.getOperand(0), Tmp2.getOperand(1), Tmp4 = DAG.getCondCode(ISD::SETNE);
Node->getOperand(4));
} else {
Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1,
DAG.getCondCode(ISD::SETNE),
Tmp2, DAG.getConstant(0, Tmp2.getValueType()),
Node->getOperand(4));
}
break;
} }
Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp4, Tmp2, Tmp3,
Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS Node->getOperand(4));
Result = DAG.UpdateNodeOperands(Result, Tmp1, Node->getOperand(1), Tmp2,
Tmp3, Node->getOperand(4));
switch (TLI.getOperationAction(ISD::BR_CC, Tmp3.getValueType())) { switch (TLI.getOperationAction(ISD::BR_CC, Tmp3.getValueType())) {
default: assert(0 && "Unexpected action for BR_CC!"); default: assert(0 && "Unexpected action for BR_CC!");
@ -805,61 +796,44 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break; break;
} }
break; break;
case ISD::BRTWOWAY_CC: case ISD::BRTWOWAY_CC: {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
if (isTypeLegal(Node->getOperand(2).getValueType())) { Tmp2 = Node->getOperand(2); // LHS
Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS Tmp3 = Node->getOperand(3); // RHS
Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS Tmp4 = Node->getOperand(1); // CC
if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2) ||
Tmp3 != Node->getOperand(3)) { LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
std::vector<SDOperand> Ops;
Ops.push_back(Tmp1); // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands,
Ops.push_back(Node->getOperand(1)); // the LHS is a legal SETCC itself. In this case, we need to compare
Ops.push_back(Tmp2); // the result against zero to select between true and false values.
Ops.push_back(Tmp3); if (Tmp3.Val == 0) {
Ops.push_back(Node->getOperand(4)); Tmp3 = DAG.getConstant(0, Tmp2.getValueType());
Ops.push_back(Node->getOperand(5)); Tmp4 = DAG.getCondCode(ISD::SETNE);
Result = DAG.UpdateNodeOperands(Result, Ops); }
} std::vector<SDOperand> Ops;
Ops.push_back(Tmp1);
Ops.push_back(Tmp4);
Ops.push_back(Tmp2);
Ops.push_back(Tmp3);
Ops.push_back(Node->getOperand(4));
Ops.push_back(Node->getOperand(5));
Result = DAG.UpdateNodeOperands(Result, Ops);
// Everything is legal, see if we should expand this op or something.
switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal: break;
case TargetLowering::Expand:
Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1,
DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), Tmp2,
Tmp3, Tmp4),
Result.getOperand(4));
Result = DAG.getNode(ISD::BR, MVT::Other, Result, Result.getOperand(5));
break; break;
} else {
Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(),
Node->getOperand(2), // LHS
Node->getOperand(3), // RHS
Node->getOperand(1)));
// If this target does not support BRTWOWAY_CC, lower it to a BRCOND/BR
// pair.
switch (TLI.getOperationAction(ISD::BRTWOWAY_CC, MVT::Other)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal: {
// If we get a SETCC back from legalizing the SETCC node we just
// created, then use its LHS, RHS, and CC directly in creating a new
// node. Otherwise, select between the true and false value based on
// comparing the result of the legalized with zero.
std::vector<SDOperand> Ops;
Ops.push_back(Tmp1);
if (Tmp2.getOpcode() == ISD::SETCC) {
Ops.push_back(Tmp2.getOperand(2));
Ops.push_back(Tmp2.getOperand(0));
Ops.push_back(Tmp2.getOperand(1));
} else {
Ops.push_back(DAG.getCondCode(ISD::SETNE));
Ops.push_back(Tmp2);
Ops.push_back(DAG.getConstant(0, Tmp2.getValueType()));
}
Ops.push_back(Node->getOperand(4));
Ops.push_back(Node->getOperand(5));
Result = DAG.UpdateNodeOperands(Result, Ops);
break;
}
case TargetLowering::Expand:
Result = DAG.getNode(ISD::BRCOND, MVT::Other, Tmp1, Tmp2,
Node->getOperand(4));
Result = DAG.getNode(ISD::BR, MVT::Other, Result, Node->getOperand(5));
break;
}
} }
break; break;
}
case ISD::LOAD: { case ISD::LOAD: {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.
@ -1315,156 +1289,47 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
} }
} }
break; break;
case ISD::SELECT_CC: case ISD::SELECT_CC: {
Tmp1 = Node->getOperand(0); // LHS
Tmp2 = Node->getOperand(1); // RHS
Tmp3 = LegalizeOp(Node->getOperand(2)); // True Tmp3 = LegalizeOp(Node->getOperand(2)); // True
Tmp4 = LegalizeOp(Node->getOperand(3)); // False Tmp4 = LegalizeOp(Node->getOperand(3)); // False
SDOperand CC = Node->getOperand(4);
if (isTypeLegal(Node->getOperand(0).getValueType())) { LegalizeSetCCOperands(Tmp1, Tmp2, CC);
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands,
// the LHS is a legal SETCC itself. In this case, we need to compare
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, // the result against zero to select between true and false values.
Node->getOperand(4)); if (Tmp2.Val == 0) {
Tmp2 = DAG.getConstant(0, Tmp1.getValueType());
// Everything is legal, see if we should expand this op or something. CC = DAG.getCondCode(ISD::SETNE);
switch (TLI.getOperationAction(ISD::SELECT_CC, }
Node->getOperand(0).getValueType())) { Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, CC);
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal: break; // Everything is legal, see if we should expand this op or something.
case TargetLowering::Custom: switch (TLI.getOperationAction(ISD::SELECT_CC, Tmp3.getValueType())) {
Tmp1 = TLI.LowerOperation(Result, DAG); default: assert(0 && "This action is not supported yet!");
if (Tmp1.Val) Result = Tmp1; case TargetLowering::Legal: break;
break; case TargetLowering::Custom:
} Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
break; break;
} else {
Tmp1 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(),
Node->getOperand(0), // LHS
Node->getOperand(1), // RHS
Node->getOperand(4)));
// If we get a SETCC back from legalizing the SETCC node we just
// created, then use its LHS, RHS, and CC directly in creating a new
// node. Otherwise, select between the true and false value based on
// comparing the result of the legalized with zero.
if (Tmp1.getOpcode() == ISD::SETCC) {
Result = DAG.getNode(ISD::SELECT_CC, Tmp3.getValueType(),
Tmp1.getOperand(0), Tmp1.getOperand(1),
Tmp3, Tmp4, Tmp1.getOperand(2));
} else {
Result = DAG.getSelectCC(Tmp1,
DAG.getConstant(0, Tmp1.getValueType()),
Tmp3, Tmp4, ISD::SETNE);
}
} }
break; break;
}
case ISD::SETCC: case ISD::SETCC:
switch (getTypeAction(Node->getOperand(0).getValueType())) { Tmp1 = Node->getOperand(0);
case Legal: Tmp2 = Node->getOperand(1);
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS Tmp3 = Node->getOperand(2);
Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS LegalizeSetCCOperands(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
// return the value we legalized, returned in the LHS
if (Tmp2.Val == 0) {
Result = Tmp1;
break; break;
case Promote:
Tmp1 = PromoteOp(Node->getOperand(0)); // LHS
Tmp2 = PromoteOp(Node->getOperand(1)); // RHS
// If this is an FP compare, the operands have already been extended.
if (MVT::isInteger(Node->getOperand(0).getValueType())) {
MVT::ValueType VT = Node->getOperand(0).getValueType();
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
// Otherwise, we have to insert explicit sign or zero extends. Note
// that we could insert sign extends for ALL conditions, but zero extend
// is cheaper on many machines (an AND instead of two shifts), so prefer
// it.
switch (cast<CondCodeSDNode>(Node->getOperand(2))->get()) {
default: assert(0 && "Unknown integer comparison!");
case ISD::SETEQ:
case ISD::SETNE:
case ISD::SETUGE:
case ISD::SETUGT:
case ISD::SETULE:
case ISD::SETULT:
// ALL of these operations will work if we either sign or zero extend
// the operands (including the unsigned comparisons!). Zero extend is
// usually a simpler/cheaper operation, so prefer it.
Tmp1 = DAG.getZeroExtendInReg(Tmp1, VT);
Tmp2 = DAG.getZeroExtendInReg(Tmp2, VT);
break;
case ISD::SETGE:
case ISD::SETGT:
case ISD::SETLT:
case ISD::SETLE:
Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1,
DAG.getValueType(VT));
Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2,
DAG.getValueType(VT));
break;
}
}
break;
case Expand:
SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
ExpandOp(Node->getOperand(0), LHSLo, LHSHi);
ExpandOp(Node->getOperand(1), RHSLo, RHSHi);
switch (cast<CondCodeSDNode>(Node->getOperand(2))->get()) {
case ISD::SETEQ:
case ISD::SETNE:
if (RHSLo == RHSHi)
if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo))
if (RHSCST->isAllOnesValue()) {
// Comparison to -1.
Tmp1 = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi);
Tmp2 = RHSLo;
break;
}
Tmp1 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo);
Tmp2 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi);
Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp2);
Tmp2 = DAG.getConstant(0, Tmp1.getValueType());
break;
default:
// If this is a comparison of the sign bit, just look at the top part.
// X > -1, x < 0
if (ConstantSDNode *CST = dyn_cast<ConstantSDNode>(Node->getOperand(1)))
if ((cast<CondCodeSDNode>(Node->getOperand(2))->get() == ISD::SETLT &&
CST->getValue() == 0) || // X < 0
(cast<CondCodeSDNode>(Node->getOperand(2))->get() == ISD::SETGT &&
(CST->isAllOnesValue()))) { // X > -1
Tmp1 = LHSHi;
Tmp2 = RHSHi;
break;
}
// FIXME: This generated code sucks.
ISD::CondCode LowCC;
switch (cast<CondCodeSDNode>(Node->getOperand(2))->get()) {
default: assert(0 && "Unknown integer setcc!");
case ISD::SETLT:
case ISD::SETULT: LowCC = ISD::SETULT; break;
case ISD::SETGT:
case ISD::SETUGT: LowCC = ISD::SETUGT; break;
case ISD::SETLE:
case ISD::SETULE: LowCC = ISD::SETULE; break;
case ISD::SETGE:
case ISD::SETUGE: LowCC = ISD::SETUGE; break;
}
// Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison
// Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands
// dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2;
// NOTE: on targets without efficient SELECT of bools, we can always use
// this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3)
Tmp1 = DAG.getSetCC(Node->getValueType(0), LHSLo, RHSLo, LowCC);
Tmp2 = DAG.getNode(ISD::SETCC, Node->getValueType(0), LHSHi, RHSHi,
Node->getOperand(2));
Result = DAG.getSetCC(Node->getValueType(0), LHSHi, RHSHi, ISD::SETEQ);
Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(),
Result, Tmp1, Tmp2));
AddLegalizedOperand(SDOperand(Node, 0), Result);
return Result;
}
} }
switch (TLI.getOperationAction(ISD::SETCC, Tmp1.getValueType())) { switch (TLI.getOperationAction(ISD::SETCC, Tmp1.getValueType())) {
@ -2699,6 +2564,127 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
return Result; return Result;
} }
/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC
/// with condition CC on the current target. This usually involves legalizing
/// or promoting the arguments. In the case where LHS and RHS must be expanded,
/// there may be no choice but to create a new SetCC node to represent the
/// legalized value of setcc lhs, rhs. In this case, the value is returned in
/// LHS, and the SDOperand returned in RHS has a nil SDNode value.
void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS,
SDOperand &RHS,
SDOperand &CC) {
SDOperand Tmp1, Tmp2, Result;
switch (getTypeAction(LHS.getValueType())) {
case Legal:
Tmp1 = LegalizeOp(LHS); // LHS
Tmp2 = LegalizeOp(RHS); // RHS
break;
case Promote:
Tmp1 = PromoteOp(LHS); // LHS
Tmp2 = PromoteOp(RHS); // RHS
// If this is an FP compare, the operands have already been extended.
if (MVT::isInteger(LHS.getValueType())) {
MVT::ValueType VT = LHS.getValueType();
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
// Otherwise, we have to insert explicit sign or zero extends. Note
// that we could insert sign extends for ALL conditions, but zero extend
// is cheaper on many machines (an AND instead of two shifts), so prefer
// it.
switch (cast<CondCodeSDNode>(CC)->get()) {
default: assert(0 && "Unknown integer comparison!");
case ISD::SETEQ:
case ISD::SETNE:
case ISD::SETUGE:
case ISD::SETUGT:
case ISD::SETULE:
case ISD::SETULT:
// ALL of these operations will work if we either sign or zero extend
// the operands (including the unsigned comparisons!). Zero extend is
// usually a simpler/cheaper operation, so prefer it.
Tmp1 = DAG.getZeroExtendInReg(Tmp1, VT);
Tmp2 = DAG.getZeroExtendInReg(Tmp2, VT);
break;
case ISD::SETGE:
case ISD::SETGT:
case ISD::SETLT:
case ISD::SETLE:
Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1,
DAG.getValueType(VT));
Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2,
DAG.getValueType(VT));
break;
}
}
break;
case Expand:
SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
ExpandOp(LHS, LHSLo, LHSHi);
ExpandOp(RHS, RHSLo, RHSHi);
switch (cast<CondCodeSDNode>(CC)->get()) {
case ISD::SETEQ:
case ISD::SETNE:
if (RHSLo == RHSHi)
if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo))
if (RHSCST->isAllOnesValue()) {
// Comparison to -1.
Tmp1 = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi);
Tmp2 = RHSLo;
break;
}
Tmp1 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo);
Tmp2 = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi);
Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp2);
Tmp2 = DAG.getConstant(0, Tmp1.getValueType());
break;
default:
// If this is a comparison of the sign bit, just look at the top part.
// X > -1, x < 0
if (ConstantSDNode *CST = dyn_cast<ConstantSDNode>(RHS))
if ((cast<CondCodeSDNode>(CC)->get() == ISD::SETLT &&
CST->getValue() == 0) || // X < 0
(cast<CondCodeSDNode>(CC)->get() == ISD::SETGT &&
CST->isAllOnesValue())) { // X > -1
Tmp1 = LHSHi;
Tmp2 = RHSHi;
break;
}
// FIXME: This generated code sucks.
ISD::CondCode LowCC;
switch (cast<CondCodeSDNode>(CC)->get()) {
default: assert(0 && "Unknown integer setcc!");
case ISD::SETLT:
case ISD::SETULT: LowCC = ISD::SETULT; break;
case ISD::SETGT:
case ISD::SETUGT: LowCC = ISD::SETUGT; break;
case ISD::SETLE:
case ISD::SETULE: LowCC = ISD::SETULE; break;
case ISD::SETGE:
case ISD::SETUGE: LowCC = ISD::SETUGE; break;
}
// Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison
// Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands
// dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2;
// NOTE: on targets without efficient SELECT of bools, we can always use
// this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3)
Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSLo, RHSLo, LowCC);
Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), LHSHi, RHSHi, CC);
Result = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETEQ);
Result = LegalizeOp(DAG.getNode(ISD::SELECT, Tmp1.getValueType(),
Result, Tmp1, Tmp2));
Tmp1 = Result;
}
}
LHS = Tmp1;
RHS = Tmp2;
}
/// ExpandBIT_CONVERT - Expand a BIT_CONVERT node into a store/load combination. /// ExpandBIT_CONVERT - Expand a BIT_CONVERT node into a store/load combination.
/// The resultant code need not be legal. Note that SrcOp is the input operand /// The resultant code need not be legal. Note that SrcOp is the input operand
/// to the BIT_CONVERT, not the BIT_CONVERT node itself. /// to the BIT_CONVERT, not the BIT_CONVERT node itself.

View File

@ -56,6 +56,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM)
setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
setOperationAction(ISD::EXTLOAD, MVT::i1, Promote); setOperationAction(ISD::EXTLOAD, MVT::i1, Promote);
setOperationAction(ISD::EXTLOAD, MVT::f32, Expand); setOperationAction(ISD::EXTLOAD, MVT::f32, Expand);

View File

@ -35,10 +35,14 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
// register class for predicate registers // register class for predicate registers
addRegisterClass(MVT::i1, IA64::PRRegisterClass); addRegisterClass(MVT::i1, IA64::PRRegisterClass);
setOperationAction(ISD::BR_CC , MVT::Other, Expand);
setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand);
setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
// ia64 uses SELECT not SELECT_CC
setOperationAction(ISD::SELECT_CC , MVT::Other, Expand);
// We need to handle ISD::RET for void functions ourselves, // We need to handle ISD::RET for void functions ourselves,
// so we get a chance to restore ar.pfs before adding a // so we get a chance to restore ar.pfs before adding a
// br.ret insn // br.ret insn

View File

@ -13,6 +13,7 @@
#include "PPCISelLowering.h" #include "PPCISelLowering.h"
#include "PPCTargetMachine.h" #include "PPCTargetMachine.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
@ -20,7 +21,7 @@
#include "llvm/CodeGen/SSARegMap.h" #include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/ADT/VectorExtras.h" #include "llvm/Support/MathExtras.h"
using namespace llvm; using namespace llvm;
PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
@ -85,7 +86,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
// PowerPC wants to optimize setcc i32, imm a bit. // PowerPC wants to optimize integer setcc a bit
setOperationAction(ISD::SETCC, MVT::i32, Custom); setOperationAction(ISD::SETCC, MVT::i32, Custom);
// PowerPC does not have BRCOND* which requires SetCC // PowerPC does not have BRCOND* which requires SetCC
@ -452,15 +453,41 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
} }
case ISD::SETCC: { case ISD::SETCC: {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
if (C->getValue() && !C->isAllOnesValue()) // If we're comparing for equality to zero, expose the fact that this is
if (CC == ISD::SETEQ || CC == ISD::SETNE || // implented as a ctlz/srl pair on ppc, so that the dag combiner can
CC == ISD::SETLT || CC == ISD::SETGT) { // fold the new nodes.
MVT::ValueType VT = Op.getValueType(); if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
SDOperand SUB = DAG.getNode(ISD::SUB, Op.getOperand(0).getValueType(), if (C->isNullValue() && CC == ISD::SETEQ) {
Op.getOperand(0), Op.getOperand(1)); MVT::ValueType VT = Op.getOperand(0).getValueType();
return DAG.getSetCC(VT, SUB, DAG.getConstant(0, VT), CC); SDOperand Zext = Op.getOperand(0);
} if (VT < MVT::i32) {
VT = MVT::i32;
Zext = DAG.getNode(ISD::ZERO_EXTEND, VT, Op.getOperand(0));
}
unsigned Log2b = Log2_32(MVT::getSizeInBits(VT));
SDOperand Clz = DAG.getNode(ISD::CTLZ, VT, Zext);
SDOperand Scc = DAG.getNode(ISD::SRL, VT, Clz,
DAG.getConstant(Log2b, getShiftAmountTy()));
return DAG.getNode(ISD::TRUNCATE, getSetCCResultTy(), Scc);
}
// Leave comparisons against 0 and -1 alone for now, since they're usually
// optimized. FIXME: revisit this when we can custom lower all setcc
// optimizations.
if (C->isAllOnesValue() || C->isNullValue())
break;
}
// If we have an integer seteq/setne, turn it into a compare against zero
// by subtracting the rhs from the lhs, which is faster than setting a
// condition register, reading it back out, and masking the correct bit.
MVT::ValueType LHSVT = Op.getOperand(0).getValueType();
if (MVT::isInteger(LHSVT) && (CC == ISD::SETEQ || CC == ISD::SETNE)) {
MVT::ValueType VT = Op.getValueType();
SDOperand Sub = DAG.getNode(ISD::SUB, LHSVT, Op.getOperand(0),
Op.getOperand(1));
return DAG.getSetCC(VT, Sub, DAG.getConstant(0, LHSVT), CC);
}
break; break;
} }
case ISD::VASTART: { case ISD::VASTART: {

View File

@ -280,32 +280,6 @@ void bar() { struct foo R = { 1.0, 2.0 }; xxx(R); }
===-------------------------------------------------------------------------=== ===-------------------------------------------------------------------------===
For this:
int h(int i, int j, int k) {
return (i==0||j==0||k == 0);
}
We currently emit this:
_h:
cntlzw r2, r3
cntlzw r3, r4
cntlzw r4, r5
srwi r2, r2, 5
srwi r3, r3, 5
srwi r4, r4, 5
or r2, r3, r2
or r3, r2, r4
blr
The ctlz/shift instructions are created by the isel, so the dag combiner doesn't
have a chance to pull the shifts through the or's (eliminating two
instructions). SETCC nodes should be custom lowered in this case, not expanded
by the isel.
===-------------------------------------------------------------------------===
Darwin Stub LICM optimization: Darwin Stub LICM optimization:
Loops like this: Loops like this:
@ -461,19 +435,3 @@ This could be done in the dag combiner, by swapping a BR_CC when a SETCC of the
same operands (but backwards) exists. In this case, this wouldn't save us same operands (but backwards) exists. In this case, this wouldn't save us
anything though, because the compares still wouldn't be shared. anything though, because the compares still wouldn't be shared.
===-------------------------------------------------------------------------===
A simple case we generate suboptimal code on:
int test(int X) {
return X == 0 ? 32 : 0;
}
_test:
cntlzw r2, r3
srwi r2, r2, 5
slwi r3, r2, 5
blr
The shifts should be one 'andi'.

View File

@ -117,6 +117,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
} }
setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand); setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand);
setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand); setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, Expand);
setOperationAction(ISD::BR_CC , MVT::Other, Expand);
setOperationAction(ISD::SELECT_CC , MVT::Other, Expand);
setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); setOperationAction(ISD::MEMMOVE , MVT::Other, Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);