aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-01-16 07:29:19 +0000
committerChris Lattner <sabre@nondot.org>2005-01-16 07:29:19 +0000
commit55ba8fba750ee0a51a9d74fa33b7242d24a4ff35 (patch)
treee671262765912d23ffc3306f6d94e72ba62d1e1a
parent171453a284b097f1ee89fb87ff495c3a6c7b6297 (diff)
Revamp supported ops. Instead of just being supported or not, we now keep
track of how to deal with it, and provide the target with a hook that they can use to legalize arbitrary operations in arbitrary ways. Implement custom lowering for a couple of ops, implement promotion for select operations (which x86 needs). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19613 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp65
1 files changed, 54 insertions, 11 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 754d5a881c..7582e3f95c 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -528,10 +528,35 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Cond
Tmp2 = LegalizeOp(Node->getOperand(1)); // TrueVal
Tmp3 = LegalizeOp(Node->getOperand(2)); // FalseVal
-
- if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) ||
- Tmp3 != Node->getOperand(2))
- Result = DAG.getNode(ISD::SELECT, Node->getValueType(0), Tmp1, Tmp2,Tmp3);
+
+ switch (TLI.getOperationAction(Node->getOpcode(), Tmp2.getValueType())) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Legal:
+ if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) ||
+ Tmp3 != Node->getOperand(2))
+ Result = DAG.getNode(ISD::SELECT, Node->getValueType(0),
+ Tmp1, Tmp2, Tmp3);
+ break;
+ case TargetLowering::Promote: {
+ MVT::ValueType NVT =
+ TLI.getTypeToPromoteTo(ISD::SELECT, Tmp2.getValueType());
+ unsigned ExtOp, TruncOp;
+ if (MVT::isInteger(Tmp2.getValueType())) {
+ ExtOp = ISD::ZERO_EXTEND;
+ TruncOp = ISD::TRUNCATE;
+ } else {
+ ExtOp = ISD::FP_EXTEND;
+ TruncOp = ISD::FP_ROUND;
+ }
+ // Promote each of the values to the new type.
+ Tmp2 = DAG.getNode(ExtOp, NVT, Tmp2);
+ Tmp3 = DAG.getNode(ExtOp, NVT, Tmp3);
+ // Perform the larger operation, then round down.
+ Result = DAG.getNode(ISD::SELECT, NVT, Tmp1, Tmp2,Tmp3);
+ Result = DAG.getNode(TruncOp, Node->getValueType(0), Result);
+ break;
+ }
+ }
break;
case ISD::SETCC:
switch (getTypeAction(Node->getOperand(0).getValueType())) {
@@ -634,7 +659,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Tmp3 = LegalizeOp(Node->getOperand(2));
SDOperand Tmp4 = LegalizeOp(Node->getOperand(3));
SDOperand Tmp5 = LegalizeOp(Node->getOperand(4));
- if (TLI.isOperationSupported(Node->getOpcode(), MVT::Other)) {
+
+ switch (TLI.getOperationAction(Node->getOpcode(), MVT::Other)) {
+ default: assert(0 && "This action not implemented for this operation!");
+ case TargetLowering::Legal:
if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) ||
Tmp3 != Node->getOperand(2) || Tmp4 != Node->getOperand(3) ||
Tmp5 != Node->getOperand(4)) {
@@ -643,7 +671,8 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Ops.push_back(Tmp4); Ops.push_back(Tmp5);
Result = DAG.getNode(Node->getOpcode(), MVT::Other, Ops);
}
- } else {
+ break;
+ case TargetLowering::Expand: {
// Otherwise, the target does not support this operation. Lower the
// operation to an explicit libcall as appropriate.
MVT::ValueType IntPtr = TLI.getPointerTy();
@@ -672,6 +701,16 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
TLI.LowerCallTo(Tmp1, Type::VoidTy,
DAG.getExternalSymbol(FnName, IntPtr), Args, DAG);
Result = LegalizeOp(CallResult.second);
+ break;
+ }
+ case TargetLowering::Custom:
+ std::vector<SDOperand> Ops;
+ Ops.push_back(Tmp1); Ops.push_back(Tmp2); Ops.push_back(Tmp3);
+ Ops.push_back(Tmp4); Ops.push_back(Tmp5);
+ Result = DAG.getNode(Node->getOpcode(), MVT::Other, Ops);
+ Result = TLI.LowerOperation(Result);
+ Result = LegalizeOp(Result);
+ break;
}
break;
}
@@ -776,7 +815,14 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
// If this operation is not supported, convert it to a shl/shr or load/store
// pair.
- if (!TLI.isOperationSupported(Node->getOpcode(), ExtraVT)) {
+ switch (TLI.getOperationAction(Node->getOpcode(), ExtraVT)) {
+ default: assert(0 && "This action not supported for this op yet!");
+ case TargetLowering::Legal:
+ if (Tmp1 != Node->getOperand(0))
+ Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1,
+ ExtraVT);
+ break;
+ case TargetLowering::Expand:
// If this is an integer extend and shifts are supported, do that.
if (Node->getOpcode() == ISD::ZERO_EXTEND_INREG) {
// NOTE: we could fall back on load/store here too for targets without
@@ -819,10 +865,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
assert(0 && "Unknown op");
}
Result = LegalizeOp(Result);
- } else {
- if (Tmp1 != Node->getOperand(0))
- Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1,
- ExtraVT);
+ break;
}
break;
}