aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h5
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp11
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp50
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp22
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp2
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp5
-rw-r--r--test/CodeGen/PowerPC/vec_splat.ll2
8 files changed, 40 insertions, 65 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 3ae26fdd24..56706689fd 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -328,7 +328,10 @@ namespace ISD {
/// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a
/// scalar value into element 0 of the resultant vector type. The top
- /// elements 1 to N-1 of the N-element vector are undefined.
+ /// elements 1 to N-1 of the N-element vector are undefined. The type
+ /// of the operand must match the vector element type, except when they
+ /// are integer types. In this case the operand is allowed to be wider
+ /// than the vector element type, and is implicitly truncated to it.
SCALAR_TO_VECTOR,
// MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index dd4fda1e84..d1ef0815c8 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -5110,8 +5110,15 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) {
// (vextract (scalar_to_vector val, 0) -> val
SDValue InVec = N->getOperand(0);
- if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR)
- return InVec.getOperand(0);
+ if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR) {
+ // If the operand is wider than the vector element type then it is implicitly
+ // truncated. Make that explicit here.
+ MVT EltVT = InVec.getValueType().getVectorElementType();
+ SDValue InOp = InVec.getOperand(0);
+ if (InOp.getValueType() != EltVT)
+ return DAG.getNode(ISD::TRUNCATE, InVec.getDebugLoc(), EltVT, InOp);
+ return InOp;
+ }
// Perform only after legalization to ensure build_vector / vector_shuffle
// optimizations have already been done.
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 5932aebf5c..5ea1ce3430 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1643,9 +1643,11 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
// then a shuffle that inserts it into the right position in the vector.
if (ConstantSDNode *InsertPos = dyn_cast<ConstantSDNode>(Tmp3)) {
// SCALAR_TO_VECTOR requires that the type of the value being inserted
- // match the element type of the vector being created.
- if (Tmp2.getValueType() ==
- Op.getValueType().getVectorElementType()) {
+ // match the element type of the vector being created, except for
+ // integers in which case the inserted value can be over width.
+ MVT EltVT = Op.getValueType().getVectorElementType();
+ if (Tmp2.getValueType() == EltVT ||
+ (EltVT.isInteger() && Tmp2.getValueType().bitsGE(EltVT))) {
SDValue ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl,
Tmp1.getValueType(), Tmp2);
@@ -5463,9 +5465,10 @@ SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) {
FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(StackPtr);
int SPFI = StackPtrFI->getIndex();
- SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Node->getOperand(0),
- StackPtr,
- PseudoSourceValue::getFixedStack(SPFI), 0);
+ SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0),
+ StackPtr,
+ PseudoSourceValue::getFixedStack(SPFI), 0,
+ Node->getValueType(0).getVectorElementType());
return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr,
PseudoSourceValue::getFixedStack(SPFI), 0);
}
@@ -5481,41 +5484,6 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
MVT OpVT = SplatValue.getValueType();
MVT EltVT = VT.getVectorElementType();
- // Check if the BUILD_VECTOR operands were promoted to legalize their types.
- if (OpVT != EltVT) {
- // Now that the DAG combiner and target-specific lowering have had a
- // chance to optimize/recognize the BUILD_VECTOR with promoted operands,
- // transform it so the operand types match the vector. Build a vector of
- // half the length out of elements of twice the bitwidth.
- // For example <4 x i16> -> <2 x i32>.
- MVT NewVT = MVT::getIntegerVT(2 * EltVT.getSizeInBits());
- assert(OpVT.isSimple() && NewVT.isSimple());
- SmallVector<SDValue, 16> NewElts;
-
- for (unsigned i = 0; i < NumElems; i += 2) {
- // Combine two successive elements into one promoted element.
- SDValue Lo = Node->getOperand(i);
- SDValue Hi = Node->getOperand(i+1);
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- Lo = DAG.getZeroExtendInReg(Lo, dl, EltVT);
- Hi = DAG.getNode(ISD::SHL, dl, OpVT, Hi,
- DAG.getConstant(EltVT.getSizeInBits(),
- TLI.getPointerTy()));
- NewElts.push_back(DAG.getNode(ISD::OR, dl, OpVT, Lo, Hi));
- }
-
- SDValue NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl,
- MVT::getVectorVT(NewVT, NewElts.size()),
- &NewElts[0], NewElts.size());
-
- // Recurse
- NewVec = ExpandBUILD_VECTOR(NewVec.getNode());
-
- // Convert the new vector to the old vector type.
- return DAG.getNode(ISD::BIT_CONVERT, dl, VT, NewVec);
- }
-
// If the only non-undef value is the low element, turn this into a
// SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X.
bool isOnlyLowElement = true;
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 115c9f8924..2dfe0e3b7d 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -863,24 +863,10 @@ SDValue DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) {
}
SDValue DAGTypeLegalizer::PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N) {
- // The vector type is legal but the element type is not. This implies
- // that the vector is a power-of-two in length and that the element
- // type does not have a strange size (eg: it is not i1).
- MVT VecVT = N->getValueType(0);
- unsigned NumElts = VecVT.getVectorNumElements();
- assert(!(NumElts & 1) && "Legal vector of one illegal element?");
- DebugLoc dl = N->getDebugLoc();
-
- MVT OldVT = N->getOperand(0).getValueType();
- MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
- assert(OldVT.isSimple() && NewVT.isSimple());
-
- SDValue ExtVal = DAG.getNode(ISD::ANY_EXTEND, dl, NewVT, N->getOperand(0));
- SDValue NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl,
- MVT::getVectorVT(NewVT, NumElts/2), ExtVal);
-
- // Convert the new vector to the old vector type.
- return DAG.getNode(ISD::BIT_CONVERT, dl, VecVT, NewVec);
+ // Integer SCALAR_TO_VECTOR operands are implicitly truncated, so just promote
+ // the operand in place.
+ return DAG.UpdateNodeOperands(SDValue(N, 0),
+ GetPromotedInteger(N->getOperand(0)));
}
SDValue DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) {
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
index f1d1f5b077..7826270a8f 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
@@ -347,6 +347,8 @@ SDValue DAGTypeLegalizer::ExpandOp_INSERT_VECTOR_ELT(SDNode *N) {
SDValue DAGTypeLegalizer::ExpandOp_SCALAR_TO_VECTOR(SDNode *N) {
DebugLoc dl = N->getDebugLoc();
MVT VT = N->getValueType(0);
+ assert(VT.getVectorElementType() == N->getOperand(0).getValueType() &&
+ "SCALAR_TO_VECTOR operand type doesn't match vector element type!");
unsigned NumElts = VT.getVectorNumElements();
SmallVector<SDValue, 16> Ops(NumElts);
Ops[0] = N->getOperand(0);
diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 935f420912..eec328f52f 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -183,7 +183,13 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
}
SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
- return N->getOperand(0);
+ // If the operand is wider than the vector element type then it is implicitly
+ // truncated. Make that explicit here.
+ MVT EltVT = N->getValueType(0).getVectorElementType();
+ SDValue InOp = N->getOperand(0);
+ if (InOp.getValueType() != EltVT)
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, InOp);
+ return InOp;
}
SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 4b8591eb85..0b2ef855fd 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2302,7 +2302,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL,
break;
case ISD::SCALAR_TO_VECTOR:
assert(VT.isVector() && !Operand.getValueType().isVector() &&
- VT.getVectorElementType() == Operand.getValueType() &&
+ (VT.getVectorElementType() == Operand.getValueType() ||
+ (VT.getVectorElementType().isInteger() &&
+ Operand.getValueType().isInteger() &&
+ VT.getVectorElementType().bitsLE(Operand.getValueType()))) &&
"Illegal SCALAR_TO_VECTOR node!");
if (OpOpcode == ISD::UNDEF)
return getUNDEF(VT);
diff --git a/test/CodeGen/PowerPC/vec_splat.ll b/test/CodeGen/PowerPC/vec_splat.ll
index bc860cbf02..a631137000 100644
--- a/test/CodeGen/PowerPC/vec_splat.ll
+++ b/test/CodeGen/PowerPC/vec_splat.ll
@@ -1,7 +1,7 @@
; Test that vectors are scalarized/lowered correctly.
; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g3 | \
; RUN: grep stfs | count 4
-; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g5 -o %t -f -disable-legalize-types
+; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g5 -o %t -f
; RUN: grep vspltw %t | count 2
; RUN: grep vsplti %t | count 3
; RUN: grep vsplth %t | count 1