• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt < %s -slsr -gvn -S | FileCheck %s
2
3target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
4
5define void @slsr1(i32 %b, i32 %s) {
6; CHECK-LABEL: @slsr1(
7  ; foo(b * s);
8  %mul0 = mul i32 %b, %s
9; CHECK: mul i32
10; CHECK-NOT: mul i32
11  call void @foo(i32 %mul0)
12
13  ; foo((b + 1) * s);
14  %b1 = add i32 %b, 1
15  %mul1 = mul i32 %b1, %s
16  call void @foo(i32 %mul1)
17
18  ; foo((b + 2) * s);
19  %b2 = add i32 %b, 2
20  %mul2 = mul i32 %b2, %s
21  call void @foo(i32 %mul2)
22
23  ret void
24}
25
26define void @non_canonicalized(i32 %b, i32 %s) {
27; CHECK-LABEL: @non_canonicalized(
28  ; foo(b * s);
29  %mul0 = mul i32 %b, %s
30; CHECK: mul i32
31; CHECK-NOT: mul i32
32  call void @foo(i32 %mul0)
33
34  ; foo((1 + b) * s);
35  %b1 = add i32 1, %b
36  %mul1 = mul i32 %b1, %s
37  call void @foo(i32 %mul1)
38
39  ; foo((2 + b) * s);
40  %b2 = add i32 2, %b
41  %mul2 = mul i32 %b2, %s
42  call void @foo(i32 %mul2)
43
44  ret void
45}
46
47define void @or(i32 %a, i32 %s) {
48  %b = shl i32 %a, 1
49; CHECK-LABEL: @or(
50  ; foo(b * s);
51  %mul0 = mul i32 %b, %s
52; CHECK: [[base:[^ ]+]] = mul i32
53  call void @foo(i32 %mul0)
54
55  ; foo((b | 1) * s);
56  %b1 = or i32 %b, 1
57  %mul1 = mul i32 %b1, %s
58; CHECK: add i32 [[base]], %s
59  call void @foo(i32 %mul1)
60
61  ; foo((b | 2) * s);
62  %b2 = or i32 %b, 2
63  %mul2 = mul i32 %b2, %s
64; CHECK: mul i32 %b2, %s
65  call void @foo(i32 %mul2)
66
67  ret void
68}
69
70; foo(a * b)
71; foo((a + 1) * b)
72; foo(a * (b + 1))
73; foo((a + 1) * (b + 1))
74define void @slsr2(i32 %a, i32 %b) {
75; CHECK-LABEL: @slsr2(
76  %a1 = add i32 %a, 1
77  %b1 = add i32 %b, 1
78  %mul0 = mul i32 %a, %b
79; CHECK: mul i32
80; CHECK-NOT: mul i32
81  %mul1 = mul i32 %a1, %b
82  %mul2 = mul i32 %a, %b1
83  %mul3 = mul i32 %a1, %b1
84
85  call void @foo(i32 %mul0)
86  call void @foo(i32 %mul1)
87  call void @foo(i32 %mul2)
88  call void @foo(i32 %mul3)
89
90  ret void
91}
92
93; The bump is a multiple of the stride.
94;
95; foo(b * s);
96; foo((b + 2) * s);
97; foo((b + 4) * s);
98;   =>
99; mul0 = b * s;
100; bump = s * 2;
101; mul1 = mul0 + bump; // GVN ensures mul1 and mul2 use the same bump.
102; mul2 = mul1 + bump;
103define void @slsr3(i32 %b, i32 %s) {
104; CHECK-LABEL: @slsr3(
105  %mul0 = mul i32 %b, %s
106; CHECK: mul i32
107  call void @foo(i32 %mul0)
108
109  %b1 = add i32 %b, 2
110  %mul1 = mul i32 %b1, %s
111; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = shl i32 %s, 1
112; CHECK: %mul1 = add i32 %mul0, [[BUMP]]
113  call void @foo(i32 %mul1)
114
115  %b2 = add i32 %b, 4
116  %mul2 = mul i32 %b2, %s
117; CHECK: %mul2 = add i32 %mul1, [[BUMP]]
118  call void @foo(i32 %mul2)
119
120  ret void
121}
122
123; Do not rewrite a candidate if its potential basis does not dominate it.
124;
125; if (cond)
126;   foo(a * b);
127; foo((a + 1) * b);
128define void @not_dominate(i1 %cond, i32 %a, i32 %b) {
129; CHECK-LABEL: @not_dominate(
130entry:
131  %a1 = add i32 %a, 1
132  br i1 %cond, label %then, label %merge
133
134then:
135  %mul0 = mul i32 %a, %b
136; CHECK: %mul0 = mul i32 %a, %b
137  call void @foo(i32 %mul0)
138  br label %merge
139
140merge:
141  %mul1 = mul i32 %a1, %b
142; CHECK: %mul1 = mul i32 %a1, %b
143  call void @foo(i32 %mul1)
144  ret void
145}
146
147declare void @foo(i32)
148