[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Jan 15 14:16:41 PST 2005
Changes in directory llvm/lib/CodeGen/SelectionDAG:
LegalizeDAG.cpp updated: 1.30 -> 1.31
---
Log message:
Implement promotion of a whole bunch more operators. I think that this is
basically everything.
---
Diffs of the changes: (+174 -12)
Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.30 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.31
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.30 Sat Jan 15 01:15:18 2005
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Sat Jan 15 16:16:26 2005
@@ -461,7 +461,9 @@
break;
}
case Promote:
- assert(0 && "Can't promote return value!");
+ Tmp2 = PromoteOp(Node->getOperand(1));
+ Result = DAG.getNode(ISD::RET, MVT::Other, Tmp1, Tmp2);
+ break;
}
break;
case 1: // ret void
@@ -484,7 +486,7 @@
break;
}
case Promote:
- assert(0 && "Can't promote return value!");
+ assert(0 && "Can't promote multiple return value yet!");
}
Result = DAG.getNode(ISD::RET, MVT::Other, NewValues);
break;
@@ -589,7 +591,44 @@
Tmp1, Tmp2);
break;
case Promote:
- assert(0 && "Can't promote setcc operands yet!");
+ 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 = TransformToType[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<SetCCSDNode>(Node)->getCondition()) {
+ 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.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT);
+ Tmp2 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp2, VT);
+ break;
+ case ISD::SETGE:
+ case ISD::SETGT:
+ case ISD::SETLT:
+ case ISD::SETLE:
+ Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT);
+ Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2, VT);
+ break;
+ }
+
+ }
+ Result = DAG.getSetCC(cast<SetCCSDNode>(Node)->getCondition(),
+ Tmp1, Tmp2);
break;
case Expand:
SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
@@ -825,6 +864,10 @@
return Result;
}
+/// PromoteOp - Given an operation that produces a value in an invalid type,
+/// promote it to compute the value into a larger type. The produced value will
+/// have the correct bits for the low portion of the register, but no guarantee
+/// is made about the top bits: it may be zero, sign-extended, or garbage.
SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
MVT::ValueType VT = Op.getValueType();
MVT::ValueType NVT = TransformToType[VT];
@@ -851,6 +894,9 @@
std::cerr << "NODE: "; Node->dump(); std::cerr << "\n";
assert(0 && "Do not know how to promote this operator!");
abort();
+ case ISD::CALL:
+ assert(0 && "Target's LowerCallTo implementation is buggy, returning value"
+ " types that are not supported by the target!");
case ISD::Constant:
Result = DAG.getNode(ISD::ZERO_EXTEND, NVT, Op);
assert(isa<ConstantSDNode>(Result) && "Didn't constant fold zext?");
@@ -875,18 +921,86 @@
assert(0 && "Cannot handle promote-promote yet");
}
break;
+ case ISD::SIGN_EXTEND:
+ case ISD::ZERO_EXTEND:
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Expand: assert(0 && "BUG: Smaller reg should have been promoted!");
+ case Legal:
+ // Input is legal? Just do extend all the way to the larger type.
+ Result = LegalizeOp(Node->getOperand(0));
+ Result = DAG.getNode(Node->getOpcode(), NVT, Result);
+ break;
+ case Promote:
+ // Promote the reg if it's smaller.
+ Result = PromoteOp(Node->getOperand(0));
+ // The high bits are not guaranteed to be anything. Insert an extend.
+ if (Node->getOpcode() == ISD::SIGN_EXTEND)
+ Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Result, VT);
+ else
+ Result = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Result, VT);
+ break;
+ }
+ break;
+
+ case ISD::FP_EXTEND:
+ assert(0 && "Case not implemented. Dynamically dead with 2 FP types!");
+ case ISD::FP_ROUND:
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Expand: assert(0 && "BUG: Cannot expand FP regs!");
+ case Promote: assert(0 && "Unreachable with 2 FP types!");
+ case Legal:
+ // Input is legal? Do an FP_ROUND_INREG.
+ Result = LegalizeOp(Node->getOperand(0));
+ Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT);
+ break;
+ }
+ break;
+
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP:
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Legal:
+ Result = LegalizeOp(Node->getOperand(0));
+ break;
+
+ case Promote:
+ Result = PromoteOp(Node->getOperand(0));
+ if (Node->getOpcode() == ISD::SINT_TO_FP)
+ Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(),
+ Result, Node->getOperand(0).getValueType());
+ else
+ Result = DAG.getNode(ISD::ZERO_EXTEND_INREG, Result.getValueType(),
+ Result, Node->getOperand(0).getValueType());
+ break;
+ case Expand:
+ assert(0 && "Unimplemented");
+ }
+ // No extra round required here.
+ Result = DAG.getNode(Node->getOpcode(), NVT, Result);
+ break;
+
+ case ISD::FP_TO_SINT:
+ case ISD::FP_TO_UINT:
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Legal:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ break;
+ case Promote:
+ // The input result is prerounded, so we don't have to do anything
+ // special.
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ break;
+ case Expand:
+ assert(0 && "not implemented");
+ }
+ Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1);
+ break;
+
case ISD::AND:
case ISD::OR:
case ISD::XOR:
- // The logical ops can just execute, they don't care what the top bits
- // coming in are.
- Tmp1 = PromoteOp(Node->getOperand(0));
- Tmp2 = PromoteOp(Node->getOperand(1));
- assert(Tmp1.getValueType() == NVT && Tmp2.getValueType() == NVT);
- Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2);
- break;
-
case ISD::ADD:
+ case ISD::SUB:
case ISD::MUL:
// The input may have strange things in the top bits of the registers, but
// these operations don't care. They may have wierd bits going out, but
@@ -899,10 +1013,58 @@
// However, if this is a floating point operation, they will give excess
// precision that we may not be able to tolerate. If we DO allow excess
// precision, just leave it, otherwise excise it.
+ // FIXME: Why would we need to round FP ops more than integer ones?
+ // Is Round(Add(Add(A,B),C)) != Round(Add(Round(Add(A,B)), C))
if (MVT::isFloatingPoint(NVT) && NoExcessFPPrecision)
Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT);
break;
+ case ISD::SDIV:
+ case ISD::SREM:
+ // These operators require that their input be sign extended.
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Tmp2 = PromoteOp(Node->getOperand(1));
+ if (MVT::isInteger(NVT)) {
+ Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT);
+ Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT);
+ }
+ Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2);
+
+ // Perform FP_ROUND: this is probably overly pessimistic.
+ if (MVT::isFloatingPoint(NVT) && NoExcessFPPrecision)
+ Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT);
+ break;
+
+ case ISD::UDIV:
+ case ISD::UREM:
+ // These operators require that their input be zero extended.
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Tmp2 = PromoteOp(Node->getOperand(1));
+ assert(MVT::isInteger(NVT) && "Operators don't apply to FP!");
+ Tmp1 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT);
+ Tmp2 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT);
+ Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2);
+ break;
+
+ case ISD::SHL:
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ Result = DAG.getNode(ISD::SHL, NVT, Tmp1, Tmp2);
+ break;
+ case ISD::SRA:
+ // The input value must be properly sign extended.
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp1, VT);
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ Result = DAG.getNode(ISD::SRA, NVT, Tmp1, Tmp2);
+ break;
+ case ISD::SRL:
+ // The input value must be properly zero extended.
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Tmp1 = DAG.getNode(ISD::ZERO_EXTEND_INREG, NVT, Tmp1, VT);
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ Result = DAG.getNode(ISD::SRL, NVT, Tmp1, Tmp2);
+ break;
case ISD::LOAD:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer.
@@ -912,7 +1074,7 @@
AddLegalizedOperand(Op.getValue(1), Result.getValue(1));
break;
case ISD::SELECT:
- Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the condition
+ Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the condition
Tmp2 = PromoteOp(Node->getOperand(1)); // Legalize the op0
Tmp3 = PromoteOp(Node->getOperand(2)); // Legalize the op1
Result = DAG.getNode(ISD::SELECT, NVT, Tmp1, Tmp2, Tmp3);
More information about the llvm-commits
mailing list