[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / InstCombine / shift-amount-reassociation.ll
blobe124a0358610e5b5db45541bf9655d05b4120792
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
4 ; Given pattern:
5 ;   (x shiftopcode Q) shiftopcode K
6 ; we should rewrite it as
7 ;   x shiftopcode (Q+K)  iff (Q+K) u< bitwidth(x)
8 ; This is valid for any shift, but they must be identical.
9 ; THIS FOLD DOES *NOT* REQUIRE ANY 'exact'/'nuw'/`nsw` FLAGS!
11 ; Basic scalar test
13 define i32 @t0(i32 %x, i32 %y) {
14 ; CHECK-LABEL: @t0(
15 ; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[X:%.*]], 30
16 ; CHECK-NEXT:    ret i32 [[T3]]
18   %t0 = sub i32 32, %y
19   %t1 = lshr i32 %x, %t0
20   %t2 = add i32 %y, -2
21   %t3 = lshr exact i32 %t1, %t2 ; while there, test that we don't propagate partial 'exact' flag
22   ret i32 %t3
25 define <2 x i32> @t1_vec_splat(<2 x i32> %x, <2 x i32> %y) {
26 ; CHECK-LABEL: @t1_vec_splat(
27 ; CHECK-NEXT:    [[T3:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 30, i32 30>
28 ; CHECK-NEXT:    ret <2 x i32> [[T3]]
30   %t0 = sub <2 x i32> <i32 32, i32 32>, %y
31   %t1 = lshr <2 x i32> %x, %t0
32   %t2 = add <2 x i32> %y, <i32 -2, i32 -2>
33   %t3 = lshr <2 x i32> %t1, %t2
34   ret <2 x i32> %t3
37 define <2 x i32> @t2_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {
38 ; CHECK-LABEL: @t2_vec_nonsplat(
39 ; CHECK-NEXT:    [[T3:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 30, i32 30>
40 ; CHECK-NEXT:    ret <2 x i32> [[T3]]
42   %t0 = sub <2 x i32> <i32 32, i32 30>, %y
43   %t1 = lshr <2 x i32> %x, %t0
44   %t2 = add <2 x i32> %y, <i32 -2, i32 0>
45   %t3 = lshr <2 x i32> %t1, %t2
46   ret <2 x i32> %t3
49 ; Basic vector tests
51 define <3 x i32> @t3_vec_nonsplat_undef0(<3 x i32> %x, <3 x i32> %y) {
52 ; CHECK-LABEL: @t3_vec_nonsplat_undef0(
53 ; CHECK-NEXT:    [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 undef, i32 30>
54 ; CHECK-NEXT:    ret <3 x i32> [[T3]]
56   %t0 = sub <3 x i32> <i32 32, i32 undef, i32 32>, %y
57   %t1 = lshr <3 x i32> %x, %t0
58   %t2 = add <3 x i32> %y, <i32 -2, i32 -2, i32 -2>
59   %t3 = lshr <3 x i32> %t1, %t2
60   ret <3 x i32> %t3
63 define <3 x i32> @t4_vec_nonsplat_undef1(<3 x i32> %x, <3 x i32> %y) {
64 ; CHECK-LABEL: @t4_vec_nonsplat_undef1(
65 ; CHECK-NEXT:    [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 undef, i32 30>
66 ; CHECK-NEXT:    ret <3 x i32> [[T3]]
68   %t0 = sub <3 x i32> <i32 32, i32 32, i32 32>, %y
69   %t1 = lshr <3 x i32> %x, %t0
70   %t2 = add <3 x i32> %y, <i32 -2, i32 undef, i32 -2>
71   %t3 = lshr <3 x i32> %t1, %t2
72   ret <3 x i32> %t3
75 define <3 x i32> @t5_vec_nonsplat_undef1(<3 x i32> %x, <3 x i32> %y) {
76 ; CHECK-LABEL: @t5_vec_nonsplat_undef1(
77 ; CHECK-NEXT:    [[T3:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 30, i32 undef, i32 30>
78 ; CHECK-NEXT:    ret <3 x i32> [[T3]]
80   %t0 = sub <3 x i32> <i32 32, i32 undef, i32 32>, %y
81   %t1 = lshr <3 x i32> %x, %t0
82   %t2 = add <3 x i32> %y, <i32 -2, i32 undef, i32 -2>
83   %t3 = lshr <3 x i32> %t1, %t2
84   ret <3 x i32> %t3
87 ; Some other shift opcodes
88 define i32 @t6_shl(i32 %x, i32 %y) {
89 ; CHECK-LABEL: @t6_shl(
90 ; CHECK-NEXT:    [[T3:%.*]] = shl i32 [[X:%.*]], 30
91 ; CHECK-NEXT:    ret i32 [[T3]]
93   %t0 = sub i32 32, %y
94   %t1 = shl nuw i32 %x, %t0 ; while there, test that we don't propagate partial 'nuw' flag
95   %t2 = add i32 %y, -2
96   %t3 = shl nsw i32 %t1, %t2 ; while there, test that we don't propagate partial 'nsw' flag
97   ret i32 %t3
99 define i32 @t7_ashr(i32 %x, i32 %y) {
100 ; CHECK-LABEL: @t7_ashr(
101 ; CHECK-NEXT:    [[T3:%.*]] = ashr i32 [[X:%.*]], 30
102 ; CHECK-NEXT:    ret i32 [[T3]]
104   %t0 = sub i32 32, %y
105   %t1 = ashr exact i32 %x, %t0 ; while there, test that we don't propagate partial 'exact' flag
106   %t2 = add i32 %y, -2
107   %t3 = ashr i32 %t1, %t2
108   ret i32 %t3
111 ; If the same flag is present on both shifts, it can be kept.
112 define i32 @t8_lshr_exact_flag_preservation(i32 %x, i32 %y) {
113 ; CHECK-LABEL: @t8_lshr_exact_flag_preservation(
114 ; CHECK-NEXT:    [[T3:%.*]] = lshr exact i32 [[X:%.*]], 30
115 ; CHECK-NEXT:    ret i32 [[T3]]
117   %t0 = sub i32 32, %y
118   %t1 = lshr exact i32 %x, %t0
119   %t2 = add i32 %y, -2
120   %t3 = lshr exact i32 %t1, %t2
121   ret i32 %t3
123 define i32 @t9_ashr_exact_flag_preservation(i32 %x, i32 %y) {
124 ; CHECK-LABEL: @t9_ashr_exact_flag_preservation(
125 ; CHECK-NEXT:    [[T3:%.*]] = ashr exact i32 [[X:%.*]], 30
126 ; CHECK-NEXT:    ret i32 [[T3]]
128   %t0 = sub i32 32, %y
129   %t1 = ashr exact i32 %x, %t0
130   %t2 = add i32 %y, -2
131   %t3 = ashr exact i32 %t1, %t2
132   ret i32 %t3
134 define i32 @t10_shl_nuw_flag_preservation(i32 %x, i32 %y) {
135 ; CHECK-LABEL: @t10_shl_nuw_flag_preservation(
136 ; CHECK-NEXT:    [[T3:%.*]] = shl nuw i32 [[X:%.*]], 30
137 ; CHECK-NEXT:    ret i32 [[T3]]
139   %t0 = sub i32 32, %y
140   %t1 = shl nuw i32 %x, %t0
141   %t2 = add i32 %y, -2
142   %t3 = shl nuw nsw i32 %t1, %t2 ; only 'nuw' should be propagated.
143   ret i32 %t3
145 define i32 @t11_shl_nsw_flag_preservation(i32 %x, i32 %y) {
146 ; CHECK-LABEL: @t11_shl_nsw_flag_preservation(
147 ; CHECK-NEXT:    [[T3:%.*]] = shl nsw i32 [[X:%.*]], 30
148 ; CHECK-NEXT:    ret i32 [[T3]]
150   %t0 = sub i32 32, %y
151   %t1 = shl nsw i32 %x, %t0
152   %t2 = add i32 %y, -2
153   %t3 = shl nsw nuw i32 %t1, %t2 ; only 'nuw' should be propagated.
154   ret i32 %t3
157 ; Reduced from https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15587
158 @X = external global i32
159 define i64 @constantexpr() {
160 ; CHECK-LABEL: @constantexpr(
161 ; CHECK-NEXT:    ret i64 0
163   %A = alloca i64
164   %L = load i64, i64* %A
165   %V = add i64 ptrtoint (i32* @X to i64), 0
166   %B2 = shl i64 %V, 0
167   %B4 = ashr i64 %B2, %L
168   %B = and i64 undef, %B4
169   ret i64 %B
172 ; No one-use tests since we will only produce a single instruction here.
174 ; Negative tests
176 ; Can't fold, total shift would be 32
177 define i32 @n12(i32 %x, i32 %y) {
178 ; CHECK-LABEL: @n12(
179 ; CHECK-NEXT:    [[T0:%.*]] = sub i32 30, [[Y:%.*]]
180 ; CHECK-NEXT:    [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]
181 ; CHECK-NEXT:    [[T2:%.*]] = add i32 [[Y]], 2
182 ; CHECK-NEXT:    [[T3:%.*]] = lshr i32 [[T1]], [[T2]]
183 ; CHECK-NEXT:    ret i32 [[T3]]
185   %t0 = sub i32 30, %y
186   %t1 = lshr i32 %x, %t0
187   %t2 = add i32 %y, 2
188   %t3 = lshr i32 %t1, %t2
189   ret i32 %t3
191 ; Can't fold, for second channel the shift would 32
192 define <2 x i32> @t13_vec(<2 x i32> %x, <2 x i32> %y) {
193 ; CHECK-LABEL: @t13_vec(
194 ; CHECK-NEXT:    [[T0:%.*]] = sub <2 x i32> <i32 32, i32 30>, [[Y:%.*]]
195 ; CHECK-NEXT:    [[T1:%.*]] = lshr <2 x i32> [[X:%.*]], [[T0]]
196 ; CHECK-NEXT:    [[T2:%.*]] = add <2 x i32> [[Y]], <i32 -2, i32 2>
197 ; CHECK-NEXT:    [[T3:%.*]] = lshr <2 x i32> [[T1]], [[T2]]
198 ; CHECK-NEXT:    ret <2 x i32> [[T3]]
200   %t0 = sub <2 x i32> <i32 32, i32 30>, %y
201   %t1 = lshr <2 x i32> %x, %t0
202   %t2 = add <2 x i32> %y, <i32 -2, i32 2>
203   %t3 = lshr <2 x i32> %t1, %t2
204   ret <2 x i32> %t3