Home | History | Annotate | Download | only in InstCombine
      1 ; Test that the ffs* library call simplifier works correctly.
      2 ;
      3 ; RUN: opt < %s -instcombine -S | FileCheck %s
      4 ; RUN: opt < %s -mtriple i386-pc-linux -instcombine -S | FileCheck %s -check-prefix=CHECK-FFS
      5 ; RUN: opt -instcombine -mtriple=arm64-apple-ios9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s
      6 ; RUN: opt -instcombine -mtriple=arm64-apple-tvos9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s
      7 ; RUN: opt -instcombine -mtriple=thumbv7k-apple-watchos2.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s
      8 ; RUN: opt -instcombine -mtriple=x86_64-apple-macosx10.11 -S %s | FileCheck --check-prefix=CHECK-FFS %s
      9 ; RUN: opt -instcombine -mtriple=x86_64-freebsd-gnu -S %s | FileCheck --check-prefix=CHECK-FFS %s
     10 
     11 declare i32 @ffs(i32)
     12 declare i32 @ffsl(i32)
     13 declare i32 @ffsll(i64)
     14 
     15 ; Check ffs(0) -> 0.
     16 
     17 define i32 @test_simplify1() {
     18 ; CHECK-LABEL: @test_simplify1(
     19   %ret = call i32 @ffs(i32 0)
     20   ret i32 %ret
     21 ; CHECK-NEXT: ret i32 0
     22 }
     23 
     24 define i32 @test_simplify2() {
     25 ; CHECK-FFS-LABEL: @test_simplify2(
     26   %ret = call i32 @ffsl(i32 0)
     27   ret i32 %ret
     28 ; CHECK-FFS-NEXT: ret i32 0
     29 }
     30 
     31 define i32 @test_simplify3() {
     32 ; CHECK-FFS-LABEL: @test_simplify3(
     33   %ret = call i32 @ffsll(i64 0)
     34   ret i32 %ret
     35 ; CHECK-FFS-NEXT: ret i32 0
     36 }
     37 
     38 ; Check ffs(c) -> cttz(c) + 1, where 'c' is a constant.
     39 
     40 define i32 @test_simplify4() {
     41 ; CHECK-LABEL: @test_simplify4(
     42   %ret = call i32 @ffs(i32 1)
     43   ret i32 %ret
     44 ; CHECK-NEXT: ret i32 1
     45 }
     46 
     47 define i32 @test_simplify5() {
     48 ; CHECK-LABEL: @test_simplify5(
     49   %ret = call i32 @ffs(i32 2048)
     50   ret i32 %ret
     51 ; CHECK-NEXT: ret i32 12
     52 }
     53 
     54 define i32 @test_simplify6() {
     55 ; CHECK-LABEL: @test_simplify6(
     56   %ret = call i32 @ffs(i32 65536)
     57   ret i32 %ret
     58 ; CHECK-NEXT: ret i32 17
     59 }
     60 
     61 define i32 @test_simplify7() {
     62 ; CHECK-FFS-LABEL: @test_simplify7(
     63   %ret = call i32 @ffsl(i32 65536)
     64   ret i32 %ret
     65 ; CHECK-FFS-NEXT: ret i32 17
     66 }
     67 
     68 define i32 @test_simplify8() {
     69 ; CHECK-FFS-LABEL: @test_simplify8(
     70   %ret = call i32 @ffsll(i64 1024)
     71   ret i32 %ret
     72 ; CHECK-FFS-NEXT: ret i32 11
     73 }
     74 
     75 define i32 @test_simplify9() {
     76 ; CHECK-FFS-LABEL: @test_simplify9(
     77   %ret = call i32 @ffsll(i64 65536)
     78   ret i32 %ret
     79 ; CHECK-FFS-NEXT: ret i32 17
     80 }
     81 
     82 define i32 @test_simplify10() {
     83 ; CHECK-FFS-LABEL: @test_simplify10(
     84   %ret = call i32 @ffsll(i64 17179869184)
     85   ret i32 %ret
     86 ; CHECK-FFS-NEXT: ret i32 35
     87 }
     88 
     89 define i32 @test_simplify11() {
     90 ; CHECK-FFS-LABEL: @test_simplify11(
     91   %ret = call i32 @ffsll(i64 281474976710656)
     92   ret i32 %ret
     93 ; CHECK-FFS-NEXT: ret i32 49
     94 }
     95 
     96 define i32 @test_simplify12() {
     97 ; CHECK-FFS-LABEL: @test_simplify12(
     98   %ret = call i32 @ffsll(i64 1152921504606846976)
     99   ret i32 %ret
    100 ; CHECK-FFS-NEXT: ret i32 61
    101 }
    102 
    103 ; Check ffs(x) -> x != 0 ? (i32)llvm.cttz(x) + 1 : 0.
    104 
    105 define i32 @test_simplify13(i32 %x) {
    106 ; CHECK-LABEL: @test_simplify13(
    107   %ret = call i32 @ffs(i32 %x)
    108 ; CHECK-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true)
    109 ; CHECK-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1
    110 ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0
    111 ; CHECK-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0
    112   ret i32 %ret
    113 ; CHECK-NEXT: ret i32 [[RET]]
    114 }
    115 
    116 define i32 @test_simplify14(i32 %x) {
    117 ; CHECK-FFS-LABEL: @test_simplify14(
    118   %ret = call i32 @ffsl(i32 %x)
    119 ; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true)
    120 ; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1
    121 ; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0
    122 ; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0
    123   ret i32 %ret
    124 ; CHECK-FFS-NEXT: ret i32 [[RET]]
    125 }
    126 
    127 define i32 @test_simplify15(i64 %x) {
    128 ; CHECK-FFS-LABEL: @test_simplify15(
    129   %ret = call i32 @ffsll(i64 %x)
    130 ; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %x, i1 true)
    131 ; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i64 [[CTTZ]], 1
    132 ; CHECK-FFS-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i64 [[INC]] to i32
    133 ; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i64 %x, 0
    134 ; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[TRUNC]], i32 0
    135   ret i32 %ret
    136 ; CHECK-FFS-NEXT: ret i32 [[RET]]
    137 }
    138