1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Test that the printf library call simplifier works correctly. 3; 4; RUN: opt < %s -instcombine -S | FileCheck %s 5; RUN: opt < %s -mtriple xcore-xmos-elf -instcombine -S | FileCheck %s -check-prefix=CHECK-IPRINTF 6 7target 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" 8 9@hello_world = constant [13 x i8] c"hello world\0A\00" 10@h = constant [2 x i8] c"h\00" 11@h2 = constant [3 x i8] c"%%\00" 12@percent = constant [2 x i8] c"%\00" 13@percent_c = constant [3 x i8] c"%c\00" 14@percent_d = constant [3 x i8] c"%d\00" 15@percent_f = constant [3 x i8] c"%f\00" 16@percent_s = constant [4 x i8] c"%s\0A\00" 17@empty = constant [1 x i8] c"\00" 18; CHECK: [[$STR:@[a-z0-9]+]] = private unnamed_addr constant [12 x i8] c"hello world\00", align 1 19 20declare i32 @printf(i8*, ...) 21 22; Check printf("") -> noop. 23 24define void @test_simplify1() { 25; CHECK-LABEL: @test_simplify1( 26; CHECK-NEXT: ret void 27; 28; CHECK-IPRINTF-LABEL: @test_simplify1( 29; CHECK-IPRINTF-NEXT: ret void 30; 31 %fmt = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0 32 call i32 (i8*, ...) @printf(i8* %fmt) 33 ret void 34} 35 36; Check printf("x") -> putchar('x'), even for '%'. 37 38define void @test_simplify2() { 39; CHECK-LABEL: @test_simplify2( 40; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) 41; CHECK-NEXT: ret void 42; 43; CHECK-IPRINTF-LABEL: @test_simplify2( 44; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) 45; CHECK-IPRINTF-NEXT: ret void 46; 47 %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0 48 call i32 (i8*, ...) @printf(i8* %fmt) 49 ret void 50} 51 52; Special case: printf("%%") -> putchar('%'). 53 54define void @test_simplify2b() { 55; CHECK-LABEL: @test_simplify2b( 56; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) 57; CHECK-NEXT: ret void 58; 59; CHECK-IPRINTF-LABEL: @test_simplify2b( 60; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) 61; CHECK-IPRINTF-NEXT: ret void 62; 63 %fmt = getelementptr [3 x i8], [3 x i8]* @h2, i32 0, i32 0 64 call i32 (i8*, ...) @printf(i8* %fmt) 65 ret void 66} 67 68define void @test_simplify3() { 69; CHECK-LABEL: @test_simplify3( 70; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) 71; CHECK-NEXT: ret void 72; 73; CHECK-IPRINTF-LABEL: @test_simplify3( 74; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 37) 75; CHECK-IPRINTF-NEXT: ret void 76; 77 %fmt = getelementptr [2 x i8], [2 x i8]* @percent, i32 0, i32 0 78 call i32 (i8*, ...) @printf(i8* %fmt) 79 ret void 80} 81 82; Check printf("foo\n") -> puts("foo"). 83 84define void @test_simplify4() { 85; CHECK-LABEL: @test_simplify4( 86; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0)) 87; CHECK-NEXT: ret void 88; 89; CHECK-IPRINTF-LABEL: @test_simplify4( 90; CHECK-IPRINTF-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @str, i32 0, i32 0)) 91; CHECK-IPRINTF-NEXT: ret void 92; 93 %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 94 call i32 (i8*, ...) @printf(i8* %fmt) 95 ret void 96} 97 98; Check printf("%c", chr) -> putchar(chr). 99 100define void @test_simplify5() { 101; CHECK-LABEL: @test_simplify5( 102; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) 103; CHECK-NEXT: ret void 104; 105; CHECK-IPRINTF-LABEL: @test_simplify5( 106; CHECK-IPRINTF-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 104) 107; CHECK-IPRINTF-NEXT: ret void 108; 109 %fmt = getelementptr [3 x i8], [3 x i8]* @percent_c, i32 0, i32 0 110 call i32 (i8*, ...) @printf(i8* %fmt, i8 104) 111 ret void 112} 113 114; Check printf("%s\n", str) -> puts(str). 115 116define void @test_simplify6() { 117; CHECK-LABEL: @test_simplify6( 118; CHECK-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) 119; CHECK-NEXT: ret void 120; 121; CHECK-IPRINTF-LABEL: @test_simplify6( 122; CHECK-IPRINTF-NEXT: [[PUTS:%.*]] = call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0)) 123; CHECK-IPRINTF-NEXT: ret void 124; 125 %fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0 126 %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 127 call i32 (i8*, ...) @printf(i8* %fmt, i8* %str) 128 ret void 129} 130 131; Check printf(format, ...) -> iprintf(format, ...) if no floating point. 132 133define void @test_simplify7() { 134; CHECK-LABEL: @test_simplify7( 135; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) 136; CHECK-NEXT: ret void 137; 138; CHECK-IPRINTF-LABEL: @test_simplify7( 139; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) 140; CHECK-IPRINTF-NEXT: ret void 141; 142 %fmt = getelementptr [3 x i8], [3 x i8]* @percent_d, i32 0, i32 0 143 call i32 (i8*, ...) @printf(i8* %fmt, i32 187) 144 ret void 145} 146 147define void @test_no_simplify1() { 148; CHECK-LABEL: @test_no_simplify1( 149; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) 150; CHECK-NEXT: ret void 151; 152; CHECK-IPRINTF-LABEL: @test_no_simplify1( 153; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) 154; CHECK-IPRINTF-NEXT: ret void 155; 156 %fmt = getelementptr [3 x i8], [3 x i8]* @percent_f, i32 0, i32 0 157 call i32 (i8*, ...) @printf(i8* %fmt, double 1.87) 158 ret void 159} 160 161define void @test_no_simplify2(i8* %fmt, double %d) { 162; CHECK-LABEL: @test_no_simplify2( 163; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) 164; CHECK-NEXT: ret void 165; 166; CHECK-IPRINTF-LABEL: @test_no_simplify2( 167; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) [[FMT:%.*]], double [[D:%.*]]) 168; CHECK-IPRINTF-NEXT: ret void 169; 170 call i32 (i8*, ...) @printf(i8* %fmt, double %d) 171 ret void 172} 173 174define i32 @test_no_simplify3() { 175; CHECK-LABEL: @test_no_simplify3( 176; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0)) 177; CHECK-NEXT: ret i32 [[RET]] 178; 179; CHECK-IPRINTF-LABEL: @test_no_simplify3( 180; CHECK-IPRINTF-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @iprintf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @h, i32 0, i32 0)) 181; CHECK-IPRINTF-NEXT: ret i32 [[TMP1]] 182; 183 %fmt = getelementptr [2 x i8], [2 x i8]* @h, i32 0, i32 0 184 %ret = call i32 (i8*, ...) @printf(i8* %fmt) 185 ret i32 %ret 186} 187