If we invalidate an attribute we need to inform all dependent ones even if the fixpoint state is not invalid. Before we only continued invalidation if the fixpoint state was invalid, now we signal a change in case the fixpoint state is valid. The test case was already included in D71620 but the problem was hiding because it only manifested with the old PM (for that input).
534 lines
18 KiB
LLVM
534 lines
18 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
|
|
; RUN: opt -attributor -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=CHECK,OLD_PM
|
|
; RUN: opt -passes=attributor -attributor-disable=false -S < %s | FileCheck %s --check-prefixes=CHECK,NEW_PM
|
|
|
|
define i32 @test0(i32* %p) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test0
|
|
; CHECK-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P]], !range !0
|
|
; CHECK-NEXT: ret i32 [[A]]
|
|
;
|
|
%a = load i32, i32* %p, !range !0
|
|
ret i32 %a
|
|
}
|
|
|
|
define i32 @test0-range-check(i32* %p) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test0-range-check
|
|
; CHECK-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
; CHECK-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]])
|
|
; CHECK-SAME: !range !0
|
|
; CHECK-NEXT: ret i32 [[A]]
|
|
;
|
|
%a = tail call i32 @test0(i32* %p)
|
|
ret i32 %a
|
|
}
|
|
|
|
declare void @use3-dummy(i1, i1, i1)
|
|
define void @use3(i1, i1, i1) {
|
|
; CHECK-LABEL: define {{[^@]+}}@use3
|
|
; CHECK-SAME: (i1 [[TMP0:%.*]], i1 [[TMP1:%.*]], i1 [[TMP2:%.*]])
|
|
; CHECK-NEXT: tail call void @use3-dummy(i1 [[TMP0]], i1 [[TMP1]], i1 [[TMP2]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
tail call void @use3-dummy(i1 %0, i1 %1, i1 %2)
|
|
ret void
|
|
}
|
|
|
|
; TEST0 icmp test
|
|
define void @test0-icmp-check(i32* %p){
|
|
; CHECK-LABEL: define {{[^@]+}}@test0-icmp-check
|
|
; CHECK-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
; CHECK-NEXT: [[RET:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly [[P]])
|
|
; CHECK-SAME: !range !0
|
|
; CHECK-NEXT: [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
|
|
; CHECK-NEXT: [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
|
|
; CHECK-NEXT: [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
|
|
; CHECK-NEXT: tail call void @use3(i1 false, i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 false)
|
|
; CHECK-NEXT: [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
|
|
; CHECK-NEXT: [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
|
|
; CHECK-NEXT: [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
|
|
; CHECK-NEXT: tail call void @use3(i1 true, i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 true)
|
|
; CHECK-NEXT: [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
|
|
; CHECK-NEXT: [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
|
|
; CHECK-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_UGT_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 false)
|
|
; CHECK-NEXT: [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
|
|
; CHECK-NEXT: [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
|
|
; CHECK-NEXT: tail call void @use3(i1 false, i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_UGE_4]], i1 true, i1 false)
|
|
; CHECK-NEXT: [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
|
|
; CHECK-NEXT: [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
|
|
; CHECK-NEXT: tail call void @use3(i1 false, i1 false, i1 [[CMP_SGT_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 true)
|
|
; CHECK-NEXT: [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
|
|
; CHECK-NEXT: [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
|
|
; CHECK-NEXT: tail call void @use3(i1 false, i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_GTE_4]], i1 true, i1 true)
|
|
; CHECK-NEXT: [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
|
|
; CHECK-NEXT: [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
|
|
; CHECK-NEXT: tail call void @use3(i1 true, i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_SLT_4]], i1 false, i1 false)
|
|
; CHECK-NEXT: [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
|
|
; CHECK-NEXT: [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
|
|
; CHECK-NEXT: [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
|
|
; CHECK-NEXT: tail call void @use3(i1 true, i1 true, i1 [[CMP_LTE_3]])
|
|
; CHECK-NEXT: tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 false)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
; ret = [0, 10)
|
|
%ret = tail call i32 @test0(i32 *%p)
|
|
|
|
; ret = [0, 10), eq
|
|
%cmp-eq-1 = icmp eq i32 %ret, 10
|
|
%cmp-eq-2 = icmp eq i32 %ret, 9
|
|
%cmp-eq-3 = icmp eq i32 %ret, 8
|
|
%cmp-eq-4 = icmp eq i32 %ret, 1
|
|
%cmp-eq-5 = icmp eq i32 %ret, 0
|
|
%cmp-eq-6 = icmp eq i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-eq-1, i1 %cmp-eq-2, i1 %cmp-eq-3)
|
|
tail call void @use3(i1 %cmp-eq-4, i1 %cmp-eq-5, i1 %cmp-eq-6)
|
|
|
|
; ret = [0, 10), ne
|
|
%cmp-ne-1 = icmp ne i32 %ret, 10
|
|
%cmp-ne-2 = icmp ne i32 %ret, 9
|
|
%cmp-ne-3 = icmp ne i32 %ret, 8
|
|
%cmp-ne-4 = icmp ne i32 %ret, 1
|
|
%cmp-ne-5 = icmp ne i32 %ret, 0
|
|
%cmp-ne-6 = icmp ne i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-ne-1, i1 %cmp-ne-2, i1 %cmp-ne-3)
|
|
tail call void @use3(i1 %cmp-ne-4, i1 %cmp-ne-5, i1 %cmp-ne-6)
|
|
|
|
; ret = [0, 10), ugt
|
|
%cmp-ugt-1 = icmp ugt i32 %ret, 10
|
|
%cmp-ugt-2 = icmp ugt i32 %ret, 9
|
|
%cmp-ugt-3 = icmp ugt i32 %ret, 8
|
|
%cmp-ugt-4 = icmp ugt i32 %ret, 1
|
|
%cmp-ugt-5 = icmp ugt i32 %ret, 0
|
|
%cmp-ugt-6 = icmp ugt i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-ugt-1, i1 %cmp-ugt-2, i1 %cmp-ugt-3)
|
|
tail call void @use3(i1 %cmp-ugt-4, i1 %cmp-ugt-5, i1 %cmp-ugt-6)
|
|
|
|
; ret = [0, 10), uge
|
|
%cmp-uge-1 = icmp uge i32 %ret, 10
|
|
%cmp-uge-2 = icmp uge i32 %ret, 9
|
|
%cmp-uge-3 = icmp uge i32 %ret, 8
|
|
%cmp-uge-4 = icmp uge i32 %ret, 1
|
|
%cmp-uge-5 = icmp uge i32 %ret, 0
|
|
%cmp-uge-6 = icmp uge i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-uge-1, i1 %cmp-uge-2, i1 %cmp-uge-3)
|
|
tail call void @use3(i1 %cmp-uge-4, i1 %cmp-uge-5, i1 %cmp-uge-6)
|
|
|
|
; ret = [0, 10), sgt
|
|
%cmp-sgt-1 = icmp sgt i32 %ret, 10
|
|
%cmp-sgt-2 = icmp sgt i32 %ret, 9
|
|
%cmp-sgt-3 = icmp sgt i32 %ret, 8
|
|
%cmp-sgt-4 = icmp sgt i32 %ret, 1
|
|
%cmp-sgt-5 = icmp sgt i32 %ret, 0
|
|
%cmp-sgt-6 = icmp sgt i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-sgt-1, i1 %cmp-sgt-2, i1 %cmp-sgt-3)
|
|
tail call void @use3(i1 %cmp-sgt-4, i1 %cmp-sgt-5, i1 %cmp-sgt-6)
|
|
|
|
; ret = [0, 10), sge
|
|
%cmp-gte-1 = icmp sge i32 %ret, 10
|
|
%cmp-gte-2 = icmp sge i32 %ret, 9
|
|
%cmp-gte-3 = icmp sge i32 %ret, 8
|
|
%cmp-gte-4 = icmp sge i32 %ret, 1
|
|
%cmp-gte-5 = icmp sge i32 %ret, 0
|
|
%cmp-gte-6 = icmp sge i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-gte-1, i1 %cmp-gte-2, i1 %cmp-gte-3)
|
|
tail call void @use3(i1 %cmp-gte-4, i1 %cmp-gte-5, i1 %cmp-gte-6)
|
|
|
|
; ret = [0, 10), slt
|
|
%cmp-slt-1 = icmp slt i32 %ret, 10
|
|
%cmp-slt-2 = icmp slt i32 %ret, 9
|
|
%cmp-slt-3 = icmp slt i32 %ret, 8
|
|
%cmp-slt-4 = icmp slt i32 %ret, 1
|
|
%cmp-slt-5 = icmp slt i32 %ret, 0
|
|
%cmp-slt-6 = icmp slt i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-slt-1, i1 %cmp-slt-2, i1 %cmp-slt-3)
|
|
tail call void @use3(i1 %cmp-slt-4, i1 %cmp-slt-5, i1 %cmp-slt-6)
|
|
|
|
; ret = [0, 10), sle
|
|
%cmp-lte-1 = icmp sle i32 %ret, 10
|
|
%cmp-lte-2 = icmp sle i32 %ret, 9
|
|
%cmp-lte-3 = icmp sle i32 %ret, 8
|
|
%cmp-lte-4 = icmp sle i32 %ret, 1
|
|
%cmp-lte-5 = icmp sle i32 %ret, 0
|
|
%cmp-lte-6 = icmp sle i32 %ret, -1
|
|
tail call void @use3(i1 %cmp-lte-1, i1 %cmp-lte-2, i1 %cmp-lte-3)
|
|
tail call void @use3(i1 %cmp-lte-4, i1 %cmp-lte-5, i1 %cmp-lte-6)
|
|
|
|
ret void
|
|
}
|
|
define i32 @test1(i32* %p) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test1
|
|
; CHECK-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]])
|
|
; CHECK-NEXT: [[LOAD_10_100:%.*]] = load i32, i32* [[P]], !range !1
|
|
; CHECK-NEXT: [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10
|
|
; CHECK-NEXT: [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10
|
|
; CHECK-NEXT: ret i32 [[MUL_10_THEN_200_1091]]
|
|
;
|
|
%load-10-100 = load i32, i32* %p, !range !1
|
|
%add-10-then-20-110 = add i32 %load-10-100, 10
|
|
%mul-10-then-200-1091 = mul i32 %add-10-then-20-110, 10
|
|
ret i32 %mul-10-then-200-1091
|
|
}
|
|
|
|
define i1 @test1-check(i32* %p) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test1-check
|
|
; CHECK-SAME: (i32* nocapture nofree readonly [[P:%.*]])
|
|
; CHECK-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly [[P]])
|
|
; CHECK-SANME: !range !2
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
;
|
|
%res = tail call i32 @test1(i32* %p)
|
|
%cmp = icmp eq i32 %res, 500
|
|
ret i1 %cmp
|
|
}
|
|
|
|
; TEST2
|
|
; int test2(int *p) { return *p == 0 ? 4 : 3; }
|
|
; int test2_check(int *p) {
|
|
; int call = test2(p);
|
|
; if (call == 5) {
|
|
; // dead block
|
|
; return 2;
|
|
; } else {
|
|
; return 3;
|
|
; }
|
|
; }
|
|
|
|
define i32 @test2(i32* %p) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test2
|
|
; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 4
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
|
|
; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3
|
|
; CHECK-NEXT: ret i32 [[COND]]
|
|
;
|
|
entry:
|
|
%0 = load i32, i32* %p, align 4
|
|
%tobool = icmp eq i32 %0, 0
|
|
%cond = select i1 %tobool, i32 4, i32 3
|
|
ret i32 %cond
|
|
}
|
|
|
|
define i32 @test2_check(i32* %p) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test2_check
|
|
; CHECK-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[IF_THEN:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: br label [[RETURN:%.*]]
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: unreachable
|
|
; CHECK: return:
|
|
; CHECK-NEXT: ret i32 2
|
|
;
|
|
entry:
|
|
%call = tail call i32 @test2(i32* %p)
|
|
%cmp = icmp slt i32 %call, 5
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
|
|
if.then: ; preds = %entry
|
|
br label %return
|
|
|
|
if.end: ; preds = %entry
|
|
br label %return
|
|
|
|
return: ; preds = %if.end, %if.then
|
|
%retval.0 = phi i32 [ 2, %if.then ], [ 3, %if.end ]
|
|
ret i32 %retval.0
|
|
}
|
|
|
|
; TEST 3 SECV test
|
|
|
|
; void unkown();
|
|
; int r1(unsigned int u){
|
|
; int sum = 0;
|
|
; for(int i = 0; i<100;i++){
|
|
; sum += i;
|
|
; }
|
|
; // sum = 50 * 49 / 2
|
|
; if(sum > 10000){
|
|
; // dead block
|
|
; return 20;
|
|
; }else {
|
|
; return 10;
|
|
; }
|
|
; }
|
|
; void f1(int u){
|
|
; if(r1(u) > 15){
|
|
; // deadblock
|
|
; unkown();
|
|
; }else {
|
|
; return;
|
|
; }
|
|
; }
|
|
|
|
declare dso_local void @unkown()
|
|
|
|
define internal i32 @r1(i32) local_unnamed_addr {
|
|
; OLD_PM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr
|
|
; OLD_PM-NEXT: br label [[TMP4:%.*]]
|
|
; OLD_PM: 1:
|
|
; OLD_PM-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000
|
|
; OLD_PM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]]
|
|
; OLD_PM: 3:
|
|
; OLD_PM-NEXT: ret i32 20
|
|
; OLD_PM: f:
|
|
; OLD_PM-NEXT: ret i32 10
|
|
; OLD_PM: 4:
|
|
; OLD_PM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ]
|
|
; OLD_PM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ]
|
|
; OLD_PM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]]
|
|
; OLD_PM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1
|
|
; OLD_PM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
|
|
; OLD_PM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]]
|
|
;
|
|
; NEW_PM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr
|
|
; NEW_PM-NEXT: br label [[TMP3:%.*]]
|
|
; NEW_PM: 1:
|
|
; NEW_PM-NEXT: br label [[F:%.*]]
|
|
; NEW_PM: 2:
|
|
; NEW_PM-NEXT: unreachable
|
|
; NEW_PM: f:
|
|
; NEW_PM-NEXT: ret i32 10
|
|
; NEW_PM: 3:
|
|
; NEW_PM-NEXT: [[TMP4:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP7:%.*]], [[TMP3]] ]
|
|
; NEW_PM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP6:%.*]], [[TMP3]] ]
|
|
; NEW_PM-NEXT: [[TMP6]] = add nuw nsw i32 [[TMP4]], [[TMP5]]
|
|
; NEW_PM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP4]], 1
|
|
; NEW_PM-NEXT: [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 100
|
|
; NEW_PM-NEXT: br i1 [[TMP8]], label [[TMP1:%.*]], label [[TMP3]]
|
|
;
|
|
br label %5
|
|
|
|
2: ; preds = %5
|
|
%3 = icmp sgt i32 %8, 10000
|
|
br i1 %3, label %4, label %f
|
|
4:
|
|
ret i32 20
|
|
f:
|
|
ret i32 10
|
|
5: ; preds = %5, %1
|
|
%6 = phi i32 [ 0, %1 ], [ %9, %5 ]
|
|
%7 = phi i32 [ 0, %1 ], [ %8, %5 ]
|
|
%8 = add nuw nsw i32 %6, %7
|
|
%9 = add nuw nsw i32 %6, 1
|
|
%10 = icmp eq i32 %9, 100
|
|
br i1 %10, label %2, label %5
|
|
}
|
|
|
|
define void @f1(i32){
|
|
; OLD_PM-LABEL: define {{[^@]+}}@f1
|
|
; OLD_PM-SAME: (i32 [[TMP0:%.*]])
|
|
; OLD_PM-NEXT: [[TMP2:%.*]] = tail call i32 @r1()
|
|
; OLD_PM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15
|
|
; OLD_PM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
|
|
; OLD_PM: 4:
|
|
; OLD_PM-NEXT: tail call void @unkown()
|
|
; OLD_PM-NEXT: br label [[TMP5]]
|
|
; OLD_PM: 5:
|
|
; OLD_PM-NEXT: ret void
|
|
;
|
|
; NEW_PM-LABEL: define {{[^@]+}}@f1
|
|
; NEW_PM-SAME: (i32 [[TMP0:%.*]])
|
|
; NEW_PM-NEXT: [[TMP2:%.*]] = tail call i32 @r1()
|
|
; NEW_PM-NEXT: br label [[TMP4:%.*]]
|
|
; NEW_PM: 3:
|
|
; NEW_PM-NEXT: unreachable
|
|
; NEW_PM: 4:
|
|
; NEW_PM-NEXT: ret void
|
|
;
|
|
%2 = tail call i32 @r1(i32 %0)
|
|
%3 = icmp sgt i32 %2, 15
|
|
br i1 %3, label %4, label %5
|
|
|
|
4: ; preds = %1
|
|
tail call void @unkown()
|
|
br label %5
|
|
|
|
5: ; preds = %1, %4
|
|
ret void
|
|
}
|
|
|
|
; TEST4 LVI test
|
|
|
|
; f1
|
|
; int test4-f1(int u){
|
|
; if(u>=0) {
|
|
; return u;
|
|
; }else{
|
|
; return 0;
|
|
; }
|
|
; }
|
|
define dso_local i32 @test4-f1(i32 %u) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-f1
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
; CHECK: return:
|
|
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
|
;
|
|
; FIXME: RETVAL_0 >= 0
|
|
entry:
|
|
%cmp = icmp sgt i32 %u, -1
|
|
br i1 %cmp, label %if.then, label %return
|
|
|
|
if.then: ; preds = %entry
|
|
br label %return
|
|
|
|
return: ; preds = %entry, %if.then
|
|
%retval.0 = phi i32 [ %u, %if.then ], [ 0, %entry ]
|
|
ret i32 %retval.0
|
|
}
|
|
|
|
|
|
define dso_local i32 @test4-g1(i32 %u) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-g1
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]])
|
|
; CHECK-NEXT: ret i32 [[CALL]]
|
|
;
|
|
; FIXME: %call should have range [0, inf]
|
|
|
|
entry:
|
|
%call = tail call i32 @test4-f1(i32 %u)
|
|
ret i32 %call
|
|
}
|
|
|
|
; f2
|
|
; int test4-f1(int u){
|
|
; if(u>-1) {
|
|
; return u+1;
|
|
; }else{
|
|
; return 1;
|
|
; }
|
|
; }
|
|
define dso_local i32 @test4-f2(i32 %u) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-f2
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1
|
|
; CHECK-NEXT: br label [[RETURN:%.*]]
|
|
; CHECK: if.else:
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
; CHECK: return:
|
|
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ]
|
|
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
|
;
|
|
entry:
|
|
%cmp = icmp sgt i32 %u, -1
|
|
br i1 %cmp, label %if.then, label %if.else
|
|
|
|
if.then: ; preds = %entry
|
|
%add = add nuw nsw i32 %u, 1
|
|
br label %return
|
|
|
|
if.else: ; preds = %entry
|
|
br label %return
|
|
|
|
return: ; preds = %if.else, %if.then
|
|
%retval.0 = phi i32 [ %add, %if.then ], [ 1, %if.else ]
|
|
ret i32 %retval.0
|
|
}
|
|
|
|
|
|
define dso_local i32 @test4-g2(i32 %u) {
|
|
; CHECK-LABEL: define {{[^@]+}}@test4-g2
|
|
; CHECK-SAME: (i32 [[U:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]])
|
|
; CHECK-NEXT: ret i32 [[CALL]]
|
|
;
|
|
; FIXME: %call should have range [1, inf]
|
|
entry:
|
|
%call = tail call i32 @test4-f2(i32 %u)
|
|
ret i32 %call
|
|
}
|
|
|
|
define dso_local i32 @test-5() {
|
|
; CHECK-LABEL: define {{[^@]+}}@test-5()
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = call i32 @rec(i32 0), !range !3
|
|
; CHECK-NEXT: ret i32 [[CALL]]
|
|
;
|
|
entry:
|
|
%call = call i32 @rec(i32 0)
|
|
ret i32 %call
|
|
}
|
|
define internal i32 @rec(i32 %depth) {
|
|
; CHECK-LABEL: define {{[^@]+}}@rec
|
|
; CHECK-SAME: (i32 [[DEPTH:%.*]])
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo(i32 [[DEPTH]])
|
|
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[CALL]], 0
|
|
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
|
|
; CHECK: if.then:
|
|
; CHECK-NEXT: br label [[RETURN:%.*]]
|
|
; CHECK: if.end:
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DEPTH]], 10
|
|
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END3:%.*]]
|
|
; CHECK: if.then1:
|
|
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[DEPTH]], 1
|
|
; CHECK-NEXT: [[CALL2:%.*]] = call i32 @rec(i32 [[ADD]])
|
|
; CHECK-NEXT: br label [[IF_END3]]
|
|
; CHECK: if.end3:
|
|
; CHECK-NEXT: br label [[RETURN]]
|
|
; CHECK: return:
|
|
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[IF_END3]] ]
|
|
; CHECK-NEXT: ret i32 [[RETVAL_0]]
|
|
;
|
|
entry:
|
|
%call = call i32 @foo(i32 %depth)
|
|
%tobool = icmp ne i32 %call, 0
|
|
br i1 %tobool, label %if.then, label %if.end
|
|
|
|
if.then: ; preds = %entry
|
|
br label %return
|
|
|
|
if.end: ; preds = %entry
|
|
%cmp = icmp slt i32 %depth, 10
|
|
br i1 %cmp, label %if.then1, label %if.end3
|
|
|
|
if.then1: ; preds = %if.end
|
|
%add = add nsw i32 %depth, 1
|
|
%call2 = call i32 @rec(i32 %add)
|
|
br label %if.end3
|
|
|
|
if.end3: ; preds = %if.then1, %if.end
|
|
br label %return
|
|
|
|
return: ; preds = %if.end3, %if.then
|
|
%retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.end3 ]
|
|
ret i32 %retval.0
|
|
}
|
|
declare dso_local i32 @foo(i32)
|
|
|
|
!0 = !{i32 0, i32 10}
|
|
!1 = !{i32 10, i32 100}
|
|
;CHECK: !0 = !{i32 0, i32 10}
|
|
;CHECK-NEXT: !1 = !{i32 10, i32 100}
|
|
;CHECK-NEXT: !2 = !{i32 200, i32 1091}
|
|
|