[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / StraightLineStrengthReduce / slsr-add.ll
blob92af617dab82b1151d3240cc7779cbc15ea9ca9a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -slsr -gvn -S | FileCheck %s
4 target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
6 define void @shl(i32 %b, i32 %s) {
7 ; CHECK-LABEL: @shl(
8 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S:%.*]]
9 ; CHECK-NEXT:    call void @foo(i32 [[T1]])
10 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], [[S]]
11 ; CHECK-NEXT:    call void @foo(i32 [[T2]])
12 ; CHECK-NEXT:    ret void
14   %t1 = add i32 %b, %s
15   call void @foo(i32 %t1)
16   %s2 = shl i32 %s, 1
17   %t2 = add i32 %b, %s2
18   call void @foo(i32 %t2)
19   ret void
22 define void @stride_is_2s(i32 %b, i32 %s) {
23 ; CHECK-LABEL: @stride_is_2s(
24 ; CHECK-NEXT:    [[S2:%.*]] = shl i32 [[S:%.*]], 1
25 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S2]]
26 ; CHECK-NEXT:    call void @foo(i32 [[T1]])
27 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], [[S2]]
28 ; CHECK-NEXT:    call void @foo(i32 [[T2]])
29 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[T2]], [[S2]]
30 ; CHECK-NEXT:    call void @foo(i32 [[T3]])
31 ; CHECK-NEXT:    ret void
33   %s2 = shl i32 %s, 1
34   %t1 = add i32 %b, %s2
35   call void @foo(i32 %t1)
36   %s4 = shl i32 %s, 2
37   %t2 = add i32 %b, %s4
38   call void @foo(i32 %t2)
39   %s6 = mul i32 %s, 6
40   %t3 = add i32 %b, %s6
41   call void @foo(i32 %t3)
42   ret void
45 define void @stride_is_3s(i32 %b, i32 %s) {
46 ; CHECK-LABEL: @stride_is_3s(
47 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[S:%.*]], [[B:%.*]]
48 ; CHECK-NEXT:    call void @foo(i32 [[T1]])
49 ; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[S]], 3
50 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], [[TMP1]]
51 ; CHECK-NEXT:    call void @foo(i32 [[T2]])
52 ; CHECK-NEXT:    [[T3:%.*]] = add i32 [[T2]], [[TMP1]]
53 ; CHECK-NEXT:    call void @foo(i32 [[T3]])
54 ; CHECK-NEXT:    ret void
56   %t1 = add i32 %s, %b
57   call void @foo(i32 %t1)
58   %s4 = shl i32 %s, 2
59   %t2 = add i32 %s4, %b
60   call void @foo(i32 %t2)
61   %s7 = mul i32 %s, 7
62   %t3 = add i32 %s7, %b
63   call void @foo(i32 %t3)
64   ret void
67 ; foo(b + 6 * s);
68 ; foo(b + 4 * s);
69 ; foo(b + 2 * s);
70 ;   =>
71 ; t1 = b + 6 * s;
72 ; foo(t1);
73 ; s2 = 2 * s;
74 ; t2 = t1 - s2;
75 ; foo(t2);
76 ; t3 = t2 - s2;
77 ; foo(t3);
78 define void @stride_is_minus_2s(i32 %b, i32 %s) {
79 ; CHECK-LABEL: @stride_is_minus_2s(
80 ; CHECK-NEXT:    [[S6:%.*]] = mul i32 [[S:%.*]], 6
81 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S6]]
82 ; CHECK-NEXT:    call void @foo(i32 [[T1]])
83 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[S]], 1
84 ; CHECK-NEXT:    [[T2:%.*]] = sub i32 [[T1]], [[TMP1]]
85 ; CHECK-NEXT:    call void @foo(i32 [[T2]])
86 ; CHECK-NEXT:    [[T3:%.*]] = sub i32 [[T2]], [[TMP1]]
87 ; CHECK-NEXT:    call void @foo(i32 [[T3]])
88 ; CHECK-NEXT:    ret void
90   %s6 = mul i32 %s, 6
91   %t1 = add i32 %b, %s6
92   call void @foo(i32 %t1)
93   %s4 = shl i32 %s, 2
94   %t2 = add i32 %b, %s4
95   call void @foo(i32 %t2)
96   %s2 = shl i32 %s, 1
97   %t3 = add i32 %b, %s2
98   call void @foo(i32 %t3)
99   ret void
102 ; TODO: This pass is targeted at simple address-calcs, so it is artificially limited to
103 ; match scalar values. The code could be modified to handle vector types too.
105 define void @stride_is_minus_2s_vec(<2 x i32> %b, <2 x i32> %s) {
106 ; CHECK-LABEL: @stride_is_minus_2s_vec(
107 ; CHECK-NEXT:    [[S6:%.*]] = mul <2 x i32> [[S:%.*]], <i32 6, i32 6>
108 ; CHECK-NEXT:    [[T1:%.*]] = add <2 x i32> [[B:%.*]], [[S6]]
109 ; CHECK-NEXT:    call void @voo(<2 x i32> [[T1]])
110 ; CHECK-NEXT:    [[S4:%.*]] = shl <2 x i32> [[S]], <i32 2, i32 2>
111 ; CHECK-NEXT:    [[T2:%.*]] = add <2 x i32> [[B]], [[S4]]
112 ; CHECK-NEXT:    call void @voo(<2 x i32> [[T2]])
113 ; CHECK-NEXT:    [[S2:%.*]] = shl <2 x i32> [[S]], <i32 1, i32 1>
114 ; CHECK-NEXT:    [[T3:%.*]] = add <2 x i32> [[B]], [[S2]]
115 ; CHECK-NEXT:    call void @voo(<2 x i32> [[T3]])
116 ; CHECK-NEXT:    ret void
118   %s6 = mul <2 x i32> %s, <i32 6, i32 6>
119   %t1 = add <2 x i32> %b, %s6
120   call void @voo(<2 x i32> %t1)
121   %s4 = shl <2 x i32> %s, <i32 2, i32 2>
122   %t2 = add <2 x i32> %b, %s4
123   call void @voo(<2 x i32> %t2)
124   %s2 = shl <2 x i32> %s, <i32 1, i32 1>
125   %t3 = add <2 x i32> %b, %s2
126   call void @voo(<2 x i32> %t3)
127   ret void
130 ; t = b + (s << 3);
131 ; foo(t);
132 ; foo(b + s);
134 ; do not rewrite b + s to t - 7 * s because the latter is more complicated.
135 define void @simple_enough(i32 %b, i32 %s) {
136 ; CHECK-LABEL: @simple_enough(
137 ; CHECK-NEXT:    [[S8:%.*]] = shl i32 [[S:%.*]], 3
138 ; CHECK-NEXT:    [[T1:%.*]] = add i32 [[B:%.*]], [[S8]]
139 ; CHECK-NEXT:    call void @foo(i32 [[T1]])
140 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[B]], [[S]]
141 ; CHECK-NEXT:    call void @foo(i32 [[T2]])
142 ; CHECK-NEXT:    ret void
144   %s8 = shl i32 %s, 3
145   %t1 = add i32 %b, %s8
146   call void @foo(i32 %t1)
147   %t2 = add i32 %b, %s
148   call void @foo(i32 %t2)
149   ret void
152 define void @slsr_strided_add_128bit(i128 %b, i128 %s) {
153 ; CHECK-LABEL: @slsr_strided_add_128bit(
154 ; CHECK-NEXT:    [[S125:%.*]] = shl i128 [[S:%.*]], 125
155 ; CHECK-NEXT:    [[T1:%.*]] = add i128 [[B:%.*]], [[S125]]
156 ; CHECK-NEXT:    call void @bar(i128 [[T1]])
157 ; CHECK-NEXT:    [[T2:%.*]] = add i128 [[T1]], [[S125]]
158 ; CHECK-NEXT:    call void @bar(i128 [[T2]])
159 ; CHECK-NEXT:    ret void
161   %s125 = shl i128 %s, 125
162   %s126 = shl i128 %s, 126
163   %t1 = add i128 %b, %s125
164   call void @bar(i128 %t1)
165   %t2 = add i128 %b, %s126
166   call void @bar(i128 %t2)
167   ret void
170 declare void @foo(i32)
171 declare void @voo(<2 x i32>)
172 declare void @bar(i128)