Home | History | Annotate | Download | only in X86
      1 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI
      2 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT
      3 ; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC
      4 
      5 
      6 define i64 @test1(i64 %A) {
      7 ; ALL-LABEL: @test1(
      8 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
      9 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
     10 ; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]]
     11 ; ALL: ret
     12 entry:
     13   %tobool = icmp eq i64 %A, 0
     14   br i1 %tobool, label %cond.end, label %cond.true
     15 
     16 cond.true:                                        ; preds = %entry
     17   %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true)
     18   br label %cond.end
     19 
     20 cond.end:                                         ; preds = %entry, %cond.true
     21   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
     22   ret i64 %cond
     23 }
     24 
     25 define i32 @test2(i32 %A) {
     26 ; ALL-LABEL: @test2(
     27 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
     28 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
     29 ; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]]
     30 ; ALL: ret
     31 entry:
     32   %tobool = icmp eq i32 %A, 0
     33   br i1 %tobool, label %cond.end, label %cond.true
     34 
     35 cond.true:                                        ; preds = %entry
     36   %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true)
     37   br label %cond.end
     38 
     39 cond.end:                                         ; preds = %entry, %cond.true
     40   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
     41   ret i32 %cond
     42 }
     43 
     44 
     45 define signext i16 @test3(i16 signext %A) {
     46 ; ALL-LABEL: @test3(
     47 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
     48 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
     49 ; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]]
     50 ; ALL: ret
     51 entry:
     52   %tobool = icmp eq i16 %A, 0
     53   br i1 %tobool, label %cond.end, label %cond.true
     54 
     55 cond.true:                                        ; preds = %entry
     56   %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true)
     57   br label %cond.end
     58 
     59 cond.end:                                         ; preds = %entry, %cond.true
     60   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
     61   ret i16 %cond
     62 }
     63 
     64 
     65 define i64 @test1b(i64 %A) {
     66 ; ALL-LABEL: @test1b(
     67 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0
     68 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
     69 ; ALL-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]]
     70 ; ALL: ret
     71 entry:
     72   %tobool = icmp eq i64 %A, 0
     73   br i1 %tobool, label %cond.end, label %cond.true
     74 
     75 cond.true:                                        ; preds = %entry
     76   %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true)
     77   br label %cond.end
     78 
     79 cond.end:                                         ; preds = %entry, %cond.true
     80   %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ]
     81   ret i64 %cond
     82 }
     83 
     84 
     85 define i32 @test2b(i32 %A) {
     86 ; ALL-LABEL: @test2b(
     87 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0
     88 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
     89 ; ALL-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]]
     90 ; ALL: ret
     91 entry:
     92   %tobool = icmp eq i32 %A, 0
     93   br i1 %tobool, label %cond.end, label %cond.true
     94 
     95 cond.true:                                        ; preds = %entry
     96   %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true)
     97   br label %cond.end
     98 
     99 cond.end:                                         ; preds = %entry, %cond.true
    100   %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ]
    101   ret i32 %cond
    102 }
    103 
    104 
    105 define signext i16 @test3b(i16 signext %A) {
    106 ; ALL-LABEL: @test3b(
    107 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0
    108 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
    109 ; ALL-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]]
    110 ; ALL: ret
    111 entry:
    112   %tobool = icmp eq i16 %A, 0
    113   br i1 %tobool, label %cond.end, label %cond.true
    114 
    115 cond.true:                                        ; preds = %entry
    116   %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true)
    117   br label %cond.end
    118 
    119 cond.end:                                         ; preds = %entry, %cond.true
    120   %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ]
    121   ret i16 %cond
    122 }
    123 
    124 ; The following tests verify that calls to cttz/ctlz are speculated even if
    125 ; basic block %cond.true has an extra zero extend/truncate which is "free"
    126 ; for the target.
    127 
    128 define i64 @test1e(i32 %x) {
    129 ; ALL-LABEL: @test1e(
    130 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
    131 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    132 ; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64
    133 ; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
    134 ; LZCNT-NOT: select
    135 ; GENERIC-NOT: select
    136 ; ALL: ret
    137 entry:
    138   %tobool = icmp eq i32 %x, 0
    139   br i1 %tobool, label %cond.end, label %cond.true
    140 
    141 cond.true:                                        ; preds = %entry
    142   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    143   %phitmp2 = zext i32 %0 to i64
    144   br label %cond.end
    145 
    146 cond.end:                                         ; preds = %entry, %cond.true
    147   %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
    148   ret i64 %cond
    149 }
    150 
    151 define i32 @test2e(i64 %x) {
    152 ; ALL-LABEL: @test2e(
    153 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
    154 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    155 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32
    156 ; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
    157 ; LZCNT-NOT: select
    158 ; GENERIC-NOT: select
    159 ; ALL: ret
    160 entry:
    161   %tobool = icmp eq i64 %x, 0
    162   br i1 %tobool, label %cond.end, label %cond.true
    163 
    164 cond.true:                                        ; preds = %entry
    165   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    166   %cast = trunc i64 %0 to i32
    167   br label %cond.end
    168 
    169 cond.end:                                         ; preds = %entry, %cond.true
    170   %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
    171   ret i32 %cond
    172 }
    173 
    174 define i64 @test3e(i32 %x) {
    175 ; ALL-LABEL: @test3e(
    176 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
    177 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    178 ; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64
    179 ; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]]
    180 ; BMI-NOT: select
    181 ; GENERIC-NOT: select
    182 ; ALL: ret
    183 entry:
    184   %tobool = icmp eq i32 %x, 0
    185   br i1 %tobool, label %cond.end, label %cond.true
    186 
    187 cond.true:                                        ; preds = %entry
    188   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    189   %phitmp2 = zext i32 %0 to i64
    190   br label %cond.end
    191 
    192 cond.end:                                         ; preds = %entry, %cond.true
    193   %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ]
    194   ret i64 %cond
    195 }
    196 
    197 define i32 @test4e(i64 %x) {
    198 ; ALL-LABEL: @test4e(
    199 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
    200 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
    201 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32
    202 ; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]]
    203 ; BMI-NOT: select
    204 ; GENERIC-NOT: select
    205 ; ALL: ret
    206 entry:
    207   %tobool = icmp eq i64 %x, 0
    208   br i1 %tobool, label %cond.end, label %cond.true
    209 
    210 cond.true:                                        ; preds = %entry
    211   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
    212   %cast = trunc i64 %0 to i32
    213   br label %cond.end
    214 
    215 cond.end:                                         ; preds = %entry, %cond.true
    216   %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ]
    217   ret i32 %cond
    218 }
    219 
    220 define i16 @test5e(i64 %x) {
    221 ; ALL-LABEL: @test5e(
    222 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
    223 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
    224 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16
    225 ; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
    226 ; BMI-NOT: select
    227 ; GENERIC-NOT: select
    228 ; ALL: ret
    229 entry:
    230   %tobool = icmp eq i64 %x, 0
    231   br i1 %tobool, label %cond.end, label %cond.true
    232 
    233 cond.true:                                        ; preds = %entry
    234   %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true)
    235   %cast = trunc i64 %0 to i16
    236   br label %cond.end
    237 
    238 cond.end:                                         ; preds = %entry, %cond.true
    239   %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
    240   ret i16 %cond
    241 }
    242 
    243 define i16 @test6e(i32 %x) {
    244 ; ALL-LABEL: @test6e(
    245 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
    246 ; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    247 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16
    248 ; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
    249 ; BMI-NOT: select
    250 ; GENERIC-NOT: select
    251 ; ALL: ret
    252 entry:
    253   %tobool = icmp eq i32 %x, 0
    254   br i1 %tobool, label %cond.end, label %cond.true
    255 
    256 cond.true:                                        ; preds = %entry
    257   %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true)
    258   %cast = trunc i32 %0 to i16
    259   br label %cond.end
    260 
    261 cond.end:                                         ; preds = %entry, %cond.true
    262   %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
    263   ret i16 %cond
    264 }
    265 
    266 define i16 @test7e(i64 %x) {
    267 ; ALL-LABEL: @test7e(
    268 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0
    269 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    270 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16
    271 ; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]]
    272 ; LZCNT-NOT: select
    273 ; GENERIC-NOT: select
    274 ; ALL: ret
    275 entry:
    276   %tobool = icmp eq i64 %x, 0
    277   br i1 %tobool, label %cond.end, label %cond.true
    278 
    279 cond.true:                                        ; preds = %entry
    280   %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true)
    281   %cast = trunc i64 %0 to i16
    282   br label %cond.end
    283 
    284 cond.end:                                         ; preds = %entry, %cond.true
    285   %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ]
    286   ret i16 %cond
    287 }
    288 
    289 define i16 @test8e(i32 %x) {
    290 ; ALL-LABEL: @test8e(
    291 ; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0
    292 ; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    293 ; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16
    294 ; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]]
    295 ; LZCNT-NOT: select
    296 ; GENERIC-NOT: select
    297 ; ALL: ret
    298 entry:
    299   %tobool = icmp eq i32 %x, 0
    300   br i1 %tobool, label %cond.end, label %cond.true
    301 
    302 cond.true:                                        ; preds = %entry
    303   %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true)
    304   %cast = trunc i32 %0 to i16
    305   br label %cond.end
    306 
    307 cond.end:                                         ; preds = %entry, %cond.true
    308   %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ]
    309   ret i16 %cond
    310 }
    311 
    312 
    313 declare i64 @llvm.ctlz.i64(i64, i1)
    314 declare i32 @llvm.ctlz.i32(i32, i1)
    315 declare i16 @llvm.ctlz.i16(i16, i1)
    316 declare i64 @llvm.cttz.i64(i64, i1)
    317 declare i32 @llvm.cttz.i32(i32, i1)
    318 declare i16 @llvm.cttz.i16(i16, i1)
    319