Skip to content

Commit db90673

Browse files
authored
[InstCombine] Re-queue users of phi when nsw/nuw flags of add are inferred (#113933)
This patch re-queue users of phi when one of its incoming add instructions is updated. If an add instruction is updated, the analysis results of phis may be improved. Thus we may further fold some users of this phi node. See the following case: ``` define i8 @trunc_in_loop_exit_block() { ; CHECK-LABEL: @trunc_in_loop_exit_block( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV_NEXT]], [[LOOP_LATCH]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[IV]], 100 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT:%.*]] ; CHECK: loop.latch: ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 ; CHECK-NEXT: br label [[LOOP]] ; CHECK: exit: ; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[PHI]] to i8 ; CHECK-NEXT: ret i8 [[TRUNC]] ; entry: br label %loop loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] %phi = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ] %cmp = icmp ult i32 %iv, 100 br i1 %cmp, label %loop.latch, label %exit loop.latch: %iv.next = add i32 %iv, 1 br label %loop exit: %trunc = trunc i32 %phi to i8 ret i8 %trunc } ``` `%iv u< 100` -> infer `nsw/nuw` for `%iv.next = add i32 %iv, 1` -> `%iv` is non-negative -> infer `samesign` for `%cmp = icmp ult i32 %iv, 100`. Without re-queuing users of phi nodes, we cannot improve `%cmp` in one iteration. Address review comment #112642 (comment). This patch also fixes some non-fixpoint issues in tests.
1 parent 6a12b43 commit db90673

File tree

4 files changed

+20
-29
lines changed

4 files changed

+20
-29
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,15 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
18681868
if (Instruction *Res = foldBinOpOfSelectAndCastOfSelectCondition(I))
18691869
return Res;
18701870

1871+
// Re-enqueue users of the induction variable of add recurrence if we infer
1872+
// new nuw/nsw flags.
1873+
if (Changed) {
1874+
PHINode *PHI;
1875+
Value *Start, *Step;
1876+
if (matchSimpleRecurrence(&I, PHI, Start, Step))
1877+
Worklist.pushUsersToWorkList(*PHI);
1878+
}
1879+
18711880
return Changed ? &I : nullptr;
18721881
}
18731882

llvm/test/Transforms/InstCombine/2007-10-31-RangeCrash.ll

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
22
; RUN: opt < %s -S -passes=instcombine | FileCheck %s
33

4-
; We do not reach a fixpoint, because we first have to infer nsw on the IV add,
5-
; and could eliminate the icmp slt afterwards, but don't revisit it.
6-
74
target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128"
85

9-
define i32 @test() "instcombine-no-verify-fixpoint" {
10-
; CHECK-LABEL: define i32 @test(
11-
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
6+
define i32 @test() {
7+
; CHECK-LABEL: define i32 @test() {
128
; CHECK-NEXT: entry:
139
; CHECK-NEXT: br i1 true, label [[BB_I:%.*]], label [[CALCULATECOLORSPECIFICBLACKLEVEL_EXIT:%.*]]
1410
; CHECK: bb.i:
1511
; CHECK-NEXT: br label [[BB51_I_I:%.*]]
1612
; CHECK: bb27.i.i:
17-
; CHECK-NEXT: [[TMP50_I_I:%.*]] = add nsw i32 [[X_0_I_I:%.*]], 2
1813
; CHECK-NEXT: br label [[BB51_I_I]]
1914
; CHECK: bb51.i.i:
20-
; CHECK-NEXT: [[X_0_I_I]] = phi i32 [ [[TMP50_I_I]], [[BB27_I_I:%.*]] ], [ 0, [[BB_I]] ]
21-
; CHECK-NEXT: [[TMP54_I_I:%.*]] = icmp slt i32 [[X_0_I_I]], 0
22-
; CHECK-NEXT: br i1 [[TMP54_I_I]], label [[BB27_I_I]], label [[BB57_I_I:%.*]]
15+
; CHECK-NEXT: br i1 false, label [[BB27_I_I:%.*]], label [[BB57_I_I:%.*]]
2316
; CHECK: bb57.i.i:
2417
; CHECK-NEXT: ret i32 0
2518
; CHECK: calculateColorSpecificBlackLevel.exit:

llvm/test/Transforms/InstCombine/cast_phi.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,14 @@ exit:
309309
ret i64 %r
310310
}
311311

312-
define i8 @trunc_in_loop_exit_block() "instcombine-no-verify-fixpoint" {
312+
define i8 @trunc_in_loop_exit_block() {
313313
; CHECK-LABEL: @trunc_in_loop_exit_block(
314314
; CHECK-NEXT: entry:
315315
; CHECK-NEXT: br label [[LOOP:%.*]]
316316
; CHECK: loop:
317317
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
318318
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV_NEXT]], [[LOOP_LATCH]] ]
319-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV]], 100
319+
; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[IV]], 100
320320
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT:%.*]]
321321
; CHECK: loop.latch:
322322
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1

llvm/test/Transforms/SimpleLoopUnswitch/2007-08-01-LCSSA.ll

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,29 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
22
; RUN: opt < %s -S -passes='loop(simple-loop-unswitch),instcombine' -verify-memoryssa | FileCheck %s
33

4-
; We do not reach a fixpoint, because we first have to infer nsw on the IV add,
5-
; and could eliminate the icmp slt afterwards, but don't revisit it.
6-
74
@.str9 = external constant [1 x i8]
85

96
declare i32 @strcmp(ptr, ptr)
107

11-
define i32 @_ZN9Generator6strregEPKc(ptr %this, ptr %s) "instcombine-no-verify-fixpoint" {
8+
define i32 @_ZN9Generator6strregEPKc(ptr %this, ptr %s) {
129
; CHECK-LABEL: define i32 @_ZN9Generator6strregEPKc(
13-
; CHECK-SAME: ptr [[THIS:%.*]], ptr [[S:%.*]]) #[[ATTR0:[0-9]+]] {
10+
; CHECK-SAME: ptr [[THIS:%.*]], ptr [[S:%.*]]) {
1411
; CHECK-NEXT: entry:
15-
; CHECK-NEXT: [[TMP122:%.*]] = icmp eq ptr [[S]], null
1612
; CHECK-NEXT: br label [[BB184:%.*]]
1713
; CHECK: bb55:
1814
; CHECK-NEXT: ret i32 0
1915
; CHECK: bb88:
20-
; CHECK-NEXT: br i1 [[TMP122]], label [[BB154:%.*]], label [[BB128:%.*]]
16+
; CHECK-NEXT: br i1 poison, label [[BB154:%.*]], label [[BB128:%.*]]
2117
; CHECK: bb128:
22-
; CHECK-NEXT: [[TMP138:%.*]] = call i32 @strcmp(ptr noundef nonnull dereferenceable(1) null, ptr noundef nonnull dereferenceable(1) [[S]])
23-
; CHECK-NEXT: [[IFTMP_37_0_IN4:%.*]] = icmp eq i32 [[TMP138]], 0
24-
; CHECK-NEXT: br i1 [[IFTMP_37_0_IN4]], label [[BB250:%.*]], label [[BB166:%.*]]
18+
; CHECK-NEXT: br i1 poison, label [[BB250:%.*]], label [[BB166:%.*]]
2519
; CHECK: bb154:
2620
; CHECK-NEXT: br i1 false, label [[BB250]], label [[BB166]]
2721
; CHECK: bb166:
28-
; CHECK-NEXT: [[TMP175:%.*]] = add i32 [[IDX_0:%.*]], 1
29-
; CHECK-NEXT: [[TMP183:%.*]] = add nsw i32 [[I33_0:%.*]], 1
3022
; CHECK-NEXT: br label [[BB184]]
3123
; CHECK: bb184:
32-
; CHECK-NEXT: [[I33_0]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP183]], [[BB166]] ]
33-
; CHECK-NEXT: [[IDX_0]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP175]], [[BB166]] ]
34-
; CHECK-NEXT: [[TMP49:%.*]] = icmp slt i32 [[I33_0]], 0
35-
; CHECK-NEXT: br i1 [[TMP49]], label [[BB88:%.*]], label [[BB55:%.*]]
24+
; CHECK-NEXT: br i1 false, label [[BB88:%.*]], label [[BB55:%.*]]
3625
; CHECK: bb250:
37-
; CHECK-NEXT: ret i32 [[IDX_0]]
26+
; CHECK-NEXT: ret i32 poison
3827
;
3928
entry:
4029
%s_addr.0 = select i1 false, ptr @.str9, ptr %s

0 commit comments

Comments
 (0)