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 define <2 x i32> @umin_of_nots(<2 x i32> %x, <2 x i32> %y) {
      5 ; CHECK-LABEL: @umin_of_nots(
      6 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <2 x i32> [[X:%.*]], [[Y:%.*]]
      7 ; CHECK-NEXT:    [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[X]], <2 x i32> [[Y]]
      8 ; CHECK-NEXT:    [[MIN:%.*]] = xor <2 x i32> [[TMP2]], <i32 -1, i32 -1>
      9 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
     10 ;
     11   %notx = xor <2 x i32> %x, <i32 -1, i32 -1>
     12   %noty = xor <2 x i32> %y, <i32 -1, i32 -1>
     13   %cmp = icmp ult <2 x i32> %notx, %noty
     14   %min = select <2 x i1> %cmp, <2 x i32> %notx, <2 x i32> %noty
     15   ret <2 x i32> %min
     16 }
     17 
     18 define <2 x i32> @smin_of_nots(<2 x i32> %x, <2 x i32> %y) {
     19 ; CHECK-LABEL: @smin_of_nots(
     20 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <2 x i32> [[X:%.*]], [[Y:%.*]]
     21 ; CHECK-NEXT:    [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[X]], <2 x i32> [[Y]]
     22 ; CHECK-NEXT:    [[MIN:%.*]] = xor <2 x i32> [[TMP2]], <i32 -1, i32 -1>
     23 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
     24 ;
     25   %notx = xor <2 x i32> %x, <i32 -1, i32 -1>
     26   %noty = xor <2 x i32> %y, <i32 -1, i32 -1>
     27   %cmp = icmp sle <2 x i32> %notx, %noty
     28   %min = select <2 x i1> %cmp, <2 x i32> %notx, <2 x i32> %noty
     29   ret <2 x i32> %min
     30 }
     31 
     32 define i32 @compute_min_2(i32 %x, i32 %y) {
     33 ; CHECK-LABEL: @compute_min_2(
     34 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
     35 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[Y]]
     36 ; CHECK-NEXT:    ret i32 [[TMP2]]
     37 ;
     38   %not_x = sub i32 -1, %x
     39   %not_y = sub i32 -1, %y
     40   %cmp = icmp sgt i32 %not_x, %not_y
     41   %not_min = select i1 %cmp, i32 %not_x, i32 %not_y
     42   %min = sub i32 -1, %not_min
     43   ret i32 %min
     44 }
     45 
     46 declare void @extra_use(i8)
     47 define i8 @umin_not_1_extra_use(i8 %x, i8 %y) {
     48 ; CHECK-LABEL: @umin_not_1_extra_use(
     49 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
     50 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]]
     51 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]]
     52 ; CHECK-NEXT:    [[MINXY:%.*]] = xor i8 [[TMP2]], -1
     53 ; CHECK-NEXT:    call void @extra_use(i8 [[NX]])
     54 ; CHECK-NEXT:    ret i8 [[MINXY]]
     55 ;
     56   %nx = xor i8 %x, -1
     57   %ny = xor i8 %y, -1
     58   %cmpxy = icmp ult i8 %nx, %ny
     59   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
     60   call void @extra_use(i8 %nx)
     61   ret i8 %minxy
     62 }
     63 
     64 define i8 @umin_not_2_extra_use(i8 %x, i8 %y) {
     65 ; CHECK-LABEL: @umin_not_2_extra_use(
     66 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
     67 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
     68 ; CHECK-NEXT:    [[CMPXY:%.*]] = icmp ult i8 [[NX]], [[NY]]
     69 ; CHECK-NEXT:    [[MINXY:%.*]] = select i1 [[CMPXY]], i8 [[NX]], i8 [[NY]]
     70 ; CHECK-NEXT:    call void @extra_use(i8 [[NX]])
     71 ; CHECK-NEXT:    call void @extra_use(i8 [[NY]])
     72 ; CHECK-NEXT:    ret i8 [[MINXY]]
     73 ;
     74   %nx = xor i8 %x, -1
     75   %ny = xor i8 %y, -1
     76   %cmpxy = icmp ult i8 %nx, %ny
     77   %minxy = select i1 %cmpxy, i8 %nx, i8 %ny
     78   call void @extra_use(i8 %nx)
     79   call void @extra_use(i8 %ny)
     80   ret i8 %minxy
     81 }
     82 
     83 ; PR35834 - https://bugs.llvm.org/show_bug.cgi?id=35834
     84 
     85 define i8 @umin3_not(i8 %x, i8 %y, i8 %z) {
     86 ; CHECK-LABEL: @umin3_not(
     87 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Z:%.*]]
     88 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Z]]
     89 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i8 [[TMP2]], [[Y:%.*]]
     90 ; CHECK-NEXT:    [[R_V:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 [[Y]]
     91 ; CHECK-NEXT:    [[R:%.*]] = xor i8 [[R_V]], -1
     92 ; CHECK-NEXT:    ret i8 [[R]]
     93 ;
     94   %nx = xor i8 %x, -1
     95   %ny = xor i8 %y, -1
     96   %nz = xor i8 %z, -1
     97   %cmpyx = icmp ult i8 %y, %x
     98   %cmpxz = icmp ult i8 %nx, %nz
     99   %minxz = select i1 %cmpxz, i8 %nx, i8 %nz
    100   %cmpyz = icmp ult i8 %ny, %nz
    101   %minyz = select i1 %cmpyz, i8 %ny, i8 %nz
    102   %r = select i1 %cmpyx, i8 %minxz, i8 %minyz
    103   ret i8 %r
    104 }
    105 
    106 ; PR35875 - https://bugs.llvm.org/show_bug.cgi?id=35875
    107 
    108 define i8 @umin3_not_more_uses(i8 %x, i8 %y, i8 %z) {
    109 ; CHECK-LABEL: @umin3_not_more_uses(
    110 ; CHECK-NEXT:    [[NX:%.*]] = xor i8 [[X:%.*]], -1
    111 ; CHECK-NEXT:    [[NY:%.*]] = xor i8 [[Y:%.*]], -1
    112 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[Z:%.*]]
    113 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Z]]
    114 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ugt i8 [[TMP2]], [[Y]]
    115 ; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 [[Y]]
    116 ; CHECK-NEXT:    [[R:%.*]] = xor i8 [[TMP4]], -1
    117 ; CHECK-NEXT:    call void @extra_use(i8 [[NX]])
    118 ; CHECK-NEXT:    call void @extra_use(i8 [[NY]])
    119 ; CHECK-NEXT:    ret i8 [[R]]
    120 ;
    121   %nx = xor i8 %x, -1
    122   %ny = xor i8 %y, -1
    123   %nz = xor i8 %z, -1
    124   %cmpxz = icmp ult i8 %nx, %nz
    125   %minxz = select i1 %cmpxz, i8 %nx, i8 %nz
    126   %cmpyz = icmp ult i8 %ny, %nz
    127   %minyz = select i1 %cmpyz, i8 %ny, i8 %nz
    128   %cmpyx = icmp ult i8 %y, %x
    129   %r = select i1 %cmpyx, i8 %minxz, i8 %minyz
    130   call void @extra_use(i8 %nx)
    131   call void @extra_use(i8 %ny)
    132   ret i8 %r
    133 }
    134 
    135 declare void @use8(i8)
    136 
    137 define i8 @umin3_not_all_ops_extra_uses(i8 %x, i8 %y, i8 %z) {
    138 ; CHECK-LABEL: @umin3_not_all_ops_extra_uses(
    139 ; CHECK-NEXT:    [[XN:%.*]] = xor i8 [[X:%.*]], -1
    140 ; CHECK-NEXT:    [[YN:%.*]] = xor i8 [[Y:%.*]], -1
    141 ; CHECK-NEXT:    [[ZN:%.*]] = xor i8 [[Z:%.*]], -1
    142 ; CHECK-NEXT:    [[CMPXZ:%.*]] = icmp ult i8 [[XN]], [[ZN]]
    143 ; CHECK-NEXT:    [[MINXZ:%.*]] = select i1 [[CMPXZ]], i8 [[XN]], i8 [[ZN]]
    144 ; CHECK-NEXT:    [[CMPXYZ:%.*]] = icmp ult i8 [[MINXZ]], [[YN]]
    145 ; CHECK-NEXT:    [[MINXYZ:%.*]] = select i1 [[CMPXYZ]], i8 [[MINXZ]], i8 [[YN]]
    146 ; CHECK-NEXT:    call void @use8(i8 [[XN]])
    147 ; CHECK-NEXT:    call void @use8(i8 [[YN]])
    148 ; CHECK-NEXT:    call void @use8(i8 [[ZN]])
    149 ; CHECK-NEXT:    ret i8 [[MINXYZ]]
    150 ;
    151   %xn = xor i8 %x, -1
    152   %yn = xor i8 %y, -1
    153   %zn = xor i8 %z, -1
    154   %cmpxz = icmp ult i8 %xn, %zn
    155   %minxz = select i1 %cmpxz, i8 %xn, i8 %zn
    156   %cmpxyz = icmp ult i8 %minxz, %yn
    157   %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn
    158   call void @use8(i8 %xn)
    159   call void @use8(i8 %yn)
    160   call void @use8(i8 %zn)
    161   ret i8 %minxyz
    162 }
    163 
    164 define void @umin3_not_all_ops_extra_uses_invert_subs(i8 %x, i8 %y, i8 %z) {
    165 ; CHECK-LABEL: @umin3_not_all_ops_extra_uses_invert_subs(
    166 ; CHECK-NEXT:    [[XN:%.*]] = xor i8 [[X:%.*]], -1
    167 ; CHECK-NEXT:    [[YN:%.*]] = xor i8 [[Y:%.*]], -1
    168 ; CHECK-NEXT:    [[ZN:%.*]] = xor i8 [[Z:%.*]], -1
    169 ; CHECK-NEXT:    [[CMPXZ:%.*]] = icmp ult i8 [[XN]], [[ZN]]
    170 ; CHECK-NEXT:    [[MINXZ:%.*]] = select i1 [[CMPXZ]], i8 [[XN]], i8 [[ZN]]
    171 ; CHECK-NEXT:    [[CMPXYZ:%.*]] = icmp ult i8 [[MINXZ]], [[YN]]
    172 ; CHECK-NEXT:    [[MINXYZ:%.*]] = select i1 [[CMPXYZ]], i8 [[MINXZ]], i8 [[YN]]
    173 ; CHECK-NEXT:    [[XMIN:%.*]] = sub i8 [[XN]], [[MINXYZ]]
    174 ; CHECK-NEXT:    [[YMIN:%.*]] = sub i8 [[YN]], [[MINXYZ]]
    175 ; CHECK-NEXT:    [[ZMIN:%.*]] = sub i8 [[ZN]], [[MINXYZ]]
    176 ; CHECK-NEXT:    call void @use8(i8 [[MINXYZ]])
    177 ; CHECK-NEXT:    call void @use8(i8 [[XMIN]])
    178 ; CHECK-NEXT:    call void @use8(i8 [[YMIN]])
    179 ; CHECK-NEXT:    call void @use8(i8 [[ZMIN]])
    180 ; CHECK-NEXT:    ret void
    181 ;
    182   %xn = xor i8 %x, -1
    183   %yn = xor i8 %y, -1
    184   %zn = xor i8 %z, -1
    185   %cmpxz = icmp ult i8 %xn, %zn
    186   %minxz = select i1 %cmpxz, i8 %xn, i8 %zn
    187   %cmpxyz = icmp ult i8 %minxz, %yn
    188   %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn
    189   %xmin = sub i8 %xn, %minxyz
    190   %ymin = sub i8 %yn, %minxyz
    191   %zmin = sub i8 %zn, %minxyz
    192   call void @use8(i8 %minxyz)
    193   call void @use8(i8 %xmin)
    194   call void @use8(i8 %ymin)
    195   call void @use8(i8 %zmin)
    196   ret void
    197 }
    198 
    199 define i32 @compute_min_3(i32 %x, i32 %y, i32 %z) {
    200 ; CHECK-LABEL: @compute_min_3(
    201 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
    202 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[Y]]
    203 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP2]], [[Z:%.*]]
    204 ; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 [[Z]]
    205 ; CHECK-NEXT:    ret i32 [[TMP4]]
    206 ;
    207   %not_x = sub i32 -1, %x
    208   %not_y = sub i32 -1, %y
    209   %not_z = sub i32 -1, %z
    210   %cmp_1 = icmp sgt i32 %not_x, %not_y
    211   %not_min_1 = select i1 %cmp_1, i32 %not_x, i32 %not_y
    212   %cmp_2 = icmp sgt i32 %not_min_1, %not_z
    213   %not_min_2 = select i1 %cmp_2, i32 %not_min_1, i32 %not_z
    214   %min = sub i32 -1, %not_min_2
    215   ret i32 %min
    216 }
    217 
    218 ; Don't increase the critical path by moving the 'not' op after the 'select'.
    219 
    220 define i32 @compute_min_arithmetic(i32 %x, i32 %y) {
    221 ; CHECK-LABEL: @compute_min_arithmetic(
    222 ; CHECK-NEXT:    [[NOT_VALUE:%.*]] = sub i32 3, [[X:%.*]]
    223 ; CHECK-NEXT:    [[NOT_Y:%.*]] = xor i32 [[Y:%.*]], -1
    224 ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[NOT_VALUE]], [[NOT_Y]]
    225 ; CHECK-NEXT:    [[NOT_MIN:%.*]] = select i1 [[CMP]], i32 [[NOT_VALUE]], i32 [[NOT_Y]]
    226 ; CHECK-NEXT:    ret i32 [[NOT_MIN]]
    227 ;
    228   %not_value = sub i32 3, %x
    229   %not_y = sub i32 -1, %y
    230   %cmp = icmp sgt i32 %not_value, %not_y
    231   %not_min = select i1 %cmp, i32 %not_value, i32 %not_y
    232   ret i32 %not_min
    233 }
    234 
    235 declare void @fake_use(i32)
    236 
    237 define i32 @compute_min_pessimization(i32 %x, i32 %y) {
    238 ; CHECK-LABEL: @compute_min_pessimization(
    239 ; CHECK-NEXT:    [[NOT_VALUE:%.*]] = sub i32 3, [[X:%.*]]
    240 ; CHECK-NEXT:    call void @fake_use(i32 [[NOT_VALUE]])
    241 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[X]], -4
    242 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[TMP1]], [[Y:%.*]]
    243 ; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[TMP2]], i32 [[Y]], i32 [[TMP1]]
    244 ; CHECK-NEXT:    ret i32 [[MIN]]
    245 ;
    246   %not_value = sub i32 3, %x
    247   call void @fake_use(i32 %not_value)
    248   %not_y = sub i32 -1, %y
    249   %cmp = icmp sgt i32 %not_value, %not_y
    250   %not_min = select i1 %cmp, i32 %not_value, i32 %not_y
    251   %min = sub i32 -1, %not_min
    252   ret i32 %min
    253 }
    254 
    255 define i32 @max_of_nots(i32 %x, i32 %y) {
    256 ; CHECK-LABEL: @max_of_nots(
    257 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[Y:%.*]], 0
    258 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[Y]], i32 0
    259 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP2]], [[X:%.*]]
    260 ; CHECK-NEXT:    [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 [[X]]
    261 ; CHECK-NEXT:    [[TMP5:%.*]] = xor i32 [[TMP4]], -1
    262 ; CHECK-NEXT:    ret i32 [[TMP5]]
    263 ;
    264   %c0 = icmp sgt i32 %y, 0
    265   %xor_y = xor i32 %y, -1
    266   %s0 = select i1 %c0, i32 %xor_y, i32 -1
    267   %xor_x = xor i32 %x, -1
    268   %c1 = icmp slt i32 %s0, %xor_x
    269   %smax96 = select i1 %c1, i32 %xor_x, i32 %s0
    270   ret i32 %smax96
    271 }
    272 
    273  ; negative test case (i.e. can not simplify) : ABS(MIN(NOT x,y))
    274 define i32 @abs_of_min_of_not(i32 %x, i32 %y) {
    275 ; CHECK-LABEL: @abs_of_min_of_not(
    276 ; CHECK-NEXT:    [[XORD:%.*]] = xor i32 [[X:%.*]], -1
    277 ; CHECK-NEXT:    [[YADD:%.*]] = add i32 [[Y:%.*]], 2
    278 ; CHECK-NEXT:    [[COND_I:%.*]] = icmp slt i32 [[YADD]], [[XORD]]
    279 ; CHECK-NEXT:    [[MIN:%.*]] = select i1 [[COND_I]], i32 [[YADD]], i32 [[XORD]]
    280 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[MIN]], 0
    281 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[MIN]]
    282 ; CHECK-NEXT:    [[ABS:%.*]] = select i1 [[CMP2]], i32 [[SUB]], i32 [[MIN]]
    283 ; CHECK-NEXT:    ret i32 [[ABS]]
    284 ;
    285 
    286   %xord = xor i32 %x, -1
    287   %yadd = add i32 %y, 2
    288   %cond.i = icmp sge i32 %yadd, %xord
    289   %min = select i1 %cond.i, i32 %xord, i32 %yadd
    290   %cmp2 = icmp sgt i32 %min, -1
    291   %sub = sub i32 0, %min
    292   %abs = select i1 %cmp2, i32 %min, i32 %sub
    293   ret i32  %abs
    294 }
    295 
    296 define <2 x i32> @max_of_nots_vec(<2 x i32> %x, <2 x i32> %y) {
    297 ; CHECK-LABEL: @max_of_nots_vec(
    298 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <2 x i32> [[Y:%.*]], zeroinitializer
    299 ; CHECK-NEXT:    [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[Y]], <2 x i32> zeroinitializer
    300 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt <2 x i32> [[TMP2]], [[X:%.*]]
    301 ; CHECK-NEXT:    [[TMP4:%.*]] = select <2 x i1> [[TMP3]], <2 x i32> [[TMP2]], <2 x i32> [[X]]
    302 ; CHECK-NEXT:    [[TMP5:%.*]] = xor <2 x i32> [[TMP4]], <i32 -1, i32 -1>
    303 ; CHECK-NEXT:    ret <2 x i32> [[TMP5]]
    304 ;
    305   %c0 = icmp sgt <2 x i32> %y, zeroinitializer
    306   %xor_y = xor <2 x i32> %y, <i32 -1, i32 -1>
    307   %s0 = select <2 x i1> %c0, <2 x i32> %xor_y, <2 x i32> <i32 -1, i32 -1>
    308   %xor_x = xor <2 x i32> %x, <i32 -1, i32 -1>
    309   %c1 = icmp slt <2 x i32> %s0, %xor_x
    310   %smax96 = select <2 x i1> %c1, <2 x i32> %xor_x, <2 x i32> %s0
    311   ret <2 x i32> %smax96
    312 }
    313 
    314 define <2 x i37> @max_of_nots_weird_type_vec(<2 x i37> %x, <2 x i37> %y) {
    315 ; CHECK-LABEL: @max_of_nots_weird_type_vec(
    316 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <2 x i37> [[Y:%.*]], zeroinitializer
    317 ; CHECK-NEXT:    [[TMP2:%.*]] = select <2 x i1> [[TMP1]], <2 x i37> [[Y]], <2 x i37> zeroinitializer
    318 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp slt <2 x i37> [[TMP2]], [[X:%.*]]
    319 ; CHECK-NEXT:    [[TMP4:%.*]] = select <2 x i1> [[TMP3]], <2 x i37> [[TMP2]], <2 x i37> [[X]]
    320 ; CHECK-NEXT:    [[TMP5:%.*]] = xor <2 x i37> [[TMP4]], <i37 -1, i37 -1>
    321 ; CHECK-NEXT:    ret <2 x i37> [[TMP5]]
    322 ;
    323   %c0 = icmp sgt <2 x i37> %y, zeroinitializer
    324   %xor_y = xor <2 x i37> %y, <i37 -1, i37 -1>
    325   %s0 = select <2 x i1> %c0, <2 x i37> %xor_y, <2 x i37> <i37 -1, i37 -1>
    326   %xor_x = xor <2 x i37> %x, <i37 -1, i37 -1>
    327   %c1 = icmp slt <2 x i37> %s0, %xor_x
    328   %smax96 = select <2 x i1> %c1, <2 x i37> %xor_x, <2 x i37> %s0
    329   ret <2 x i37> %smax96
    330 }
    331 
    332 ; max(min(%a, -1), -1) == -1
    333 define i32 @max_of_min(i32 %a) {
    334 ; CHECK-LABEL: @max_of_min(
    335 ; CHECK-NEXT:    ret i32 -1
    336 ;
    337   %not_a = xor i32 %a, -1
    338   %c0 = icmp sgt i32 %a, 0
    339   %s0 = select i1 %c0, i32 %not_a, i32 -1
    340   %c1 = icmp sgt i32 %s0, -1
    341   %s1 = select i1 %c1, i32 %s0, i32 -1
    342   ret i32 %s1
    343 }
    344 
    345 ; max(min(%a, -1), -1) == -1 (swap predicate and select ops)
    346 define i32 @max_of_min_swap(i32 %a) {
    347 ; CHECK-LABEL: @max_of_min_swap(
    348 ; CHECK-NEXT:    ret i32 -1
    349 ;
    350   %not_a = xor i32 %a, -1
    351   %c0 = icmp slt i32 %a, 0
    352   %s0 = select i1 %c0, i32 -1, i32 %not_a
    353   %c1 = icmp sgt i32 %s0, -1
    354   %s1 = select i1 %c1, i32 %s0, i32 -1
    355   ret i32 %s1
    356 }
    357 
    358 ; min(max(%a, -1), -1) == -1
    359 define i32 @min_of_max(i32 %a) {
    360 ; CHECK-LABEL: @min_of_max(
    361 ; CHECK-NEXT:    ret i32 -1
    362 ;
    363   %not_a = xor i32 %a, -1
    364   %c0 = icmp slt i32 %a, 0
    365   %s0 = select i1 %c0, i32 %not_a, i32 -1
    366   %c1 = icmp slt i32 %s0, -1
    367   %s1 = select i1 %c1, i32 %s0, i32 -1
    368   ret i32 %s1
    369 }
    370 
    371 ; min(max(%a, -1), -1) == -1 (swap predicate and select ops)
    372 define i32 @min_of_max_swap(i32 %a) {
    373 ; CHECK-LABEL: @min_of_max_swap(
    374 ; CHECK-NEXT:    ret i32 -1
    375 ;
    376   %not_a = xor i32 %a, -1
    377   %c0 = icmp sgt i32 %a, 0
    378   %s0 = select i1 %c0, i32 -1, i32 %not_a
    379   %c1 = icmp slt i32 %s0, -1
    380   %s1 = select i1 %c1, i32 %s0, i32 -1
    381   ret i32 %s1
    382 }
    383 
    384 define <2 x i32> @max_of_min_vec(<2 x i32> %a) {
    385 ; CHECK-LABEL: @max_of_min_vec(
    386 ; CHECK-NEXT:    ret <2 x i32> <i32 -1, i32 -1>
    387 ;
    388   %not_a = xor <2 x i32> %a, <i32 -1, i32 -1>
    389   %c0 = icmp sgt <2 x i32> %a, zeroinitializer
    390   %s0 = select <2 x i1> %c0, <2 x i32> %not_a, <2 x i32> <i32 -1, i32 -1>
    391   %c1 = icmp sgt <2 x i32> %s0, <i32 -1, i32 -1>
    392   %s1 = select <2 x i1> %c1, <2 x i32> %s0, <2 x i32> <i32 -1, i32 -1>
    393   ret <2 x i32> %s1
    394 }
    395 
    396