mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
df7e45dd98
I think currently isImpliedViaMerge can incorrectly return true for phis in a loop/cycle, if the found condition involves the previous value of Consider the case in exit_cond_depends_on_inner_loop. At some point, we call (modulo simplifications) isImpliedViaMerge(<=, %x.lcssa, -1, %call, -1). The existing code tries to prove IncV <= -1 for all incoming values InvV using the found condition (%call <= -1). At the moment this succeeds, but only because it does not compare the same runtime value. The found condition checks the value of the last iteration, but the incoming value is from the *previous* iteration. Hence we incorrectly determine that the *previous* value was <= -1, which may not be true. I think we need to be more careful when looking at the incoming values here. In particular, we need to rule out that a found condition refers to any value that may refer to one of the previous iterations. I'm not sure there's a reliable way to do so (that also works of irreducible control flow). So for now this patch adds an additional requirement that the incoming value must properly dominate the phi block. This should ensure the values do not change in a cycle. I am not entirely sure if will catch all cases and I appreciate a through second look in that regard. Alternatively we could also unconditionally bail out in this case, instead of checking the incoming values Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D101829
495 lines
16 KiB
LLVM
495 lines
16 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -indvars -S < %s | FileCheck %s
|
|
|
|
define void @ult(i64 %n, i64 %m) {
|
|
; CHECK-LABEL: @ult(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP0:%.*]] = icmp ult i64 [[N:%.*]], [[M:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: call void @side_effect()
|
|
; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT_LOOPEXIT]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp0 = icmp ult i64 %n, %m
|
|
br i1 %cmp0, label %loop, label %exit
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
|
|
%iv.next = add i64 %iv, 1
|
|
%cmp1 = icmp ult i64 %iv, %n
|
|
br i1 %cmp1, label %latch, label %exit
|
|
latch:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i64 %iv, %m
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @ugt(i64 %n, i64 %m) {
|
|
; CHECK-LABEL: @ugt(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP0:%.*]] = icmp ugt i64 [[N:%.*]], [[M:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
|
|
; CHECK-NEXT: br i1 true, label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: call void @side_effect()
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[M]]
|
|
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT_LOOPEXIT]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp0 = icmp ugt i64 %n, %m
|
|
br i1 %cmp0, label %loop, label %exit
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
|
|
%iv.next = add i64 %iv, 1
|
|
%cmp1 = icmp ult i64 %iv, %n
|
|
br i1 %cmp1, label %latch, label %exit
|
|
latch:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i64 %iv, %m
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @ule(i64 %n, i64 %m) {
|
|
; CHECK-LABEL: @ule(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP0:%.*]] = icmp ule i64 [[N:%.*]], [[M:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: call void @side_effect()
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[M]]
|
|
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT_LOOPEXIT]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp0 = icmp ule i64 %n, %m
|
|
br i1 %cmp0, label %loop, label %exit
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
|
|
%iv.next = add i64 %iv, 1
|
|
%cmp1 = icmp ult i64 %iv, %n
|
|
br i1 %cmp1, label %latch, label %exit
|
|
latch:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i64 %iv, %m
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @uge(i64 %n, i64 %m) {
|
|
; CHECK-LABEL: @uge(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP0:%.*]] = icmp uge i64 [[N:%.*]], [[M:%.*]]
|
|
; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: call void @side_effect()
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[M]]
|
|
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT_LOOPEXIT]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp0 = icmp uge i64 %n, %m
|
|
br i1 %cmp0, label %loop, label %exit
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
|
|
%iv.next = add i64 %iv, 1
|
|
%cmp1 = icmp ult i64 %iv, %n
|
|
br i1 %cmp1, label %latch, label %exit
|
|
latch:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i64 %iv, %m
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
|
|
define void @ult_const_max(i64 %n) {
|
|
; CHECK-LABEL: @ult_const_max(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP0:%.*]] = icmp ult i64 [[N:%.*]], 20
|
|
; CHECK-NEXT: br i1 [[CMP0]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: br i1 true, label [[LATCH]], label [[EXIT_LOOPEXIT:%.*]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: call void @side_effect()
|
|
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[IV]], [[N]]
|
|
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP]], label [[EXIT_LOOPEXIT]]
|
|
; CHECK: exit.loopexit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%cmp0 = icmp ult i64 %n, 20
|
|
br i1 %cmp0, label %loop, label %exit
|
|
loop:
|
|
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
|
|
%iv.next = add i64 %iv, 1
|
|
%udiv = udiv i64 %iv, 10
|
|
%cmp1 = icmp ult i64 %udiv, 2
|
|
br i1 %cmp1, label %latch, label %exit
|
|
latch:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i64 %iv, %n
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @mixed_width(i32 %len) {
|
|
; CHECK-LABEL: @mixed_width(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[LEN_ZEXT:%.*]] = zext i32 [[LEN:%.*]] to i64
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
|
|
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], [[LEN_ZEXT]]
|
|
; CHECK-NEXT: br i1 [[CMP1]], label [[BACKEDGE]], label [[EXIT:%.*]]
|
|
; CHECK: backedge:
|
|
; CHECK-NEXT: call void @side_effect()
|
|
; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%len.zext = zext i32 %len to i64
|
|
br label %loop
|
|
loop:
|
|
%iv = phi i64 [0, %entry], [%iv.next, %backedge]
|
|
%iv2 = phi i32 [0, %entry], [%iv2.next, %backedge]
|
|
%iv.next = add i64 %iv, 1
|
|
%iv2.next = add i32 %iv2, 1
|
|
%cmp1 = icmp ult i64 %iv, %len.zext
|
|
br i1 %cmp1, label %backedge, label %exit
|
|
|
|
backedge:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i32 %iv2, %len
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @many_exits([100 x i64] %len) {
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%iv = phi i64 [0, %entry], [%iv.next, %backedge]
|
|
%len0 = extractvalue [100 x i64] %len, 0
|
|
%early0 = icmp eq i64 %iv, %len0
|
|
call void @side_effect()
|
|
br i1 %early0, label %exit, label %cont0
|
|
cont0:
|
|
%len1 = extractvalue [100 x i64] %len, 1
|
|
%early1 = icmp eq i64 %iv, %len1
|
|
call void @side_effect()
|
|
br i1 %early1, label %exit, label %cont1
|
|
cont1:
|
|
%len2 = extractvalue [100 x i64] %len, 2
|
|
%early2 = icmp eq i64 %iv, %len2
|
|
call void @side_effect()
|
|
br i1 %early2, label %exit, label %cont2
|
|
cont2:
|
|
%len3 = extractvalue [100 x i64] %len, 3
|
|
%early3 = icmp eq i64 %iv, %len3
|
|
call void @side_effect()
|
|
br i1 %early3, label %exit, label %cont3
|
|
cont3:
|
|
%len4 = extractvalue [100 x i64] %len, 4
|
|
%early4 = icmp eq i64 %iv, %len4
|
|
call void @side_effect()
|
|
br i1 %early4, label %exit, label %cont4
|
|
cont4:
|
|
%len5 = extractvalue [100 x i64] %len, 5
|
|
%early5 = icmp eq i64 %iv, %len5
|
|
call void @side_effect()
|
|
br i1 %early5, label %exit, label %cont5
|
|
cont5:
|
|
%len6 = extractvalue [100 x i64] %len, 6
|
|
%early6 = icmp eq i64 %iv, %len6
|
|
call void @side_effect()
|
|
br i1 %early6, label %exit, label %cont6
|
|
cont6:
|
|
%len7 = extractvalue [100 x i64] %len, 7
|
|
%early7 = icmp eq i64 %iv, %len7
|
|
call void @side_effect()
|
|
br i1 %early7, label %exit, label %cont7
|
|
cont7:
|
|
%len8 = extractvalue [100 x i64] %len, 8
|
|
%early8 = icmp eq i64 %iv, %len8
|
|
call void @side_effect()
|
|
br i1 %early8, label %exit, label %cont8
|
|
cont8:
|
|
%len9 = extractvalue [100 x i64] %len, 9
|
|
%early9 = icmp eq i64 %iv, %len9
|
|
call void @side_effect()
|
|
br i1 %early9, label %exit, label %cont9
|
|
cont9:
|
|
%len10 = extractvalue [100 x i64] %len, 10
|
|
%early10 = icmp eq i64 %iv, %len10
|
|
call void @side_effect()
|
|
br i1 %early10, label %exit, label %cont10
|
|
cont10:
|
|
%len11 = extractvalue [100 x i64] %len, 11
|
|
%early11 = icmp eq i64 %iv, %len11
|
|
call void @side_effect()
|
|
br i1 %early11, label %exit, label %cont11
|
|
cont11:
|
|
%len12 = extractvalue [100 x i64] %len, 12
|
|
%early12 = icmp eq i64 %iv, %len12
|
|
call void @side_effect()
|
|
br i1 %early12, label %exit, label %cont12
|
|
cont12:
|
|
%len13 = extractvalue [100 x i64] %len, 13
|
|
%early13 = icmp eq i64 %iv, %len13
|
|
call void @side_effect()
|
|
br i1 %early13, label %exit, label %cont13
|
|
cont13:
|
|
%len14 = extractvalue [100 x i64] %len, 14
|
|
%early14 = icmp eq i64 %iv, %len14
|
|
call void @side_effect()
|
|
br i1 %early14, label %exit, label %cont14
|
|
cont14:
|
|
%len15 = extractvalue [100 x i64] %len, 15
|
|
%early15 = icmp eq i64 %iv, %len15
|
|
call void @side_effect()
|
|
br i1 %early15, label %exit, label %cont15
|
|
cont15:
|
|
%len16 = extractvalue [100 x i64] %len, 16
|
|
%early16 = icmp eq i64 %iv, %len16
|
|
call void @side_effect()
|
|
br i1 %early16, label %exit, label %cont16
|
|
cont16:
|
|
%len17 = extractvalue [100 x i64] %len, 17
|
|
%early17 = icmp eq i64 %iv, %len17
|
|
call void @side_effect()
|
|
br i1 %early17, label %exit, label %cont17
|
|
cont17:
|
|
%len18 = extractvalue [100 x i64] %len, 18
|
|
%early18 = icmp eq i64 %iv, %len18
|
|
call void @side_effect()
|
|
br i1 %early18, label %exit, label %cont18
|
|
cont18:
|
|
%len19 = extractvalue [100 x i64] %len, 19
|
|
%early19 = icmp eq i64 %iv, %len19
|
|
call void @side_effect()
|
|
br i1 %early19, label %exit, label %cont19
|
|
cont19:
|
|
%len20 = extractvalue [100 x i64] %len, 20
|
|
%early20 = icmp eq i64 %iv, %len20
|
|
call void @side_effect()
|
|
br i1 %early20, label %exit, label %cont20
|
|
cont20:
|
|
%len21 = extractvalue [100 x i64] %len, 21
|
|
%early21 = icmp eq i64 %iv, %len21
|
|
call void @side_effect()
|
|
br i1 %early21, label %exit, label %cont21
|
|
cont21:
|
|
%len22 = extractvalue [100 x i64] %len, 22
|
|
%early22 = icmp eq i64 %iv, %len22
|
|
call void @side_effect()
|
|
br i1 %early22, label %exit, label %cont22
|
|
cont22:
|
|
%len23 = extractvalue [100 x i64] %len, 23
|
|
%early23 = icmp eq i64 %iv, %len23
|
|
call void @side_effect()
|
|
br i1 %early23, label %exit, label %cont23
|
|
cont23:
|
|
%len24 = extractvalue [100 x i64] %len, 24
|
|
%early24 = icmp eq i64 %iv, %len24
|
|
call void @side_effect()
|
|
br i1 %early24, label %exit, label %cont24
|
|
cont24:
|
|
%len25 = extractvalue [100 x i64] %len, 25
|
|
%early25 = icmp eq i64 %iv, %len25
|
|
call void @side_effect()
|
|
br i1 %early25, label %exit, label %cont25
|
|
cont25:
|
|
%len26 = extractvalue [100 x i64] %len, 26
|
|
%early26 = icmp eq i64 %iv, %len26
|
|
call void @side_effect()
|
|
br i1 %early26, label %exit, label %cont26
|
|
cont26:
|
|
%len27 = extractvalue [100 x i64] %len, 27
|
|
%early27 = icmp eq i64 %iv, %len27
|
|
call void @side_effect()
|
|
br i1 %early27, label %exit, label %cont27
|
|
cont27:
|
|
%len28 = extractvalue [100 x i64] %len, 28
|
|
%early28 = icmp eq i64 %iv, %len28
|
|
call void @side_effect()
|
|
br i1 %early28, label %exit, label %cont28
|
|
cont28:
|
|
%len29 = extractvalue [100 x i64] %len, 29
|
|
%early29 = icmp eq i64 %iv, %len29
|
|
call void @side_effect()
|
|
br i1 %early29, label %exit, label %cont29
|
|
cont29:
|
|
%len30 = extractvalue [100 x i64] %len, 30
|
|
%early30 = icmp eq i64 %iv, %len30
|
|
call void @side_effect()
|
|
br i1 %early30, label %exit, label %cont30
|
|
cont30:
|
|
%len31 = extractvalue [100 x i64] %len, 31
|
|
%early31 = icmp eq i64 %iv, %len31
|
|
call void @side_effect()
|
|
br i1 %early31, label %exit, label %cont31
|
|
cont31:
|
|
%len32 = extractvalue [100 x i64] %len, 32
|
|
%early32 = icmp eq i64 %iv, %len32
|
|
call void @side_effect()
|
|
br i1 %early32, label %exit, label %cont32
|
|
cont32:
|
|
%len33 = extractvalue [100 x i64] %len, 33
|
|
%early33 = icmp eq i64 %iv, %len33
|
|
call void @side_effect()
|
|
br i1 %early33, label %exit, label %cont33
|
|
cont33:
|
|
%len34 = extractvalue [100 x i64] %len, 34
|
|
%early34 = icmp eq i64 %iv, %len34
|
|
call void @side_effect()
|
|
br i1 %early34, label %exit, label %cont34
|
|
cont34:
|
|
%len35 = extractvalue [100 x i64] %len, 35
|
|
%early35 = icmp eq i64 %iv, %len35
|
|
call void @side_effect()
|
|
br i1 %early35, label %exit, label %cont35
|
|
cont35:
|
|
%len36 = extractvalue [100 x i64] %len, 36
|
|
%early36 = icmp eq i64 %iv, %len36
|
|
call void @side_effect()
|
|
br i1 %early36, label %exit, label %cont36
|
|
cont36:
|
|
%len37 = extractvalue [100 x i64] %len, 37
|
|
%early37 = icmp eq i64 %iv, %len37
|
|
call void @side_effect()
|
|
br i1 %early37, label %exit, label %cont37
|
|
cont37:
|
|
%len38 = extractvalue [100 x i64] %len, 38
|
|
%early38 = icmp eq i64 %iv, %len38
|
|
call void @side_effect()
|
|
br i1 %early38, label %exit, label %cont38
|
|
cont38:
|
|
%len39 = extractvalue [100 x i64] %len, 39
|
|
%early39 = icmp eq i64 %iv, %len39
|
|
call void @side_effect()
|
|
br i1 %early39, label %exit, label %cont39
|
|
cont39:
|
|
br label %backedge
|
|
backedge:
|
|
call void @side_effect()
|
|
%cmp2 = icmp ult i64 %iv, 999
|
|
%iv.next = add i64 %iv, 1
|
|
br i1 %cmp2, label %loop, label %exit
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
declare void @side_effect()
|
|
|
|
; The exit condition %outer.cond.1 depends on a phi in %inner. Make sure we do
|
|
; not incorrectly determine %x.lcssa <= -1.
|
|
define i32 @exit_cond_depends_on_inner_loop() {
|
|
; CHECK-LABEL: @exit_cond_depends_on_inner_loop(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
|
|
; CHECK: outer.header:
|
|
; CHECK-NEXT: [[IV_OUTER:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_OUTER_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]
|
|
; CHECK-NEXT: br label [[INNER:%.*]]
|
|
; CHECK: inner:
|
|
; CHECK-NEXT: [[X:%.*]] = phi i32 [ -1, [[OUTER_HEADER]] ], [ [[CALL:%.*]], [[INNER]] ]
|
|
; CHECK-NEXT: [[CALL]] = call i32 @match()
|
|
; CHECK-NEXT: [[INNER_COND:%.*]] = icmp sgt i32 [[CALL]], -1
|
|
; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER]], label [[OUTER_EXITING_1:%.*]]
|
|
; CHECK: outer.exiting.1:
|
|
; CHECK-NEXT: [[X_LCSSA:%.*]] = phi i32 [ [[X]], [[INNER]] ]
|
|
; CHECK-NEXT: [[OUTER_COND_1:%.*]] = icmp sgt i32 [[X_LCSSA]], -1
|
|
; CHECK-NEXT: br i1 [[OUTER_COND_1]], label [[EXIT:%.*]], label [[OUTER_LATCH]]
|
|
; CHECK: outer.latch:
|
|
; CHECK-NEXT: [[IV_OUTER_NEXT]] = add nuw nsw i32 [[IV_OUTER]], 1
|
|
; CHECK-NEXT: [[OUTER_COND_2:%.*]] = icmp ult i32 [[IV_OUTER]], 100
|
|
; CHECK-NEXT: br i1 [[OUTER_COND_2]], label [[OUTER_HEADER]], label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[X_RES:%.*]] = phi i32 [ [[X_LCSSA]], [[OUTER_EXITING_1]] ], [ -1, [[OUTER_LATCH]] ]
|
|
; CHECK-NEXT: ret i32 [[X_RES]]
|
|
;
|
|
entry:
|
|
br label %outer.header
|
|
|
|
outer.header:
|
|
%iv.outer = phi i32 [ 0, %entry ], [ %iv.outer.next , %outer.latch ]
|
|
br label %inner
|
|
|
|
inner:
|
|
%x = phi i32 [ -1, %outer.header ], [ %call, %inner ]
|
|
%call = call i32 @match()
|
|
%inner.cond = icmp sgt i32 %call, -1
|
|
br i1 %inner.cond, label %inner, label %outer.exiting.1
|
|
|
|
outer.exiting.1:
|
|
%x.lcssa = phi i32 [ %x, %inner ]
|
|
%outer.cond.1 = icmp sgt i32 %x.lcssa, -1
|
|
br i1 %outer.cond.1, label %exit, label %outer.latch
|
|
|
|
outer.latch:
|
|
%iv.outer.next = add nuw nsw i32 %iv.outer, 1
|
|
%outer.cond.2 = icmp ult i32 %iv.outer, 100
|
|
br i1 %outer.cond.2, label %outer.header, label %exit
|
|
|
|
exit:
|
|
%x.res = phi i32 [ %x.lcssa, %outer.exiting.1 ], [ -1, %outer.latch ]
|
|
ret i32 %x.res
|
|
}
|
|
|
|
declare i32 @match()
|