summaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
diff options
context:
space:
mode:
authorMichael Liao <michael.liao@intel.com>2012-09-13 19:58:21 +0000
committerMichael Liao <michael.liao@intel.com>2012-09-13 19:58:21 +0000
commit092122f124b6589a3a432473c1047bf5834df3c1 (patch)
tree4c61108a3f08456937b2aa4215d3732b85c10e36 /lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
parentda0e8219b72e79a41f18c4dc4ea7e11ec2211d2e (diff)
downloadllvm-092122f124b6589a3a432473c1047bf5834df3c1.tar.gz
llvm-092122f124b6589a3a432473c1047bf5834df3c1.tar.bz2
llvm-092122f124b6589a3a432473c1047bf5834df3c1.tar.xz
Enhance type legalization on bitcast from vector to integer
- Find a legal vector type before casting and extracting element from it. - As the new vector type may have more than 2 elements, build the final hi/lo pair by BFS pairing them from bottom to top. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163830 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp39
1 files changed, 34 insertions, 5 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
index 06f6bd63b6..08668e1b40 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
@@ -94,14 +94,43 @@ void DAGTypeLegalizer::ExpandRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi) {
if (InVT.isVector() && OutVT.isInteger()) {
// Handle cases like i64 = BITCAST v1i64 on x86, where the operand
// is legal but the result is not.
- EVT NVT = EVT::getVectorVT(*DAG.getContext(), NOutVT, 2);
+ unsigned NumElems = 2;
+ EVT NVT = EVT::getVectorVT(*DAG.getContext(), NOutVT, NumElems);
+
+ // If <NOutVT * N> is not a legal type, try <NOutVT/2 * (N*2)>.
+ while (!isTypeLegal(NVT)) {
+ unsigned NewSizeInBits = NOutVT.getSizeInBits() / 2;
+ // If the element size is smaller than byte, bail.
+ if (NewSizeInBits < 8)
+ break;
+ NumElems *= 2;
+ NOutVT = EVT::getIntegerVT(*DAG.getContext(), NewSizeInBits);
+ NVT = EVT::getVectorVT(*DAG.getContext(), NOutVT, NumElems);
+ }
if (isTypeLegal(NVT)) {
SDValue CastInOp = DAG.getNode(ISD::BITCAST, dl, NVT, InOp);
- Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp,
- DAG.getIntPtrConstant(0));
- Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp,
- DAG.getIntPtrConstant(1));
+
+ SmallVector<SDValue, 8> Vals;
+ for (unsigned i = 0; i < NumElems; ++i)
+ Vals.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT,
+ CastInOp, DAG.getIntPtrConstant(i)));
+
+ // Build Lo, Hi pair by pairing extracted elements if needed.
+ unsigned Slot = 0;
+ for (unsigned e = Vals.size(); e - Slot > 2; Slot += 2, e += 1) {
+ // Each iteration will BUILD_PAIR two nodes and append the result until
+ // there are only two nodes left, i.e. Lo and Hi.
+ SDValue LHS = Vals[Slot];
+ SDValue RHS = Vals[Slot + 1];
+ Vals.push_back(DAG.getNode(ISD::BUILD_PAIR, dl,
+ EVT::getIntegerVT(
+ *DAG.getContext(),
+ LHS.getValueType().getSizeInBits() << 1),
+ LHS, RHS));
+ }
+ Lo = Vals[Slot++];
+ Hi = Vals[Slot++];
if (TLI.isBigEndian())
std::swap(Lo, Hi);