#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
WorkList.end());
}
+ /// visit - call the node-specific routine that knows how to fold each
+ /// particular type of node.
+ SDOperand visit(SDNode *N);
+
public:
/// AddToWorkList - Add to the work list making sure it's instance is at the
/// the back (next to be processed.)
/// SimplifyDemandedBits - Check the specified integer node value to see if
/// it can be simplified or if things it uses can be simplified by bit
/// propagation. If so, return true.
- bool SimplifyDemandedBits(SDOperand Op) {
+ bool SimplifyDemandedBits(SDOperand Op, uint64_t Demanded = ~0ULL) {
TargetLowering::TargetLoweringOpt TLO(DAG);
uint64_t KnownZero, KnownOne;
- uint64_t Demanded = MVT::getIntVTBitMask(Op.getValueType());
+ Demanded &= MVT::getIntVTBitMask(Op.getValueType());
if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO))
return false;
DOUT << '\n';
std::vector<SDNode*> NowDead;
- DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, NowDead);
+ DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, &NowDead);
// Push the new node and any (possibly new) users onto the worklist.
AddToWorkList(TLO.New.Val);
bool CombineToPostIndexedLoadStore(SDNode *N);
- /// visit - call the node-specific routine that knows how to fold each
- /// particular type of node.
- SDOperand visit(SDNode *N);
+ /// combine - call the node-specific routine that knows how to fold each
+ /// particular type of node. If that doesn't do anything, try the
+ /// target-specific DAG combines.
+ SDOperand combine(SDNode *N);
// Visitation implementation - Implement dag node combining for different
// node types. The semantics are as follows:
SDOperand visitUREM(SDNode *N);
SDOperand visitMULHU(SDNode *N);
SDOperand visitMULHS(SDNode *N);
+ SDOperand visitSMUL_LOHI(SDNode *N);
+ SDOperand visitUMUL_LOHI(SDNode *N);
+ SDOperand visitSDIVREM(SDNode *N);
+ SDOperand visitUDIVREM(SDNode *N);
SDOperand visitAND(SDNode *N);
SDOperand visitOR(SDNode *N);
SDOperand visitXOR(SDNode *N);
SDOperand visitLOAD(SDNode *N);
SDOperand visitSTORE(SDNode *N);
SDOperand visitINSERT_VECTOR_ELT(SDNode *N);
+ SDOperand visitEXTRACT_VECTOR_ELT(SDNode *N);
SDOperand visitBUILD_VECTOR(SDNode *N);
SDOperand visitCONCAT_VECTORS(SDNode *N);
SDOperand visitVECTOR_SHUFFLE(SDNode *N);
bool NotExtCompare = false);
SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1,
ISD::CondCode Cond, bool foldBooleans = true);
+ bool SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, unsigned HiOp);
SDOperand ConstantFoldBIT_CONVERTofBUILD_VECTOR(SDNode *, MVT::ValueType);
SDOperand BuildSDIV(SDNode *N);
SDOperand BuildUDIV(SDNode *N);
SDNode *MatchRotate(SDOperand LHS, SDOperand RHS);
SDOperand ReduceLoadWidth(SDNode *N);
+ SDOperand GetDemandedBits(SDOperand V, uint64_t Mask);
+
/// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes,
/// looking for aliasing nodes and adding them to the Aliases vector.
void GatherAllAliases(SDNode *N, SDOperand OriginalChain,
/// specified expression for the same cost as the expression itself, or 2 if we
/// can compute the negated form more cheaply than the expression itself.
static char isNegatibleForFree(SDOperand Op, unsigned Depth = 0) {
+ // No compile time optimizations on this type.
+ if (Op.getValueType() == MVT::ppcf128)
+ return 0;
+
// fneg is removable even if it has multiple uses.
if (Op.getOpcode() == ISD::FNEG) return 2;
assert(Depth <= 6 && "GetNegatedExpression doesn't match isNegatibleForFree");
switch (Op.getOpcode()) {
default: assert(0 && "Unknown code");
- case ISD::ConstantFP:
- return DAG.getConstantFP(-cast<ConstantFPSDNode>(Op)->getValue(),
- Op.getValueType());
+ case ISD::ConstantFP: {
+ APFloat V = cast<ConstantFPSDNode>(Op)->getValueAPF();
+ V.changeSign();
+ return DAG.getConstantFP(V, Op.getValueType());
+ }
case ISD::FADD:
// FIXME: determine better conditions for this xform.
assert(UnsafeFPMath);
// -(0-B) -> B
if (ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(Op.getOperand(0)))
- if (N0CFP->getValue() == 0.0)
+ if (N0CFP->getValueAPF().isZero())
return Op.getOperand(1);
// -(A-B) -> B-A
// done. Set it to null to avoid confusion.
DAG.setRoot(SDOperand());
- /// DagCombineInfo - Expose the DAG combiner to the target combiner impls.
- TargetLowering::DAGCombinerInfo
- DagCombineInfo(DAG, !RunningAfterLegalize, false, this);
-
// while the worklist isn't empty, inspect the node on the end of it and
// try and combine it.
while (!WorkList.empty()) {
continue;
}
- SDOperand RV = visit(N);
-
- // If nothing happened, try a target-specific DAG combine.
- if (RV.Val == 0) {
- assert(N->getOpcode() != ISD::DELETED_NODE &&
- "Node was deleted but visit returned NULL!");
- if (N->getOpcode() >= ISD::BUILTIN_OP_END ||
- TLI.hasTargetDAGCombine((ISD::NodeType)N->getOpcode()))
- RV = TLI.PerformDAGCombine(N, DagCombineInfo);
- }
+ SDOperand RV = combine(N);
if (RV.Val) {
++NodesCombined;
case ISD::UREM: return visitUREM(N);
case ISD::MULHU: return visitMULHU(N);
case ISD::MULHS: return visitMULHS(N);
+ case ISD::SMUL_LOHI: return visitSMUL_LOHI(N);
+ case ISD::UMUL_LOHI: return visitUMUL_LOHI(N);
+ case ISD::SDIVREM: return visitSDIVREM(N);
+ case ISD::UDIVREM: return visitUDIVREM(N);
case ISD::AND: return visitAND(N);
case ISD::OR: return visitOR(N);
case ISD::XOR: return visitXOR(N);
case ISD::LOAD: return visitLOAD(N);
case ISD::STORE: return visitSTORE(N);
case ISD::INSERT_VECTOR_ELT: return visitINSERT_VECTOR_ELT(N);
+ case ISD::EXTRACT_VECTOR_ELT: return visitEXTRACT_VECTOR_ELT(N);
case ISD::BUILD_VECTOR: return visitBUILD_VECTOR(N);
case ISD::CONCAT_VECTORS: return visitCONCAT_VECTORS(N);
case ISD::VECTOR_SHUFFLE: return visitVECTOR_SHUFFLE(N);
return SDOperand();
}
+SDOperand DAGCombiner::combine(SDNode *N) {
+
+ SDOperand RV = visit(N);
+
+ // If nothing happened, try a target-specific DAG combine.
+ if (RV.Val == 0) {
+ assert(N->getOpcode() != ISD::DELETED_NODE &&
+ "Node was deleted but visit returned NULL!");
+
+ if (N->getOpcode() >= ISD::BUILTIN_OP_END ||
+ TLI.hasTargetDAGCombine((ISD::NodeType)N->getOpcode())) {
+
+ // Expose the DAG combiner to the target combiner impls.
+ TargetLowering::DAGCombinerInfo
+ DagCombineInfo(DAG, !AfterLegalize, false, this);
+
+ RV = TLI.PerformDAGCombine(N, DagCombineInfo);
+ }
+ }
+
+ return RV;
+}
+
/// getInputChainForNode - Given a node, return its input chain if it has one,
/// otherwise return a null sd operand.
static SDOperand getInputChainForNode(SDNode *N) {
return SDOperand();
}
+/// SimplifyNodeWithTwoResults - Perform optimizations common to nodes that
+/// compute two values. LoOp and HiOp give the opcodes for the two computations
+/// that are being performed. Return true if a simplification was made.
+///
+bool DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N,
+ unsigned LoOp, unsigned HiOp) {
+ // If the high half is not needed, just compute the low half.
+ bool HiExists = N->hasAnyUseOfValue(1);
+ if (!HiExists &&
+ (!AfterLegalize ||
+ TLI.isOperationLegal(LoOp, N->getValueType(0)))) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0),
+ DAG.getNode(LoOp, N->getValueType(0),
+ N->op_begin(),
+ N->getNumOperands()));
+ return true;
+ }
+
+ // If the low half is not needed, just compute the high half.
+ bool LoExists = N->hasAnyUseOfValue(0);
+ if (!LoExists &&
+ (!AfterLegalize ||
+ TLI.isOperationLegal(HiOp, N->getValueType(1)))) {
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
+ DAG.getNode(HiOp, N->getValueType(1),
+ N->op_begin(),
+ N->getNumOperands()));
+ return true;
+ }
+
+ // If both halves are used, return as it is.
+ if (LoExists && HiExists)
+ return false;
+
+ // If the two computed results can be simplified separately, separate them.
+ bool RetVal = false;
+ if (LoExists) {
+ SDOperand Lo = DAG.getNode(LoOp, N->getValueType(0),
+ N->op_begin(), N->getNumOperands());
+ SDOperand LoOpt = combine(Lo.Val);
+ if (LoOpt.Val && LoOpt != Lo &&
+ TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType())) {
+ RetVal = true;
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), LoOpt);
+ }
+ }
+
+ if (HiExists) {
+ SDOperand Hi = DAG.getNode(HiOp, N->getValueType(1),
+ N->op_begin(), N->getNumOperands());
+ SDOperand HiOpt = combine(Hi.Val);
+ if (HiOpt.Val && HiOpt != Hi &&
+ TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())) {
+ RetVal = true;
+ DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), HiOpt);
+ }
+ }
+
+ return RetVal;
+}
+
+SDOperand DAGCombiner::visitSMUL_LOHI(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHS))
+ return SDOperand();
+
+ return SDOperand();
+}
+
+SDOperand DAGCombiner::visitUMUL_LOHI(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHU))
+ return SDOperand();
+
+ return SDOperand();
+}
+
+SDOperand DAGCombiner::visitSDIVREM(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::SDIV, ISD::SREM))
+ return SDOperand();
+
+ return SDOperand();
+}
+
+SDOperand DAGCombiner::visitUDIVREM(SDNode *N) {
+
+ if (SimplifyNodeWithTwoResults(N, ISD::UDIV, ISD::UREM))
+ return SDOperand();
+
+ return SDOperand();
+}
+
/// SimplifyBinOpWithSameOpcodeHands - If this is a binary operator with
/// two operands of the same opcode, try to simplify it.
SDOperand DAGCombiner::SimplifyBinOpWithSameOpcodeHands(SDNode *N) {
// read fewer bytes from the same pointer.
unsigned PtrOff =
(MVT::getSizeInBits(LoadedVT) - MVT::getSizeInBits(EVT)) / 8;
+ unsigned Alignment = LN0->getAlignment();
SDOperand NewPtr = LN0->getBasePtr();
- if (!TLI.isLittleEndian())
+ if (!TLI.isLittleEndian()) {
NewPtr = DAG.getNode(ISD::ADD, PtrType, NewPtr,
DAG.getConstant(PtrOff, PtrType));
+ Alignment = MinAlign(Alignment, PtrOff);
+ }
AddToWorkList(NewPtr.Val);
SDOperand Load =
DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(), NewPtr,
LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
- LN0->isVolatile(), LN0->getAlignment());
+ LN0->isVolatile(), Alignment);
AddToWorkList(N);
CombineTo(N0.Val, Load, Load.getValue(1));
return SDOperand(N, 0); // Return N so it doesn't get rechecked!
assert(0 && "Unhandled SetCC Equivalent!");
abort();
}
+ // fold (not (zext (setcc x, y))) -> (zext (not (setcc x, y)))
+ if (N1C && N1C->getValue() == 1 && N0.getOpcode() == ISD::ZERO_EXTEND &&
+ N0.Val->hasOneUse() && isSetCCEquivalent(N0.getOperand(0), LHS, RHS, CC)){
+ SDOperand V = N0.getOperand(0);
+ V = DAG.getNode(ISD::XOR, V.getValueType(), V,
+ DAG.getConstant(1, V.getValueType()));
+ AddToWorkList(V.Val);
+ return DAG.getNode(ISD::ZERO_EXTEND, VT, V);
+ }
+
// fold !(x or y) -> (!x and !y) iff x or y are setcc
if (N1C && N1C->getValue() == 1 && VT == MVT::i1 &&
(N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) {
cast<CondCodeSDNode>(N->getOperand(2))->get());
}
+// ExtendUsesToFormExtLoad - Trying to extend uses of a load to enable this:
+// "fold ({s|z}ext (load x)) -> ({s|z}ext (truncate ({s|z}extload x)))"
+// transformation. Returns true if extension are possible and the above
+// mentioned transformation is profitable.
+static bool ExtendUsesToFormExtLoad(SDNode *N, SDOperand N0,
+ unsigned ExtOpc,
+ SmallVector<SDNode*, 4> &ExtendNodes,
+ TargetLowering &TLI) {
+ bool HasCopyToRegUses = false;
+ bool isTruncFree = TLI.isTruncateFree(N->getValueType(0), N0.getValueType());
+ for (SDNode::use_iterator UI = N0.Val->use_begin(), UE = N0.Val->use_end();
+ UI != UE; ++UI) {
+ SDNode *User = *UI;
+ if (User == N)
+ continue;
+ // FIXME: Only extend SETCC N, N and SETCC N, c for now.
+ if (User->getOpcode() == ISD::SETCC) {
+ ISD::CondCode CC = cast<CondCodeSDNode>(User->getOperand(2))->get();
+ if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC))
+ // Sign bits will be lost after a zext.
+ return false;
+ bool Add = false;
+ for (unsigned i = 0; i != 2; ++i) {
+ SDOperand UseOp = User->getOperand(i);
+ if (UseOp == N0)
+ continue;
+ if (!isa<ConstantSDNode>(UseOp))
+ return false;
+ Add = true;
+ }
+ if (Add)
+ ExtendNodes.push_back(User);
+ } else {
+ for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
+ SDOperand UseOp = User->getOperand(i);
+ if (UseOp == N0) {
+ // If truncate from extended type to original load type is free
+ // on this target, then it's ok to extend a CopyToReg.
+ if (isTruncFree && User->getOpcode() == ISD::CopyToReg)
+ HasCopyToRegUses = true;
+ else
+ return false;
+ }
+ }
+ }
+ }
+
+ if (HasCopyToRegUses) {
+ bool BothLiveOut = false;
+ for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
+ UI != UE; ++UI) {
+ SDNode *User = *UI;
+ for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
+ SDOperand UseOp = User->getOperand(i);
+ if (UseOp.Val == N && UseOp.ResNo == 0) {
+ BothLiveOut = true;
+ break;
+ }
+ }
+ }
+ if (BothLiveOut)
+ // Both unextended and extended values are live out. There had better be
+ // good a reason for the transformation.
+ return ExtendNodes.size();
+ }
+ return true;
+}
+
SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
SDOperand N0 = N->getOperand(0);
MVT::ValueType VT = N->getValueType(0);
}
// fold (sext (load x)) -> (sext (truncate (sextload x)))
- if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() &&
+ if (ISD::isNON_EXTLoad(N0.Val) &&
(!AfterLegalize||TLI.isLoadXLegal(ISD::SEXTLOAD, N0.getValueType()))){
- LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
- LN0->getBasePtr(), LN0->getSrcValue(),
- LN0->getSrcValueOffset(),
- N0.getValueType(),
- LN0->isVolatile(),
- LN0->getAlignment());
- CombineTo(N, ExtLoad);
- CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
- ExtLoad.getValue(1));
- return SDOperand(N, 0); // Return N so it doesn't get rechecked!
+ bool DoXform = true;
+ SmallVector<SDNode*, 4> SetCCs;
+ if (!N0.hasOneUse())
+ DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::SIGN_EXTEND, SetCCs, TLI);
+ if (DoXform) {
+ LoadSDNode *LN0 = cast<LoadSDNode>(N0);
+ SDOperand ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, VT, LN0->getChain(),
+ LN0->getBasePtr(), LN0->getSrcValue(),
+ LN0->getSrcValueOffset(),
+ N0.getValueType(),
+ LN0->isVolatile(),
+ LN0->getAlignment());
+ CombineTo(N, ExtLoad);
+ SDOperand Trunc = DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad);
+ CombineTo(N0.Val, Trunc, ExtLoad.getValue(1));
+ // Extend SetCC uses if necessary.
+ for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) {
+ SDNode *SetCC = SetCCs[i];
+ SmallVector<SDOperand, 4> Ops;
+ for (unsigned j = 0; j != 2; ++j) {
+ SDOperand 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(SetCC->getOperand(2));
+ CombineTo(SetCC, DAG.getNode(ISD::SETCC, SetCC->getValueType(0),
+ &Ops[0], Ops.size()));
+ }
+ return SDOperand(N, 0); // Return N so it doesn't get rechecked!
+ }
}
// fold (sext (sextload x)) -> (sext (truncate (sextload x)))
}
// fold (zext (load x)) -> (zext (truncate (zextload x)))
- if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() &&
+ if (ISD::isNON_EXTLoad(N0.Val) &&
(!AfterLegalize||TLI.isLoadXLegal(ISD::ZEXTLOAD, N0.getValueType()))) {
- LoadSDNode *LN0 = cast<LoadSDNode>(N0);
- SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
- LN0->getBasePtr(), LN0->getSrcValue(),
- LN0->getSrcValueOffset(),
- N0.getValueType(),
- LN0->isVolatile(),
- LN0->getAlignment());
- CombineTo(N, ExtLoad);
- CombineTo(N0.Val, DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad),
- ExtLoad.getValue(1));
- return SDOperand(N, 0); // Return N so it doesn't get rechecked!
+ bool DoXform = true;
+ SmallVector<SDNode*, 4> SetCCs;
+ if (!N0.hasOneUse())
+ DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::ZERO_EXTEND, SetCCs, TLI);
+ if (DoXform) {
+ LoadSDNode *LN0 = cast<LoadSDNode>(N0);
+ SDOperand ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, VT, LN0->getChain(),
+ LN0->getBasePtr(), LN0->getSrcValue(),
+ LN0->getSrcValueOffset(),
+ N0.getValueType(),
+ LN0->isVolatile(),
+ LN0->getAlignment());
+ CombineTo(N, ExtLoad);
+ SDOperand Trunc = DAG.getNode(ISD::TRUNCATE, N0.getValueType(), ExtLoad);
+ CombineTo(N0.Val, Trunc, ExtLoad.getValue(1));
+ // Extend SetCC uses if necessary.
+ for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) {
+ SDNode *SetCC = SetCCs[i];
+ SmallVector<SDOperand, 4> Ops;
+ for (unsigned j = 0; j != 2; ++j) {
+ SDOperand 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(SetCC->getOperand(2));
+ CombineTo(SetCC, DAG.getNode(ISD::SETCC, SetCC->getValueType(0),
+ &Ops[0], Ops.size()));
+ }
+ return SDOperand(N, 0); // Return N so it doesn't get rechecked!
+ }
}
// fold (zext (zextload x)) -> (zext (truncate (zextload x)))
return SDOperand();
}
+/// GetDemandedBits - See if the specified operand can be simplified with the
+/// knowledge that only the bits specified by Mask are used. If so, return the
+/// simpler operand, otherwise return a null SDOperand.
+SDOperand DAGCombiner::GetDemandedBits(SDOperand V, uint64_t Mask) {
+ switch (V.getOpcode()) {
+ default: break;
+ case ISD::OR:
+ case ISD::XOR:
+ // If the LHS or RHS don't contribute bits to the or, drop them.
+ if (DAG.MaskedValueIsZero(V.getOperand(0), Mask))
+ return V.getOperand(1);
+ if (DAG.MaskedValueIsZero(V.getOperand(1), Mask))
+ return V.getOperand(0);
+ break;
+ case ISD::SRL:
+ // Only look at single-use SRLs.
+ if (!V.Val->hasOneUse())
+ break;
+ if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
+ // See if we can recursively simplify the LHS.
+ unsigned Amt = RHSC->getValue();
+ Mask = (Mask << Amt) & MVT::getIntVTBitMask(V.getValueType());
+ SDOperand SimplifyLHS = GetDemandedBits(V.getOperand(0), Mask);
+ if (SimplifyLHS.Val) {
+ return DAG.getNode(ISD::SRL, V.getValueType(),
+ SimplifyLHS, V.getOperand(1));
+ }
+ }
+ }
+ return SDOperand();
+}
+
/// ReduceLoadWidth - If the result of a wider load is shifted to right of N
/// bits and then truncated to a narrower type and where N is a multiple
/// of number of bits of the narrower type, transform it to a narrower load
if (!TLI.isLittleEndian())
ShAmt = MVT::getSizeInBits(N0.getValueType()) - ShAmt - EVTBits;
uint64_t PtrOff = ShAmt / 8;
+ unsigned NewAlign = MinAlign(LN0->getAlignment(), PtrOff);
SDOperand NewPtr = DAG.getNode(ISD::ADD, PtrType, LN0->getBasePtr(),
DAG.getConstant(PtrOff, PtrType));
AddToWorkList(NewPtr.Val);
SDOperand Load = (ExtType == ISD::NON_EXTLOAD)
? DAG.getLoad(VT, LN0->getChain(), NewPtr,
LN0->getSrcValue(), LN0->getSrcValueOffset(),
- LN0->isVolatile(), LN0->getAlignment())
+ LN0->isVolatile(), NewAlign)
: DAG.getExtLoad(ExtType, VT, LN0->getChain(), NewPtr,
LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT,
- LN0->isVolatile(), LN0->getAlignment());
+ LN0->isVolatile(), NewAlign);
AddToWorkList(N);
if (CombineSRL) {
- std::vector<SDNode*> NowDead;
- DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1), NowDead);
+ DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1));
CombineTo(N->getOperand(0).Val, Load);
} else
CombineTo(N0.Val, Load, Load.getValue(1));
return N0.getOperand(0);
}
+ // See if we can simplify the input to this truncate through knowledge that
+ // only the low bits are being used. For example "trunc (or (shl x, 8), y)"
+ // -> trunc y
+ SDOperand Shorter = GetDemandedBits(N0, MVT::getIntVTBitMask(VT));
+ if (Shorter.Val)
+ return DAG.getNode(ISD::TRUNCATE, VT, Shorter);
+
// fold (truncate (load x)) -> (smaller load x)
// fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits))
return ReduceLoadWidth(N);
return DAG.getNode(ISD::BIT_CONVERT, VT, N0.getOperand(0));
// fold (conv (load x)) -> (load (conv*)x)
- // If the resultant load doesn't need a higher alignment than the original!
- if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() &&
- ISD::isUNINDEXEDLoad(N0.Val) &&
+ // If the resultant load doesn't need a higher alignment than the original!
+ if (ISD::isNormalLoad(N0.Val) && N0.hasOneUse() &&
TLI.isOperationLegal(ISD::LOAD, VT)) {
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
unsigned Align = TLI.getTargetMachine().getTargetData()->
}
// fold (fadd c1, c2) -> c1+c2
- if (N0CFP && N1CFP)
+ if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FADD, VT, N0, N1);
// canonicalize constant to RHS
if (N0CFP && !N1CFP)
}
// fold (fsub c1, c2) -> c1-c2
- if (N0CFP && N1CFP)
+ if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FSUB, VT, N0, N1);
// fold (0-B) -> -B
- if (UnsafeFPMath && N0CFP && N0CFP->getValue() == 0.0) {
+ if (UnsafeFPMath && N0CFP && N0CFP->getValueAPF().isZero()) {
if (isNegatibleForFree(N1))
return GetNegatedExpression(N1, DAG);
return DAG.getNode(ISD::FNEG, VT, N1);
}
// fold (fmul c1, c2) -> c1*c2
- if (N0CFP && N1CFP)
+ if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FMUL, VT, N0, N1);
// canonicalize constant to RHS
if (N0CFP && !N1CFP)
}
// fold (fdiv c1, c2) -> c1/c2
- if (N0CFP && N1CFP)
+ if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FDIV, VT, N0, N1);
MVT::ValueType VT = N->getValueType(0);
// fold (frem c1, c2) -> fmod(c1,c2)
- if (N0CFP && N1CFP)
+ if (N0CFP && N1CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FREM, VT, N0, N1);
return SDOperand();
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
MVT::ValueType VT = N->getValueType(0);
- if (N0CFP && N1CFP) // Constant fold
+ if (N0CFP && N1CFP && VT != MVT::ppcf128) // Constant fold
return DAG.getNode(ISD::FCOPYSIGN, VT, N0, N1);
if (N1CFP) {
- APFloat V = N1CFP->getValueAPF();
+ const APFloat& V = N1CFP->getValueAPF();
// copysign(x, c1) -> fabs(x) iff ispos(c1)
// copysign(x, c1) -> fneg(fabs(x)) iff isneg(c1)
if (!V.isNegative())
MVT::ValueType VT = N->getValueType(0);
// fold (sint_to_fp c1) -> c1fp
- if (N0C)
+ if (N0C && N0.getValueType() != MVT::ppcf128)
return DAG.getNode(ISD::SINT_TO_FP, VT, N0);
return SDOperand();
}
MVT::ValueType VT = N->getValueType(0);
// fold (uint_to_fp c1) -> c1fp
- if (N0C)
+ if (N0C && N0.getValueType() != MVT::ppcf128)
return DAG.getNode(ISD::UINT_TO_FP, VT, N0);
return SDOperand();
}
MVT::ValueType VT = N->getValueType(0);
// fold (fp_to_uint c1fp) -> c1
- if (N0CFP)
+ if (N0CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FP_TO_UINT, VT, N0);
return SDOperand();
}
MVT::ValueType VT = N->getValueType(0);
// fold (fp_round c1fp) -> c1fp
- if (N0CFP)
+ if (N0CFP && N0.getValueType() != MVT::ppcf128)
return DAG.getNode(ISD::FP_ROUND, VT, N0);
// fold (fp_round (fp_extend x)) -> x
// fold (fp_round_inreg c1fp) -> c1fp
if (N0CFP) {
- SDOperand Round = DAG.getConstantFP(N0CFP->getValue(), EVT);
+ SDOperand Round = DAG.getConstantFP(N0CFP->getValueAPF(), EVT);
return DAG.getNode(ISD::FP_EXTEND, VT, Round);
}
return SDOperand();
MVT::ValueType VT = N->getValueType(0);
// fold (fp_extend c1fp) -> c1fp
- if (N0CFP)
+ if (N0CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FP_EXTEND, VT, N0);
// fold (fpext (load x)) -> (fpext (fpround (extload x)))
MVT::ValueType VT = N->getValueType(0);
// fold (fabs c1) -> fabs(c1)
- if (N0CFP)
+ if (N0CFP && VT != MVT::ppcf128)
return DAG.getNode(ISD::FABS, VT, N0);
// fold (fabs (fabs x)) -> (fabs x)
if (N0.getOpcode() == ISD::FABS)
std::vector<SDNode*> NowDead;
if (isLoad) {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
- NowDead);
+ &NowDead);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
- NowDead);
+ &NowDead);
} else {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
- NowDead);
+ &NowDead);
}
// Nodes can end up on the worklist more than once. Make sure we do
// Replace the uses of Ptr with uses of the updated base value.
DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0),
- NowDead);
+ &NowDead);
removeFromWorkList(Ptr.Val);
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
removeFromWorkList(NowDead[i]);
std::vector<SDNode*> NowDead;
if (isLoad) {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
- NowDead);
+ &NowDead);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
- NowDead);
+ &NowDead);
} else {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
- NowDead);
+ &NowDead);
}
// Nodes can end up on the worklist more than once. Make sure we do
// Replace the uses of Use with uses of the updated base value.
DAG.ReplaceAllUsesOfValueWith(SDOperand(Op, 0),
Result.getValue(isLoad ? 1 : 0),
- NowDead);
+ &NowDead);
removeFromWorkList(Op);
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
removeFromWorkList(NowDead[i]);
// Replace the chain to void dependency.
if (LD->getExtensionType() == ISD::NON_EXTLOAD) {
ReplLoad = DAG.getLoad(N->getValueType(0), BetterChain, Ptr,
- LD->getSrcValue(), LD->getSrcValueOffset(),
- LD->isVolatile(), LD->getAlignment());
+ LD->getSrcValue(), LD->getSrcValueOffset(),
+ LD->isVolatile(), LD->getAlignment());
} else {
ReplLoad = DAG.getExtLoad(LD->getExtensionType(),
LD->getValueType(0),
SDOperand Tmp;
switch (CFP->getValueType(0)) {
default: assert(0 && "Unknown FP type");
+ case MVT::f80: // We don't do this for these yet.
+ case MVT::f128:
+ case MVT::ppcf128:
+ break;
case MVT::f32:
if (!AfterLegalize || TLI.isTypeLegal(MVT::i32)) {
- Tmp = DAG.getConstant(FloatToBits(CFP->getValueAPF().convertToFloat()), MVT::i32);
+ Tmp = DAG.getConstant((uint32_t)CFP->getValueAPF().
+ convertToAPInt().getZExtValue(), MVT::i32);
return DAG.getStore(Chain, Tmp, Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->isVolatile(),
ST->getAlignment());
break;
case MVT::f64:
if (!AfterLegalize || TLI.isTypeLegal(MVT::i64)) {
- Tmp = DAG.getConstant(DoubleToBits(CFP->getValueAPF().convertToDouble()), MVT::i64);
+ Tmp = DAG.getConstant(CFP->getValueAPF().convertToAPInt().
+ getZExtValue(), MVT::i64);
return DAG.getStore(Chain, Tmp, Ptr, ST->getSrcValue(),
ST->getSrcValueOffset(), ST->isVolatile(),
ST->getAlignment());
} else if (TLI.isTypeLegal(MVT::i32)) {
- // Many FP stores are not make apparent until after legalize, e.g. for
+ // Many FP stores are not made apparent until after legalize, e.g. for
// argument passing. Since this is so common, custom legalize the
// 64-bit integer store into two 32-bit stores.
- uint64_t Val = DoubleToBits(CFP->getValueAPF().convertToDouble());
+ uint64_t Val = CFP->getValueAPF().convertToAPInt().getZExtValue();
SDOperand Lo = DAG.getConstant(Val & 0xFFFFFFFF, MVT::i32);
SDOperand Hi = DAG.getConstant(Val >> 32, MVT::i32);
if (!TLI.isLittleEndian()) std::swap(Lo, Hi);
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getConstant(4, Ptr.getValueType()));
SVOffset += 4;
- if (Alignment > 4)
- Alignment = 4;
+ Alignment = MinAlign(Alignment, 4U);
SDOperand St1 = DAG.getStore(Chain, Hi, Ptr, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
return DAG.getNode(ISD::TokenFactor, MVT::Other, St0, St1);
if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N))
return SDOperand(N, 0);
+ // FIXME: is there such a think as a truncating indexed store?
+ if (ST->isTruncatingStore() && ST->getAddressingMode() == ISD::UNINDEXED &&
+ MVT::isInteger(Value.getValueType())) {
+ // See if we can simplify the input to this truncstore with knowledge that
+ // only the low bits are being used. For example:
+ // "truncstore (or (shl x, 8), y), i8" -> "truncstore y, i8"
+ SDOperand Shorter =
+ GetDemandedBits(Value, MVT::getIntVTBitMask(ST->getStoredVT()));
+ AddToWorkList(Value.Val);
+ if (Shorter.Val)
+ return DAG.getTruncStore(Chain, Shorter, Ptr, ST->getSrcValue(),
+ ST->getSrcValueOffset(), ST->getStoredVT(),
+ ST->isVolatile(), ST->getAlignment());
+
+ // Otherwise, see if we can simplify the operation with
+ // SimplifyDemandedBits, which only works if the value has a single use.
+ if (SimplifyDemandedBits(Value, MVT::getIntVTBitMask(ST->getStoredVT())))
+ return SDOperand(N, 0);
+ }
+
return SDOperand();
}
return SDOperand();
}
+SDOperand DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) {
+ SDOperand InVec = N->getOperand(0);
+ SDOperand EltNo = N->getOperand(1);
+
+ // (vextract (v4f32 s2v (f32 load $addr)), 0) -> (f32 load $addr)
+ // (vextract (v4i32 bc (v4f32 s2v (f32 load $addr))), 0) -> (i32 load $addr)
+ if (isa<ConstantSDNode>(EltNo)) {
+ unsigned Elt = cast<ConstantSDNode>(EltNo)->getValue();
+ bool NewLoad = false;
+ if (Elt == 0) {
+ MVT::ValueType VT = InVec.getValueType();
+ MVT::ValueType EVT = MVT::getVectorElementType(VT);
+ MVT::ValueType LVT = EVT;
+ unsigned NumElts = MVT::getVectorNumElements(VT);
+ if (InVec.getOpcode() == ISD::BIT_CONVERT) {
+ MVT::ValueType BCVT = InVec.getOperand(0).getValueType();
+ if (!MVT::isVector(BCVT) ||
+ NumElts != MVT::getVectorNumElements(BCVT))
+ return SDOperand();
+ InVec = InVec.getOperand(0);
+ EVT = MVT::getVectorElementType(BCVT);
+ NewLoad = true;
+ }
+ if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR &&
+ InVec.getOperand(0).getValueType() == EVT &&
+ ISD::isNormalLoad(InVec.getOperand(0).Val) &&
+ InVec.getOperand(0).hasOneUse()) {
+ LoadSDNode *LN0 = cast<LoadSDNode>(InVec.getOperand(0));
+ unsigned Align = LN0->getAlignment();
+ if (NewLoad) {
+ // Check the resultant load doesn't need a higher alignment than the
+ // original load.
+ unsigned NewAlign = TLI.getTargetMachine().getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(LVT));
+ if (!TLI.isOperationLegal(ISD::LOAD, LVT) || NewAlign > Align)
+ return SDOperand();
+ Align = NewAlign;
+ }
+
+ return DAG.getLoad(LVT, LN0->getChain(), LN0->getBasePtr(),
+ LN0->getSrcValue(), LN0->getSrcValueOffset(),
+ LN0->isVolatile(), Align);
+ }
+ }
+ }
+ return SDOperand();
+}
+
+
SDOperand DAGCombiner::visitBUILD_VECTOR(SDNode *N) {
unsigned NumInScalars = N->getNumOperands();
MVT::ValueType VT = N->getValueType(0);
if (!Base.Val)
return N0;
for (unsigned i = 0; i != NumElems; ++i) {
- if (V->getOperand(i).getOpcode() != ISD::UNDEF &&
- V->getOperand(i) != Base) {
+ if (V->getOperand(i) != Base) {
AllSame = false;
break;
}
if ((RHSOp.getOpcode() == ISD::Constant &&
cast<ConstantSDNode>(RHSOp.Val)->isNullValue()) ||
(RHSOp.getOpcode() == ISD::ConstantFP &&
- !cast<ConstantFPSDNode>(RHSOp.Val)->getValue()))
+ cast<ConstantFPSDNode>(RHSOp.Val)->getValueAPF().isZero()))
break;
}
Ops.push_back(DAG.getNode(N->getOpcode(), EltType, LHSOp, RHSOp));
if (CombinerGlobalAA) {
// Use alias analysis information.
- int Overlap1 = Size1 + SrcValueOffset1;
- int Overlap2 = Size2 + SrcValueOffset2;
+ int64_t MinOffset = std::min(SrcValueOffset1, SrcValueOffset2);
+ int64_t Overlap1 = Size1 + SrcValueOffset1 - MinOffset;
+ int64_t Overlap2 = Size2 + SrcValueOffset2 - MinOffset;
AliasAnalysis::AliasResult AAResult =
AA.alias(SrcValue1, Overlap1, SrcValue2, Overlap2);
if (AAResult == AliasAnalysis::NoAlias)