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=38149
      5 
      6 ; Pattern:
      7 ;   ((%x << MaskedBits) a>> MaskedBits) == %x
      8 ; Should be transformed into:
      9 ;   (add %x, (1 << (KeptBits-1))) u< (1 << KeptBits)
     10 ; Where  KeptBits = bitwidth(%x) - MaskedBits
     11 
     12 ; ============================================================================ ;
     13 ; Basic positive tests
     14 ; ============================================================================ ;
     15 
     16 define i1 @p0(i8 %x) {
     17 ; CHECK-LABEL: @p0(
     18 ; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X:%.*]], 4
     19 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 8
     20 ; CHECK-NEXT:    ret i1 [[TMP2]]
     21 ;
     22   %tmp0 = shl i8 %x, 5
     23   %tmp1 = ashr exact i8 %tmp0, 5
     24   %tmp2 = icmp eq i8 %tmp1, %x
     25   ret i1 %tmp2
     26 }
     27 
     28 ; Big unusual bit width, https://bugs.llvm.org/show_bug.cgi?id=38204
     29 define i1 @pb(i65 %x) {
     30 ; CHECK-LABEL: @pb(
     31 ; CHECK-NEXT:    [[TMP1:%.*]] = add i65 [[X:%.*]], 9223372036854775808
     32 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i65 [[TMP1]], -1
     33 ; CHECK-NEXT:    ret i1 [[TMP2]]
     34 ;
     35   %tmp0 = shl i65 %x, 1
     36   %tmp1 = ashr exact i65 %tmp0, 1
     37   %tmp2 = icmp eq i65 %x, %tmp1
     38   ret i1 %tmp2
     39 }
     40 
     41 ; ============================================================================ ;
     42 ; Vector tests
     43 ; ============================================================================ ;
     44 
     45 define <2 x i1> @p1_vec_splat(<2 x i8> %x) {
     46 ; CHECK-LABEL: @p1_vec_splat(
     47 ; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 4, i8 4>
     48 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <2 x i8> [[TMP1]], <i8 8, i8 8>
     49 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
     50 ;
     51   %tmp0 = shl <2 x i8> %x, <i8 5, i8 5>
     52   %tmp1 = ashr exact <2 x i8> %tmp0, <i8 5, i8 5>
     53   %tmp2 = icmp eq <2 x i8> %tmp1, %x
     54   ret <2 x i1> %tmp2
     55 }
     56 
     57 define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) {
     58 ; CHECK-LABEL: @p2_vec_nonsplat(
     59 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 6>
     60 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact <2 x i8> [[TMP0]], <i8 5, i8 6>
     61 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], [[X]]
     62 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
     63 ;
     64   %tmp0 = shl <2 x i8> %x, <i8 5, i8 6>
     65   %tmp1 = ashr exact <2 x i8> %tmp0, <i8 5, i8 6>
     66   %tmp2 = icmp eq <2 x i8> %tmp1, %x
     67   ret <2 x i1> %tmp2
     68 }
     69 
     70 define <3 x i1> @p3_vec_undef0(<3 x i8> %x) {
     71 ; CHECK-LABEL: @p3_vec_undef0(
     72 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i8> [[X:%.*]], <i8 5, i8 undef, i8 5>
     73 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact <3 x i8> [[TMP0]], <i8 5, i8 5, i8 5>
     74 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <3 x i8> [[TMP1]], [[X]]
     75 ; CHECK-NEXT:    ret <3 x i1> [[TMP2]]
     76 ;
     77   %tmp0 = shl <3 x i8> %x, <i8 5, i8 undef, i8 5>
     78   %tmp1 = ashr exact <3 x i8> %tmp0, <i8 5, i8 5, i8 5>
     79   %tmp2 = icmp eq <3 x i8> %tmp1, %x
     80   ret <3 x i1> %tmp2
     81 }
     82 
     83 define <3 x i1> @p4_vec_undef1(<3 x i8> %x) {
     84 ; CHECK-LABEL: @p4_vec_undef1(
     85 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i8> [[X:%.*]], <i8 5, i8 5, i8 5>
     86 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact <3 x i8> [[TMP0]], <i8 5, i8 undef, i8 5>
     87 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <3 x i8> [[TMP1]], [[X]]
     88 ; CHECK-NEXT:    ret <3 x i1> [[TMP2]]
     89 ;
     90   %tmp0 = shl <3 x i8> %x, <i8 5, i8 5, i8 5>
     91   %tmp1 = ashr exact <3 x i8> %tmp0, <i8 5, i8 undef, i8 5>
     92   %tmp2 = icmp eq <3 x i8> %tmp1, %x
     93   ret <3 x i1> %tmp2
     94 }
     95 
     96 define <3 x i1> @p5_vec_undef2(<3 x i8> %x) {
     97 ; CHECK-LABEL: @p5_vec_undef2(
     98 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <3 x i8> [[X:%.*]], <i8 5, i8 undef, i8 5>
     99 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact <3 x i8> [[TMP0]], <i8 5, i8 undef, i8 5>
    100 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <3 x i8> [[TMP1]], [[X]]
    101 ; CHECK-NEXT:    ret <3 x i1> [[TMP2]]
    102 ;
    103   %tmp0 = shl <3 x i8> %x, <i8 5, i8 undef, i8 5>
    104   %tmp1 = ashr exact <3 x i8> %tmp0, <i8 5, i8 undef, i8 5>
    105   %tmp2 = icmp eq <3 x i8> %tmp1, %x
    106   ret <3 x i1> %tmp2
    107 }
    108 
    109 ; ============================================================================ ;
    110 ; Commutativity tests.
    111 ; ============================================================================ ;
    112 
    113 declare i8 @gen8()
    114 
    115 define i1 @c0() {
    116 ; CHECK-LABEL: @c0(
    117 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
    118 ; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], 4
    119 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 8
    120 ; CHECK-NEXT:    ret i1 [[TMP2]]
    121 ;
    122   %x = call i8 @gen8()
    123   %tmp0 = shl i8 %x, 5
    124   %tmp1 = ashr exact i8 %tmp0, 5
    125   %tmp2 = icmp eq i8 %x, %tmp1 ; swapped order
    126   ret i1 %tmp2
    127 }
    128 
    129 ; ============================================================================ ;
    130 ; One-use tests.
    131 ; ============================================================================ ;
    132 
    133 declare void @use8(i8)
    134 
    135 define i1 @n_oneuse0(i8 %x) {
    136 ; CHECK-LABEL: @n_oneuse0(
    137 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i8 [[X:%.*]], 5
    138 ; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
    139 ; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], 4
    140 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i8 [[TMP1]], 8
    141 ; CHECK-NEXT:    ret i1 [[TMP2]]
    142 ;
    143   %tmp0 = shl i8 %x, 5
    144   call void @use8(i8 %tmp0)
    145   %tmp1 = ashr exact i8 %tmp0, 5
    146   %tmp2 = icmp eq i8 %tmp1, %x
    147   ret i1 %tmp2
    148 }
    149 
    150 define i1 @n_oneuse1(i8 %x) {
    151 ; CHECK-LABEL: @n_oneuse1(
    152 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i8 [[X:%.*]], 5
    153 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 5
    154 ; CHECK-NEXT:    call void @use8(i8 [[TMP1]])
    155 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[X]]
    156 ; CHECK-NEXT:    ret i1 [[TMP2]]
    157 ;
    158   %tmp0 = shl i8 %x, 5
    159   %tmp1 = ashr exact i8 %tmp0, 5
    160   call void @use8(i8 %tmp1)
    161   %tmp2 = icmp eq i8 %tmp1, %x
    162   ret i1 %tmp2
    163 }
    164 
    165 define i1 @n_oneuse2(i8 %x) {
    166 ; CHECK-LABEL: @n_oneuse2(
    167 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i8 [[X:%.*]], 5
    168 ; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
    169 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 5
    170 ; CHECK-NEXT:    call void @use8(i8 [[TMP1]])
    171 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[X]]
    172 ; CHECK-NEXT:    ret i1 [[TMP2]]
    173 ;
    174   %tmp0 = shl i8 %x, 5
    175   call void @use8(i8 %tmp0)
    176   %tmp1 = ashr exact i8 %tmp0, 5
    177   call void @use8(i8 %tmp1)
    178   %tmp2 = icmp eq i8 %tmp1, %x
    179   ret i1 %tmp2
    180 }
    181 
    182 ; ============================================================================ ;
    183 ; Negative tests
    184 ; ============================================================================ ;
    185 
    186 define i1 @n0(i8 %x) {
    187 ; CHECK-LABEL: @n0(
    188 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i8 [[X:%.*]], 5
    189 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 3
    190 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[X]]
    191 ; CHECK-NEXT:    ret i1 [[TMP2]]
    192 ;
    193   %tmp0 = shl i8 %x, 5
    194   %tmp1 = ashr exact i8 %tmp0, 3 ; not 5
    195   %tmp2 = icmp eq i8 %tmp1, %x
    196   ret i1 %tmp2
    197 }
    198 
    199 define i1 @n1(i8 %x) {
    200 ; CHECK-LABEL: @n1(
    201 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 8
    202 ; CHECK-NEXT:    ret i1 [[TMP1]]
    203 ;
    204   %tmp0 = shl i8 %x, 5
    205   %tmp1 = lshr exact i8 %tmp0, 5 ; not ashr
    206   %tmp2 = icmp eq i8 %tmp1, %x
    207   ret i1 %tmp2
    208 }
    209 
    210 define i1 @n2(i8 %x, i8 %y) {
    211 ; CHECK-LABEL: @n2(
    212 ; CHECK-NEXT:    [[TMP0:%.*]] = shl i8 [[X:%.*]], 5
    213 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i8 [[TMP0]], 5
    214 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], [[Y:%.*]]
    215 ; CHECK-NEXT:    ret i1 [[TMP2]]
    216 ;
    217   %tmp0 = shl i8 %x, 5
    218   %tmp1 = ashr exact i8 %tmp0, 5
    219   %tmp2 = icmp eq i8 %tmp1, %y ; not %x
    220   ret i1 %tmp2
    221 }
    222 
    223 define <2 x i1> @n3_vec_nonsplat(<2 x i8> %x) {
    224 ; CHECK-LABEL: @n3_vec_nonsplat(
    225 ; CHECK-NEXT:    [[TMP0:%.*]] = shl <2 x i8> [[X:%.*]], <i8 5, i8 5>
    226 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact <2 x i8> [[TMP0]], <i8 5, i8 3>
    227 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], [[X]]
    228 ; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
    229 ;
    230   %tmp0 = shl <2 x i8> %x, <i8 5, i8 5>
    231   %tmp1 = ashr exact <2 x i8> %tmp0, <i8 5, i8 3> ; 3 instead of 5
    232   %tmp2 = icmp eq <2 x i8> %tmp1, %x
    233   ret <2 x i1> %tmp2
    234 }
    235