diff options
author | Dale Johannesen <dalej@apple.com> | 2008-11-07 01:28:02 +0000 |
---|---|---|
committer | Dale Johannesen <dalej@apple.com> | 2008-11-07 01:28:02 +0000 |
commit | d0a7c0eb006563aa47d9e4338986c7766b191a2c (patch) | |
tree | 7971bcf9cef3aa08e40cdcaa4ea8a0f6badad4e9 /lib | |
parent | 8126a3f4f8d04e45f8fa21d4c76c128477ac4398 (diff) | |
download | external_llvm-d0a7c0eb006563aa47d9e4338986c7766b191a2c.zip external_llvm-d0a7c0eb006563aa47d9e4338986c7766b191a2c.tar.gz external_llvm-d0a7c0eb006563aa47d9e4338986c7766b191a2c.tar.bz2 |
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')
-rw-r--r-- | lib/CodeGen/SelectionDAG/TargetLowering.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index ed80b40..0a8538a 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) { |