Skip to content

Commit

Permalink
[InstCombine] Preserve the nsw/nuw flags for (X | Op01C) + Op1C --> X…
Browse files Browse the repository at this point in the history
… + (Op01C + Op1C) (#94586)

This patch simplifies `sdiv` to `udiv` by preserving the `nsw` flag for
`(X | Op01C) + Op1C --> X + (Op01C + Op1C)` if the sum of `Op01C` and
`Op1C` will not overflow, and preserves the `nuw` flag unconditionally.

Alive2 Proofs (provided by @nikic): https://alive2.llvm.org/ce/z/nrdCZT,
https://alive2.llvm.org/ce/z/YnJHnH
  • Loading branch information
csstormq authored Jun 8, 2024
1 parent dc3f8c2 commit 96af114
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 deletions.
10 changes: 8 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,8 +905,14 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {

// (X | Op01C) + Op1C --> X + (Op01C + Op1C) iff the `or` is actually an `add`
Constant *Op01C;
if (match(Op0, m_DisjointOr(m_Value(X), m_ImmConstant(Op01C))))
return BinaryOperator::CreateAdd(X, ConstantExpr::getAdd(Op01C, Op1C));
if (match(Op0, m_DisjointOr(m_Value(X), m_ImmConstant(Op01C)))) {
BinaryOperator *NewAdd =
BinaryOperator::CreateAdd(X, ConstantExpr::getAdd(Op01C, Op1C));
NewAdd->setHasNoSignedWrap(Add.hasNoSignedWrap() &&
willNotOverflowSignedAdd(Op01C, Op1C, Add));
NewAdd->setHasNoUnsignedWrap(Add.hasNoUnsignedWrap());
return NewAdd;
}

// (X | C2) + C --> (X | C2) ^ C2 iff (C2 == -C)
const APInt *C2;
Expand Down
40 changes: 40 additions & 0 deletions llvm/test/Transforms/InstCombine/add.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,46 @@ define i8 @add_like_or_t2_extrause(i8 %x) {
%r = add i8 %i1, 42
ret i8 %r
}
define i8 @fold_add_constant_preserve_nsw(i8 %x) {
; CHECK-LABEL: @fold_add_constant_preserve_nsw(
; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], -120
; CHECK-NEXT: ret i8 [[ADD]]
;
%or = or disjoint i8 %x, -128
%add = add nsw i8 %or, 8
ret i8 %add
}
define i8 @fold_add_constant_no_nsw(i8 %x) {
; CHECK-LABEL: @fold_add_constant_no_nsw(
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 120
; CHECK-NEXT: ret i8 [[ADD]]
;
%or = or disjoint i8 %x, -128
%add = add nsw i8 %or, -8
ret i8 %add
}
define i8 @fold_add_constant_preserve_nuw(i8 %x) {
; CHECK-LABEL: @fold_add_constant_preserve_nuw(
; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X:%.*]], -116
; CHECK-NEXT: ret i8 [[ADD]]
;
%or = or disjoint i8 %x, 128
%add = add nuw i8 %or, 12
ret i8 %add
}
define i32 @sdiv_to_udiv(i32 %arg0, i32 %arg1) {
; CHECK-LABEL: @sdiv_to_udiv(
; CHECK-NEXT: [[T0:%.*]] = shl nuw nsw i32 [[ARG0:%.*]], 8
; CHECK-NEXT: [[T2:%.*]] = add nuw nsw i32 [[T0]], 6242049
; CHECK-NEXT: [[T3:%.*]] = udiv i32 [[T2]], 192
; CHECK-NEXT: ret i32 [[T3]]
;
%t0 = shl nuw nsw i32 %arg0, 8
%t1 = or disjoint i32 %t0, 1
%t2 = add nuw nsw i32 %t1, 6242048
%t3 = sdiv i32 %t2, 192
ret i32 %t3
}

define i8 @add_like_or_disjoint(i8 %x) {
; CHECK-LABEL: @add_like_or_disjoint(
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/sadd-with-overflow.ll
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ define { i32, i1 } @fold_sub_simple(i32 %x) {

define { i32, i1 } @fold_with_distjoin_or(i32 %x) {
; CHECK-LABEL: @fold_with_distjoin_or(
; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], 6
; CHECK-NEXT: [[B:%.*]] = add nsw i32 [[X:%.*]], 6
; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[B]], 0
; CHECK-NEXT: ret { i32, i1 } [[TMP1]]
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,11 @@ define void @matrix_extract_insert_loop(i32 %i, ptr nonnull align 8 dereferencea
; CHECK: vector.body.1:
; CHECK-NEXT: [[INDEX_1:%.*]] = phi i64 [ 0, [[VECTOR_PH_1]] ], [ [[INDEX_NEXT_1:%.*]], [[VECTOR_BODY_1]] ]
; CHECK-NEXT: [[TMP33:%.*]] = add nuw nsw i64 [[INDEX_1]], 15
; CHECK-NEXT: [[TMP34:%.*]] = add i64 [[INDEX_1]], 16
; CHECK-NEXT: [[TMP34:%.*]] = add nuw nsw i64 [[INDEX_1]], 16
; CHECK-NEXT: [[TMP35:%.*]] = insertelement <2 x i64> poison, i64 [[TMP33]], i64 0
; CHECK-NEXT: [[TMP36:%.*]] = insertelement <2 x i64> [[TMP35]], i64 [[TMP34]], i64 1
; CHECK-NEXT: [[TMP37:%.*]] = add i64 [[INDEX_1]], 17
; CHECK-NEXT: [[TMP38:%.*]] = add i64 [[INDEX_1]], 18
; CHECK-NEXT: [[TMP37:%.*]] = add nuw nsw i64 [[INDEX_1]], 17
; CHECK-NEXT: [[TMP38:%.*]] = add nuw nsw i64 [[INDEX_1]], 18
; CHECK-NEXT: [[TMP39:%.*]] = insertelement <2 x i64> poison, i64 [[TMP37]], i64 0
; CHECK-NEXT: [[TMP40:%.*]] = insertelement <2 x i64> [[TMP39]], i64 [[TMP38]], i64 1
; CHECK-NEXT: [[TMP41:%.*]] = icmp ult <2 x i64> [[TMP36]], <i64 225, i64 225>
Expand Down Expand Up @@ -259,11 +259,11 @@ define void @matrix_extract_insert_loop(i32 %i, ptr nonnull align 8 dereferencea
; CHECK: vector.body.2:
; CHECK-NEXT: [[INDEX_2:%.*]] = phi i64 [ 0, [[VECTOR_PH_2]] ], [ [[INDEX_NEXT_2:%.*]], [[VECTOR_BODY_2]] ]
; CHECK-NEXT: [[TMP64:%.*]] = add nuw nsw i64 [[INDEX_2]], 30
; CHECK-NEXT: [[TMP65:%.*]] = add i64 [[INDEX_2]], 31
; CHECK-NEXT: [[TMP65:%.*]] = add nuw nsw i64 [[INDEX_2]], 31
; CHECK-NEXT: [[TMP66:%.*]] = insertelement <2 x i64> poison, i64 [[TMP64]], i64 0
; CHECK-NEXT: [[TMP67:%.*]] = insertelement <2 x i64> [[TMP66]], i64 [[TMP65]], i64 1
; CHECK-NEXT: [[TMP68:%.*]] = add i64 [[INDEX_2]], 32
; CHECK-NEXT: [[TMP69:%.*]] = add i64 [[INDEX_2]], 33
; CHECK-NEXT: [[TMP68:%.*]] = add nuw nsw i64 [[INDEX_2]], 32
; CHECK-NEXT: [[TMP69:%.*]] = add nuw nsw i64 [[INDEX_2]], 33
; CHECK-NEXT: [[TMP70:%.*]] = insertelement <2 x i64> poison, i64 [[TMP68]], i64 0
; CHECK-NEXT: [[TMP71:%.*]] = insertelement <2 x i64> [[TMP70]], i64 [[TMP69]], i64 1
; CHECK-NEXT: [[TMP72:%.*]] = icmp ult <2 x i64> [[TMP67]], <i64 225, i64 225>
Expand Down Expand Up @@ -336,11 +336,11 @@ define void @matrix_extract_insert_loop(i32 %i, ptr nonnull align 8 dereferencea
; CHECK: vector.body.3:
; CHECK-NEXT: [[INDEX_3:%.*]] = phi i64 [ 0, [[VECTOR_PH_3]] ], [ [[INDEX_NEXT_3:%.*]], [[VECTOR_BODY_3]] ]
; CHECK-NEXT: [[TMP95:%.*]] = add nuw nsw i64 [[INDEX_3]], 45
; CHECK-NEXT: [[TMP96:%.*]] = add i64 [[INDEX_3]], 46
; CHECK-NEXT: [[TMP96:%.*]] = add nuw nsw i64 [[INDEX_3]], 46
; CHECK-NEXT: [[TMP97:%.*]] = insertelement <2 x i64> poison, i64 [[TMP95]], i64 0
; CHECK-NEXT: [[TMP98:%.*]] = insertelement <2 x i64> [[TMP97]], i64 [[TMP96]], i64 1
; CHECK-NEXT: [[TMP99:%.*]] = add i64 [[INDEX_3]], 47
; CHECK-NEXT: [[TMP100:%.*]] = add i64 [[INDEX_3]], 48
; CHECK-NEXT: [[TMP99:%.*]] = add nuw nsw i64 [[INDEX_3]], 47
; CHECK-NEXT: [[TMP100:%.*]] = add nuw nsw i64 [[INDEX_3]], 48
; CHECK-NEXT: [[TMP101:%.*]] = insertelement <2 x i64> poison, i64 [[TMP99]], i64 0
; CHECK-NEXT: [[TMP102:%.*]] = insertelement <2 x i64> [[TMP101]], i64 [[TMP100]], i64 1
; CHECK-NEXT: [[TMP103:%.*]] = icmp ult <2 x i64> [[TMP98]], <i64 225, i64 225>
Expand Down

0 comments on commit 96af114

Please sign in to comment.