Home | History | Annotate | Download | only in EarlyCSE
      1 ; RUN: opt < %s -S -early-cse | FileCheck %s
      2 ; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
      3 
      4 define void @test1(float %A, float %B, float* %PA, float* %PB) {
      5 ; CHECK-LABEL: @test1(
      6 ; CHECK-NEXT:    [[C:%.*]] = fadd float %A, %B
      7 ; CHECK-NEXT:    store float [[C]], float* %PA
      8 ; CHECK-NEXT:    store float [[C]], float* %PB
      9 ; CHECK-NEXT:    ret void
     10 ;
     11   %C = fadd float %A, %B
     12   store float %C, float* %PA
     13   %D = fadd float %B, %A
     14   store float %D, float* %PB
     15   ret void
     16 }
     17 
     18 define void @test2(float %A, float %B, i1* %PA, i1* %PB) {
     19 ; CHECK-LABEL: @test2(
     20 ; CHECK-NEXT:    [[C:%.*]] = fcmp oeq float %A, %B
     21 ; CHECK-NEXT:    store i1 [[C]], i1* %PA
     22 ; CHECK-NEXT:    store i1 [[C]], i1* %PB
     23 ; CHECK-NEXT:    ret void
     24 ;
     25   %C = fcmp oeq float %A, %B
     26   store i1 %C, i1* %PA
     27   %D = fcmp oeq float %B, %A
     28   store i1 %D, i1* %PB
     29   ret void
     30 }
     31 
     32 define void @test3(float %A, float %B, i1* %PA, i1* %PB) {
     33 ; CHECK-LABEL: @test3(
     34 ; CHECK-NEXT:    [[C:%.*]] = fcmp uge float %A, %B
     35 ; CHECK-NEXT:    store i1 [[C]], i1* %PA
     36 ; CHECK-NEXT:    store i1 [[C]], i1* %PB
     37 ; CHECK-NEXT:    ret void
     38 ;
     39   %C = fcmp uge float %A, %B
     40   store i1 %C, i1* %PA
     41   %D = fcmp ule float %B, %A
     42   store i1 %D, i1* %PB
     43   ret void
     44 }
     45 
     46 define void @test4(i32 %A, i32 %B, i1* %PA, i1* %PB) {
     47 ; CHECK-LABEL: @test4(
     48 ; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 %A, %B
     49 ; CHECK-NEXT:    store i1 [[C]], i1* %PA
     50 ; CHECK-NEXT:    store i1 [[C]], i1* %PB
     51 ; CHECK-NEXT:    ret void
     52 ;
     53   %C = icmp eq i32 %A, %B
     54   store i1 %C, i1* %PA
     55   %D = icmp eq i32 %B, %A
     56   store i1 %D, i1* %PB
     57   ret void
     58 }
     59 
     60 define void @test5(i32 %A, i32 %B, i1* %PA, i1* %PB) {
     61 ; CHECK-LABEL: @test5(
     62 ; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 %A, %B
     63 ; CHECK-NEXT:    store i1 [[C]], i1* %PA
     64 ; CHECK-NEXT:    store i1 [[C]], i1* %PB
     65 ; CHECK-NEXT:    ret void
     66 ;
     67   %C = icmp sgt i32 %A, %B
     68   store i1 %C, i1* %PA
     69   %D = icmp slt i32 %B, %A
     70   store i1 %D, i1* %PB
     71   ret void
     72 }
     73 
     74 ; Min/max operands may be commuted in the compare and select.
     75 
     76 define i8 @smin_commute(i8 %a, i8 %b) {
     77 ; CHECK-LABEL: @smin_commute(
     78 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
     79 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %b, %a
     80 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
     81 ; CHECK-NEXT:    [[R:%.*]] = mul i8 [[M1]], [[M1]]
     82 ; CHECK-NEXT:    ret i8 [[R]]
     83 ;
     84   %cmp1 = icmp slt i8 %a, %b
     85   %cmp2 = icmp slt i8 %b, %a
     86   %m1 = select i1 %cmp1, i8 %a, i8 %b
     87   %m2 = select i1 %cmp2, i8 %b, i8 %a
     88   %r = mul i8 %m1, %m2
     89   ret i8 %r
     90 }
     91 
     92 ; Min/max can also have a swapped predicate and select operands.
     93 
     94 define i1 @smin_swapped(i8 %a, i8 %b) {
     95 ; CHECK-LABEL: @smin_swapped(
     96 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
     97 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, %b
     98 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a
     99 ; CHECK-NEXT:    ret i1 true
    100 ;
    101   %cmp1 = icmp sgt i8 %a, %b
    102   %cmp2 = icmp slt i8 %a, %b
    103   %m1 = select i1 %cmp1, i8 %b, i8 %a
    104   %m2 = select i1 %cmp2, i8 %a, i8 %b
    105   %r = icmp eq i8 %m2, %m1
    106   ret i1 %r
    107 }
    108 
    109 define i8 @smax_commute(i8 %a, i8 %b) {
    110 ; CHECK-LABEL: @smax_commute(
    111 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, %b
    112 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %b, %a
    113 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
    114 ; CHECK-NEXT:    ret i8 0
    115 ;
    116   %cmp1 = icmp sgt i8 %a, %b
    117   %cmp2 = icmp sgt i8 %b, %a
    118   %m1 = select i1 %cmp1, i8 %a, i8 %b
    119   %m2 = select i1 %cmp2, i8 %b, i8 %a
    120   %r = urem i8 %m2, %m1
    121   ret i8 %r
    122 }
    123 
    124 define i8 @smax_swapped(i8 %a, i8 %b) {
    125 ; CHECK-LABEL: @smax_swapped(
    126 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
    127 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, %b
    128 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a
    129 ; CHECK-NEXT:    ret i8 1
    130 ;
    131   %cmp1 = icmp slt i8 %a, %b
    132   %cmp2 = icmp sgt i8 %a, %b
    133   %m1 = select i1 %cmp1, i8 %b, i8 %a
    134   %m2 = select i1 %cmp2, i8 %a, i8 %b
    135   %r = sdiv i8 %m1, %m2
    136   ret i8 %r
    137 }
    138 
    139 define i8 @umin_commute(i8 %a, i8 %b) {
    140 ; CHECK-LABEL: @umin_commute(
    141 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
    142 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 %b, %a
    143 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
    144 ; CHECK-NEXT:    ret i8 0
    145 ;
    146   %cmp1 = icmp ult i8 %a, %b
    147   %cmp2 = icmp ult i8 %b, %a
    148   %m1 = select i1 %cmp1, i8 %a, i8 %b
    149   %m2 = select i1 %cmp2, i8 %b, i8 %a
    150   %r = sub i8 %m2, %m1
    151   ret i8 %r
    152 }
    153 
    154 ; Choose a vector type just to show that works.
    155 
    156 define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) {
    157 ; CHECK-LABEL: @umin_swapped(
    158 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt <2 x i8> %a, %b
    159 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult <2 x i8> %a, %b
    160 ; CHECK-NEXT:    [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> %b, <2 x i8> %a
    161 ; CHECK-NEXT:    ret <2 x i8> zeroinitializer
    162 ;
    163   %cmp1 = icmp ugt <2 x i8> %a, %b
    164   %cmp2 = icmp ult <2 x i8> %a, %b
    165   %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a
    166   %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b
    167   %r = sub <2 x i8> %m2, %m1
    168   ret <2 x i8> %r
    169 }
    170 
    171 define i8 @umax_commute(i8 %a, i8 %b) {
    172 ; CHECK-LABEL: @umax_commute(
    173 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i8 %a, %b
    174 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %b, %a
    175 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
    176 ; CHECK-NEXT:    ret i8 1
    177 ;
    178   %cmp1 = icmp ugt i8 %a, %b
    179   %cmp2 = icmp ugt i8 %b, %a
    180   %m1 = select i1 %cmp1, i8 %a, i8 %b
    181   %m2 = select i1 %cmp2, i8 %b, i8 %a
    182   %r = udiv i8 %m1, %m2
    183   ret i8 %r
    184 }
    185 
    186 define i8 @umax_swapped(i8 %a, i8 %b) {
    187 ; CHECK-LABEL: @umax_swapped(
    188 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i8 %a, %b
    189 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i8 %a, %b
    190 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a
    191 ; CHECK-NEXT:    [[R:%.*]] = add i8 [[M1]], [[M1]]
    192 ; CHECK-NEXT:    ret i8 [[R]]
    193 ;
    194   %cmp1 = icmp ult i8 %a, %b
    195   %cmp2 = icmp ugt i8 %a, %b
    196   %m1 = select i1 %cmp1, i8 %b, i8 %a
    197   %m2 = select i1 %cmp2, i8 %a, i8 %b
    198   %r = add i8 %m2, %m1
    199   ret i8 %r
    200 }
    201 
    202 ; Min/max may exist with non-canonical operands. Value tracking can match those.
    203 
    204 define i8 @smax_nsw(i8 %a, i8 %b) {
    205 ; CHECK-LABEL: @smax_nsw(
    206 ; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i8 %a, %b
    207 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, %b
    208 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0
    209 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]
    210 ; CHECK-NEXT:    ret i8 0
    211 ;
    212   %sub = sub nsw i8 %a, %b
    213   %cmp1 = icmp slt i8 %a, %b
    214   %cmp2 = icmp sgt i8 %sub, 0
    215   %m1 = select i1 %cmp1, i8 0, i8 %sub
    216   %m2 = select i1 %cmp2, i8 %sub, i8 0
    217   %r = sub i8 %m2, %m1
    218   ret i8 %r
    219 }
    220 
    221 define i8 @abs_swapped(i8 %a) {
    222 ; CHECK-LABEL: @abs_swapped(
    223 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, %a
    224 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, 0
    225 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, 0
    226 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]]
    227 ; CHECK-NEXT:    ret i8 [[M1]]
    228 ;
    229   %neg = sub i8 0, %a
    230   %cmp1 = icmp sgt i8 %a, 0
    231   %cmp2 = icmp slt i8 %a, 0
    232   %m1 = select i1 %cmp1, i8 %a, i8 %neg
    233   %m2 = select i1 %cmp2, i8 %neg, i8 %a
    234   %r = or i8 %m2, %m1
    235   ret i8 %r
    236 }
    237 
    238 define i8 @nabs_swapped(i8 %a) {
    239 ; CHECK-LABEL: @nabs_swapped(
    240 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, %a
    241 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, 0
    242 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, 0
    243 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]]
    244 ; CHECK-NEXT:    ret i8 0
    245 ;
    246   %neg = sub i8 0, %a
    247   %cmp1 = icmp slt i8 %a, 0
    248   %cmp2 = icmp sgt i8 %a, 0
    249   %m1 = select i1 %cmp1, i8 %a, i8 %neg
    250   %m2 = select i1 %cmp2, i8 %neg, i8 %a
    251   %r = xor i8 %m2, %m1
    252   ret i8 %r
    253 }
    254 
    255 ; These two tests make sure we still consider it a match when the RHS of the
    256 ; compares are different.
    257 define i8 @abs_different_constants(i8 %a) {
    258 ; CHECK-LABEL: @abs_different_constants(
    259 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, %a
    260 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp sgt i8 %a, -1
    261 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i8 %a, 0
    262 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]]
    263 ; CHECK-NEXT:    ret i8 [[M1]]
    264 ;
    265   %neg = sub i8 0, %a
    266   %cmp1 = icmp sgt i8 %a, -1
    267   %cmp2 = icmp slt i8 %a, 0
    268   %m1 = select i1 %cmp1, i8 %a, i8 %neg
    269   %m2 = select i1 %cmp2, i8 %neg, i8 %a
    270   %r = or i8 %m2, %m1
    271   ret i8 %r
    272 }
    273 
    274 define i8 @nabs_different_constants(i8 %a) {
    275 ; CHECK-LABEL: @nabs_different_constants(
    276 ; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, %a
    277 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i8 %a, 0
    278 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i8 %a, -1
    279 ; CHECK-NEXT:    [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 [[NEG]]
    280 ; CHECK-NEXT:    ret i8 0
    281 ;
    282   %neg = sub i8 0, %a
    283   %cmp1 = icmp slt i8 %a, 0
    284   %cmp2 = icmp sgt i8 %a, -1
    285   %m1 = select i1 %cmp1, i8 %a, i8 %neg
    286   %m2 = select i1 %cmp2, i8 %neg, i8 %a
    287   %r = xor i8 %m2, %m1
    288   ret i8 %r
    289 }
    290 
    291