mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 06:33:24 +00:00
Fix some of the stuff in the PPC README file, and clean up legalization
of the SELECT_CC, BR_CC, and BRTWOWAY_CC nodes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25875 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1f7c6302be
commit
750ac1bdfa
@ -1081,6 +1081,16 @@ SDOperand DAGCombiner::visitOR(SDNode *N) {
|
||||
WorkList.push_back(ORNode.Val);
|
||||
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
|
||||
if (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SHL)
|
||||
std::swap(N0, N1);
|
||||
@ -1196,6 +1206,16 @@ SDOperand DAGCombiner::visitXOR(SDNode *N) {
|
||||
WorkList.push_back(XORNode.Val);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1396,14 +1416,20 @@ SDOperand DAGCombiner::visitSELECT(SDNode *N) {
|
||||
// fold X ? Y : X --> X ? Y : 0 --> X & Y
|
||||
if (MVT::i1 == VT && N0 == N2)
|
||||
return DAG.getNode(ISD::AND, VT, N0, N1);
|
||||
|
||||
// If we can fold this based on the true/false value, do so.
|
||||
if (SimplifySelectOps(N, N1, N2))
|
||||
return SDOperand();
|
||||
|
||||
// fold selects based on a setcc into other things, such as min/max/abs
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1927,6 +1953,13 @@ SDOperand DAGCombiner::visitBRCOND(SDNode *N) {
|
||||
// unconditional branch
|
||||
if (N1C && N1C->getValue() == 1)
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1943,6 +1976,19 @@ SDOperand DAGCombiner::visitBRCONDTWOWAY(SDNode *N) {
|
||||
// unconditional branch to false mbb
|
||||
if (N1C && N1C->isNullValue())
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,8 @@ private:
|
||||
void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);
|
||||
SDOperand PromoteOp(SDOperand O);
|
||||
|
||||
void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
|
||||
|
||||
SDOperand ExpandLibCall(const char *Name, SDNode *Node,
|
||||
SDOperand &Hi);
|
||||
SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
|
||||
@ -717,33 +719,22 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
break;
|
||||
case ISD::BR_CC:
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
||||
if (!isTypeLegal(Node->getOperand(2).getValueType())) {
|
||||
Tmp2 = LegalizeOp(DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(),
|
||||
Node->getOperand(2), // LHS
|
||||
Node->getOperand(3), // RHS
|
||||
Node->getOperand(1)));
|
||||
// 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 (Tmp2.getOpcode() == ISD::SETCC) {
|
||||
Result = DAG.getNode(ISD::BR_CC, MVT::Other, Tmp1, Tmp2.getOperand(2),
|
||||
Tmp2.getOperand(0), Tmp2.getOperand(1),
|
||||
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 = Node->getOperand(2); // LHS
|
||||
Tmp3 = Node->getOperand(3); // RHS
|
||||
Tmp4 = Node->getOperand(1); // CC
|
||||
|
||||
LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
|
||||
|
||||
// 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
|
||||
// the result against zero to select between true and false values.
|
||||
if (Tmp3.Val == 0) {
|
||||
Tmp3 = DAG.getConstant(0, Tmp2.getValueType());
|
||||
Tmp4 = DAG.getCondCode(ISD::SETNE);
|
||||
}
|
||||
|
||||
Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS
|
||||
Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS
|
||||
|
||||
Result = DAG.UpdateNodeOperands(Result, Tmp1, Node->getOperand(1), Tmp2,
|
||||
Tmp3, Node->getOperand(4));
|
||||
|
||||
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp4, Tmp2, Tmp3,
|
||||
Node->getOperand(4));
|
||||
|
||||
switch (TLI.getOperationAction(ISD::BR_CC, Tmp3.getValueType())) {
|
||||
default: assert(0 && "Unexpected action for BR_CC!");
|
||||
@ -805,61 +796,44 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ISD::BRTWOWAY_CC:
|
||||
case ISD::BRTWOWAY_CC: {
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
||||
if (isTypeLegal(Node->getOperand(2).getValueType())) {
|
||||
Tmp2 = LegalizeOp(Node->getOperand(2)); // LHS
|
||||
Tmp3 = LegalizeOp(Node->getOperand(3)); // RHS
|
||||
if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2) ||
|
||||
Tmp3 != Node->getOperand(3)) {
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Tmp1);
|
||||
Ops.push_back(Node->getOperand(1));
|
||||
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);
|
||||
}
|
||||
Tmp2 = Node->getOperand(2); // LHS
|
||||
Tmp3 = Node->getOperand(3); // RHS
|
||||
Tmp4 = Node->getOperand(1); // CC
|
||||
|
||||
LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
|
||||
|
||||
// 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
|
||||
// the result against zero to select between true and false values.
|
||||
if (Tmp3.Val == 0) {
|
||||
Tmp3 = DAG.getConstant(0, Tmp2.getValueType());
|
||||
Tmp4 = DAG.getCondCode(ISD::SETNE);
|
||||
}
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
case ISD::LOAD: {
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
||||
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.
|
||||
@ -1315,156 +1289,47 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
}
|
||||
}
|
||||
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
|
||||
Tmp4 = LegalizeOp(Node->getOperand(3)); // False
|
||||
SDOperand CC = Node->getOperand(4);
|
||||
|
||||
if (isTypeLegal(Node->getOperand(0).getValueType())) {
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
|
||||
Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS
|
||||
|
||||
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4,
|
||||
Node->getOperand(4));
|
||||
|
||||
// Everything is legal, see if we should expand this op or something.
|
||||
switch (TLI.getOperationAction(ISD::SELECT_CC,
|
||||
Node->getOperand(0).getValueType())) {
|
||||
default: assert(0 && "This action is not supported yet!");
|
||||
case TargetLowering::Legal: break;
|
||||
case TargetLowering::Custom:
|
||||
Tmp1 = TLI.LowerOperation(Result, DAG);
|
||||
if (Tmp1.Val) Result = Tmp1;
|
||||
break;
|
||||
}
|
||||
LegalizeSetCCOperands(Tmp1, Tmp2, CC);
|
||||
|
||||
// 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
|
||||
// the result against zero to select between true and false values.
|
||||
if (Tmp2.Val == 0) {
|
||||
Tmp2 = DAG.getConstant(0, Tmp1.getValueType());
|
||||
CC = DAG.getCondCode(ISD::SETNE);
|
||||
}
|
||||
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, CC);
|
||||
|
||||
// Everything is legal, see if we should expand this op or something.
|
||||
switch (TLI.getOperationAction(ISD::SELECT_CC, Tmp3.getValueType())) {
|
||||
default: assert(0 && "This action is not supported yet!");
|
||||
case TargetLowering::Legal: break;
|
||||
case TargetLowering::Custom:
|
||||
Tmp1 = TLI.LowerOperation(Result, DAG);
|
||||
if (Tmp1.Val) Result = Tmp1;
|
||||
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;
|
||||
}
|
||||
case ISD::SETCC:
|
||||
switch (getTypeAction(Node->getOperand(0).getValueType())) {
|
||||
case Legal:
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
|
||||
Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS
|
||||
Tmp1 = Node->getOperand(0);
|
||||
Tmp2 = Node->getOperand(1);
|
||||
Tmp3 = Node->getOperand(2);
|
||||
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;
|
||||
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())) {
|
||||
@ -2699,6 +2564,127 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
|
||||
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.
|
||||
/// The resultant code need not be legal. Note that SrcOp is the input operand
|
||||
/// to the BIT_CONVERT, not the BIT_CONVERT node itself.
|
||||
|
@ -56,6 +56,8 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM)
|
||||
|
||||
setOperationAction(ISD::BRCONDTWOWAY, 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::f32, Expand);
|
||||
|
@ -35,10 +35,14 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
|
||||
// register class for predicate registers
|
||||
addRegisterClass(MVT::i1, IA64::PRRegisterClass);
|
||||
|
||||
setOperationAction(ISD::BR_CC , MVT::Other, Expand);
|
||||
setOperationAction(ISD::BRCONDTWOWAY , MVT::Other, Expand);
|
||||
setOperationAction(ISD::BRTWOWAY_CC , MVT::Other, 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,
|
||||
// so we get a chance to restore ar.pfs before adding a
|
||||
// br.ret insn
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "PPCISelLowering.h"
|
||||
#include "PPCTargetMachine.h"
|
||||
#include "llvm/ADT/VectorExtras.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
@ -20,7 +21,7 @@
|
||||
#include "llvm/CodeGen/SSARegMap.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/ADT/VectorExtras.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
using namespace llvm;
|
||||
|
||||
PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
|
||||
@ -85,7 +86,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f32, 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);
|
||||
|
||||
// PowerPC does not have BRCOND* which requires SetCC
|
||||
@ -452,15 +453,41 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
}
|
||||
case ISD::SETCC: {
|
||||
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
|
||||
if (C->getValue() && !C->isAllOnesValue())
|
||||
if (CC == ISD::SETEQ || CC == ISD::SETNE ||
|
||||
CC == ISD::SETLT || CC == ISD::SETGT) {
|
||||
MVT::ValueType VT = Op.getValueType();
|
||||
SDOperand SUB = DAG.getNode(ISD::SUB, Op.getOperand(0).getValueType(),
|
||||
Op.getOperand(0), Op.getOperand(1));
|
||||
return DAG.getSetCC(VT, SUB, DAG.getConstant(0, VT), CC);
|
||||
}
|
||||
|
||||
// If we're comparing for equality to zero, expose the fact that this is
|
||||
// implented as a ctlz/srl pair on ppc, so that the dag combiner can
|
||||
// fold the new nodes.
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
||||
if (C->isNullValue() && CC == ISD::SETEQ) {
|
||||
MVT::ValueType VT = Op.getOperand(0).getValueType();
|
||||
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;
|
||||
}
|
||||
case ISD::VASTART: {
|
||||
|
@ -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:
|
||||
|
||||
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
|
||||
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'.
|
||||
|
||||
|
@ -117,6 +117,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||
}
|
||||
setOperationAction(ISD::BRCONDTWOWAY , 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::SIGN_EXTEND_INREG, MVT::i16 , Expand);
|
||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
|
||||
|
Loading…
x
Reference in New Issue
Block a user