//
// This pass combines dag nodes to form fewer, simpler DAG nodes. It can be run
// both before and after the DAG is legalized.
-//
-// FIXME: Missing folds
-// sdiv, udiv, srem, urem (X, const) where X is an integer can be expanded into
-// a sequence of multiplies, shifts, and adds. This should be controlled by
-// some kind of hint from the target that int div is expensive.
-// various folds of mulh[s,u] by constants such as -1, powers of 2, etc.
-//
-// FIXME: select C, pow2, pow2 -> something smart
-// FIXME: trunc(select X, Y, Z) -> select X, trunc(Y), trunc(Z)
-// FIXME: Dead stores -> nuke
-// FIXME: shr X, (and Y,31) -> shr X, Y (TRICKY!)
-// FIXME: mul (x, const) -> shifts + adds
-// FIXME: undef values
-// FIXME: divide by zero is currently left unfolded. do we want to turn this
-// into an undef?
-// FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false
//
//===----------------------------------------------------------------------===//
#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"
/// it can be simplified or if things it uses can be simplified by bit
/// propagation. If so, return true.
bool SimplifyDemandedBits(SDOperand Op, uint64_t Demanded = ~0ULL) {
- TargetLowering::TargetLoweringOpt TLO(DAG);
+ TargetLowering::TargetLoweringOpt TLO(DAG, AfterLegalize);
uint64_t KnownZero, KnownOne;
Demanded &= MVT::getIntVTBitMask(Op.getValueType());
if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO))
SDOperand XformToShuffleWithZero(SDNode *N);
SDOperand ReassociateOps(unsigned Opc, SDOperand LHS, SDOperand RHS);
+ SDOperand visitShiftByConstant(SDNode *N, unsigned Amt);
+
bool SimplifySelectOps(SDNode *SELECT, SDOperand LHS, SDOperand RHS);
SDOperand SimplifyBinOpWithSameOpcodeHands(SDNode *N);
SDOperand SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2);
DAG.MaskedValueIsZero(N0, SignBit))
return DAG.getNode(ISD::UREM, VT, N0, N1);
- // Unconditionally lower X%C -> X-X/C*C. This allows the X/C logic to hack on
- // the remainder operation.
+ // 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()) {
SDOperand Div = DAG.getNode(ISD::SDIV, VT, N0, N1);
- SDOperand Mul = DAG.getNode(ISD::MUL, VT, Div, N1);
- SDOperand Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
- AddToWorkList(Div.Val);
- AddToWorkList(Mul.Val);
- return Sub;
+ SDOperand OptimizedDiv = combine(Div.Val);
+ if (OptimizedDiv.Val && OptimizedDiv.Val != Div.Val) {
+ SDOperand Mul = DAG.getNode(ISD::MUL, VT, OptimizedDiv, N1);
+ SDOperand Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
+ AddToWorkList(Mul.Val);
+ return Sub;
+ }
}
// undef % X -> 0
}
}
- // Unconditionally lower X%C -> X-X/C*C. This allows the X/C logic to hack on
- // the remainder operation.
+ // 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()) {
SDOperand Div = DAG.getNode(ISD::UDIV, VT, N0, N1);
- SDOperand Mul = DAG.getNode(ISD::MUL, VT, Div, N1);
- SDOperand Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
- AddToWorkList(Div.Val);
- AddToWorkList(Mul.Val);
- return Sub;
+ SDOperand OptimizedDiv = combine(Div.Val);
+ if (OptimizedDiv.Val && OptimizedDiv.Val != Div.Val) {
+ SDOperand Mul = DAG.getNode(ISD::MUL, VT, OptimizedDiv, N1);
+ SDOperand Sub = DAG.getNode(ISD::SUB, VT, N0, Mul);
+ AddToWorkList(Mul.Val);
+ return Sub;
+ }
}
// undef % X -> 0
bool DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N,
unsigned LoOp, unsigned HiOp) {
// If the high half is not needed, just compute the low half.
- if (!N->hasAnyUseOfValue(1) &&
+ bool HiExists = N->hasAnyUseOfValue(1);
+ if (!HiExists &&
(!AfterLegalize ||
TLI.isOperationLegal(LoOp, N->getValueType(0)))) {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0),
}
// If the low half is not needed, just compute the high half.
- if (!N->hasAnyUseOfValue(0) &&
+ bool LoExists = N->hasAnyUseOfValue(0);
+ if (!LoExists &&
(!AfterLegalize ||
TLI.isOperationLegal(HiOp, N->getValueType(1)))) {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
return true;
}
- // If the two computed results can be siplified separately, separate them.
- SDOperand Lo = DAG.getNode(LoOp, N->getValueType(0),
- N->op_begin(), N->getNumOperands());
- SDOperand Hi = DAG.getNode(HiOp, N->getValueType(1),
- N->op_begin(), N->getNumOperands());
- unsigned LoExists = !Lo.use_empty();
- unsigned HiExists = !Hi.use_empty();
- SDOperand LoOpt = Lo;
- SDOperand HiOpt = Hi;
- if (!LoExists || !HiExists) {
- SDOperand Pair = DAG.getNode(ISD::BUILD_PAIR, MVT::Other, Lo, Hi);
- assert(Pair.use_empty() && "Pair with type MVT::Other already exists!");
- LoOpt = combine(Lo.Val);
- HiOpt = combine(Hi.Val);
- if (!LoOpt.Val)
- LoOpt = Pair.getOperand(0);
- if (!HiOpt.Val)
- HiOpt = Pair.getOperand(1);
- DAG.DeleteNode(Pair.Val);
- }
- if ((LoExists || LoOpt != Lo) &&
- (HiExists || HiOpt != Hi) &&
- TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType()) &&
- TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType())) {
- DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), LoOpt);
- DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), HiOpt);
- 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);
+ } else
+ DAG.DeleteNode(Lo.Val);
}
- return false;
+ 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);
+ } else
+ DAG.DeleteNode(Hi.Val);
+ }
+
+ return RetVal;
}
SDOperand DAGCombiner::visitSMUL_LOHI(SDNode *N) {
// 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 =
- (MVT::getSizeInBits(LoadedVT) - MVT::getSizeInBits(EVT)) / 8;
+ unsigned LVTStoreBytes = MVT::getStoreSizeInBits(LoadedVT)/8;
+ unsigned EVTStoreBytes = MVT::getStoreSizeInBits(EVT)/8;
+ unsigned PtrOff = LVTStoreBytes - EVTStoreBytes;
unsigned Alignment = LN0->getAlignment();
SDOperand NewPtr = LN0->getBasePtr();
if (!TLI.isLittleEndian()) {
return SDOperand();
}
+/// visitShiftByConstant - Handle transforms common to the three shifts, when
+/// the shift amount is a constant.
+SDOperand DAGCombiner::visitShiftByConstant(SDNode *N, unsigned Amt) {
+ SDNode *LHS = N->getOperand(0).Val;
+ if (!LHS->hasOneUse()) return SDOperand();
+
+ // We want to pull some binops through shifts, so that we have (and (shift))
+ // instead of (shift (and)), likewise for add, or, xor, etc. This sort of
+ // thing happens with address calculations, so it's important to canonicalize
+ // it.
+ bool HighBitSet = false; // Can we transform this if the high bit is set?
+
+ switch (LHS->getOpcode()) {
+ default: return SDOperand();
+ case ISD::OR:
+ case ISD::XOR:
+ HighBitSet = false; // We can only transform sra if the high bit is clear.
+ break;
+ case ISD::AND:
+ HighBitSet = true; // We can only transform sra if the high bit is set.
+ break;
+ case ISD::ADD:
+ if (N->getOpcode() != ISD::SHL)
+ return SDOperand(); // only shl(add) not sr[al](add).
+ HighBitSet = false; // We can only transform sra if the high bit is clear.
+ break;
+ }
+
+ // We require the RHS of the binop to be a constant as well.
+ ConstantSDNode *BinOpCst = dyn_cast<ConstantSDNode>(LHS->getOperand(1));
+ if (!BinOpCst) return SDOperand();
+
+
+ // 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:
+ //
+ //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).Val;
+ if ((BinOpLHSVal->getOpcode() != ISD::SHL &&
+ BinOpLHSVal->getOpcode() != ISD::SRA &&
+ BinOpLHSVal->getOpcode() != ISD::SRL) ||
+ !isa<ConstantSDNode>(BinOpLHSVal->getOperand(1)))
+ return SDOperand();
+
+ MVT::ValueType 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 (N->getOpcode() == ISD::SRA) {
+ uint64_t BinOpRHSSign = BinOpCst->getValue() >> MVT::getSizeInBits(VT)-1;
+ if ((bool)BinOpRHSSign != HighBitSet)
+ return SDOperand();
+ }
+
+ // Fold the constants, shifting the binop RHS by the shift amount.
+ SDOperand NewRHS = DAG.getNode(N->getOpcode(), N->getValueType(0),
+ LHS->getOperand(1), N->getOperand(1));
+
+ // Create the new shift.
+ SDOperand NewShift = DAG.getNode(N->getOpcode(), VT, LHS->getOperand(0),
+ N->getOperand(1));
+
+ // Create the new binop.
+ return DAG.getNode(LHS->getOpcode(), VT, NewShift, NewRHS);
+}
+
+
SDOperand DAGCombiner::visitSHL(SDNode *N) {
SDOperand N0 = N->getOperand(0);
SDOperand N1 = N->getOperand(1);
if (N1C && N0.getOpcode() == ISD::SRA && N1 == N0.getOperand(1))
return DAG.getNode(ISD::AND, VT, N0.getOperand(0),
DAG.getConstant(~0ULL << N1C->getValue(), VT));
- return SDOperand();
+
+ return N1C ? visitShiftByConstant(N, N1C->getValue()) : SDOperand();
}
SDOperand DAGCombiner::visitSRA(SDNode *N) {
// If the sign bit is known to be zero, switch this to a SRL.
if (DAG.MaskedValueIsZero(N0, MVT::getIntVTSignBit(VT)))
return DAG.getNode(ISD::SRL, VT, N0, N1);
- return SDOperand();
+
+ return N1C ? visitShiftByConstant(N, N1C->getValue()) : SDOperand();
}
SDOperand DAGCombiner::visitSRL(SDNode *N) {
if (N1C && SimplifyDemandedBits(SDOperand(N, 0)))
return SDOperand(N, 0);
- return SDOperand();
+ return N1C ? visitShiftByConstant(N, N1C->getValue()) : SDOperand();
}
SDOperand DAGCombiner::visitCTLZ(SDNode *N) {
return DAG.getNode(ISD::TRUNCATE, VT, XORNode);
}
// fold select C, 0, X -> ~C & X
- if (VT == VT0 && N1C && N1C->isNullValue()) {
+ if (VT == VT0 && VT == MVT::i1 && N1C && N1C->isNullValue()) {
SDOperand XORNode = DAG.getNode(ISD::XOR, VT, N0, DAG.getConstant(1, VT));
AddToWorkList(XORNode.Val);
return DAG.getNode(ISD::AND, VT, XORNode, N2);
}
// fold select C, X, 1 -> ~C | X
- if (VT == VT0 && N2C && N2C->getValue() == 1) {
+ if (VT == VT0 && VT == MVT::i1 && N2C && N2C->getValue() == 1) {
SDOperand XORNode = DAG.getNode(ISD::XOR, VT, N0, DAG.getConstant(1, VT));
AddToWorkList(XORNode.Val);
return DAG.getNode(ISD::OR, VT, XORNode, N1);
MVT::ValueType 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.isLittleEndian())
- ShAmt = MVT::getSizeInBits(N0.getValueType()) - ShAmt - EVTBits;
+ if (!TLI.isLittleEndian()) {
+ unsigned LVTStoreBits = MVT::getStoreSizeInBits(N0.getValueType());
+ unsigned EVTStoreBits = MVT::getStoreSizeInBits(EVT);
+ ShAmt = LVTStoreBits - EVTStoreBits - ShAmt;
+ }
uint64_t PtrOff = ShAmt / 8;
unsigned NewAlign = MinAlign(LN0->getAlignment(), PtrOff);
SDOperand NewPtr = DAG.getNode(ISD::ADD, PtrType, LN0->getBasePtr(),
if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N))
return SDOperand(N, 0);
- // FIXME: is there such a think as a truncating indexed store?
+ // FIXME: is there such a thing 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
return SDOperand(N, 0);
}
+ // 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 &&
+ ST->getAddressingMode() == ISD::UNINDEXED &&
+ ST->getStoredVT() == Ld->getLoadedVT()) {
+ // The store is dead, remove it.
+ return Chain;
+ }
+ }
+
return SDOperand();
}