SDOperand CombineTo(SDNode *N, const std::vector<SDOperand> &To) {
++NodesCombined;
DEBUG(std::cerr << "\nReplacing "; N->dump();
- std::cerr << "\nWith: "; To[0].Val->dump();
+ std::cerr << "\nWith: "; To[0].Val->dump(&DAG);
std::cerr << " and " << To.size()-1 << " other values\n");
std::vector<SDNode*> NowDead;
DAG.ReplaceAllUsesWith(N, To, &NowDead);
// Replace the old value with the new one.
++NodesCombined;
DEBUG(std::cerr << "\nReplacing "; TLO.Old.Val->dump();
- std::cerr << "\nWith: "; TLO.New.Val->dump());
+ std::cerr << "\nWith: "; TLO.New.Val->dump(&DAG));
std::vector<SDNode*> NowDead;
DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, NowDead);
// mechanics for us, we have no work to do in this case.
if (RV.Val != N) {
DEBUG(std::cerr << "\nReplacing "; N->dump();
- std::cerr << "\nWith: "; RV.Val->dump();
+ std::cerr << "\nWith: "; RV.Val->dump(&DAG);
std::cerr << '\n');
std::vector<SDNode*> NowDead;
DAG.ReplaceAllUsesWith(N, std::vector<SDOperand>(1, RV), &NowDead);
// If the token factor has two operands and one is the entry token, replace
// the token factor with the other operand.
if (N->getNumOperands() == 2) {
- if (N->getOperand(0).getOpcode() == ISD::EntryToken)
+ if (N->getOperand(0).getOpcode() == ISD::EntryToken ||
+ N->getOperand(0) == N->getOperand(1))
return N->getOperand(1);
if (N->getOperand(1).getOpcode() == ISD::EntryToken)
return N->getOperand(0);
Changed = true;
for (unsigned j = 0, e = Op.getNumOperands(); j != e; ++j)
Ops.push_back(Op.getOperand(j));
- } else {
+ } else if (i == 0 || N->getOperand(i) != N->getOperand(i-1)) {
Ops.push_back(Op);
+ } else {
+ // Deleted an operand that was the same as the last one.
+ Changed = true;
}
}
if (Changed)
// fold (OP (zext x), (zext y)) -> (zext (OP x, y))
// fold (OP (sext x), (sext y)) -> (sext (OP x, y))
// fold (OP (aext x), (aext y)) -> (aext (OP x, y))
+ // fold (OP (trunc x), (trunc y)) -> (trunc (OP x, y))
if ((N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND||
- N0.getOpcode() == ISD::SIGN_EXTEND) &&
+ N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::TRUNCATE) &&
N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
SDOperand ORNode = DAG.getNode(N->getOpcode(),
N0.getOperand(0).getValueType(),
return DAG.getNode(N0.getOpcode(), VT, ORNode);
}
- // fold (and (trunc x), (trunc y)) -> (trunc (and x, y))
- // fold (or (trunc x), (trunc y)) -> (trunc (or x, y))
- // fold (xor (trunc x), (trunc y)) -> (trunc (xor x, y))
- if (N0.getOpcode() == ISD::TRUNCATE &&
- N0.getOperand(0).getValueType() == N1.getOperand(0).getValueType()) {
- SDOperand ORNode = DAG.getNode(N->getOpcode(),
- N0.getOperand(0).getValueType(),
- N0.getOperand(0), N1.getOperand(0));
- AddToWorkList(ORNode.Val);
- return DAG.getNode(ISD::TRUNCATE, VT, ORNode);
- }
-
-
// For each of OP in SHL/SRL/SRA/AND...
// fold (and (OP x, z), (OP y, z)) -> (OP (and x, y), z)
// fold (or (OP x, z), (OP y, z)) -> (OP (or x, y), z)
}
}
+ // Simplify, based on bits shifted out of the LHS.
+ if (N1C && SimplifyDemandedBits(SDOperand(N, 0)))
+ return SDOperand(N, 0);
+
+
// If the sign bit is known to be zero, switch this to a SRL.
if (TLI.MaskedValueIsZero(N0, MVT::getIntVTSignBit(VT)))
return DAG.getNode(ISD::SRL, VT, N0, N1);
DAG.getConstant(c1 + c2, N1.getValueType()));
}
+ // fold (srl (anyextend x), c) -> (anyextend (srl x, c))
+ if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) {
+ // Shifting in all undef bits?
+ MVT::ValueType SmallVT = N0.getOperand(0).getValueType();
+ if (N1C->getValue() >= MVT::getSizeInBits(SmallVT))
+ return DAG.getNode(ISD::UNDEF, VT);
+
+ SDOperand SmallShift = DAG.getNode(ISD::SRL, SmallVT, N0.getOperand(0), N1);
+ AddToWorkList(SmallShift.Val);
+ return DAG.getNode(ISD::ANY_EXTEND, VT, SmallShift);
+ }
+
// fold (srl (ctlz x), "5") -> x iff x has one bit set (the low bit).
if (N1C && N0.getOpcode() == ISD::CTLZ &&
N1C->getValue() == Log2_32(MVT::getSizeInBits(VT))) {
SDOperand DAGCombiner::visitCTLZ(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (ctlz c1) -> c2
- if (N0C)
+ if (isa<ConstantSDNode>(N0))
return DAG.getNode(ISD::CTLZ, VT, N0);
return SDOperand();
}
SDOperand DAGCombiner::visitCTTZ(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (cttz c1) -> c2
- if (N0C)
+ if (isa<ConstantSDNode>(N0))
return DAG.getNode(ISD::CTTZ, VT, N0);
return SDOperand();
}
SDOperand DAGCombiner::visitCTPOP(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (ctpop c1) -> c2
- if (N0C)
+ if (isa<ConstantSDNode>(N0))
return DAG.getNode(ISD::CTPOP, VT, N0);
return SDOperand();
}
SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (sext c1) -> c1
- if (N0C)
+ if (ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0))
return DAG.getNode(ISD::SIGN_EXTEND, VT, N0);
+
// fold (sext (sext x)) -> (sext x)
- if (N0.getOpcode() == ISD::SIGN_EXTEND)
+ // 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));
+
// fold (sext (truncate x)) -> (sextinreg x) iff x size == sext size.
if (N0.getOpcode() == ISD::TRUNCATE && N0.getOperand(0).getValueType() == VT&&
(!AfterLegalize ||
TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, N0.getValueType())))
return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0.getOperand(0),
DAG.getValueType(N0.getValueType()));
+
// fold (sext (load x)) -> (sext (truncate (sextload x)))
if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse() &&
(!AfterLegalize||TLI.isOperationLegal(ISD::SEXTLOAD, N0.getValueType()))){
// fold (sext ( extload x)) -> (sext (truncate (sextload x)))
if ((N0.getOpcode() == ISD::SEXTLOAD || N0.getOpcode() == ISD::EXTLOAD) &&
N0.hasOneUse()) {
- SDOperand ExtLoad = DAG.getNode(ISD::SEXTLOAD, VT, N0.getOperand(0),
- N0.getOperand(1), N0.getOperand(2),
- N0.getOperand(3));
+ MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
+ SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, N0.getOperand(0),
+ N0.getOperand(1), N0.getOperand(2), EVT);
CombineTo(N, ExtLoad);
CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
ExtLoad.getValue(1));
SDOperand DAGCombiner::visitZERO_EXTEND(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (zext c1) -> c1
- if (N0C)
+ if (ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0))
return DAG.getNode(ISD::ZERO_EXTEND, VT, N0);
// fold (zext (zext x)) -> (zext x)
- if (N0.getOpcode() == ISD::ZERO_EXTEND)
+ // 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));
// fold (zext (truncate x)) -> (zextinreg x) iff x size == zext size.
if (N0.getOpcode() == ISD::TRUNCATE && N0.getOperand(0).getValueType() == VT&&
// fold (zext ( extload x)) -> (zext (truncate (zextload x)))
if ((N0.getOpcode() == ISD::ZEXTLOAD || N0.getOpcode() == ISD::EXTLOAD) &&
N0.hasOneUse()) {
- SDOperand ExtLoad = DAG.getNode(ISD::ZEXTLOAD, VT, N0.getOperand(0),
- N0.getOperand(1), N0.getOperand(2),
- N0.getOperand(3));
+ MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
+ SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, N0.getOperand(0),
+ N0.getOperand(1), N0.getOperand(2), EVT);
CombineTo(N, ExtLoad);
CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
ExtLoad.getValue(1));
SDOperand DAGCombiner::visitANY_EXTEND(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (aext c1) -> c1
- if (N0C)
+ if (isa<ConstantSDNode>(N0))
return DAG.getNode(ISD::ANY_EXTEND, VT, N0);
// fold (aext (aext x)) -> (aext x)
// fold (aext (zext x)) -> (zext x)
if ((N0.getOpcode() == ISD::ZEXTLOAD || N0.getOpcode() == ISD::EXTLOAD ||
N0.getOpcode() == ISD::SEXTLOAD) &&
N0.hasOneUse()) {
- SDOperand ExtLoad = DAG.getNode(N0.getOpcode(), VT, N0.getOperand(0),
- N0.getOperand(1), N0.getOperand(2),
- N0.getOperand(3));
+ MVT::ValueType EVT = cast<VTSDNode>(N0.getOperand(3))->getVT();
+ SDOperand ExtLoad = DAG.getExtLoad(N0.getOpcode(), VT, N0.getOperand(0),
+ N0.getOperand(1), N0.getOperand(2), EVT);
CombineTo(N, ExtLoad);
CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
ExtLoad.getValue(1));
SDOperand DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) {
SDOperand N0 = N->getOperand(0);
SDOperand N1 = N->getOperand(1);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
MVT::ValueType EVT = cast<VTSDNode>(N1)->getVT();
unsigned EVTBits = MVT::getSizeInBits(EVT);
// fold (sext_in_reg c1) -> c1
- if (N0C) {
- SDOperand Truncate = DAG.getConstant(N0C->getValue(), EVT);
- return DAG.getNode(ISD::SIGN_EXTEND, VT, Truncate);
- }
- // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt1
- if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
- cast<VTSDNode>(N0.getOperand(1))->getVT() <= EVT) {
+ if (isa<ConstantSDNode>(N0) || N0.getOpcode() == ISD::UNDEF)
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0, N1);
+
+ // If the input is already sign extended, just drop the extension.
+ if (TLI.ComputeNumSignBits(N0) >= MVT::getSizeInBits(VT)-EVTBits+1)
return N0;
- }
+
// fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2
if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG &&
EVT < cast<VTSDNode>(N0.getOperand(1))->getVT()) {
return DAG.getNode(ISD::SIGN_EXTEND_INREG, VT, N0.getOperand(0), N1);
}
- // fold (sext_in_reg (assert_sext x)) -> (assert_sext x)
- if (N0.getOpcode() == ISD::AssertSext &&
- cast<VTSDNode>(N0.getOperand(1))->getVT() <= EVT) {
- return N0;
- }
- // fold (sext_in_reg (sextload x)) -> (sextload x)
- if (N0.getOpcode() == ISD::SEXTLOAD &&
- cast<VTSDNode>(N0.getOperand(3))->getVT() <= EVT) {
- return N0;
- }
- // fold (sext_in_reg (setcc x)) -> setcc x iff (setcc x) == 0 or -1
- if (N0.getOpcode() == ISD::SETCC &&
- TLI.getSetCCResultContents() ==
- TargetLowering::ZeroOrNegativeOneSetCCResult)
- return N0;
+
// fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is zero
if (TLI.MaskedValueIsZero(N0, 1ULL << (EVTBits-1)))
return DAG.getZeroExtendInReg(N0, EVT);
+
+ // 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)))
+ if (ShAmt->getValue()+EVTBits <= MVT::getSizeInBits(VT)) {
+ // We can turn this into an SRA iff the input to the SRL is already sign
+ // extended enough.
+ unsigned InSignBits = TLI.ComputeNumSignBits(N0.getOperand(0));
+ if (MVT::getSizeInBits(VT)-(ShAmt->getValue()+EVTBits) < InSignBits)
+ return DAG.getNode(ISD::SRA, VT, N0.getOperand(0), N0.getOperand(1));
+ }
+ }
+
// fold (sext_inreg (extload x)) -> (sextload x)
if (N0.getOpcode() == ISD::EXTLOAD &&
EVT == cast<VTSDNode>(N0.getOperand(3))->getVT() &&
SDOperand DAGCombiner::visitTRUNCATE(SDNode *N) {
SDOperand N0 = N->getOperand(0);
- ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// noop truncate
if (N0.getValueType() == N->getValueType(0))
return N0;
// fold (truncate c1) -> c1
- if (N0C)
+ if (isa<ConstantSDNode>(N0))
return DAG.getNode(ISD::TRUNCATE, VT, N0);
// fold (truncate (truncate x)) -> (truncate x)
if (N0.getOpcode() == ISD::TRUNCATE)
return DAG.getNode(ISD::TRUNCATE, 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){
+ if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::SIGN_EXTEND||
+ N0.getOpcode() == ISD::ANY_EXTEND) {
if (N0.getValueType() < VT)
// if the source is smaller than the dest, we still need an extend
return DAG.getNode(N0.getOpcode(), VT, N0.getOperand(0));
// fold (fp_extend c1fp) -> c1fp
if (N0CFP)
return DAG.getNode(ISD::FP_EXTEND, VT, N0);
+
+ // fold (fpext (load x)) -> (fpext (fpround (extload x)))
+ if (N0.getOpcode() == ISD::LOAD && N0.hasOneUse() &&
+ (!AfterLegalize||TLI.isOperationLegal(ISD::EXTLOAD, N0.getValueType()))) {
+ SDOperand ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, VT, N0.getOperand(0),
+ N0.getOperand(1), N0.getOperand(2),
+ N0.getValueType());
+ CombineTo(N, ExtLoad);
+ CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad),
+ ExtLoad.getValue(1));
+ return SDOperand(N, 0); // Return N so it doesn't get rechecked!
+ }
+
+
return SDOperand();
}