Skip to content

Commit 1a3eace

Browse files
authored
[InstCombine] Fold umax(X, C) + -C into usub.sat(X, C) (#118195)
Alive2: https://alive2.llvm.org/ce/z/oSWe5S Closes #118155
1 parent 22417ec commit 1a3eace

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,12 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {
994994
}
995995
}
996996

997+
// umax(X, C) + -C --> usub.sat(X, C)
998+
if (match(Op0, m_OneUse(m_UMax(m_Value(X), m_SpecificInt(-*C)))))
999+
return replaceInstUsesWith(
1000+
Add, Builder.CreateBinaryIntrinsic(
1001+
Intrinsic::usub_sat, X, ConstantInt::get(Add.getType(), -*C)));
1002+
9971003
// Fold (add (zext (add X, -1)), 1) -> (zext X) if X is non-zero.
9981004
// TODO: There's a general form for any constant on the outer add.
9991005
if (C->isOne()) {

llvm/test/Transforms/InstCombine/saturating-add-sub.ll

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,3 +2316,39 @@ define i32 @uadd_sat_via_add_swapped_cmp_select_nonstrict(i32 %x, i32 %y) {
23162316
%r = select i1 %c, i32 %a, i32 -1
23172317
ret i32 %r
23182318
}
2319+
2320+
define i8 @fold_add_umax_to_usub(i8 %a) {
2321+
; CHECK-LABEL: @fold_add_umax_to_usub(
2322+
; CHECK-NEXT: [[SEL:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10)
2323+
; CHECK-NEXT: ret i8 [[SEL]]
2324+
;
2325+
%umax = call i8 @llvm.umax.i8(i8 %a, i8 10)
2326+
%sel = add i8 %umax, -10
2327+
ret i8 %sel
2328+
}
2329+
2330+
define i8 @fold_add_umax_to_usub_incorrect_rhs(i8 %a) {
2331+
; CHECK-LABEL: @fold_add_umax_to_usub_incorrect_rhs(
2332+
; CHECK-NEXT: [[UMAX:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 10)
2333+
; CHECK-NEXT: [[SEL:%.*]] = add i8 [[UMAX]], -11
2334+
; CHECK-NEXT: ret i8 [[SEL]]
2335+
;
2336+
%umax = call i8 @llvm.umax.i8(i8 %a, i8 10)
2337+
%sel = add i8 %umax, -11
2338+
ret i8 %sel
2339+
}
2340+
2341+
define i8 @fold_add_umax_to_usub_multiuse(i8 %a) {
2342+
; CHECK-LABEL: @fold_add_umax_to_usub_multiuse(
2343+
; CHECK-NEXT: [[UMAX:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 10)
2344+
; CHECK-NEXT: call void @usei8(i8 [[UMAX]])
2345+
; CHECK-NEXT: [[SEL:%.*]] = add i8 [[UMAX]], -10
2346+
; CHECK-NEXT: ret i8 [[SEL]]
2347+
;
2348+
%umax = call i8 @llvm.umax.i8(i8 %a, i8 10)
2349+
call void @usei8(i8 %umax)
2350+
%sel = add i8 %umax, -10
2351+
ret i8 %sel
2352+
}
2353+
2354+
declare void @usei8(i8)

0 commit comments

Comments
 (0)