[llvm] [RISCV] and x (sub 0, y) -> andn x y (PR #129253)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 28 07:22:05 PST 2025


https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/129253

>From a1094b21d0226d8993ab43bfd39fdf32490b4db6 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Fri, 28 Feb 2025 15:38:00 +0100
Subject: [PATCH 1/2] [RISCV][SelDAG] and x (sub 0, y) -> andn x y

---
 llvm/lib/Target/RISCV/RISCVInstrInfoZb.td     |   1 +
 .../CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll  | 329 +++++++++++++-----
 .../CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll  |  27 ++
 llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll       |  94 +++--
 llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll       |  27 ++
 5 files changed, 362 insertions(+), 116 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index 2ce909c5d0e21..92d126fb8bcf9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -483,6 +483,7 @@ def invLogicImm : ComplexPattern<XLenVT, 1, "selectInvLogicImm", [], [], 0>;
 
 let Predicates = [HasStdExtZbbOrZbkb] in {
 def : Pat<(XLenVT (and GPR:$rs1, (not GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
+def : Pat<(XLenVT (and GPR:$rs1, (sub 0, GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
 def : Pat<(XLenVT (or  GPR:$rs1, (not GPR:$rs2))), (ORN  GPR:$rs1, GPR:$rs2)>;
 def : Pat<(XLenVT (xor GPR:$rs1, (not GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
 
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll
index ababec16f7f8f..03a3e4b3ff742 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll
@@ -22,6 +22,22 @@ define i32 @andn_i32(i32 %a, i32 %b) nounwind {
   ret i32 %and
 }
 
+define i32 @andn_i32_from_sub(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: andn_i32_from_sub:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    neg a1, a1
+; RV32I-NEXT:    and a0, a1, a0
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: andn_i32_from_sub:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a1
+; RV32ZBB-ZBKB-NEXT:    ret
+  %neg = sub i32 0, %b
+  %and = and i32 %neg, %a
+  ret i32 %and
+}
+
 define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 ; RV32I-LABEL: andn_i64:
 ; RV32I:       # %bb.0:
@@ -41,6 +57,30 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
   ret i64 %and
 }
 
+define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
+; RV32I-LABEL: andn_i64_from_sub:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    neg a4, a2
+; RV32I-NEXT:    snez a2, a2
+; RV32I-NEXT:    neg a3, a3
+; RV32I-NEXT:    sub a3, a3, a2
+; RV32I-NEXT:    and a0, a4, a0
+; RV32I-NEXT:    and a1, a3, a1
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: andn_i64_from_sub:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    snez a4, a2
+; RV32ZBB-ZBKB-NEXT:    neg a3, a3
+; RV32ZBB-ZBKB-NEXT:    sub a3, a3, a4
+; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a2
+; RV32ZBB-ZBKB-NEXT:    and a1, a3, a1
+; RV32ZBB-ZBKB-NEXT:    ret
+  %neg = sub i64 0, %b
+  %and = and i64 %neg, %a
+  ret i64 %and
+}
+
 define i32 @orn_i32(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: orn_i32:
 ; RV32I:       # %bb.0:
@@ -136,53 +176,102 @@ define i32 @rol_i32(i32 %a, i32 %b) nounwind {
 declare i64 @llvm.fshl.i64(i64, i64, i64)
 
 define i64 @rol_i64(i64 %a, i64 %b) nounwind {
-; CHECK-LABEL: rol_i64:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    andi a6, a2, 63
-; CHECK-NEXT:    li a4, 32
-; CHECK-NEXT:    bltu a6, a4, .LBB7_2
-; CHECK-NEXT:  # %bb.1:
-; CHECK-NEXT:    li a3, 0
-; CHECK-NEXT:    sll a7, a0, a6
-; CHECK-NEXT:    j .LBB7_3
-; CHECK-NEXT:  .LBB7_2:
-; CHECK-NEXT:    sll a3, a0, a2
-; CHECK-NEXT:    neg a5, a6
-; CHECK-NEXT:    srl a5, a0, a5
-; CHECK-NEXT:    sll a7, a1, a2
-; CHECK-NEXT:    or a7, a5, a7
-; CHECK-NEXT:  .LBB7_3:
-; CHECK-NEXT:    neg a5, a2
-; CHECK-NEXT:    mv a2, a1
-; CHECK-NEXT:    beqz a6, .LBB7_5
-; CHECK-NEXT:  # %bb.4:
-; CHECK-NEXT:    mv a2, a7
-; CHECK-NEXT:  .LBB7_5:
-; CHECK-NEXT:    andi a6, a5, 63
-; CHECK-NEXT:    bltu a6, a4, .LBB7_7
-; CHECK-NEXT:  # %bb.6:
-; CHECK-NEXT:    srl a7, a1, a6
-; CHECK-NEXT:    bnez a6, .LBB7_8
-; CHECK-NEXT:    j .LBB7_9
-; CHECK-NEXT:  .LBB7_7:
-; CHECK-NEXT:    srl a7, a0, a5
-; CHECK-NEXT:    neg t0, a6
-; CHECK-NEXT:    sll t0, a1, t0
-; CHECK-NEXT:    or a7, a7, t0
-; CHECK-NEXT:    beqz a6, .LBB7_9
-; CHECK-NEXT:  .LBB7_8:
-; CHECK-NEXT:    mv a0, a7
-; CHECK-NEXT:  .LBB7_9:
-; CHECK-NEXT:    bltu a6, a4, .LBB7_11
-; CHECK-NEXT:  # %bb.10:
-; CHECK-NEXT:    li a1, 0
-; CHECK-NEXT:    j .LBB7_12
-; CHECK-NEXT:  .LBB7_11:
-; CHECK-NEXT:    srl a1, a1, a5
-; CHECK-NEXT:  .LBB7_12:
-; CHECK-NEXT:    or a0, a3, a0
-; CHECK-NEXT:    or a1, a2, a1
-; CHECK-NEXT:    ret
+; RV32I-LABEL: rol_i64:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    andi a6, a2, 63
+; RV32I-NEXT:    li a4, 32
+; RV32I-NEXT:    bltu a6, a4, .LBB9_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    li a3, 0
+; RV32I-NEXT:    sll a7, a0, a6
+; RV32I-NEXT:    j .LBB9_3
+; RV32I-NEXT:  .LBB9_2:
+; RV32I-NEXT:    sll a3, a0, a2
+; RV32I-NEXT:    neg a5, a6
+; RV32I-NEXT:    srl a5, a0, a5
+; RV32I-NEXT:    sll a7, a1, a2
+; RV32I-NEXT:    or a7, a5, a7
+; RV32I-NEXT:  .LBB9_3:
+; RV32I-NEXT:    neg a5, a2
+; RV32I-NEXT:    mv a2, a1
+; RV32I-NEXT:    beqz a6, .LBB9_5
+; RV32I-NEXT:  # %bb.4:
+; RV32I-NEXT:    mv a2, a7
+; RV32I-NEXT:  .LBB9_5:
+; RV32I-NEXT:    andi a6, a5, 63
+; RV32I-NEXT:    bltu a6, a4, .LBB9_7
+; RV32I-NEXT:  # %bb.6:
+; RV32I-NEXT:    srl a7, a1, a6
+; RV32I-NEXT:    bnez a6, .LBB9_8
+; RV32I-NEXT:    j .LBB9_9
+; RV32I-NEXT:  .LBB9_7:
+; RV32I-NEXT:    srl a7, a0, a5
+; RV32I-NEXT:    neg t0, a6
+; RV32I-NEXT:    sll t0, a1, t0
+; RV32I-NEXT:    or a7, a7, t0
+; RV32I-NEXT:    beqz a6, .LBB9_9
+; RV32I-NEXT:  .LBB9_8:
+; RV32I-NEXT:    mv a0, a7
+; RV32I-NEXT:  .LBB9_9:
+; RV32I-NEXT:    bltu a6, a4, .LBB9_11
+; RV32I-NEXT:  # %bb.10:
+; RV32I-NEXT:    li a1, 0
+; RV32I-NEXT:    j .LBB9_12
+; RV32I-NEXT:  .LBB9_11:
+; RV32I-NEXT:    srl a1, a1, a5
+; RV32I-NEXT:  .LBB9_12:
+; RV32I-NEXT:    or a0, a3, a0
+; RV32I-NEXT:    or a1, a2, a1
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: rol_i64:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    andi a6, a2, 63
+; RV32ZBB-ZBKB-NEXT:    li a4, 32
+; RV32ZBB-ZBKB-NEXT:    bltu a6, a4, .LBB9_2
+; RV32ZBB-ZBKB-NEXT:  # %bb.1:
+; RV32ZBB-ZBKB-NEXT:    li a3, 0
+; RV32ZBB-ZBKB-NEXT:    sll a7, a0, a6
+; RV32ZBB-ZBKB-NEXT:    j .LBB9_3
+; RV32ZBB-ZBKB-NEXT:  .LBB9_2:
+; RV32ZBB-ZBKB-NEXT:    sll a3, a0, a2
+; RV32ZBB-ZBKB-NEXT:    neg a5, a6
+; RV32ZBB-ZBKB-NEXT:    srl a5, a0, a5
+; RV32ZBB-ZBKB-NEXT:    sll a7, a1, a2
+; RV32ZBB-ZBKB-NEXT:    or a7, a5, a7
+; RV32ZBB-ZBKB-NEXT:  .LBB9_3:
+; RV32ZBB-ZBKB-NEXT:    li t0, 63
+; RV32ZBB-ZBKB-NEXT:    mv a5, a1
+; RV32ZBB-ZBKB-NEXT:    beqz a6, .LBB9_5
+; RV32ZBB-ZBKB-NEXT:  # %bb.4:
+; RV32ZBB-ZBKB-NEXT:    mv a5, a7
+; RV32ZBB-ZBKB-NEXT:  .LBB9_5:
+; RV32ZBB-ZBKB-NEXT:    andn a6, t0, a2
+; RV32ZBB-ZBKB-NEXT:    neg a2, a2
+; RV32ZBB-ZBKB-NEXT:    bltu a6, a4, .LBB9_7
+; RV32ZBB-ZBKB-NEXT:  # %bb.6:
+; RV32ZBB-ZBKB-NEXT:    srl a7, a1, a6
+; RV32ZBB-ZBKB-NEXT:    bnez a6, .LBB9_8
+; RV32ZBB-ZBKB-NEXT:    j .LBB9_9
+; RV32ZBB-ZBKB-NEXT:  .LBB9_7:
+; RV32ZBB-ZBKB-NEXT:    srl a7, a0, a2
+; RV32ZBB-ZBKB-NEXT:    neg t0, a6
+; RV32ZBB-ZBKB-NEXT:    sll t0, a1, t0
+; RV32ZBB-ZBKB-NEXT:    or a7, a7, t0
+; RV32ZBB-ZBKB-NEXT:    beqz a6, .LBB9_9
+; RV32ZBB-ZBKB-NEXT:  .LBB9_8:
+; RV32ZBB-ZBKB-NEXT:    mv a0, a7
+; RV32ZBB-ZBKB-NEXT:  .LBB9_9:
+; RV32ZBB-ZBKB-NEXT:    bltu a6, a4, .LBB9_11
+; RV32ZBB-ZBKB-NEXT:  # %bb.10:
+; RV32ZBB-ZBKB-NEXT:    li a1, 0
+; RV32ZBB-ZBKB-NEXT:    j .LBB9_12
+; RV32ZBB-ZBKB-NEXT:  .LBB9_11:
+; RV32ZBB-ZBKB-NEXT:    srl a1, a1, a2
+; RV32ZBB-ZBKB-NEXT:  .LBB9_12:
+; RV32ZBB-ZBKB-NEXT:    or a0, a3, a0
+; RV32ZBB-ZBKB-NEXT:    or a1, a5, a1
+; RV32ZBB-ZBKB-NEXT:    ret
   %or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
   ret i64 %or
 }
@@ -212,54 +301,104 @@ define i32 @ror_i32(i32 %a, i32 %b) nounwind {
 declare i64 @llvm.fshr.i64(i64, i64, i64)
 
 define i64 @ror_i64(i64 %a, i64 %b) nounwind {
-; CHECK-LABEL: ror_i64:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    andi a5, a2, 63
-; CHECK-NEXT:    li a4, 32
-; CHECK-NEXT:    bltu a5, a4, .LBB9_2
-; CHECK-NEXT:  # %bb.1:
-; CHECK-NEXT:    srl a6, a1, a5
-; CHECK-NEXT:    mv a3, a0
-; CHECK-NEXT:    bnez a5, .LBB9_3
-; CHECK-NEXT:    j .LBB9_4
-; CHECK-NEXT:  .LBB9_2:
-; CHECK-NEXT:    srl a3, a0, a2
-; CHECK-NEXT:    neg a6, a5
-; CHECK-NEXT:    sll a6, a1, a6
-; CHECK-NEXT:    or a6, a3, a6
-; CHECK-NEXT:    mv a3, a0
-; CHECK-NEXT:    beqz a5, .LBB9_4
-; CHECK-NEXT:  .LBB9_3:
-; CHECK-NEXT:    mv a3, a6
-; CHECK-NEXT:  .LBB9_4:
-; CHECK-NEXT:    neg a6, a2
-; CHECK-NEXT:    bltu a5, a4, .LBB9_7
-; CHECK-NEXT:  # %bb.5:
-; CHECK-NEXT:    li a2, 0
-; CHECK-NEXT:    andi a5, a6, 63
-; CHECK-NEXT:    bgeu a5, a4, .LBB9_8
-; CHECK-NEXT:  .LBB9_6:
-; CHECK-NEXT:    sll a4, a0, a6
-; CHECK-NEXT:    neg a7, a5
-; CHECK-NEXT:    srl a0, a0, a7
-; CHECK-NEXT:    sll a6, a1, a6
-; CHECK-NEXT:    or a0, a0, a6
-; CHECK-NEXT:    bnez a5, .LBB9_9
-; CHECK-NEXT:    j .LBB9_10
-; CHECK-NEXT:  .LBB9_7:
-; CHECK-NEXT:    srl a2, a1, a2
-; CHECK-NEXT:    andi a5, a6, 63
-; CHECK-NEXT:    bltu a5, a4, .LBB9_6
-; CHECK-NEXT:  .LBB9_8:
-; CHECK-NEXT:    li a4, 0
-; CHECK-NEXT:    sll a0, a0, a5
-; CHECK-NEXT:    beqz a5, .LBB9_10
-; CHECK-NEXT:  .LBB9_9:
-; CHECK-NEXT:    mv a1, a0
-; CHECK-NEXT:  .LBB9_10:
-; CHECK-NEXT:    or a0, a3, a4
-; CHECK-NEXT:    or a1, a2, a1
-; CHECK-NEXT:    ret
+; RV32I-LABEL: ror_i64:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    andi a5, a2, 63
+; RV32I-NEXT:    li a4, 32
+; RV32I-NEXT:    bltu a5, a4, .LBB11_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    srl a6, a1, a5
+; RV32I-NEXT:    mv a3, a0
+; RV32I-NEXT:    bnez a5, .LBB11_3
+; RV32I-NEXT:    j .LBB11_4
+; RV32I-NEXT:  .LBB11_2:
+; RV32I-NEXT:    srl a3, a0, a2
+; RV32I-NEXT:    neg a6, a5
+; RV32I-NEXT:    sll a6, a1, a6
+; RV32I-NEXT:    or a6, a3, a6
+; RV32I-NEXT:    mv a3, a0
+; RV32I-NEXT:    beqz a5, .LBB11_4
+; RV32I-NEXT:  .LBB11_3:
+; RV32I-NEXT:    mv a3, a6
+; RV32I-NEXT:  .LBB11_4:
+; RV32I-NEXT:    neg a6, a2
+; RV32I-NEXT:    bltu a5, a4, .LBB11_7
+; RV32I-NEXT:  # %bb.5:
+; RV32I-NEXT:    li a2, 0
+; RV32I-NEXT:    andi a5, a6, 63
+; RV32I-NEXT:    bgeu a5, a4, .LBB11_8
+; RV32I-NEXT:  .LBB11_6:
+; RV32I-NEXT:    sll a4, a0, a6
+; RV32I-NEXT:    neg a7, a5
+; RV32I-NEXT:    srl a0, a0, a7
+; RV32I-NEXT:    sll a6, a1, a6
+; RV32I-NEXT:    or a0, a0, a6
+; RV32I-NEXT:    bnez a5, .LBB11_9
+; RV32I-NEXT:    j .LBB11_10
+; RV32I-NEXT:  .LBB11_7:
+; RV32I-NEXT:    srl a2, a1, a2
+; RV32I-NEXT:    andi a5, a6, 63
+; RV32I-NEXT:    bltu a5, a4, .LBB11_6
+; RV32I-NEXT:  .LBB11_8:
+; RV32I-NEXT:    li a4, 0
+; RV32I-NEXT:    sll a0, a0, a5
+; RV32I-NEXT:    beqz a5, .LBB11_10
+; RV32I-NEXT:  .LBB11_9:
+; RV32I-NEXT:    mv a1, a0
+; RV32I-NEXT:  .LBB11_10:
+; RV32I-NEXT:    or a0, a3, a4
+; RV32I-NEXT:    or a1, a2, a1
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: ror_i64:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    andi a4, a2, 63
+; RV32ZBB-ZBKB-NEXT:    li a5, 32
+; RV32ZBB-ZBKB-NEXT:    bltu a4, a5, .LBB11_2
+; RV32ZBB-ZBKB-NEXT:  # %bb.1:
+; RV32ZBB-ZBKB-NEXT:    srl a6, a1, a4
+; RV32ZBB-ZBKB-NEXT:    mv a3, a0
+; RV32ZBB-ZBKB-NEXT:    bnez a4, .LBB11_3
+; RV32ZBB-ZBKB-NEXT:    j .LBB11_4
+; RV32ZBB-ZBKB-NEXT:  .LBB11_2:
+; RV32ZBB-ZBKB-NEXT:    srl a3, a0, a2
+; RV32ZBB-ZBKB-NEXT:    neg a6, a4
+; RV32ZBB-ZBKB-NEXT:    sll a6, a1, a6
+; RV32ZBB-ZBKB-NEXT:    or a6, a3, a6
+; RV32ZBB-ZBKB-NEXT:    mv a3, a0
+; RV32ZBB-ZBKB-NEXT:    beqz a4, .LBB11_4
+; RV32ZBB-ZBKB-NEXT:  .LBB11_3:
+; RV32ZBB-ZBKB-NEXT:    mv a3, a6
+; RV32ZBB-ZBKB-NEXT:  .LBB11_4:
+; RV32ZBB-ZBKB-NEXT:    li a6, 63
+; RV32ZBB-ZBKB-NEXT:    bltu a4, a5, .LBB11_7
+; RV32ZBB-ZBKB-NEXT:  # %bb.5:
+; RV32ZBB-ZBKB-NEXT:    li a4, 0
+; RV32ZBB-ZBKB-NEXT:    andn a6, a6, a2
+; RV32ZBB-ZBKB-NEXT:    bgeu a6, a5, .LBB11_8
+; RV32ZBB-ZBKB-NEXT:  .LBB11_6:
+; RV32ZBB-ZBKB-NEXT:    neg a5, a2
+; RV32ZBB-ZBKB-NEXT:    neg a7, a6
+; RV32ZBB-ZBKB-NEXT:    sll a2, a0, a5
+; RV32ZBB-ZBKB-NEXT:    srl a0, a0, a7
+; RV32ZBB-ZBKB-NEXT:    sll a5, a1, a5
+; RV32ZBB-ZBKB-NEXT:    or a0, a0, a5
+; RV32ZBB-ZBKB-NEXT:    bnez a6, .LBB11_9
+; RV32ZBB-ZBKB-NEXT:    j .LBB11_10
+; RV32ZBB-ZBKB-NEXT:  .LBB11_7:
+; RV32ZBB-ZBKB-NEXT:    srl a4, a1, a2
+; RV32ZBB-ZBKB-NEXT:    andn a6, a6, a2
+; RV32ZBB-ZBKB-NEXT:    bltu a6, a5, .LBB11_6
+; RV32ZBB-ZBKB-NEXT:  .LBB11_8:
+; RV32ZBB-ZBKB-NEXT:    li a2, 0
+; RV32ZBB-ZBKB-NEXT:    sll a0, a0, a6
+; RV32ZBB-ZBKB-NEXT:    beqz a6, .LBB11_10
+; RV32ZBB-ZBKB-NEXT:  .LBB11_9:
+; RV32ZBB-ZBKB-NEXT:    mv a1, a0
+; RV32ZBB-ZBKB-NEXT:  .LBB11_10:
+; RV32ZBB-ZBKB-NEXT:    or a0, a3, a2
+; RV32ZBB-ZBKB-NEXT:    or a1, a4, a1
+; RV32ZBB-ZBKB-NEXT:    ret
   %or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
   ret i64 %or
 }
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll
index 79d08772e8853..842ef1b215cd1 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll
@@ -6,6 +6,17 @@
 ; RUN: llc -mtriple=riscv64 -global-isel -mattr=+zbkb -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s -check-prefixes=CHECK,RV64ZBB-ZBKB,RV64ZBKB
 
+define signext i32 @andn_i32_from_sub(i32 signext %a, i32 signext %b) nounwind {
+; CHECK-LABEL: andn_i32_from_sub:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    negw a1, a1
+; CHECK-NEXT:    and a0, a1, a0
+; CHECK-NEXT:    ret
+  %neg = sub i32 0, %b
+  %and = and i32 %neg, %a
+  ret i32 %and
+}
+
 define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: andn_i32:
 ; RV64I:       # %bb.0:
@@ -38,6 +49,22 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
   ret i64 %and
 }
 
+define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: andn_i64_from_sub:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    neg a1, a1
+; RV64I-NEXT:    and a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64ZBB-ZBKB-LABEL: andn_i64_from_sub:
+; RV64ZBB-ZBKB:       # %bb.0:
+; RV64ZBB-ZBKB-NEXT:    andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT:    ret
+  %neg = sub i64 0, %b
+  %and = and i64 %neg, %a
+  ret i64 %and
+}
+
 define signext i32 @orn_i32(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: orn_i32:
 ; RV64I:       # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
index b6344f88cddaa..045d0939d0764 100644
--- a/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
@@ -22,6 +22,22 @@ define i32 @andn_i32(i32 %a, i32 %b) nounwind {
   ret i32 %and
 }
 
+define i32 @andn_i32_from_sub(i32 %a, i32 %b) nounwind {
+; RV32I-LABEL: andn_i32_from_sub:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    neg a1, a1
+; RV32I-NEXT:    and a0, a1, a0
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: andn_i32_from_sub:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a1
+; RV32ZBB-ZBKB-NEXT:    ret
+  %neg = sub i32 0, %b
+  %and = and i32 %neg, %a
+  ret i32 %and
+}
+
 define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 ; RV32I-LABEL: andn_i64:
 ; RV32I:       # %bb.0:
@@ -41,6 +57,29 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
   ret i64 %and
 }
 
+define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
+; RV32I-LABEL: andn_i64_from_sub:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    snez a4, a2
+; RV32I-NEXT:    neg a3, a3
+; RV32I-NEXT:    neg a2, a2
+; RV32I-NEXT:    sub a3, a3, a4
+; RV32I-NEXT:    and a0, a2, a0
+; RV32I-NEXT:    and a1, a3, a1
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: andn_i64_from_sub:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    snez a4, a2
+; RV32ZBB-ZBKB-NEXT:    add a3, a3, a4
+; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a2
+; RV32ZBB-ZBKB-NEXT:    andn a1, a1, a3
+; RV32ZBB-ZBKB-NEXT:    ret
+  %neg = sub i64 0, %b
+  %and = and i64 %neg, %a
+  ret i64 %and
+}
+
 define i32 @orn_i32(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: orn_i32:
 ; RV32I:       # %bb.0:
@@ -141,15 +180,15 @@ define i64 @rol_i64(i64 %a, i64 %b) nounwind {
 ; CHECK-NEXT:    slli a5, a2, 26
 ; CHECK-NEXT:    srli a5, a5, 31
 ; CHECK-NEXT:    mv a3, a1
-; CHECK-NEXT:    bnez a5, .LBB7_2
+; CHECK-NEXT:    bnez a5, .LBB9_2
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    mv a3, a0
-; CHECK-NEXT:  .LBB7_2:
+; CHECK-NEXT:  .LBB9_2:
 ; CHECK-NEXT:    sll a4, a3, a2
-; CHECK-NEXT:    bnez a5, .LBB7_4
+; CHECK-NEXT:    bnez a5, .LBB9_4
 ; CHECK-NEXT:  # %bb.3:
 ; CHECK-NEXT:    mv a0, a1
-; CHECK-NEXT:  .LBB7_4:
+; CHECK-NEXT:  .LBB9_4:
 ; CHECK-NEXT:    srli a1, a0, 1
 ; CHECK-NEXT:    not a5, a2
 ; CHECK-NEXT:    sll a2, a0, a2
@@ -192,15 +231,15 @@ define i64 @ror_i64(i64 %a, i64 %b) nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    andi a5, a2, 32
 ; CHECK-NEXT:    mv a3, a0
-; CHECK-NEXT:    beqz a5, .LBB9_2
+; CHECK-NEXT:    beqz a5, .LBB11_2
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    mv a3, a1
-; CHECK-NEXT:  .LBB9_2:
+; CHECK-NEXT:  .LBB11_2:
 ; CHECK-NEXT:    srl a4, a3, a2
-; CHECK-NEXT:    beqz a5, .LBB9_4
+; CHECK-NEXT:    beqz a5, .LBB11_4
 ; CHECK-NEXT:  # %bb.3:
 ; CHECK-NEXT:    mv a1, a0
-; CHECK-NEXT:  .LBB9_4:
+; CHECK-NEXT:  .LBB11_4:
 ; CHECK-NEXT:    slli a0, a1, 1
 ; CHECK-NEXT:    not a5, a2
 ; CHECK-NEXT:    srl a1, a1, a2
@@ -293,19 +332,32 @@ define i32 @not_shl_one_i32(i32 %x) {
 }
 
 define i64 @not_shl_one_i64(i64 %x) {
-; CHECK-LABEL: not_shl_one_i64:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    addi a1, a0, -32
-; CHECK-NEXT:    li a2, 1
-; CHECK-NEXT:    slti a1, a1, 0
-; CHECK-NEXT:    sll a0, a2, a0
-; CHECK-NEXT:    neg a2, a1
-; CHECK-NEXT:    addi a1, a1, -1
-; CHECK-NEXT:    and a2, a2, a0
-; CHECK-NEXT:    and a1, a1, a0
-; CHECK-NEXT:    not a0, a2
-; CHECK-NEXT:    not a1, a1
-; CHECK-NEXT:    ret
+; RV32I-LABEL: not_shl_one_i64:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi a1, a0, -32
+; RV32I-NEXT:    li a2, 1
+; RV32I-NEXT:    slti a1, a1, 0
+; RV32I-NEXT:    sll a0, a2, a0
+; RV32I-NEXT:    neg a2, a1
+; RV32I-NEXT:    addi a1, a1, -1
+; RV32I-NEXT:    and a2, a2, a0
+; RV32I-NEXT:    and a1, a1, a0
+; RV32I-NEXT:    not a0, a2
+; RV32I-NEXT:    not a1, a1
+; RV32I-NEXT:    ret
+;
+; RV32ZBB-ZBKB-LABEL: not_shl_one_i64:
+; RV32ZBB-ZBKB:       # %bb.0:
+; RV32ZBB-ZBKB-NEXT:    li a1, 1
+; RV32ZBB-ZBKB-NEXT:    addi a2, a0, -32
+; RV32ZBB-ZBKB-NEXT:    sll a0, a1, a0
+; RV32ZBB-ZBKB-NEXT:    slti a1, a2, 0
+; RV32ZBB-ZBKB-NEXT:    addi a2, a1, -1
+; RV32ZBB-ZBKB-NEXT:    andn a1, a0, a1
+; RV32ZBB-ZBKB-NEXT:    and a2, a2, a0
+; RV32ZBB-ZBKB-NEXT:    not a0, a1
+; RV32ZBB-ZBKB-NEXT:    not a1, a2
+; RV32ZBB-ZBKB-NEXT:    ret
   %1 = shl i64 1, %x
   %2 = xor i64 %1, -1
   ret i64 %2
diff --git a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
index bf077364c9c7a..b4ed47d9c4fbc 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
@@ -22,6 +22,17 @@ define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {
   ret i32 %and
 }
 
+define signext i32 @andn_i32_from_sub(i32 signext %a, i32 signext %b) nounwind {
+; CHECK-LABEL: andn_i32_from_sub:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    negw a1, a1
+; CHECK-NEXT:    and a0, a1, a0
+; CHECK-NEXT:    ret
+  %neg = sub i32 0, %b
+  %and = and i32 %neg, %a
+  ret i32 %and
+}
+
 define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 ; RV64I-LABEL: andn_i64:
 ; RV64I:       # %bb.0:
@@ -38,6 +49,22 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
   ret i64 %and
 }
 
+define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
+; RV64I-LABEL: andn_i64_from_sub:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    neg a1, a1
+; RV64I-NEXT:    and a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64ZBB-ZBKB-LABEL: andn_i64_from_sub:
+; RV64ZBB-ZBKB:       # %bb.0:
+; RV64ZBB-ZBKB-NEXT:    andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT:    ret
+  %neg = sub i64 0, %b
+  %and = and i64 %neg, %a
+  ret i64 %and
+}
+
 define signext i32 @orn_i32(i32 signext %a, i32 signext %b) nounwind {
 ; RV64I-LABEL: orn_i32:
 ; RV64I:       # %bb.0:

>From 4a6834991bbd00254bb1a7b7e6589eb0d9ad4a09 Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Fri, 28 Feb 2025 16:21:53 +0100
Subject: [PATCH 2/2] It is -1 not 0

---
 llvm/lib/Target/RISCV/RISCVInstrInfoZb.td     |   2 +-
 .../CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll  | 320 ++++++------------
 .../CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll  |  14 +-
 llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll       |  53 +--
 llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll       |  21 +-
 5 files changed, 152 insertions(+), 258 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index 92d126fb8bcf9..75b1f5593cf50 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -483,7 +483,7 @@ def invLogicImm : ComplexPattern<XLenVT, 1, "selectInvLogicImm", [], [], 0>;
 
 let Predicates = [HasStdExtZbbOrZbkb] in {
 def : Pat<(XLenVT (and GPR:$rs1, (not GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
-def : Pat<(XLenVT (and GPR:$rs1, (sub 0, GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
+def : Pat<(XLenVT (and GPR:$rs1, (sub -1, GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
 def : Pat<(XLenVT (or  GPR:$rs1, (not GPR:$rs2))), (ORN  GPR:$rs1, GPR:$rs2)>;
 def : Pat<(XLenVT (xor GPR:$rs1, (not GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
 
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll
index 03a3e4b3ff742..385563864933b 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll
@@ -25,15 +25,16 @@ define i32 @andn_i32(i32 %a, i32 %b) nounwind {
 define i32 @andn_i32_from_sub(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: andn_i32_from_sub:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    neg a1, a1
-; RV32I-NEXT:    and a0, a1, a0
+; RV32I-NEXT:    li a2, -1
+; RV32I-NEXT:    sub a2, a2, a1
+; RV32I-NEXT:    and a0, a2, a0
 ; RV32I-NEXT:    ret
 ;
 ; RV32ZBB-ZBKB-LABEL: andn_i32_from_sub:
 ; RV32ZBB-ZBKB:       # %bb.0:
 ; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a1
 ; RV32ZBB-ZBKB-NEXT:    ret
-  %neg = sub i32 0, %b
+  %neg = sub i32 -1, %b
   %and = and i32 %neg, %a
   ret i32 %and
 }
@@ -60,23 +61,25 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
 ; RV32I-LABEL: andn_i64_from_sub:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    neg a4, a2
-; RV32I-NEXT:    snez a2, a2
-; RV32I-NEXT:    neg a3, a3
-; RV32I-NEXT:    sub a3, a3, a2
-; RV32I-NEXT:    and a0, a4, a0
-; RV32I-NEXT:    and a1, a3, a1
+; RV32I-NEXT:    li a4, -1
+; RV32I-NEXT:    sub a5, a4, a2
+; RV32I-NEXT:    sltu a2, a4, a2
+; RV32I-NEXT:    sub a4, a4, a3
+; RV32I-NEXT:    sub a4, a4, a2
+; RV32I-NEXT:    and a0, a5, a0
+; RV32I-NEXT:    and a1, a4, a1
 ; RV32I-NEXT:    ret
 ;
 ; RV32ZBB-ZBKB-LABEL: andn_i64_from_sub:
 ; RV32ZBB-ZBKB:       # %bb.0:
-; RV32ZBB-ZBKB-NEXT:    snez a4, a2
-; RV32ZBB-ZBKB-NEXT:    neg a3, a3
-; RV32ZBB-ZBKB-NEXT:    sub a3, a3, a4
+; RV32ZBB-ZBKB-NEXT:    li a4, -1
+; RV32ZBB-ZBKB-NEXT:    sltu a5, a4, a2
+; RV32ZBB-ZBKB-NEXT:    sub a4, a4, a3
+; RV32ZBB-ZBKB-NEXT:    sub a4, a4, a5
 ; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a2
-; RV32ZBB-ZBKB-NEXT:    and a1, a3, a1
+; RV32ZBB-ZBKB-NEXT:    and a1, a4, a1
 ; RV32ZBB-ZBKB-NEXT:    ret
-  %neg = sub i64 0, %b
+  %neg = sub i64 -1, %b
   %and = and i64 %neg, %a
   ret i64 %and
 }
@@ -176,102 +179,53 @@ define i32 @rol_i32(i32 %a, i32 %b) nounwind {
 declare i64 @llvm.fshl.i64(i64, i64, i64)
 
 define i64 @rol_i64(i64 %a, i64 %b) nounwind {
-; RV32I-LABEL: rol_i64:
-; RV32I:       # %bb.0:
-; RV32I-NEXT:    andi a6, a2, 63
-; RV32I-NEXT:    li a4, 32
-; RV32I-NEXT:    bltu a6, a4, .LBB9_2
-; RV32I-NEXT:  # %bb.1:
-; RV32I-NEXT:    li a3, 0
-; RV32I-NEXT:    sll a7, a0, a6
-; RV32I-NEXT:    j .LBB9_3
-; RV32I-NEXT:  .LBB9_2:
-; RV32I-NEXT:    sll a3, a0, a2
-; RV32I-NEXT:    neg a5, a6
-; RV32I-NEXT:    srl a5, a0, a5
-; RV32I-NEXT:    sll a7, a1, a2
-; RV32I-NEXT:    or a7, a5, a7
-; RV32I-NEXT:  .LBB9_3:
-; RV32I-NEXT:    neg a5, a2
-; RV32I-NEXT:    mv a2, a1
-; RV32I-NEXT:    beqz a6, .LBB9_5
-; RV32I-NEXT:  # %bb.4:
-; RV32I-NEXT:    mv a2, a7
-; RV32I-NEXT:  .LBB9_5:
-; RV32I-NEXT:    andi a6, a5, 63
-; RV32I-NEXT:    bltu a6, a4, .LBB9_7
-; RV32I-NEXT:  # %bb.6:
-; RV32I-NEXT:    srl a7, a1, a6
-; RV32I-NEXT:    bnez a6, .LBB9_8
-; RV32I-NEXT:    j .LBB9_9
-; RV32I-NEXT:  .LBB9_7:
-; RV32I-NEXT:    srl a7, a0, a5
-; RV32I-NEXT:    neg t0, a6
-; RV32I-NEXT:    sll t0, a1, t0
-; RV32I-NEXT:    or a7, a7, t0
-; RV32I-NEXT:    beqz a6, .LBB9_9
-; RV32I-NEXT:  .LBB9_8:
-; RV32I-NEXT:    mv a0, a7
-; RV32I-NEXT:  .LBB9_9:
-; RV32I-NEXT:    bltu a6, a4, .LBB9_11
-; RV32I-NEXT:  # %bb.10:
-; RV32I-NEXT:    li a1, 0
-; RV32I-NEXT:    j .LBB9_12
-; RV32I-NEXT:  .LBB9_11:
-; RV32I-NEXT:    srl a1, a1, a5
-; RV32I-NEXT:  .LBB9_12:
-; RV32I-NEXT:    or a0, a3, a0
-; RV32I-NEXT:    or a1, a2, a1
-; RV32I-NEXT:    ret
-;
-; RV32ZBB-ZBKB-LABEL: rol_i64:
-; RV32ZBB-ZBKB:       # %bb.0:
-; RV32ZBB-ZBKB-NEXT:    andi a6, a2, 63
-; RV32ZBB-ZBKB-NEXT:    li a4, 32
-; RV32ZBB-ZBKB-NEXT:    bltu a6, a4, .LBB9_2
-; RV32ZBB-ZBKB-NEXT:  # %bb.1:
-; RV32ZBB-ZBKB-NEXT:    li a3, 0
-; RV32ZBB-ZBKB-NEXT:    sll a7, a0, a6
-; RV32ZBB-ZBKB-NEXT:    j .LBB9_3
-; RV32ZBB-ZBKB-NEXT:  .LBB9_2:
-; RV32ZBB-ZBKB-NEXT:    sll a3, a0, a2
-; RV32ZBB-ZBKB-NEXT:    neg a5, a6
-; RV32ZBB-ZBKB-NEXT:    srl a5, a0, a5
-; RV32ZBB-ZBKB-NEXT:    sll a7, a1, a2
-; RV32ZBB-ZBKB-NEXT:    or a7, a5, a7
-; RV32ZBB-ZBKB-NEXT:  .LBB9_3:
-; RV32ZBB-ZBKB-NEXT:    li t0, 63
-; RV32ZBB-ZBKB-NEXT:    mv a5, a1
-; RV32ZBB-ZBKB-NEXT:    beqz a6, .LBB9_5
-; RV32ZBB-ZBKB-NEXT:  # %bb.4:
-; RV32ZBB-ZBKB-NEXT:    mv a5, a7
-; RV32ZBB-ZBKB-NEXT:  .LBB9_5:
-; RV32ZBB-ZBKB-NEXT:    andn a6, t0, a2
-; RV32ZBB-ZBKB-NEXT:    neg a2, a2
-; RV32ZBB-ZBKB-NEXT:    bltu a6, a4, .LBB9_7
-; RV32ZBB-ZBKB-NEXT:  # %bb.6:
-; RV32ZBB-ZBKB-NEXT:    srl a7, a1, a6
-; RV32ZBB-ZBKB-NEXT:    bnez a6, .LBB9_8
-; RV32ZBB-ZBKB-NEXT:    j .LBB9_9
-; RV32ZBB-ZBKB-NEXT:  .LBB9_7:
-; RV32ZBB-ZBKB-NEXT:    srl a7, a0, a2
-; RV32ZBB-ZBKB-NEXT:    neg t0, a6
-; RV32ZBB-ZBKB-NEXT:    sll t0, a1, t0
-; RV32ZBB-ZBKB-NEXT:    or a7, a7, t0
-; RV32ZBB-ZBKB-NEXT:    beqz a6, .LBB9_9
-; RV32ZBB-ZBKB-NEXT:  .LBB9_8:
-; RV32ZBB-ZBKB-NEXT:    mv a0, a7
-; RV32ZBB-ZBKB-NEXT:  .LBB9_9:
-; RV32ZBB-ZBKB-NEXT:    bltu a6, a4, .LBB9_11
-; RV32ZBB-ZBKB-NEXT:  # %bb.10:
-; RV32ZBB-ZBKB-NEXT:    li a1, 0
-; RV32ZBB-ZBKB-NEXT:    j .LBB9_12
-; RV32ZBB-ZBKB-NEXT:  .LBB9_11:
-; RV32ZBB-ZBKB-NEXT:    srl a1, a1, a2
-; RV32ZBB-ZBKB-NEXT:  .LBB9_12:
-; RV32ZBB-ZBKB-NEXT:    or a0, a3, a0
-; RV32ZBB-ZBKB-NEXT:    or a1, a5, a1
-; RV32ZBB-ZBKB-NEXT:    ret
+; CHECK-LABEL: rol_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    andi a6, a2, 63
+; CHECK-NEXT:    li a4, 32
+; CHECK-NEXT:    bltu a6, a4, .LBB9_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    li a3, 0
+; CHECK-NEXT:    sll a7, a0, a6
+; CHECK-NEXT:    j .LBB9_3
+; CHECK-NEXT:  .LBB9_2:
+; CHECK-NEXT:    sll a3, a0, a2
+; CHECK-NEXT:    neg a5, a6
+; CHECK-NEXT:    srl a5, a0, a5
+; CHECK-NEXT:    sll a7, a1, a2
+; CHECK-NEXT:    or a7, a5, a7
+; CHECK-NEXT:  .LBB9_3:
+; CHECK-NEXT:    neg a5, a2
+; CHECK-NEXT:    mv a2, a1
+; CHECK-NEXT:    beqz a6, .LBB9_5
+; CHECK-NEXT:  # %bb.4:
+; CHECK-NEXT:    mv a2, a7
+; CHECK-NEXT:  .LBB9_5:
+; CHECK-NEXT:    andi a6, a5, 63
+; CHECK-NEXT:    bltu a6, a4, .LBB9_7
+; CHECK-NEXT:  # %bb.6:
+; CHECK-NEXT:    srl a7, a1, a6
+; CHECK-NEXT:    bnez a6, .LBB9_8
+; CHECK-NEXT:    j .LBB9_9
+; CHECK-NEXT:  .LBB9_7:
+; CHECK-NEXT:    srl a7, a0, a5
+; CHECK-NEXT:    neg t0, a6
+; CHECK-NEXT:    sll t0, a1, t0
+; CHECK-NEXT:    or a7, a7, t0
+; CHECK-NEXT:    beqz a6, .LBB9_9
+; CHECK-NEXT:  .LBB9_8:
+; CHECK-NEXT:    mv a0, a7
+; CHECK-NEXT:  .LBB9_9:
+; CHECK-NEXT:    bltu a6, a4, .LBB9_11
+; CHECK-NEXT:  # %bb.10:
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    j .LBB9_12
+; CHECK-NEXT:  .LBB9_11:
+; CHECK-NEXT:    srl a1, a1, a5
+; CHECK-NEXT:  .LBB9_12:
+; CHECK-NEXT:    or a0, a3, a0
+; CHECK-NEXT:    or a1, a2, a1
+; CHECK-NEXT:    ret
   %or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
   ret i64 %or
 }
@@ -301,104 +255,54 @@ define i32 @ror_i32(i32 %a, i32 %b) nounwind {
 declare i64 @llvm.fshr.i64(i64, i64, i64)
 
 define i64 @ror_i64(i64 %a, i64 %b) nounwind {
-; RV32I-LABEL: ror_i64:
-; RV32I:       # %bb.0:
-; RV32I-NEXT:    andi a5, a2, 63
-; RV32I-NEXT:    li a4, 32
-; RV32I-NEXT:    bltu a5, a4, .LBB11_2
-; RV32I-NEXT:  # %bb.1:
-; RV32I-NEXT:    srl a6, a1, a5
-; RV32I-NEXT:    mv a3, a0
-; RV32I-NEXT:    bnez a5, .LBB11_3
-; RV32I-NEXT:    j .LBB11_4
-; RV32I-NEXT:  .LBB11_2:
-; RV32I-NEXT:    srl a3, a0, a2
-; RV32I-NEXT:    neg a6, a5
-; RV32I-NEXT:    sll a6, a1, a6
-; RV32I-NEXT:    or a6, a3, a6
-; RV32I-NEXT:    mv a3, a0
-; RV32I-NEXT:    beqz a5, .LBB11_4
-; RV32I-NEXT:  .LBB11_3:
-; RV32I-NEXT:    mv a3, a6
-; RV32I-NEXT:  .LBB11_4:
-; RV32I-NEXT:    neg a6, a2
-; RV32I-NEXT:    bltu a5, a4, .LBB11_7
-; RV32I-NEXT:  # %bb.5:
-; RV32I-NEXT:    li a2, 0
-; RV32I-NEXT:    andi a5, a6, 63
-; RV32I-NEXT:    bgeu a5, a4, .LBB11_8
-; RV32I-NEXT:  .LBB11_6:
-; RV32I-NEXT:    sll a4, a0, a6
-; RV32I-NEXT:    neg a7, a5
-; RV32I-NEXT:    srl a0, a0, a7
-; RV32I-NEXT:    sll a6, a1, a6
-; RV32I-NEXT:    or a0, a0, a6
-; RV32I-NEXT:    bnez a5, .LBB11_9
-; RV32I-NEXT:    j .LBB11_10
-; RV32I-NEXT:  .LBB11_7:
-; RV32I-NEXT:    srl a2, a1, a2
-; RV32I-NEXT:    andi a5, a6, 63
-; RV32I-NEXT:    bltu a5, a4, .LBB11_6
-; RV32I-NEXT:  .LBB11_8:
-; RV32I-NEXT:    li a4, 0
-; RV32I-NEXT:    sll a0, a0, a5
-; RV32I-NEXT:    beqz a5, .LBB11_10
-; RV32I-NEXT:  .LBB11_9:
-; RV32I-NEXT:    mv a1, a0
-; RV32I-NEXT:  .LBB11_10:
-; RV32I-NEXT:    or a0, a3, a4
-; RV32I-NEXT:    or a1, a2, a1
-; RV32I-NEXT:    ret
-;
-; RV32ZBB-ZBKB-LABEL: ror_i64:
-; RV32ZBB-ZBKB:       # %bb.0:
-; RV32ZBB-ZBKB-NEXT:    andi a4, a2, 63
-; RV32ZBB-ZBKB-NEXT:    li a5, 32
-; RV32ZBB-ZBKB-NEXT:    bltu a4, a5, .LBB11_2
-; RV32ZBB-ZBKB-NEXT:  # %bb.1:
-; RV32ZBB-ZBKB-NEXT:    srl a6, a1, a4
-; RV32ZBB-ZBKB-NEXT:    mv a3, a0
-; RV32ZBB-ZBKB-NEXT:    bnez a4, .LBB11_3
-; RV32ZBB-ZBKB-NEXT:    j .LBB11_4
-; RV32ZBB-ZBKB-NEXT:  .LBB11_2:
-; RV32ZBB-ZBKB-NEXT:    srl a3, a0, a2
-; RV32ZBB-ZBKB-NEXT:    neg a6, a4
-; RV32ZBB-ZBKB-NEXT:    sll a6, a1, a6
-; RV32ZBB-ZBKB-NEXT:    or a6, a3, a6
-; RV32ZBB-ZBKB-NEXT:    mv a3, a0
-; RV32ZBB-ZBKB-NEXT:    beqz a4, .LBB11_4
-; RV32ZBB-ZBKB-NEXT:  .LBB11_3:
-; RV32ZBB-ZBKB-NEXT:    mv a3, a6
-; RV32ZBB-ZBKB-NEXT:  .LBB11_4:
-; RV32ZBB-ZBKB-NEXT:    li a6, 63
-; RV32ZBB-ZBKB-NEXT:    bltu a4, a5, .LBB11_7
-; RV32ZBB-ZBKB-NEXT:  # %bb.5:
-; RV32ZBB-ZBKB-NEXT:    li a4, 0
-; RV32ZBB-ZBKB-NEXT:    andn a6, a6, a2
-; RV32ZBB-ZBKB-NEXT:    bgeu a6, a5, .LBB11_8
-; RV32ZBB-ZBKB-NEXT:  .LBB11_6:
-; RV32ZBB-ZBKB-NEXT:    neg a5, a2
-; RV32ZBB-ZBKB-NEXT:    neg a7, a6
-; RV32ZBB-ZBKB-NEXT:    sll a2, a0, a5
-; RV32ZBB-ZBKB-NEXT:    srl a0, a0, a7
-; RV32ZBB-ZBKB-NEXT:    sll a5, a1, a5
-; RV32ZBB-ZBKB-NEXT:    or a0, a0, a5
-; RV32ZBB-ZBKB-NEXT:    bnez a6, .LBB11_9
-; RV32ZBB-ZBKB-NEXT:    j .LBB11_10
-; RV32ZBB-ZBKB-NEXT:  .LBB11_7:
-; RV32ZBB-ZBKB-NEXT:    srl a4, a1, a2
-; RV32ZBB-ZBKB-NEXT:    andn a6, a6, a2
-; RV32ZBB-ZBKB-NEXT:    bltu a6, a5, .LBB11_6
-; RV32ZBB-ZBKB-NEXT:  .LBB11_8:
-; RV32ZBB-ZBKB-NEXT:    li a2, 0
-; RV32ZBB-ZBKB-NEXT:    sll a0, a0, a6
-; RV32ZBB-ZBKB-NEXT:    beqz a6, .LBB11_10
-; RV32ZBB-ZBKB-NEXT:  .LBB11_9:
-; RV32ZBB-ZBKB-NEXT:    mv a1, a0
-; RV32ZBB-ZBKB-NEXT:  .LBB11_10:
-; RV32ZBB-ZBKB-NEXT:    or a0, a3, a2
-; RV32ZBB-ZBKB-NEXT:    or a1, a4, a1
-; RV32ZBB-ZBKB-NEXT:    ret
+; CHECK-LABEL: ror_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    andi a5, a2, 63
+; CHECK-NEXT:    li a4, 32
+; CHECK-NEXT:    bltu a5, a4, .LBB11_2
+; CHECK-NEXT:  # %bb.1:
+; CHECK-NEXT:    srl a6, a1, a5
+; CHECK-NEXT:    mv a3, a0
+; CHECK-NEXT:    bnez a5, .LBB11_3
+; CHECK-NEXT:    j .LBB11_4
+; CHECK-NEXT:  .LBB11_2:
+; CHECK-NEXT:    srl a3, a0, a2
+; CHECK-NEXT:    neg a6, a5
+; CHECK-NEXT:    sll a6, a1, a6
+; CHECK-NEXT:    or a6, a3, a6
+; CHECK-NEXT:    mv a3, a0
+; CHECK-NEXT:    beqz a5, .LBB11_4
+; CHECK-NEXT:  .LBB11_3:
+; CHECK-NEXT:    mv a3, a6
+; CHECK-NEXT:  .LBB11_4:
+; CHECK-NEXT:    neg a6, a2
+; CHECK-NEXT:    bltu a5, a4, .LBB11_7
+; CHECK-NEXT:  # %bb.5:
+; CHECK-NEXT:    li a2, 0
+; CHECK-NEXT:    andi a5, a6, 63
+; CHECK-NEXT:    bgeu a5, a4, .LBB11_8
+; CHECK-NEXT:  .LBB11_6:
+; CHECK-NEXT:    sll a4, a0, a6
+; CHECK-NEXT:    neg a7, a5
+; CHECK-NEXT:    srl a0, a0, a7
+; CHECK-NEXT:    sll a6, a1, a6
+; CHECK-NEXT:    or a0, a0, a6
+; CHECK-NEXT:    bnez a5, .LBB11_9
+; CHECK-NEXT:    j .LBB11_10
+; CHECK-NEXT:  .LBB11_7:
+; CHECK-NEXT:    srl a2, a1, a2
+; CHECK-NEXT:    andi a5, a6, 63
+; CHECK-NEXT:    bltu a5, a4, .LBB11_6
+; CHECK-NEXT:  .LBB11_8:
+; CHECK-NEXT:    li a4, 0
+; CHECK-NEXT:    sll a0, a0, a5
+; CHECK-NEXT:    beqz a5, .LBB11_10
+; CHECK-NEXT:  .LBB11_9:
+; CHECK-NEXT:    mv a1, a0
+; CHECK-NEXT:  .LBB11_10:
+; CHECK-NEXT:    or a0, a3, a4
+; CHECK-NEXT:    or a1, a2, a1
+; CHECK-NEXT:    ret
   %or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
   ret i64 %or
 }
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll
index 842ef1b215cd1..239d17032c07a 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll
@@ -9,10 +9,11 @@
 define signext i32 @andn_i32_from_sub(i32 signext %a, i32 signext %b) nounwind {
 ; CHECK-LABEL: andn_i32_from_sub:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    negw a1, a1
-; CHECK-NEXT:    and a0, a1, a0
+; CHECK-NEXT:    li a2, -1
+; CHECK-NEXT:    subw a2, a2, a1
+; CHECK-NEXT:    and a0, a2, a0
 ; CHECK-NEXT:    ret
-  %neg = sub i32 0, %b
+  %neg = sub i32 -1, %b
   %and = and i32 %neg, %a
   ret i32 %and
 }
@@ -52,15 +53,16 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
 ; RV64I-LABEL: andn_i64_from_sub:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    neg a1, a1
-; RV64I-NEXT:    and a0, a1, a0
+; RV64I-NEXT:    li a2, -1
+; RV64I-NEXT:    sub a2, a2, a1
+; RV64I-NEXT:    and a0, a2, a0
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-ZBKB-LABEL: andn_i64_from_sub:
 ; RV64ZBB-ZBKB:       # %bb.0:
 ; RV64ZBB-ZBKB-NEXT:    andn a0, a0, a1
 ; RV64ZBB-ZBKB-NEXT:    ret
-  %neg = sub i64 0, %b
+  %neg = sub i64 -1, %b
   %and = and i64 %neg, %a
   ret i64 %and
 }
diff --git a/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
index 045d0939d0764..4ea8b1b3f84f5 100644
--- a/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zbb-zbkb.ll
@@ -25,7 +25,7 @@ define i32 @andn_i32(i32 %a, i32 %b) nounwind {
 define i32 @andn_i32_from_sub(i32 %a, i32 %b) nounwind {
 ; RV32I-LABEL: andn_i32_from_sub:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    neg a1, a1
+; RV32I-NEXT:    not a1, a1
 ; RV32I-NEXT:    and a0, a1, a0
 ; RV32I-NEXT:    ret
 ;
@@ -33,7 +33,7 @@ define i32 @andn_i32_from_sub(i32 %a, i32 %b) nounwind {
 ; RV32ZBB-ZBKB:       # %bb.0:
 ; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a1
 ; RV32ZBB-ZBKB-NEXT:    ret
-  %neg = sub i32 0, %b
+  %neg = sub i32 -1, %b
   %and = and i32 %neg, %a
   ret i32 %and
 }
@@ -60,22 +60,18 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
 ; RV32I-LABEL: andn_i64_from_sub:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    snez a4, a2
-; RV32I-NEXT:    neg a3, a3
-; RV32I-NEXT:    neg a2, a2
-; RV32I-NEXT:    sub a3, a3, a4
+; RV32I-NEXT:    not a3, a3
+; RV32I-NEXT:    not a2, a2
 ; RV32I-NEXT:    and a0, a2, a0
 ; RV32I-NEXT:    and a1, a3, a1
 ; RV32I-NEXT:    ret
 ;
 ; RV32ZBB-ZBKB-LABEL: andn_i64_from_sub:
 ; RV32ZBB-ZBKB:       # %bb.0:
-; RV32ZBB-ZBKB-NEXT:    snez a4, a2
-; RV32ZBB-ZBKB-NEXT:    add a3, a3, a4
 ; RV32ZBB-ZBKB-NEXT:    andn a0, a0, a2
 ; RV32ZBB-ZBKB-NEXT:    andn a1, a1, a3
 ; RV32ZBB-ZBKB-NEXT:    ret
-  %neg = sub i64 0, %b
+  %neg = sub i64 -1, %b
   %and = and i64 %neg, %a
   ret i64 %and
 }
@@ -332,32 +328,19 @@ define i32 @not_shl_one_i32(i32 %x) {
 }
 
 define i64 @not_shl_one_i64(i64 %x) {
-; RV32I-LABEL: not_shl_one_i64:
-; RV32I:       # %bb.0:
-; RV32I-NEXT:    addi a1, a0, -32
-; RV32I-NEXT:    li a2, 1
-; RV32I-NEXT:    slti a1, a1, 0
-; RV32I-NEXT:    sll a0, a2, a0
-; RV32I-NEXT:    neg a2, a1
-; RV32I-NEXT:    addi a1, a1, -1
-; RV32I-NEXT:    and a2, a2, a0
-; RV32I-NEXT:    and a1, a1, a0
-; RV32I-NEXT:    not a0, a2
-; RV32I-NEXT:    not a1, a1
-; RV32I-NEXT:    ret
-;
-; RV32ZBB-ZBKB-LABEL: not_shl_one_i64:
-; RV32ZBB-ZBKB:       # %bb.0:
-; RV32ZBB-ZBKB-NEXT:    li a1, 1
-; RV32ZBB-ZBKB-NEXT:    addi a2, a0, -32
-; RV32ZBB-ZBKB-NEXT:    sll a0, a1, a0
-; RV32ZBB-ZBKB-NEXT:    slti a1, a2, 0
-; RV32ZBB-ZBKB-NEXT:    addi a2, a1, -1
-; RV32ZBB-ZBKB-NEXT:    andn a1, a0, a1
-; RV32ZBB-ZBKB-NEXT:    and a2, a2, a0
-; RV32ZBB-ZBKB-NEXT:    not a0, a1
-; RV32ZBB-ZBKB-NEXT:    not a1, a2
-; RV32ZBB-ZBKB-NEXT:    ret
+; CHECK-LABEL: not_shl_one_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi a1, a0, -32
+; CHECK-NEXT:    li a2, 1
+; CHECK-NEXT:    slti a1, a1, 0
+; CHECK-NEXT:    sll a0, a2, a0
+; CHECK-NEXT:    neg a2, a1
+; CHECK-NEXT:    addi a1, a1, -1
+; CHECK-NEXT:    and a2, a2, a0
+; CHECK-NEXT:    and a1, a1, a0
+; CHECK-NEXT:    not a0, a2
+; CHECK-NEXT:    not a1, a1
+; CHECK-NEXT:    ret
   %1 = shl i64 1, %x
   %2 = xor i64 %1, -1
   ret i64 %2
diff --git a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
index b4ed47d9c4fbc..30936c247b233 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll
@@ -23,12 +23,17 @@ define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {
 }
 
 define signext i32 @andn_i32_from_sub(i32 signext %a, i32 signext %b) nounwind {
-; CHECK-LABEL: andn_i32_from_sub:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    negw a1, a1
-; CHECK-NEXT:    and a0, a1, a0
-; CHECK-NEXT:    ret
-  %neg = sub i32 0, %b
+; RV64I-LABEL: andn_i32_from_sub:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    not a1, a1
+; RV64I-NEXT:    and a0, a1, a0
+; RV64I-NEXT:    ret
+;
+; RV64ZBB-ZBKB-LABEL: andn_i32_from_sub:
+; RV64ZBB-ZBKB:       # %bb.0:
+; RV64ZBB-ZBKB-NEXT:    andn a0, a0, a1
+; RV64ZBB-ZBKB-NEXT:    ret
+  %neg = sub i32 -1, %b
   %and = and i32 %neg, %a
   ret i32 %and
 }
@@ -52,7 +57,7 @@ define i64 @andn_i64(i64 %a, i64 %b) nounwind {
 define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
 ; RV64I-LABEL: andn_i64_from_sub:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    neg a1, a1
+; RV64I-NEXT:    not a1, a1
 ; RV64I-NEXT:    and a0, a1, a0
 ; RV64I-NEXT:    ret
 ;
@@ -60,7 +65,7 @@ define i64 @andn_i64_from_sub(i64 %a, i64 %b) nounwind {
 ; RV64ZBB-ZBKB:       # %bb.0:
 ; RV64ZBB-ZBKB-NEXT:    andn a0, a0, a1
 ; RV64ZBB-ZBKB-NEXT:    ret
-  %neg = sub i64 0, %b
+  %neg = sub i64 -1, %b
   %and = and i64 %neg, %a
   ret i64 %and
 }



More information about the llvm-commits mailing list