1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Test that the sprintf library call simplifier works correctly. 3; 4; RUN: opt < %s -passes=instcombine -S | FileCheck %s 5; RUN: opt < %s -mtriple xcore-xmos-elf -passes=instcombine -S | FileCheck %s -check-prefixes=CHECK,WITHSTPCPY,CHECK-IPRINTF 6; RUN: opt < %s -mtriple=i386-pc-windows-msvc -passes=instcombine -S | FileCheck %s --check-prefixes=CHECK,NOSTPCPY 7; RUN: opt < %s -mtriple=i386-mingw32 -passes=instcombine -S | FileCheck %s --check-prefixes=CHECK,NOSTPCPY 8; RUN: opt < %s -mtriple=armv7-none-linux-android16 -passes=instcombine -S | FileCheck %s --check-prefixes=CHECK,NOSTPCPY 9; RUN: opt < %s -mtriple=armv7-none-linux-android21 -passes=instcombine -S | FileCheck %s --check-prefixes=CHECK,WITHSTPCPY 10; RUN: opt < %s -mtriple=x86_64-scei-ps4 -passes=instcombine -S | FileCheck %s --check-prefixes=CHECK,NOSTPCPY 11 12target 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" 13 14@hello_world = constant [13 x i8] c"hello world\0A\00" 15@null = constant [1 x i8] zeroinitializer 16@null_hello = constant [7 x i8] c"\00hello\00" 17@h = constant [2 x i8] c"h\00" 18@percent_c = constant [3 x i8] c"%c\00" 19@percent_d = constant [3 x i8] c"%d\00" 20@percent_f = constant [3 x i8] c"%f\00" 21@percent_s = constant [3 x i8] c"%s\00" 22 23declare i32 @sprintf(ptr, ptr, ...) 24 25; Check sprintf(dst, fmt) -> llvm.memcpy(str, fmt, strlen(fmt) + 1, 1). 26 27define void @test_simplify1(ptr %dst) { 28; CHECK-LABEL: @test_simplify1( 29; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(13) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(13) @hello_world, i32 13, i1 false) 30; CHECK-NEXT: ret void 31; 32 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @hello_world) 33 ret void 34} 35 36define void @test_simplify2(ptr %dst) { 37; CHECK-LABEL: @test_simplify2( 38; CHECK-NEXT: store i8 0, ptr [[DST:%.*]], align 1 39; CHECK-NEXT: ret void 40; 41 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @null) 42 ret void 43} 44 45define void @test_simplify3(ptr %dst) { 46; CHECK-LABEL: @test_simplify3( 47; CHECK-NEXT: store i8 0, ptr [[DST:%.*]], align 1 48; CHECK-NEXT: ret void 49; 50 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @null_hello) 51 ret void 52} 53 54; Check sprintf(dst, "%c", chr) -> *(ptr)dst = chr; *((ptr)dst + 1) = 0. 55 56define void @test_simplify4(ptr %dst) { 57; CHECK-LABEL: @test_simplify4( 58; CHECK-NEXT: store i8 104, ptr [[DST:%.*]], align 1 59; CHECK-NEXT: [[NUL:%.*]] = getelementptr inbounds nuw i8, ptr [[DST]], i32 1 60; CHECK-NEXT: store i8 0, ptr [[NUL]], align 1 61; CHECK-NEXT: ret void 62; 63 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_c, i8 104) 64 ret void 65} 66 67; Check sprintf(dst, "%s", str) -> strcpy(dst, "%s", str) if result is unused. 68 69define void @test_simplify5(ptr %dst, ptr %str) { 70; CHECK-LABEL: @test_simplify5( 71; CHECK-NEXT: [[STRCPY:%.*]] = call ptr @strcpy(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[STR:%.*]]) 72; CHECK-NEXT: ret void 73; 74 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str) 75 ret void 76} 77 78; Check sprintf(dst, format, ...) -> siprintf(str, format, ...) if no floating. 79 80define void @test_simplify6(ptr %dst) { 81; CHECK-IPRINTF-LABEL: @test_simplify6( 82; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (ptr, ptr, ...) @siprintf(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) @percent_d, i32 187) 83; CHECK-IPRINTF-NEXT: ret void 84; 85; NOSTPCPY-LABEL: @test_simplify6( 86; NOSTPCPY-NEXT: [[TMP1:%.*]] = call i32 (ptr, ptr, ...) @sprintf(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) @percent_d, i32 187) 87; NOSTPCPY-NEXT: ret void 88; 89 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_d, i32 187) 90 ret void 91} 92 93; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1). 94 95define i32 @test_simplify7(ptr %dst, ptr %str) { 96; WITHSTPCPY-LABEL: @test_simplify7( 97; WITHSTPCPY-NEXT: [[STPCPY:%.*]] = call ptr @stpcpy(ptr [[DST:%.*]], ptr [[STR:%.*]]) 98; WITHSTPCPY-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[STPCPY]] to i32 99; WITHSTPCPY-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[DST]] to i32 100; WITHSTPCPY-NEXT: [[R:%.*]] = sub i32 [[TMP1]], [[TMP2]] 101; WITHSTPCPY-NEXT: ret i32 [[R]] 102; 103; NOSTPCPY-LABEL: @test_simplify7( 104; NOSTPCPY-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]]) 105; NOSTPCPY-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1 106; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr nonnull align 1 [[STR]], i32 [[LENINC]], i1 false) 107; NOSTPCPY-NEXT: ret i32 [[STRLEN]] 108; 109 %r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str) 110 ret i32 %r 111} 112 113; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1). 114define i32 @test_simplify8(ptr %dst) { 115; CHECK-LABEL: @test_simplify8( 116; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(13) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(13) @hello_world, i32 13, i1 false) 117; CHECK-NEXT: ret i32 12 118; 119 %r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr @hello_world) 120 ret i32 %r 121} 122 123; Check sprintf(dst, "%s", str) -> stpcpy(dest, str) - dest 124 125define i32 @test_simplify9(ptr %dst, ptr %str) { 126; WITHSTPCPY-LABEL: @test_simplify9( 127; WITHSTPCPY-NEXT: [[STPCPY:%.*]] = call ptr @stpcpy(ptr [[DST:%.*]], ptr [[STR:%.*]]) 128; WITHSTPCPY-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[STPCPY]] to i32 129; WITHSTPCPY-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[DST]] to i32 130; WITHSTPCPY-NEXT: [[R:%.*]] = sub i32 [[TMP1]], [[TMP2]] 131; WITHSTPCPY-NEXT: ret i32 [[R]] 132; 133; NOSTPCPY-LABEL: @test_simplify9( 134; NOSTPCPY-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]]) 135; NOSTPCPY-NEXT: [[LENINC:%.*]] = add i32 [[STRLEN]], 1 136; NOSTPCPY-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[DST:%.*]], ptr nonnull align 1 [[STR]], i32 [[LENINC]], i1 false) 137; NOSTPCPY-NEXT: ret i32 [[STRLEN]] 138; 139 %r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str) 140 ret i32 %r 141} 142 143define void @test_no_simplify1(ptr %dst) { 144; CHECK-LABEL: @test_no_simplify1( 145; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ptr, ...) @sprintf(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) @percent_f, double 1.870000e+00) 146; CHECK-NEXT: ret void 147; 148 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_f, double 1.87) 149 ret void 150} 151 152define void @test_no_simplify2(ptr %dst, ptr %fmt, double %d) { 153; CHECK-LABEL: @test_no_simplify2( 154; CHECK-NEXT: [[TMP1:%.*]] = call i32 (ptr, ptr, ...) @sprintf(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) 155; CHECK-NEXT: ret void 156; 157 call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr %fmt, double %d) 158 ret void 159} 160 161define i32 @test_no_simplify3(ptr %dst, ptr %str) minsize { 162; WITHSTPCPY-LABEL: @test_no_simplify3( 163; WITHSTPCPY-NEXT: [[STPCPY:%.*]] = call ptr @stpcpy(ptr [[DST:%.*]], ptr [[STR:%.*]]) 164; WITHSTPCPY-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[STPCPY]] to i32 165; WITHSTPCPY-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[DST]] to i32 166; WITHSTPCPY-NEXT: [[R:%.*]] = sub i32 [[TMP1]], [[TMP2]] 167; WITHSTPCPY-NEXT: ret i32 [[R]] 168; 169; NOSTPCPY-LABEL: @test_no_simplify3( 170; NOSTPCPY-NEXT: [[R:%.*]] = call i32 (ptr, ptr, ...) @sprintf(ptr noundef nonnull dereferenceable(1) [[DST:%.*]], ptr noundef nonnull dereferenceable(1) @percent_s, ptr [[STR:%.*]]) 171; NOSTPCPY-NEXT: ret i32 [[R]] 172; 173 %r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr %str) 174 ret i32 %r 175} 176