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=38123
      5 
      6 ; Pattern:
      7 ;   x u<= x & C
      8 ; Should be transformed into:
      9 ;   x u<= C
     10 ; Iff: isPowerOf2(C + 1)
     11 
     12 declare i8 @gen8()
     13 declare <2 x i8> @gen2x8()
     14 declare <3 x i8> @gen3x8()
     15 
     16 ; ============================================================================ ;
     17 ; Basic positive tests
     18 ; ============================================================================ ;
     19 
     20 define i1 @p0() {
     21 ; CHECK-LABEL: @p0(
     22 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
     23 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X]], 4
     24 ; CHECK-NEXT:    ret i1 [[TMP1]]
     25 ;
     26   %x = call i8 @gen8()
     27   %tmp0 = and i8 %x, 3
     28   %ret = icmp ule i8 %x, %tmp0
     29   ret i1 %ret
     30 }
     31 
     32 define i1 @pv(i8 %y) {
     33 ; CHECK-LABEL: @pv(
     34 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
     35 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
     36 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i8 [[X]], [[TMP0]]
     37 ; CHECK-NEXT:    ret i1 [[TMP1]]
     38 ;
     39   %x = call i8 @gen8()
     40   %tmp0 = lshr i8 -1, %y
     41   %tmp1 = and i8 %tmp0, %x
     42   %ret = icmp ule i8 %x, %tmp1
     43   ret i1 %ret
     44 }
     45 
     46 ; ============================================================================ ;
     47 ; Vector tests
     48 ; ============================================================================ ;
     49 
     50 define <2 x i1> @p1_vec_splat() {
     51 ; CHECK-LABEL: @p1_vec_splat(
     52 ; CHECK-NEXT:    [[X:%.*]] = call <2 x i8> @gen2x8()
     53 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], <i8 4, i8 4>
     54 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
     55 ;
     56   %x = call <2 x i8> @gen2x8()
     57   %tmp0 = and <2 x i8> %x, <i8 3, i8 3>
     58   %ret = icmp ule <2 x i8> %x, %tmp0
     59   ret <2 x i1> %ret
     60 }
     61 
     62 define <2 x i1> @p2_vec_nonsplat() {
     63 ; CHECK-LABEL: @p2_vec_nonsplat(
     64 ; CHECK-NEXT:    [[X:%.*]] = call <2 x i8> @gen2x8()
     65 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[X]], <i8 4, i8 16>
     66 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
     67 ;
     68   %x = call <2 x i8> @gen2x8()
     69   %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat.
     70   %ret = icmp ule <2 x i8> %x, %tmp0
     71   ret <2 x i1> %ret
     72 }
     73 
     74 define <3 x i1> @p3_vec_splat_undef() {
     75 ; CHECK-LABEL: @p3_vec_splat_undef(
     76 ; CHECK-NEXT:    [[X:%.*]] = call <3 x i8> @gen3x8()
     77 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <3 x i8> [[X]], <i8 4, i8 undef, i8 4>
     78 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
     79 ;
     80   %x = call <3 x i8> @gen3x8()
     81   %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 3>
     82   %ret = icmp ule <3 x i8> %x, %tmp0
     83   ret <3 x i1> %ret
     84 }
     85 
     86 ; ============================================================================ ;
     87 ; Commutativity tests.
     88 ; ============================================================================ ;
     89 
     90 define i1 @c0(i8 %x) {
     91 ; CHECK-LABEL: @c0(
     92 ; CHECK-NEXT:    ret i1 true
     93 ;
     94   %tmp0 = and i8 %x, 3
     95   %ret = icmp ule i8 %tmp0, %x ; swapped order
     96   ret i1 %ret
     97 }
     98 
     99 ; ============================================================================ ;
    100 ; Commutativity tests with variable
    101 ; ============================================================================ ;
    102 
    103 define i1 @cv0(i8 %y) {
    104 ; CHECK-LABEL: @cv0(
    105 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
    106 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
    107 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i8 [[X]], [[TMP0]]
    108 ; CHECK-NEXT:    ret i1 [[TMP1]]
    109 ;
    110   %x = call i8 @gen8()
    111   %tmp0 = lshr i8 -1, %y
    112   %tmp1 = and i8 %tmp0, %x ; swapped order
    113   %ret = icmp ule i8 %x, %tmp1
    114   ret i1 %ret
    115 }
    116 
    117 define i1 @cv1(i8 %y) {
    118 ; CHECK-LABEL: @cv1(
    119 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
    120 ; CHECK-NEXT:    ret i1 true
    121 ;
    122   %x = call i8 @gen8()
    123   %tmp0 = lshr i8 -1, %y
    124   %tmp1 = and i8 %x, %tmp0
    125   %ret = icmp ule i8 %tmp1, %x ; swapped order
    126   ret i1 %ret
    127 }
    128 
    129 define i1 @cv2(i8 %x, i8 %y) {
    130 ; CHECK-LABEL: @cv2(
    131 ; CHECK-NEXT:    ret i1 true
    132 ;
    133   %tmp0 = lshr i8 -1, %y
    134   %tmp1 = and i8 %tmp0, %x ; swapped order
    135   %ret = icmp ule i8 %tmp1, %x ; swapped order
    136   ret i1 %ret
    137 }
    138 
    139 ; ============================================================================ ;
    140 ; One-use tests. We don't care about multi-uses here.
    141 ; ============================================================================ ;
    142 
    143 declare void @use8(i8)
    144 
    145 define i1 @oneuse0() {
    146 ; CHECK-LABEL: @oneuse0(
    147 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
    148 ; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X]], 3
    149 ; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
    150 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X]], 4
    151 ; CHECK-NEXT:    ret i1 [[TMP1]]
    152 ;
    153   %x = call i8 @gen8()
    154   %tmp0 = and i8 %x, 3
    155   call void @use8(i8 %tmp0)
    156   %ret = icmp ule i8 %x, %tmp0
    157   ret i1 %ret
    158 }
    159 
    160 ; ============================================================================ ;
    161 ; Negative tests
    162 ; ============================================================================ ;
    163 
    164 define i1 @n0() {
    165 ; CHECK-LABEL: @n0(
    166 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
    167 ; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X]], 4
    168 ; CHECK-NEXT:    [[RET:%.*]] = icmp ule i8 [[X]], [[TMP0]]
    169 ; CHECK-NEXT:    ret i1 [[RET]]
    170 ;
    171   %x = call i8 @gen8()
    172   %tmp0 = and i8 %x, 4 ; power-of-two, but invalid.
    173   %ret = icmp ule i8 %x, %tmp0
    174   ret i1 %ret
    175 }
    176 
    177 define i1 @n1(i8 %y, i8 %notx) {
    178 ; CHECK-LABEL: @n1(
    179 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
    180 ; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X]], 3
    181 ; CHECK-NEXT:    [[RET:%.*]] = icmp ule i8 [[TMP0]], [[NOTX:%.*]]
    182 ; CHECK-NEXT:    ret i1 [[RET]]
    183 ;
    184   %x = call i8 @gen8()
    185   %tmp0 = and i8 %x, 3
    186   %ret = icmp ule i8 %tmp0, %notx ; not %x
    187   ret i1 %ret
    188 }
    189 
    190 define <2 x i1> @n2() {
    191 ; CHECK-LABEL: @n2(
    192 ; CHECK-NEXT:    [[X:%.*]] = call <2 x i8> @gen2x8()
    193 ; CHECK-NEXT:    [[TMP0:%.*]] = and <2 x i8> [[X]], <i8 3, i8 16>
    194 ; CHECK-NEXT:    [[RET:%.*]] = icmp ule <2 x i8> [[X]], [[TMP0]]
    195 ; CHECK-NEXT:    ret <2 x i1> [[RET]]
    196 ;
    197   %x = call <2 x i8> @gen2x8()
    198   %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.
    199   %ret = icmp ule <2 x i8> %x, %tmp0
    200   ret <2 x i1> %ret
    201 }
    202