1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4@.str = private unnamed_addr constant [4 x i8] c"str\00", align 1 5@.str.1 = private unnamed_addr constant [3 x i8] c"%%\00", align 1 6@.str.2 = private unnamed_addr constant [3 x i8] c"%c\00", align 1 7@.str.3 = private unnamed_addr constant [3 x i8] c"%s\00", align 1 8@.str.4 = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 9 10 11declare i32 @snprintf(ptr, i64, ptr, ...) #1 12 13define void @test_not_const_fmt(ptr %buf, ptr %fmt) #0 { 14; CHECK-LABEL: @test_not_const_fmt( 15; CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 32, ptr [[FMT:%.*]]) 16; CHECK-NEXT: ret void 17; 18 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr %fmt) #2 19 ret void 20} 21 22; size is '0', do not add nonnull attribute 23define void @test_not_const_fmt_zero_size_return_value(ptr %buf, ptr %fmt) #0 { 24; CHECK-LABEL: @test_not_const_fmt_zero_size_return_value( 25; CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 0, ptr [[FMT:%.*]]) 26; CHECK-NEXT: ret void 27; 28 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr %fmt) #2 29 ret void 30} 31 32define void @test_not_const_size(ptr %buf, i64 %size) #0 { 33; CHECK-LABEL: @test_not_const_size( 34; CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 [[SIZE:%.*]], ptr nonnull @.str) 35; CHECK-NEXT: ret void 36; 37 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 %size, ptr @.str) #2 38 ret void 39} 40 41 42define i32 @test_return_value(ptr %buf) #0 { 43; CHECK-LABEL: @test_return_value( 44; CHECK-NEXT: ret i32 3 45; 46 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr @.str) #2 47 ret i32 %call 48} 49 50define void @test_percentage(ptr %buf) #0 { 51; CHECK-LABEL: @test_percentage( 52; CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 32, ptr nonnull @.str.1) 53; CHECK-NEXT: ret void 54; 55 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str.1) #2 56 ret void 57} 58 59define i32 @test_null_buf_return_value() #0 { 60; CHECK-LABEL: @test_null_buf_return_value( 61; CHECK-NEXT: ret i32 3 62; 63 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str) #2 64 ret i32 %call 65} 66 67define i32 @test_percentage_return_value() #0 { 68; CHECK-LABEL: @test_percentage_return_value( 69; CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr nonnull @.str.1) 70; CHECK-NEXT: ret i32 [[CALL]] 71; 72 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr null, i64 0, ptr @.str.1) #3 73 ret i32 %call 74} 75 76 77define void @test_correct_copy(ptr %buf) #0 { 78; CHECK-LABEL: @test_correct_copy( 79; CHECK-NEXT: store i32 7500915, ptr [[BUF:%.*]], align 1 80; CHECK-NEXT: ret void 81; 82 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str) #2 83 ret void 84} 85 86define i32 @test_char_zero_size(ptr %buf) #0 { 87; CHECK-LABEL: @test_char_zero_size( 88; CHECK-NEXT: ret i32 1 89; 90 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr @.str.2, i32 65) #2 91 ret i32 %call 92} 93 94define i32 @test_char_small_size(ptr %buf) #0 { 95; CHECK-LABEL: @test_char_small_size( 96; CHECK-NEXT: store i8 0, ptr [[BUF:%.*]], align 1 97; CHECK-NEXT: ret i32 1 98; 99 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 1, ptr @.str.2, i32 65) #2 100 ret i32 %call 101} 102 103define i32 @test_char_ok_size(ptr %buf) #0 { 104; CHECK-LABEL: @test_char_ok_size( 105; CHECK-NEXT: store i8 65, ptr [[BUF:%.*]], align 1 106; CHECK-NEXT: [[NUL:%.*]] = getelementptr inbounds nuw i8, ptr [[BUF]], i64 1 107; CHECK-NEXT: store i8 0, ptr [[NUL]], align 1 108; CHECK-NEXT: ret i32 1 109; 110 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str.2, i32 65) #2 111 ret i32 %call 112} 113 114define i32 @test_str_zero_size(ptr %buf) #0 { 115; CHECK-LABEL: @test_str_zero_size( 116; CHECK-NEXT: ret i32 3 117; 118 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 0, ptr @.str.3, ptr @.str) #2 119 ret i32 %call 120} 121 122define i32 @test_str_small_size(ptr %buf) #0 { 123; CHECK-LABEL: @test_str_small_size( 124; CHECK-NEXT: store i8 0, ptr [[BUF:%.*]], align 1 125; CHECK-NEXT: ret i32 3 126; 127 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 1, ptr @.str.3, ptr @.str) #2 128 ret i32 %call 129} 130 131define i32 @test_str_ok_size(ptr %buf) #0 { 132; CHECK-LABEL: @test_str_ok_size( 133; CHECK-NEXT: store i32 7500915, ptr [[BUF:%.*]], align 1 134; CHECK-NEXT: ret i32 3 135; 136 %call = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 32, ptr @.str.3, ptr @.str) #2 137 ret i32 %call 138} 139 140; snprintf(buf, 32, "") -> memcpy -> store 141define i32 @test_str_ok_size_tail(ptr %buf) { 142; CHECK-LABEL: @test_str_ok_size_tail( 143; CHECK-NEXT: store i8 0, ptr [[BUF:%.*]], align 1 144; CHECK-NEXT: ret i32 0 145; 146 %1 = tail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.4) 147 ret i32 %1 148} 149 150define i32 @test_str_ok_size_musttail(ptr %buf, i64 %x, ptr %y, ...) { 151; CHECK-LABEL: @test_str_ok_size_musttail( 152; CHECK-NEXT: [[TMP1:%.*]] = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 8, ptr nonnull @.str.4, ...) 153; CHECK-NEXT: ret i32 [[TMP1]] 154; 155 %1 = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.4, ...) 156 ret i32 %1 157} 158 159; snprintf(buf, 32, "%s", "str") -> memcpy -> store 160define i32 @test_str_ok_size_tail2(ptr %buf) { 161; CHECK-LABEL: @test_str_ok_size_tail2( 162; CHECK-NEXT: store i32 7500915, ptr [[BUF:%.*]], align 1 163; CHECK-NEXT: ret i32 3 164; 165 %1 = tail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.3, ptr @.str) 166 ret i32 %1 167} 168 169define i32 @test_str_ok_size_musttail2(ptr %buf, i64 %x, ptr %y, ...) { 170; CHECK-LABEL: @test_str_ok_size_musttail2( 171; CHECK-NEXT: [[TMP1:%.*]] = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[BUF:%.*]], i64 8, ptr nonnull @.str.3, ptr nonnull @.str, ...) 172; CHECK-NEXT: ret i32 [[TMP1]] 173; 174 %1 = musttail call i32 (ptr, i64, ptr, ...) @snprintf(ptr %buf, i64 8, ptr @.str.3, ptr @.str, ...) 175 ret i32 %1 176} 177