mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
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
This commit is contained in:
parent
b7c6ebcb47
commit
89217a6f18
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user