[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Apr 17 20:48:57 PDT 2005
Changes in directory llvm/lib/CodeGen/SelectionDAG:
SelectionDAG.cpp updated: 1.83 -> 1.84
---
Log message:
Make the AND elimination operation recursive and significantly more powerful,
eliminating an and for Nate's testcase:
int %bar(int %a, int %b) {
entry:
%tmp.1 = setne int %a, 0
%tmp.2 = setne int %b, 0
%tmp.3 = or bool %tmp.1, %tmp.2
%retval = cast bool %tmp.3 to int
ret int %retval
}
generating:
_bar:
addic r2, r3, -1
subfe r2, r2, r3
addic r3, r4, -1
subfe r3, r3, r4
or r3, r2, r3
blr
instead of:
_bar:
addic r2, r3, -1
subfe r2, r2, r3
addic r3, r4, -1
subfe r3, r3, r4
or r2, r2, r3
rlwinm r3, r2, 0, 31, 31
blr
---
Diffs of the changes: (+57 -26)
SelectionDAG.cpp | 83 +++++++++++++++++++++++++++++++++++++------------------
1 files changed, 57 insertions(+), 26 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.83 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.84
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.83 Thu Apr 14 03:56:52 2005
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Sun Apr 17 22:48:41 2005
@@ -647,6 +647,56 @@
return SDOperand(N, 0);
}
+/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
+/// this predicate to simplify operations downstream. V and Mask are known to
+/// be the same type.
+static bool MaskedValueIsZero(const SDOperand &Op, uint64_t Mask,
+ const TargetLowering &TLI) {
+ unsigned SrcBits;
+ if (Mask == 0) return true;
+
+ // If we know the result of a setcc has the top bits zero, use this info.
+ switch (Op.getOpcode()) {
+ case ISD::UNDEF:
+ return true;
+ case ISD::Constant:
+ return (cast<ConstantSDNode>(Op)->getValue() & Mask) == 0;
+
+ case ISD::SETCC:
+ return ((Mask & 1) == 0) &&
+ TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult;
+
+ case ISD::ZEXTLOAD:
+ SrcBits = MVT::getSizeInBits(cast<MVTSDNode>(Op)->getExtraValueType());
+ return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits.
+ case ISD::ZERO_EXTEND:
+ SrcBits = MVT::getSizeInBits(Op.getOperand(0).getValueType());
+ return MaskedValueIsZero(Op.getOperand(0),Mask & ((1ULL << SrcBits)-1),TLI);
+
+ case ISD::AND:
+ // (X & C1) & C2 == 0 iff C1 & C2 == 0.
+ if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(Op.getOperand(0)))
+ return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI);
+
+ // FALL THROUGH
+ case ISD::OR:
+ case ISD::XOR:
+ return MaskedValueIsZero(Op.getOperand(0), Mask, TLI) &&
+ MaskedValueIsZero(Op.getOperand(1), Mask, TLI);
+ case ISD::SELECT:
+ return MaskedValueIsZero(Op.getOperand(1), Mask, TLI) &&
+ MaskedValueIsZero(Op.getOperand(2), Mask, TLI);
+
+ // TODO: (shl X, C1) & C2 == 0 iff (-1 << C1) & C2 == 0
+ // TODO: (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0
+ default: break;
+ }
+
+ return false;
+}
+
+
+
SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
SDOperand N1, SDOperand N2) {
#ifndef NDEBUG
@@ -770,7 +820,7 @@
case ISD::SRL:
case ISD::SRA:
// If the shift amount is bigger than the size of the data, then all the
- // bits are shifted out. Simplify to loading constant zero.
+ // bits are shifted out. Simplify to undef.
if (C2 >= MVT::getSizeInBits(N1.getValueType())) {
return getNode(ISD::UNDEF, N1.getValueType());
}
@@ -782,6 +832,12 @@
if (N2C->isAllOnesValue())
return N1; // X and -1 -> X
+ if (MaskedValueIsZero(N1, C2, TLI)) // X and 0 -> 0
+ return getConstant(0, VT);
+
+ if (MaskedValueIsZero(N1, ~C2, TLI))
+ return N1; // if (X & ~C2) -> 0, the and is redundant
+
// FIXME: Should add a corresponding version of this for
// ZERO_EXTEND/SIGN_EXTEND by converting them to an ANY_EXTEND node which
// we don't have yet.
@@ -795,31 +851,6 @@
if ((C2 & (~0ULL << ExtendBits)) == 0)
return getNode(ISD::AND, VT, N1.getOperand(0), N2);
}
- if (N1.getOpcode() == ISD::AND)
- if (ConstantSDNode *OpRHS = dyn_cast<ConstantSDNode>(N1.getOperand(1)))
- return getNode(ISD::AND, VT, N1.getOperand(0),
- getNode(ISD::AND, VT, N1.getOperand(1), N2));
-
- // If we are anding the result of a setcc, and we know setcc always
- // returns 0 or 1, simplify the RHS to either be 0 or 1
- if (N1.getOpcode() == ISD::SETCC &&
- TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult)
- if (C2 & 1)
- return N1;
- else
- return getConstant(0, VT);
-
- if (N1.getOpcode() == ISD::ZEXTLOAD) {
- // If we are anding the result of a zext load, realize that the top bits
- // of the loaded value are already zero to simplify C2.
- unsigned SrcBits =
- MVT::getSizeInBits(cast<MVTSDNode>(N1)->getExtraValueType());
- uint64_t C3 = C2 & (~0ULL >> (64-SrcBits));
- if (C3 != C2)
- return getNode(ISD::AND, VT, N1, getConstant(C3, VT));
- else if (C2 == (~0ULL >> (64-SrcBits)))
- return N1; // Anding out just what is already masked.
- }
break;
case ISD::OR:
if (!C2)return N1; // X or 0 -> X
More information about the llvm-commits
mailing list