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 6target 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 16declare i32 @strlen(i8*) 17 18; Check strlen(string constant) -> integer constant. 19 20define 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 29define 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 38define 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 47define 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 57define 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 67define 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 80define 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 90define 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 101define 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 116define 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 128define i32 @test_simplify11(i32 %x) { 129; CHECK-LABEL: @test_simplify11( 130; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 7 131; CHECK-NEXT: [[TMP1:%.*]] = sub nuw 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 142define i32 @test_no_simplify1() { 143; CHECK-LABEL: @test_no_simplify1( 144; CHECK-NEXT: [[A_L:%.*]] = call i32 @strlen(i8* nonnull dereferenceable(1) 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 154define 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 165define 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 178define 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 191define 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 204define i32 @test1(i8* %str) { 205; CHECK-LABEL: @test1( 206; CHECK-NEXT: [[LEN:%.*]] = tail call i32 @strlen(i8* nonnull dereferenceable(1) [[STR:%.*]]) #1 207; CHECK-NEXT: ret i32 [[LEN]] 208; 209 %len = tail call i32 @strlen(i8* %str) nounwind 210 ret i32 %len 211} 212 213define i32 @test2(i8* %str) #0 { 214; CHECK-LABEL: @test2( 215; CHECK-NEXT: [[LEN:%.*]] = tail call i32 @strlen(i8* [[STR:%.*]]) #1 216; CHECK-NEXT: ret i32 [[LEN]] 217; 218 %len = tail call i32 @strlen(i8* %str) nounwind 219 ret i32 %len 220} 221 222; Test cases for PR47149. 223define i1 @strlen0_after_write_to_first_byte_global() { 224; CHECK-LABEL: @strlen0_after_write_to_first_byte_global( 225; CHECK-NEXT: store i8 49, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), align 16 226; CHECK-NEXT: ret i1 false 227; 228 store i8 49, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i64 0, i64 0), align 16 229 %len = tail call i32 @strlen(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i64 0, i64 0)) 230 %cmp = icmp eq i32 %len, 0 231 ret i1 %cmp 232} 233 234define i1 @strlen0_after_write_to_second_byte_global() { 235; CHECK-LABEL: @strlen0_after_write_to_second_byte_global( 236; CHECK-NEXT: store i8 49, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 1), align 16 237; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i8, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), align 1 238; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[STRLENFIRST]], 0 239; CHECK-NEXT: ret i1 [[CMP]] 240; 241 store i8 49, i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i64 0, i64 1), align 16 242 %len = tail call i32 @strlen(i8* nonnull dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i64 0, i64 0)) 243 %cmp = icmp eq i32 %len, 0 244 ret i1 %cmp 245} 246 247define i1 @strlen0_after_write_to_first_byte(i8 *%ptr) { 248; CHECK-LABEL: @strlen0_after_write_to_first_byte( 249; CHECK-NEXT: store i8 49, i8* [[PTR:%.*]], align 1 250; CHECK-NEXT: ret i1 false 251; 252 store i8 49, i8* %ptr 253 %len = tail call i32 @strlen(i8* nonnull dereferenceable(1) %ptr) 254 %cmp = icmp eq i32 %len, 0 255 ret i1 %cmp 256} 257 258define i1 @strlen0_after_write_to_second_byte(i8 *%ptr) { 259; CHECK-LABEL: @strlen0_after_write_to_second_byte( 260; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, i8* [[PTR:%.*]], i32 1 261; CHECK-NEXT: store i8 49, i8* [[GEP]], align 1 262; CHECK-NEXT: [[STRLENFIRST:%.*]] = load i8, i8* [[PTR]], align 1 263; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[STRLENFIRST]], 0 264; CHECK-NEXT: ret i1 [[CMP]] 265; 266 %gep = getelementptr i8, i8* %ptr, i64 1 267 store i8 49, i8* %gep 268 %len = tail call i32 @strlen(i8* nonnull dereferenceable(1) %ptr) 269 %cmp = icmp eq i32 %len, 0 270 ret i1 %cmp 271} 272 273attributes #0 = { null_pointer_is_valid } 274