1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -loop-reduce -S | FileCheck %s
3; REQUIRES: x86-registered-target
4
5target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
6target triple = "x86_64-unknown-linux-gnu"
7
8; FIXME: iv.next is supposed to be inserted in the backedge.
9define i32 @test_01(i32* %p, i64 %len, i32 %x) {
10; CHECK-LABEL: @test_01(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
13; CHECK-NEXT:    br label [[LOOP:%.*]]
14; CHECK:       loop:
15; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
16; CHECK-NEXT:    [[IV_NEXT]] = add nsw i64 [[IV]], -1
17; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[IV]], 0
18; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
19; CHECK:       backedge:
20; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[IV]]
21; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
22; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
23; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
24; CHECK:       exit:
25; CHECK-NEXT:    ret i32 -1
26; CHECK:       failure:
27; CHECK-NEXT:    unreachable
28;
29entry:
30  br label %loop
31
32loop:                                             ; preds = %backedge, %entry
33  %iv = phi i64 [ %iv.next, %backedge ], [ %len, %entry ]
34  %iv.next = add nsw i64 %iv, -1
35  %cond_1 = icmp eq i64 %iv, 0
36  br i1 %cond_1, label %exit, label %backedge
37
38backedge:                                         ; preds = %loop
39  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next
40  %loaded = load atomic i32, i32* %addr unordered, align 4
41  %cond_2 = icmp eq i32 %loaded, %x
42  br i1 %cond_2, label %failure, label %loop
43
44exit:                                             ; preds = %loop
45  ret i32 -1
46
47failure:                                          ; preds = %backedge
48  unreachable
49}
50
51define i32 @test_02(i32* %p, i64 %len, i32 %x) {
52; CHECK-LABEL: @test_02(
53; CHECK-NEXT:  entry:
54; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
55; CHECK-NEXT:    br label [[LOOP:%.*]]
56; CHECK:       loop:
57; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
58; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[LSR_IV]], 0
59; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
60; CHECK:       backedge:
61; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[LSR_IV]]
62; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
63; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
64; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
65; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
66; CHECK:       exit:
67; CHECK-NEXT:    ret i32 -1
68; CHECK:       failure:
69; CHECK-NEXT:    unreachable
70;
71entry:
72  %start = add i64 %len, -1
73  br label %loop
74
75loop:                                             ; preds = %backedge, %entry
76  %iv = phi i64 [ %iv.next, %backedge ], [ %start, %entry ]
77  %iv.next = add nsw i64 %iv, -1
78  %iv.offset = add i64 %iv, 1
79  %iv.next.offset = add i64 %iv.next, 1
80  %cond_1 = icmp eq i64 %iv.offset, 0
81  br i1 %cond_1, label %exit, label %backedge
82
83backedge:                                         ; preds = %loop
84  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next.offset
85  %loaded = load atomic i32, i32* %addr unordered, align 4
86  %cond_2 = icmp eq i32 %loaded, %x
87  br i1 %cond_2, label %failure, label %loop
88
89exit:                                             ; preds = %loop
90  ret i32 -1
91
92failure:                                          ; preds = %backedge
93  unreachable
94}
95
96define i32 @test_03(i32* %p, i64 %len, i32 %x) {
97; CHECK-LABEL: @test_03(
98; CHECK-NEXT:  entry:
99; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 -1
100; CHECK-NEXT:    br label [[LOOP:%.*]]
101; CHECK:       loop:
102; CHECK-NEXT:    [[LSR_IV:%.*]] = phi i64 [ [[LSR_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[LEN:%.*]], [[ENTRY:%.*]] ]
103; CHECK-NEXT:    [[COND_1:%.*]] = icmp eq i64 [[LSR_IV]], 0
104; CHECK-NEXT:    br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]]
105; CHECK:       backedge:
106; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i32, i32* [[SCEVGEP]], i64 [[LSR_IV]]
107; CHECK-NEXT:    [[LOADED:%.*]] = load atomic i32, i32* [[SCEVGEP1]] unordered, align 4
108; CHECK-NEXT:    [[COND_2:%.*]] = icmp eq i32 [[LOADED]], [[X:%.*]]
109; CHECK-NEXT:    [[LSR_IV_NEXT]] = add i64 [[LSR_IV]], -1
110; CHECK-NEXT:    br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]]
111; CHECK:       exit:
112; CHECK-NEXT:    ret i32 -1
113; CHECK:       failure:
114; CHECK-NEXT:    unreachable
115;
116entry:
117  %start = add i64 %len, -100
118  br label %loop
119
120loop:                                             ; preds = %backedge, %entry
121  %iv = phi i64 [ %iv.next, %backedge ], [ %start, %entry ]
122  %iv.next = add nsw i64 %iv, -1
123  %iv.offset = add i64 %iv, 100
124  %iv.next.offset = add i64 %iv.next, 100
125  %cond_1 = icmp eq i64 %iv.offset, 0
126  br i1 %cond_1, label %exit, label %backedge
127
128backedge:                                         ; preds = %loop
129  %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next.offset
130  %loaded = load atomic i32, i32* %addr unordered, align 4
131  %cond_2 = icmp eq i32 %loaded, %x
132  br i1 %cond_2, label %failure, label %loop
133
134exit:                                             ; preds = %loop
135  ret i32 -1
136
137failure:                                          ; preds = %backedge
138  unreachable
139}
140