1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

Improve support for vector casts in LLVM IR and CodeGen.

llvm-svn: 54784
This commit is contained in:
Dan Gohman 2008-08-14 20:04:46 +00:00
parent 169e5e5b99
commit b0f5e18201
7 changed files with 294 additions and 111 deletions

View File

@ -3146,6 +3146,10 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
MVT VT = N->getValueType(0);
MVT EVT = N->getValueType(0);
// This transformation isn't valid for vector loads.
if (VT.isVector())
return SDValue();
// Special case: SIGN_EXTEND_INREG is basically truncating to EVT then
// extended to VT.
if (Opc == ISD::SIGN_EXTEND_INREG) {

View File

@ -201,6 +201,7 @@ private:
SDValue EmitStackConvert(SDValue SrcOp, MVT SlotVT, MVT DestVT);
SDValue ExpandBUILD_VECTOR(SDNode *Node);
SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node);
SDValue LegalizeINT_TO_FP(SDValue Result, bool isSigned, MVT DestTy, SDValue Op);
SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, MVT DestVT);
SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, MVT DestVT, bool isSigned);
SDValue PromoteLegalFP_TO_INT(SDValue LegalOp, MVT DestVT, bool isSigned);
@ -3623,51 +3624,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP: {
bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP;
switch (getTypeAction(Node->getOperand(0).getValueType())) {
case Legal:
switch (TLI.getOperationAction(Node->getOpcode(),
Node->getOperand(0).getValueType())) {
default: assert(0 && "Unknown operation action!");
case TargetLowering::Custom:
isCustom = true;
// FALLTHROUGH
case TargetLowering::Legal:
Tmp1 = LegalizeOp(Node->getOperand(0));
Result = DAG.UpdateNodeOperands(Result, Tmp1);
if (isCustom) {
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
}
break;
case TargetLowering::Expand:
Result = ExpandLegalINT_TO_FP(isSigned,
LegalizeOp(Node->getOperand(0)),
Node->getValueType(0));
break;
case TargetLowering::Promote:
Result = PromoteLegalINT_TO_FP(LegalizeOp(Node->getOperand(0)),
Node->getValueType(0),
isSigned);
break;
}
break;
case Expand:
Result = ExpandIntToFP(Node->getOpcode() == ISD::SINT_TO_FP,
Node->getValueType(0), Node->getOperand(0));
break;
case Promote:
Tmp1 = PromoteOp(Node->getOperand(0));
if (isSigned) {
Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, Tmp1.getValueType(),
Tmp1, DAG.getValueType(Node->getOperand(0).getValueType()));
} else {
Tmp1 = DAG.getZeroExtendInReg(Tmp1,
Node->getOperand(0).getValueType());
}
Result = DAG.UpdateNodeOperands(Result, Tmp1);
Result = LegalizeOp(Result); // The 'op' is not necessarily legal!
break;
}
Result = LegalizeINT_TO_FP(Result, isSigned,
Node->getValueType(0), Node->getOperand(0));
break;
}
case ISD::TRUNCATE:
@ -5250,6 +5208,62 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node,
return Result;
}
/// LegalizeINT_TO_FP - Legalize a [US]INT_TO_FP operation.
///
SDValue SelectionDAGLegalize::
LegalizeINT_TO_FP(SDValue Result, bool isSigned, MVT DestTy, SDValue Op) {
bool isCustom = false;
SDValue Tmp1;
switch (getTypeAction(Op.getValueType())) {
case Legal:
switch (TLI.getOperationAction(isSigned ? ISD::SINT_TO_FP : ISD::UINT_TO_FP,
Op.getValueType())) {
default: assert(0 && "Unknown operation action!");
case TargetLowering::Custom:
isCustom = true;
// FALLTHROUGH
case TargetLowering::Legal:
Tmp1 = LegalizeOp(Op);
if (Result.Val)
Result = DAG.UpdateNodeOperands(Result, Tmp1);
else
Result = DAG.getNode(isSigned ? ISD::SINT_TO_FP : ISD::UINT_TO_FP,
DestTy, Tmp1);
if (isCustom) {
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
}
break;
case TargetLowering::Expand:
Result = ExpandLegalINT_TO_FP(isSigned, LegalizeOp(Op), DestTy);
break;
case TargetLowering::Promote:
Result = PromoteLegalINT_TO_FP(LegalizeOp(Op), DestTy, isSigned);
break;
}
break;
case Expand:
Result = ExpandIntToFP(isSigned, DestTy, Op);
break;
case Promote:
Tmp1 = PromoteOp(Op);
if (isSigned) {
Tmp1 = DAG.getNode(ISD::SIGN_EXTEND_INREG, Tmp1.getValueType(),
Tmp1, DAG.getValueType(Op.getValueType()));
} else {
Tmp1 = DAG.getZeroExtendInReg(Tmp1,
Op.getValueType());
}
if (Result.Val)
Result = DAG.UpdateNodeOperands(Result, Tmp1);
else
Result = DAG.getNode(isSigned ? ISD::SINT_TO_FP : ISD::UINT_TO_FP,
DestTy, Tmp1);
Result = LegalizeOp(Result); // The 'op' is not necessarily legal!
break;
}
return Result;
}
/// ExpandIntToFP - Expand a [US]INT_TO_FP operation.
///
@ -5258,6 +5272,26 @@ ExpandIntToFP(bool isSigned, MVT DestTy, SDValue Source) {
MVT SourceVT = Source.getValueType();
bool ExpandSource = getTypeAction(SourceVT) == Expand;
// Expand unsupported int-to-fp vector casts by unrolling them.
if (DestTy.isVector()) {
if (!ExpandSource)
return LegalizeOp(UnrollVectorOp(Source));
MVT DestEltTy = DestTy.getVectorElementType();
if (DestTy.getVectorNumElements() == 1) {
SDValue Scalar = ScalarizeVectorOp(Source);
SDValue Result = LegalizeINT_TO_FP(SDValue(), isSigned,
DestEltTy, Scalar);
return DAG.getNode(ISD::BUILD_VECTOR, DestTy, Result);
}
SDValue Lo, Hi;
SplitVectorOp(Source, Lo, Hi);
MVT SplitDestTy = MVT::getVectorVT(DestEltTy,
DestTy.getVectorNumElements() / 2);
SDValue LoResult = LegalizeINT_TO_FP(SDValue(), isSigned, SplitDestTy, Lo);
SDValue HiResult = LegalizeINT_TO_FP(SDValue(), isSigned, SplitDestTy, Hi);
return LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, DestTy, LoResult, HiResult));
}
// Special case for i32 source to take advantage of UINTTOFP_I32_F32, etc.
if (!isSigned && SourceVT != MVT::i32) {
// The integer value loaded will be incorrectly if the 'sign bit' of the
@ -5863,12 +5897,13 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){
SDValue Ch = LD->getChain(); // Legalize the chain.
SDValue Ptr = LD->getBasePtr(); // Legalize the pointer.
ISD::LoadExtType ExtType = LD->getExtensionType();
const Value *SV = LD->getSrcValue();
int SVOffset = LD->getSrcValueOffset();
unsigned Alignment = LD->getAlignment();
bool isVolatile = LD->isVolatile();
if (ExtType == ISD::NON_EXTLOAD) {
Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset,
Lo = DAG.getLoad(NVT, Ch, Ptr, SV, SVOffset,
isVolatile, Alignment);
if (VT == MVT::f32 || VT == MVT::f64) {
// f32->i32 or f64->i64 one to one expansion.
@ -5886,7 +5921,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){
DAG.getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset,
Hi = DAG.getLoad(NVT, Ch, Ptr, SV, SVOffset,
isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
@ -5904,7 +5939,7 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){
if ((VT == MVT::f64 && EVT == MVT::f32) ||
(VT == MVT::ppcf128 && (EVT==MVT::f64 || EVT==MVT::f32))) {
// f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
SDValue Load = DAG.getLoad(EVT, Ch, Ptr, LD->getSrcValue(),
SDValue Load = DAG.getLoad(EVT, Ch, Ptr, SV,
SVOffset, isVolatile, Alignment);
// Remember that we legalized the chain.
AddLegalizedOperand(SDValue(Node, 1), LegalizeOp(Load.getValue(1)));
@ -5913,10 +5948,10 @@ void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){
}
if (EVT == NVT)
Lo = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(),
Lo = DAG.getLoad(NVT, Ch, Ptr, SV,
SVOffset, isVolatile, Alignment);
else
Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, LD->getSrcValue(),
Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, SV,
SVOffset, EVT, isVolatile,
Alignment);
@ -6817,6 +6852,7 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo,
Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, LH, RH);
break;
}
case ISD::FP_ROUND:
case ISD::FPOWI: {
SDValue L, H;
SplitVectorOp(Node->getOperand(0), L, H);
@ -6836,7 +6872,12 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo,
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT:
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP: {
case ISD::UINT_TO_FP:
case ISD::TRUNCATE:
case ISD::ANY_EXTEND:
case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::FP_EXTEND: {
SDValue L, H;
SplitVectorOp(Node->getOperand(0), L, H);
@ -6848,18 +6889,31 @@ void SelectionDAGLegalize::SplitVectorOp(SDValue Op, SDValue &Lo,
LoadSDNode *LD = cast<LoadSDNode>(Node);
SDValue Ch = LD->getChain();
SDValue Ptr = LD->getBasePtr();
ISD::LoadExtType ExtType = LD->getExtensionType();
const Value *SV = LD->getSrcValue();
int SVOffset = LD->getSrcValueOffset();
MVT MemoryVT = LD->getMemoryVT();
unsigned Alignment = LD->getAlignment();
bool isVolatile = LD->isVolatile();
Lo = DAG.getLoad(NewVT_Lo, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
unsigned IncrementSize = NewNumElts_Lo * NewEltVT.getSizeInBits()/8;
assert(LD->isUnindexed() && "Indexed vector loads are not supported yet!");
SDValue Offset = DAG.getNode(ISD::UNDEF, Ptr.getValueType());
MVT MemNewEltVT = MemoryVT.getVectorElementType();
MVT MemNewVT_Lo = MVT::getVectorVT(MemNewEltVT, NewNumElts_Lo);
MVT MemNewVT_Hi = MVT::getVectorVT(MemNewEltVT, NewNumElts_Hi);
Lo = DAG.getLoad(ISD::UNINDEXED, ExtType,
NewVT_Lo, Ch, Ptr, Offset,
SV, SVOffset, MemNewVT_Lo, isVolatile, Alignment);
unsigned IncrementSize = NewNumElts_Lo * MemNewEltVT.getSizeInBits()/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(NewVT_Hi, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
Hi = DAG.getLoad(ISD::UNINDEXED, ExtType,
NewVT_Hi, Ch, Ptr, Offset,
SV, SVOffset, MemNewVT_Hi, isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
// other one.
@ -6951,11 +7005,21 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) {
case ISD::FSQRT:
case ISD::FSIN:
case ISD::FCOS:
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT:
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP:
case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::ANY_EXTEND:
case ISD::TRUNCATE:
case ISD::FP_EXTEND:
Result = DAG.getNode(Node->getOpcode(),
NewVT,
ScalarizeVectorOp(Node->getOperand(0)));
break;
case ISD::FPOWI:
case ISD::FP_ROUND:
Result = DAG.getNode(Node->getOpcode(),
NewVT,
ScalarizeVectorOp(Node->getOperand(0)),
@ -6965,11 +7029,20 @@ SDValue SelectionDAGLegalize::ScalarizeVectorOp(SDValue Op) {
LoadSDNode *LD = cast<LoadSDNode>(Node);
SDValue Ch = LegalizeOp(LD->getChain()); // Legalize the chain.
SDValue Ptr = LegalizeOp(LD->getBasePtr()); // Legalize the pointer.
ISD::LoadExtType ExtType = LD->getExtensionType();
const Value *SV = LD->getSrcValue();
int SVOffset = LD->getSrcValueOffset();
Result = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset,
LD->isVolatile(), LD->getAlignment());
MVT MemoryVT = LD->getMemoryVT();
unsigned Alignment = LD->getAlignment();
bool isVolatile = LD->isVolatile();
assert(LD->isUnindexed() && "Indexed vector loads are not supported yet!");
SDValue Offset = DAG.getNode(ISD::UNDEF, Ptr.getValueType());
Result = DAG.getLoad(ISD::UNINDEXED, ExtType,
NewVT, Ch, Ptr, Offset, SV, SVOffset,
MemoryVT.getVectorElementType(),
isVolatile, Alignment);
// Remember that we legalized the chain.
AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));

View File

@ -115,11 +115,16 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
}
SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
assert(ISD::isNormalLoad(N) && "Extending load of one-element vector?");
SDValue Result = DAG.getLoad(N->getValueType(0).getVectorElementType(),
N->getChain(), N->getBasePtr(),
N->getSrcValue(), N->getSrcValueOffset(),
N->isVolatile(), N->getAlignment());
assert(N->isUnindexed() && "Indexed vector load?");
SDValue Result = DAG.getLoad(ISD::UNINDEXED, N->getExtensionType(),
N->getValueType(0).getVectorElementType(),
N->getChain(), N->getBasePtr(),
DAG.getNode(ISD::UNDEF,
N->getBasePtr().getValueType()),
N->getSrcValue(), N->getSrcValueOffset(),
N->getMemoryVT().getVectorElementType(),
N->isVolatile(), N->getAlignment());
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
@ -232,8 +237,17 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
/// ScalarizeVecOp_STORE - If the value to store is a vector that needs to be
/// scalarized, it must be <1 x ty>. Just store the element.
SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
assert(ISD::isNormalStore(N) && "Truncating store of one-element vector?");
assert(N->isUnindexed() && "Indexed store of one-element vector?");
assert(OpNo == 1 && "Do not know how to scalarize this operand!");
if (N->isTruncatingStore())
return DAG.getTruncStore(N->getChain(),
GetScalarizedVector(N->getOperand(1)),
N->getBasePtr(),
N->getSrcValue(), N->getSrcValueOffset(),
N->getMemoryVT().getVectorElementType(),
N->isVolatile(), N->getAlignment());
return DAG.getStore(N->getChain(), GetScalarizedVector(N->getOperand(1)),
N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
N->isVolatile(), N->getAlignment());
@ -460,33 +474,34 @@ void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
MVT LoVT, HiVT;
GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT);
ISD::LoadExtType ExtType = LD->getExtensionType();
SDValue Ch = LD->getChain();
SDValue Ptr = LD->getBasePtr();
SDValue Offset = DAG.getNode(ISD::UNDEF, Ptr.getValueType());
const Value *SV = LD->getSrcValue();
int SVOffset = LD->getSrcValueOffset();
MVT MemoryVT = LD->getMemoryVT();
unsigned Alignment = LD->getAlignment();
bool isVolatile = LD->isVolatile();
Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
MVT LoMemVT, HiMemVT;
GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT);
if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
unsigned IncrementSize = LoVT.getSizeInBits()/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, Ch, Ptr, Offset,
SV, SVOffset, LoMemVT, isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
// other one.
Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
Hi.getValue(1));
} else {
assert(LD->getExtensionType() == ISD::EXTLOAD &&
"Unsupported vector extending load!");
Hi = DAG.getNode(ISD::UNDEF, HiVT);
Ch = Lo.getValue(1);
}
unsigned IncrementSize = LoMemVT.getSizeInBits()/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, Ch, Ptr, Offset,
SV, SVOffset, HiMemVT, isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
// other one.
Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
Hi.getValue(1));
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
@ -679,27 +694,44 @@ SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
}
SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
assert(ISD::isNormalStore(N) && "Truncating store of vector?");
assert(N->isUnindexed() && "Indexed store of vector?");
assert(OpNo == 1 && "Can only split the stored value");
bool isTruncating = N->isTruncatingStore();
SDValue Ch = N->getChain();
SDValue Ptr = N->getBasePtr();
int SVOffset = N->getSrcValueOffset();
MVT MemoryVT = N->getMemoryVT();
unsigned Alignment = N->getAlignment();
bool isVol = N->isVolatile();
SDValue Lo, Hi;
GetSplitVector(N->getOperand(1), Lo, Hi);
unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8;
MVT LoMemVT, HiMemVT;
GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT);
Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment);
unsigned IncrementSize = LoMemVT.getSizeInBits()/8;
if (isTruncating)
Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
LoMemVT, isVol, Alignment);
else
Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
isVol, Alignment);
// Increment the pointer to the other half.
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getIntPtrConstant(IncrementSize));
Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
isVol, MinAlign(Alignment, IncrementSize));
if (isTruncating)
Hi = DAG.getTruncStore(Ch, Hi, Ptr,
N->getSrcValue(), SVOffset+IncrementSize,
HiMemVT,
isVol, MinAlign(Alignment, IncrementSize));
else
Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
isVol, MinAlign(Alignment, IncrementSize));
return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
}

View File

@ -2067,7 +2067,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) {
unsigned OpOpcode = Operand.Val->getOpcode();
switch (Opcode) {
case ISD::TokenFactor:
return Operand; // Factor of one node? No need.
case ISD::CONCAT_VECTORS:
return Operand; // Factor or concat of one node? No need.
case ISD::FP_ROUND: assert(0 && "Invalid method to make FP_ROUND node");
case ISD::FP_EXTEND:
assert(VT.isFloatingPoint() &&
@ -2196,6 +2197,16 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT,
if (N1.getOpcode() == ISD::EntryToken) return N2;
if (N2.getOpcode() == ISD::EntryToken) return N1;
break;
case ISD::CONCAT_VECTORS:
// A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to
// one big BUILD_VECTOR.
if (N1.getOpcode() == ISD::BUILD_VECTOR &&
N2.getOpcode() == ISD::BUILD_VECTOR) {
SmallVector<SDValue, 16> Elts(N1.Val->op_begin(), N1.Val->op_end());
Elts.insert(Elts.end(), N2.Val->op_begin(), N2.Val->op_end());
return getNode(ISD::BUILD_VECTOR, VT, &Elts[0], Elts.size());
}
break;
case ISD::AND:
assert(VT.isInteger() && N1.getValueType() == N2.getValueType() &&
N1.getValueType() == VT && "Binary operator types must match!");
@ -2541,6 +2552,18 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT,
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val);
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val);
switch (Opcode) {
case ISD::CONCAT_VECTORS:
// A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to
// one big BUILD_VECTOR.
if (N1.getOpcode() == ISD::BUILD_VECTOR &&
N2.getOpcode() == ISD::BUILD_VECTOR &&
N3.getOpcode() == ISD::BUILD_VECTOR) {
SmallVector<SDValue, 16> Elts(N1.Val->op_begin(), N1.Val->op_end());
Elts.insert(Elts.end(), N2.Val->op_begin(), N2.Val->op_end());
Elts.insert(Elts.end(), N3.Val->op_begin(), N3.Val->op_end());
return getNode(ISD::BUILD_VECTOR, VT, &Elts[0], Elts.size());
}
break;
case ISD::SETCC: {
// Use FoldSetCC to simplify SETCC's.
SDValue Simp = FoldSetCC(VT, N1, N2, cast<CondCodeSDNode>(N3)->get());
@ -3179,7 +3202,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
} else {
// Extending load.
if (VT.isVector())
assert(EVT == VT.getVectorElementType() && "Invalid vector extload!");
assert(EVT.getVectorNumElements() == VT.getVectorNumElements() &&
"Invalid vector extload!");
else
assert(EVT.bitsLT(VT) &&
"Should only be an extending load, not truncating!");

View File

@ -2251,37 +2251,42 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy) {
switch (op) {
default: return false; // This is an input error
case Instruction::Trunc:
return SrcTy->isInteger() && DstTy->isInteger()&& SrcBitSize > DstBitSize;
return SrcTy->isIntOrIntVector() &&
DstTy->isIntOrIntVector()&& SrcBitSize > DstBitSize;
case Instruction::ZExt:
return SrcTy->isInteger() && DstTy->isInteger()&& SrcBitSize < DstBitSize;
return SrcTy->isIntOrIntVector() &&
DstTy->isIntOrIntVector()&& SrcBitSize < DstBitSize;
case Instruction::SExt:
return SrcTy->isInteger() && DstTy->isInteger()&& SrcBitSize < DstBitSize;
return SrcTy->isIntOrIntVector() &&
DstTy->isIntOrIntVector()&& SrcBitSize < DstBitSize;
case Instruction::FPTrunc:
return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
SrcBitSize > DstBitSize;
return SrcTy->isFPOrFPVector() &&
DstTy->isFPOrFPVector() &&
SrcBitSize > DstBitSize;
case Instruction::FPExt:
return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
SrcBitSize < DstBitSize;
return SrcTy->isFPOrFPVector() &&
DstTy->isFPOrFPVector() &&
SrcBitSize < DstBitSize;
case Instruction::UIToFP:
case Instruction::SIToFP:
if (const VectorType *SVTy = dyn_cast<VectorType>(SrcTy)) {
if (const VectorType *DVTy = dyn_cast<VectorType>(DstTy)) {
return SVTy->getElementType()->isInteger() &&
DVTy->getElementType()->isFloatingPoint() &&
return SVTy->getElementType()->isIntOrIntVector() &&
DVTy->getElementType()->isFPOrFPVector() &&
SVTy->getNumElements() == DVTy->getNumElements();
}
}
return SrcTy->isInteger() && DstTy->isFloatingPoint();
return SrcTy->isIntOrIntVector() && DstTy->isFPOrFPVector();
case Instruction::FPToUI:
case Instruction::FPToSI:
if (const VectorType *SVTy = dyn_cast<VectorType>(SrcTy)) {
if (const VectorType *DVTy = dyn_cast<VectorType>(DstTy)) {
return SVTy->getElementType()->isFloatingPoint() &&
DVTy->getElementType()->isInteger() &&
return SVTy->getElementType()->isFPOrFPVector() &&
DVTy->getElementType()->isIntOrIntVector() &&
SVTy->getNumElements() == DVTy->getNumElements();
}
}
return SrcTy->isFloatingPoint() && DstTy->isInteger();
return SrcTy->isFPOrFPVector() && DstTy->isIntOrIntVector();
case Instruction::PtrToInt:
return isa<PointerType>(SrcTy) && DstTy->isInteger();
case Instruction::IntToPtr:

View File

@ -665,8 +665,8 @@ void Verifier::visitTruncInst(TruncInst &I) {
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isInteger(), "Trunc only operates on integer", &I);
Assert1(DestTy->isInteger(), "Trunc only produces integer", &I);
Assert1(SrcTy->isIntOrIntVector(), "Trunc only operates on integer", &I);
Assert1(DestTy->isIntOrIntVector(), "Trunc only produces integer", &I);
Assert1(SrcBitSize > DestBitSize,"DestTy too big for Trunc", &I);
visitInstruction(I);
@ -678,8 +678,8 @@ void Verifier::visitZExtInst(ZExtInst &I) {
const Type *DestTy = I.getType();
// Get the size of the types in bits, we'll need this later
Assert1(SrcTy->isInteger(), "ZExt only operates on integer", &I);
Assert1(DestTy->isInteger(), "ZExt only produces an integer", &I);
Assert1(SrcTy->isIntOrIntVector(), "ZExt only operates on integer", &I);
Assert1(DestTy->isIntOrIntVector(), "ZExt only produces an integer", &I);
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
@ -697,8 +697,8 @@ void Verifier::visitSExtInst(SExtInst &I) {
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isInteger(), "SExt only operates on integer", &I);
Assert1(DestTy->isInteger(), "SExt only produces an integer", &I);
Assert1(SrcTy->isIntOrIntVector(), "SExt only operates on integer", &I);
Assert1(DestTy->isIntOrIntVector(), "SExt only produces an integer", &I);
Assert1(SrcBitSize < DestBitSize,"Type too small for SExt", &I);
visitInstruction(I);
@ -712,8 +712,8 @@ void Verifier::visitFPTruncInst(FPTruncInst &I) {
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isFloatingPoint(),"FPTrunc only operates on FP", &I);
Assert1(DestTy->isFloatingPoint(),"FPTrunc only produces an FP", &I);
Assert1(SrcTy->isFPOrFPVector(),"FPTrunc only operates on FP", &I);
Assert1(DestTy->isFPOrFPVector(),"FPTrunc only produces an FP", &I);
Assert1(SrcBitSize > DestBitSize,"DestTy too big for FPTrunc", &I);
visitInstruction(I);
@ -728,8 +728,8 @@ void Verifier::visitFPExtInst(FPExtInst &I) {
unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits();
unsigned DestBitSize = DestTy->getPrimitiveSizeInBits();
Assert1(SrcTy->isFloatingPoint(),"FPExt only operates on FP", &I);
Assert1(DestTy->isFloatingPoint(),"FPExt only produces an FP", &I);
Assert1(SrcTy->isFPOrFPVector(),"FPExt only operates on FP", &I);
Assert1(DestTy->isFPOrFPVector(),"FPExt only produces an FP", &I);
Assert1(SrcBitSize < DestBitSize,"DestTy too small for FPExt", &I);
visitInstruction(I);

View File

@ -0,0 +1,45 @@
; RUN: llvm-as < %s | llc
; PR2671
define void @a(<2 x double>* %p, <2 x i8>* %q) {
%t = load <2 x double>* %p
%r = fptosi <2 x double> %t to <2 x i8>
store <2 x i8> %r, <2 x i8>* %q
ret void
}
define void @b(<2 x double>* %p, <2 x i8>* %q) {
%t = load <2 x double>* %p
%r = fptoui <2 x double> %t to <2 x i8>
store <2 x i8> %r, <2 x i8>* %q
ret void
}
define void @c(<2 x i8>* %p, <2 x double>* %q) {
%t = load <2 x i8>* %p
%r = sitofp <2 x i8> %t to <2 x double>
store <2 x double> %r, <2 x double>* %q
ret void
}
define void @d(<2 x i8>* %p, <2 x double>* %q) {
%t = load <2 x i8>* %p
%r = uitofp <2 x i8> %t to <2 x double>
store <2 x double> %r, <2 x double>* %q
ret void
}
define void @e(<2 x i8>* %p, <2 x i16>* %q) {
%t = load <2 x i8>* %p
%r = sext <2 x i8> %t to <2 x i16>
store <2 x i16> %r, <2 x i16>* %q
ret void
}
define void @f(<2 x i8>* %p, <2 x i16>* %q) {
%t = load <2 x i8>* %p
%r = zext <2 x i8> %t to <2 x i16>
store <2 x i16> %r, <2 x i16>* %q
ret void
}
define void @g(<2 x i16>* %p, <2 x i8>* %q) {
%t = load <2 x i16>* %p
%r = trunc <2 x i16> %t to <2 x i8>
store <2 x i8> %r, <2 x i8>* %q
ret void
}