Home | History | Annotate | Download | only in InstCombine
      1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
      2 ; Test that the strlen library call simplifier works correctly.
      3 ;
      4 ; RUN: opt < %s -instcombine -S | FileCheck %s
      5 
      6 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
      7 
      8 @hello = constant [6 x i8] c"hello\00"
      9 @longer = constant [7 x i8] c"longer\00"
     10 @null = constant [1 x i8] zeroinitializer
     11 @null_hello = constant [7 x i8] c"\00hello\00"
     12 @nullstring = constant i8 0
     13 @a = common global [32 x i8] zeroinitializer, align 1
     14 @null_hello_mid = constant [13 x i8] c"hello wor\00ld\00"
     15 
     16 declare i32 @strlen(i8*)
     17 
     18 ; Check strlen(string constant) -> integer constant.
     19 
     20 define i32 @test_simplify1() {
     21 ; CHECK-LABEL: @test_simplify1(
     22 ; CHECK-NEXT:    ret i32 5
     23 ;
     24   %hello_p = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
     25   %hello_l = call i32 @strlen(i8* %hello_p)
     26   ret i32 %hello_l
     27 }
     28 
     29 define i32 @test_simplify2() {
     30 ; CHECK-LABEL: @test_simplify2(
     31 ; CHECK-NEXT:    ret i32 0
     32 ;
     33   %null_p = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0
     34   %null_l = call i32 @strlen(i8* %null_p)
     35   ret i32 %null_l
     36 }
     37 
     38 define i32 @test_simplify3() {
     39 ; CHECK-LABEL: @test_simplify3(
     40 ; CHECK-NEXT:    ret i32 0
     41 ;
     42   %null_hello_p = getelementptr [7 x i8], [7 x i8]* @null_hello, i32 0, i32 0
     43   %null_hello_l = call i32 @strlen(i8* %null_hello_p)
     44   ret i32 %null_hello_l
     45 }
     46 
     47 define i32 @test_simplify4() {
     48 ; CHECK-LABEL: @test_simplify4(
     49 ; CHECK-NEXT:    ret i32 0
     50 ;
     51   %len = tail call i32 @strlen(i8* @nullstring) nounwind
     52   ret i32 %len
     53 }
     54 
     55 ; Check strlen(x) == 0 --> *x == 0.
     56 
     57 define i1 @test_simplify5() {
     58 ; CHECK-LABEL: @test_simplify5(
     59 ; CHECK-NEXT:    ret i1 false
     60 ;
     61   %hello_p = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
     62   %hello_l = call i32 @strlen(i8* %hello_p)
     63   %eq_hello = icmp eq i32 %hello_l, 0
     64   ret i1 %eq_hello
     65 }
     66 
     67 define i1 @test_simplify6(i8* %str_p) {
     68 ; CHECK-LABEL: @test_simplify6(
     69 ; CHECK-NEXT:    [[STRLENFIRST:%.*]] = load i8, i8* [[STR_P:%.*]], align 1
     70 ; CHECK-NEXT:    [[EQ_NULL:%.*]] = icmp eq i8 [[STRLENFIRST]], 0
     71 ; CHECK-NEXT:    ret i1 [[EQ_NULL]]
     72 ;
     73   %str_l = call i32 @strlen(i8* %str_p)
     74   %eq_null = icmp eq i32 %str_l, 0
     75   ret i1 %eq_null
     76 }
     77 
     78 ; Check strlen(x) != 0 --> *x != 0.
     79 
     80 define i1 @test_simplify7() {
     81 ; CHECK-LABEL: @test_simplify7(
     82 ; CHECK-NEXT:    ret i1 true
     83 ;
     84   %hello_p = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
     85   %hello_l = call i32 @strlen(i8* %hello_p)
     86   %ne_hello = icmp ne i32 %hello_l, 0
     87   ret i1 %ne_hello
     88 }
     89 
     90 define i1 @test_simplify8(i8* %str_p) {
     91 ; CHECK-LABEL: @test_simplify8(
     92 ; CHECK-NEXT:    [[STRLENFIRST:%.*]] = load i8, i8* [[STR_P:%.*]], align 1
     93 ; CHECK-NEXT:    [[NE_NULL:%.*]] = icmp ne i8 [[STRLENFIRST]], 0
     94 ; CHECK-NEXT:    ret i1 [[NE_NULL]]
     95 ;
     96   %str_l = call i32 @strlen(i8* %str_p)
     97   %ne_null = icmp ne i32 %str_l, 0
     98   ret i1 %ne_null
     99 }
    100 
    101 define i32 @test_simplify9(i1 %x) {
    102 ; CHECK-LABEL: @test_simplify9(
    103 ; CHECK-NEXT:    [[TMP1:%.*]] = select i1 %x, i32 5, i32 6
    104 ; CHECK-NEXT:    ret i32 [[TMP1]]
    105 ;
    106   %hello = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0
    107   %longer = getelementptr [7 x i8], [7 x i8]* @longer, i32 0, i32 0
    108   %s = select i1 %x, i8* %hello, i8* %longer
    109   %l = call i32 @strlen(i8* %s)
    110   ret i32 %l
    111 }
    112 
    113 ; Check the case that should be simplified to a sub instruction.
    114 ; strlen(@hello + x) --> 5 - x
    115 
    116 define i32 @test_simplify10(i32 %x) {
    117 ; CHECK-LABEL: @test_simplify10(
    118 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 5, %x
    119 ; CHECK-NEXT:    ret i32 [[TMP1]]
    120 ;
    121   %hello_p = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 %x
    122   %hello_l = call i32 @strlen(i8* %hello_p)
    123   ret i32 %hello_l
    124 }
    125 
    126 ; strlen(@null_hello_mid + (x & 7)) --> 9 - (x & 7)
    127 
    128 define i32 @test_simplify11(i32 %x) {
    129 ; CHECK-LABEL: @test_simplify11(
    130 ; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 7
    131 ; CHECK-NEXT:    [[TMP1:%.*]] = sub nsw i32 9, [[AND]]
    132 ; CHECK-NEXT:    ret i32 [[TMP1]]
    133 ;
    134   %and = and i32 %x, 7
    135   %hello_p = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 %and
    136   %hello_l = call i32 @strlen(i8* %hello_p)
    137   ret i32 %hello_l
    138 }
    139 
    140 ; Check cases that shouldn't be simplified.
    141 
    142 define i32 @test_no_simplify1() {
    143 ; CHECK-LABEL: @test_no_simplify1(
    144 ; CHECK-NEXT:    [[A_L:%.*]] = call i32 @strlen(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0))
    145 ; CHECK-NEXT:    ret i32 [[A_L]]
    146 ;
    147   %a_p = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
    148   %a_l = call i32 @strlen(i8* %a_p)
    149   ret i32 %a_l
    150 }
    151 
    152 ; strlen(@null_hello + x) should not be simplified to a sub instruction.
    153 
    154 define i32 @test_no_simplify2(i32 %x) {
    155 ; CHECK-LABEL: @test_no_simplify2(
    156 ; CHECK-NEXT:    [[HELLO_P:%.*]] = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x
    157 ; CHECK-NEXT:    [[HELLO_L:%.*]] = call i32 @strlen(i8* nonnull [[HELLO_P]])
    158 ; CHECK-NEXT:    ret i32 [[HELLO_L]]
    159 ;
    160   %hello_p = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x
    161   %hello_l = call i32 @strlen(i8* %hello_p)
    162   ret i32 %hello_l
    163 }
    164 
    165 define i32 @test_no_simplify2_no_null_opt(i32 %x) #0 {
    166 ; CHECK-LABEL: @test_no_simplify2_no_null_opt(
    167 ; CHECK-NEXT:    [[HELLO_P:%.*]] = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x
    168 ; CHECK-NEXT:    [[HELLO_L:%.*]] = call i32 @strlen(i8* [[HELLO_P]])
    169 ; CHECK-NEXT:    ret i32 [[HELLO_L]]
    170 ;
    171   %hello_p = getelementptr inbounds [7 x i8], [7 x i8]* @null_hello, i32 0, i32 %x
    172   %hello_l = call i32 @strlen(i8* %hello_p)
    173   ret i32 %hello_l
    174 }
    175 
    176 ; strlen(@null_hello_mid + (x & 15)) should not be simplified to a sub instruction.
    177 
    178 define i32 @test_no_simplify3(i32 %x) {
    179 ; CHECK-LABEL: @test_no_simplify3(
    180 ; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 15
    181 ; CHECK-NEXT:    [[HELLO_P:%.*]] = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 [[AND]]
    182 ; CHECK-NEXT:    [[HELLO_L:%.*]] = call i32 @strlen(i8* nonnull [[HELLO_P]])
    183 ; CHECK-NEXT:    ret i32 [[HELLO_L]]
    184 ;
    185   %and = and i32 %x, 15
    186   %hello_p = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 %and
    187   %hello_l = call i32 @strlen(i8* %hello_p)
    188   ret i32 %hello_l
    189 }
    190 
    191 define i32 @test_no_simplify3_on_null_opt(i32 %x) #0 {
    192 ; CHECK-LABEL: @test_no_simplify3_on_null_opt(
    193 ; CHECK-NEXT:    [[AND:%.*]] = and i32 %x, 15
    194 ; CHECK-NEXT:    [[HELLO_P:%.*]] = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 [[AND]]
    195 ; CHECK-NEXT:    [[HELLO_L:%.*]] = call i32 @strlen(i8* [[HELLO_P]])
    196 ; CHECK-NEXT:    ret i32 [[HELLO_L]]
    197 ;
    198   %and = and i32 %x, 15
    199   %hello_p = getelementptr inbounds [13 x i8], [13 x i8]* @null_hello_mid, i32 0, i32 %and
    200   %hello_l = call i32 @strlen(i8* %hello_p)
    201   ret i32 %hello_l
    202 }
    203 
    204 attributes #0 = { "null-pointer-is-valid"="true" }
    205