• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -nary-reassociate -S | FileCheck %s
2
3target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
4
5declare void @foo(i32)
6
7; foo(a + c);
8; foo((a + (b + c));
9;   =>
10; t = a + c;
11; foo(t);
12; foo(t + b);
13define void @left_reassociate(i32 %a, i32 %b, i32 %c) {
14; CHECK-LABEL: @left_reassociate(
15  %1 = add i32 %a, %c
16; CHECK: [[BASE:%[a-zA-Z0-9]+]] = add i32 %a, %c
17  call void @foo(i32 %1)
18  %2 = add i32 %b, %c
19  %3 = add i32 %a, %2
20; CHECK: add i32 [[BASE]], %b
21  call void @foo(i32 %3)
22  ret void
23}
24
25; foo(a + c);
26; foo((a + b) + c);
27;   =>
28; t = a + c;
29; foo(t);
30; foo(t + b);
31define void @right_reassociate(i32 %a, i32 %b, i32 %c) {
32; CHECK-LABEL: @right_reassociate(
33  %1 = add i32 %a, %c
34; CHECK: [[BASE:%[a-zA-Z0-9]+]] = add i32 %a, %c
35  call void @foo(i32 %1)
36  %2 = add i32 %a, %b
37  %3 = add i32 %2, %c
38; CHECK: add i32 [[BASE]], %b
39  call void @foo(i32 %3)
40  ret void
41}
42
43; t1 = a + c;
44; foo(t1);
45; t2 = a + b;
46; foo(t2);
47; t3 = t2 + c;
48; foo(t3);
49;
50; Do not rewrite t3 into t1 + b because t2 is used elsewhere and is likely free.
51define void @no_reassociate(i32 %a, i32 %b, i32 %c) {
52; CHECK-LABEL: @no_reassociate(
53  %1 = add i32 %a, %c
54; CHECK: add i32 %a, %c
55  call void @foo(i32 %1)
56  %2 = add i32 %a, %b
57; CHECK: add i32 %a, %b
58  call void @foo(i32 %2)
59  %3 = add i32 %2, %c
60; CHECK: add i32 %2, %c
61  call void @foo(i32 %3)
62  ret void
63}
64
65; if (p1)
66;   foo(a + c);
67; if (p2)
68;   foo(a + c);
69; if (p3)
70;   foo((a + b) + c);
71;
72; No action because (a + c) does not dominate ((a + b) + c).
73define void @conditional(i1 %p1, i1 %p2, i1 %p3, i32 %a, i32 %b, i32 %c) {
74; CHECK-LABEL: @conditional(
75entry:
76  br i1 %p1, label %then1, label %branch1
77
78then1:
79  %0 = add i32 %a, %c
80; CHECK: add i32 %a, %c
81  call void @foo(i32 %0)
82  br label %branch1
83
84branch1:
85  br i1 %p2, label %then2, label %branch2
86
87then2:
88  %1 = add i32 %a, %c
89; CHECK: add i32 %a, %c
90  call void @foo(i32 %1)
91  br label %branch2
92
93branch2:
94  br i1 %p3, label %then3, label %return
95
96then3:
97  %2 = add i32 %a, %b
98; CHECK: %2 = add i32 %a, %b
99  %3 = add i32 %2, %c
100; CHECK: add i32 %2, %c
101  call void @foo(i32 %3)
102  br label %return
103
104return:
105  ret void
106}
107
108; This test involves more conditional reassociation candidates. It exercises
109; the stack optimization in tryReassociatedAdd that pops the candidates that
110; do not dominate the current instruction.
111;
112;       def1
113;      cond1
114;      /  \
115;     /    \
116;   cond2  use2
117;   /  \
118;  /    \
119; def2  def3
120;      cond3
121;       /  \
122;      /    \
123;    def4   use1
124;
125; NaryReassociate should match use1 with def3, and use2 with def1.
126define void @conditional2(i32 %a, i32 %b, i32 %c, i1 %cond1, i1 %cond2, i1 %cond3) {
127entry:
128  %def1 = add i32 %a, %b
129  br i1 %cond1, label %bb1, label %bb6
130bb1:
131  br i1 %cond2, label %bb2, label %bb3
132bb2:
133  %def2 = add i32 %a, %b
134  call void @foo(i32 %def2)
135  ret void
136bb3:
137  %def3 = add i32 %a, %b
138  br i1 %cond3, label %bb4, label %bb5
139bb4:
140  %def4 = add i32 %a, %b
141  call void @foo(i32 %def4)
142  ret void
143bb5:
144  %0 = add i32 %a, %c
145  %1 = add i32 %0, %b
146; CHECK: [[t1:%[0-9]+]] = add i32 %def3, %c
147  call void @foo(i32 %1) ; foo((a + c) + b);
148; CHECK-NEXT: call void @foo(i32 [[t1]])
149  ret void
150bb6:
151  %2 = add i32 %a, %c
152  %3 = add i32 %2, %b
153; CHECK: [[t2:%[0-9]+]] = add i32 %def1, %c
154  call void @foo(i32 %3) ; foo((a + c) + b);
155; CHECK-NEXT: call void @foo(i32 [[t2]])
156  ret void
157}
158
159; foo((a + b) + c)
160; foo(((a + d) + b) + c)
161;   =>
162; t = (a + b) + c;
163; foo(t);
164; foo(t + d);
165define void @quaternary(i32 %a, i32 %b, i32 %c, i32 %d) {
166; CHECK-LABEL: @quaternary(
167  %1 = add i32 %a, %b
168  %2 = add i32 %1, %c
169  call void @foo(i32 %2)
170; CHECK: call void @foo(i32 [[TMP1:%[a-zA-Z0-9]]])
171  %3 = add i32 %a, %d
172  %4 = add i32 %3, %b
173  %5 = add i32 %4, %c
174; CHECK: [[TMP2:%[a-zA-Z0-9]]] = add i32 [[TMP1]], %d
175  call void @foo(i32 %5)
176; CHECK: call void @foo(i32 [[TMP2]]
177  ret void
178}
179
180define void @iterative(i32 %a, i32 %b, i32 %c) {
181  %ab = add i32 %a, %b
182  %abc = add i32 %ab, %c
183  call void @foo(i32 %abc)
184
185  %ab2 = add i32 %ab, %b
186  %ab2c = add i32 %ab2, %c
187; CHECK: %ab2c = add i32 %abc, %b
188  call void @foo(i32 %ab2c)
189; CHECK-NEXT: call void @foo(i32 %ab2c)
190
191  %ab3 = add i32 %ab2, %b
192  %ab3c = add i32 %ab3, %c
193; CHECK-NEXT: %ab3c = add i32 %ab2c, %b
194  call void @foo(i32 %ab3c)
195; CHECK-NEXT: call void @foo(i32 %ab3c)
196
197  ret void
198}
199