From cd1e45ba4e9003c4ef60b48e38d6ee20adc2580b Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Tue, 16 Sep 2025 12:31:33 +0200 Subject: [PATCH 1/2] [RISCV][test] Add (select c, (1 << N) + 1, 0) --- llvm/test/CodeGen/RISCV/rv32zba.ll | 63 ++++++++++++++++++++++++++++++ llvm/test/CodeGen/RISCV/rv64zba.ll | 30 ++++++++++++++ llvm/test/CodeGen/RISCV/xqciac.ll | 22 +++++++++++ 3 files changed, 115 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rv32zba.ll b/llvm/test/CodeGen/RISCV/rv32zba.ll index ab099103b4216..71e16d33db502 100644 --- a/llvm/test/CodeGen/RISCV/rv32zba.ll +++ b/llvm/test/CodeGen/RISCV/rv32zba.ll @@ -1136,3 +1136,66 @@ define i32 @mul_neg8(i32 %a) { %c = mul i32 %a, -8 ret i32 %c } + +define i32 @select3i32(i1 zeroext %x) { +; CHECK-LABEL: select3i32: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 3 +; CHECK-NEXT: ret + %select = select i1 %x, i32 3, i32 0 + ret i32 %select +} + +define i32 @select5i32(i1 zeroext %x) { +; CHECK-LABEL: select5i32: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 5 +; CHECK-NEXT: ret + %select = select i1 %x, i32 5, i32 0 + ret i32 %select +} + +define i32 @select9i32(i1 zeroext %x) { +; CHECK-LABEL: select9i32: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 9 +; CHECK-NEXT: ret + %select = select i1 %x, i32 9, i32 0 + ret i32 %select +} + +define i64 @select3i64(i1 zeroext %x) { +; CHECK-LABEL: select3i64: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 3 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: ret + %select = select i1 %x, i64 3, i64 0 + ret i64 %select +} + +define i64 @select5i64(i1 zeroext %x) { +; CHECK-LABEL: select5i64: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 5 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: ret + %select = select i1 %x, i64 5, i64 0 + ret i64 %select +} + +define i64 @select9i64(i1 zeroext %x) { +; CHECK-LABEL: select9i64: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 9 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: ret + %select = select i1 %x, i64 9, i64 0 + ret i64 %select +} diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index b46f7cc440b7a..54c8cd77326d9 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -4576,3 +4576,33 @@ define i64 @append_32ones(i64 %x) { %o = or i64 %s, 4294967295 ret i64 %o } + +define i32 @select3(i1 zeroext %x) { +; CHECK-LABEL: select3: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 3 +; CHECK-NEXT: ret + %select = select i1 %x, i32 3, i32 0 + ret i32 %select +} + +define i32 @select5(i1 zeroext %x) { +; CHECK-LABEL: select5: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 5 +; CHECK-NEXT: ret + %select = select i1 %x, i32 5, i32 0 + ret i32 %select +} + +define i32 @select9(i1 zeroext %x) { +; CHECK-LABEL: select9: +; CHECK: # %bb.0: +; CHECK-NEXT: neg a0, a0 +; CHECK-NEXT: andi a0, a0, 9 +; CHECK-NEXT: ret + %select = select i1 %x, i32 9, i32 0 + ret i32 %select +} diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll index ec83fd7a28f32..e75f18d27f6e2 100644 --- a/llvm/test/CodeGen/RISCV/xqciac.ll +++ b/llvm/test/CodeGen/RISCV/xqciac.ll @@ -599,3 +599,25 @@ define i32 @add_shl_moreOneUse_4(i32 %x) { %add = add i32 %mul, %or ret i32 %add } + +define i32 @select65(i1 zeroext %x) { +; RV32IM-LABEL: select65: +; RV32IM: # %bb.0: +; RV32IM-NEXT: neg a0, a0 +; RV32IM-NEXT: andi a0, a0, 65 +; RV32IM-NEXT: ret +; +; RV32IMXQCIAC-LABEL: select65: +; RV32IMXQCIAC: # %bb.0: +; RV32IMXQCIAC-NEXT: neg a0, a0 +; RV32IMXQCIAC-NEXT: andi a0, a0, 65 +; RV32IMXQCIAC-NEXT: ret +; +; RV32IZBAMXQCIAC-LABEL: select65: +; RV32IZBAMXQCIAC: # %bb.0: +; RV32IZBAMXQCIAC-NEXT: neg a0, a0 +; RV32IZBAMXQCIAC-NEXT: andi a0, a0, 65 +; RV32IZBAMXQCIAC-NEXT: ret + %select = select i1 %x, i32 65, i32 0 + ret i32 %select +} From 6a62335227d0d8de90979503ef3aea522a0e1fcc Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Tue, 16 Sep 2025 12:32:09 +0200 Subject: [PATCH 2/2] [RISCV] Lower (select c, (1 << N) + 1, 0) -> (c << N) + c --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 20 ++- llvm/test/CodeGen/RISCV/rv32zba.ll | 132 +++++++++++++++----- llvm/test/CodeGen/RISCV/rv64zba.ll | 60 ++++++--- llvm/test/CodeGen/RISCV/xqciac.ll | 6 +- 4 files changed, 162 insertions(+), 56 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 9d90eb0a65218..cb20959e9dcc8 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -9150,10 +9150,22 @@ static SDValue lowerSelectToBinOp(SDNode *N, SelectionDAG &DAG, DAG.getNode(ISD::ADD, DL, VT, CondV, DAG.getAllOnesConstant(DL, VT)); return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(FalseV)); } - // (select c, y, 0) -> -c & y - if (isNullConstant(FalseV) && (!HasCZero || isSimm12Constant(TrueV))) { - SDValue Neg = DAG.getNegative(CondV, DL, VT); - return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV)); + if (isNullConstant(FalseV)) { + // (select c, (1 << ShAmount) + 1, 0) -> (c << ShAmount) + c + if (auto *TrueC = dyn_cast(TrueV)) { + uint64_t TrueM1 = TrueC->getZExtValue() - 1; + if (isPowerOf2_64(TrueM1)) { + unsigned ShAmount = Log2_64(TrueM1); + if (Subtarget.hasShlAdd(ShAmount)) + return DAG.getNode(RISCVISD::SHL_ADD, DL, VT, CondV, + DAG.getConstant(ShAmount, DL, VT), CondV); + } + } + // (select c, y, 0) -> -c & y + if (!HasCZero || isSimm12Constant(TrueV)) { + SDValue Neg = DAG.getNegative(CondV, DL, VT); + return DAG.getNode(ISD::AND, DL, VT, Neg, DAG.getFreeze(TrueV)); + } } } diff --git a/llvm/test/CodeGen/RISCV/rv32zba.ll b/llvm/test/CodeGen/RISCV/rv32zba.ll index 71e16d33db502..0d490682d1ff3 100644 --- a/llvm/test/CodeGen/RISCV/rv32zba.ll +++ b/llvm/test/CodeGen/RISCV/rv32zba.ll @@ -1138,64 +1138,130 @@ define i32 @mul_neg8(i32 %a) { } define i32 @select3i32(i1 zeroext %x) { -; CHECK-LABEL: select3i32: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 3 -; CHECK-NEXT: ret +; RV32I-LABEL: select3i32: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 3 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select3i32: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh1add a0, a0, a0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select3i32: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV32XANDESPERF-NEXT: ret %select = select i1 %x, i32 3, i32 0 ret i32 %select } define i32 @select5i32(i1 zeroext %x) { -; CHECK-LABEL: select5i32: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 5 -; CHECK-NEXT: ret +; RV32I-LABEL: select5i32: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 5 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select5i32: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh2add a0, a0, a0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select5i32: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.w a0, a0, a0 +; RV32XANDESPERF-NEXT: ret %select = select i1 %x, i32 5, i32 0 ret i32 %select } define i32 @select9i32(i1 zeroext %x) { -; CHECK-LABEL: select9i32: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 9 -; CHECK-NEXT: ret +; RV32I-LABEL: select9i32: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 9 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select9i32: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh3add a0, a0, a0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select9i32: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV32XANDESPERF-NEXT: ret %select = select i1 %x, i32 9, i32 0 ret i32 %select } define i64 @select3i64(i1 zeroext %x) { -; CHECK-LABEL: select3i64: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 3 -; CHECK-NEXT: li a1, 0 -; CHECK-NEXT: ret +; RV32I-LABEL: select3i64: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 3 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select3i64: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh1add a0, a0, a0 +; RV32ZBA-NEXT: li a1, 0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select3i64: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV32XANDESPERF-NEXT: li a1, 0 +; RV32XANDESPERF-NEXT: ret %select = select i1 %x, i64 3, i64 0 ret i64 %select } define i64 @select5i64(i1 zeroext %x) { -; CHECK-LABEL: select5i64: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 5 -; CHECK-NEXT: li a1, 0 -; CHECK-NEXT: ret +; RV32I-LABEL: select5i64: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 5 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select5i64: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh2add a0, a0, a0 +; RV32ZBA-NEXT: li a1, 0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select5i64: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.w a0, a0, a0 +; RV32XANDESPERF-NEXT: li a1, 0 +; RV32XANDESPERF-NEXT: ret %select = select i1 %x, i64 5, i64 0 ret i64 %select } define i64 @select9i64(i1 zeroext %x) { -; CHECK-LABEL: select9i64: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 9 -; CHECK-NEXT: li a1, 0 -; CHECK-NEXT: ret +; RV32I-LABEL: select9i64: +; RV32I: # %bb.0: +; RV32I-NEXT: neg a0, a0 +; RV32I-NEXT: andi a0, a0, 9 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; +; RV32ZBA-LABEL: select9i64: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: sh3add a0, a0, a0 +; RV32ZBA-NEXT: li a1, 0 +; RV32ZBA-NEXT: ret +; +; RV32XANDESPERF-LABEL: select9i64: +; RV32XANDESPERF: # %bb.0: +; RV32XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV32XANDESPERF-NEXT: li a1, 0 +; RV32XANDESPERF-NEXT: ret %select = select i1 %x, i64 9, i64 0 ret i64 %select } diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index 54c8cd77326d9..95f9f7116fe68 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -4578,31 +4578,61 @@ define i64 @append_32ones(i64 %x) { } define i32 @select3(i1 zeroext %x) { -; CHECK-LABEL: select3: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 3 -; CHECK-NEXT: ret +; RV64I-LABEL: select3: +; RV64I: # %bb.0: +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: andi a0, a0, 3 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: select3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: select3: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV64XANDESPERF-NEXT: ret %select = select i1 %x, i32 3, i32 0 ret i32 %select } define i32 @select5(i1 zeroext %x) { -; CHECK-LABEL: select5: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 5 -; CHECK-NEXT: ret +; RV64I-LABEL: select5: +; RV64I: # %bb.0: +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: andi a0, a0, 5 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: select5: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh2add a0, a0, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: select5: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: nds.lea.w a0, a0, a0 +; RV64XANDESPERF-NEXT: ret %select = select i1 %x, i32 5, i32 0 ret i32 %select } define i32 @select9(i1 zeroext %x) { -; CHECK-LABEL: select9: -; CHECK: # %bb.0: -; CHECK-NEXT: neg a0, a0 -; CHECK-NEXT: andi a0, a0, 9 -; CHECK-NEXT: ret +; RV64I-LABEL: select9: +; RV64I: # %bb.0: +; RV64I-NEXT: neg a0, a0 +; RV64I-NEXT: andi a0, a0, 9 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: select9: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: select9: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV64XANDESPERF-NEXT: ret %select = select i1 %x, i32 9, i32 0 ret i32 %select } diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll index e75f18d27f6e2..918468bdf03d3 100644 --- a/llvm/test/CodeGen/RISCV/xqciac.ll +++ b/llvm/test/CodeGen/RISCV/xqciac.ll @@ -609,14 +609,12 @@ define i32 @select65(i1 zeroext %x) { ; ; RV32IMXQCIAC-LABEL: select65: ; RV32IMXQCIAC: # %bb.0: -; RV32IMXQCIAC-NEXT: neg a0, a0 -; RV32IMXQCIAC-NEXT: andi a0, a0, 65 +; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a0, 6 ; RV32IMXQCIAC-NEXT: ret ; ; RV32IZBAMXQCIAC-LABEL: select65: ; RV32IZBAMXQCIAC: # %bb.0: -; RV32IZBAMXQCIAC-NEXT: neg a0, a0 -; RV32IZBAMXQCIAC-NEXT: andi a0, a0, 65 +; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a0, 6 ; RV32IZBAMXQCIAC-NEXT: ret %select = select i1 %x, i32 65, i32 0 ret i32 %select