Skip to content

Commit

Permalink
[InstCombine] Fold umax(nuw_mul(x, C0), x + 1) into (x == 0 ? 1 : nuw…
Browse files Browse the repository at this point in the history
…_mul(x, C0))
  • Loading branch information
Ruhung committed Jan 18, 2025
1 parent 60dae2c commit 5da19e8
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
31 changes: 31 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1847,6 +1847,37 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
}
}
// If C0 is not 0:
// umax(nuw_shl(x, C0), x + 1) -> x == 0 ? 1 : nuw_shl(x, C0)
// If C0 is not 0 or 1:
// umax(nuw_mul(x, C0), x + 1) -> x == 0 ? 1 : nuw_mul(x, C0)
ConstantInt *C0;
bool isShl = false;
BinaryOperator *Op = nullptr;
auto matchShiftOrMul = [&](Value *I) {
if (match(I, m_OneUse(m_NUWShl(m_Value(X), m_ConstantInt(C0))))) {
isShl = true;
return true;
} else if (match(I, m_OneUse(m_NUWMul(m_Value(X), m_ConstantInt(C0)))) &&
C0 && !C0->isOne()) {
isShl = false;
return true;
}
return false;
};
if (((matchShiftOrMul(I0) &&
match(I1, m_OneUse(m_Add(m_Specific(X), m_One())))) ||
(matchShiftOrMul(I1) &&
match(I0, m_OneUse(m_Add(m_Specific(X), m_One()))))) &&
C0 && !C0->isZero()) {
Op = isShl ? BinaryOperator::CreateNUWShl(X, C0)
: BinaryOperator::CreateNUWMul(X, C0);
Builder.Insert(Op);
Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(X->getType(), 0));
Value *NewSelect =
Builder.CreateSelect(Cmp, ConstantInt::get(X->getType(), 1), Op);
return replaceInstUsesWith(*II, NewSelect);
}
// If both operands of unsigned min/max are sign-extended, it is still ok
// to narrow the operation.
[[fallthrough]];
Expand Down
32 changes: 16 additions & 16 deletions llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
define i64 @test_shl_by_2(i64 %x) {
; CHECK-LABEL: define i64 @test_shl_by_2(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 2
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
; CHECK-NEXT: ret i64 [[MAX]]
;
%x1 = add i64 %x, 1
Expand All @@ -27,9 +27,9 @@ define i64 @test_shl_by_2(i64 %x) {
define i64 @test_shl_by_5(i64 %x) {
; CHECK-LABEL: define i64 @test_shl_by_5(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 5
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
; CHECK-NEXT: ret i64 [[MAX]]
;
%x1 = add i64 %x, 1
Expand All @@ -43,9 +43,9 @@ define i64 @test_shl_by_5(i64 %x) {
define i64 @test_shl_umax_commuted(i64 %x) {
; CHECK-LABEL: define i64 @test_shl_umax_commuted(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[X]], 2
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[SHL]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP2]], i64 1, i64 [[SHL]]
; CHECK-NEXT: ret i64 [[MAX]]
;
%x1 = add i64 %x, 1
Expand Down Expand Up @@ -135,9 +135,9 @@ define i64 @test_shl_multi_use_shl(i64 %x) {
define i64 @test_shl_multi_use_max(i64 %x) {
; CHECK-LABEL: define i64 @test_shl_multi_use_max(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 3
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
; CHECK-NEXT: call void @use(i64 [[MAX]])
; CHECK-NEXT: ret i64 [[MAX]]
;
Expand All @@ -153,9 +153,9 @@ define i64 @test_shl_multi_use_max(i64 %x) {
define i64 @test_mul_by_2(i64 %x) {
; CHECK-LABEL: define i64 @test_mul_by_2(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 1
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
; CHECK-NEXT: ret i64 [[MAX]]
;
%x1 = add i64 %x, 1
Expand All @@ -167,9 +167,9 @@ define i64 @test_mul_by_2(i64 %x) {
define i64 @test_mul_by_5(i64 %x) {
; CHECK-LABEL: define i64 @test_mul_by_5(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i64 [[X]], 5
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP2]], i64 1, i64 [[MUL]]
; CHECK-NEXT: ret i64 [[MAX]]
;
%x1 = add i64 %x, 1
Expand All @@ -183,9 +183,9 @@ define i64 @test_mul_by_5(i64 %x) {
define i64 @test_mul_max_commuted(i64 %x) {
; CHECK-LABEL: define i64 @test_mul_max_commuted(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[MUL:%.*]] = shl nuw i64 [[X]], 1
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[MUL]])
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP2]], i64 1, i64 [[MUL]]
; CHECK-NEXT: ret i64 [[MAX]]
;
%x1 = add i64 %x, 1
Expand Down Expand Up @@ -286,9 +286,9 @@ define i64 @test_mul_multi_use_mul(i64 %x) {
define i64 @test_mul_multi_use_max(i64 %x) {
; CHECK-LABEL: define i64 @test_mul_multi_use_max(
; CHECK-SAME: i64 [[X:%.*]]) {
; CHECK-NEXT: [[X1:%.*]] = add i64 [[X]], 1
; CHECK-NEXT: [[TMP2:%.*]] = shl nuw i64 [[X]], 1
; CHECK-NEXT: [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
; CHECK-NEXT: call void @use(i64 [[MAX]])
; CHECK-NEXT: ret i64 [[MAX]]
;
Expand Down

0 comments on commit 5da19e8

Please sign in to comment.