SDOperand To[] = { Res0, Res1 };
return CombineTo(N, To, 2, AddTo);
}
+
private:
/// SimplifyDemandedBits - Check the specified integer node value to see if
GetNegatedExpression(Op.getOperand(1), DAG, Depth+1));
case ISD::FP_EXTEND:
- case ISD::FP_ROUND:
case ISD::FSIN:
return DAG.getNode(Op.getOpcode(), Op.getValueType(),
GetNegatedExpression(Op.getOperand(0), DAG, Depth+1));
+ case ISD::FP_ROUND:
+ return DAG.getNode(ISD::FP_ROUND, Op.getValueType(),
+ GetNegatedExpression(Op.getOperand(0), DAG, Depth+1),
+ Op.getOperand(1));
}
}
SDOperand DAGCombiner::visitFP_ROUND(SDNode *N) {
SDOperand N0 = N->getOperand(0);
+ SDOperand N1 = N->getOperand(1);
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
MVT::ValueType VT = N->getValueType(0);
// fold (fp_round c1fp) -> c1fp
if (N0CFP && N0.getValueType() != MVT::ppcf128)
- return DAG.getNode(ISD::FP_ROUND, VT, N0);
+ return DAG.getNode(ISD::FP_ROUND, VT, N0, N1);
// fold (fp_round (fp_extend x)) -> x
if (N0.getOpcode() == ISD::FP_EXTEND && VT == N0.getOperand(0).getValueType())
// fold (fp_round (copysign X, Y)) -> (copysign (fp_round X), Y)
if (N0.getOpcode() == ISD::FCOPYSIGN && N0.Val->hasOneUse()) {
- SDOperand Tmp = DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0));
+ SDOperand Tmp = DAG.getNode(ISD::FP_ROUND, VT, N0.getOperand(0), N1);
AddToWorkList(Tmp.Val);
return DAG.getNode(ISD::FCOPYSIGN, VT, Tmp, N0.getOperand(1));
}
// If this is fp_round(fpextend), don't fold it, allow ourselves to be folded.
if (N->hasOneUse() && (*N->use_begin())->getOpcode() == ISD::FP_ROUND)
return SDOperand();
-
+
// fold (fp_extend c1fp) -> c1fp
if (N0CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FP_EXTEND, VT, N0);
-
- // fold (fpext (load x)) -> (fpext (fpround (extload x)))
+
+ // Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the
+ // value of X.
+ if (N0.getOpcode() == ISD::FP_ROUND && N0.Val->getConstantOperandVal(1) == 1){
+ SDOperand In = N0.getOperand(0);
+ if (In.getValueType() == VT) return In;
+ if (VT < In.getValueType())
+ return DAG.getNode(ISD::FP_ROUND, VT, In, N0.getOperand(1));
+ return DAG.getNode(ISD::FP_EXTEND, VT, In);
+ }
+
+ // fold (fpext (load x)) -> (fpext (fptrunc (extload x)))
if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() &&
(!AfterLegalize||TLI.isLoadXLegal(ISD::EXTLOAD, N0.getValueType()))) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
LN0->isVolatile(),
LN0->getAlignment());
CombineTo(N, ExtLoad);
- CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad),
+ CombineTo(N0.Val, DAG.getNode(ISD::FP_ROUND, N0.getValueType(), ExtLoad,
+ DAG.getIntPtrConstant(1)),
ExtLoad.getValue(1));
return SDOperand(N, 0); // Return N so it doesn't get rechecked!
}
if (!LD->isVolatile()) {
if (N->getValueType(1) == MVT::Other) {
// Unindexed loads.
- if (N->hasNUsesOfValue(0, 0))
- return CombineTo(N, DAG.getNode(ISD::UNDEF, N->getValueType(0)), Chain);
+ if (N->hasNUsesOfValue(0, 0)) {
+ // It's not safe to use the two value CombineTo variant here. e.g.
+ // v1, chain2 = load chain1, loc
+ // v2, chain3 = load chain2, loc
+ // v3 = add v2, c
+ // Now we replace use of v1 with undef, use of chain2 with chain1.
+ // ReplaceAllUsesWith() will iterate through uses of the first load and
+ // update operands:
+ // v1, chain2 = load chain1, loc
+ // v2, chain3 = load chain1, loc
+ // v3 = add v2, c
+ // Now the second load is the same as the first load, SelectionDAG cse
+ // will ensure the use of second load is replaced with the first load.
+ // v1, chain2 = load chain1, loc
+ // v3 = add v1, c
+ // Then v1 is replaced with undef and bad things happen.
+ std::vector<SDNode*> NowDead;
+ SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+ DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
+ DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
+ DOUT << " and 1 other value\n";
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Chain, &NowDead);
+ removeFromWorkList(N);
+ for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+ removeFromWorkList(NowDead[i]);
+ DAG.DeleteNode(N);
+ return SDOperand(N, 0); // Return N so it doesn't get rechecked!
+ }
} else {
// Indexed loads.
assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?");
if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) {
- SDOperand Undef0 = DAG.getNode(ISD::UNDEF, N->getValueType(0));
- SDOperand Undef1 = DAG.getNode(ISD::UNDEF, N->getValueType(1));
- SDOperand To[] = { Undef0, Undef1, Chain };
- return CombineTo(N, To, 3);
+ std::vector<SDNode*> NowDead;
+ SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
+ DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
+ DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
+ DOUT << " and 2 other values\n";
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
+ DAG.getNode(ISD::UNDEF, N->getValueType(1)),
+ &NowDead);
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 2), Chain, &NowDead);
+ removeFromWorkList(N);
+ for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+ removeFromWorkList(NowDead[i]);
+ DAG.DeleteNode(N);
+ return SDOperand(N, 0); // Return N so it doesn't get rechecked!
}
}
}
return SDOperand();
}
+
SDOperand DAGCombiner::visitSTORE(SDNode *N) {
StoreSDNode *ST = cast<StoreSDNode>(N);
SDOperand Chain = ST->getChain();
// If this is a load followed by a store to the same location, then the store
// is dead/noop.
if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Value)) {
- if (Chain.Val == Ld && Ld->getBasePtr() == Ptr &&
+ if (Ld->getBasePtr() == Ptr && ST->getStoredVT() == Ld->getLoadedVT() &&
ST->getAddressingMode() == ISD::UNINDEXED &&
- ST->getStoredVT() == Ld->getLoadedVT() &&
- !ST->isVolatile()) {
+ !ST->isVolatile() &&
+ // There can't be any side effects between the load and store, such as
+ // a call or store.
+ Chain.reachesChainWithoutSideEffects(SDOperand(Ld, 1))) {
// The store is dead, remove it.
return Chain;
}
// Otherwise, use InIdx + VecSize
unsigned Idx = cast<ConstantSDNode>(Extract.getOperand(1))->getValue();
- BuildVecIndices.push_back(DAG.getConstant(Idx+NumInScalars,
- TLI.getPointerTy()));
+ BuildVecIndices.push_back(DAG.getIntPtrConstant(Idx+NumInScalars));
}
// Add count and size info.
- MVT::ValueType BuildVecVT =
- MVT::getVectorType(TLI.getPointerTy(), NumElts);
+ MVT::ValueType BuildVecVT = MVT::getVectorType(TLI.getPointerTy(), NumElts);
// Return the new VECTOR_SHUFFLE node.
SDOperand Ops[5];