diff options
| author | Petar Avramovic <Petar.Avramovic@rt-rk.com> | 2019-12-30 11:26:45 +0100 |
|---|---|---|
| committer | Petar Avramovic <Petar.Avramovic@rt-rk.com> | 2019-12-30 11:26:45 +0100 |
| commit | dbc136e0fe7e14c64dcb78e72321bb41af60afa4 (patch) | |
| tree | d45452755ac0733c9411611617b10d7e3aaa7854 /llvm/lib | |
| parent | 94a24e7a401be7a3db0ddfa2035855b75c8cc55d (diff) | |
| download | bcm5719-llvm-dbc136e0fe7e14c64dcb78e72321bb41af60afa4.tar.gz bcm5719-llvm-dbc136e0fe7e14c64dcb78e72321bb41af60afa4.zip | |
[MIPS GlobalISel] Select bitreverse
G_BITREVERSE is generated from llvm.bitreverse.<type> intrinsics,
clang genrates these intrinsics from __builtin_bitreverse32 and
__builtin_bitreverse64.
Add lower and narrowscalar for G_BITREVERSE.
Lower G_BITREVERSE on MIPS32.
Differential Revision: https://reviews.llvm.org/D71363
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 46 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsLegalizerInfo.cpp | 4 |
2 files changed, 49 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 6a56a4e3c65..8e49db7b7fc 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1075,7 +1075,8 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, MI.eraseFromParent(); return Legalized; } - case TargetOpcode::G_BSWAP: { + case TargetOpcode::G_BSWAP: + case TargetOpcode::G_BITREVERSE: { if (SizeOp0 % NarrowSize != 0) return UnableToLegalize; @@ -2312,6 +2313,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) { return lowerInsert(MI); case G_BSWAP: return lowerBswap(MI); + case G_BITREVERSE: + return lowerBitreverse(MI); } } @@ -4384,3 +4387,44 @@ LegalizerHelper::lowerBswap(MachineInstr &MI) { MI.eraseFromParent(); return Legalized; } + +//{ (Src & Mask) >> N } | { (Src << N) & Mask } +static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, + MachineInstrBuilder Src, APInt Mask) { + const LLT Ty = Dst.getLLTTy(*B.getMRI()); + MachineInstrBuilder C_N = B.buildConstant(Ty, N); + MachineInstrBuilder MaskLoNTo0 = B.buildConstant(Ty, Mask); + return B.buildOr(Dst, B.buildLShr(Ty, B.buildAnd(Ty, Src, MaskLoNTo0), C_N), + B.buildAnd(Ty, B.buildShl(Ty, Src, C_N), MaskLoNTo0)); +} + +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerBitreverse(MachineInstr &MI) { + Register Dst = MI.getOperand(0).getReg(); + Register Src = MI.getOperand(1).getReg(); + const LLT Ty = MRI.getType(Src); + unsigned Size = Ty.getSizeInBits(); + + MachineInstrBuilder BSWAP = + MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {Ty}, {Src}); + + // swap high and low 4 bits in 8 bit blocks 7654|3210 -> 3210|7654 + // [(val & 0xF0F0F0F0) >> 4] | [(val & 0x0F0F0F0F) << 4] + // -> [(val & 0xF0F0F0F0) >> 4] | [(val << 4) & 0xF0F0F0F0] + MachineInstrBuilder Swap4 = + SwapN(4, Ty, MIRBuilder, BSWAP, APInt::getSplat(Size, APInt(8, 0xF0))); + + // swap high and low 2 bits in 4 bit blocks 32|10 76|54 -> 10|32 54|76 + // [(val & 0xCCCCCCCC) >> 2] & [(val & 0x33333333) << 2] + // -> [(val & 0xCCCCCCCC) >> 2] & [(val << 2) & 0xCCCCCCCC] + MachineInstrBuilder Swap2 = + SwapN(2, Ty, MIRBuilder, Swap4, APInt::getSplat(Size, APInt(8, 0xCC))); + + // swap high and low 1 bit in 2 bit blocks 1|0 3|2 5|4 7|6 -> 0|1 2|3 4|5 6|7 + // [(val & 0xAAAAAAAA) >> 1] & [(val & 0x55555555) << 1] + // -> [(val & 0xAAAAAAAA) >> 1] & [(val << 1) & 0xAAAAAAAA] + SwapN(1, Dst, MIRBuilder, Swap2, APInt::getSplat(Size, APInt(8, 0xAA))); + + MI.eraseFromParent(); + return Legalized; +} diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp index 51ad1e2de3a..39e53a75ac7 100644 --- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp +++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -198,6 +198,10 @@ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { }) .maxScalar(0, s32); + getActionDefinitionsBuilder(G_BITREVERSE) + .lowerFor({s32}) + .maxScalar(0, s32); + // FP instructions getActionDefinitionsBuilder(G_FCONSTANT) .legalFor({s32, s64}); |

