Home | History | Annotate | Download | only in InstCombine
      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