[PATCH] D149814: [RISCV] Optimize i32 range checks

Yingwei Zheng via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 3 22:10:18 PDT 2023


dtcxzyw created this revision.
dtcxzyw added a reviewer: craig.topper.
Herald added subscribers: jobnoorman, luke, VincentWu, vkmr, frasercrmck, evandro, luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, simoncook, johnrusso, rbar, asb, hiraditya, arichardson.
Herald added a project: All.
dtcxzyw requested review of this revision.
Herald added subscribers: llvm-commits, pcwang-thead, eopXD, MaskRay.
Herald added a project: LLVM.

This patch improves instruction selection for i32 range check patterns like `INT_MIN <= x && x <= INT_MAX` and its alternatives.
On rv32: GCC: https://godbolt.org/z/1zKjfMqax Alive2: https://alive2.llvm.org/ce/z/FPc4ss
On rv64: GCC: https://godbolt.org/z/ezTsv8cEo Alive2: https://alive2.llvm.org/ce/z/ZkF7Er

I am unsure whether it is suitable to do the pattern match in ISel. I also have an alternative <https://github.com/llvm/llvm-project/compare/main...dtcxzyw:llvm-project:i32-range-check> that does pattern match in `RISCVCodeGenPrepare`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149814

Files:
  llvm/lib/Target/RISCV/RISCVInstrInfo.td
  llvm/test/CodeGen/RISCV/setcc-logic.ll


Index: llvm/test/CodeGen/RISCV/setcc-logic.ll
===================================================================
--- llvm/test/CodeGen/RISCV/setcc-logic.ll
+++ llvm/test/CodeGen/RISCV/setcc-logic.ll
@@ -1322,3 +1322,23 @@
 8:                                                ; preds = %8, %4
   ret void
 }
+
+define i32 @i32_range_check(i64 %0) {
+; RV32I-LABEL: i32_range_check:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    srai a0, a0, 31
+; RV32I-NEXT:    xor a0, a0, a1
+; RV32I-NEXT:    seqz a0, a0
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: i32_range_check:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    sext.w a1, a0
+; RV64I-NEXT:    xor a0, a0, a1
+; RV64I-NEXT:    seqz a0, a0
+; RV64I-NEXT:    ret
+  %2 = add i64 %0, 2147483648
+  %3 = icmp ult i64 %2, 4294967296
+  %4 = zext i1 %3 to i32
+  ret i32 %4
+}
Index: llvm/lib/Target/RISCV/RISCVInstrInfo.td
===================================================================
--- llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1242,6 +1242,7 @@
 def and_oneuse : binop_oneuse<and>;
 def add_oneuse : binop_oneuse<add>;
 def mul_oneuse : binop_oneuse<mul>;
+def srl_oneuse : binop_oneuse<srl>;
 
 def mul_const_oneuse : PatFrag<(ops node:$A, node:$B),
                                (mul node:$A, node:$B), [{
@@ -1367,6 +1368,18 @@
 def riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>;
 def riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>;
 
+// i32 range checks
+let Predicates = [IsRV64] in {
+// Select ADDIW on rv64
+def : Pat<(seteq (srl_oneuse (add_oneuse GPR:$rs1, (i64 2147483648)), (i64 32)), (i64 0)),
+          (SLTIU (XOR $rs1, (ADDIW $rs1, 0)), 1)>;
+}
+let Predicates = [IsRV32] in {
+// Select SRAI on rv32
+def : Pat<(seteq (add_oneuse GPR:$rs1, (binop_oneuse<setult> (add_oneuse GPR:$rs2, (i32 -2147483648)), GPR:$rs2)), (i32 0)),
+          (SLTIU (XOR (SRAI $rs2, 31), $rs1), 1)>;
+}
+
 // Define pattern expansions for setcc operations that aren't directly
 // handled by a RISC-V instruction.
 def : Pat<(riscv_seteq GPR:$rs1), (SLTIU GPR:$rs1, 1)>;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149814.519355.patch
Type: text/x-patch
Size: 2097 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230504/2d58a634/attachment.bin>


More information about the llvm-commits mailing list