diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1242,6 +1242,7 @@ def and_oneuse : binop_oneuse; def add_oneuse : binop_oneuse; def mul_oneuse : binop_oneuse; +def srl_oneuse : binop_oneuse; def mul_const_oneuse : PatFrag<(ops node:$A, node:$B), (mul node:$A, node:$B), [{ @@ -1367,6 +1368,18 @@ def riscv_setne : ComplexPattern; def riscv_seteq : ComplexPattern; +// 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 (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)>; diff --git a/llvm/test/CodeGen/RISCV/setcc-logic.ll b/llvm/test/CodeGen/RISCV/setcc-logic.ll --- a/llvm/test/CodeGen/RISCV/setcc-logic.ll +++ b/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 +}