1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[PowerPC] support ZERO_EXTEND in tryBitPermutation

This patch add a support of ISD::ZERO_EXTEND in PPCDAGToDAGISel::tryBitPermutation to increase the opportunity to use rotate-and-mask by reordering ZEXT and ANDI.
Since tryBitPermutation stops analyzing nodes if it hits a ZEXT node while traversing SDNodes, we want to avoid ZEXT between two nodes that can be folded into a rotate-and-mask instruction.

For example, we allow these nodes

      t9: i32 = add t7, Constant:i32<1>
    t11: i32 = and t9, Constant:i32<255>
  t12: i64 = zero_extend t11
t14: i64 = shl t12, Constant:i64<2>

to be folded into a rotate-and-mask instruction.
Such case often happens in array accesses with logical AND operation in the index, e.g. array[i & 0xFF];

Differential Revision: https://reviews.llvm.org/D37514

llvm-svn: 314655
This commit is contained in:
Hiroshi Inoue 2017-10-02 09:24:00 +00:00
parent 95d7ccccc9
commit 6289766cd1
2 changed files with 87 additions and 17 deletions

View File

@ -1063,6 +1063,25 @@ class BitPermutationSelector {
return std::make_pair(Interesting = true, &Bits); return std::make_pair(Interesting = true, &Bits);
} }
case ISD::ZERO_EXTEND: {
// We support only the case with zero extension from i32 to i64 so far.
if (V.getValueType() != MVT::i64 ||
V.getOperand(0).getValueType() != MVT::i32)
break;
const SmallVector<ValueBit, 64> *LHSBits;
const unsigned NumOperandBits = 32;
std::tie(Interesting, LHSBits) = getValueBits(V.getOperand(0),
NumOperandBits);
for (unsigned i = 0; i < NumOperandBits; ++i)
Bits[i] = (*LHSBits)[i];
for (unsigned i = NumOperandBits; i < NumBits; ++i)
Bits[i] = ValueBit(ValueBit::ConstZero);
return std::make_pair(Interesting, &Bits);
}
} }
for (unsigned i = 0; i < NumBits; ++i) for (unsigned i = 0; i < NumBits; ++i)
@ -1324,6 +1343,24 @@ class BitPermutationSelector {
return ~Mask; return ~Mask;
} }
// This method extends an input value to 64 bit if input is 32-bit integer.
// While selecting instructions in BitPermutationSelector in 64-bit mode,
// an input value can be a 32-bit integer if a ZERO_EXTEND node is included.
// In such case, we extend it to 64 bit to be consistent with other values.
SDValue ExtendToInt64(SDValue V, const SDLoc &dl) {
if (V.getValueSizeInBits() == 64)
return V;
assert(V.getValueSizeInBits() == 32);
SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_32, dl, MVT::i32);
SDValue ImDef = SDValue(CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl,
MVT::i64), 0);
SDValue ExtVal = SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl,
MVT::i64, ImDef, V,
SubRegIdx), 0);
return ExtVal;
}
// Depending on the number of groups for a particular value, it might be // Depending on the number of groups for a particular value, it might be
// better to rotate, mask explicitly (using andi/andis), and then or the // better to rotate, mask explicitly (using andi/andis), and then or the
// result. Select this part of the result first. // result. Select this part of the result first.
@ -1540,27 +1577,30 @@ class BitPermutationSelector {
assert(InstMaskStart >= 32 && "Mask cannot start out of range"); assert(InstMaskStart >= 32 && "Mask cannot start out of range");
assert(InstMaskEnd >= 32 && "Mask cannot end out of range"); assert(InstMaskEnd >= 32 && "Mask cannot end out of range");
SDValue Ops[] = SDValue Ops[] =
{ V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart - 32, dl), { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
getI32Imm(InstMaskEnd - 32, dl) }; getI32Imm(InstMaskStart - 32, dl), getI32Imm(InstMaskEnd - 32, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLWINM8, dl, MVT::i64, return SDValue(CurDAG->getMachineNode(PPC::RLWINM8, dl, MVT::i64,
Ops), 0); Ops), 0);
} }
if (InstMaskEnd == 63) { if (InstMaskEnd == 63) {
SDValue Ops[] = SDValue Ops[] =
{ V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart, dl) }; { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
getI32Imm(InstMaskStart, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Ops), 0); return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Ops), 0);
} }
if (InstMaskStart == 0) { if (InstMaskStart == 0) {
SDValue Ops[] = SDValue Ops[] =
{ V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskEnd, dl) }; { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
getI32Imm(InstMaskEnd, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Ops), 0); return SDValue(CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Ops), 0);
} }
if (InstMaskEnd == 63 - RLAmt) { if (InstMaskEnd == 63 - RLAmt) {
SDValue Ops[] = SDValue Ops[] =
{ V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart, dl) }; { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
getI32Imm(InstMaskStart, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, Ops), 0); return SDValue(CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, Ops), 0);
} }
@ -1601,15 +1641,16 @@ class BitPermutationSelector {
assert(InstMaskStart >= 32 && "Mask cannot start out of range"); assert(InstMaskStart >= 32 && "Mask cannot start out of range");
assert(InstMaskEnd >= 32 && "Mask cannot end out of range"); assert(InstMaskEnd >= 32 && "Mask cannot end out of range");
SDValue Ops[] = SDValue Ops[] =
{ Base, V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart - 32, dl), { ExtendToInt64(Base, dl), ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
getI32Imm(InstMaskEnd - 32, dl) }; getI32Imm(InstMaskStart - 32, dl), getI32Imm(InstMaskEnd - 32, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64, return SDValue(CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64,
Ops), 0); Ops), 0);
} }
if (InstMaskEnd == 63 - RLAmt) { if (InstMaskEnd == 63 - RLAmt) {
SDValue Ops[] = SDValue Ops[] =
{ Base, V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart, dl) }; { ExtendToInt64(Base, dl), ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
getI32Imm(InstMaskStart, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops), 0); return SDValue(CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops), 0);
} }
@ -1759,10 +1800,14 @@ class BitPermutationSelector {
SDValue ANDIVal, ANDISVal; SDValue ANDIVal, ANDISVal;
if (ANDIMask != 0) if (ANDIMask != 0)
ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDIo8, dl, MVT::i64, ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDIo8, dl, MVT::i64,
VRot, getI32Imm(ANDIMask, dl)), 0); ExtendToInt64(VRot, dl),
getI32Imm(ANDIMask, dl)),
0);
if (ANDISMask != 0) if (ANDISMask != 0)
ANDISVal = SDValue(CurDAG->getMachineNode(PPC::ANDISo8, dl, MVT::i64, ANDISVal = SDValue(CurDAG->getMachineNode(PPC::ANDISo8, dl, MVT::i64,
VRot, getI32Imm(ANDISMask, dl)), 0); ExtendToInt64(VRot, dl),
getI32Imm(ANDISMask, dl)),
0);
if (!ANDIVal) if (!ANDIVal)
TotalVal = ANDISVal; TotalVal = ANDISVal;
@ -1770,19 +1815,21 @@ class BitPermutationSelector {
TotalVal = ANDIVal; TotalVal = ANDIVal;
else else
TotalVal = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64, TotalVal = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
ANDIVal, ANDISVal), 0); ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
} else { } else {
TotalVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0); TotalVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0);
TotalVal = TotalVal =
SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64, SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
VRot, TotalVal), 0); ExtendToInt64(VRot, dl), TotalVal),
0);
} }
if (!Res) if (!Res)
Res = TotalVal; Res = TotalVal;
else else
Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64, Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
Res, TotalVal), 0); ExtendToInt64(Res, dl), TotalVal),
0);
// Now, remove all groups with this underlying value and rotation // Now, remove all groups with this underlying value and rotation
// factor. // factor.
@ -1902,10 +1949,10 @@ class BitPermutationSelector {
SDValue ANDIVal, ANDISVal; SDValue ANDIVal, ANDISVal;
if (ANDIMask != 0) if (ANDIMask != 0)
ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDIo8, dl, MVT::i64, ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDIo8, dl, MVT::i64,
Res, getI32Imm(ANDIMask, dl)), 0); ExtendToInt64(Res, dl), getI32Imm(ANDIMask, dl)), 0);
if (ANDISMask != 0) if (ANDISMask != 0)
ANDISVal = SDValue(CurDAG->getMachineNode(PPC::ANDISo8, dl, MVT::i64, ANDISVal = SDValue(CurDAG->getMachineNode(PPC::ANDISo8, dl, MVT::i64,
Res, getI32Imm(ANDISMask, dl)), 0); ExtendToInt64(Res, dl), getI32Imm(ANDISMask, dl)), 0);
if (!ANDIVal) if (!ANDIVal)
Res = ANDISVal; Res = ANDISVal;
@ -1913,14 +1960,14 @@ class BitPermutationSelector {
Res = ANDIVal; Res = ANDIVal;
else else
Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64, Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
ANDIVal, ANDISVal), 0); ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
} else { } else {
if (InstCnt) *InstCnt += selectI64ImmInstrCount(Mask) + /* and */ 1; if (InstCnt) *InstCnt += selectI64ImmInstrCount(Mask) + /* and */ 1;
SDValue MaskVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0); SDValue MaskVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0);
Res = Res =
SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64, SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
Res, MaskVal), 0); ExtendToInt64(Res, dl), MaskVal), 0);
} }
} }

View File

@ -0,0 +1,23 @@
; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s
; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s
; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s
; Test case for PPCTargetLowering::extendSubTreeForBitPermutation.
; We expect mask and rotate are folded into a rlwinm instruction.
define zeroext i32 @func(i32* %p, i32 zeroext %i) {
; CHECK-LABEL: @func
; CHECK: addi [[REG1:[0-9]+]], 4, 1
; CHECK: rlwinm [[REG2:[0-9]+]], [[REG1]], 2, 22, 29
; CHECK-NOT: sldi
; CHECK: lwzx 3, 3, [[REG2]]
; CHECK: blr
entry:
%add = add i32 %i, 1
%and = and i32 %add, 255
%idxprom = zext i32 %and to i64
%arrayidx = getelementptr inbounds i32, i32* %p, i64 %idxprom
%0 = load i32, i32* %arrayidx, align 4
ret i32 %0
}