aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/TargetLowering.cpp
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2008-11-07 01:28:02 +0000
committerDale Johannesen <dalej@apple.com>2008-11-07 01:28:02 +0000
commit89217a6f1852e764e58c489872b2d155dc2b7b8b (patch)
tree7971bcf9cef3aa08e40cdcaa4ea8a0f6badad4e9 /lib/CodeGen/SelectionDAG/TargetLowering.cpp
parentb7c6ebcb4732302310cfaca81e1d26c3802c1646 (diff)
When we're doing a compare of load-AND-constant to 0
(e.g. a bitfield test) narrow the load as much as possible. The has the potential to avoid unnecessary partial-word load-after-store conflicts, which cause stalls on several targets. Also a size win on x86 (testb vs testl). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58825 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/TargetLowering.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index ed80b4018c..0a8538ac7f 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1352,6 +1352,52 @@ TargetLowering::SimplifySetCC(MVT VT, SDValue N0, SDValue N1,
Zero, Cond);
}
}
+
+ // If the LHS is '(and load, const)', the RHS is 0,
+ // the test is for equality or unsigned, and all 1 bits of the const are
+ // in the same partial word, see if we can shorten the load.
+ if (DCI.isBeforeLegalize() &&
+ N0.getOpcode() == ISD::AND && C1 == 0 &&
+ isa<LoadSDNode>(N0.getOperand(0)) &&
+ N0.getOperand(0).getNode()->hasOneUse() &&
+ isa<ConstantSDNode>(N0.getOperand(1))) {
+ LoadSDNode *Lod = cast<LoadSDNode>(N0.getOperand(0));
+ uint64_t Mask = cast<ConstantSDNode>(N0.getOperand(1))->getZExtValue();
+ unsigned bestWidth = 0, bestOffset = 0;
+ if (!Lod->isVolatile()) {
+ unsigned origWidth = N0.getValueType().getSizeInBits();
+ for (unsigned width = origWidth / 2; width>=8; width /= 2) {
+ uint64_t newMask = (1ULL << width) - 1;
+ for (unsigned offset=0; offset<origWidth/width; offset++) {
+ if ((newMask & Mask)==Mask) {
+ bestOffset = (uint64_t)offset * (width/8);
+ bestWidth = width;
+ break;
+ }
+ newMask = newMask << width;
+ }
+ }
+ }
+ if (bestWidth) {
+ MVT newVT = MVT::getIntegerVT(bestWidth);
+ if (newVT.isRound()) {
+ uint64_t bestMask = Mask >> (bestOffset * 8);
+ MVT PtrType = Lod->getOperand(1).getValueType();
+ SDValue Ptr = Lod->getBasePtr();
+ if (bestOffset != 0)
+ Ptr = DAG.getNode(ISD::ADD, PtrType, Lod->getBasePtr(),
+ DAG.getConstant(bestOffset, PtrType));
+ unsigned NewAlign = MinAlign(Lod->getAlignment(), bestOffset);
+ SDValue NewLoad = DAG.getLoad(newVT, Lod->getChain(), Ptr,
+ Lod->getSrcValue(),
+ Lod->getSrcValueOffset() + bestOffset,
+ false, NewAlign);
+ return DAG.getSetCC(VT, DAG.getNode(ISD::AND, newVT, NewLoad,
+ DAG.getConstant(bestMask, newVT)),
+ DAG.getConstant(0LL, newVT), Cond);
+ }
+ }
+ }
// If the LHS is a ZERO_EXTEND, perform the comparison on the input.
if (N0.getOpcode() == ISD::ZERO_EXTEND) {