Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt -instcombine -S < %s | FileCheck %s
      2 
      3 ; This test is to verify that the instruction combiner is able to fold
      4 ; a cttz/ctlz followed by a icmp + select into a single cttz/ctlz with
      5 ; the 'is_zero_undef' flag cleared.
      6 
      7 define i16 @test1(i16 %x) {
      8 ; CHECK-LABEL: @test1(
      9 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
     10 ; CHECK-NEXT: ret i16 [[VAR]]
     11 entry:
     12   %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
     13   %tobool = icmp ne i16 %x, 0
     14   %cond = select i1 %tobool, i16 %0, i16 16
     15   ret i16 %cond
     16 }
     17 
     18 define i32 @test2(i32 %x) {
     19 ; CHECK-LABEL: @test2(
     20 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
     21 ; CHECK-NEXT: ret i32 [[VAR]]
     22 entry:
     23   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
     24   %tobool = icmp ne i32 %x, 0
     25   %cond = select i1 %tobool, i32 %0, i32 32
     26   ret i32 %cond
     27 }
     28 
     29 define i64 @test3(i64 %x) {
     30 ; CHECK-LABEL: @test3(
     31 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
     32 ; CHECK-NEXT: ret i64 [[VAR]]
     33 entry:
     34   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
     35   %tobool = icmp ne i64 %x, 0
     36   %cond = select i1 %tobool, i64 %0, i64 64
     37   ret i64 %cond
     38 }
     39 
     40 define i16 @test4(i16 %x) {
     41 ; CHECK-LABEL: @test4(
     42 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
     43 ; CHECK-NEXT: ret i16 [[VAR]]
     44 entry:
     45   %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
     46   %tobool = icmp eq i16 %x, 0
     47   %cond = select i1 %tobool, i16 16, i16 %0
     48   ret i16 %cond
     49 }
     50 
     51 define i32 @test5(i32 %x) {
     52 ; CHECK-LABEL: @test5(
     53 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
     54 ; CHECK-NEXT: ret i32 [[VAR]]
     55 entry:
     56   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
     57   %tobool = icmp eq i32 %x, 0
     58   %cond = select i1 %tobool, i32 32, i32 %0
     59   ret i32 %cond
     60 }
     61 
     62 define i64 @test6(i64 %x) {
     63 ; CHECK-LABEL: @test6(
     64 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
     65 ; CHECK-NEXT: ret i64 [[VAR]]
     66 entry:
     67   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
     68   %tobool = icmp eq i64 %x, 0
     69   %cond = select i1 %tobool, i64 64, i64 %0
     70   ret i64 %cond
     71 }
     72 
     73 define i16 @test1b(i16 %x) {
     74 ; CHECK-LABEL: @test1b(
     75 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
     76 ; CHECK-NEXT: ret i16 [[VAR]]
     77 entry:
     78   %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
     79   %tobool = icmp ne i16 %x, 0
     80   %cond = select i1 %tobool, i16 %0, i16 16
     81   ret i16 %cond
     82 }
     83 
     84 define i32 @test2b(i32 %x) {
     85 ; CHECK-LABEL: @test2b(
     86 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
     87 ; CHECK-NEXT: ret i32 [[VAR]]
     88 entry:
     89   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
     90   %tobool = icmp ne i32 %x, 0
     91   %cond = select i1 %tobool, i32 %0, i32 32
     92   ret i32 %cond
     93 }
     94 
     95 define i64 @test3b(i64 %x) {
     96 ; CHECK-LABEL: @test3b(
     97 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
     98 ; CHECK-NEXT: ret i64 [[VAR]]
     99 entry:
    100   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    101   %tobool = icmp ne i64 %x, 0
    102   %cond = select i1 %tobool, i64 %0, i64 64
    103   ret i64 %cond
    104 }
    105 
    106 define i16 @test4b(i16 %x) {
    107 ; CHECK-LABEL: @test4b(
    108 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
    109 ; CHECK-NEXT: ret i16 [[VAR]]
    110 entry:
    111   %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
    112   %tobool = icmp eq i16 %x, 0
    113   %cond = select i1 %tobool, i16 16, i16 %0
    114   ret i16 %cond
    115 }
    116 
    117 define i32 @test5b(i32 %x) {
    118 ; CHECK-LABEL: @test5b(
    119 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    120 ; CHECK-NEXT: ret i32 [[VAR]]
    121 entry:
    122   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    123   %tobool = icmp eq i32 %x, 0
    124   %cond = select i1 %tobool, i32 32, i32 %0
    125   ret i32 %cond
    126 }
    127 
    128 define i64 @test6b(i64 %x) {
    129 ; CHECK-LABEL: @test6b(
    130 ; CHECK: [[VAR:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
    131 ; CHECK-NEXT: ret i64 [[VAR]]
    132 entry:
    133   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    134   %tobool = icmp eq i64 %x, 0
    135   %cond = select i1 %tobool, i64 64, i64 %0
    136   ret i64 %cond
    137 }
    138 
    139 define i32 @test1c(i16 %x) {
    140 ; CHECK-LABEL: @test1c(
    141 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
    142 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32
    143 ; CHECK-NEXT: ret i32 [[VAR2]]
    144 entry:
    145   %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
    146   %cast2 = zext i16 %0 to i32
    147   %tobool = icmp ne i16 %x, 0
    148   %cond = select i1 %tobool, i32 %cast2, i32 16
    149   ret i32 %cond
    150 }
    151 
    152 define i64 @test2c(i16 %x) {
    153 ; CHECK-LABEL: @test2c(
    154 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %x, i1 false)
    155 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64
    156 ; CHECK-NEXT: ret i64 [[VAR2]]
    157 entry:
    158   %0 = tail call i16 @llvm.cttz.i16(i16 %x, i1 true)
    159   %conv = zext i16 %0 to i64
    160   %tobool = icmp ne i16 %x, 0
    161   %cond = select i1 %tobool, i64 %conv, i64 16
    162   ret i64 %cond
    163 }
    164 
    165 define i64 @test3c(i32 %x) {
    166 ; CHECK-LABEL: @test3c(
    167 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    168 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
    169 ; CHECK-NEXT: ret i64 [[VAR2]]
    170 entry:
    171   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    172   %conv = zext i32 %0 to i64
    173   %tobool = icmp ne i32 %x, 0
    174   %cond = select i1 %tobool, i64 %conv, i64 32
    175   ret i64 %cond
    176 }
    177 
    178 define i32 @test4c(i16 %x) {
    179 ; CHECK-LABEL: @test4c(
    180 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
    181 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i32
    182 ; CHECK-NEXT: ret i32 [[VAR2]]
    183 entry:
    184   %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
    185   %cast = zext i16 %0 to i32
    186   %tobool = icmp ne i16 %x, 0
    187   %cond = select i1 %tobool, i32 %cast, i32 16
    188   ret i32 %cond
    189 }
    190 
    191 define i64 @test5c(i16 %x) {
    192 ; CHECK-LABEL: @test5c(
    193 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
    194 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i16 [[VAR1]] to i64
    195 ; CHECK-NEXT: ret i64 [[VAR2]]
    196 entry:
    197   %0 = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true)
    198   %cast = zext i16 %0 to i64
    199   %tobool = icmp ne i16 %x, 0
    200   %cond = select i1 %tobool, i64 %cast, i64 16
    201   ret i64 %cond
    202 }
    203 
    204 define i64 @test6c(i32 %x) {
    205 ; CHECK-LABEL: @test6c(
    206 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
    207 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
    208 ; CHECK-NEXT: ret i64 [[VAR2]]
    209 entry:
    210   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    211   %cast = zext i32 %0 to i64
    212   %tobool = icmp ne i32 %x, 0
    213   %cond = select i1 %tobool, i64 %cast, i64 32
    214   ret i64 %cond
    215 }
    216 
    217 define i16 @test1d(i64 %x) {
    218 ; CHECK-LABEL: @test1d(
    219 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
    220 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16
    221 ; CHECK-NEXT: ret i16 [[VAR2]]
    222 entry:
    223   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    224   %conv = trunc i64 %0 to i16
    225   %tobool = icmp ne i64 %x, 0
    226   %cond = select i1 %tobool, i16 %conv, i16 64
    227   ret i16 %cond
    228 }
    229 
    230 define i32 @test2d(i64 %x) {
    231 ; CHECK-LABEL: @test2d(
    232 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 false)
    233 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32
    234 ; CHECK-NEXT: ret i32 [[VAR2]]
    235 entry:
    236   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    237   %cast = trunc i64 %0 to i32
    238   %tobool = icmp ne i64 %x, 0
    239   %cond = select i1 %tobool, i32 %cast, i32 64
    240   ret i32 %cond
    241 }
    242 
    243 define i16 @test3d(i32 %x) {
    244 ; CHECK-LABEL: @test3d(
    245 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    246 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
    247 ; CHECK-NEXT: ret i16 [[VAR2]]
    248 entry:
    249   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    250   %cast = trunc i32 %0 to i16
    251   %tobool = icmp ne i32 %x, 0
    252   %cond = select i1 %tobool, i16 %cast, i16 32
    253   ret i16 %cond
    254 }
    255 
    256 define i16 @test4d(i64 %x) {
    257 ; CHECK-LABEL: @test4d(
    258 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
    259 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i16
    260 ; CHECK-NEXT: ret i16 [[VAR2]]
    261 entry:
    262   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
    263   %cast = trunc i64 %0 to i16
    264   %tobool = icmp ne i64 %x, 0
    265   %cond = select i1 %tobool, i16 %cast, i16 64
    266   ret i16 %cond
    267 }
    268 
    269 define i32 @test5d(i64 %x) {
    270 ; CHECK-LABEL: @test5d(
    271 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
    272 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i64 [[VAR1]] to i32
    273 ; CHECK-NEXT: ret i32 [[VAR2]]
    274 entry:
    275   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
    276   %cast = trunc i64 %0 to i32
    277   %tobool = icmp ne i64 %x, 0
    278   %cond = select i1 %tobool, i32 %cast, i32 64
    279   ret i32 %cond
    280 }
    281 
    282 define i16 @test6d(i32 %x) {
    283 ; CHECK-LABEL: @test6d(
    284 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
    285 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
    286 ; CHECK-NEXT: ret i16 [[VAR2]]
    287 entry:
    288   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    289   %cast = trunc i32 %0 to i16
    290   %tobool = icmp ne i32 %x, 0
    291   %cond = select i1 %tobool, i16 %cast, i16 32
    292   ret i16 %cond
    293 }
    294 
    295 define i64 @select_bug1(i32 %x) {
    296 ; CHECK-LABEL: @select_bug1(
    297 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    298 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = zext i32 [[VAR1]] to i64
    299 ; CHECK-NEXT: ret i64 [[VAR2]]
    300 entry:
    301   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    302   %conv = zext i32 %0 to i64
    303   %tobool = icmp ne i32 %x, 0
    304   %cond = select i1 %tobool, i64 %conv, i64 32
    305   ret i64 %cond
    306 }
    307 
    308 define i16 @select_bug2(i32 %x) {
    309 ; CHECK-LABEL: @select_bug2(
    310 ; CHECK: [[VAR1:%[a-zA-Z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    311 ; CHECK-NEXT: [[VAR2:%[a-zA-Z0-9]+]] = trunc i32 [[VAR1]] to i16
    312 ; CHECK-NEXT: ret i16 [[VAR2]]
    313 entry:
    314   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 false)
    315   %conv = trunc i32 %0 to i16
    316   %tobool = icmp ne i32 %x, 0
    317   %cond = select i1 %tobool, i16 %conv, i16 32
    318   ret i16 %cond
    319 }
    320 
    321 
    322 declare i16 @llvm.ctlz.i16(i16, i1)
    323 declare i32 @llvm.ctlz.i32(i32, i1)
    324 declare i64 @llvm.ctlz.i64(i64, i1)
    325 declare i16 @llvm.cttz.i16(i16, i1)
    326 declare i32 @llvm.cttz.i32(i32, i1)
    327 declare i64 @llvm.cttz.i64(i64, i1)
    328