Implement vector widening, splitting, and scalarizing for SIGN_EXTEND_INREG.

llvm-svn: 91158
This commit is contained in:
Dan Gohman 2009-12-11 21:31:27 +00:00
parent 8811885366
commit 1d459e4937
10 changed files with 134 additions and 32 deletions

View File

@ -167,6 +167,12 @@ namespace llvm {
} }
} }
/// getScalarType - If this is a vector type, return the element type,
/// otherwise return this.
MVT getScalarType() const {
return isVector() ? getVectorElementType() : *this;
}
MVT getVectorElementType() const { MVT getVectorElementType() const {
switch (SimpleTy) { switch (SimpleTy) {
default: default:
@ -524,6 +530,12 @@ namespace llvm {
return V; return V;
} }
/// getScalarType - If this is a vector type, return the element type,
/// otherwise return this.
EVT getScalarType() const {
return isVector() ? getVectorElementType() : *this;
}
/// getVectorElementType - Given a vector type, return the type of /// getVectorElementType - Given a vector type, return the type of
/// each element. /// each element.
EVT getVectorElementType() const { EVT getVectorElementType() const {

View File

@ -119,7 +119,8 @@ namespace {
/// it can be simplified or if things it uses can be simplified by bit /// it can be simplified or if things it uses can be simplified by bit
/// propagation. If so, return true. /// propagation. If so, return true.
bool SimplifyDemandedBits(SDValue Op) { bool SimplifyDemandedBits(SDValue Op) {
APInt Demanded = APInt::getAllOnesValue(Op.getValueSizeInBits()); unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
APInt Demanded = APInt::getAllOnesValue(BitWidth);
return SimplifyDemandedBits(Op, Demanded); return SimplifyDemandedBits(Op, Demanded);
} }
@ -2441,7 +2442,7 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
EVT VT = N0.getValueType(); EVT VT = N0.getValueType();
unsigned OpSizeInBits = VT.getSizeInBits(); unsigned OpSizeInBits = VT.getScalarType().getSizeInBits();
// fold (shl c1, c2) -> c1<<c2 // fold (shl c1, c2) -> c1<<c2
if (N0C && N1C) if (N0C && N1C)
@ -2457,7 +2458,7 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
return N0; return N0;
// if (shl x, c) is known to be zero, return 0 // if (shl x, c) is known to be zero, return 0
if (DAG.MaskedValueIsZero(SDValue(N, 0), if (DAG.MaskedValueIsZero(SDValue(N, 0),
APInt::getAllOnesValue(VT.getSizeInBits()))) APInt::getAllOnesValue(OpSizeInBits)))
return DAG.getConstant(0, VT); return DAG.getConstant(0, VT);
// fold (shl x, (trunc (and y, c))) -> (shl x, (and (trunc y), (trunc c))). // fold (shl x, (trunc (and y, c))) -> (shl x, (and (trunc y), (trunc c))).
if (N1.getOpcode() == ISD::TRUNCATE && if (N1.getOpcode() == ISD::TRUNCATE &&
@ -2533,6 +2534,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
EVT VT = N0.getValueType(); EVT VT = N0.getValueType();
unsigned OpSizeInBits = VT.getScalarType().getSizeInBits();
// fold (sra c1, c2) -> (sra c1, c2) // fold (sra c1, c2) -> (sra c1, c2)
if (N0C && N1C) if (N0C && N1C)
@ -2544,7 +2546,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
if (N0C && N0C->isAllOnesValue()) if (N0C && N0C->isAllOnesValue())
return N0; return N0;
// fold (sra x, (setge c, size(x))) -> undef // fold (sra x, (setge c, size(x))) -> undef
if (N1C && N1C->getZExtValue() >= VT.getSizeInBits()) if (N1C && N1C->getZExtValue() >= OpSizeInBits)
return DAG.getUNDEF(VT); return DAG.getUNDEF(VT);
// fold (sra x, 0) -> x // fold (sra x, 0) -> x
if (N1C && N1C->isNullValue()) if (N1C && N1C->isNullValue())
@ -2552,7 +2554,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
// fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target supports // fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target supports
// sext_inreg. // sext_inreg.
if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) { if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) {
unsigned LowBits = VT.getSizeInBits() - (unsigned)N1C->getZExtValue(); unsigned LowBits = OpSizeInBits - (unsigned)N1C->getZExtValue();
EVT EVT = EVT::getIntegerVT(*DAG.getContext(), LowBits); EVT EVT = EVT::getIntegerVT(*DAG.getContext(), LowBits);
if ((!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, EVT))) if ((!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, EVT)))
return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT,
@ -2563,7 +2565,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
if (N1C && N0.getOpcode() == ISD::SRA) { if (N1C && N0.getOpcode() == ISD::SRA) {
if (ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) { if (ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
unsigned Sum = N1C->getZExtValue() + C1->getZExtValue(); unsigned Sum = N1C->getZExtValue() + C1->getZExtValue();
if (Sum >= VT.getSizeInBits()) Sum = VT.getSizeInBits()-1; if (Sum >= OpSizeInBits) Sum = OpSizeInBits-1;
return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0.getOperand(0), return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getConstant(Sum, N1C->getValueType(0))); DAG.getConstant(Sum, N1C->getValueType(0)));
} }
@ -2579,9 +2581,8 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
const ConstantSDNode *N01C = dyn_cast<ConstantSDNode>(N0.getOperand(1)); const ConstantSDNode *N01C = dyn_cast<ConstantSDNode>(N0.getOperand(1));
if (N01C && N1C) { if (N01C && N1C) {
// Determine what the truncate's result bitsize and type would be. // Determine what the truncate's result bitsize and type would be.
unsigned VTValSize = VT.getSizeInBits();
EVT TruncVT = EVT TruncVT =
EVT::getIntegerVT(*DAG.getContext(), VTValSize - N1C->getZExtValue()); EVT::getIntegerVT(*DAG.getContext(), OpSizeInBits - N1C->getZExtValue());
// Determine the residual right-shift amount. // Determine the residual right-shift amount.
signed ShiftAmt = N1C->getZExtValue() - N01C->getZExtValue(); signed ShiftAmt = N1C->getZExtValue() - N01C->getZExtValue();
@ -2614,7 +2615,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
EVT TruncVT = N1.getValueType(); EVT TruncVT = N1.getValueType();
SDValue N100 = N1.getOperand(0).getOperand(0); SDValue N100 = N1.getOperand(0).getOperand(0);
APInt TruncC = N101C->getAPIntValue(); APInt TruncC = N101C->getAPIntValue();
TruncC.trunc(TruncVT.getSizeInBits()); TruncC.trunc(TruncVT.getScalarType().getSizeInBits());
return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0,
DAG.getNode(ISD::AND, N->getDebugLoc(), DAG.getNode(ISD::AND, N->getDebugLoc(),
TruncVT, TruncVT,
@ -2643,7 +2644,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
EVT VT = N0.getValueType(); EVT VT = N0.getValueType();
unsigned OpSizeInBits = VT.getSizeInBits(); unsigned OpSizeInBits = VT.getScalarType().getSizeInBits();
// fold (srl c1, c2) -> c1 >>u c2 // fold (srl c1, c2) -> c1 >>u c2
if (N0C && N1C) if (N0C && N1C)
@ -3036,7 +3037,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
else if (Op.getValueType().bitsGT(VT)) else if (Op.getValueType().bitsGT(VT))
Op = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), VT, Op); Op = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), VT, Op);
return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, Op, return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, Op,
DAG.getValueType(N0.getValueType())); DAG.getValueType(N0.getValueType().getScalarType()));
} }
} }
@ -3177,7 +3178,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
} else if (Op.getValueType().bitsGT(VT)) { } else if (Op.getValueType().bitsGT(VT)) {
Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op); Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op);
} }
return DAG.getZeroExtendInReg(Op, N->getDebugLoc(), N0.getValueType()); return DAG.getZeroExtendInReg(Op, N->getDebugLoc(),
N0.getValueType().getScalarType());
} }
// Fold (zext (and (trunc x), cst)) -> (and x, cst), // Fold (zext (and (trunc x), cst)) -> (and x, cst),
@ -3536,7 +3538,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
SDValue N1 = N->getOperand(1); SDValue N1 = N->getOperand(1);
EVT VT = N->getValueType(0); EVT VT = N->getValueType(0);
EVT EVT = cast<VTSDNode>(N1)->getVT(); EVT EVT = cast<VTSDNode>(N1)->getVT();
unsigned VTBits = VT.getSizeInBits(); unsigned VTBits = VT.getScalarType().getSizeInBits();
unsigned EVTBits = EVT.getSizeInBits(); unsigned EVTBits = EVT.getSizeInBits();
// fold (sext_in_reg c1) -> c1 // fold (sext_in_reg c1) -> c1
@ -3544,7 +3546,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, N0, N1); return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, N0, N1);
// If the input is already sign extended, just drop the extension. // If the input is already sign extended, just drop the extension.
if (DAG.ComputeNumSignBits(N0) >= VT.getSizeInBits()-EVTBits+1) if (DAG.ComputeNumSignBits(N0) >= VTBits-EVTBits+1)
return N0; return N0;
// fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2 // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2
@ -3559,7 +3561,7 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
// if x is small enough. // if x is small enough.
if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) { if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) {
SDValue N00 = N0.getOperand(0); SDValue N00 = N0.getOperand(0);
if (N00.getValueType().getSizeInBits() < EVTBits) if (N00.getValueType().getScalarType().getSizeInBits() < EVTBits)
return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N00, N1); return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N00, N1);
} }
@ -3583,11 +3585,11 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
// We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" above. // We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" above.
if (N0.getOpcode() == ISD::SRL) { if (N0.getOpcode() == ISD::SRL) {
if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1))) if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1)))
if (ShAmt->getZExtValue()+EVTBits <= VT.getSizeInBits()) { if (ShAmt->getZExtValue()+EVTBits <= VTBits) {
// We can turn this into an SRA iff the input to the SRL is already sign // We can turn this into an SRA iff the input to the SRL is already sign
// extended enough. // extended enough.
unsigned InSignBits = DAG.ComputeNumSignBits(N0.getOperand(0)); unsigned InSignBits = DAG.ComputeNumSignBits(N0.getOperand(0));
if (VT.getSizeInBits()-(ShAmt->getZExtValue()+EVTBits) < InSignBits) if (VTBits-(ShAmt->getZExtValue()+EVTBits) < InSignBits)
return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT,
N0.getOperand(0), N0.getOperand(1)); N0.getOperand(0), N0.getOperand(1));
} }

View File

@ -2294,9 +2294,16 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
// NOTE: we could fall back on load/store here too for targets without // NOTE: we could fall back on load/store here too for targets without
// SAR. However, it is doubtful that any exist. // SAR. However, it is doubtful that any exist.
EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT(); EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
unsigned BitsDiff = Node->getValueType(0).getSizeInBits() - EVT VT = Node->getValueType(0);
EVT ShiftAmountTy = TLI.getShiftAmountTy();
if (ExtraVT.isVector()) ExtraVT = ExtraVT.getVectorElementType();
if (VT.isVector()) {
ShiftAmountTy = VT;
VT = VT.getVectorElementType();
}
unsigned BitsDiff = VT.getSizeInBits() -
ExtraVT.getSizeInBits(); ExtraVT.getSizeInBits();
SDValue ShiftCst = DAG.getConstant(BitsDiff, TLI.getShiftAmountTy()); SDValue ShiftCst = DAG.getConstant(BitsDiff, ShiftAmountTy);
Tmp1 = DAG.getNode(ISD::SHL, dl, Node->getValueType(0), Tmp1 = DAG.getNode(ISD::SHL, dl, Node->getValueType(0),
Node->getOperand(0), ShiftCst); Node->getOperand(0), ShiftCst);
Tmp1 = DAG.getNode(ISD::SRA, dl, Node->getValueType(0), Tmp1, ShiftCst); Tmp1 = DAG.getNode(ISD::SRA, dl, Node->getValueType(0), Tmp1, ShiftCst);

View File

@ -517,6 +517,7 @@ private:
SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N); SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N);
SDValue ScalarizeVecRes_LOAD(LoadSDNode *N); SDValue ScalarizeVecRes_LOAD(LoadSDNode *N);
SDValue ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N); SDValue ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N);
SDValue ScalarizeVecRes_SIGN_EXTEND_INREG(SDNode *N);
SDValue ScalarizeVecRes_SELECT(SDNode *N); SDValue ScalarizeVecRes_SELECT(SDNode *N);
SDValue ScalarizeVecRes_SELECT_CC(SDNode *N); SDValue ScalarizeVecRes_SELECT_CC(SDNode *N);
SDValue ScalarizeVecRes_SETCC(SDNode *N); SDValue ScalarizeVecRes_SETCC(SDNode *N);
@ -560,6 +561,7 @@ private:
void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi);
void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo, void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo,
@ -602,6 +604,7 @@ private:
SDValue WidenVecRes_INSERT_VECTOR_ELT(SDNode* N); SDValue WidenVecRes_INSERT_VECTOR_ELT(SDNode* N);
SDValue WidenVecRes_LOAD(SDNode* N); SDValue WidenVecRes_LOAD(SDNode* N);
SDValue WidenVecRes_SCALAR_TO_VECTOR(SDNode* N); SDValue WidenVecRes_SCALAR_TO_VECTOR(SDNode* N);
SDValue WidenVecRes_SIGN_EXTEND_INREG(SDNode* N);
SDValue WidenVecRes_SELECT(SDNode* N); SDValue WidenVecRes_SELECT(SDNode* N);
SDValue WidenVecRes_SELECT_CC(SDNode* N); SDValue WidenVecRes_SELECT_CC(SDNode* N);
SDValue WidenVecRes_UNDEF(SDNode *N); SDValue WidenVecRes_UNDEF(SDNode *N);

View File

@ -179,6 +179,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
case ISD::FRINT: case ISD::FRINT:
case ISD::FNEARBYINT: case ISD::FNEARBYINT:
case ISD::FFLOOR: case ISD::FFLOOR:
case ISD::SIGN_EXTEND_INREG:
QueryType = Node->getValueType(0); QueryType = Node->getValueType(0);
break; break;
case ISD::SINT_TO_FP: case ISD::SINT_TO_FP:

View File

@ -54,6 +54,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break; case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break; case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break; case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_SIGN_EXTEND_INREG(N); break;
case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break; case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break; case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break; case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
@ -195,6 +196,13 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
return InOp; return InOp;
} }
SDValue DAGTypeLegalizer::ScalarizeVecRes_SIGN_EXTEND_INREG(SDNode *N) {
EVT EltVT = N->getValueType(0).getVectorElementType();
SDValue LHS = GetScalarizedVector(N->getOperand(0));
return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), EltVT,
LHS, N->getOperand(1));
}
SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) { SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
SDValue LHS = GetScalarizedVector(N->getOperand(1)); SDValue LHS = GetScalarizedVector(N->getOperand(1));
return DAG.getNode(ISD::SELECT, N->getDebugLoc(), return DAG.getNode(ISD::SELECT, N->getDebugLoc(),
@ -401,6 +409,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break;
case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, Hi); break; case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, Hi); break;
case ISD::SIGN_EXTEND_INREG: SplitVecRes_SIGN_EXTEND_INREG(N, Lo, Hi); break;
case ISD::LOAD: case ISD::LOAD:
SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
break; break;
@ -700,6 +709,18 @@ void DAGTypeLegalizer::SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo,
Hi = DAG.getUNDEF(HiVT); Hi = DAG.getUNDEF(HiVT);
} }
void DAGTypeLegalizer::SplitVecRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo,
SDValue &Hi) {
SDValue LHSLo, LHSHi;
GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
DebugLoc dl = N->getDebugLoc();
Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
N->getOperand(1));
Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
N->getOperand(1));
}
void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
SDValue &Hi) { SDValue &Hi) {
assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!"); assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
@ -1141,6 +1162,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break; case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
case ISD::LOAD: Res = WidenVecRes_LOAD(N); break; case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
case ISD::SCALAR_TO_VECTOR: Res = WidenVecRes_SCALAR_TO_VECTOR(N); break; case ISD::SCALAR_TO_VECTOR: Res = WidenVecRes_SCALAR_TO_VECTOR(N); break;
case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_SIGN_EXTEND_INREG(N); break;
case ISD::SELECT: Res = WidenVecRes_SELECT(N); break; case ISD::SELECT: Res = WidenVecRes_SELECT(N); break;
case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break; case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break; case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
@ -1691,6 +1713,13 @@ SDValue DAGTypeLegalizer::WidenVecRes_SCALAR_TO_VECTOR(SDNode *N) {
WidenVT, N->getOperand(0)); WidenVT, N->getOperand(0));
} }
SDValue DAGTypeLegalizer::WidenVecRes_SIGN_EXTEND_INREG(SDNode *N) {
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(),
WidenVT, WidenLHS, N->getOperand(1));
}
SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) { SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) {
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
unsigned WidenNumElts = WidenVT.getVectorNumElements(); unsigned WidenNumElts = WidenVT.getVectorNumElements();

View File

@ -832,8 +832,12 @@ SDValue SelectionDAG::getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) {
} }
SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT VT) { SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT VT) {
assert(!VT.isVector() &&
"getZeroExtendInReg should use the vector element type instead of "
"the vector type!");
if (Op.getValueType() == VT) return Op; if (Op.getValueType() == VT) return Op;
APInt Imm = APInt::getLowBitsSet(Op.getValueSizeInBits(), unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
APInt Imm = APInt::getLowBitsSet(BitWidth,
VT.getSizeInBits()); VT.getSizeInBits());
return getNode(ISD::AND, DL, Op.getValueType(), Op, return getNode(ISD::AND, DL, Op.getValueType(), Op,
getConstant(Imm, Op.getValueType())); getConstant(Imm, Op.getValueType()));
@ -1481,7 +1485,7 @@ bool SelectionDAG::SignBitIsZero(SDValue Op, unsigned Depth) const {
if (Op.getValueType().isVector()) if (Op.getValueType().isVector())
return false; return false;
unsigned BitWidth = Op.getValueSizeInBits(); unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits();
return MaskedValueIsZero(Op, APInt::getSignBit(BitWidth), Depth); return MaskedValueIsZero(Op, APInt::getSignBit(BitWidth), Depth);
} }
@ -1504,7 +1508,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
APInt &KnownZero, APInt &KnownOne, APInt &KnownZero, APInt &KnownOne,
unsigned Depth) const { unsigned Depth) const {
unsigned BitWidth = Mask.getBitWidth(); unsigned BitWidth = Mask.getBitWidth();
assert(BitWidth == Op.getValueType().getSizeInBits() && assert(BitWidth == Op.getValueType().getScalarType().getSizeInBits() &&
"Mask size mismatches value type size!"); "Mask size mismatches value type size!");
KnownZero = KnownOne = APInt(BitWidth, 0); // Don't know anything. KnownZero = KnownOne = APInt(BitWidth, 0); // Don't know anything.
@ -1761,7 +1765,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
} }
case ISD::ZERO_EXTEND: { case ISD::ZERO_EXTEND: {
EVT InVT = Op.getOperand(0).getValueType(); EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getSizeInBits(); unsigned InBits = InVT.getScalarType().getSizeInBits();
APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask; APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask;
APInt InMask = Mask; APInt InMask = Mask;
InMask.trunc(InBits); InMask.trunc(InBits);
@ -1775,7 +1779,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
} }
case ISD::SIGN_EXTEND: { case ISD::SIGN_EXTEND: {
EVT InVT = Op.getOperand(0).getValueType(); EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getSizeInBits(); unsigned InBits = InVT.getScalarType().getSizeInBits();
APInt InSignBit = APInt::getSignBit(InBits); APInt InSignBit = APInt::getSignBit(InBits);
APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask; APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask;
APInt InMask = Mask; APInt InMask = Mask;
@ -1816,7 +1820,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
} }
case ISD::ANY_EXTEND: { case ISD::ANY_EXTEND: {
EVT InVT = Op.getOperand(0).getValueType(); EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getSizeInBits(); unsigned InBits = InVT.getScalarType().getSizeInBits();
APInt InMask = Mask; APInt InMask = Mask;
InMask.trunc(InBits); InMask.trunc(InBits);
KnownZero.trunc(InBits); KnownZero.trunc(InBits);
@ -1828,7 +1832,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
} }
case ISD::TRUNCATE: { case ISD::TRUNCATE: {
EVT InVT = Op.getOperand(0).getValueType(); EVT InVT = Op.getOperand(0).getValueType();
unsigned InBits = InVT.getSizeInBits(); unsigned InBits = InVT.getScalarType().getSizeInBits();
APInt InMask = Mask; APInt InMask = Mask;
InMask.zext(InBits); InMask.zext(InBits);
KnownZero.zext(InBits); KnownZero.zext(InBits);
@ -1961,7 +1965,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{
EVT VT = Op.getValueType(); EVT VT = Op.getValueType();
assert(VT.isInteger() && "Invalid VT!"); assert(VT.isInteger() && "Invalid VT!");
unsigned VTBits = VT.getSizeInBits(); unsigned VTBits = VT.getScalarType().getSizeInBits();
unsigned Tmp, Tmp2; unsigned Tmp, Tmp2;
unsigned FirstAnswer = 1; unsigned FirstAnswer = 1;
@ -1988,7 +1992,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{
} }
case ISD::SIGN_EXTEND: case ISD::SIGN_EXTEND:
Tmp = VTBits-Op.getOperand(0).getValueType().getSizeInBits(); Tmp = VTBits-Op.getOperand(0).getValueType().getScalarType().getSizeInBits();
return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp; return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp;
case ISD::SIGN_EXTEND_INREG: case ISD::SIGN_EXTEND_INREG:
@ -2624,6 +2628,9 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
assert(VT == N1.getValueType() && "Not an inreg extend!"); assert(VT == N1.getValueType() && "Not an inreg extend!");
assert(VT.isInteger() && EVT.isInteger() && assert(VT.isInteger() && EVT.isInteger() &&
"Cannot *_EXTEND_INREG FP types"); "Cannot *_EXTEND_INREG FP types");
assert(!EVT.isVector() &&
"AssertSExt/AssertZExt type should be the vector element type "
"rather than the vector type!");
assert(EVT.bitsLE(VT) && "Not extending!"); assert(EVT.bitsLE(VT) && "Not extending!");
if (VT == EVT) return N1; // noop assertion. if (VT == EVT) return N1; // noop assertion.
break; break;
@ -2633,12 +2640,15 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
assert(VT == N1.getValueType() && "Not an inreg extend!"); assert(VT == N1.getValueType() && "Not an inreg extend!");
assert(VT.isInteger() && EVT.isInteger() && assert(VT.isInteger() && EVT.isInteger() &&
"Cannot *_EXTEND_INREG FP types"); "Cannot *_EXTEND_INREG FP types");
assert(EVT.bitsLE(VT) && "Not extending!"); assert(!EVT.isVector() &&
"SIGN_EXTEND_INREG type should be the vector element type rather "
"than the vector type!");
assert(EVT.bitsLE(VT.getScalarType()) && "Not extending!");
if (EVT == VT) return N1; // Not actually extending if (EVT == VT) return N1; // Not actually extending
if (N1C) { if (N1C) {
APInt Val = N1C->getAPIntValue(); APInt Val = N1C->getAPIntValue();
unsigned FromBits = cast<VTSDNode>(N2)->getVT().getSizeInBits(); unsigned FromBits = EVT.getSizeInBits();
Val <<= Val.getBitWidth()-FromBits; Val <<= Val.getBitWidth()-FromBits;
Val = Val.ashr(Val.getBitWidth()-FromBits); Val = Val.ashr(Val.getBitWidth()-FromBits);
return getConstant(Val, VT); return getConstant(Val, VT);

View File

@ -911,7 +911,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
TargetLoweringOpt &TLO, TargetLoweringOpt &TLO,
unsigned Depth) const { unsigned Depth) const {
unsigned BitWidth = DemandedMask.getBitWidth(); unsigned BitWidth = DemandedMask.getBitWidth();
assert(Op.getValueSizeInBits() == BitWidth && assert(Op.getValueType().getScalarType().getSizeInBits() == BitWidth &&
"Mask size mismatches value type size!"); "Mask size mismatches value type size!");
APInt NewMask = DemandedMask; APInt NewMask = DemandedMask;
DebugLoc dl = Op.getDebugLoc(); DebugLoc dl = Op.getDebugLoc();
@ -1240,7 +1240,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
// demand the input sign bit. // demand the input sign bit.
APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt); APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt);
if (HighBits.intersects(NewMask)) if (HighBits.intersects(NewMask))
InDemandedMask |= APInt::getSignBit(VT.getSizeInBits()); InDemandedMask |= APInt::getSignBit(VT.getScalarType().getSizeInBits());
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask, if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask,
KnownZero, KnownOne, TLO, Depth+1)) KnownZero, KnownOne, TLO, Depth+1))

View File

@ -595,6 +595,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
setOperationAction(ISD::FP_TO_SINT, (MVT::SimpleValueType)VT, Expand); setOperationAction(ISD::FP_TO_SINT, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::UINT_TO_FP, (MVT::SimpleValueType)VT, Expand); setOperationAction(ISD::UINT_TO_FP, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::SINT_TO_FP, (MVT::SimpleValueType)VT, Expand); setOperationAction(ISD::SINT_TO_FP, (MVT::SimpleValueType)VT, Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, (MVT::SimpleValueType)VT,Expand);
} }
// FIXME: In order to prevent SSE instructions being expanded to MMX ones // FIXME: In order to prevent SSE instructions being expanded to MMX ones

View File

@ -0,0 +1,37 @@
; RUN: llc < %s -march=x86-64
define <8 x i32> @a(<8 x i32> %a) nounwind {
%b = trunc <8 x i32> %a to <8 x i16>
%c = sext <8 x i16> %b to <8 x i32>
ret <8 x i32> %c
}
define <3 x i32> @b(<3 x i32> %a) nounwind {
%b = trunc <3 x i32> %a to <3 x i16>
%c = sext <3 x i16> %b to <3 x i32>
ret <3 x i32> %c
}
define <1 x i32> @c(<1 x i32> %a) nounwind {
%b = trunc <1 x i32> %a to <1 x i16>
%c = sext <1 x i16> %b to <1 x i32>
ret <1 x i32> %c
}
define <8 x i32> @d(<8 x i32> %a) nounwind {
%b = trunc <8 x i32> %a to <8 x i16>
%c = zext <8 x i16> %b to <8 x i32>
ret <8 x i32> %c
}
define <3 x i32> @e(<3 x i32> %a) nounwind {
%b = trunc <3 x i32> %a to <3 x i16>
%c = zext <3 x i16> %b to <3 x i32>
ret <3 x i32> %c
}
define <1 x i32> @f(<1 x i32> %a) nounwind {
%b = trunc <1 x i32> %a to <1 x i16>
%c = zext <1 x i16> %b to <1 x i32>
ret <1 x i32> %c
}