forked from OSchip/llvm-project
Make EXTRACT_VECTOR_ELT a bit more flexible in terms of the returned
value. Adjust other code to deal with that correctly. Make DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT take advantage of this new flexibility to simplify the code and make it deal with unusual vectors (like <4 x i1>) correctly. Fixes PR3037. llvm-svn: 75176
This commit is contained in:
parent
cf1441ab20
commit
2b77eef160
|
@ -303,7 +303,9 @@ namespace ISD {
|
|||
INSERT_VECTOR_ELT,
|
||||
|
||||
/// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
|
||||
/// identified by the (potentially variable) element number IDX.
|
||||
/// identified by the (potentially variable) element number IDX. If the
|
||||
/// return type is an integer type larger than the element type of the
|
||||
/// vector, the result is extended to the width of the return type.
|
||||
EXTRACT_VECTOR_ELT,
|
||||
|
||||
/// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of
|
||||
|
|
|
@ -1526,7 +1526,11 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) {
|
|||
|
||||
StackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, StackPtr);
|
||||
|
||||
return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0);
|
||||
if (Op.getValueType().isVector())
|
||||
return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0);
|
||||
else
|
||||
return DAG.getExtLoad(ISD::EXTLOAD, dl, Op.getValueType(), Ch, StackPtr,
|
||||
NULL, 0, Vec.getValueType().getVectorElementType());
|
||||
}
|
||||
|
||||
SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) {
|
||||
|
|
|
@ -303,52 +303,10 @@ SDValue DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) {
|
|||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
|
||||
MVT OldVT = N->getValueType(0);
|
||||
SDValue OldVec = N->getOperand(0);
|
||||
if (getTypeAction(OldVec.getValueType()) == WidenVector)
|
||||
OldVec = GetWidenedVector(N->getOperand(0));
|
||||
unsigned OldElts = OldVec.getValueType().getVectorNumElements();
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
if (OldElts == 1) {
|
||||
assert(!isTypeLegal(OldVec.getValueType()) &&
|
||||
"Legal one-element vector of a type needing promotion!");
|
||||
// It is tempting to follow GetScalarizedVector by a call to
|
||||
// GetPromotedInteger, but this would be wrong because the
|
||||
// scalarized value may not yet have been processed.
|
||||
return DAG.getNode(ISD::ANY_EXTEND, dl, TLI.getTypeToTransformTo(OldVT),
|
||||
GetScalarizedVector(OldVec));
|
||||
}
|
||||
|
||||
// Convert to a vector half as long with an element type of twice the width,
|
||||
// for example <4 x i16> -> <2 x i32>.
|
||||
assert(!(OldElts & 1) && "Odd length vectors not supported!");
|
||||
MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
|
||||
assert(OldVT.isSimple() && NewVT.isSimple());
|
||||
|
||||
SDValue NewVec = DAG.getNode(ISD::BIT_CONVERT, dl,
|
||||
MVT::getVectorVT(NewVT, OldElts / 2),
|
||||
OldVec);
|
||||
|
||||
// Extract the element at OldIdx / 2 from the new vector.
|
||||
SDValue OldIdx = N->getOperand(1);
|
||||
SDValue NewIdx = DAG.getNode(ISD::SRL, dl, OldIdx.getValueType(), OldIdx,
|
||||
DAG.getConstant(1, TLI.getPointerTy()));
|
||||
SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, NewVec, NewIdx);
|
||||
|
||||
// Select the appropriate half of the element: Lo if OldIdx was even,
|
||||
// Hi if it was odd.
|
||||
SDValue Lo = Elt;
|
||||
SDValue Hi = DAG.getNode(ISD::SRL, dl, NewVT, Elt,
|
||||
DAG.getConstant(OldVT.getSizeInBits(),
|
||||
TLI.getPointerTy()));
|
||||
if (TLI.isBigEndian())
|
||||
std::swap(Lo, Hi);
|
||||
|
||||
// Extend to the promoted type.
|
||||
SDValue Odd = DAG.getNode(ISD::TRUNCATE, dl, MVT::i1, OldIdx);
|
||||
SDValue Res = DAG.getNode(ISD::SELECT, dl, NewVT, Odd, Hi, Lo);
|
||||
return DAG.getNode(ISD::ANY_EXTEND, dl, TLI.getTypeToTransformTo(OldVT), Res);
|
||||
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
|
||||
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NVT, N->getOperand(0),
|
||||
N->getOperand(1));
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
|
||||
|
|
|
@ -331,7 +331,11 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
|
|||
/// be scalarized, it must be <1 x ty>, so just return the element, ignoring the
|
||||
/// index.
|
||||
SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
||||
return GetScalarizedVector(N->getOperand(0));
|
||||
SDValue Res = GetScalarizedVector(N->getOperand(0));
|
||||
if (Res.getValueType() != N->getValueType(0))
|
||||
Res = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0),
|
||||
Res);
|
||||
return Res;
|
||||
}
|
||||
|
||||
/// ScalarizeVecOp_STORE - If the value to store is a vector that needs to be
|
||||
|
@ -1052,7 +1056,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
|||
|
||||
// Load back the required element.
|
||||
StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx);
|
||||
return DAG.getLoad(EltVT, dl, Store, StackPtr, SV, 0);
|
||||
return DAG.getExtLoad(ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
|
||||
SV, 0, EltVT);
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
|
||||
|
@ -1904,9 +1909,8 @@ SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
|
|||
|
||||
SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
||||
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
||||
MVT EltVT = InOp.getValueType().getVectorElementType();
|
||||
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(),
|
||||
EltVT, InOp, N->getOperand(1));
|
||||
N->getValueType(0), InOp, N->getOperand(1));
|
||||
}
|
||||
|
||||
SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
|
||||
|
|
|
@ -2693,13 +2693,16 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT,
|
|||
// expanding large vector constants.
|
||||
if (N2C && N1.getOpcode() == ISD::BUILD_VECTOR) {
|
||||
SDValue Elt = N1.getOperand(N2C->getZExtValue());
|
||||
if (Elt.getValueType() != VT) {
|
||||
MVT VEltTy = N1.getValueType().getVectorElementType();
|
||||
if (Elt.getValueType() != VEltTy) {
|
||||
// If the vector element type is not legal, the BUILD_VECTOR operands
|
||||
// are promoted and implicitly truncated. Make that explicit here.
|
||||
assert(VT.isInteger() && Elt.getValueType().isInteger() &&
|
||||
VT.bitsLE(Elt.getValueType()) &&
|
||||
"Bad type for BUILD_VECTOR operand");
|
||||
Elt = getNode(ISD::TRUNCATE, DL, VT, Elt);
|
||||
Elt = getNode(ISD::TRUNCATE, DL, VEltTy, Elt);
|
||||
}
|
||||
if (VT != VEltTy) {
|
||||
// If the vector element type is not legal, the EXTRACT_VECTOR_ELT
|
||||
// result is implicitly extended.
|
||||
Elt = getNode(ISD::ANY_EXTEND, DL, VT, Elt);
|
||||
}
|
||||
return Elt;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
; RUN: llvm-as < %s | llc -march=x86 -disable-mmx
|
||||
|
||||
define void @test2(<2 x i32> %A, <2 x i32> %B, <2 x i32>* %C) nounwind {
|
||||
%D = icmp sgt <2 x i32> %A, %B
|
||||
%E = zext <2 x i1> %D to <2 x i32>
|
||||
store <2 x i32> %E, <2 x i32>* %C
|
||||
ret void
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
; RUN: llvm-as < %s | llc -march=x86
|
||||
; PR3037
|
||||
|
||||
define void @entry(<4 x i8>* %dest) {
|
||||
%1 = xor <4 x i1> zeroinitializer, < i1 true, i1 true, i1 true, i1 true >
|
||||
%2 = extractelement <4 x i1> %1, i32 3
|
||||
%3 = zext i1 %2 to i8
|
||||
%4 = insertelement <4 x i8> zeroinitializer, i8 %3, i32 3
|
||||
store <4 x i8> %4, <4 x i8>* %dest, align 1
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue