bool SimplifySelectOps(SDNode *SELECT, SDValue LHS, SDValue RHS);
SDValue SimplifyBinOpWithSameOpcodeHands(SDNode *N);
- SDValue SimplifySelect(SDValue N0, SDValue N1, SDValue N2);
- SDValue SimplifySelectCC(SDValue N0, SDValue N1, SDValue N2,
- SDValue N3, ISD::CondCode CC,
- bool NotExtCompare = false);
+ SDValue SimplifySelect(DebugLoc DL, SDValue N0, SDValue N1, SDValue N2);
+ SDValue SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue N2,
+ SDValue N3, ISD::CondCode CC,
+ bool NotExtCompare = false);
SDValue SimplifySetCC(MVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond,
bool foldBooleans = true);
SDValue SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp,
SDValue ConstantFoldBIT_CONVERTofBUILD_VECTOR(SDNode *, MVT);
SDValue BuildSDIV(SDNode *N);
SDValue BuildUDIV(SDNode *N);
- SDNode *MatchRotate(SDValue LHS, SDValue RHS);
+ SDNode *MatchRotate(SDValue LHS, SDValue RHS, DebugLoc DL);
SDValue ReduceLoadWidth(SDNode *N);
SDValue GetDemandedBits(SDValue V, const APInt &Mask);
bool isAlias(SDValue Ptr1, int64_t Size1,
const Value *SrcValue1, int SrcValueOffset1,
SDValue Ptr2, int64_t Size2,
- const Value *SrcValue2, int SrcValueOffset2);
+ const Value *SrcValue2, int SrcValueOffset2) const;
/// FindAliasInfo - Extracts the relevant alias information from the memory
/// node. Returns true if the operand was a load.
bool FindAliasInfo(SDNode *N,
SDValue &Ptr, int64_t &Size,
- const Value *&SrcValue, int &SrcValueOffset);
+ const Value *&SrcValue, int &SrcValueOffset) const;
/// FindBetterChain - Walk up chain skipping non-aliasing memory nodes,
/// looking for a better chain (aliasing node.)
SDValue FindBetterChain(SDNode *N, SDValue Chain);
-
+
+ /// getShiftAmountTy - Returns a type large enough to hold any valid
+ /// shift amount - before type legalization these can be huge.
+ MVT getShiftAmountTy() {
+ return LegalTypes ? TLI.getShiftAmountTy() : TLI.getPointerTy();
+ }
+
public:
DAGCombiner(SelectionDAG &D, AliasAnalysis &A, bool fast)
: DAG(D),
// FIXME: determine better conditions for this xform.
if (!UnsafeFPMath) return 0;
- // -(A+B) -> -A - B
+ // fold (fsub (fadd A, B)) -> (fsub (fneg A), B)
if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1))
return V;
- // -(A+B) -> -B - A
+ // fold (fneg (fadd A, B)) -> (fsub (fneg B), A)
return isNegatibleForFree(Op.getOperand(1), LegalOperations, Depth+1);
case ISD::FSUB:
// We can't turn -(A-B) into B-A when we honor signed zeros.
if (!UnsafeFPMath) return 0;
- // -(A-B) -> B-A
+ // fold (fneg (fsub A, B)) -> (fsub B, A)
return 1;
case ISD::FMUL:
case ISD::FDIV:
if (HonorSignDependentRoundingFPMath()) return 0;
- // -(X*Y) -> (-X * Y) or (X*-Y)
+ // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y))
if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1))
return V;
// FIXME: determine better conditions for this xform.
assert(UnsafeFPMath);
- // -(A+B) -> -A - B
+ // fold (fneg (fadd A, B)) -> (fsub (fneg A), B)
if (isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1))
return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(),
GetNegatedExpression(Op.getOperand(0), DAG,
LegalOperations, Depth+1),
Op.getOperand(1));
- // -(A+B) -> -B - A
+ // fold (fneg (fadd A, B)) -> (fsub (fneg B), A)
return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(),
GetNegatedExpression(Op.getOperand(1), DAG,
LegalOperations, Depth+1),
// We can't turn -(A-B) into B-A when we honor signed zeros.
assert(UnsafeFPMath);
- // -(0-B) -> B
+ // fold (fneg (fsub 0, B)) -> B
if (ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(Op.getOperand(0)))
if (N0CFP->getValueAPF().isZero())
return Op.getOperand(1);
- // -(A-B) -> B-A
+ // fold (fneg (fsub A, B)) -> (fsub B, A)
return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(),
Op.getOperand(1), Op.getOperand(0));
case ISD::FDIV:
assert(!HonorSignDependentRoundingFPMath());
- // -(X*Y) -> -X * Y
+ // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y)
if (isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1))
return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(),
GetNegatedExpression(Op.getOperand(0), DAG,
LegalOperations, Depth+1),
Op.getOperand(1));
- // -(X*Y) -> X * -Y
+ // fold (fneg (fmul X, Y)) -> (fmul X, (fneg Y))
return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(),
Op.getOperand(0),
GetNegatedExpression(Op.getOperand(1), DAG,
if (N0.getOpcode() == Opc && isa<ConstantSDNode>(N0.getOperand(1))) {
if (isa<ConstantSDNode>(N1)) {
// reassoc. (op (op x, c1), c2) -> (op x, (op c1, c2))
- SDValue OpNode = DAG.getNode(Opc, N1.getDebugLoc(), VT,
- N0.getOperand(1), N1);
- AddToWorkList(OpNode.getNode());
+ SDValue OpNode =
+ DAG.FoldConstantArithmetic(Opc, VT,
+ cast<ConstantSDNode>(N0.getOperand(1)),
+ cast<ConstantSDNode>(N1));
return DAG.getNode(Opc, DL, VT, N0.getOperand(0), OpNode);
} else if (N0.hasOneUse()) {
// reassoc. (op (op x, c1), y) -> (op (op x, y), c1) iff x+c1 has one use
if (N1.getOpcode() == Opc && isa<ConstantSDNode>(N1.getOperand(1))) {
if (isa<ConstantSDNode>(N0)) {
// reassoc. (op c2, (op x, c1)) -> (op x, (op c1, c2))
- SDValue OpNode = DAG.getNode(Opc, N1.getDebugLoc(), VT,
- N1.getOperand(1), N0);
- AddToWorkList(OpNode.getNode());
+ SDValue OpNode =
+ DAG.FoldConstantArithmetic(Opc, VT,
+ cast<ConstantSDNode>(N1.getOperand(1)),
+ cast<ConstantSDNode>(N0));
return DAG.getNode(Opc, DL, VT, N1.getOperand(0), OpNode);
} else if (N1.hasOneUse()) {
// reassoc. (op y, (op x, c1)) -> (op (op x, y), c1) iff x+c1 has one use
return DAG.FoldConstantArithmetic(ISD::SUB, VT, N0C, N1C);
// fold (sub x, c) -> (add x, -c)
if (N1C)
- return DAG.getNode(ISD::ADD, VT, N0,
+ return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0,
DAG.getConstant(-N1C->getAPIntValue(), VT));
// fold (A+B)-A -> B
if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1)
(N0.getOperand(1).getOpcode() == ISD::SUB ||
N0.getOperand(1).getOpcode() == ISD::ADD) &&
N0.getOperand(1).getOperand(0) == N1)
- return DAG.getNode(N0.getOperand(1).getOpcode(), VT, N0.getOperand(0),
- N0.getOperand(1).getOperand(1));
+ return DAG.getNode(N0.getOperand(1).getOpcode(), N->getDebugLoc(), VT,
+ N0.getOperand(0), N0.getOperand(1).getOperand(1));
// fold ((A+(C+B))-B) -> A+C
if (N0.getOpcode() == ISD::ADD &&
N0.getOperand(1).getOpcode() == ISD::ADD &&
N0.getOperand(1).getOperand(1) == N1)
- return DAG.getNode(ISD::ADD, VT, N0.getOperand(0),
- N0.getOperand(1).getOperand(0));
+ return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT,
+ N0.getOperand(0), N0.getOperand(1).getOperand(0));
// fold ((A-(B-C))-C) -> A-B
if (N0.getOpcode() == ISD::SUB &&
N0.getOperand(1).getOpcode() == ISD::SUB &&
N0.getOperand(1).getOperand(1) == N1)
- return DAG.getNode(ISD::SUB, VT, N0.getOperand(0),
- N0.getOperand(1).getOperand(0));
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
+ N0.getOperand(0), N0.getOperand(1).getOperand(0));
// fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c))
if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) {
SDValue Result = combineSelectAndUse(N, N1, N0, DAG, TLI, LegalOperations);
if (Result.getNode()) return Result;
}
+
// If either operand of a sub is undef, the result is undef
if (N0.getOpcode() == ISD::UNDEF)
return N0;
return DAG.FoldConstantArithmetic(ISD::MUL, VT, N0C, N1C);
// canonicalize constant to RHS
if (N0C && !N1C)
- return DAG.getNode(ISD::MUL, VT, N1, N0);
+ return DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, N1, N0);
// fold (mul x, 0) -> 0
if (N1C && N1C->isNullValue())
return N1;
// fold (mul x, -1) -> 0-x
if (N1C && N1C->isAllOnesValue())
- return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT), N0);
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
+ DAG.getConstant(0, VT), N0);
// fold (mul x, (1 << c)) -> x << c
if (N1C && N1C->getAPIntValue().isPowerOf2())
- return DAG.getNode(ISD::SHL, VT, N0,
+ return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
DAG.getConstant(N1C->getAPIntValue().logBase2(),
- TLI.getShiftAmountTy()));
+ getShiftAmountTy()));
// fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c
- if (N1C && isPowerOf2_64(-N1C->getSExtValue())) {
+ if (N1C && isPowerOf2_64(-N1C->getSExtValue()))
// FIXME: If the input is something that is easily negated (e.g. a
// single-use add), we should put the negate there.
- return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT),
- DAG.getNode(ISD::SHL, VT, N0,
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
+ DAG.getConstant(0, VT),
+ DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
DAG.getConstant(Log2_64(-N1C->getSExtValue()),
- TLI.getShiftAmountTy())));
- }
-
+ getShiftAmountTy())));
// (mul (shl X, c1), c2) -> (mul X, c2 << c1)
- if (N1C && N0.getOpcode() == ISD::SHL &&
+ if (N1C && N0.getOpcode() == ISD::SHL &&
isa<ConstantSDNode>(N0.getOperand(1))) {
- SDValue C3 = DAG.getNode(ISD::SHL, VT, N1, N0.getOperand(1));
+ SDValue C3 = DAG.getNode(ISD::SHL, N->getDebugLoc(), VT,
+ N1, N0.getOperand(1));
AddToWorkList(C3.getNode());
- return DAG.getNode(ISD::MUL, VT, N0.getOperand(0), C3);
+ return DAG.getNode(ISD::MUL, N->getDebugLoc(), VT,
+ N0.getOperand(0), C3);
}
// Change (mul (shl X, C), Y) -> (shl (mul X, Y), C) when the shift has one
N1.getNode()->hasOneUse()) {
Sh = N1; Y = N0;
}
+
if (Sh.getNode()) {
- SDValue Mul = DAG.getNode(ISD::MUL, VT, Sh.getOperand(0), Y);
- return DAG.getNode(ISD::SHL, VT, Mul, Sh.getOperand(1));
+ SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT,
+ Sh.getOperand(0), Y);
+ return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT,
+ Mul, Sh.getOperand(1));
}
}
+
// fold (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2)
if (N1C && N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse() &&
- isa<ConstantSDNode>(N0.getOperand(1))) {
- return DAG.getNode(ISD::ADD, VT,
- DAG.getNode(ISD::MUL, VT, N0.getOperand(0), N1),
- DAG.getNode(ISD::MUL, VT, N0.getOperand(1), N1));
- }
+ isa<ConstantSDNode>(N0.getOperand(1)))
+ return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT,
+ DAG.getNode(ISD::MUL, N0.getDebugLoc(), VT,
+ N0.getOperand(0), N1),
+ DAG.getNode(ISD::MUL, N1.getDebugLoc(), VT,
+ N0.getOperand(1), N1));
// reassociate mul
SDValue RMUL = ReassociateOps(ISD::MUL, N->getDebugLoc(), N0, N1);
return N0;
// fold (sdiv X, -1) -> 0-X
if (N1C && N1C->isAllOnesValue())
- return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT), N0);
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
+ DAG.getConstant(0, VT), N0);
// If we know the sign bits of both operands are zero, strength reduce to a
// udiv instead. Handles (X&15) /s 4 -> X&15 >> 2
if (!VT.isVector()) {
if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::UDIV, N1.getValueType(), N0, N1);
+ return DAG.getNode(ISD::UDIV, N->getDebugLoc(), N1.getValueType(),
+ N0, N1);
}
// fold (sdiv X, pow2) -> simple ops after legalize
if (N1C && !N1C->isNullValue() && !TLI.isIntDivCheap() &&
// fold.
if (TLI.isPow2DivCheap())
return SDValue();
+
int64_t pow2 = N1C->getSExtValue();
int64_t abs2 = pow2 > 0 ? pow2 : -pow2;
unsigned lg2 = Log2_64(abs2);
+
// Splat the sign bit into the register
- SDValue SGN = DAG.getNode(ISD::SRA, VT, N0,
- DAG.getConstant(VT.getSizeInBits()-1,
- TLI.getShiftAmountTy()));
+ SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0,
+ DAG.getConstant(VT.getSizeInBits()-1,
+ getShiftAmountTy()));
AddToWorkList(SGN.getNode());
+
// Add (N0 < 0) ? abs2 - 1 : 0;
- SDValue SRL = DAG.getNode(ISD::SRL, VT, SGN,
- DAG.getConstant(VT.getSizeInBits()-lg2,
- TLI.getShiftAmountTy()));
- SDValue ADD = DAG.getNode(ISD::ADD, VT, N0, SRL);
+ SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN,
+ DAG.getConstant(VT.getSizeInBits() - lg2,
+ getShiftAmountTy()));
+ SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL);
AddToWorkList(SRL.getNode());
AddToWorkList(ADD.getNode()); // Divide by pow2
- SDValue SRA = DAG.getNode(ISD::SRA, VT, ADD,
- DAG.getConstant(lg2, TLI.getShiftAmountTy()));
+ SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD,
+ DAG.getConstant(lg2, getShiftAmountTy()));
+
// If we're dividing by a positive value, we're done. Otherwise, we must
// negate the result.
if (pow2 > 0)
return SRA;
+
AddToWorkList(SRA.getNode());
- return DAG.getNode(ISD::SUB, VT, DAG.getConstant(0, VT), SRA);
+ return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
+ DAG.getConstant(0, VT), SRA);
}
+
// if integer divide is expensive and we satisfy the requirements, emit an
// alternate sequence.
if (N1C && (N1C->getSExtValue() < -1 || N1C->getSExtValue() > 1) &&
return DAG.FoldConstantArithmetic(ISD::UDIV, VT, N0C, N1C);
// fold (udiv x, (1 << c)) -> x >>u c
if (N1C && N1C->getAPIntValue().isPowerOf2())
- return DAG.getNode(ISD::SRL, VT, N0,
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0,
DAG.getConstant(N1C->getAPIntValue().logBase2(),
- TLI.getShiftAmountTy()));
+ getShiftAmountTy()));
// fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2
if (N1.getOpcode() == ISD::SHL) {
if (ConstantSDNode *SHC = dyn_cast<ConstantSDNode>(N1.getOperand(0))) {
if (SHC->getAPIntValue().isPowerOf2()) {
MVT ADDVT = N1.getOperand(1).getValueType();
- SDValue Add = DAG.getNode(ISD::ADD, ADDVT, N1.getOperand(1),
- DAG.getConstant(SHC->getAPIntValue()
- .logBase2(),
- ADDVT));
+ SDValue Add = DAG.getNode(ISD::ADD, N->getDebugLoc(), ADDVT,
+ N1.getOperand(1),
+ DAG.getConstant(SHC->getAPIntValue()
+ .logBase2(),
+ ADDVT));
AddToWorkList(Add.getNode());
- return DAG.getNode(ISD::SRL, VT, N0, Add);
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, Add);
}
}
}
// urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15
if (!VT.isVector()) {
if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::UREM, VT, N0, N1);
+ return DAG.getNode(ISD::UREM, N->getDebugLoc(), VT, N0, N1);
}
// If X/C can be simplified by the division-by-constant logic, lower
// X%C to the equivalent of X-X/C*C.
if (N1C && !N1C->isNullValue()) {
- SDValue Div = DAG.getNode(ISD::SDIV, VT, N0, N1);
+ SDValue Div = DAG.getNode(ISD::SDIV, N->getDebugLoc(), VT, N0, N1);
AddToWorkList(Div.getNode());
SDValue OptimizedDiv = combine(Div.getNode());
if (OptimizedDiv.getNode() && OptimizedDiv.getNode() != Div.getNode()) {
- SDValue Mul = DAG.getNode(ISD::MUL, VT, OptimizedDiv, N1);
- SDValue Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
+ SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT,
+ OptimizedDiv, N1);
+ SDValue Sub = DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, Mul);
AddToWorkList(Mul.getNode());
return Sub;
}
return DAG.FoldConstantArithmetic(ISD::UREM, VT, N0C, N1C);
// fold (urem x, pow2) -> (and x, pow2-1)
if (N1C && !N1C->isNullValue() && N1C->getAPIntValue().isPowerOf2())
- return DAG.getNode(ISD::AND, VT, N0,
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0,
DAG.getConstant(N1C->getAPIntValue()-1,VT));
// fold (urem x, (shl pow2, y)) -> (and x, (add (shl pow2, y), -1))
if (N1.getOpcode() == ISD::SHL) {
if (ConstantSDNode *SHC = dyn_cast<ConstantSDNode>(N1.getOperand(0))) {
if (SHC->getAPIntValue().isPowerOf2()) {
SDValue Add =
- DAG.getNode(ISD::ADD, VT, N1,
+ DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1,
DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()),
VT));
AddToWorkList(Add.getNode());
- return DAG.getNode(ISD::AND, VT, N0, Add);
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, Add);
}
}
}
// If X/C can be simplified by the division-by-constant logic, lower
// X%C to the equivalent of X-X/C*C.
if (N1C && !N1C->isNullValue()) {
- SDValue Div = DAG.getNode(ISD::UDIV, VT, N0, N1);
+ SDValue Div = DAG.getNode(ISD::UDIV, N->getDebugLoc(), VT, N0, N1);
AddToWorkList(Div.getNode());
SDValue OptimizedDiv = combine(Div.getNode());
if (OptimizedDiv.getNode() && OptimizedDiv.getNode() != Div.getNode()) {
- SDValue Mul = DAG.getNode(ISD::MUL, VT, OptimizedDiv, N1);
- SDValue Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
+ SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT,
+ OptimizedDiv, N1);
+ SDValue Sub = DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, Mul);
AddToWorkList(Mul.getNode());
return Sub;
}
return N1;
// fold (mulhs x, 1) -> (sra x, size(x)-1)
if (N1C && N1C->getAPIntValue() == 1)
- return DAG.getNode(ISD::SRA, N0.getValueType(), N0,
- DAG.getConstant(N0.getValueType().getSizeInBits()-1,
- TLI.getShiftAmountTy()));
+ return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0,
+ DAG.getConstant(N0.getValueType().getSizeInBits() - 1,
+ getShiftAmountTy()));
// fold (mulhs x, undef) -> 0
if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF)
return DAG.getConstant(0, VT);
if (!HiExists &&
(!LegalOperations ||
TLI.isOperationLegal(LoOp, N->getValueType(0)))) {
- SDValue Res = DAG.getNode(LoOp, N->getValueType(0), N->op_begin(),
- N->getNumOperands());
+ SDValue Res = DAG.getNode(LoOp, N->getDebugLoc(), N->getValueType(0),
+ N->op_begin(), N->getNumOperands());
return CombineTo(N, Res, Res);
}
if (!LoExists &&
(!LegalOperations ||
TLI.isOperationLegal(HiOp, N->getValueType(1)))) {
- SDValue Res = DAG.getNode(HiOp, N->getValueType(1), N->op_begin(),
- N->getNumOperands());
+ SDValue Res = DAG.getNode(HiOp, N->getDebugLoc(), N->getValueType(1),
+ N->op_begin(), N->getNumOperands());
return CombineTo(N, Res, Res);
}
// If the two computed results can be simplified separately, separate them.
if (LoExists) {
- SDValue Lo = DAG.getNode(LoOp, N->getValueType(0),
- N->op_begin(), N->getNumOperands());
+ SDValue Lo = DAG.getNode(LoOp, N->getDebugLoc(), N->getValueType(0),
+ N->op_begin(), N->getNumOperands());
AddToWorkList(Lo.getNode());
SDValue LoOpt = combine(Lo.getNode());
if (LoOpt.getNode() && LoOpt.getNode() != Lo.getNode() &&
}
if (HiExists) {
- SDValue Hi = DAG.getNode(HiOp, N->getValueType(1),
+ SDValue Hi = DAG.getNode(HiOp, N->getDebugLoc(), N->getValueType(1),
N->op_begin(), N->getNumOperands());
AddToWorkList(Hi.getNode());
SDValue HiOpt = combine(Hi.getNode());
TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())))
return CombineTo(N, HiOpt, HiOpt);
}
+
return SDValue();
}
if ((N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND||
N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::TRUNCATE) &&
N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
- SDValue ORNode = DAG.getNode(N->getOpcode(),
- N0.getOperand(0).getValueType(),
- N0.getOperand(0), N1.getOperand(0));
+ SDValue ORNode = DAG.getNode(N->getOpcode(), N0.getDebugLoc(),
+ N0.getOperand(0).getValueType(),
+ N0.getOperand(0), N1.getOperand(0));
AddToWorkList(ORNode.getNode());
- return DAG.getNode(N0.getOpcode(), VT, ORNode);
+ return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, ORNode);
}
// For each of OP in SHL/SRL/SRA/AND...
if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL ||
N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::AND) &&
N0.getOperand(1) == N1.getOperand(1)) {
- SDValue ORNode = DAG.getNode(N->getOpcode(),
- N0.getOperand(0).getValueType(),
- N0.getOperand(0), N1.getOperand(0));
+ SDValue ORNode = DAG.getNode(N->getOpcode(), N0.getDebugLoc(),
+ N0.getOperand(0).getValueType(),
+ N0.getOperand(0), N1.getOperand(0));
AddToWorkList(ORNode.getNode());
- return DAG.getNode(N0.getOpcode(), VT, ORNode, N0.getOperand(1));
+ return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT,
+ ORNode, N0.getOperand(1));
}
return SDValue();
APInt Mask = ~N1C->getAPIntValue();
Mask.trunc(N0Op0.getValueSizeInBits());
if (DAG.MaskedValueIsZero(N0Op0, Mask)) {
- SDValue Zext = DAG.getNode(ISD::ZERO_EXTEND, N0.getValueType(),
- N0Op0);
+ SDValue Zext = DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(),
+ N0.getValueType(), N0Op0);
// Replace uses of the AND with uses of the Zero extend node.
CombineTo(N, Zext);
if (LR == RR && isa<ConstantSDNode>(LR) && Op0 == Op1 &&
LL.getValueType().isInteger()) {
- // fold (X == 0) & (Y == 0) -> (X|Y == 0)
+ // fold (and (seteq X, 0), (seteq Y, 0)) -> (seteq (or X, Y), 0)
if (cast<ConstantSDNode>(LR)->isNullValue() && Op1 == ISD::SETEQ) {
- SDValue ORNode = DAG.getNode(ISD::OR, LR.getValueType(), LL, RL);
+ SDValue ORNode = DAG.getNode(ISD::OR, N0.getDebugLoc(),
+ LR.getValueType(), LL, RL);
AddToWorkList(ORNode.getNode());
- return DAG.getSetCC(VT, ORNode, LR, Op1);
+ return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1);
}
- // fold (X == -1) & (Y == -1) -> (X&Y == -1)
+ // fold (and (seteq X, -1), (seteq Y, -1)) -> (seteq (and X, Y), -1)
if (cast<ConstantSDNode>(LR)->isAllOnesValue() && Op1 == ISD::SETEQ) {
- SDValue ANDNode = DAG.getNode(ISD::AND, LR.getValueType(), LL, RL);
+ SDValue ANDNode = DAG.getNode(ISD::AND, N0.getDebugLoc(),
+ LR.getValueType(), LL, RL);
AddToWorkList(ANDNode.getNode());
- return DAG.getSetCC(VT, ANDNode, LR, Op1);
+ return DAG.getSetCC(N->getDebugLoc(), VT, ANDNode, LR, Op1);
}
- // fold (X > -1) & (Y > -1) -> (X|Y > -1)
+ // fold (and (setgt X, -1), (setgt Y, -1)) -> (setgt (or X, Y), -1)
if (cast<ConstantSDNode>(LR)->isAllOnesValue() && Op1 == ISD::SETGT) {
- SDValue ORNode = DAG.getNode(ISD::OR, LR.getValueType(), LL, RL);
+ SDValue ORNode = DAG.getNode(ISD::OR, N0.getDebugLoc(),
+ LR.getValueType(), LL, RL);
AddToWorkList(ORNode.getNode());
- return DAG.getSetCC(VT, ORNode, LR, Op1);
+ return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1);
}
}
// canonicalize equivalent to ll == rl
ISD::CondCode Result = ISD::getSetCCAndOperation(Op0, Op1, isInteger);
if (Result != ISD::SETCC_INVALID &&
(!LegalOperations || TLI.isCondCodeLegal(Result, LL.getValueType())))
- return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
+ return DAG.getSetCC(N->getDebugLoc(), N0.getValueType(),
+ LL, LR, Result);
}
}
- // Simplify: and (op x...), (op y...) -> (op (and x, y))
+ // Simplify: (and (op x...), (op y...)) -> (op (and x, y))
if (N0.getOpcode() == N1.getOpcode()) {
SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N);
if (Tmp.getNode()) return Tmp;
BitWidth - EVT.getSizeInBits())) &&
((!LegalOperations && !LN0->isVolatile()) ||
TLI.isLoadExtLegal(ISD::ZEXTLOAD, EVT))) {
- SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
- LN0->getBasePtr(), LN0->getSrcValue(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT,
+ LN0->getChain(), LN0->getBasePtr(),
+ LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
AddToWorkList(N);
BitWidth - EVT.getSizeInBits())) &&
((!LegalOperations && !LN0->isVolatile()) ||
TLI.isLoadExtLegal(ISD::ZEXTLOAD, EVT))) {
- SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
EVT = MVT::getIntegerVT(ActiveBits);
MVT LoadedVT = LN0->getMemoryVT();
+
// Do not generate loads of non-round integer types since these can
// be expensive (and would be wrong if the type is not byte sized).
if (EVT != MVT::Other && LoadedVT.bitsGT(EVT) && EVT.isRound() &&
(!LegalOperations || TLI.isLoadExtLegal(ISD::ZEXTLOAD, EVT))) {
MVT PtrType = N0.getOperand(1).getValueType();
+
// For big endian targets, we need to add an offset to the pointer to
// load the correct bytes. For little endian systems, we merely need to
// read fewer bytes from the same pointer.
unsigned PtrOff = LVTStoreBytes - EVTStoreBytes;
unsigned Alignment = LN0->getAlignment();
SDValue NewPtr = LN0->getBasePtr();
+
if (TLI.isBigEndian()) {
- NewPtr = DAG.getNode(ISD::ADD, PtrType, NewPtr,
- DAG.getConstant(PtrOff, PtrType));
+ NewPtr = DAG.getNode(ISD::ADD, LN0->getDebugLoc(), PtrType,
+ NewPtr, DAG.getConstant(PtrOff, PtrType));
Alignment = MinAlign(Alignment, PtrOff);
}
+
AddToWorkList(NewPtr.getNode());
SDValue Load =
- DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(), NewPtr,
- LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
- LN0->isVolatile(), Alignment);
+ DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), VT, LN0->getChain(),
+ NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset(),
+ EVT, LN0->isVolatile(), Alignment);
AddToWorkList(N);
CombineTo(N0.getNode(), Load, Load.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
return DAG.FoldConstantArithmetic(ISD::OR, VT, N0C, N1C);
// canonicalize constant to RHS
if (N0C && !N1C)
- return DAG.getNode(ISD::OR, VT, N1, N0);
+ return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N1, N0);
// fold (or x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
if (N1C && N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() &&
isa<ConstantSDNode>(N0.getOperand(1))) {
ConstantSDNode *C1 = cast<ConstantSDNode>(N0.getOperand(1));
- return DAG.getNode(ISD::AND, VT, DAG.getNode(ISD::OR, VT, N0.getOperand(0),
- N1),
- DAG.getConstant(N1C->getAPIntValue() |
- C1->getAPIntValue(), VT));
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT,
+ DAG.getNode(ISD::OR, N0.getDebugLoc(), VT,
+ N0.getOperand(0), N1),
+ DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1));
}
// fold (or (setcc x), (setcc y)) -> (setcc (or x, y))
if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){
if (LR == RR && isa<ConstantSDNode>(LR) && Op0 == Op1 &&
LL.getValueType().isInteger()) {
- // fold (X != 0) | (Y != 0) -> (X|Y != 0)
- // fold (X < 0) | (Y < 0) -> (X|Y < 0)
+ // fold (or (setne X, 0), (setne Y, 0)) -> (setne (or X, Y), 0)
+ // fold (or (setlt X, 0), (setlt Y, 0)) -> (setne (or X, Y), 0)
if (cast<ConstantSDNode>(LR)->isNullValue() &&
(Op1 == ISD::SETNE || Op1 == ISD::SETLT)) {
- SDValue ORNode = DAG.getNode(ISD::OR, LR.getValueType(), LL, RL);
+ SDValue ORNode = DAG.getNode(ISD::OR, LR.getDebugLoc(),
+ LR.getValueType(), LL, RL);
AddToWorkList(ORNode.getNode());
- return DAG.getSetCC(VT, ORNode, LR, Op1);
+ return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1);
}
- // fold (X != -1) | (Y != -1) -> (X&Y != -1)
- // fold (X > -1) | (Y > -1) -> (X&Y > -1)
+ // fold (or (setne X, -1), (setne Y, -1)) -> (setne (and X, Y), -1)
+ // fold (or (setgt X, -1), (setgt Y -1)) -> (setgt (and X, Y), -1)
if (cast<ConstantSDNode>(LR)->isAllOnesValue() &&
(Op1 == ISD::SETNE || Op1 == ISD::SETGT)) {
- SDValue ANDNode = DAG.getNode(ISD::AND, LR.getValueType(), LL, RL);
+ SDValue ANDNode = DAG.getNode(ISD::AND, LR.getDebugLoc(),
+ LR.getValueType(), LL, RL);
AddToWorkList(ANDNode.getNode());
- return DAG.getSetCC(VT, ANDNode, LR, Op1);
+ return DAG.getSetCC(N->getDebugLoc(), VT, ANDNode, LR, Op1);
}
}
// canonicalize equivalent to ll == rl
ISD::CondCode Result = ISD::getSetCCOrOperation(Op0, Op1, isInteger);
if (Result != ISD::SETCC_INVALID &&
(!LegalOperations || TLI.isCondCodeLegal(Result, LL.getValueType())))
- return DAG.getSetCC(N0.getValueType(), LL, LR, Result);
+ return DAG.getSetCC(N->getDebugLoc(), N0.getValueType(),
+ LL, LR, Result);
}
}
- // Simplify: or (op x...), (op y...) -> (op (or x, y))
+ // Simplify: (or (op x...), (op y...)) -> (op (or x, y))
if (N0.getOpcode() == N1.getOpcode()) {
SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N);
if (Tmp.getNode()) return Tmp;
}
- // (X & C1) | (Y & C2) -> (X|Y) & C3 if possible.
+ // (or (and X, C1), (and Y, C2)) -> (and (or X, Y), C3) if possible.
if (N0.getOpcode() == ISD::AND &&
N1.getOpcode() == ISD::AND &&
N0.getOperand(1).getOpcode() == ISD::Constant &&
if (DAG.MaskedValueIsZero(N0.getOperand(0), RHSMask&~LHSMask) &&
DAG.MaskedValueIsZero(N1.getOperand(0), LHSMask&~RHSMask)) {
- SDValue X =DAG.getNode(ISD::OR, VT, N0.getOperand(0), N1.getOperand(0));
- return DAG.getNode(ISD::AND, VT, X, DAG.getConstant(LHSMask|RHSMask, VT));
+ SDValue X = DAG.getNode(ISD::OR, N0.getDebugLoc(), VT,
+ N0.getOperand(0), N1.getOperand(0));
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, X,
+ DAG.getConstant(LHSMask | RHSMask, VT));
}
}
-
// See if this is some rotate idiom.
- if (SDNode *Rot = MatchRotate(N0, N1))
+ if (SDNode *Rot = MatchRotate(N0, N1, N->getDebugLoc()))
return SDValue(Rot, 0);
return SDValue();
}
-
/// MatchRotateHalf - Match "(X shl/srl V1) & V2" where V2 may not be present.
static bool MatchRotateHalf(SDValue Op, SDValue &Shift, SDValue &Mask) {
if (Op.getOpcode() == ISD::AND) {
Shift = Op;
return true;
}
+
return false;
}
-
// MatchRotate - Handle an 'or' of two operands. If this is one of the many
// idioms for rotate, and if the target supports rotation instructions, generate
// a rot[lr].
-SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS) {
+SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, DebugLoc DL) {
// Must be a legal type. Expanded 'n promoted things won't work with rotates.
MVT VT = LHS.getValueType();
if (!TLI.isTypeLegal(VT)) return 0;
SDValue Rot;
if (HasROTL)
- Rot = DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt);
+ Rot = DAG.getNode(ISD::ROTL, DL, VT, LHSShiftArg, LHSShiftAmt);
else
- Rot = DAG.getNode(ISD::ROTR, VT, LHSShiftArg, RHSShiftAmt);
+ Rot = DAG.getNode(ISD::ROTR, DL, VT, LHSShiftArg, RHSShiftAmt);
// If there is an AND of either shifted operand, apply it to the result.
if (LHSMask.getNode() || RHSMask.getNode()) {
Mask &= cast<ConstantSDNode>(RHSMask)->getAPIntValue() | LHSBits;
}
- Rot = DAG.getNode(ISD::AND, VT, Rot, DAG.getConstant(Mask, VT));
+ Rot = DAG.getNode(ISD::AND, DL, VT, Rot, DAG.getConstant(Mask, VT));
}
return Rot.getNode();
dyn_cast<ConstantSDNode>(RHSShiftAmt.getOperand(0))) {
if (SUBC->getAPIntValue() == OpSizeInBits) {
if (HasROTL)
- return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt).getNode();
+ return DAG.getNode(ISD::ROTL, DL, VT,
+ LHSShiftArg, LHSShiftAmt).getNode();
else
- return DAG.getNode(ISD::ROTR, VT, LHSShiftArg, RHSShiftAmt).getNode();
+ return DAG.getNode(ISD::ROTR, DL, VT,
+ LHSShiftArg, RHSShiftAmt).getNode();
}
}
}
dyn_cast<ConstantSDNode>(LHSShiftAmt.getOperand(0))) {
if (SUBC->getAPIntValue() == OpSizeInBits) {
if (HasROTR)
- return DAG.getNode(ISD::ROTR, VT, LHSShiftArg, RHSShiftAmt).getNode();
+ return DAG.getNode(ISD::ROTR, DL, VT,
+ LHSShiftArg, RHSShiftAmt).getNode();
else
- return DAG.getNode(ISD::ROTL, VT, LHSShiftArg, LHSShiftAmt).getNode();
+ return DAG.getNode(ISD::ROTL, DL, VT,
+ LHSShiftArg, LHSShiftAmt).getNode();
}
}
}
if (ConstantSDNode *SUBC =
dyn_cast<ConstantSDNode>(RExtOp0.getOperand(0))) {
if (SUBC->getAPIntValue() == OpSizeInBits) {
- return DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, VT, LHSShiftArg,
+ return DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, VT,
+ LHSShiftArg,
HasROTL ? LHSShiftAmt : RHSShiftAmt).getNode();
}
}
if (ConstantSDNode *SUBC =
dyn_cast<ConstantSDNode>(LExtOp0.getOperand(0))) {
if (SUBC->getAPIntValue() == OpSizeInBits) {
- return DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, VT, LHSShiftArg,
+ return DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, VT,
+ LHSShiftArg,
HasROTR ? RHSShiftAmt : LHSShiftAmt).getNode();
}
}
return 0;
}
-
SDValue DAGCombiner::visitXOR(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
return DAG.FoldConstantArithmetic(ISD::XOR, VT, N0C, N1C);
// canonicalize constant to RHS
if (N0C && !N1C)
- return DAG.getNode(ISD::XOR, VT, N1, N0);
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N1, N0);
// fold (xor x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
assert(0 && "Unhandled SetCC Equivalent!");
abort();
case ISD::SETCC:
- return DAG.getSetCC(VT, LHS, RHS, NotCC);
+ return DAG.getSetCC(N->getDebugLoc(), VT, LHS, RHS, NotCC);
case ISD::SELECT_CC:
- return DAG.getSelectCC(LHS, RHS, N0.getOperand(2),
+ return DAG.getSelectCC(N->getDebugLoc(), LHS, RHS, N0.getOperand(2),
N0.getOperand(3), NotCC);
}
}
N0.getNode()->hasOneUse() &&
isSetCCEquivalent(N0.getOperand(0), LHS, RHS, CC)){
SDValue V = N0.getOperand(0);
- V = DAG.getNode(ISD::XOR, V.getValueType(), V,
+ V = DAG.getNode(ISD::XOR, N0.getDebugLoc(), V.getValueType(), V,
DAG.getConstant(1, V.getValueType()));
AddToWorkList(V.getNode());
- return DAG.getNode(ISD::ZERO_EXTEND, VT, V);
+ return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, V);
}
- // fold !(x or y) -> (!x and !y) iff x or y are setcc
+ // fold (not (or x, y)) -> (and (not x), (not y)) iff x or y are setcc
if (N1C && N1C->getAPIntValue() == 1 && VT == MVT::i1 &&
(N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) {
SDValue LHS = N0.getOperand(0), RHS = N0.getOperand(1);
if (isOneUseSetCC(RHS) || isOneUseSetCC(LHS)) {
unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND;
- LHS = DAG.getNode(ISD::XOR, VT, LHS, N1); // RHS = ~LHS
- RHS = DAG.getNode(ISD::XOR, VT, RHS, N1); // RHS = ~RHS
+ LHS = DAG.getNode(ISD::XOR, LHS.getDebugLoc(), VT, LHS, N1); // LHS = ~LHS
+ RHS = DAG.getNode(ISD::XOR, RHS.getDebugLoc(), VT, RHS, N1); // RHS = ~RHS
AddToWorkList(LHS.getNode()); AddToWorkList(RHS.getNode());
- return DAG.getNode(NewOpcode, VT, LHS, RHS);
+ return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS);
}
}
- // fold !(x or y) -> (!x and !y) iff x or y are constants
+ // fold (not (or x, y)) -> (and (not x), (not y)) iff x or y are constants
if (N1C && N1C->isAllOnesValue() &&
(N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) {
SDValue LHS = N0.getOperand(0), RHS = N0.getOperand(1);
if (isa<ConstantSDNode>(RHS) || isa<ConstantSDNode>(LHS)) {
unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND;
- LHS = DAG.getNode(ISD::XOR, VT, LHS, N1); // RHS = ~LHS
- RHS = DAG.getNode(ISD::XOR, VT, RHS, N1); // RHS = ~RHS
+ LHS = DAG.getNode(ISD::XOR, LHS.getDebugLoc(), VT, LHS, N1); // LHS = ~LHS
+ RHS = DAG.getNode(ISD::XOR, RHS.getDebugLoc(), VT, RHS, N1); // RHS = ~RHS
AddToWorkList(LHS.getNode()); AddToWorkList(RHS.getNode());
- return DAG.getNode(NewOpcode, VT, LHS, RHS);
+ return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS);
}
}
- // fold (xor (xor x, c1), c2) -> (xor x, c1^c2)
+ // fold (xor (xor x, c1), c2) -> (xor x, (xor c1, c2))
if (N1C && N0.getOpcode() == ISD::XOR) {
ConstantSDNode *N00C = dyn_cast<ConstantSDNode>(N0.getOperand(0));
ConstantSDNode *N01C = dyn_cast<ConstantSDNode>(N0.getOperand(1));
if (N00C)
- return DAG.getNode(ISD::XOR, VT, N0.getOperand(1),
- DAG.getConstant(N1C->getAPIntValue()^
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N0.getOperand(1),
+ DAG.getConstant(N1C->getAPIntValue() ^
N00C->getAPIntValue(), VT));
if (N01C)
- return DAG.getNode(ISD::XOR, VT, N0.getOperand(0),
- DAG.getConstant(N1C->getAPIntValue()^
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N0.getOperand(0),
+ DAG.getConstant(N1C->getAPIntValue() ^
N01C->getAPIntValue(), VT));
}
// fold (xor x, x) -> 0
// Produce a vector of zeros.
SDValue El = DAG.getConstant(0, VT.getVectorElementType());
std::vector<SDValue> Ops(VT.getVectorNumElements(), El);
- return DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], Ops.size());
+ return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT,
+ &Ops[0], Ops.size());
}
}
// We require the RHS of the binop to be a constant as well.
ConstantSDNode *BinOpCst = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
if (!BinOpCst) return SDValue();
-
-
- // FIXME: disable this for unless the input to the binop is a shift by a
- // constant. If it is not a shift, it pessimizes some common cases like:
+
+ // FIXME: disable this unless the input to the binop is a shift by a constant.
+ // If it is not a shift, it pessimizes some common cases like:
//
- //void foo(int *X, int i) { X[i & 1235] = 1; }
- //int bar(int *X, int i) { return X[i & 255]; }
+ // void foo(int *X, int i) { X[i & 1235] = 1; }
+ // int bar(int *X, int i) { return X[i & 255]; }
SDNode *BinOpLHSVal = LHS->getOperand(0).getNode();
if ((BinOpLHSVal->getOpcode() != ISD::SHL &&
BinOpLHSVal->getOpcode() != ISD::SRA &&
MVT VT = N->getValueType(0);
- // If this is a signed shift right, and the high bit is modified
- // by the logical operation, do not perform the transformation.
- // The highBitSet boolean indicates the value of the high bit of
- // the constant which would cause it to be modified for this
- // operation.
+ // If this is a signed shift right, and the high bit is modified by the
+ // logical operation, do not perform the transformation. The highBitSet
+ // boolean indicates the value of the high bit of the constant which would
+ // cause it to be modified for this operation.
if (N->getOpcode() == ISD::SRA) {
bool BinOpRHSSignSet = BinOpCst->getAPIntValue().isNegative();
if (BinOpRHSSignSet != HighBitSet)
}
// Fold the constants, shifting the binop RHS by the shift amount.
- SDValue NewRHS = DAG.getNode(N->getOpcode(), N->getValueType(0),
- LHS->getOperand(1), N->getOperand(1));
+ SDValue NewRHS = DAG.getNode(N->getOpcode(), LHS->getOperand(1).getDebugLoc(),
+ N->getValueType(0),
+ LHS->getOperand(1), N->getOperand(1));
// Create the new shift.
- SDValue NewShift = DAG.getNode(N->getOpcode(), VT, LHS->getOperand(0),
- N->getOperand(1));
+ SDValue NewShift = DAG.getNode(N->getOpcode(), LHS->getOperand(0).getDebugLoc(),
+ VT, LHS->getOperand(0), N->getOperand(1));
// Create the new binop.
- return DAG.getNode(LHS->getOpcode(), VT, NewShift, NewRHS);
+ return DAG.getNode(LHS->getOpcode(), N->getDebugLoc(), VT, NewShift, NewRHS);
}
-
SDValue DAGCombiner::visitSHL(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
return N0;
// fold (shl x, c >= size(x)) -> undef
if (N1C && N1C->getZExtValue() >= OpSizeInBits)
- return DAG.getNode(ISD::UNDEF, VT);
+ return DAG.getNode(ISD::UNDEF, N->getDebugLoc(), VT);
// fold (shl x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
SDValue N100 = N1.getOperand(0).getOperand(0);
uint64_t TruncC = TruncVT.getIntegerVTBitMask() &
N101C->getZExtValue();
- return DAG.getNode(ISD::SHL, VT, N0,
+ return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
DAG.getNode(ISD::AND, TruncVT,
DAG.getNode(ISD::TRUNCATE, TruncVT, N100),
DAG.getConstant(TruncC, TruncVT)));
if (N1C && SimplifyDemandedBits(SDValue(N, 0)))
return SDValue(N, 0);
- // fold (shl (shl x, c1), c2) -> 0 or (shl x, c1+c2)
+
+ // fold (shl (shl x, c1), c2) -> 0 or (shl x, (add c1, c2))
if (N1C && N0.getOpcode() == ISD::SHL &&
N0.getOperand(1).getOpcode() == ISD::Constant) {
uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
uint64_t c2 = N1C->getZExtValue();
if (c1 + c2 > OpSizeInBits)
return DAG.getConstant(0, VT);
- return DAG.getNode(ISD::SHL, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getConstant(c1 + c2, N1.getValueType()));
}
- // fold (shl (srl x, c1), c2) -> (shl (and x, -1 << c1), c2-c1) or
- // (srl (and x, -1 << c1), c1-c2)
+ // fold (shl (srl x, c1), c2) -> (shl (and x, (shl -1, c1)), (sub c2, c1)) or
+ // (srl (and x, (shl -1, c1)), (sub c1, c2))
if (N1C && N0.getOpcode() == ISD::SRL &&
N0.getOperand(1).getOpcode() == ISD::Constant) {
uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
uint64_t c2 = N1C->getZExtValue();
- SDValue Mask = DAG.getNode(ISD::AND, VT, N0.getOperand(0),
- DAG.getConstant(~0ULL << c1, VT));
+ SDValue Mask = DAG.getNode(ISD::AND, N0.getDebugLoc(), VT, N0.getOperand(0),
+ DAG.getConstant(~0ULL << c1, VT));
if (c2 > c1)
- return DAG.getNode(ISD::SHL, VT, Mask,
+ return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, Mask,
DAG.getConstant(c2-c1, N1.getValueType()));
else
- return DAG.getNode(ISD::SRL, VT, Mask,
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, Mask,
DAG.getConstant(c1-c2, N1.getValueType()));
}
- // fold (shl (sra x, c1), c1) -> (and x, -1 << c1)
+ // fold (shl (sra x, c1), c1) -> (and x, (shl -1, c1))
if (N1C && N0.getOpcode() == ISD::SRA && N1 == N0.getOperand(1))
- return DAG.getNode(ISD::AND, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getConstant(~0ULL << N1C->getZExtValue(), VT));
return N1C ? visitShiftByConstant(N, N1C->getZExtValue()) : SDValue();
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
MVT VT = N0.getValueType();
- // fold (sra c1, c2) -> c1>>c2
+ // fold (sra c1, c2) -> (sra c1, c2)
if (N0C && N1C)
return DAG.FoldConstantArithmetic(ISD::SRA, VT, N0C, N1C);
// fold (sra 0, x) -> 0
// fold (sra -1, x) -> -1
if (N0C && N0C->isAllOnesValue())
return N0;
- // fold (sra x, c >= size(x)) -> undef
+ // fold (sra x, (setge c, size(x))) -> undef
if (N1C && N1C->getZExtValue() >= VT.getSizeInBits())
- return DAG.getNode(ISD::UNDEF, VT);
+ return DAG.getNode(ISD::UNDEF, N->getDebugLoc(), VT);
// fold (sra x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
unsigned LowBits = VT.getSizeInBits() - (unsigned)N1C->getZExtValue();
MVT EVT = MVT::getIntegerVT(LowBits);
if ((!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, EVT)))
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0.getOperand(0),
- DAG.getValueType(EVT));
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT,
+ N0.getOperand(0), DAG.getValueType(EVT));
}
- // fold (sra (sra x, c1), c2) -> (sra x, c1+c2)
+ // fold (sra (sra x, c1), c2) -> (sra x, (add c1, c2))
if (N1C && N0.getOpcode() == ISD::SRA) {
if (ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
unsigned Sum = N1C->getZExtValue() + C1->getZExtValue();
if (Sum >= VT.getSizeInBits()) Sum = VT.getSizeInBits()-1;
- return DAG.getNode(ISD::SRA, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getConstant(Sum, N1C->getValueType(0)));
}
}
- // fold sra (shl X, m), result_size - n
- // -> (sign_extend (trunc (shl X, result_size - n - m))) for
+ // fold (sra (shl X, m), (sub result_size, n))
+ // -> (sign_extend (trunc (shl X, (sub (sub result_size, n), m)))) for
// result_size - n != m.
// If truncate is free for the target sext(shl) is likely to result in better
// code.
TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) &&
TLI.isTruncateFree(VT, TruncVT)) {
- SDValue Amt = DAG.getConstant(ShiftAmt, TLI.getShiftAmountTy());
- SDValue Shift = DAG.getNode(ISD::SRL, VT, N0.getOperand(0), Amt);
- SDValue Trunc = DAG.getNode(ISD::TRUNCATE, TruncVT, Shift);
- return DAG.getNode(ISD::SIGN_EXTEND, N->getValueType(0), Trunc);
+ SDValue Amt = DAG.getConstant(ShiftAmt, getShiftAmountTy());
+ SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT,
+ N0.getOperand(0), Amt);
+ SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT,
+ Shift);
+ return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(),
+ N->getValueType(0), Trunc);
}
}
}
SDValue N100 = N1.getOperand(0).getOperand(0);
uint64_t TruncC = TruncVT.getIntegerVTBitMask() &
N101C->getZExtValue();
- return DAG.getNode(ISD::SRA, VT, N0,
- DAG.getNode(ISD::AND, TruncVT,
- DAG.getNode(ISD::TRUNCATE, TruncVT, N100),
+ return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0,
+ DAG.getNode(ISD::AND, N->getDebugLoc(),
+ TruncVT,
+ DAG.getNode(ISD::TRUNCATE,
+ N->getDebugLoc(),
+ TruncVT, N100),
DAG.getConstant(TruncC, TruncVT)));
}
}
// If the sign bit is known to be zero, switch this to a SRL.
if (DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::SRL, VT, N0, N1);
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, N1);
return N1C ? visitShiftByConstant(N, N1C->getZExtValue()) : SDValue();
}
return N0;
// fold (srl x, c >= size(x)) -> undef
if (N1C && N1C->getZExtValue() >= OpSizeInBits)
- return DAG.getNode(ISD::UNDEF, VT);
+ return DAG.getNode(ISD::UNDEF, N->getDebugLoc(), VT);
// fold (srl x, 0) -> x
if (N1C && N1C->isNullValue())
return N0;
APInt::getAllOnesValue(OpSizeInBits)))
return DAG.getConstant(0, VT);
- // fold (srl (srl x, c1), c2) -> 0 or (srl x, c1+c2)
+ // fold (srl (srl x, c1), c2) -> 0 or (srl x, (add c1, c2))
if (N1C && N0.getOpcode() == ISD::SRL &&
N0.getOperand(1).getOpcode() == ISD::Constant) {
uint64_t c1 = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
uint64_t c2 = N1C->getZExtValue();
if (c1 + c2 > OpSizeInBits)
return DAG.getConstant(0, VT);
- return DAG.getNode(ISD::SRL, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getConstant(c1 + c2, N1.getValueType()));
}
// Shifting in all undef bits?
MVT SmallVT = N0.getOperand(0).getValueType();
if (N1C->getZExtValue() >= SmallVT.getSizeInBits())
- return DAG.getNode(ISD::UNDEF, VT);
+ return DAG.getNode(ISD::UNDEF, N->getDebugLoc(), VT);
- SDValue SmallShift = DAG.getNode(ISD::SRL, SmallVT, N0.getOperand(0), N1);
+ SDValue SmallShift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), SmallVT,
+ N0.getOperand(0), N1);
AddToWorkList(SmallShift.getNode());
- return DAG.getNode(ISD::ANY_EXTEND, VT, SmallShift);
+ return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, SmallShift);
}
// fold (srl (sra X, Y), 31) -> (srl X, 31). This srl only looks at the sign
// bit, which is unmodified by sra.
- if (N1C && N1C->getZExtValue()+1 == VT.getSizeInBits()) {
+ if (N1C && N1C->getZExtValue() + 1 == VT.getSizeInBits()) {
if (N0.getOpcode() == ISD::SRA)
- return DAG.getNode(ISD::SRL, VT, N0.getOperand(0), N1);
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0), N1);
}
// fold (srl (ctlz x), "5") -> x iff x has one bit set (the low bit).
if (UnknownBits == 0) return DAG.getConstant(1, VT);
// Otherwise, check to see if there is exactly one bit input to the ctlz.
- if ((UnknownBits & (UnknownBits-1)) == 0) {
+ if ((UnknownBits & (UnknownBits - 1)) == 0) {
// Okay, we know that only that the single bit specified by UnknownBits
- // could be set on input to the CTLZ node. If this bit is set, the SRL
- // will return 0, if it is clear, it returns 1. Change the CTLZ/SRL pair
- // to an SRL,XOR pair, which is likely to simplify more.
+ // could be set on input to the CTLZ node. If this bit is set, the SRL
+ // will return 0, if it is clear, it returns 1. Change the CTLZ/SRL pair
+ // to an SRL/XOR pair, which is likely to simplify more.
unsigned ShAmt = UnknownBits.countTrailingZeros();
SDValue Op = N0.getOperand(0);
+
if (ShAmt) {
- Op = DAG.getNode(ISD::SRL, VT, Op,
- DAG.getConstant(ShAmt, TLI.getShiftAmountTy()));
+ Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op,
+ DAG.getConstant(ShAmt, getShiftAmountTy()));
AddToWorkList(Op.getNode());
}
- return DAG.getNode(ISD::XOR, VT, Op, DAG.getConstant(1, VT));
+
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT,
+ Op, DAG.getConstant(1, VT));
}
}
SDValue N100 = N1.getOperand(0).getOperand(0);
uint64_t TruncC = TruncVT.getIntegerVTBitMask() &
N101C->getZExtValue();
- return DAG.getNode(ISD::SRL, VT, N0,
- DAG.getNode(ISD::AND, TruncVT,
- DAG.getNode(ISD::TRUNCATE, TruncVT, N100),
+ return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0,
+ DAG.getNode(ISD::AND, N->getDebugLoc(),
+ TruncVT,
+ DAG.getNode(ISD::TRUNCATE,
+ N->getDebugLoc(),
+ TruncVT, N100),
DAG.getConstant(TruncC, TruncVT)));
}
}
// fold (ctlz c1) -> c2
if (isa<ConstantSDNode>(N0))
- return DAG.getNode(ISD::CTLZ, VT, N0);
+ return DAG.getNode(ISD::CTLZ, N->getDebugLoc(), VT, N0);
return SDValue();
}
// fold (cttz c1) -> c2
if (isa<ConstantSDNode>(N0))
- return DAG.getNode(ISD::CTTZ, VT, N0);
+ return DAG.getNode(ISD::CTTZ, N->getDebugLoc(), VT, N0);
return SDValue();
}
// fold (ctpop c1) -> c2
if (isa<ConstantSDNode>(N0))
- return DAG.getNode(ISD::CTPOP, VT, N0);
+ return DAG.getNode(ISD::CTPOP, N->getDebugLoc(), VT, N0);
return SDValue();
}
MVT VT = N->getValueType(0);
MVT VT0 = N0.getValueType();
- // fold select C, X, X -> X
+ // fold (select C, X, X) -> X
if (N1 == N2)
return N1;
- // fold select true, X, Y -> X
+ // fold (select true, X, Y) -> X
if (N0C && !N0C->isNullValue())
return N1;
- // fold select false, X, Y -> Y
+ // fold (select false, X, Y) -> Y
if (N0C && N0C->isNullValue())
return N2;
- // fold select C, 1, X -> C | X
+ // fold (select C, 1, X) -> (or C, X)
if (VT == MVT::i1 && N1C && N1C->getAPIntValue() == 1)
- return DAG.getNode(ISD::OR, VT, N0, N2);
- // fold select C, 0, 1 -> C ^ 1
+ return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N2);
+ // fold (select C, 0, 1) -> (xor C, 1)
if (VT.isInteger() &&
(VT0 == MVT::i1 ||
(VT0.isInteger() &&
TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent)) &&
N1C && N2C && N1C->isNullValue() && N2C->getAPIntValue() == 1) {
- SDValue XORNode = DAG.getNode(ISD::XOR, VT0, N0, DAG.getConstant(1, VT0));
+ SDValue XORNode;
if (VT == VT0)
- return XORNode;
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT0,
+ N0, DAG.getConstant(1, VT0));
+ XORNode = DAG.getNode(ISD::XOR, N0.getDebugLoc(), VT0,
+ N0, DAG.getConstant(1, VT0));
AddToWorkList(XORNode.getNode());
if (VT.bitsGT(VT0))
- return DAG.getNode(ISD::ZERO_EXTEND, VT, XORNode);
- return DAG.getNode(ISD::TRUNCATE, VT, XORNode);
+ return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, XORNode);
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, XORNode);
}
- // fold select C, 0, X -> ~C & X
+ // fold (select C, 0, X) -> (and (not C), X)
if (VT == VT0 && VT == MVT::i1 && N1C && N1C->isNullValue()) {
- SDValue NOTNode = DAG.getNOT(N0, VT);
+ SDValue NOTNode = DAG.getNOT(N0.getDebugLoc(), N0, VT);
AddToWorkList(NOTNode.getNode());
- return DAG.getNode(ISD::AND, VT, NOTNode, N2);
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, NOTNode, N2);
}
- // fold select C, X, 1 -> ~C | X
+ // fold (select C, X, 1) -> (or (not C), X)
if (VT == VT0 && VT == MVT::i1 && N2C && N2C->getAPIntValue() == 1) {
- SDValue NOTNode = DAG.getNOT(N0, VT);
+ SDValue NOTNode = DAG.getNOT(N0.getDebugLoc(), N0, VT);
AddToWorkList(NOTNode.getNode());
- return DAG.getNode(ISD::OR, VT, NOTNode, N1);
+ return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, NOTNode, N1);
}
- // fold select C, X, 0 -> C & X
+ // fold (select C, X, 0) -> (and C, X)
if (VT == MVT::i1 && N2C && N2C->isNullValue())
- return DAG.getNode(ISD::AND, VT, N0, N1);
- // fold X ? X : Y --> X ? 1 : Y --> X | Y
- if (VT == MVT::i1 && N0 == N1)
- return DAG.getNode(ISD::OR, VT, N0, N2);
- // fold X ? Y : X --> X ? Y : 0 --> X & Y
- if (VT == MVT::i1 && N0 == N2)
- return DAG.getNode(ISD::AND, VT, N0, N1);
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, N1);
+ // fold (select X, X, Y) -> (or X, Y)
+ // fold (select X, 1, Y) -> (or X, Y)
+ if (VT == MVT::i1 && (N0 == N1 || (N1C && N1C->getAPIntValue() == 1)))
+ return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N2);
+ // fold (select X, Y, X) -> (and X, Y)
+ // fold (select X, Y, 0) -> (and X, Y)
+ if (VT == MVT::i1 && (N0 == N2 || (N2C && N2C->getAPIntValue() == 0)))
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, N1);
// If we can fold this based on the true/false value, do so.
if (SimplifySelectOps(N, N1, N2))
// having to say they don't support SELECT_CC on every type the DAG knows
// about, since there is no way to mark an opcode illegal at all value types
if (TLI.isOperationLegalOrCustom(ISD::SELECT_CC, MVT::Other))
- return DAG.getNode(ISD::SELECT_CC, VT, N0.getOperand(0), N0.getOperand(1),
+ return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), VT,
+ N0.getOperand(0), N0.getOperand(1),
N1, N2, N0.getOperand(2));
else
- return SimplifySelect(N0, N1, N2);
+ return SimplifySelect(N->getDebugLoc(), N0, N1, N2);
}
+
return SDValue();
}
// Fold to a simpler select_cc
if (SCC.getNode() && SCC.getOpcode() == ISD::SETCC)
- return DAG.getNode(ISD::SELECT_CC, N2.getValueType(),
+ return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), N2.getValueType(),
SCC.getOperand(0), SCC.getOperand(1), N2, N3,
SCC.getOperand(2));
return SDValue(N, 0); // Don't revisit N.
// fold select_cc into other things, such as min/max/abs
- return SimplifySelectCC(N0, N1, N2, N3, CC);
+ return SimplifySelectCC(N->getDebugLoc(), N0, N1, N2, N3, CC);
}
SDValue DAGCombiner::visitSETCC(SDNode *N) {
// fold (sext c1) -> c1
if (isa<ConstantSDNode>(N0))
- return DAG.getNode(ISD::SIGN_EXTEND, VT, N0);
+ return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N0);
// fold (sext (sext x)) -> (sext x)
// fold (sext (aext x)) -> (sext x)
if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND)
- return DAG.getNode(ISD::SIGN_EXTEND, VT, N0.getOperand(0));
+ return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT,
+ N0.getOperand(0));
if (N0.getOpcode() == ISD::TRUNCATE) {
// fold (sext (truncate (load x))) -> (sext (smaller load x))
if (NarrowLoad.getNode()) {
if (NarrowLoad.getNode() != N0.getNode())
CombineTo(N0.getNode(), NarrowLoad);
- return DAG.getNode(ISD::SIGN_EXTEND, VT, NarrowLoad);
+ return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, NarrowLoad);
}
// See if the value being truncated is already sign extended. If so, just
// Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign
// bits, just sext from i32.
if (NumSignBits > OpBits-MidBits)
- return DAG.getNode(ISD::SIGN_EXTEND, VT, Op);
+ return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, Op);
} else {
// Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign
// bits, just truncate to i32.
if (NumSignBits > OpBits-MidBits)
- return DAG.getNode(ISD::TRUNCATE, VT, Op);
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op);
}
// fold (sext (truncate x)) -> (sextinreg x).
if (!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG,
N0.getValueType())) {
if (Op.getValueType().bitsLT(VT))
- Op = DAG.getNode(ISD::ANY_EXTEND, VT, Op);
+ Op = DAG.getNode(ISD::ANY_EXTEND, N0.getDebugLoc(), VT, Op);
else if (Op.getValueType().bitsGT(VT))
- Op = DAG.getNode(ISD::TRUNCATE, VT, Op);
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, Op,
+ Op = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), VT, Op);
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, Op,
DAG.getValueType(N0.getValueType()));
}
}
DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::SIGN_EXTEND, SetCCs, TLI);
if (DoXform) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(),
+ VT, LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(),
N0.getValueType(),
LN0->isVolatile(), LN0->getAlignment());
CombineTo(N, ExtLoad);
- SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad);
+ SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(),
+ N0.getValueType(), ExtLoad);
CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
+
// Extend SetCC uses if necessary.
for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) {
SDNode *SetCC = SetCCs[i];
SmallVector<SDValue, 4> Ops;
+
for (unsigned j = 0; j != 2; ++j) {
SDValue SOp = SetCC->getOperand(j);
if (SOp == Trunc)
Ops.push_back(ExtLoad);
else
- Ops.push_back(DAG.getNode(ISD::SIGN_EXTEND, VT, SOp));
- }
+ Ops.push_back(DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(),
+ VT, SOp));
+ }
+
Ops.push_back(SetCC->getOperand(2));
- CombineTo(SetCC, DAG.getNode(ISD::SETCC, SetCC->getValueType(0),
+ CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(),
+ SetCC->getValueType(0),
&Ops[0], Ops.size()));
}
+
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
}
MVT EVT = LN0->getMemoryVT();
if ((!LegalOperations && !LN0->isVolatile()) ||
TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT)) {
- SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
CombineTo(N, ExtLoad);
CombineTo(N0.getNode(),
- DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
+ DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(),
+ N0.getValueType(), ExtLoad),
ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
}
- // sext(setcc x,y,cc) -> select_cc x, y, -1, 0, cc
+ // sext(setcc x, y, cc) -> (select_cc x, y, -1, 0, cc)
if (N0.getOpcode() == ISD::SETCC) {
SDValue SCC =
- SimplifySelectCC(N0.getOperand(0), N0.getOperand(1),
+ SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1),
DAG.getConstant(~0ULL, VT), DAG.getConstant(0, VT),
cast<CondCodeSDNode>(N0.getOperand(2))->get(), true);
if (SCC.getNode()) return SCC;
// fold (sext x) -> (zext x) if the sign bit is known zero.
if ((!LegalOperations || TLI.isOperationLegal(ISD::ZERO_EXTEND, VT)) &&
DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
+ return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0);
return SDValue();
}
// fold (zext c1) -> c1
if (isa<ConstantSDNode>(N0))
- return DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
+ return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0);
// fold (zext (zext x)) -> (zext x)
// fold (zext (aext x)) -> (zext x)
if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND)
- return DAG.getNode(ISD::ZERO_EXTEND, VT, N0.getOperand(0));
+ return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT,
+ N0.getOperand(0));
// fold (zext (truncate (load x))) -> (zext (smaller load x))
// fold (zext (truncate (srl (load x), c))) -> (zext (small load (x+c/n)))
if (NarrowLoad.getNode()) {
if (NarrowLoad.getNode() != N0.getNode())
CombineTo(N0.getNode(), NarrowLoad);
- return DAG.getNode(ISD::ZERO_EXTEND, VT, NarrowLoad);
+ return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, NarrowLoad);
}
}
(!LegalOperations || TLI.isOperationLegal(ISD::AND, VT))) {
SDValue Op = N0.getOperand(0);
if (Op.getValueType().bitsLT(VT)) {
- Op = DAG.getNode(ISD::ANY_EXTEND, VT, Op);
+ Op = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, Op);
} else if (Op.getValueType().bitsGT(VT)) {
- Op = DAG.getNode(ISD::TRUNCATE, VT, Op);
+ Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op);
}
- return DAG.getZeroExtendInReg(Op, N0.getValueType());
+ return DAG.getZeroExtendInReg(Op, N->getDebugLoc(), N0.getValueType());
}
// fold (zext (and (trunc x), cst)) -> (and x, cst).
N0.getOperand(1).getOpcode() == ISD::Constant) {
SDValue X = N0.getOperand(0).getOperand(0);
if (X.getValueType().bitsLT(VT)) {
- X = DAG.getNode(ISD::ANY_EXTEND, VT, X);
+ X = DAG.getNode(ISD::ANY_EXTEND, X.getDebugLoc(), VT, X);
} else if (X.getValueType().bitsGT(VT)) {
- X = DAG.getNode(ISD::TRUNCATE, VT, X);
+ X = DAG.getNode(ISD::TRUNCATE, X.getDebugLoc(), VT, X);
}
APInt Mask = cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
Mask.zext(VT.getSizeInBits());
- return DAG.getNode(ISD::AND, VT, X, DAG.getConstant(Mask, VT));
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT,
+ X, DAG.getConstant(Mask, VT));
}
// fold (zext (load x)) -> (zext (truncate (zextload x)))
DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::ZERO_EXTEND, SetCCs, TLI);
if (DoXform) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(),
N0.getValueType(),
LN0->isVolatile(), LN0->getAlignment());
CombineTo(N, ExtLoad);
- SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad);
+ SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(),
+ N0.getValueType(), ExtLoad);
CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1));
+
// Extend SetCC uses if necessary.
for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) {
SDNode *SetCC = SetCCs[i];
SmallVector<SDValue, 4> Ops;
+
for (unsigned j = 0; j != 2; ++j) {
SDValue SOp = SetCC->getOperand(j);
if (SOp == Trunc)
Ops.push_back(ExtLoad);
else
- Ops.push_back(DAG.getNode(ISD::ZERO_EXTEND, VT, SOp));
- }
+ Ops.push_back(DAG.getNode(ISD::ZERO_EXTEND,
+ N->getDebugLoc(), VT, SOp));
+ }
+
Ops.push_back(SetCC->getOperand(2));
- CombineTo(SetCC, DAG.getNode(ISD::SETCC, SetCC->getValueType(0),
+ CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(),
+ SetCC->getValueType(0),
&Ops[0], Ops.size()));
}
+
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
}
MVT EVT = LN0->getMemoryVT();
if ((!LegalOperations && !LN0->isVolatile()) ||
TLI.isLoadExtLegal(ISD::ZEXTLOAD, EVT)) {
- SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
CombineTo(N, ExtLoad);
CombineTo(N0.getNode(),
- DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
+ DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(),
+ ExtLoad),
ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
// zext(setcc x,y,cc) -> select_cc x, y, 1, 0, cc
if (N0.getOpcode() == ISD::SETCC) {
SDValue SCC =
- SimplifySelectCC(N0.getOperand(0), N0.getOperand(1),
+ SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1),
DAG.getConstant(1, VT), DAG.getConstant(0, VT),
cast<CondCodeSDNode>(N0.getOperand(2))->get(), true);
if (SCC.getNode()) return SCC;
if (N0.getOpcode() == ISD::ANY_EXTEND ||
N0.getOpcode() == ISD::ZERO_EXTEND ||
N0.getOpcode() == ISD::SIGN_EXTEND)
- return DAG.getNode(N0.getOpcode(), VT, N0.getOperand(0));
+ return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, N0.getOperand(0));
// fold (aext (truncate (load x))) -> (aext (smaller load x))
// fold (aext (truncate (srl (load x), c))) -> (aext (small load (x+c/n)))
if (NarrowLoad.getNode()) {
if (NarrowLoad.getNode() != N0.getNode())
CombineTo(N0.getNode(), NarrowLoad);
- return DAG.getNode(ISD::ANY_EXTEND, VT, NarrowLoad);
+ return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, NarrowLoad);
}
}
if (TruncOp.getValueType() == VT)
return TruncOp; // x iff x size == zext size.
if (TruncOp.getValueType().bitsGT(VT))
- return DAG.getNode(ISD::TRUNCATE, VT, TruncOp);
- return DAG.getNode(ISD::ANY_EXTEND, VT, TruncOp);
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, TruncOp);
+ return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, TruncOp);
}
// fold (aext (and (trunc x), cst)) -> (and x, cst).
N0.getOperand(1).getOpcode() == ISD::Constant) {
SDValue X = N0.getOperand(0).getOperand(0);
if (X.getValueType().bitsLT(VT)) {
- X = DAG.getNode(ISD::ANY_EXTEND, VT, X);
+ X = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, X);
} else if (X.getValueType().bitsGT(VT)) {
- X = DAG.getNode(ISD::TRUNCATE, VT, X);
+ X = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, X);
}
APInt Mask = cast<ConstantSDNode>(N0.getOperand(1))->getAPIntValue();
Mask.zext(VT.getSizeInBits());
- return DAG.getNode(ISD::AND, VT, X, DAG.getConstant(Mask, VT));
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT,
+ X, DAG.getConstant(Mask, VT));
}
// fold (aext (load x)) -> (aext (truncate (extload x)))
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(),
N0.getValueType(),
SDValue(ExtLoad.getNode(), 1));
// If any node needs the original loaded value, recompute it.
if (!LN0->use_empty())
- CombineTo(LN0, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
+ CombineTo(LN0, DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(),
+ N0.getValueType(), ExtLoad),
ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
N0.hasOneUse()) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
MVT EVT = LN0->getMemoryVT();
- SDValue ExtLoad = DAG.getExtLoad(LN0->getExtensionType(), VT,
- LN0->getChain(), LN0->getBasePtr(),
+ SDValue ExtLoad = DAG.getExtLoad(LN0->getExtensionType(), N->getDebugLoc(),
+ VT, LN0->getChain(), LN0->getBasePtr(),
LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
CombineTo(N, ExtLoad);
CombineTo(N0.getNode(),
- DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
+ DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(),
+ N0.getValueType(), ExtLoad),
ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
// aext(setcc x,y,cc) -> select_cc x, y, 1, 0, cc
if (N0.getOpcode() == ISD::SETCC) {
SDValue SCC =
- SimplifySelectCC(N0.getOperand(0), N0.getOperand(1),
+ SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1),
DAG.getConstant(1, VT), DAG.getConstant(0, VT),
cast<CondCodeSDNode>(N0.getOperand(2))->get(), true);
if (SCC.getNode())
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
// See if we can recursively simplify the LHS.
unsigned Amt = RHSC->getZExtValue();
+
// Watch out for shift count overflow though.
if (Amt >= Mask.getBitWidth()) break;
APInt NewMask = Mask << Amt;
SDValue SimplifyLHS = GetDemandedBits(V.getOperand(0), NewMask);
- if (SimplifyLHS.getNode()) {
- return DAG.getNode(ISD::SRL, V.getValueType(),
+ if (SimplifyLHS.getNode())
+ return DAG.getNode(ISD::SRL, V.getDebugLoc(), V.getValueType(),
SimplifyLHS, V.getOperand(1));
- }
}
}
return SDValue();
!cast<LoadSDNode>(N0)->isVolatile()) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
MVT PtrType = N0.getOperand(1).getValueType();
+
// For big endian targets, we need to adjust the offset to the pointer to
// load the correct bytes.
if (TLI.isBigEndian()) {
unsigned EVTStoreBits = EVT.getStoreSizeInBits();
ShAmt = LVTStoreBits - EVTStoreBits - ShAmt;
}
+
uint64_t PtrOff = ShAmt / 8;
unsigned NewAlign = MinAlign(LN0->getAlignment(), PtrOff);
- SDValue NewPtr = DAG.getNode(ISD::ADD, PtrType, LN0->getBasePtr(),
+ SDValue NewPtr = DAG.getNode(ISD::ADD, LN0->getDebugLoc(),
+ PtrType, LN0->getBasePtr(),
DAG.getConstant(PtrOff, PtrType));
AddToWorkList(NewPtr.getNode());
+
SDValue Load = (ExtType == ISD::NON_EXTLOAD)
- ? DAG.getLoad(VT, LN0->getChain(), NewPtr,
+ ? DAG.getLoad(VT, N0.getDebugLoc(), LN0->getChain(), NewPtr,
LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff,
LN0->isVolatile(), NewAlign)
- : DAG.getExtLoad(ExtType, VT, LN0->getChain(), NewPtr,
+ : DAG.getExtLoad(ExtType, N0.getDebugLoc(), VT, LN0->getChain(), NewPtr,
LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff,
EVT, LN0->isVolatile(), NewAlign);
+
// Replace the old load's chain with the new load's chain.
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1),
&DeadNodes);
+
// Return the new loaded value.
return Load;
}
return SDValue();
}
-
SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
// fold (sext_in_reg c1) -> c1
if (isa<ConstantSDNode>(N0) || N0.getOpcode() == ISD::UNDEF)
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, 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 (DAG.ComputeNumSignBits(N0) >= VT.getSizeInBits()-EVTBits+1)
// fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2
if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
EVT.bitsLT(cast<VTSDNode>(N0.getOperand(1))->getVT())) {
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0.getOperand(0), N1);
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT,
+ N0.getOperand(0), N1);
}
// fold (sext_in_reg (sext x)) -> (sext x)
if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) {
SDValue N00 = N0.getOperand(0);
if (N00.getValueType().getSizeInBits() < EVTBits)
- return DAG.getNode(ISD::SIGN_EXTEND, VT, N00, N1);
+ return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N00, N1);
}
// fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is known zero.
if (NarrowLoad.getNode())
return NarrowLoad;
- // fold (sext_in_reg (srl X, 24), i8) -> sra X, 24
- // fold (sext_in_reg (srl X, 23), i8) -> sra X, 23 iff possible.
+ // fold (sext_in_reg (srl X, 24), i8) -> (sra X, 24)
+ // fold (sext_in_reg (srl X, 23), i8) -> (sra X, 23) iff possible.
// We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" above.
if (N0.getOpcode() == ISD::SRL) {
if (ConstantSDNode *ShAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1)))
// extended enough.
unsigned InSignBits = DAG.ComputeNumSignBits(N0.getOperand(0));
if (VT.getSizeInBits()-(ShAmt->getZExtValue()+EVTBits) < InSignBits)
- return DAG.getNode(ISD::SRA, VT, N0.getOperand(0), N0.getOperand(1));
+ return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT,
+ N0.getOperand(0), N0.getOperand(1));
}
}
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT))) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT))) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(), EVT,
LN0->isVolatile(), LN0->getAlignment());
return N0;
// fold (truncate c1) -> c1
if (isa<ConstantSDNode>(N0))
- return DAG.getNode(ISD::TRUNCATE, VT, N0);
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0);
// fold (truncate (truncate x)) -> (truncate x)
if (N0.getOpcode() == ISD::TRUNCATE)
- return DAG.getNode(ISD::TRUNCATE, VT, N0.getOperand(0));
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0.getOperand(0));
// fold (truncate (ext x)) -> (ext x) or (truncate x) or x
if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::SIGN_EXTEND||
N0.getOpcode() == ISD::ANY_EXTEND) {
if (N0.getOperand(0).getValueType().bitsLT(VT))
// if the source is smaller than the dest, we still need an extend
- return DAG.getNode(N0.getOpcode(), VT, N0.getOperand(0));
+ return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT,
+ N0.getOperand(0));
else if (N0.getOperand(0).getValueType().bitsGT(VT))
// if the source is larger than the dest, than we just need the truncate
- return DAG.getNode(ISD::TRUNCATE, VT, N0.getOperand(0));
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0.getOperand(0));
else
// if the source and dest are the same type, we can drop both the extend
// and the truncate
GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(),
VT.getSizeInBits()));
if (Shorter.getNode())
- return DAG.getNode(ISD::TRUNCATE, VT, Shorter);
+ return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter);
// fold (truncate (load x)) -> (smaller load x)
// fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits))
MVT LD1VT = LD1->getValueType(0);
SDNode *LD2 = getBuildPairElt(N, 1);
const MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+
if (ISD::isNON_EXTLoad(LD2) &&
LD2->hasOneUse() &&
// If both are volatile this would reduce the number of volatile loads.
unsigned Align = LD->getAlignment();
unsigned NewAlign = TLI.getTargetData()->
getABITypeAlignment(VT.getTypeForMVT());
+
if (NewAlign <= Align &&
(!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT)))
- return DAG.getLoad(VT, LD->getChain(), LD->getBasePtr(),
+ return DAG.getLoad(VT, N->getDebugLoc(), LD->getChain(), LD->getBasePtr(),
LD->getSrcValue(), LD->getSrcValueOffset(),
false, Align);
}
+
return SDValue();
}
MVT DestEltVT = N->getValueType(0).getVectorElementType();
assert(!DestEltVT.isVector() &&
"Element type of vector ValueType must not be vector!");
- if (isSimple) {
+ if (isSimple)
return ConstantFoldBIT_CONVERTofBUILD_VECTOR(N0.getNode(), DestEltVT);
- }
}
// If the input is a constant, let getNode fold it.
if (isa<ConstantSDNode>(N0) || isa<ConstantFPSDNode>(N0)) {
- SDValue Res = DAG.getNode(ISD::BIT_CONVERT, VT, N0);
+ SDValue Res = DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT, N0);
if (Res.getNode() != N) return Res;
}
- if (N0.getOpcode() == ISD::BIT_CONVERT) // conv(conv(x,t1),t2) -> conv(x,t2)
- return DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
+ // (conv (conv x, t1), t2) -> (conv x, t2)
+ if (N0.getOpcode() == ISD::BIT_CONVERT)
+ return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT,
+ N0.getOperand(0));
// fold (conv (load x)) -> (load (conv*)x)
// If the resultant load doesn't need a higher alignment than the original!
unsigned Align = TLI.getTargetData()->
getABITypeAlignment(VT.getTypeForMVT());
unsigned OrigAlign = LN0->getAlignment();
+
if (Align <= OrigAlign) {
- SDValue Load = DAG.getLoad(VT, LN0->getChain(), LN0->getBasePtr(),
+ SDValue Load = DAG.getLoad(VT, N->getDebugLoc(), LN0->getChain(),
+ LN0->getBasePtr(),
LN0->getSrcValue(), LN0->getSrcValueOffset(),
LN0->isVolatile(), OrigAlign);
AddToWorkList(N);
CombineTo(N0.getNode(),
- DAG.getNode(ISD::BIT_CONVERT, N0.getValueType(), Load),
+ DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(),
+ N0.getValueType(), Load),
Load.getValue(1));
return Load;
}
}
- // Fold bitconvert(fneg(x)) -> xor(bitconvert(x), signbit)
- // Fold bitconvert(fabs(x)) -> and(bitconvert(x), ~signbit)
+ // fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit)
+ // fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit))
// This often reduces constant pool loads.
if ((N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FABS) &&
N0.getNode()->hasOneUse() && VT.isInteger() && !VT.isVector()) {
- SDValue NewConv = DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
+ SDValue NewConv = DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), VT,
+ N0.getOperand(0));
AddToWorkList(NewConv.getNode());
APInt SignBit = APInt::getSignBit(VT.getSizeInBits());
if (N0.getOpcode() == ISD::FNEG)
- return DAG.getNode(ISD::XOR, VT, NewConv, DAG.getConstant(SignBit, VT));
+ return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT,
+ NewConv, DAG.getConstant(SignBit, VT));
assert(N0.getOpcode() == ISD::FABS);
- return DAG.getNode(ISD::AND, VT, NewConv, DAG.getConstant(~SignBit, VT));
+ return DAG.getNode(ISD::AND, N->getDebugLoc(), VT,
+ NewConv, DAG.getConstant(~SignBit, VT));
}
- // Fold bitconvert(fcopysign(cst, x)) -> bitconvert(x)&sign | cst&~sign'
- // Note that we don't handle copysign(x,cst) because this can always be folded
- // to an fneg or fabs.
+ // fold (bitconvert (fcopysign cst, x)) ->
+ // (or (and (bitconvert x), sign), (and cst, (not sign)))
+ // Note that we don't handle (copysign x, cst) because this can always be
+ // folded to an fneg or fabs.
if (N0.getOpcode() == ISD::FCOPYSIGN && N0.getNode()->hasOneUse() &&
isa<ConstantFPSDNode>(N0.getOperand(0)) &&
VT.isInteger() && !VT.isVector()) {
unsigned OrigXWidth = N0.getOperand(1).getValueType().getSizeInBits();
MVT IntXVT = MVT::getIntegerVT(OrigXWidth);
if (TLI.isTypeLegal(IntXVT) || !LegalTypes) {
- SDValue X = DAG.getNode(ISD::BIT_CONVERT, IntXVT, N0.getOperand(1));
+ SDValue X = DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(),
+ IntXVT, N0.getOperand(1));
AddToWorkList(X.getNode());
// If X has a different width than the result/lhs, sext it or truncate it.
unsigned VTWidth = VT.getSizeInBits();
if (OrigXWidth < VTWidth) {
- X = DAG.getNode(ISD::SIGN_EXTEND, VT, X);
+ X = DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, X);
AddToWorkList(X.getNode());
} else if (OrigXWidth > VTWidth) {
// To get the sign bit in the right place, we have to shift it right
// before truncating.
- X = DAG.getNode(ISD::SRL, X.getValueType(), X,
+ X = DAG.getNode(ISD::SRL, X.getDebugLoc(),
+ X.getValueType(), X,
DAG.getConstant(OrigXWidth-VTWidth, X.getValueType()));
AddToWorkList(X.getNode());
- X = DAG.getNode(ISD::TRUNCATE, VT, X);
+ X = DAG.getNode(ISD::TRUNCATE, X.getDebugLoc(), VT, X);
AddToWorkList(X.getNode());
}
APInt SignBit = APInt::getSignBit(VT.getSizeInBits());
- X = DAG.getNode(ISD::AND, VT, X, DAG.getConstant(SignBit, VT));
+ X = DAG.getNode(ISD::AND, X.getDebugLoc(), VT,
+ X, DAG.getConstant(SignBit, VT));
AddToWorkList(X.getNode());
- SDValue Cst = DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
- Cst = DAG.getNode(ISD::AND, VT, Cst, DAG.getConstant(~SignBit, VT));
+ SDValue Cst = DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(),
+ VT, N0.getOperand(0));
+ Cst = DAG.getNode(ISD::AND, Cst.getDebugLoc(), VT,
+ Cst, DAG.getConstant(~SignBit, VT));
AddToWorkList(Cst.getNode());
- return DAG.getNode(ISD::OR, VT, X, Cst);
+ return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, X, Cst);
}
}
}
MVT VT = MVT::getVectorVT(DstEltVT,
BV->getValueType(0).getVectorNumElements());
- return DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], Ops.size());
+ return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT,
+ &Ops[0], Ops.size());
}
// Otherwise, we're growing or shrinking the elements. To avoid having to
}
if (EltIsUndef)
- Ops.push_back(DAG.getNode(ISD::UNDEF, DstEltVT));
+ Ops.push_back(DAG.getNode(ISD::UNDEF, BV->getDebugLoc(), DstEltVT));
else
Ops.push_back(DAG.getConstant(NewBits, DstEltVT));
}
MVT VT = MVT::getVectorVT(DstEltVT, Ops.size());
- return DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], Ops.size());
+ return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT,
+ &Ops[0], Ops.size());
}
// Finally, this must be the case where we are shrinking elements: each input
unsigned NumOutputsPerInput = SrcBitSize/DstBitSize;
MVT VT = MVT::getVectorVT(DstEltVT, NumOutputsPerInput*BV->getNumOperands());
SmallVector<SDValue, 8> Ops;
+
for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
if (BV->getOperand(i).getOpcode() == ISD::UNDEF) {
for (unsigned j = 0; j != NumOutputsPerInput; ++j)
- Ops.push_back(DAG.getNode(ISD::UNDEF, DstEltVT));
+ Ops.push_back(DAG.getNode(ISD::UNDEF, BV->getDebugLoc(), DstEltVT));
continue;
}
+
APInt OpVal = cast<ConstantSDNode>(BV->getOperand(i))->getAPIntValue();
+
for (unsigned j = 0; j != NumOutputsPerInput; ++j) {
APInt ThisVal = APInt(OpVal).trunc(DstBitSize);
Ops.push_back(DAG.getConstant(ThisVal, DstEltVT));
if (isS2V && i == 0 && j == 0 && APInt(ThisVal).zext(SrcBitSize) == OpVal)
// Simply turn this into a SCALAR_TO_VECTOR of the new type.
- return DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, Ops[0]);
+ return DAG.getNode(ISD::SCALAR_TO_VECTOR, BV->getDebugLoc(), VT,
+ Ops[0]);
OpVal = OpVal.lshr(DstBitSize);
}
if (TLI.isBigEndian())
std::reverse(Ops.end()-NumOutputsPerInput, Ops.end());
}
- return DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], Ops.size());
-}
-
+ return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT,
+ &Ops[0], Ops.size());
+}
SDValue DAGCombiner::visitFADD(SDNode *N) {
SDValue N0 = N->getOperand(0);
if (FoldedVOp.getNode()) return FoldedVOp;
}
- // fold (fadd c1, c2) -> c1+c2
+ // fold (fadd c1, c2) -> (fadd c1, c2)
if (N0CFP && N1CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FADD, VT, N0, N1);
+ return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N1);
// canonicalize constant to RHS
if (N0CFP && !N1CFP)
- return DAG.getNode(ISD::FADD, VT, N1, N0);
- // fold (A + 0) -> A
+ return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N1, N0);
+ // fold (fadd A, 0) -> A
if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero())
return N0;
- // fold (A + (-B)) -> A-B
+ // fold (fadd A, (fneg B)) -> (fsub A, B)
if (isNegatibleForFree(N1, LegalOperations) == 2)
- return DAG.getNode(ISD::FSUB, VT, N0,
+ return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N0,
GetNegatedExpression(N1, DAG, LegalOperations));
- // fold ((-A) + B) -> B-A
+ // fold (fadd (fneg A), B) -> (fsub B, A)
if (isNegatibleForFree(N0, LegalOperations) == 2)
- return DAG.getNode(ISD::FSUB, VT, N1,
+ return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N1,
GetNegatedExpression(N0, DAG, LegalOperations));
// If allowed, fold (fadd (fadd x, c1), c2) -> (fadd x, (fadd c1, c2))
if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FADD &&
N0.getNode()->hasOneUse() && isa<ConstantFPSDNode>(N0.getOperand(1)))
- return DAG.getNode(ISD::FADD, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getNode(ISD::FADD, VT, N0.getOperand(1), N1));
return SDValue();
// fold (fsub c1, c2) -> c1-c2
if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FSUB, VT, N0, N1);
- // fold (A-0) -> A
+ // fold (fsub A, 0) -> A
if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero())
return N0;
- // fold (0-B) -> -B
+ // fold (fsub 0, B) -> -B
if (UnsafeFPMath && N0CFP && N0CFP->getValueAPF().isZero()) {
if (isNegatibleForFree(N1, LegalOperations))
return GetNegatedExpression(N1, DAG, LegalOperations);
if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))
- return DAG.getNode(ISD::FNEG, VT, N1);
+ return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N1);
}
- // fold (A-(-B)) -> A+B
+ // fold (fsub A, (fneg B)) -> (fadd A, B)
if (isNegatibleForFree(N1, LegalOperations))
- return DAG.getNode(ISD::FADD, VT, N0,
+ return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0,
GetNegatedExpression(N1, DAG, LegalOperations));
return SDValue();
// fold (fmul c1, c2) -> c1*c2
if (N0CFP && N1CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FMUL, VT, N0, N1);
+ return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0, N1);
// canonicalize constant to RHS
if (N0CFP && !N1CFP)
- return DAG.getNode(ISD::FMUL, VT, N1, N0);
- // fold (A * 0) -> 0
+ return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N1, N0);
+ // fold (fmul A, 0) -> 0
if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero())
return N1;
// fold (fmul X, 2.0) -> (fadd X, X)
if (N1CFP && N1CFP->isExactlyValue(+2.0))
- return DAG.getNode(ISD::FADD, VT, N0, N0);
- // fold (fmul X, -1.0) -> (fneg X)
+ return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N0);
+ // fold (fmul X, (fneg 1.0)) -> (fneg X)
if (N1CFP && N1CFP->isExactlyValue(-1.0))
if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))
- return DAG.getNode(ISD::FNEG, VT, N0);
+ return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N0);
- // -X * -Y -> X*Y
+ // fold (fmul (fneg X), (fneg Y)) -> (fmul X, Y)
if (char LHSNeg = isNegatibleForFree(N0, LegalOperations)) {
if (char RHSNeg = isNegatibleForFree(N1, LegalOperations)) {
// Both can be negated for free, check to see if at least one is cheaper
// negated.
if (LHSNeg == 2 || RHSNeg == 2)
- return DAG.getNode(ISD::FMUL, VT,
+ return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT,
GetNegatedExpression(N0, DAG, LegalOperations),
GetNegatedExpression(N1, DAG, LegalOperations));
}
// If allowed, fold (fmul (fmul x, c1), c2) -> (fmul x, (fmul c1, c2))
if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FMUL &&
N0.getNode()->hasOneUse() && isa<ConstantFPSDNode>(N0.getOperand(1)))
- return DAG.getNode(ISD::FMUL, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getNode(ISD::FMUL, VT, N0.getOperand(1), N1));
return SDValue();
// fold (fdiv c1, c2) -> c1/c2
if (N0CFP && N1CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FDIV, VT, N0, N1);
+ return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT, N0, N1);
- // -X / -Y -> X*Y
+ // (fdiv (fneg X), (fneg Y)) -> (fdiv X, Y)
if (char LHSNeg = isNegatibleForFree(N0, LegalOperations)) {
if (char RHSNeg = isNegatibleForFree(N1, LegalOperations)) {
// Both can be negated for free, check to see if at least one is cheaper
// negated.
if (LHSNeg == 2 || RHSNeg == 2)
- return DAG.getNode(ISD::FDIV, VT,
+ return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT,
GetNegatedExpression(N0, DAG, LegalOperations),
GetNegatedExpression(N1, DAG, LegalOperations));
}
// fold (frem c1, c2) -> fmod(c1,c2)
if (N0CFP && N1CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FREM, VT, N0, N1);
+ return DAG.getNode(ISD::FREM, N->getDebugLoc(), VT, N0, N1);
return SDValue();
}
// copysign(x, c1) -> fneg(fabs(x)) iff isneg(c1)
if (!V.isNegative()) {
if (!LegalOperations || TLI.isOperationLegal(ISD::FABS, VT))
- return DAG.getNode(ISD::FABS, VT, N0);
+ return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0);
} else {
if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))
- return DAG.getNode(ISD::FNEG, VT, DAG.getNode(ISD::FABS, VT, N0));
+ return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT,
+ DAG.getNode(ISD::FABS, N0.getDebugLoc(), VT, N0));
}
}
// copysign(copysign(x,z), y) -> copysign(x, y)
if (N0.getOpcode() == ISD::FABS || N0.getOpcode() == ISD::FNEG ||
N0.getOpcode() == ISD::FCOPYSIGN)
- return DAG.getNode(ISD::FCOPYSIGN, VT, N0.getOperand(0), N1);
+ return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT,
+ N0.getOperand(0), N1);
// copysign(x, abs(y)) -> abs(x)
if (N1.getOpcode() == ISD::FABS)
- return DAG.getNode(ISD::FABS, VT, N0);
+ return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0);
// copysign(x, copysign(y,z)) -> copysign(x, z)
if (N1.getOpcode() == ISD::FCOPYSIGN)
- return DAG.getNode(ISD::FCOPYSIGN, VT, N0, N1.getOperand(1));
+ return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT,
+ N0, N1.getOperand(1));
// copysign(x, fp_extend(y)) -> copysign(x, y)
// copysign(x, fp_round(y)) -> copysign(x, y)
if (N1.getOpcode() == ISD::FP_EXTEND || N1.getOpcode() == ISD::FP_ROUND)
- return DAG.getNode(ISD::FCOPYSIGN, VT, N0, N1.getOperand(0));
+ return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT,
+ N0, N1.getOperand(0));
return SDValue();
}
// fold (sint_to_fp c1) -> c1fp
if (N0C && OpVT != MVT::ppcf128)
- return DAG.getNode(ISD::SINT_TO_FP, VT, N0);
+ return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0);
// If the input is a legal type, and SINT_TO_FP is not legal on this target,
// but UINT_TO_FP is legal on this target, try to convert.
TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, OpVT)) {
// If the sign bit is known to be zero, we can change this to UINT_TO_FP.
if (DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::UINT_TO_FP, VT, N0);
+ return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0);
}
-
-
+
return SDValue();
}
// fold (uint_to_fp c1) -> c1fp
if (N0C && OpVT != MVT::ppcf128)
- return DAG.getNode(ISD::UINT_TO_FP, VT, N0);
+ return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0);
// If the input is a legal type, and UINT_TO_FP is not legal on this target,
// but SINT_TO_FP is legal on this target, try to convert.
TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, OpVT)) {
// If the sign bit is known to be zero, we can change this to SINT_TO_FP.
if (DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::SINT_TO_FP, VT, N0);
+ return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0);
}
return SDValue();
// fold (fp_to_sint c1fp) -> c1
if (N0CFP)
- return DAG.getNode(ISD::FP_TO_SINT, VT, N0);
+ return DAG.getNode(ISD::FP_TO_SINT, N->getDebugLoc(), VT, N0);
+
return SDValue();
}
// fold (fp_to_uint c1fp) -> c1
if (N0CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FP_TO_UINT, VT, N0);
+ return DAG.getNode(ISD::FP_TO_UINT, N->getDebugLoc(), VT, N0);
+
return SDValue();
}
// fold (fp_round c1fp) -> c1fp
if (N0CFP && N0.getValueType() != MVT::ppcf128)
- return DAG.getNode(ISD::FP_ROUND, VT, N0, N1);
+ return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, N0, N1);
// fold (fp_round (fp_extend x)) -> x
if (N0.getOpcode() == ISD::FP_EXTEND && VT == N0.getOperand(0).getValueType())
// This is a value preserving truncation if both round's are.
bool IsTrunc = N->getConstantOperandVal(1) == 1 &&
N0.getNode()->getConstantOperandVal(1) == 1;
- return DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0),
+ return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, N0.getOperand(0),
DAG.getIntPtrConstant(IsTrunc));
}
// fold (fp_round (copysign X, Y)) -> (copysign (fp_round X), Y)
if (N0.getOpcode() == ISD::FCOPYSIGN && N0.getNode()->hasOneUse()) {
- SDValue Tmp = DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0), N1);
+ SDValue Tmp = DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), VT,
+ N0.getOperand(0), N1);
AddToWorkList(Tmp.getNode());
- return DAG.getNode(ISD::FCOPYSIGN, VT, Tmp, N0.getOperand(1));
+ return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT,
+ Tmp, N0.getOperand(1));
}
return SDValue();
// fold (fp_round_inreg c1fp) -> c1fp
if (N0CFP && (TLI.isTypeLegal(EVT) || !LegalTypes)) {
SDValue Round = DAG.getConstantFP(*N0CFP->getConstantFPValue(), EVT);
- return DAG.getNode(ISD::FP_EXTEND, VT, Round);
+ return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, Round);
}
+
return SDValue();
}
// fold (fp_extend c1fp) -> c1fp
if (N0CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FP_EXTEND, VT, N0);
+ return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, N0);
// Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the
// value of X.
SDValue In = N0.getOperand(0);
if (In.getValueType() == VT) return In;
if (VT.bitsLT(In.getValueType()))
- return DAG.getNode(ISD::FP_ROUND, VT, In, N0.getOperand(1));
- return DAG.getNode(ISD::FP_EXTEND, VT, In);
+ return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT,
+ In, N0.getOperand(1));
+ return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, In);
}
// fold (fpext (load x)) -> (fpext (fptrunc (extload x)))
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, LN0->getChain(),
+ SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, N->getDebugLoc(), VT,
+ LN0->getChain(),
LN0->getBasePtr(), LN0->getSrcValue(),
LN0->getSrcValueOffset(),
N0.getValueType(),
LN0->isVolatile(), LN0->getAlignment());
CombineTo(N, ExtLoad);
- CombineTo(N0.getNode(), DAG.getNode(ISD::FP_ROUND, N0.getValueType(),
- ExtLoad, DAG.getIntPtrConstant(1)),
+ CombineTo(N0.getNode(),
+ DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(),
+ N0.getValueType(), ExtLoad, DAG.getIntPtrConstant(1)),
ExtLoad.getValue(1));
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
SDValue Int = N0.getOperand(0);
MVT IntVT = Int.getValueType();
if (IntVT.isInteger() && !IntVT.isVector()) {
- Int = DAG.getNode(ISD::XOR, IntVT, Int,
+ Int = DAG.getNode(ISD::XOR, N0.getDebugLoc(), IntVT, Int,
DAG.getConstant(IntVT.getIntegerVTSignBit(), IntVT));
AddToWorkList(Int.getNode());
- return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Int);
+ return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(),
+ N->getValueType(0), Int);
}
}
// fold (fabs c1) -> fabs(c1)
if (N0CFP && VT != MVT::ppcf128)
- return DAG.getNode(ISD::FABS, VT, N0);
+ return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0);
// fold (fabs (fabs x)) -> (fabs x)
if (N0.getOpcode() == ISD::FABS)
return N->getOperand(0);
// fold (fabs (fneg x)) -> (fabs x)
// fold (fabs (fcopysign x, y)) -> (fabs x)
if (N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FCOPYSIGN)
- return DAG.getNode(ISD::FABS, VT, N0.getOperand(0));
+ return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0.getOperand(0));
// Transform fabs(bitconvert(x)) -> bitconvert(x&~sign) to avoid loading
// constant pool values.
SDValue Int = N0.getOperand(0);
MVT IntVT = Int.getValueType();
if (IntVT.isInteger() && !IntVT.isVector()) {
- Int = DAG.getNode(ISD::AND, IntVT, Int,
+ Int = DAG.getNode(ISD::AND, N0.getDebugLoc(), IntVT, Int,
DAG.getConstant(~IntVT.getIntegerVTSignBit(), IntVT));
AddToWorkList(Int.getNode());
- return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Int);
+ return DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(),
+ N->getValueType(0), Int);
}
}
return Chain;
// unconditional branch
if (N1C && N1C->getAPIntValue() == 1)
- return DAG.getNode(ISD::BR, MVT::Other, Chain, N2);
+ return DAG.getNode(ISD::BR, N->getDebugLoc(), MVT::Other, Chain, N2);
// fold a brcond with a setcc condition into a BR_CC node if BR_CC is legal
// on the target.
if (N1.getOpcode() == ISD::SETCC &&
TLI.isOperationLegalOrCustom(ISD::BR_CC, MVT::Other)) {
- return DAG.getNode(ISD::BR_CC, MVT::Other, Chain, N1.getOperand(2),
+ return DAG.getNode(ISD::BR_CC, N->getDebugLoc(), MVT::Other,
+ Chain, N1.getOperand(2),
N1.getOperand(0), N1.getOperand(1), N2);
}
+
return SDValue();
}
// fold br_cc true, dest -> br dest (unconditional branch)
if (SCCC && !SCCC->isNullValue())
- return DAG.getNode(ISD::BR, MVT::Other, N->getOperand(0),
- N->getOperand(4));
+ return DAG.getNode(ISD::BR, N->getDebugLoc(), MVT::Other,
+ N->getOperand(0), N->getOperand(4));
// fold br_cc false, dest -> unconditional fall through
if (SCCC && SCCC->isNullValue())
return N->getOperand(0);
// fold to a simpler setcc
if (Simp.getNode() && Simp.getOpcode() == ISD::SETCC)
- return DAG.getNode(ISD::BR_CC, MVT::Other, N->getOperand(0),
- Simp.getOperand(2), Simp.getOperand(0),
- Simp.getOperand(1), N->getOperand(4));
+ return DAG.getNode(ISD::BR_CC, N->getDebugLoc(), MVT::Other,
+ N->getOperand(0), Simp.getOperand(2),
+ Simp.getOperand(0), Simp.getOperand(1),
+ N->getOperand(4));
+
return SDValue();
}
-
/// CombineToPreIndexedLoadStore - Try turning a load / store into a
/// pre-indexed load / store when the base pointer is an add or subtract
/// and it has other uses besides the load / store. After the
return false;
Ptr = ST->getBasePtr();
isLoad = false;
- } else
+ } else {
return false;
+ }
// If the pointer is not an add/sub, or if it doesn't have multiple uses, bail
// out. There is no reason to make this a preinc/predec.
cast<StoreSDNode>(Use)->getBasePtr() == Ptr)))
RealUse = true;
}
+
if (!RealUse)
return false;
SDValue Result;
if (isLoad)
- Result = DAG.getIndexedLoad(SDValue(N,0), BasePtr, Offset, AM);
+ Result = DAG.getIndexedLoad(SDValue(N,0), N->getDebugLoc(),
+ BasePtr, Offset, AM);
else
- Result = DAG.getIndexedStore(SDValue(N,0), BasePtr, Offset, AM);
+ Result = DAG.getIndexedStore(SDValue(N,0), N->getDebugLoc(),
+ BasePtr, Offset, AM);
++PreIndexedNodes;
++NodesCombined;
DOUT << "\nReplacing.4 "; DEBUG(N->dump(&DAG));
return false;
Ptr = ST->getBasePtr();
isLoad = false;
- } else
+ } else {
return false;
+ }
if (Ptr.getNode()->hasOneUse())
return false;
}
}
}
+
if (TryNext)
continue;
// Check for #2
if (!Op->isPredecessorOf(N) && !N->isPredecessorOf(Op)) {
SDValue Result = isLoad
- ? DAG.getIndexedLoad(SDValue(N,0), BasePtr, Offset, AM)
- : DAG.getIndexedStore(SDValue(N,0), BasePtr, Offset, AM);
+ ? DAG.getIndexedLoad(SDValue(N,0), N->getDebugLoc(),
+ BasePtr, Offset, AM)
+ : DAG.getIndexedStore(SDValue(N,0), N->getDebugLoc(),
+ BasePtr, Offset, AM);
++PostIndexedNodes;
++NodesCombined;
DOUT << "\nReplacing.5 "; DEBUG(N->dump(&DAG));
}
}
}
+
return false;
}
if (!Fast && LD->isUnindexed()) {
if (unsigned Align = InferAlignment(Ptr, DAG)) {
if (Align > LD->getAlignment())
- return DAG.getExtLoad(LD->getExtensionType(), LD->getValueType(0),
+ return DAG.getExtLoad(LD->getExtensionType(), N->getDebugLoc(),
+ LD->getValueType(0),
Chain, Ptr, LD->getSrcValue(),
LD->getSrcValueOffset(), LD->getMemoryVT(),
LD->isVolatile(), Align);
}
}
-
// If load is not volatile and there are no uses of the loaded value (and
// the updated indexed value in case of indexed loads), change uses of the
DOUT << "\n";
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Chain, &DeadNodes);
+
if (N->use_empty()) {
removeFromWorkList(N);
DAG.DeleteNode(N);
}
+
return SDValue(N, 0); // Return N so it doesn't get rechecked!
}
} else {
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Undef, &DeadNodes);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1),
- DAG.getNode(ISD::UNDEF, N->getValueType(1)),
+ DAG.getNode(ISD::UNDEF, N->getDebugLoc(),
+ N->getValueType(1)),
&DeadNodes);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 2), Chain, &DeadNodes);
removeFromWorkList(N);
// Replace the chain to void dependency.
if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
- ReplLoad = DAG.getLoad(N->getValueType(0), BetterChain, Ptr,
+ ReplLoad = DAG.getLoad(N->getValueType(0), LD->getDebugLoc(),
+ BetterChain, Ptr,
LD->getSrcValue(), LD->getSrcValueOffset(),
LD->isVolatile(), LD->getAlignment());
} else {
- ReplLoad = DAG.getExtLoad(LD->getExtensionType(),
+ ReplLoad = DAG.getExtLoad(LD->getExtensionType(), LD->getDebugLoc(),
LD->getValueType(0),
BetterChain, Ptr, LD->getSrcValue(),
LD->getSrcValueOffset(),
}
// Create token factor to keep old chain connected.
- SDValue Token = DAG.getNode(ISD::TokenFactor, MVT::Other,
- Chain, ReplLoad.getValue(1));
+ SDValue Token = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(),
+ MVT::Other, Chain, ReplLoad.getValue(1));
// Replace uses with load result and token factor. Don't add users
// to work list.
return SDValue();
}
-
SDValue DAGCombiner::visitSTORE(SDNode *N) {
StoreSDNode *ST = cast<StoreSDNode>(N);
SDValue Chain = ST->getChain();
if (!Fast && ST->isUnindexed()) {
if (unsigned Align = InferAlignment(Ptr, DAG)) {
if (Align > ST->getAlignment())
- return DAG.getTruncStore(Chain, Value, Ptr, ST->getSrcValue(),
+ return DAG.getTruncStore(Chain, N->getDebugLoc(), Value,
+ Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->getMemoryVT(),
ST->isVolatile(), Align);
}
if (Align <= OrigAlign &&
((!LegalOperations && !ST->isVolatile()) ||
TLI.isOperationLegalOrCustom(ISD::STORE, SVT)))
- return DAG.getStore(Chain, Value.getOperand(0), Ptr, ST->getSrcValue(),
+ return DAG.getStore(Chain, N->getDebugLoc(), Value.getOperand(0),
+ Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->isVolatile(), OrigAlign);
}
TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) {
Tmp = DAG.getConstant((uint32_t)CFP->getValueAPF().
bitcastToAPInt().getZExtValue(), MVT::i32);
- return DAG.getStore(Chain, Tmp, Ptr, ST->getSrcValue(),
+ return DAG.getStore(Chain, N->getDebugLoc(), Tmp,
+ Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->isVolatile(),
ST->getAlignment());
}
!ST->isVolatile()) ||
TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i64)) {
Tmp = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt().
- getZExtValue(), MVT::i64);
- return DAG.getStore(Chain, Tmp, Ptr, ST->getSrcValue(),
+ getZExtValue(), MVT::i64);
+ return DAG.getStore(Chain, N->getDebugLoc(), Tmp,
+ Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->isVolatile(),
ST->getAlignment());
} else if (!ST->isVolatile() &&
unsigned Alignment = ST->getAlignment();
bool isVolatile = ST->isVolatile();
- SDValue St0 = DAG.getStore(Chain, Lo, Ptr, ST->getSrcValue(),
- ST->getSrcValueOffset(),
- isVolatile, ST->getAlignment());
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ SDValue St0 = DAG.getStore(Chain, ST->getDebugLoc(), Lo,
+ Ptr, ST->getSrcValue(),
+ ST->getSrcValueOffset(),
+ isVolatile, ST->getAlignment());
+ Ptr = DAG.getNode(ISD::ADD, N->getDebugLoc(), Ptr.getValueType(), Ptr,
DAG.getConstant(4, Ptr.getValueType()));
SVOffset += 4;
Alignment = MinAlign(Alignment, 4U);
- SDValue St1 = DAG.getStore(Chain, Hi, Ptr, ST->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- return DAG.getNode(ISD::TokenFactor, MVT::Other, St0, St1);
+ SDValue St1 = DAG.getStore(Chain, ST->getDebugLoc(), Hi,
+ Ptr, ST->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+ return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other,
+ St0, St1);
}
+
break;
}
}
// Replace the chain to avoid dependency.
SDValue ReplStore;
if (ST->isTruncatingStore()) {
- ReplStore = DAG.getTruncStore(BetterChain, Value, Ptr,
+ ReplStore = DAG.getTruncStore(BetterChain, N->getDebugLoc(), Value, Ptr,
ST->getSrcValue(),ST->getSrcValueOffset(),
ST->getMemoryVT(),
ST->isVolatile(), ST->getAlignment());
} else {
- ReplStore = DAG.getStore(BetterChain, Value, Ptr,
+ ReplStore = DAG.getStore(BetterChain, N->getDebugLoc(), Value, Ptr,
ST->getSrcValue(), ST->getSrcValueOffset(),
ST->isVolatile(), ST->getAlignment());
}
// Create token to keep both nodes around.
- SDValue Token =
- DAG.getNode(ISD::TokenFactor, MVT::Other, Chain, ReplStore);
-
+ SDValue Token = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(),
+ MVT::Other, Chain, ReplStore);
+
// Don't add users to work list.
return CombineTo(N, Token, false);
}
// "truncstore (or (shl x, 8), y), i8" -> "truncstore y, i8"
SDValue Shorter =
GetDemandedBits(Value,
- APInt::getLowBitsSet(Value.getValueSizeInBits(),
- ST->getMemoryVT().getSizeInBits()));
+ APInt::getLowBitsSet(Value.getValueSizeInBits(),
+ ST->getMemoryVT().getSizeInBits()));
AddToWorkList(Value.getNode());
if (Shorter.getNode())
- return DAG.getTruncStore(Chain, Shorter, Ptr, ST->getSrcValue(),
+ return DAG.getTruncStore(Chain, N->getDebugLoc(), Shorter,
+ Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->getMemoryVT(),
ST->isVolatile(), ST->getAlignment());
&& Value.getNode()->hasOneUse() && ST->isUnindexed() &&
TLI.isTruncStoreLegal(Value.getOperand(0).getValueType(),
ST->getMemoryVT())) {
- return DAG.getTruncStore(Chain, Value.getOperand(0), Ptr, ST->getSrcValue(),
+ return DAG.getTruncStore(Chain, N->getDebugLoc(), Value.getOperand(0),
+ Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->getMemoryVT(),
ST->isVolatile(), ST->getAlignment());
}
InVec.getNode()->op_end());
if (Elt < Ops.size())
Ops[Elt] = InVal;
- return DAG.getNode(ISD::BUILD_VECTOR, InVec.getValueType(),
- &Ops[0], Ops.size());
+ return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(),
+ InVec.getValueType(), &Ops[0], Ops.size());
}
return SDValue();
MVT VT = InVec.getValueType();
MVT EVT = VT.getVectorElementType();
MVT LVT = EVT;
+
if (InVec.getOpcode() == ISD::BIT_CONVERT) {
MVT BCVT = InVec.getOperand(0).getValueType();
if (!BCVT.isVector() || EVT.bitsGT(BCVT.getVectorElementType()))
}
LoadSDNode *LN0 = NULL;
- if (ISD::isNormalLoad(InVec.getNode()))
+ if (ISD::isNormalLoad(InVec.getNode())) {
LN0 = cast<LoadSDNode>(InVec);
- else if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR &&
- InVec.getOperand(0).getValueType() == EVT &&
- ISD::isNormalLoad(InVec.getOperand(0).getNode())) {
+ } else if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR &&
+ InVec.getOperand(0).getValueType() == EVT &&
+ ISD::isNormalLoad(InVec.getOperand(0).getNode())) {
LN0 = cast<LoadSDNode>(InVec.getOperand(0));
} else if (InVec.getOpcode() == ISD::VECTOR_SHUFFLE) {
// (vextract (vector_shuffle (load $addr), v2, <1, u, u, u>), 1)
Elt = (Idx < NumElems) ? Idx : Idx - NumElems;
}
}
+
if (!LN0 || !LN0->hasOneUse() || LN0->isVolatile())
return SDValue();
if (NewLoad) {
// Check the resultant load doesn't need a higher alignment than the
// original load.
- unsigned NewAlign = TLI.getTargetData()->
- getABITypeAlignment(LVT.getTypeForMVT());
+ unsigned NewAlign =
+ TLI.getTargetData()->getABITypeAlignment(LVT.getTypeForMVT());
+
if (NewAlign > Align || !TLI.isOperationLegalOrCustom(ISD::LOAD, LVT))
return SDValue();
+
Align = NewAlign;
}
MVT PtrType = NewPtr.getValueType();
if (TLI.isBigEndian())
PtrOff = VT.getSizeInBits() / 8 - PtrOff;
- NewPtr = DAG.getNode(ISD::ADD, PtrType, NewPtr,
+ NewPtr = DAG.getNode(ISD::ADD, N->getDebugLoc(), PtrType, NewPtr,
DAG.getConstant(PtrOff, PtrType));
}
- return DAG.getLoad(LVT, LN0->getChain(), NewPtr,
+
+ return DAG.getLoad(LVT, N->getDebugLoc(), LN0->getChain(), NewPtr,
LN0->getSrcValue(), LN0->getSrcValueOffset(),
LN0->isVolatile(), Align);
}
+
return SDValue();
}
-
SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) {
unsigned NumInScalars = N->getNumOperands();
SmallVector<SDValue, 8> BuildVecIndices;
for (unsigned i = 0; i != NumInScalars; ++i) {
if (N->getOperand(i).getOpcode() == ISD::UNDEF) {
- BuildVecIndices.push_back(DAG.getNode(ISD::UNDEF, TLI.getPointerTy()));
+ BuildVecIndices.push_back(DAG.getNode(ISD::UNDEF,
+ N->getDebugLoc(),
+ TLI.getPointerTy()));
continue;
}
} else {
// Use an undef build_vector as input for the second operand.
std::vector<SDValue> UnOps(NumInScalars,
- DAG.getNode(ISD::UNDEF,
- EltType));
- Ops[1] = DAG.getNode(ISD::BUILD_VECTOR, VT,
+ DAG.getNode(ISD::UNDEF, EltType));
+ Ops[1] = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT,
&UnOps[0], UnOps.size());
AddToWorkList(Ops[1].getNode());
}
- Ops[2] = DAG.getNode(ISD::BUILD_VECTOR, BuildVecVT,
+
+ Ops[2] = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), BuildVecVT,
&BuildVecIndices[0], BuildVecIndices.size());
- return DAG.getNode(ISD::VECTOR_SHUFFLE, VT, Ops, 3);
+ return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(), VT, Ops, 3);
}
return SDValue();
// node.
// If we only have one input vector, we don't need to do any concatenation.
- if (N->getNumOperands() == 1) {
+ if (N->getNumOperands() == 1)
return N->getOperand(0);
- }
return SDValue();
}
// Check the SHUFFLE mask, mapping any inputs from the 2nd operand into the
// first operand.
SmallVector<SDValue, 8> MappedOps;
+
for (unsigned i = 0; i != NumElts; ++i) {
if (ShufMask.getOperand(i).getOpcode() == ISD::UNDEF ||
cast<ConstantSDNode>(ShufMask.getOperand(i))->getZExtValue() <
ShufMask.getOperand(i).getValueType()));
}
}
- ShufMask = DAG.getNode(ISD::BUILD_VECTOR, ShufMask.getValueType(),
+
+ ShufMask = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(),
+ ShufMask.getValueType(),
&MappedOps[0], MappedOps.size());
AddToWorkList(ShufMask.getNode());
- return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getValueType(0),
- N0,
+ return DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(),
+ N->getValueType(0), N0,
DAG.getNode(ISD::UNDEF, N->getValueType(0)),
ShufMask);
}
MVT VT = MVT::getVectorVT(EVT, NumElts);
MVT MaskVT = MVT::getVectorVT(TLI.getPointerTy(), NumElts);
std::vector<SDValue> Ops;
- LHS = DAG.getNode(ISD::BIT_CONVERT, VT, LHS);
+ LHS = DAG.getNode(ISD::BIT_CONVERT, LHS.getDebugLoc(), VT, LHS);
Ops.push_back(LHS);
AddToWorkList(LHS.getNode());
std::vector<SDValue> ZeroOps(NumElts, DAG.getConstant(0, EVT));
- Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, VT,
- &ZeroOps[0], ZeroOps.size()));
- Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, MaskVT,
- &IdxOps[0], IdxOps.size()));
- SDValue Result = DAG.getNode(ISD::VECTOR_SHUFFLE, VT,
- &Ops[0], Ops.size());
+ Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(),
+ VT, &ZeroOps[0], ZeroOps.size()));
+ Ops.push_back(DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(),
+ MaskVT, &IdxOps[0], IdxOps.size()));
+ SDValue Result = DAG.getNode(ISD::VECTOR_SHUFFLE, N->getDebugLoc(),
+ VT, &Ops[0], Ops.size());
+
if (VT != N->getValueType(0))
- Result = DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Result);
+ Result = DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(),
+ N->getValueType(0), Result);
+
return Result;
}
}
+
return SDValue();
}
RHSOp.getOpcode() != ISD::Constant &&
RHSOp.getOpcode() != ISD::ConstantFP))
break;
+
// Can't fold divide by zero.
if (N->getOpcode() == ISD::SDIV || N->getOpcode() == ISD::UDIV ||
N->getOpcode() == ISD::FDIV) {
cast<ConstantFPSDNode>(RHSOp.getNode())->getValueAPF().isZero()))
break;
}
- Ops.push_back(DAG.getNode(N->getOpcode(), EltType, LHSOp, RHSOp));
+
+ Ops.push_back(DAG.getNode(N->getOpcode(), LHS.getDebugLoc(),
+ EltType, LHSOp, RHSOp));
AddToWorkList(Ops.back().getNode());
assert((Ops.back().getOpcode() == ISD::UNDEF ||
Ops.back().getOpcode() == ISD::Constant ||
if (Ops.size() == LHS.getNumOperands()) {
MVT VT = LHS.getValueType();
- return DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], Ops.size());
+ return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT,
+ &Ops[0], Ops.size());
}
}
return SDValue();
}
-SDValue DAGCombiner::SimplifySelect(SDValue N0, SDValue N1, SDValue N2){
+SDValue DAGCombiner::SimplifySelect(DebugLoc DL, SDValue N0,
+ SDValue N1, SDValue N2){
assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!");
- SDValue SCC = SimplifySelectCC(N0.getOperand(0), N0.getOperand(1), N1, N2,
+ SDValue SCC = SimplifySelectCC(DL, N0.getOperand(0), N0.getOperand(1), N1, N2,
cast<CondCodeSDNode>(N0.getOperand(2))->get());
+
// If we got a simplified select_cc node back from SimplifySelectCC, then
// break it down into a new SETCC node, and a new SELECT node, and then return
// the SELECT node, since we were called with a SELECT node.
// Check to see if we got a select_cc back (to turn into setcc/select).
// Otherwise, just return whatever node we got back, like fabs.
if (SCC.getOpcode() == ISD::SELECT_CC) {
- SDValue SETCC = DAG.getNode(ISD::SETCC, N0.getValueType(),
- SCC.getOperand(0), SCC.getOperand(1),
- SCC.getOperand(4));
+ SDValue SETCC = DAG.getNode(ISD::SETCC, N0.getDebugLoc(),
+ N0.getValueType(),
+ SCC.getOperand(0), SCC.getOperand(1),
+ SCC.getOperand(4));
AddToWorkList(SETCC.getNode());
- return DAG.getNode(ISD::SELECT, SCC.getValueType(), SCC.getOperand(2),
- SCC.getOperand(3), SETCC);
+ return DAG.getNode(ISD::SELECT, SCC.getDebugLoc(), SCC.getValueType(),
+ SCC.getOperand(2), SCC.getOperand(3), SETCC);
}
+
return SCC;
}
return SDValue();
/// returns true. As such, they should return the appropriate thing (e.g. the
/// node) back to the top-level of the DAG combiner loop to avoid it being
/// looked at.
-///
bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS,
SDValue RHS) {
// this will induce a cycle into the DAG.
if (!LLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) &&
!RLD->isPredecessorOf(TheSelect->getOperand(0).getNode())) {
- Addr = DAG.getNode(ISD::SELECT, LLD->getBasePtr().getValueType(),
+ Addr = DAG.getNode(ISD::SELECT, TheSelect->getDebugLoc(),
+ LLD->getBasePtr().getValueType(),
TheSelect->getOperand(0), LLD->getBasePtr(),
RLD->getBasePtr());
}
!RLD->isPredecessorOf(TheSelect->getOperand(0).getNode()) &&
!LLD->isPredecessorOf(TheSelect->getOperand(1).getNode()) &&
!RLD->isPredecessorOf(TheSelect->getOperand(1).getNode())) {
- Addr = DAG.getNode(ISD::SELECT_CC, LLD->getBasePtr().getValueType(),
- TheSelect->getOperand(0),
- TheSelect->getOperand(1),
- LLD->getBasePtr(), RLD->getBasePtr(),
- TheSelect->getOperand(4));
+ Addr = DAG.getNode(ISD::SELECT_CC, TheSelect->getDebugLoc(),
+ LLD->getBasePtr().getValueType(),
+ TheSelect->getOperand(0),
+ TheSelect->getOperand(1),
+ LLD->getBasePtr(), RLD->getBasePtr(),
+ TheSelect->getOperand(4));
}
}
if (Addr.getNode()) {
SDValue Load;
- if (LLD->getExtensionType() == ISD::NON_EXTLOAD)
- Load = DAG.getLoad(TheSelect->getValueType(0), LLD->getChain(),
+ if (LLD->getExtensionType() == ISD::NON_EXTLOAD) {
+ Load = DAG.getLoad(TheSelect->getValueType(0),
+ TheSelect->getDebugLoc(),
+ LLD->getChain(),
Addr,LLD->getSrcValue(),
LLD->getSrcValueOffset(),
LLD->isVolatile(),
LLD->getAlignment());
- else {
+ } else {
Load = DAG.getExtLoad(LLD->getExtensionType(),
+ TheSelect->getDebugLoc(),
TheSelect->getValueType(0),
LLD->getChain(), Addr, LLD->getSrcValue(),
LLD->getSrcValueOffset(),
LLD->isVolatile(),
LLD->getAlignment());
}
+
// Users of the select now use the result of the load.
CombineTo(TheSelect, Load);
return false;
}
-SDValue DAGCombiner::SimplifySelectCC(SDValue N0, SDValue N1,
+SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
SDValue N2, SDValue N3,
ISD::CondCode CC, bool NotExtCompare) {
-
MVT VT = N2.getValueType();
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode());
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.getNode());
if ((CC == ISD::SETGE || CC == ISD::SETGT) &&
N0 == N2 && N3.getOpcode() == ISD::FNEG &&
N2 == N3.getOperand(0))
- return DAG.getNode(ISD::FABS, VT, N0);
+ return DAG.getNode(ISD::FABS, DL, VT, N0);
// select (setl[te] X, +/-0.0), fneg(X), X -> fabs
if ((CC == ISD::SETLT || CC == ISD::SETLE) &&
N0 == N3 && N2.getOpcode() == ISD::FNEG &&
N2.getOperand(0) == N3)
- return DAG.getNode(ISD::FABS, VT, N3);
+ return DAG.getNode(ISD::FABS, DL, VT, N3);
}
}
// Check to see if we can perform the "gzip trick", transforming
- // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A
+ // (select_cc setlt X, 0, A, 0) -> (and (sra X, (sub size(X), 1), A)
if (N1C && N3C && N3C->isNullValue() && CC == ISD::SETLT &&
N0.getValueType().isInteger() &&
N2.getValueType().isInteger() &&
if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) {
unsigned ShCtV = N2C->getAPIntValue().logBase2();
ShCtV = XType.getSizeInBits()-ShCtV-1;
- SDValue ShCt = DAG.getConstant(ShCtV, TLI.getShiftAmountTy());
- SDValue Shift = DAG.getNode(ISD::SRL, XType, N0, ShCt);
+ SDValue ShCt = DAG.getConstant(ShCtV, getShiftAmountTy());
+ SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(),
+ XType, N0, ShCt);
AddToWorkList(Shift.getNode());
+
if (XType.bitsGT(AType)) {
- Shift = DAG.getNode(ISD::TRUNCATE, AType, Shift);
+ Shift = DAG.getNode(ISD::TRUNCATE, DL, AType, Shift);
AddToWorkList(Shift.getNode());
}
- return DAG.getNode(ISD::AND, AType, Shift, N2);
+
+ return DAG.getNode(ISD::AND, DL, AType, Shift, N2);
}
- SDValue Shift = DAG.getNode(ISD::SRA, XType, N0,
- DAG.getConstant(XType.getSizeInBits()-1,
- TLI.getShiftAmountTy()));
+
+ SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(),
+ XType, N0,
+ DAG.getConstant(XType.getSizeInBits()-1,
+ getShiftAmountTy()));
AddToWorkList(Shift.getNode());
+
if (XType.bitsGT(AType)) {
- Shift = DAG.getNode(ISD::TRUNCATE, AType, Shift);
+ Shift = DAG.getNode(ISD::TRUNCATE, DL, AType, Shift);
AddToWorkList(Shift.getNode());
}
- return DAG.getNode(ISD::AND, AType, Shift, N2);
+
+ return DAG.getNode(ISD::AND, DL, AType, Shift, N2);
}
}
SDValue Temp, SCC;
// cast from setcc result type to select result type
if (LegalTypes) {
- SCC = DAG.getSetCC(TLI.getSetCCResultType(N0.getValueType()),
+ SCC = DAG.getSetCC(DL, TLI.getSetCCResultType(N0.getValueType()),
N0, N1, CC);
if (N2.getValueType().bitsLT(SCC.getValueType()))
- Temp = DAG.getZeroExtendInReg(SCC, N2.getValueType());
+ Temp = DAG.getZeroExtendInReg(SCC, N2.getDebugLoc(), N2.getValueType());
else
- Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getValueType(), SCC);
+ Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getDebugLoc(),
+ N2.getValueType(), SCC);
} else {
- SCC = DAG.getSetCC(MVT::i1, N0, N1, CC);
- Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getValueType(), SCC);
+ SCC = DAG.getSetCC(N0.getDebugLoc(), MVT::i1, N0, N1, CC);
+ Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getDebugLoc(),
+ N2.getValueType(), SCC);
}
+
AddToWorkList(SCC.getNode());
AddToWorkList(Temp.getNode());
if (N2C->getAPIntValue() == 1)
return Temp;
+
// shl setcc result by log2 n2c
- return DAG.getNode(ISD::SHL, N2.getValueType(), Temp,
+ return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp,
DAG.getConstant(N2C->getAPIntValue().logBase2(),
- TLI.getShiftAmountTy()));
+ getShiftAmountTy()));
}
// Check to see if this is the equivalent of setcc
MVT XType = N0.getValueType();
if (!LegalOperations ||
TLI.isOperationLegal(ISD::SETCC, TLI.getSetCCResultType(XType))) {
- SDValue Res = DAG.getSetCC(TLI.getSetCCResultType(XType), N0, N1, CC);
+ SDValue Res = DAG.getSetCC(DL, TLI.getSetCCResultType(XType), N0, N1, CC);
if (Res.getValueType() != VT)
- Res = DAG.getNode(ISD::ZERO_EXTEND, VT, Res);
+ Res = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Res);
return Res;
}
- // seteq X, 0 -> srl (ctlz X, log2(size(X)))
+ // fold (seteq X, 0) -> (srl (ctlz X, log2(size(X))))
if (N1C && N1C->isNullValue() && CC == ISD::SETEQ &&
(!LegalOperations ||
TLI.isOperationLegal(ISD::CTLZ, XType))) {
- SDValue Ctlz = DAG.getNode(ISD::CTLZ, XType, N0);
- return DAG.getNode(ISD::SRL, XType, Ctlz,
+ SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0);
+ return DAG.getNode(ISD::SRL, DL, XType, Ctlz,
DAG.getConstant(Log2_32(XType.getSizeInBits()),
- TLI.getShiftAmountTy()));
+ getShiftAmountTy()));
}
- // setgt X, 0 -> srl (and (-X, ~X), size(X)-1)
+ // fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1))
if (N1C && N1C->isNullValue() && CC == ISD::SETGT) {
- SDValue NegN0 = DAG.getNode(ISD::SUB, XType, DAG.getConstant(0, XType),
- N0);
- SDValue NotN0 = DAG.getNOT(N0, XType);
- return DAG.getNode(ISD::SRL, XType,
+ SDValue NegN0 = DAG.getNode(ISD::SUB, N0.getDebugLoc(),
+ XType, DAG.getConstant(0, XType), N0);
+ SDValue NotN0 = DAG.getNOT(N0.getDebugLoc(), N0, XType);
+ return DAG.getNode(ISD::SRL, DL, XType,
DAG.getNode(ISD::AND, XType, NegN0, NotN0),
DAG.getConstant(XType.getSizeInBits()-1,
- TLI.getShiftAmountTy()));
+ getShiftAmountTy()));
}
- // setgt X, -1 -> xor (srl (X, size(X)-1), 1)
+ // fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1))
if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) {
- SDValue Sign = DAG.getNode(ISD::SRL, XType, N0,
- DAG.getConstant(XType.getSizeInBits()-1,
- TLI.getShiftAmountTy()));
- return DAG.getNode(ISD::XOR, XType, Sign, DAG.getConstant(1, XType));
+ SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0,
+ DAG.getConstant(XType.getSizeInBits()-1,
+ getShiftAmountTy()));
+ return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType));
}
}
N0 == N3 && N2.getOpcode() == ISD::SUB && N0 == N2.getOperand(1) &&
N2.getOperand(0) == N1 && N0.getValueType().isInteger()) {
MVT XType = N0.getValueType();
- SDValue Shift = DAG.getNode(ISD::SRA, XType, N0,
- DAG.getConstant(XType.getSizeInBits()-1,
- TLI.getShiftAmountTy()));
- SDValue Add = DAG.getNode(ISD::ADD, XType, N0, Shift);
+ SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0,
+ DAG.getConstant(XType.getSizeInBits()-1,
+ getShiftAmountTy()));
+ SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), XType,
+ N0, Shift);
AddToWorkList(Shift.getNode());
AddToWorkList(Add.getNode());
- return DAG.getNode(ISD::XOR, XType, Add, Shift);
+ return DAG.getNode(ISD::XOR, DL, XType, Add, Shift);
}
// Check to see if this is an integer abs. select_cc setgt X, -1, X, -X ->
// Y = sra (X, size(X)-1); xor (add (X, Y), Y)
if (ConstantSDNode *SubC = dyn_cast<ConstantSDNode>(N3.getOperand(0))) {
MVT XType = N0.getValueType();
if (SubC->isNullValue() && XType.isInteger()) {
- SDValue Shift = DAG.getNode(ISD::SRA, XType, N0,
- DAG.getConstant(XType.getSizeInBits()-1,
- TLI.getShiftAmountTy()));
- SDValue Add = DAG.getNode(ISD::ADD, XType, N0, Shift);
+ SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType,
+ N0,
+ DAG.getConstant(XType.getSizeInBits()-1,
+ getShiftAmountTy()));
+ SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(),
+ XType, N0, Shift);
AddToWorkList(Shift.getNode());
AddToWorkList(Add.getNode());
- return DAG.getNode(ISD::XOR, XType, Add, Shift);
+ return DAG.getNode(ISD::XOR, DL, XType, Add, Shift);
}
}
}
bool DAGCombiner::isAlias(SDValue Ptr1, int64_t Size1,
const Value *SrcValue1, int SrcValueOffset1,
SDValue Ptr2, int64_t Size2,
- const Value *SrcValue2, int SrcValueOffset2)
-{
+ const Value *SrcValue2, int SrcValueOffset2) const {
// If they are the same then they must be aliases.
if (Ptr1 == Ptr2) return true;
bool KnownBase2 = FindBaseOffset(Ptr2, Base2, Offset2);
// If they have a same base address then...
- if (Base1 == Base2) {
+ if (Base1 == Base2)
// Check to see if the addresses overlap.
- return!((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1);
- }
+ return !((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1);
// If we know both bases then they can't alias.
if (KnownBase1 && KnownBase2) return false;
/// node. Returns true if the operand was a load.
bool DAGCombiner::FindAliasInfo(SDNode *N,
SDValue &Ptr, int64_t &Size,
- const Value *&SrcValue, int &SrcValueOffset) {
+ const Value *&SrcValue, int &SrcValueOffset) const {
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
Ptr = LD->getBasePtr();
Size = LD->getMemoryVT().getSizeInBits() >> 3;