Skip to content

Commit

Permalink
[RISCV] Add computeKnownBits support for RISCVISD::GORC.
Browse files Browse the repository at this point in the history
Reviewed By: luismarques

Differential Revision: https://reviews.llvm.org/D121575
  • Loading branch information
topperc committed Mar 28, 2022
1 parent 1a963d3 commit 0120391
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 20 deletions.
47 changes: 31 additions & 16 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Expand Up @@ -8931,21 +8931,33 @@ bool RISCVTargetLowering::targetShrinkDemandedConstant(
return UseMask(NewMask);
}

static void computeGREV(APInt &Src, unsigned ShAmt) {
static void computeGREVOrGORC(APInt &Src, unsigned ShAmt, bool IsGORC,
bool ComputeZeros = false) {
static const uint64_t GREVMasks[] = {
0x5555555555555555ULL, 0x3333333333333333ULL, 0x0F0F0F0F0F0F0F0FULL,
0x00FF00FF00FF00FFULL, 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};

ShAmt &= Src.getBitWidth() - 1;
uint64_t x = Src.getZExtValue();
if (ShAmt & 1)
x = ((x & 0x5555555555555555LL) << 1) | ((x & 0xAAAAAAAAAAAAAAAALL) >> 1);
if (ShAmt & 2)
x = ((x & 0x3333333333333333LL) << 2) | ((x & 0xCCCCCCCCCCCCCCCCLL) >> 2);
if (ShAmt & 4)
x = ((x & 0x0F0F0F0F0F0F0F0FLL) << 4) | ((x & 0xF0F0F0F0F0F0F0F0LL) >> 4);
if (ShAmt & 8)
x = ((x & 0x00FF00FF00FF00FFLL) << 8) | ((x & 0xFF00FF00FF00FF00LL) >> 8);
if (ShAmt & 16)
x = ((x & 0x0000FFFF0000FFFFLL) << 16) | ((x & 0xFFFF0000FFFF0000LL) >> 16);
if (ShAmt & 32)
x = ((x & 0x00000000FFFFFFFFLL) << 32) | ((x & 0xFFFFFFFF00000000LL) >> 32);

// To compute zeros, we need to invert the value and invert it back after.
if (ComputeZeros)
x = ~x;

for (unsigned Stage = 0; Stage != 6; ++Stage) {
unsigned Shift = 1 << Stage;
if (ShAmt & Shift) {
uint64_t Mask = GREVMasks[Stage];
uint64_t Res = ((x & Mask) << Shift) | ((x >> Shift) & Mask);
if (IsGORC)
Res |= x;
x = Res;
}
}

if (ComputeZeros)
x = ~x;

Src = x;
}

Expand Down Expand Up @@ -9011,12 +9023,15 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
Known.Zero.setBitsFrom(LowBits);
break;
}
case RISCVISD::GREV: {
case RISCVISD::GREV:
case RISCVISD::GORC: {
if (auto *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
Known = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
unsigned ShAmt = C->getZExtValue();
computeGREV(Known.Zero, ShAmt);
computeGREV(Known.One, ShAmt);
bool IsGORC = Op.getOpcode() == RISCVISD::GORC;
computeGREVOrGORC(Known.Zero, ShAmt, IsGORC,
/*ComputeZeros*/ true);
computeGREVOrGORC(Known.One, ShAmt, IsGORC);
}
break;
}
Expand Down
19 changes: 19 additions & 0 deletions llvm/test/CodeGen/RISCV/rv32zbb-intrinsic.ll
Expand Up @@ -12,3 +12,22 @@ define i32 @orcb(i32 %a) nounwind {
%tmp = call i32 @llvm.riscv.orc.b.i32(i32 %a)
ret i32 %tmp
}

; Second and+or are redundant with the first, make sure we remove it.
define i32 @orcb_knownbits(i32 %a) nounwind {
; RV32ZBB-LABEL: orcb_knownbits:
; RV32ZBB: # %bb.0:
; RV32ZBB-NEXT: lui a1, 1044480
; RV32ZBB-NEXT: and a0, a0, a1
; RV32ZBB-NEXT: lui a1, 2048
; RV32ZBB-NEXT: addi a1, a1, 1
; RV32ZBB-NEXT: or a0, a0, a1
; RV32ZBB-NEXT: orc.b a0, a0
; RV32ZBB-NEXT: ret
%tmp = and i32 %a, 4278190080 ; 0xFF000000
%tmp2 = or i32 %tmp, 8388609 ; 0x800001
%tmp3 = call i32 @llvm.riscv.orc.b.i32(i32 %tmp2)
%tmp4 = and i32 %tmp3, 4278190080 ; 0xFF000000
%tmp5 = or i32 %tmp4, 16711935 ; 0xFF00FF
ret i32 %tmp5
}
71 changes: 67 additions & 4 deletions llvm/test/CodeGen/RISCV/rv64zbb-intrinsic.ll
Expand Up @@ -25,20 +25,46 @@ define zeroext i32 @orcb32_zext(i32 zeroext %a) nounwind {
; RV64ZBB-LABEL: orcb32_zext:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: orc.b a0, a0
; RV64ZBB-NEXT: slli a0, a0, 32
; RV64ZBB-NEXT: srli a0, a0, 32
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: orcb32_zext:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: orc.b a0, a0
; RV64ZBP-NEXT: slli a0, a0, 32
; RV64ZBP-NEXT: srli a0, a0, 32
; RV64ZBP-NEXT: ret
%tmp = call i32 @llvm.riscv.orc.b.i32(i32 %a)
ret i32 %tmp
}

; Second and+or is redundant with the first, make sure we remove them.
define signext i32 @orcb32_knownbits(i32 signext %a) nounwind {
; RV64ZBB-LABEL: orcb32_knownbits:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: lui a1, 1044480
; RV64ZBB-NEXT: and a0, a0, a1
; RV64ZBB-NEXT: lui a1, 2048
; RV64ZBB-NEXT: addiw a1, a1, 1
; RV64ZBB-NEXT: or a0, a0, a1
; RV64ZBB-NEXT: orc.b a0, a0
; RV64ZBB-NEXT: sext.w a0, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: orcb32_knownbits:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: lui a1, 1044480
; RV64ZBP-NEXT: and a0, a0, a1
; RV64ZBP-NEXT: lui a1, 2048
; RV64ZBP-NEXT: addiw a1, a1, 1
; RV64ZBP-NEXT: or a0, a0, a1
; RV64ZBP-NEXT: gorciw a0, a0, 7
; RV64ZBP-NEXT: ret
%tmp = and i32 %a, 4278190080 ; 0xFF000000
%tmp2 = or i32 %tmp, 8388609 ; 0x800001
%tmp3 = call i32 @llvm.riscv.orc.b.i32(i32 %tmp2)
%tmp4 = and i32 %tmp3, 4278190080 ; 0xFF000000
%tmp5 = or i32 %tmp4, 16711935 ; 0xFF00FF
ret i32 %tmp5
}

declare i64 @llvm.riscv.orc.b.i64(i64)

define i64 @orcb64(i64 %a) nounwind {
Expand All @@ -54,3 +80,40 @@ define i64 @orcb64(i64 %a) nounwind {
%tmp = call i64 @llvm.riscv.orc.b.i64(i64 %a)
ret i64 %tmp
}

; Second and+or is redundant with the first, make sure we remove them.
define i64 @orcb64_knownbits(i64 %a) nounwind {
; RV64ZBB-LABEL: orcb64_knownbits:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: lui a1, 65535
; RV64ZBB-NEXT: slli a1, a1, 12
; RV64ZBB-NEXT: and a0, a0, a1
; RV64ZBB-NEXT: lui a1, 131073
; RV64ZBB-NEXT: slli a1, a1, 13
; RV64ZBB-NEXT: addi a1, a1, 1
; RV64ZBB-NEXT: slli a1, a1, 20
; RV64ZBB-NEXT: addi a1, a1, 8
; RV64ZBB-NEXT: or a0, a0, a1
; RV64ZBB-NEXT: orc.b a0, a0
; RV64ZBB-NEXT: ret
;
; RV64ZBP-LABEL: orcb64_knownbits:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: lui a1, 65535
; RV64ZBP-NEXT: slli a1, a1, 12
; RV64ZBP-NEXT: and a0, a0, a1
; RV64ZBP-NEXT: lui a1, 131073
; RV64ZBP-NEXT: slli a1, a1, 13
; RV64ZBP-NEXT: addi a1, a1, 1
; RV64ZBP-NEXT: slli a1, a1, 20
; RV64ZBP-NEXT: addi a1, a1, 8
; RV64ZBP-NEXT: or a0, a0, a1
; RV64ZBP-NEXT: orc.b a0, a0
; RV64ZBP-NEXT: ret
%tmp = and i64 %a, 1099494850560 ; 0x000000ffff000000
%tmp2 = or i64 %tmp, 4611721202800525320 ; 0x4000200000100008
%tmp3 = call i64 @llvm.riscv.orc.b.i64(i64 %tmp2)
%tmp4 = and i64 %tmp3, 1099494850560 ; 0x000000ffff000000
%tmp5 = or i64 %tmp4, 18374966855153418495 ; 0xff00ff0000ff00ff
ret i64 %tmp5
}
24 changes: 24 additions & 0 deletions llvm/test/CodeGen/RISCV/rv64zbp-intrinsic.ll
Expand Up @@ -75,6 +75,15 @@ define signext i32 @gorci32(i32 signext %a) nounwind {
ret i32 %tmp
}

define zeroext i32 @gorci32_zext(i32 zeroext %a) nounwind {
; RV64ZBP-LABEL: gorci32_zext:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: orc.w a0, a0
; RV64ZBP-NEXT: ret
%tmp = call i32 @llvm.riscv.gorc.i32(i32 %a, i32 31)
ret i32 %tmp
}

declare i32 @llvm.riscv.shfl.i32(i32 %a, i32 %b)

define signext i32 @shfl32(i32 signext %a, i32 signext %b) nounwind {
Expand Down Expand Up @@ -515,6 +524,21 @@ define i64 @gorci64(i64 %a) nounwind {
ret i64 %tmp
}

; The second OR is redundant with the first. Make sure we remove it.
define i64 @gorci64_knownbits(i64 %a) nounwind {
; RV64ZBP-LABEL: gorci64_knownbits:
; RV64ZBP: # %bb.0:
; RV64ZBP-NEXT: lui a1, %hi(.LCPI54_0)
; RV64ZBP-NEXT: ld a1, %lo(.LCPI54_0)(a1)
; RV64ZBP-NEXT: or a0, a0, a1
; RV64ZBP-NEXT: orc32 a0, a0
; RV64ZBP-NEXT: ret
%tmp = or i64 %a, 72624976668147840 ; 0x102040810204080
%tmp2 = call i64 @llvm.riscv.gorc.i64(i64 %tmp, i64 32)
%tmp3 = or i64 %tmp2, 1234624599046636680 ; 0x1122448811224488
ret i64 %tmp3
}

define i64 @orchi64(i64 %a) nounwind {
; RV64ZBP-LABEL: orchi64:
; RV64ZBP: # %bb.0:
Expand Down

0 comments on commit 0120391

Please sign in to comment.