Allow targets to legalize operations (with illegal operands) that produces multiple values. For example, a load with an illegal operand (a load produces two values, a value and chain).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62663 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 3cfaa27..aae84de 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -722,7 +722,7 @@
Lo = Hi = SDValue();
// See if the target wants to custom expand this node.
- if (CustomLowerResults(N, ResNo))
+ if (CustomLowerResults(N, ResNo, true))
return;
switch (N->getOpcode()) {
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index d84cd62..89ae2fd 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -34,7 +34,7 @@
SDValue Result = SDValue();
// See if the target wants to custom expand this node.
- if (CustomLowerResults(N, ResNo))
+ if (CustomLowerResults(N, ResNo, true))
return;
switch (N->getOpcode()) {
@@ -623,45 +623,42 @@
DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n");
SDValue Res = SDValue();
- if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
- == TargetLowering::Custom)
- Res = TLI.LowerOperation(SDValue(N, 0), DAG);
+ if (CustomLowerResults(N, OpNo, false))
+ return false;
- if (Res.getNode() == 0) {
- switch (N->getOpcode()) {
- default:
+ switch (N->getOpcode()) {
+ default:
#ifndef NDEBUG
- cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
+ cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
#endif
- assert(0 && "Do not know how to promote this operator's operand!");
- abort();
+ assert(0 && "Do not know how to promote this operator's operand!");
+ abort();
- case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break;
- case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break;
- case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break;
- case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break;
- case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
- case ISD::CONVERT_RNDSAT:
- Res = PromoteIntOp_CONVERT_RNDSAT(N); break;
- case ISD::INSERT_VECTOR_ELT:
- Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);break;
- case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break;
- case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break;
- case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break;
- case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break;
- case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
- case ISD::SINT_TO_FP: Res = PromoteIntOp_SINT_TO_FP(N); break;
- case ISD::STORE: Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
- OpNo); break;
- case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break;
- case ISD::UINT_TO_FP: Res = PromoteIntOp_UINT_TO_FP(N); break;
- case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
- }
+ case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break;
+ case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break;
+ case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break;
+ case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break;
+ case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
+ case ISD::CONVERT_RNDSAT:
+ Res = PromoteIntOp_CONVERT_RNDSAT(N); break;
+ case ISD::INSERT_VECTOR_ELT:
+ Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);break;
+ case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break;
+ case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break;
+ case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break;
+ case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break;
+ case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
+ case ISD::SINT_TO_FP: Res = PromoteIntOp_SINT_TO_FP(N); break;
+ case ISD::STORE: Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
+ OpNo); break;
+ case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break;
+ case ISD::UINT_TO_FP: Res = PromoteIntOp_UINT_TO_FP(N); break;
+ case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
}
-
+
// If the result is null, the sub-method took care of registering results etc.
- if (!Res.getNode()) return false;
+ if (! Res.getNode()) return false;
// If the result is N, the sub-method updated N in place. Tell the legalizer
// core about this.
@@ -921,7 +918,7 @@
Lo = Hi = SDValue();
// See if the target wants to custom expand this node.
- if (CustomLowerResults(N, ResNo))
+ if (CustomLowerResults(N, ResNo, true))
return;
switch (N->getOpcode()) {
@@ -1851,35 +1848,32 @@
DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n");
SDValue Res = SDValue();
- if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
- == TargetLowering::Custom)
- Res = TLI.LowerOperation(SDValue(N, 0), DAG);
+ if (CustomLowerResults(N, OpNo, false))
+ return false;
- if (Res.getNode() == 0) {
- switch (N->getOpcode()) {
- default:
+ switch (N->getOpcode()) {
+ default:
#ifndef NDEBUG
- cerr << "ExpandIntegerOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
+ cerr << "ExpandIntegerOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
#endif
- assert(0 && "Do not know how to expand this operator's operand!");
- abort();
+ assert(0 && "Do not know how to expand this operator's operand!");
+ abort();
- case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
- case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break;
- case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
- case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break;
- case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break;
+ case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
+ case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break;
+ case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
+ case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break;
+ case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break;
- case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
- case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
- case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
- case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break;
- case ISD::STORE: Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo);
- break;
- case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break;
- case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break;
- }
+ case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
+ case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
+ case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
+ case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break;
+ case ISD::STORE: Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo);
+ break;
+ case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break;
+ case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break;
}
// If the result is null, the sub-method took care of registering results etc.
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
index 330ea86..ff7b8a9 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
@@ -848,14 +848,28 @@
/// CustomLowerResults - Replace the node's results with custom code provided
/// by the target and return "true", or do nothing and return "false".
-bool DAGTypeLegalizer::CustomLowerResults(SDNode *N, unsigned ResNo) {
+/// The last parameter is FALSE if we are dealing with a node with legal
+/// result types and illegal operand. The second parameter denotes the illegal
+/// OperandNo in that case.
+/// The last parameter being TRUE means we are dealing with a
+/// node with illegal result types. The second parameter denotes the illegal
+/// ResNo in that case.
+bool DAGTypeLegalizer::CustomLowerResults(SDNode *N, unsigned Num,
+ bool LegalizeResult) {
+ // Get the type of illegal Result or Operand.
+ MVT ValueTy = (LegalizeResult) ? N->getValueType(Num)
+ : N->getOperand(Num).getValueType();
+
// See if the target wants to custom lower this node.
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) !=
- TargetLowering::Custom)
+ if (TLI.getOperationAction(N->getOpcode(), ValueTy) != TargetLowering::Custom)
return false;
SmallVector<SDValue, 8> Results;
- TLI.ReplaceNodeResults(N, Results, DAG);
+ if (LegalizeResult)
+ TLI.ReplaceNodeResults(N, Results, DAG);
+ else
+ TLI.LowerOperationWrapper(SDValue(N, 0), Results, DAG);
+
if (Results.empty())
// The target didn't want to custom lower it after all.
return false;
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 949ee34..d57aec0 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -191,7 +191,7 @@
// Common routines.
SDValue BitConvertToInteger(SDValue Op);
SDValue CreateStackStoreLoad(SDValue Op, MVT DestVT);
- bool CustomLowerResults(SDNode *N, unsigned ResNo);
+ bool CustomLowerResults(SDNode *N, unsigned ResNo, bool LegalizeResult);
SDValue GetVectorElementPointer(SDValue VecPtr, MVT EltVT, SDValue Index);
SDValue JoinIntegers(SDValue Lo, SDValue Hi);
SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index b134b23..d0023a0 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -5568,6 +5568,15 @@
return std::make_pair(Res, Chain);
}
+void TargetLowering::LowerOperationWrapper(SDValue Op,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) {
+ SDValue Res;
+ Res = LowerOperation(Op, DAG);
+ if (Res.getNode())
+ Results.push_back(Res);
+}
+
SDValue TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
assert(0 && "LowerOperation not implemented for this target!");
abort();