1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -instcombine -S | FileCheck %s 3 4 ; https://bugs.llvm.org/show_bug.cgi?id=37603 5 ; https://reviews.llvm.org/D46760#1123713 6 7 ; Pattern: 8 ; x >> y << y 9 ; Should be transformed into: 10 ; x & (-1 << y) 11 12 ; ============================================================================ ; 13 ; Basic positive tests 14 ; ============================================================================ ; 15 16 define i32 @positive_samevar(i32 %x, i32 %y) { 17 ; CHECK-LABEL: @positive_samevar( 18 ; CHECK-NEXT: [[TMP1:%.*]] = shl i32 -1, [[Y:%.*]] 19 ; CHECK-NEXT: [[RET:%.*]] = and i32 [[TMP1]], [[X:%.*]] 20 ; CHECK-NEXT: ret i32 [[RET]] 21 ; 22 %tmp0 = ashr i32 %x, %y 23 %ret = shl i32 %tmp0, %y 24 ret i32 %ret 25 } 26 27 define i32 @positive_sameconst(i32 %x) { 28 ; CHECK-LABEL: @positive_sameconst( 29 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], -32 30 ; CHECK-NEXT: ret i32 [[TMP1]] 31 ; 32 %tmp0 = ashr i32 %x, 5 33 %ret = shl i32 %tmp0, 5 34 ret i32 %ret 35 } 36 37 define i32 @positive_biggerashr(i32 %x) { 38 ; CHECK-LABEL: @positive_biggerashr( 39 ; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 [[X:%.*]], 10 40 ; CHECK-NEXT: [[RET:%.*]] = shl nsw i32 [[TMP0]], 5 41 ; CHECK-NEXT: ret i32 [[RET]] 42 ; 43 %tmp0 = ashr i32 %x, 10 44 %ret = shl i32 %tmp0, 5 45 ret i32 %ret 46 } 47 48 define i32 @positive_biggershl(i32 %x) { 49 ; CHECK-LABEL: @positive_biggershl( 50 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 5 51 ; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP1]], 10 52 ; CHECK-NEXT: ret i32 [[RET]] 53 ; 54 %tmp0 = ashr i32 %x, 5 55 %ret = shl i32 %tmp0, 10 56 ret i32 %ret 57 } 58 59 ; ============================================================================ ; 60 ; EXACT on the first shift 61 ; ============================================================================ ; 62 63 define i32 @positive_samevar_ashrexact(i32 %x, i32 %y) { 64 ; CHECK-LABEL: @positive_samevar_ashrexact( 65 ; CHECK-NEXT: ret i32 [[X:%.*]] 66 ; 67 %tmp0 = ashr exact i32 %x, %y 68 %ret = shl i32 %tmp0, %y ; this one is obviously 'nuw'. 69 ret i32 %ret 70 } 71 72 define i32 @positive_sameconst_ashrexact(i32 %x) { 73 ; CHECK-LABEL: @positive_sameconst_ashrexact( 74 ; CHECK-NEXT: ret i32 [[X:%.*]] 75 ; 76 %tmp0 = ashr exact i32 %x, 5 77 %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'. 78 ret i32 %ret 79 } 80 81 define i32 @positive_biggerashr_ashrexact(i32 %x) { 82 ; CHECK-LABEL: @positive_biggerashr_ashrexact( 83 ; CHECK-NEXT: [[RET:%.*]] = ashr exact i32 [[X:%.*]], 5 84 ; CHECK-NEXT: ret i32 [[RET]] 85 ; 86 %tmp0 = ashr exact i32 %x, 10 87 %ret = shl i32 %tmp0, 5 ; this one is obviously 'nuw'. 88 ret i32 %ret 89 } 90 91 define i32 @positive_biggershl_ashrexact(i32 %x) { 92 ; CHECK-LABEL: @positive_biggershl_ashrexact( 93 ; CHECK-NEXT: [[RET:%.*]] = shl i32 [[X:%.*]], 5 94 ; CHECK-NEXT: ret i32 [[RET]] 95 ; 96 %tmp0 = ashr exact i32 %x, 5 97 %ret = shl i32 %tmp0, 10 98 ret i32 %ret 99 } 100 101 define i32 @positive_biggershl_ashrexact_shlnuw(i32 %x) { 102 ; CHECK-LABEL: @positive_biggershl_ashrexact_shlnuw( 103 ; CHECK-NEXT: [[RET:%.*]] = shl nuw i32 [[X:%.*]], 5 104 ; CHECK-NEXT: ret i32 [[RET]] 105 ; 106 %tmp0 = ashr exact i32 %x, 5 107 %ret = shl nuw i32 %tmp0, 10 108 ret i32 %ret 109 } 110 111 ; ============================================================================ ; 112 ; Vector 113 ; ============================================================================ ; 114 115 define <2 x i32> @positive_samevar_vec(<2 x i32> %x, <2 x i32> %y) { 116 ; CHECK-LABEL: @positive_samevar_vec( 117 ; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> <i32 -1, i32 -1>, [[Y:%.*]] 118 ; CHECK-NEXT: [[RET:%.*]] = and <2 x i32> [[TMP1]], [[X:%.*]] 119 ; CHECK-NEXT: ret <2 x i32> [[RET]] 120 ; 121 %tmp0 = ashr <2 x i32> %x, %y 122 %ret = shl <2 x i32> %tmp0, %y 123 ret <2 x i32> %ret 124 } 125 126 ; ============================================================================ ; 127 ; Constant Vectors 128 ; ============================================================================ ; 129 130 define <2 x i32> @positive_sameconst_vec(<2 x i32> %x) { 131 ; CHECK-LABEL: @positive_sameconst_vec( 132 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[X:%.*]], <i32 -32, i32 -32> 133 ; CHECK-NEXT: ret <2 x i32> [[TMP1]] 134 ; 135 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5> 136 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5> 137 ret <2 x i32> %ret 138 } 139 140 define <3 x i32> @positive_sameconst_vec_undef0(<3 x i32> %x) { 141 ; CHECK-LABEL: @positive_sameconst_vec_undef0( 142 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5> 143 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5> 144 ; CHECK-NEXT: ret <3 x i32> [[RET]] 145 ; 146 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 147 %ret = shl <3 x i32> %tmp0, <i32 5, i32 5, i32 5> 148 ret <3 x i32> %ret 149 } 150 151 define <3 x i32> @positive_sameconst_vec_undef1(<3 x i32> %x) { 152 ; CHECK-LABEL: @positive_sameconst_vec_undef1( 153 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5> 154 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5> 155 ; CHECK-NEXT: ret <3 x i32> [[RET]] 156 ; 157 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 5, i32 5> 158 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 159 ret <3 x i32> %ret 160 } 161 162 define <3 x i32> @positive_sameconst_vec_undef2(<3 x i32> %x) { 163 ; CHECK-LABEL: @positive_sameconst_vec_undef2( 164 ; CHECK-NEXT: [[RET:%.*]] = and <3 x i32> [[X:%.*]], <i32 -32, i32 undef, i32 -32> 165 ; CHECK-NEXT: ret <3 x i32> [[RET]] 166 ; 167 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 168 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 169 ret <3 x i32> %ret 170 } 171 172 define <2 x i32> @positive_biggerashr_vec(<2 x i32> %x) { 173 ; CHECK-LABEL: @positive_biggerashr_vec( 174 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 10, i32 10> 175 ; CHECK-NEXT: [[RET:%.*]] = shl nsw <2 x i32> [[TMP0]], <i32 5, i32 5> 176 ; CHECK-NEXT: ret <2 x i32> [[RET]] 177 ; 178 %tmp0 = ashr <2 x i32> %x, <i32 10, i32 10> 179 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5> 180 ret <2 x i32> %ret 181 } 182 183 define <3 x i32> @positive_biggerashr_vec_undef0(<3 x i32> %x) { 184 ; CHECK-LABEL: @positive_biggerashr_vec_undef0( 185 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10> 186 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 5, i32 5> 187 ; CHECK-NEXT: ret <3 x i32> [[RET]] 188 ; 189 %tmp0 = ashr <3 x i32> %x, <i32 10, i32 undef, i32 10> 190 %ret = shl <3 x i32> %tmp0, <i32 5, i32 5, i32 5> 191 ret <3 x i32> %ret 192 } 193 194 define <3 x i32> @positive_biggerashr_vec_undef1(<3 x i32> %x) { 195 ; CHECK-LABEL: @positive_biggerashr_vec_undef1( 196 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 10, i32 10> 197 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5> 198 ; CHECK-NEXT: ret <3 x i32> [[RET]] 199 ; 200 %tmp0 = ashr <3 x i32> %x, <i32 10, i32 10, i32 10> 201 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 202 ret <3 x i32> %ret 203 } 204 205 define <3 x i32> @positive_biggerashr_vec_undef2(<3 x i32> %x) { 206 ; CHECK-LABEL: @positive_biggerashr_vec_undef2( 207 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 10, i32 undef, i32 10> 208 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 5, i32 undef, i32 5> 209 ; CHECK-NEXT: ret <3 x i32> [[RET]] 210 ; 211 %tmp0 = ashr <3 x i32> %x, <i32 10, i32 undef, i32 10> 212 %ret = shl <3 x i32> %tmp0, <i32 5, i32 undef, i32 5> 213 ret <3 x i32> %ret 214 } 215 216 define <2 x i32> @positive_biggershl_vec(<2 x i32> %x) { 217 ; CHECK-LABEL: @positive_biggershl_vec( 218 ; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 5, i32 5> 219 ; CHECK-NEXT: [[RET:%.*]] = shl <2 x i32> [[TMP1]], <i32 10, i32 10> 220 ; CHECK-NEXT: ret <2 x i32> [[RET]] 221 ; 222 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5> 223 %ret = shl <2 x i32> %tmp0, <i32 10, i32 10> 224 ret <2 x i32> %ret 225 } 226 227 define <3 x i32> @positive_biggershl_vec_undef0(<3 x i32> %x) { 228 ; CHECK-LABEL: @positive_biggershl_vec_undef0( 229 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5> 230 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 10, i32 10> 231 ; CHECK-NEXT: ret <3 x i32> [[RET]] 232 ; 233 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 234 %ret = shl <3 x i32> %tmp0, <i32 10, i32 10, i32 10> 235 ret <3 x i32> %ret 236 } 237 238 define <3 x i32> @positive_biggershl_vec_undef1(<3 x i32> %x) { 239 ; CHECK-LABEL: @positive_biggershl_vec_undef1( 240 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 5, i32 5> 241 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10> 242 ; CHECK-NEXT: ret <3 x i32> [[RET]] 243 ; 244 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 5, i32 5> 245 %ret = shl <3 x i32> %tmp0, <i32 10, i32 undef, i32 10> 246 ret <3 x i32> %ret 247 } 248 249 define <3 x i32> @positive_biggershl_vec_undef2(<3 x i32> %x) { 250 ; CHECK-LABEL: @positive_biggershl_vec_undef2( 251 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <3 x i32> [[X:%.*]], <i32 5, i32 undef, i32 5> 252 ; CHECK-NEXT: [[RET:%.*]] = shl <3 x i32> [[TMP0]], <i32 10, i32 undef, i32 10> 253 ; CHECK-NEXT: ret <3 x i32> [[RET]] 254 ; 255 %tmp0 = ashr <3 x i32> %x, <i32 5, i32 undef, i32 5> 256 %ret = shl <3 x i32> %tmp0, <i32 10, i32 undef, i32 10> 257 ret <3 x i32> %ret 258 } 259 260 ; ============================================================================ ; 261 ; Positive multi-use tests with constant 262 ; ============================================================================ ; 263 264 ; FIXME: drop 'exact' once it is no longer needed. 265 266 define i32 @positive_sameconst_multiuse(i32 %x) { 267 ; CHECK-LABEL: @positive_sameconst_multiuse( 268 ; CHECK-NEXT: [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 5 269 ; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 270 ; CHECK-NEXT: ret i32 [[X]] 271 ; 272 %tmp0 = ashr exact i32 %x, 5 273 call void @use32(i32 %tmp0) 274 %ret = shl i32 %tmp0, 5 275 ret i32 %ret 276 } 277 278 define i32 @positive_biggerashr_multiuse(i32 %x) { 279 ; CHECK-LABEL: @positive_biggerashr_multiuse( 280 ; CHECK-NEXT: [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 10 281 ; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 282 ; CHECK-NEXT: [[RET:%.*]] = ashr exact i32 [[X]], 5 283 ; CHECK-NEXT: ret i32 [[RET]] 284 ; 285 %tmp0 = ashr exact i32 %x, 10 286 call void @use32(i32 %tmp0) 287 %ret = shl i32 %tmp0, 5 288 ret i32 %ret 289 } 290 291 define i32 @positive_biggershl_multiuse(i32 %x) { 292 ; CHECK-LABEL: @positive_biggershl_multiuse( 293 ; CHECK-NEXT: [[TMP0:%.*]] = ashr exact i32 [[X:%.*]], 5 294 ; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 295 ; CHECK-NEXT: [[RET:%.*]] = shl i32 [[X]], 5 296 ; CHECK-NEXT: ret i32 [[RET]] 297 ; 298 %tmp0 = ashr exact i32 %x, 5 299 call void @use32(i32 %tmp0) 300 %ret = shl i32 %tmp0, 10 301 ret i32 %ret 302 } 303 304 ; ============================================================================ ; 305 ; Constant Non-Splat Vectors 306 ; ============================================================================ ; 307 308 define <2 x i32> @positive_biggerashr_vec_nonsplat(<2 x i32> %x) { 309 ; CHECK-LABEL: @positive_biggerashr_vec_nonsplat( 310 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 5> 311 ; CHECK-NEXT: [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 5, i32 10> 312 ; CHECK-NEXT: ret <2 x i32> [[RET]] 313 ; 314 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 5> 315 %ret = shl <2 x i32> %tmp0, <i32 5, i32 10> 316 ret <2 x i32> %ret 317 } 318 319 define <2 x i32> @positive_biggerLashr_vec_nonsplat(<2 x i32> %x) { 320 ; CHECK-LABEL: @positive_biggerLashr_vec_nonsplat( 321 ; CHECK-NEXT: [[TMP0:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 5, i32 10> 322 ; CHECK-NEXT: [[RET:%.*]] = shl <2 x i32> [[TMP0]], <i32 5, i32 5> 323 ; CHECK-NEXT: ret <2 x i32> [[RET]] 324 ; 325 %tmp0 = ashr <2 x i32> %x, <i32 5, i32 10> 326 %ret = shl <2 x i32> %tmp0, <i32 5, i32 5> 327 ret <2 x i32> %ret 328 } 329 330 ; ============================================================================ ; 331 ; Negative tests. Should not be folded. 332 ; ============================================================================ ; 333 334 define i32 @negative_twovars(i32 %x, i32 %y, i32 %z) { 335 ; CHECK-LABEL: @negative_twovars( 336 ; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]] 337 ; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP0]], [[Z:%.*]] 338 ; CHECK-NEXT: ret i32 [[RET]] 339 ; 340 %tmp0 = ashr i32 %x, %y 341 %ret = shl i32 %tmp0, %z ; $z, not %y 342 ret i32 %ret 343 } 344 345 declare void @use32(i32) 346 347 ; One use only. 348 define i32 @negative_oneuse(i32 %x, i32 %y) { 349 ; CHECK-LABEL: @negative_oneuse( 350 ; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 [[X:%.*]], [[Y:%.*]] 351 ; CHECK-NEXT: call void @use32(i32 [[TMP0]]) 352 ; CHECK-NEXT: [[RET:%.*]] = shl i32 [[TMP0]], [[Y]] 353 ; CHECK-NEXT: ret i32 [[RET]] 354 ; 355 %tmp0 = ashr i32 %x, %y 356 call void @use32(i32 %tmp0) 357 %ret = shl i32 %tmp0, %y 358 ret i32 %ret 359 } 360