[llvm] [RISCV][P-ext] Recognize (select (X >u ((1 << C) - 1), sext(X >s -1), trunc(X)) as usati (PR #190810)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 7 12:28:24 PDT 2026
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/190810
>From 5b968ed0da64f7ec8023832b3078f96f4641d7a2 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 7 Apr 2026 08:38:33 -0700
Subject: [PATCH 1/3] Pre-commit tests
---
llvm/test/CodeGen/RISCV/rv32p.ll | 132 +++++++++++++
llvm/test/CodeGen/RISCV/rv64p.ll | 312 +++++++++++++++++++++++++++++++
2 files changed, 444 insertions(+)
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index 99bd1f7fd31e2..0e510efac0776 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -1795,3 +1795,135 @@ entry:
%3 = or i32 %1, %2
ret i32 %3
}
+
+; Test USATI select patterns.
+define i4 @usati_i4_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i4_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 15
+; CHECK-NEXT: bgeu a1, a0, .LBB143_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB143_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 15
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i4
+ %trunc = trunc i32 %x to i4
+ %sel = select i1 %cmp1, i4 %cmp2.ext, i4 %trunc
+ ret i4 %sel
+}
+
+define i8 @usati_i8_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i8_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 255
+; CHECK-NEXT: bgeu a1, a0, .LBB144_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB144_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 255
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i8
+ %trunc = trunc i32 %x to i8
+ %sel = select i1 %cmp1, i8 %cmp2.ext, i8 %trunc
+ ret i8 %sel
+}
+
+define i12 @usati_i12_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i12_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 12
+; CHECK-NEXT: beqz a1, .LBB145_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB145_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 4095
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i12
+ %trunc = trunc i32 %x to i12
+ %sel = select i1 %cmp1, i12 %cmp2.ext, i12 %trunc
+ ret i12 %sel
+}
+
+define i16 @usati_i16_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i16_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 16
+; CHECK-NEXT: beqz a1, .LBB146_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB146_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 65535
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i16
+ %trunc = trunc i32 %x to i16
+ %sel = select i1 %cmp1, i16 %cmp2.ext, i16 %trunc
+ ret i16 %sel
+}
+
+define i24 @usati_i24_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i24_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 24
+; CHECK-NEXT: beqz a1, .LBB147_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB147_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 16777215
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i24
+ %trunc = trunc i32 %x to i24
+ %sel = select i1 %cmp1, i24 %cmp2.ext, i24 %trunc
+ ret i24 %sel
+}
+
+; Test USATI with non-XLen source types (now supported by looking through truncates)
+define i4 @usati_i4_from_i8(i8 %x) {
+; CHECK-LABEL: usati_i4_from_i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: zext.b a1, a0
+; CHECK-NEXT: li a2, 15
+; CHECK-NEXT: bgeu a2, a1, .LBB148_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a0, a0, 24
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB148_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i8 %x, 15
+ %cmp2 = icmp sgt i8 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i4
+ %trunc = trunc i8 %x to i4
+ %sel = select i1 %cmp1, i4 %cmp2.ext, i4 %trunc
+ ret i4 %sel
+}
+
+define i8 @usati_i8_from_i16(i16 %x) {
+; CHECK-LABEL: usati_i8_from_i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: zext.h a1, a0
+; CHECK-NEXT: li a2, 255
+; CHECK-NEXT: bgeu a2, a1, .LBB149_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: srli a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB149_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i16 %x, 255
+ %cmp2 = icmp sgt i16 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i8
+ %trunc = trunc i16 %x to i8
+ %sel = select i1 %cmp1, i8 %cmp2.ext, i8 %trunc
+ ret i8 %sel
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index a05e454a1b5dd..468f6deb85c39 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -1032,6 +1032,318 @@ entry:
ret i64 %3
}
+; Test USATI select patterns
+define i3 @usati_i3_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i3_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 7
+; CHECK-NEXT: bgeu a1, a0, .LBB87_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB87_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 7
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i3
+ %trunc = trunc i64 %x to i3
+ %sel = select i1 %cmp1, i3 %cmp2.ext, i3 %trunc
+ ret i3 %sel
+}
+
+define i5 @usati_i5_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i5_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 31
+; CHECK-NEXT: bgeu a1, a0, .LBB88_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB88_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 31
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i5
+ %trunc = trunc i64 %x to i5
+ %sel = select i1 %cmp1, i5 %cmp2.ext, i5 %trunc
+ ret i5 %sel
+}
+
+define i7 @usati_i7_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i7_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 127
+; CHECK-NEXT: bgeu a1, a0, .LBB89_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB89_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 127
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i7
+ %trunc = trunc i64 %x to i7
+ %sel = select i1 %cmp1, i7 %cmp2.ext, i7 %trunc
+ ret i7 %sel
+}
+
+define i8 @usati_i8_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i8_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 255
+; CHECK-NEXT: bgeu a1, a0, .LBB90_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB90_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 255
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i8
+ %trunc = trunc i64 %x to i8
+ %sel = select i1 %cmp1, i8 %cmp2.ext, i8 %trunc
+ ret i8 %sel
+}
+
+define i10 @usati_i10_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i10_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: li a1, 1023
+; CHECK-NEXT: bgeu a1, a0, .LBB91_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB91_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 1023
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i10
+ %trunc = trunc i64 %x to i10
+ %sel = select i1 %cmp1, i10 %cmp2.ext, i10 %trunc
+ ret i10 %sel
+}
+
+define i16 @usati_i16_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i16_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 16
+; CHECK-NEXT: beqz a1, .LBB92_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB92_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 65535
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i16
+ %trunc = trunc i64 %x to i16
+ %sel = select i1 %cmp1, i16 %cmp2.ext, i16 %trunc
+ ret i16 %sel
+}
+
+define i20 @usati_i20_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i20_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 20
+; CHECK-NEXT: beqz a1, .LBB93_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB93_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 1048575
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i20
+ %trunc = trunc i64 %x to i20
+ %sel = select i1 %cmp1, i20 %cmp2.ext, i20 %trunc
+ ret i20 %sel
+}
+
+define i32 @usati_i32_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i32_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 32
+; CHECK-NEXT: beqz a1, .LBB94_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB94_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 4294967295
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i32
+ %trunc = trunc i64 %x to i32
+ %sel = select i1 %cmp1, i32 %cmp2.ext, i32 %trunc
+ ret i32 %sel
+}
+
+define i40 @usati_i40_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i40_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 40
+; CHECK-NEXT: beqz a1, .LBB95_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB95_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 1099511627775
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i40
+ %trunc = trunc i64 %x to i40
+ %sel = select i1 %cmp1, i40 %cmp2.ext, i40 %trunc
+ ret i40 %sel
+}
+
+define i48 @usati_i48_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i48_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 48
+; CHECK-NEXT: beqz a1, .LBB96_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB96_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 281474976710655
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i48
+ %trunc = trunc i64 %x to i48
+ %sel = select i1 %cmp1, i48 %cmp2.ext, i48 %trunc
+ ret i48 %sel
+}
+
+define i56 @usati_i56_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i56_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a1, a0, 56
+; CHECK-NEXT: beqz a1, .LBB97_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB97_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 72057594037927935
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i56
+ %trunc = trunc i64 %x to i56
+ %sel = select i1 %cmp1, i56 %cmp2.ext, i56 %trunc
+ ret i56 %sel
+}
+
+define i63 @usati_i63_from_i64(i64 %x) {
+; CHECK-LABEL: usati_i63_from_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: bgez a0, .LBB98_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB98_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i64 %x, 9223372036854775807
+ %cmp2 = icmp sgt i64 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i63
+ %trunc = trunc i64 %x to i63
+ %sel = select i1 %cmp1, i63 %cmp2.ext, i63 %trunc
+ ret i63 %sel
+}
+
+; Test USATI with non-XLen source types (now supported by looking through truncates)
+define i8 @usati_i8_from_i16(i16 %x) {
+; CHECK-LABEL: usati_i8_from_i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: zext.h a1, a0
+; CHECK-NEXT: li a2, 255
+; CHECK-NEXT: bgeu a2, a1, .LBB99_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a0, a0, 48
+; CHECK-NEXT: srli a0, a0, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB99_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i16 %x, 255
+ %cmp2 = icmp sgt i16 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i8
+ %trunc = trunc i16 %x to i8
+ %sel = select i1 %cmp1, i8 %cmp2.ext, i8 %trunc
+ ret i8 %sel
+}
+
+define i8 @usati_i8_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i8_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: sext.w a1, a0
+; CHECK-NEXT: li a2, 255
+; CHECK-NEXT: bgeu a2, a1, .LBB100_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srliw a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB100_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 255
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i8
+ %trunc = trunc i32 %x to i8
+ %sel = select i1 %cmp1, i8 %cmp2.ext, i8 %trunc
+ ret i8 %sel
+}
+
+define i16 @usati_i16_from_i32(i32 %x) {
+; CHECK-LABEL: usati_i16_from_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srliw a1, a0, 16
+; CHECK-NEXT: beqz a1, .LBB101_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srliw a0, a0, 31
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB101_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i32 %x, 65535
+ %cmp2 = icmp sgt i32 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i16
+ %trunc = trunc i32 %x to i16
+ %sel = select i1 %cmp1, i16 %cmp2.ext, i16 %trunc
+ ret i16 %sel
+}
+
+define i16 @usati_i16_from_i48(i48 %x) {
+; CHECK-LABEL: usati_i16_from_i48:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slli a1, a0, 16
+; CHECK-NEXT: srli a2, a1, 32
+; CHECK-NEXT: beqz a2, .LBB102_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a1, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB102_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i48 %x, 65535
+ %cmp2 = icmp sgt i48 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i16
+ %trunc = trunc i48 %x to i16
+ %sel = select i1 %cmp1, i16 %cmp2.ext, i16 %trunc
+ ret i16 %sel
+}
+
+define i32 @usati_i32_from_i48(i48 %x) {
+; CHECK-LABEL: usati_i32_from_i48:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slli a1, a0, 16
+; CHECK-NEXT: srli a2, a1, 48
+; CHECK-NEXT: beqz a2, .LBB103_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: srli a0, a1, 63
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: .LBB103_2:
+; CHECK-NEXT: ret
+ %cmp1 = icmp ugt i48 %x, 4294967295
+ %cmp2 = icmp sgt i48 %x, -1
+ %cmp2.ext = sext i1 %cmp2 to i32
+ %trunc = trunc i48 %x to i32
+ %sel = select i1 %cmp1, i32 %cmp2.ext, i32 %trunc
+ ret i32 %sel
+}
+
define i64 @macc_w00(i64 %rd, i32 %a, i32 %b) nounwind {
; CHECK-LABEL: macc_w00:
; CHECK: # %bb.0:
>From 887a4afa8609423850e06bc963d29fc92037988d Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 7 Apr 2026 08:55:46 -0700
Subject: [PATCH 2/3] [RISCV][P-ext] Recognize (select (X >u ((1 << C) - 1),
sext(X >s -1), trunc(src)) as usati.
Where the result is a type with C bits. The unsigned compare on the
select treats negative values as large positive values so any value
that isn't in the range [0, (1 << C) - 1] will use the True operand
of the select. The sext(X >s -1) creates all ones for positive values
of X and 0 for negative values of X.
This pattern appears in the picojpeg workload of embench-iot with
an i8 result type.
Assisted-by: Claude Sonnet 4.5
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 66 ++++++++++
llvm/test/CodeGen/RISCV/rv32p.ll | 55 ++-------
llvm/test/CodeGen/RISCV/rv64p.ll | 130 ++++----------------
3 files changed, 99 insertions(+), 152 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f8200826883ef..6196e3ac1826a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20280,11 +20280,77 @@ static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
return DAG.getNode(ISD::ADD, DL, VT, A, NewB);
}
+// Fold (iC (select (src >u ((1 << C) - 1)), sext(src >s -1), trunc(src))) to
+// USATI. This pattern saturates a signed value to an unsigned N-bit range
+// [0, 2^N-1]:
+// - If src < 0: result = 0
+// (via the inner comparison src > -1 = false, sext to 0)
+// - If src > ((1 << C) - 1): result = all 1s
+// (via sext(true) = -1 = 0xFF...)
+// - Otherwise: result = src (via trunc(src))
+// The outer comparison is unsigned, so negative values appear as large
+// unsigned values and trigger the saturation to MaxVal path, where the
+// inner signed comparison then produces 0.
+// TODO: Support (select (src <=u ((1 << C) - 1)), trunc(src), sext(src >s -1)).
+static SDValue foldSelectToUSATI(SDNode *N, SelectionDAG &DAG,
+ const RISCVSubtarget &Subtarget) {
+ if (!Subtarget.hasStdExtP())
+ return SDValue();
+
+ EVT VT = N->getValueType(0);
+ MVT XLenVT = Subtarget.getXLenVT();
+
+ // Only support scalar integer types smaller than XLenVT
+ if (!VT.isScalarInteger() || VT.bitsGE(XLenVT))
+ return SDValue();
+
+ unsigned SatWidth = VT.getSizeInBits();
+ uint64_t MaxVal = (1ULL << SatWidth) - 1;
+
+ using namespace SDPatternMatch;
+
+ SDValue Src, InnerSetCC, FalseSrc;
+ if (!sd_match(N, m_Select(m_SetCC(m_Value(Src), m_SpecificInt(MaxVal),
+ m_SpecificCondCode(ISD::SETUGT)),
+ m_SExt(m_Value(InnerSetCC)),
+ m_Trunc(m_Value(FalseSrc)))))
+ return SDValue();
+
+ // Src can't be larger than XLenVT.
+ if (Src.getValueType().bitsGT(XLenVT))
+ return SDValue();
+
+ // Check inner setcc: src > -1 (signed comparison)
+ if (InnerSetCC.getValueType() != MVT::i1 ||
+ !sd_match(InnerSetCC, m_SetCC(m_Specific(Src), m_AllOnes(),
+ m_SpecificCondCode(ISD::SETGT))))
+ return SDValue();
+
+ // FalseSrc may have been optimized from a truncate of a truncate. There may
+ // still be a truncate on Src. Look through it so we can compare them.
+ SDValue CmpSrc = Src;
+ if (CmpSrc.getOpcode() == ISD::TRUNCATE)
+ CmpSrc = CmpSrc.getOperand(0);
+
+ if (CmpSrc != FalseSrc)
+ return SDValue();
+
+ // We found a USATI pattern.
+ SDLoc DL(N);
+ Src = DAG.getNode(ISD::SIGN_EXTEND, DL, XLenVT, Src);
+ SDValue USATI = DAG.getNode(RISCVISD::USATI, DL, XLenVT, Src,
+ DAG.getTargetConstant(SatWidth, DL, XLenVT));
+ return DAG.getNode(ISD::TRUNCATE, DL, VT, USATI);
+}
+
static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
if (SDValue Folded = foldSelectOfCTTZOrCTLZ(N, DAG))
return Folded;
+ if (SDValue V = foldSelectToUSATI(N, DAG, Subtarget))
+ return V;
+
if (SDValue V = useInversedSetcc(N, DAG, Subtarget))
return V;
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index 0e510efac0776..284e6a75b7be5 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -1800,12 +1800,7 @@ entry:
define i4 @usati_i4_from_i32(i32 %x) {
; CHECK-LABEL: usati_i4_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 15
-; CHECK-NEXT: bgeu a1, a0, .LBB143_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB143_2:
+; CHECK-NEXT: usati a0, a0, 4
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 15
%cmp2 = icmp sgt i32 %x, -1
@@ -1818,12 +1813,7 @@ define i4 @usati_i4_from_i32(i32 %x) {
define i8 @usati_i8_from_i32(i32 %x) {
; CHECK-LABEL: usati_i8_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 255
-; CHECK-NEXT: bgeu a1, a0, .LBB144_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB144_2:
+; CHECK-NEXT: usati a0, a0, 8
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 255
%cmp2 = icmp sgt i32 %x, -1
@@ -1836,12 +1826,7 @@ define i8 @usati_i8_from_i32(i32 %x) {
define i12 @usati_i12_from_i32(i32 %x) {
; CHECK-LABEL: usati_i12_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 12
-; CHECK-NEXT: beqz a1, .LBB145_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB145_2:
+; CHECK-NEXT: usati a0, a0, 12
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 4095
%cmp2 = icmp sgt i32 %x, -1
@@ -1854,12 +1839,7 @@ define i12 @usati_i12_from_i32(i32 %x) {
define i16 @usati_i16_from_i32(i32 %x) {
; CHECK-LABEL: usati_i16_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 16
-; CHECK-NEXT: beqz a1, .LBB146_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB146_2:
+; CHECK-NEXT: usati a0, a0, 16
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 65535
%cmp2 = icmp sgt i32 %x, -1
@@ -1872,12 +1852,7 @@ define i16 @usati_i16_from_i32(i32 %x) {
define i24 @usati_i24_from_i32(i32 %x) {
; CHECK-LABEL: usati_i24_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 24
-; CHECK-NEXT: beqz a1, .LBB147_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB147_2:
+; CHECK-NEXT: usati a0, a0, 24
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 16777215
%cmp2 = icmp sgt i32 %x, -1
@@ -1891,14 +1866,8 @@ define i24 @usati_i24_from_i32(i32 %x) {
define i4 @usati_i4_from_i8(i8 %x) {
; CHECK-LABEL: usati_i4_from_i8:
; CHECK: # %bb.0:
-; CHECK-NEXT: zext.b a1, a0
-; CHECK-NEXT: li a2, 15
-; CHECK-NEXT: bgeu a2, a1, .LBB148_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: slli a0, a0, 24
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB148_2:
+; CHECK-NEXT: sext.b a0, a0
+; CHECK-NEXT: usati a0, a0, 4
; CHECK-NEXT: ret
%cmp1 = icmp ugt i8 %x, 15
%cmp2 = icmp sgt i8 %x, -1
@@ -1911,14 +1880,8 @@ define i4 @usati_i4_from_i8(i8 %x) {
define i8 @usati_i8_from_i16(i16 %x) {
; CHECK-LABEL: usati_i8_from_i16:
; CHECK: # %bb.0:
-; CHECK-NEXT: zext.h a1, a0
-; CHECK-NEXT: li a2, 255
-; CHECK-NEXT: bgeu a2, a1, .LBB149_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: slli a0, a0, 16
-; CHECK-NEXT: srli a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB149_2:
+; CHECK-NEXT: sext.h a0, a0
+; CHECK-NEXT: usati a0, a0, 8
; CHECK-NEXT: ret
%cmp1 = icmp ugt i16 %x, 255
%cmp2 = icmp sgt i16 %x, -1
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index 468f6deb85c39..0635aaed63117 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -1036,12 +1036,7 @@ entry:
define i3 @usati_i3_from_i64(i64 %x) {
; CHECK-LABEL: usati_i3_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 7
-; CHECK-NEXT: bgeu a1, a0, .LBB87_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB87_2:
+; CHECK-NEXT: usati a0, a0, 3
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 7
%cmp2 = icmp sgt i64 %x, -1
@@ -1054,12 +1049,7 @@ define i3 @usati_i3_from_i64(i64 %x) {
define i5 @usati_i5_from_i64(i64 %x) {
; CHECK-LABEL: usati_i5_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 31
-; CHECK-NEXT: bgeu a1, a0, .LBB88_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB88_2:
+; CHECK-NEXT: usati a0, a0, 5
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 31
%cmp2 = icmp sgt i64 %x, -1
@@ -1072,12 +1062,7 @@ define i5 @usati_i5_from_i64(i64 %x) {
define i7 @usati_i7_from_i64(i64 %x) {
; CHECK-LABEL: usati_i7_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 127
-; CHECK-NEXT: bgeu a1, a0, .LBB89_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB89_2:
+; CHECK-NEXT: usati a0, a0, 7
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 127
%cmp2 = icmp sgt i64 %x, -1
@@ -1090,12 +1075,7 @@ define i7 @usati_i7_from_i64(i64 %x) {
define i8 @usati_i8_from_i64(i64 %x) {
; CHECK-LABEL: usati_i8_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 255
-; CHECK-NEXT: bgeu a1, a0, .LBB90_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB90_2:
+; CHECK-NEXT: usati a0, a0, 8
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 255
%cmp2 = icmp sgt i64 %x, -1
@@ -1108,12 +1088,7 @@ define i8 @usati_i8_from_i64(i64 %x) {
define i10 @usati_i10_from_i64(i64 %x) {
; CHECK-LABEL: usati_i10_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 1023
-; CHECK-NEXT: bgeu a1, a0, .LBB91_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB91_2:
+; CHECK-NEXT: usati a0, a0, 10
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 1023
%cmp2 = icmp sgt i64 %x, -1
@@ -1126,12 +1101,7 @@ define i10 @usati_i10_from_i64(i64 %x) {
define i16 @usati_i16_from_i64(i64 %x) {
; CHECK-LABEL: usati_i16_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 16
-; CHECK-NEXT: beqz a1, .LBB92_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB92_2:
+; CHECK-NEXT: usati a0, a0, 16
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 65535
%cmp2 = icmp sgt i64 %x, -1
@@ -1144,12 +1114,7 @@ define i16 @usati_i16_from_i64(i64 %x) {
define i20 @usati_i20_from_i64(i64 %x) {
; CHECK-LABEL: usati_i20_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 20
-; CHECK-NEXT: beqz a1, .LBB93_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB93_2:
+; CHECK-NEXT: usati a0, a0, 20
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 1048575
%cmp2 = icmp sgt i64 %x, -1
@@ -1162,12 +1127,7 @@ define i20 @usati_i20_from_i64(i64 %x) {
define i32 @usati_i32_from_i64(i64 %x) {
; CHECK-LABEL: usati_i32_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 32
-; CHECK-NEXT: beqz a1, .LBB94_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB94_2:
+; CHECK-NEXT: usati a0, a0, 32
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 4294967295
%cmp2 = icmp sgt i64 %x, -1
@@ -1180,12 +1140,7 @@ define i32 @usati_i32_from_i64(i64 %x) {
define i40 @usati_i40_from_i64(i64 %x) {
; CHECK-LABEL: usati_i40_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 40
-; CHECK-NEXT: beqz a1, .LBB95_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB95_2:
+; CHECK-NEXT: usati a0, a0, 40
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 1099511627775
%cmp2 = icmp sgt i64 %x, -1
@@ -1198,12 +1153,7 @@ define i40 @usati_i40_from_i64(i64 %x) {
define i48 @usati_i48_from_i64(i64 %x) {
; CHECK-LABEL: usati_i48_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 48
-; CHECK-NEXT: beqz a1, .LBB96_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB96_2:
+; CHECK-NEXT: usati a0, a0, 48
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 281474976710655
%cmp2 = icmp sgt i64 %x, -1
@@ -1216,12 +1166,7 @@ define i48 @usati_i48_from_i64(i64 %x) {
define i56 @usati_i56_from_i64(i64 %x) {
; CHECK-LABEL: usati_i56_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a1, a0, 56
-; CHECK-NEXT: beqz a1, .LBB97_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB97_2:
+; CHECK-NEXT: usati a0, a0, 56
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 72057594037927935
%cmp2 = icmp sgt i64 %x, -1
@@ -1234,11 +1179,7 @@ define i56 @usati_i56_from_i64(i64 %x) {
define i63 @usati_i63_from_i64(i64 %x) {
; CHECK-LABEL: usati_i63_from_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: bgez a0, .LBB98_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB98_2:
+; CHECK-NEXT: usati a0, a0, 63
; CHECK-NEXT: ret
%cmp1 = icmp ugt i64 %x, 9223372036854775807
%cmp2 = icmp sgt i64 %x, -1
@@ -1252,14 +1193,8 @@ define i63 @usati_i63_from_i64(i64 %x) {
define i8 @usati_i8_from_i16(i16 %x) {
; CHECK-LABEL: usati_i8_from_i16:
; CHECK: # %bb.0:
-; CHECK-NEXT: zext.h a1, a0
-; CHECK-NEXT: li a2, 255
-; CHECK-NEXT: bgeu a2, a1, .LBB99_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: slli a0, a0, 48
-; CHECK-NEXT: srli a0, a0, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB99_2:
+; CHECK-NEXT: sext.h a0, a0
+; CHECK-NEXT: usati a0, a0, 8
; CHECK-NEXT: ret
%cmp1 = icmp ugt i16 %x, 255
%cmp2 = icmp sgt i16 %x, -1
@@ -1272,13 +1207,8 @@ define i8 @usati_i8_from_i16(i16 %x) {
define i8 @usati_i8_from_i32(i32 %x) {
; CHECK-LABEL: usati_i8_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: sext.w a1, a0
-; CHECK-NEXT: li a2, 255
-; CHECK-NEXT: bgeu a2, a1, .LBB100_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srliw a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB100_2:
+; CHECK-NEXT: sext.w a0, a0
+; CHECK-NEXT: usati a0, a0, 8
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 255
%cmp2 = icmp sgt i32 %x, -1
@@ -1291,12 +1221,8 @@ define i8 @usati_i8_from_i32(i32 %x) {
define i16 @usati_i16_from_i32(i32 %x) {
; CHECK-LABEL: usati_i16_from_i32:
; CHECK: # %bb.0:
-; CHECK-NEXT: srliw a1, a0, 16
-; CHECK-NEXT: beqz a1, .LBB101_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srliw a0, a0, 31
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB101_2:
+; CHECK-NEXT: sext.w a0, a0
+; CHECK-NEXT: usati a0, a0, 16
; CHECK-NEXT: ret
%cmp1 = icmp ugt i32 %x, 65535
%cmp2 = icmp sgt i32 %x, -1
@@ -1309,13 +1235,9 @@ define i16 @usati_i16_from_i32(i32 %x) {
define i16 @usati_i16_from_i48(i48 %x) {
; CHECK-LABEL: usati_i16_from_i48:
; CHECK: # %bb.0:
-; CHECK-NEXT: slli a1, a0, 16
-; CHECK-NEXT: srli a2, a1, 32
-; CHECK-NEXT: beqz a2, .LBB102_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a1, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB102_2:
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: srai a0, a0, 16
+; CHECK-NEXT: usati a0, a0, 16
; CHECK-NEXT: ret
%cmp1 = icmp ugt i48 %x, 65535
%cmp2 = icmp sgt i48 %x, -1
@@ -1328,13 +1250,9 @@ define i16 @usati_i16_from_i48(i48 %x) {
define i32 @usati_i32_from_i48(i48 %x) {
; CHECK-LABEL: usati_i32_from_i48:
; CHECK: # %bb.0:
-; CHECK-NEXT: slli a1, a0, 16
-; CHECK-NEXT: srli a2, a1, 48
-; CHECK-NEXT: beqz a2, .LBB103_2
-; CHECK-NEXT: # %bb.1:
-; CHECK-NEXT: srli a0, a1, 63
-; CHECK-NEXT: addi a0, a0, -1
-; CHECK-NEXT: .LBB103_2:
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: srai a0, a0, 16
+; CHECK-NEXT: usati a0, a0, 32
; CHECK-NEXT: ret
%cmp1 = icmp ugt i48 %x, 4294967295
%cmp2 = icmp sgt i48 %x, -1
>From 19bb9ce8dc0b91f752cc01d2810ae032b6c0c02f Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 7 Apr 2026 12:23:02 -0700
Subject: [PATCH 3/3] fixup! Address review comments
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 6196e3ac1826a..f3f0638d51faf 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20280,7 +20280,7 @@ static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
return DAG.getNode(ISD::ADD, DL, VT, A, NewB);
}
-// Fold (iC (select (src >u ((1 << C) - 1)), sext(src >s -1), trunc(src))) to
+// Fold (iN (select (src >u ((1 << N) - 1)), sext(src >s -1), trunc(src))) to
// USATI. This pattern saturates a signed value to an unsigned N-bit range
// [0, 2^N-1]:
// - If src < 0: result = 0
@@ -20321,9 +20321,9 @@ static SDValue foldSelectToUSATI(SDNode *N, SelectionDAG &DAG,
return SDValue();
// Check inner setcc: src > -1 (signed comparison)
- if (InnerSetCC.getValueType() != MVT::i1 ||
- !sd_match(InnerSetCC, m_SetCC(m_Specific(Src), m_AllOnes(),
- m_SpecificCondCode(ISD::SETGT))))
+ if (!sd_match(InnerSetCC,
+ m_SpecificVT(MVT::i1, m_SetCC(m_Specific(Src), m_AllOnes(),
+ m_SpecificCondCode(ISD::SETGT)))))
return SDValue();
// FalseSrc may have been optimized from a truncate of a truncate. There may
More information about the llvm-commits
mailing list