• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
2; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,irce' -S < %s 2>&1 | FileCheck %s
3
4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"
5target triple = "x86_64-unknown-linux-gnu"
6
7; IRCE should fail here because the preheader's exiting value is a phi from the
8; loop, and this value cannot be expanded at loop's preheader.
9
10; CHECK-NOT:   irce: in function test_01: constrained Loop
11; CHECK-NOT:   irce: in function test_02: constrained Loop
12; CHECK-LABEL: irce: in function test_03: constrained Loop
13
14define void @test_01() {
15
16; CHECK-NOT:   irce: in function test_01: constrained Loop
17
18; CHECK-LABEL: test_01
19; CHECK-NOT:   preloop
20; CHECK-NOT:   postloop
21; CHECK-NOT:   br i1 false
22; CHECK-NOT:   br i1 true
23
24entry:
25  br label %loop
26
27exit:                                       ; preds = %guarded, %loop
28  ret void
29
30loop:                                      ; preds = %guarded, %entry
31  %iv = phi i64 [ 380, %entry ], [ %limit, %guarded ]
32  %bad_phi = phi i32 [ 3, %entry ], [ %bad_phi.next, %guarded ]
33  %bad_phi.next = add nuw nsw i32 %bad_phi, 1
34  %iv.next = add nuw nsw i64 %iv, 1
35  %rc = icmp slt i64 %iv.next, 5
36  br i1 %rc, label %guarded, label %exit
37
38guarded:
39  %limit = add nsw i64 %iv, -1
40  %tmp5 = add nuw nsw i32 %bad_phi, 8
41  %tmp6 = zext i32 %tmp5 to i64
42  %tmp7 = icmp eq i64 %limit, %tmp6
43  br i1 %tmp7, label %exit, label %loop
44}
45
46; This test should fail because we are unable to prove that the division is
47; safe to expand it to preheader: if we exit by maybe_exit condition, it is
48; unsafe to execute it there.
49
50define void @test_02(i64* %p1, i64* %p2, i1 %maybe_exit) {
51
52; CHECK-LABEL: test_02
53; CHECK-NOT:   preloop
54; CHECK-NOT:   postloop
55; CHECK-NOT:   br i1 false
56; CHECK-NOT:   br i1 true
57
58
59entry:
60  %num = load i64, i64* %p1, align 4, !range !0
61  %denom = load i64, i64* %p2, align 4, !range !0
62  br label %loop
63
64exit:                                       ; preds = %guarded, %loop
65  ret void
66
67loop:                                      ; preds = %guarded, %entry
68  %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ]
69  %iv.next = add nuw nsw i64 %iv, 1
70  br i1 %maybe_exit, label %range_check, label %exit
71
72range_check:
73  %div_result = udiv i64 %num, %denom
74  %rc = icmp slt i64 %iv.next, %div_result
75  br i1 %rc, label %guarded, label %exit
76
77guarded:
78  %gep = getelementptr i64, i64* %p1, i64 %iv.next
79  %loaded = load i64, i64* %gep, align 4
80  %tmp7 = icmp slt i64 %iv.next, 1000
81  br i1 %tmp7, label %loop, label %exit
82}
83
84define void @test_03(i64* %p1, i64* %p2, i1 %maybe_exit) {
85
86; Show that IRCE would hit test_02 if the division was safe (denom not zero).
87
88; CHECK-LABEL: test_03
89; CHECK:       entry:
90; CHECK-NEXT:    %num = load i64, i64* %p1, align 4
91; CHECK-NEXT:    [[DIV:%[^ ]+]] = udiv i64 %num, 13
92; CHECK-NEXT:    [[DIV_MINUS_1:%[^ ]+]] = add nsw i64 [[DIV]], -1
93; CHECK-NEXT:    [[COMP1:%[^ ]+]] = icmp sgt i64 [[DIV_MINUS_1]], 0
94; CHECK-NEXT:    %exit.mainloop.at = select i1 [[COMP1]], i64 [[DIV_MINUS_1]], i64 0
95; CHECK-NEXT:    [[COMP2:%[^ ]+]] = icmp slt i64 0, %exit.mainloop.at
96; CHECK-NEXT:    br i1 [[COMP2]], label %loop.preheader, label %main.pseudo.exit
97; CHECK-NOT:     preloop
98; CHECK:       loop:
99; CHECK-NEXT:    %iv = phi i64 [ %iv.next, %guarded ], [ 0, %loop.preheader ]
100; CHECK-NEXT:    %iv.next = add nuw nsw i64 %iv, 1
101; CHECK-NEXT:    %rc = icmp slt i64 %iv.next, %div_result
102; CHECK-NEXT:    %or.cond = and i1 %maybe_exit, true
103; CHECK-NEXT:    br i1 %or.cond, label %guarded, label %exit.loopexit1
104; CHECK:       guarded:
105; CHECK-NEXT:    %gep = getelementptr i64, i64* %p1, i64 %iv.next
106; CHECK-NEXT:    %loaded = load i64, i64* %gep, align 4
107; CHECK-NEXT:    %tmp7 = icmp slt i64 %iv.next, 1000
108; CHECK-NEXT:    [[EXIT_MAIN_LOOP:%[^ ]+]] = icmp slt i64 %iv.next, %exit.mainloop.at
109; CHECK-NEXT:    br i1 [[EXIT_MAIN_LOOP]], label %loop, label %main.exit.selector
110; CHECK:       postloop
111
112entry:
113  %num = load i64, i64* %p1, align 4, !range !0
114  br label %loop
115
116exit:                                       ; preds = %guarded, %loop
117  ret void
118
119loop:                                      ; preds = %guarded, %entry
120  %iv = phi i64 [ 0, %entry ], [ %iv.next, %guarded ]
121  %iv.next = add nuw nsw i64 %iv, 1
122  br i1 %maybe_exit, label %range_check, label %exit
123
124range_check:
125  %div_result = udiv i64 %num, 13
126  %rc = icmp slt i64 %iv.next, %div_result
127  br i1 %rc, label %guarded, label %exit
128
129guarded:
130  %gep = getelementptr i64, i64* %p1, i64 %iv.next
131  %loaded = load i64, i64* %gep, align 4
132  %tmp7 = icmp slt i64 %iv.next, 1000
133  br i1 %tmp7, label %loop, label %exit
134}
135
136!0 = !{i64 0, i64 100}
137