diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td index 2ce909c5d0e21..75b1f5593cf50 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -483,6 +483,7 @@ def invLogicImm : ComplexPattern; 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 -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 ababec16f7f8f..385563864933b 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb-zbkb.ll @@ -22,6 +22,23 @@ 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: 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 -1, %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 +58,32 @@ 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: 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: 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, a4, a1 +; RV32ZBB-ZBKB-NEXT: ret + %neg = sub i64 -1, %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: @@ -140,46 +183,46 @@ define i64 @rol_i64(i64 %a, i64 %b) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a6, a2, 63 ; CHECK-NEXT: li a4, 32 -; CHECK-NEXT: bltu a6, a4, .LBB7_2 +; 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 .LBB7_3 -; CHECK-NEXT: .LBB7_2: +; 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: .LBB7_3: +; CHECK-NEXT: .LBB9_3: ; CHECK-NEXT: neg a5, a2 ; CHECK-NEXT: mv a2, a1 -; CHECK-NEXT: beqz a6, .LBB7_5 +; CHECK-NEXT: beqz a6, .LBB9_5 ; CHECK-NEXT: # %bb.4: ; CHECK-NEXT: mv a2, a7 -; CHECK-NEXT: .LBB7_5: +; CHECK-NEXT: .LBB9_5: ; CHECK-NEXT: andi a6, a5, 63 -; CHECK-NEXT: bltu a6, a4, .LBB7_7 +; CHECK-NEXT: bltu a6, a4, .LBB9_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: 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, .LBB7_9 -; CHECK-NEXT: .LBB7_8: +; CHECK-NEXT: beqz a6, .LBB9_9 +; CHECK-NEXT: .LBB9_8: ; CHECK-NEXT: mv a0, a7 -; CHECK-NEXT: .LBB7_9: -; CHECK-NEXT: bltu a6, a4, .LBB7_11 +; CHECK-NEXT: .LBB9_9: +; CHECK-NEXT: bltu a6, a4, .LBB9_11 ; CHECK-NEXT: # %bb.10: ; CHECK-NEXT: li a1, 0 -; CHECK-NEXT: j .LBB7_12 -; CHECK-NEXT: .LBB7_11: +; CHECK-NEXT: j .LBB9_12 +; CHECK-NEXT: .LBB9_11: ; CHECK-NEXT: srl a1, a1, a5 -; CHECK-NEXT: .LBB7_12: +; CHECK-NEXT: .LBB9_12: ; CHECK-NEXT: or a0, a3, a0 ; CHECK-NEXT: or a1, a2, a1 ; CHECK-NEXT: ret @@ -216,47 +259,47 @@ define i64 @ror_i64(i64 %a, i64 %b) nounwind { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a5, a2, 63 ; CHECK-NEXT: li a4, 32 -; CHECK-NEXT: bltu a5, a4, .LBB9_2 +; 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, .LBB9_3 -; CHECK-NEXT: j .LBB9_4 -; CHECK-NEXT: .LBB9_2: +; 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, .LBB9_4 -; CHECK-NEXT: .LBB9_3: +; CHECK-NEXT: beqz a5, .LBB11_4 +; CHECK-NEXT: .LBB11_3: ; CHECK-NEXT: mv a3, a6 -; CHECK-NEXT: .LBB9_4: +; CHECK-NEXT: .LBB11_4: ; CHECK-NEXT: neg a6, a2 -; CHECK-NEXT: bltu a5, a4, .LBB9_7 +; 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, .LBB9_8 -; CHECK-NEXT: .LBB9_6: +; 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, .LBB9_9 -; CHECK-NEXT: j .LBB9_10 -; CHECK-NEXT: .LBB9_7: +; 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, .LBB9_6 -; CHECK-NEXT: .LBB9_8: +; 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, .LBB9_10 -; CHECK-NEXT: .LBB9_9: +; CHECK-NEXT: beqz a5, .LBB11_10 +; CHECK-NEXT: .LBB11_9: ; CHECK-NEXT: mv a1, a0 -; CHECK-NEXT: .LBB9_10: +; CHECK-NEXT: .LBB11_10: ; CHECK-NEXT: or a0, a3, a4 ; CHECK-NEXT: or a1, a2, a1 ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll index 79d08772e8853..239d17032c07a 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv64zbb-zbkb.ll @@ -6,6 +6,18 @@ ; 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: li a2, -1 +; CHECK-NEXT: subw a2, a2, a1 +; CHECK-NEXT: and a0, a2, a0 +; CHECK-NEXT: ret + %neg = sub i32 -1, %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 +50,23 @@ 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: 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 -1, %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..4ea8b1b3f84f5 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: not 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 -1, %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,25 @@ 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: 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: andn a0, a0, a2 +; RV32ZBB-ZBKB-NEXT: andn a1, a1, a3 +; RV32ZBB-ZBKB-NEXT: ret + %neg = sub i64 -1, %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 +176,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 +227,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 diff --git a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll index bf077364c9c7a..30936c247b233 100644 --- a/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll +++ b/llvm/test/CodeGen/RISCV/rv64zbb-zbkb.ll @@ -22,6 +22,22 @@ 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 { +; 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 +} + define i64 @andn_i64(i64 %a, i64 %b) nounwind { ; RV64I-LABEL: andn_i64: ; RV64I: # %bb.0: @@ -38,6 +54,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: not 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 -1, %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: