1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
; RUN: opt < %s -loop-reduce -S | FileCheck %s
; LSR shouldn't consider %t8 to be an interesting user of %t6, and it
; should be able to form pretty GEPs.
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
; Check that LSR hoists %t2 computation outside the loop,
; folds %t3's add within the address
; and uses the induction variable (%t4) to access the right element.
define void @test(ptr %ptr.i8, ptr %ptr.float) {
; CHECK-LABEL: define void @test
; CHECK-SAME: (ptr [[PTR_I8:%.*]], ptr [[PTR_FLOAT:%.*]]) {
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[BB3:%.*]]
; CHECK: bb1:
; CHECK-NEXT: br i1 true, label [[BB10:%.*]], label [[BB2:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[T:%.*]] = add i64 [[T4:%.*]], 1
; CHECK-NEXT: br label [[BB3]]
; CHECK: bb3:
; CHECK-NEXT: [[T4]] = phi i64 [ [[T]], [[BB2]] ], [ 0, [[BB:%.*]] ]
; CHECK-NEXT: br label [[BB1:%.*]]
; CHECK: bb10:
; CHECK-NEXT: [[T7:%.*]] = icmp eq i64 [[T4]], 0
; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i8, ptr [[PTR_I8]], i64 [[T4]]
; CHECK-NEXT: br label [[BB14:%.*]]
; CHECK: bb14:
; CHECK-NEXT: store i8 undef, ptr [[SCEVGEP]], align 1
; CHECK-NEXT: [[T6:%.*]] = load ptr, ptr [[PTR_FLOAT]], align 8
; CHECK-NEXT: [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[T6]], i64 16
; CHECK-NEXT: [[SCEVGEP2:%.*]] = getelementptr i8, ptr [[SCEVGEP1]], i64 [[T4]]
; CHECK-NEXT: store i8 undef, ptr [[SCEVGEP2]], align 1
; CHECK-NEXT: br label [[BB14]]
;
bb:
br label %bb3
bb1: ; preds = %bb3
br i1 true, label %bb10, label %bb2
bb2: ; preds = %bb1
%t = add i64 %t4, 1 ; <i64> [#uses=1]
br label %bb3
bb3: ; preds = %bb2, %bb
%t4 = phi i64 [ %t, %bb2 ], [ 0, %bb ] ; <i64> [#uses=3]
br label %bb1
bb10: ; preds = %bb9
%t7 = icmp eq i64 %t4, 0 ; <i1> [#uses=1]
%t3 = add i64 %t4, 16 ; <i64> [#uses=1]
br label %bb14
bb14: ; preds = %bb14, %bb10
%t2 = getelementptr inbounds i8, ptr %ptr.i8, i64 %t4 ; <ptr> [#uses=1]
store i8 undef, ptr %t2
%t6 = load ptr, ptr %ptr.float
%t9 = getelementptr inbounds i8, ptr %t6, i64 %t3 ; <ptr> [#uses=1]
store i8 undef, ptr %t9
br label %bb14
}
; Check that induction variable is initialized to -2.
; IVNEXT covers the uses of %i0 and %t0.
; Therefore, %t0 should be removed and the critical edge must be split.
define fastcc void @TransformLine() nounwind {
; CHECK-LABEL: define fastcc void @TransformLine
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[LOOP0:%.*]]
; CHECK: loop0:
; CHECK-NEXT: [[LSR_IV:%.*]] = phi i32 [ [[LSR_IV_NEXT:%.*]], [[LOOP0]] ], [ -2, [[BB:%.*]] ]
; CHECK-NEXT: [[LSR_IV_NEXT]] = add nuw nsw i32 [[LSR_IV]], 1
; CHECK-NEXT: br i1 false, label [[LOOP0]], label [[BB0:%.*]]
; CHECK: bb0:
; CHECK-NEXT: br label [[LOOP1:%.*]]
; CHECK: loop1:
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ 0, [[BB0]] ], [ [[I1_NEXT:%.*]], [[BB5:%.*]] ]
; CHECK-NEXT: br i1 false, label [[BB2:%.*]], label [[LOOP1_BB6_CRIT_EDGE:%.*]]
; CHECK: bb2:
; CHECK-NEXT: br i1 true, label [[BB6SPLITSPLIT:%.*]], label [[BB5]]
; CHECK: bb5:
; CHECK-NEXT: [[I1_NEXT]] = add i32 [[I1]], 1
; CHECK-NEXT: br i1 true, label [[BB5_BB6SPLIT_CRIT_EDGE:%.*]], label [[LOOP1]]
; CHECK: bb5.bb6split_crit_edge:
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LSR_IV_NEXT]], [[I1_NEXT]]
; CHECK-NEXT: br label [[BB6SPLIT:%.*]]
; CHECK: bb6splitsplit:
; CHECK-NEXT: br label [[BB6SPLIT]]
; CHECK: bb6split:
; CHECK-NEXT: [[P8_PH:%.*]] = phi i32 [ [[TMP0]], [[BB5_BB6SPLIT_CRIT_EDGE]] ], [ undef, [[BB6SPLITSPLIT]] ]
; CHECK-NEXT: [[P9_PH:%.*]] = phi i32 [ undef, [[BB5_BB6SPLIT_CRIT_EDGE]] ], [ [[I1]], [[BB6SPLITSPLIT]] ]
; CHECK-NEXT: br label [[BB6:%.*]]
; CHECK: loop1.bb6_crit_edge:
; CHECK-NEXT: [[I1_LCSSA:%.*]] = phi i32 [ [[I1]], [[LOOP1]] ]
; CHECK-NEXT: br label [[BB6]]
; CHECK: bb6:
; CHECK-NEXT: [[P8:%.*]] = phi i32 [ undef, [[LOOP1_BB6_CRIT_EDGE]] ], [ [[P8_PH]], [[BB6SPLIT]] ]
; CHECK-NEXT: [[P9:%.*]] = phi i32 [ [[I1_LCSSA]], [[LOOP1_BB6_CRIT_EDGE]] ], [ [[P9_PH]], [[BB6SPLIT]] ]
; CHECK-NEXT: unreachable
;
bb:
br label %loop0
loop0: ; preds = %loop0, %bb
%i0 = phi i32 [ %i0.next, %loop0 ], [ 0, %bb ] ; <i32> [#uses=2]
%i0.next = add i32 %i0, 1 ; <i32> [#uses=1]
br i1 false, label %loop0, label %bb0
bb0: ; preds = %loop0
br label %loop1
loop1: ; preds = %bb5, %bb0
%i1 = phi i32 [ 0, %bb0 ], [ %i1.next, %bb5 ] ; <i32> [#uses=4]
%t0 = add i32 %i0, %i1 ; <i32> [#uses=1]
br i1 false, label %bb2, label %bb6
bb2: ; preds = %loop1
br i1 true, label %bb6, label %bb5
bb5: ; preds = %bb2
%i1.next = add i32 %i1, 1 ; <i32> [#uses=1]
br i1 true, label %bb6, label %loop1
bb6: ; preds = %bb5, %bb2, %loop1
%p8 = phi i32 [ %t0, %bb5 ], [ undef, %loop1 ], [ undef, %bb2 ] ; <i32> [#uses=0]
%p9 = phi i32 [ undef, %bb5 ], [ %i1, %loop1 ], [ %i1, %bb2 ] ; <i32> [#uses=0]
unreachable
}
|