summaryrefslogtreecommitdiffstats
path: root/llvm/lib
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
commit7aad542d358a0a07512c46f755d457e80a4976fc (patch)
tree164ecbeb215cc6e1e643b5907c8c587e581a9310 /llvm/lib
parenteb4268d72fa08d7e35c1efdb833a5e0469f2a420 (diff)
downloadbcm5719-llvm-7aad542d358a0a07512c46f755d457e80a4976fc.tar.gz
bcm5719-llvm-7aad542d358a0a07512c46f755d457e80a4976fc.zip
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). llvm-svn: 58825
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index ed80b4018ca..0a8538ac7f1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/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) {
OpenPOWER on IntegriCloud