• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -S -indvars < %s | FileCheck %s
2
3; Check that SCEV is able to recognize and use guards to prove
4; conditions gaurding loop entries and backedges.  This isn't intended
5; to be a comprehensive test of SCEV's simplification capabilities,
6; tests directly testing e.g. if SCEV can elide a sext should go
7; elsewhere.
8
9target datalayout = "n8:16:32:64"
10
11declare void @llvm.experimental.guard(i1, ...)
12
13define void @test_1(i1* %cond_buf, i32* %len_buf) {
14; CHECK-LABEL: @test_1(
15entry:
16  %len = load i32, i32* %len_buf, !range !{i32 1, i32 2147483648}
17  br label %loop
18
19loop:
20; CHECK: loop:
21; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
22; CHECK:  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
23; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
24; CHECK: leave:
25
26  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
27  %iv.inc = add i32 %iv, 1
28
29  %iv.cmp = icmp slt i32 %iv, %len
30  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
31
32  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
33  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
34
35  %becond = load volatile i1, i1* %cond_buf
36  br i1 %becond, label %loop, label %leave
37
38leave:
39  ret void
40}
41
42define void @test_2(i32 %n, i32* %len_buf) {
43; CHECK-LABEL: @test_2(
44; CHECK:  [[LEN_SEXT:%[^ ]+]] = sext i32 %len to i64
45; CHECK:  br label %loop
46
47entry:
48  %len = load i32, i32* %len_buf, !range !{i32 0, i32 2147483648}
49  br label %loop
50
51loop:
52; CHECK: loop:
53; CHECK:  %indvars.iv = phi i64 [ %indvars.iv.next, %loop ], [ 0, %entry ]
54; CHECK:  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
55; CHECK:  %iv.inc.cmp = icmp slt i64 %indvars.iv.next, [[LEN_SEXT]]
56; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
57; CHECK: leave:
58
59  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
60  %iv.inc = add i32 %iv, 1
61
62  %iv.sext = sext i32 %iv to i64
63
64  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
65  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
66
67  %becond = icmp ne i32 %iv, %n
68  br i1 %becond, label %loop, label %leave
69
70leave:
71  ret void
72}
73
74define void @test_3(i1* %cond_buf, i32* %len_buf) {
75; CHECK-LABEL: @test_3(
76
77entry:
78  %len = load i32, i32* %len_buf
79  %entry.cond = icmp sgt i32 %len, 0
80  call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
81  br label %loop
82
83loop:
84; CHECK: loop:
85; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
86; CHECK:  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
87; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
88; CHECK: leave:
89  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
90  %iv.inc = add i32 %iv, 1
91
92  %iv.cmp = icmp slt i32 %iv, %len
93  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
94
95  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
96  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
97
98  %becond = load volatile i1, i1* %cond_buf
99  br i1 %becond, label %loop, label %leave
100
101leave:
102  ret void
103}
104
105define void @test_4(i1* %cond_buf, i32* %len_buf) {
106; CHECK-LABEL: @test_4(
107
108entry:
109  %len = load i32, i32* %len_buf
110  %entry.cond = icmp sgt i32 %len, 0
111  call void(i1, ...) @llvm.experimental.guard(i1 %entry.cond) [ "deopt"() ]
112  br label %loop
113
114loop:
115  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]
116  %iv.inc = add i32 %iv, 1
117
118  %cond = load volatile i1, i1* %cond_buf
119  br i1 %cond, label %left, label %be
120
121left:
122  ; Does not dominate the backedge, so cannot be used in the inductive proof
123  %iv.inc.cmp = icmp slt i32 %iv.inc, %len
124  call void(i1, ...) @llvm.experimental.guard(i1 %iv.inc.cmp) [ "deopt"() ]
125  br label %be
126
127be:
128; CHECK: be:
129; CHECK-NEXT:  %iv.cmp = icmp slt i32 %iv, %len
130; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
131; CHECK: leave:
132
133  %iv.cmp = icmp slt i32 %iv, %len
134  call void(i1, ...) @llvm.experimental.guard(i1 %iv.cmp) [ "deopt"() ]
135
136  %becond = load volatile i1, i1* %cond_buf
137  br i1 %becond, label %loop, label %leave
138
139leave:
140  ret void
141}
142