[llvm] [DAGCombiner] Fold subtraction if above threshold to `umin` (PR #134235)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 8 06:45:27 PDT 2025
================
@@ -1699,3 +1699,209 @@ entry:
%cmp = icmp eq i32 %popcnt, 1
ret i1 %cmp
}
+
+define i8 @sub_if_uge_i8(i8 %x, i8 %y) {
+; RV64I-LABEL: sub_if_uge_i8:
+; RV64I: # %bb.0:
+; RV64I-NEXT: zext.b a2, a1
+; RV64I-NEXT: zext.b a3, a0
+; RV64I-NEXT: sltu a2, a3, a2
+; RV64I-NEXT: addi a2, a2, -1
+; RV64I-NEXT: and a1, a2, a1
+; RV64I-NEXT: sub a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_i8:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: zext.b a2, a0
+; RV64ZBB-NEXT: subw a0, a0, a1
+; RV64ZBB-NEXT: zext.b a0, a0
+; RV64ZBB-NEXT: minu a0, a2, a0
+; RV64ZBB-NEXT: ret
+ %cmp = icmp ult i8 %x, %y
+ %select = select i1 %cmp, i8 0, i8 %y
+ %sub = sub nuw i8 %x, %select
+ ret i8 %sub
+}
+
+define i16 @sub_if_uge_i16(i16 %x, i16 %y) {
+; RV64I-LABEL: sub_if_uge_i16:
+; RV64I: # %bb.0:
+; RV64I-NEXT: lui a2, 16
+; RV64I-NEXT: addiw a2, a2, -1
+; RV64I-NEXT: and a3, a1, a2
+; RV64I-NEXT: and a2, a0, a2
+; RV64I-NEXT: sltu a2, a2, a3
+; RV64I-NEXT: addi a2, a2, -1
+; RV64I-NEXT: and a1, a2, a1
+; RV64I-NEXT: sub a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_i16:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: zext.h a2, a0
+; RV64ZBB-NEXT: subw a0, a0, a1
+; RV64ZBB-NEXT: zext.h a0, a0
+; RV64ZBB-NEXT: minu a0, a2, a0
+; RV64ZBB-NEXT: ret
+ %cmp = icmp ult i16 %x, %y
+ %select = select i1 %cmp, i16 0, i16 %y
+ %sub = sub nuw i16 %x, %select
+ ret i16 %sub
+}
+
+define i32 @sub_if_uge_i32(i32 %x, i32 %y) {
+; RV64I-LABEL: sub_if_uge_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sext.w a2, a1
+; RV64I-NEXT: sext.w a3, a0
+; RV64I-NEXT: sltu a2, a3, a2
+; RV64I-NEXT: addi a2, a2, -1
+; RV64I-NEXT: and a1, a2, a1
+; RV64I-NEXT: subw a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_i32:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: sext.w a2, a0
+; RV64ZBB-NEXT: subw a0, a0, a1
+; RV64ZBB-NEXT: minu a0, a2, a0
+; RV64ZBB-NEXT: ret
+ %cmp = icmp ult i32 %x, %y
+ %select = select i1 %cmp, i32 0, i32 %y
+ %sub = sub nuw i32 %x, %select
+ ret i32 %sub
+}
+
+define i64 @sub_if_uge_i64(i64 %x, i64 %y) {
+; RV64I-LABEL: sub_if_uge_i64:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sltu a2, a0, a1
+; RV64I-NEXT: addi a2, a2, -1
+; RV64I-NEXT: and a1, a2, a1
+; RV64I-NEXT: sub a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_i64:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: sub a1, a0, a1
+; RV64ZBB-NEXT: minu a0, a0, a1
+; RV64ZBB-NEXT: ret
+ %cmp = icmp ult i64 %x, %y
+ %select = select i1 %cmp, i64 0, i64 %y
+ %sub = sub nuw i64 %x, %select
+ ret i64 %sub
+}
+
+define i128 @sub_if_uge_i128(i128 %x, i128 %y) {
+; RV64I-LABEL: sub_if_uge_i128:
+; RV64I: # %bb.0:
+; RV64I-NEXT: beq a1, a3, .LBB66_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: sltu a4, a1, a3
+; RV64I-NEXT: j .LBB66_3
+; RV64I-NEXT: .LBB66_2:
+; RV64I-NEXT: sltu a4, a0, a2
+; RV64I-NEXT: .LBB66_3:
+; RV64I-NEXT: addi a4, a4, -1
+; RV64I-NEXT: and a3, a4, a3
+; RV64I-NEXT: and a2, a4, a2
+; RV64I-NEXT: sltu a4, a0, a2
+; RV64I-NEXT: sub a1, a1, a3
+; RV64I-NEXT: sub a1, a1, a4
+; RV64I-NEXT: sub a0, a0, a2
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_i128:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: beq a1, a3, .LBB66_2
+; RV64ZBB-NEXT: # %bb.1:
+; RV64ZBB-NEXT: sltu a4, a1, a3
+; RV64ZBB-NEXT: j .LBB66_3
+; RV64ZBB-NEXT: .LBB66_2:
+; RV64ZBB-NEXT: sltu a4, a0, a2
+; RV64ZBB-NEXT: .LBB66_3:
+; RV64ZBB-NEXT: addi a4, a4, -1
+; RV64ZBB-NEXT: and a3, a4, a3
+; RV64ZBB-NEXT: and a2, a4, a2
+; RV64ZBB-NEXT: sltu a4, a0, a2
+; RV64ZBB-NEXT: sub a1, a1, a3
+; RV64ZBB-NEXT: sub a1, a1, a4
+; RV64ZBB-NEXT: sub a0, a0, a2
+; RV64ZBB-NEXT: ret
+ %cmp = icmp ult i128 %x, %y
+ %select = select i1 %cmp, i128 0, i128 %y
+ %sub = sub nuw i128 %x, %select
+ ret i128 %sub
+}
+
+define i32 @sub_if_uge_multiuse_select_i32(i32 %x, i32 %y) {
+; RV64I-LABEL: sub_if_uge_multiuse_select_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sext.w a2, a1
+; RV64I-NEXT: sext.w a3, a0
+; RV64I-NEXT: sltu a2, a3, a2
+; RV64I-NEXT: addi a2, a2, -1
+; RV64I-NEXT: and a1, a2, a1
+; RV64I-NEXT: subw a0, a0, a1
+; RV64I-NEXT: sllw a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_multiuse_select_i32:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: sext.w a2, a1
+; RV64ZBB-NEXT: sext.w a3, a0
+; RV64ZBB-NEXT: sltu a2, a3, a2
+; RV64ZBB-NEXT: addi a2, a2, -1
+; RV64ZBB-NEXT: and a1, a2, a1
+; RV64ZBB-NEXT: subw a0, a0, a1
+; RV64ZBB-NEXT: sllw a0, a0, a1
+; RV64ZBB-NEXT: ret
+ %cmp = icmp ult i32 %x, %y
+ %select = select i1 %cmp, i32 0, i32 %y
+ %sub = sub nuw i32 %x, %select
+ %shl = shl i32 %sub, %select
+ ret i32 %shl
+}
+
+define i32 @sub_if_uge_multiuse_cmp_i32(i32 %x, i32 %y) {
+; RV64I-LABEL: sub_if_uge_multiuse_cmp_i32:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sext.w a2, a1
+; RV64I-NEXT: sext.w a3, a0
+; RV64I-NEXT: sltu a4, a3, a2
+; RV64I-NEXT: addi a4, a4, -1
+; RV64I-NEXT: and a1, a4, a1
+; RV64I-NEXT: subw a0, a0, a1
+; RV64I-NEXT: bltu a3, a2, .LBB68_2
+; RV64I-NEXT: # %bb.1:
+; RV64I-NEXT: li a1, 4
+; RV64I-NEXT: sllw a0, a0, a1
+; RV64I-NEXT: ret
+; RV64I-NEXT: .LBB68_2:
+; RV64I-NEXT: li a1, 2
+; RV64I-NEXT: sllw a0, a0, a1
+; RV64I-NEXT: ret
+;
+; RV64ZBB-LABEL: sub_if_uge_multiuse_cmp_i32:
+; RV64ZBB: # %bb.0:
+; RV64ZBB-NEXT: sext.w a2, a1
----------------
lukel97 wrote:
Nit, we could add a common CHECK prefix for the RV64I + RV64ZBB run lines?
https://github.com/llvm/llvm-project/pull/134235
More information about the llvm-commits
mailing list