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(i8*, i64, i8*, ...) #1 12 13define void @test_not_const_fmt(i8* %buf, i8* %fmt) #0 { 14; CHECK-LABEL: @test_not_const_fmt( 15; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 32, i8* [[FMT:%.*]]) 16; CHECK-NEXT: ret void 17; 18 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* %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(i8* %buf, i8* %fmt) #0 { 24; CHECK-LABEL: @test_not_const_fmt_zero_size_return_value( 25; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 0, i8* [[FMT:%.*]]) 26; CHECK-NEXT: ret void 27; 28 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 0, i8* %fmt) #2 29 ret void 30} 31 32define void @test_not_const_size(i8* %buf, i64 %size) #0 { 33; CHECK-LABEL: @test_not_const_size( 34; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 [[SIZE:%.*]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) 35; CHECK-NEXT: ret void 36; 37 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 %size, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 38 ret void 39} 40 41 42define i32 @test_return_value(i8* %buf) #0 { 43; CHECK-LABEL: @test_return_value( 44; CHECK-NEXT: ret i32 3 45; 46 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 0, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 47 ret i32 %call 48} 49 50define void @test_percentage(i8* %buf) #0 { 51; CHECK-LABEL: @test_percentage( 52; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) 53; CHECK-NEXT: ret void 54; 55 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) #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 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #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 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) 70; CHECK-NEXT: ret i32 [[CALL]] 71; 72 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.1, i64 0, i64 0)) #3 73 ret i32 %call 74} 75 76 77define void @test_correct_copy(i8* %buf) #0 { 78; CHECK-LABEL: @test_correct_copy( 79; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[BUF:%.*]] to i32* 80; CHECK-NEXT: store i32 7500915, i32* [[TMP1]], align 1 81; CHECK-NEXT: ret void 82; 83 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 84 ret void 85} 86 87define i32 @test_char_zero_size(i8* %buf) #0 { 88; CHECK-LABEL: @test_char_zero_size( 89; CHECK-NEXT: ret i32 1 90; 91 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) #2 92 ret i32 %call 93} 94 95define i32 @test_char_wrong_size(i8* %buf) #0 { 96; CHECK-LABEL: @test_char_wrong_size( 97; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) 98; CHECK-NEXT: ret i32 [[CALL]] 99; 100 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) #2 101 ret i32 %call 102} 103 104define i32 @test_char_ok_size(i8* %buf) #0 { 105; CHECK-LABEL: @test_char_ok_size( 106; CHECK-NEXT: store i8 65, i8* [[BUF:%.*]], align 1 107; CHECK-NEXT: [[NUL:%.*]] = getelementptr inbounds i8, i8* [[BUF]], i64 1 108; CHECK-NEXT: store i8 0, i8* [[NUL]], align 1 109; CHECK-NEXT: ret i32 1 110; 111 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i64 0, i64 0), i32 65) #2 112 ret i32 %call 113} 114 115define i32 @test_str_zero_size(i8* %buf) #0 { 116; CHECK-LABEL: @test_str_zero_size( 117; CHECK-NEXT: ret i32 3 118; 119 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 120 ret i32 %call 121} 122 123define i32 @test_str_wrong_size(i8* %buf) #0 { 124; CHECK-LABEL: @test_str_wrong_size( 125; CHECK-NEXT: [[CALL:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* noundef nonnull dereferenceable(1) [[BUF:%.*]], i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) 126; CHECK-NEXT: ret i32 [[CALL]] 127; 128 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 1, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 129 ret i32 %call 130} 131 132define i32 @test_str_ok_size(i8* %buf) #0 { 133; CHECK-LABEL: @test_str_ok_size( 134; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[BUF:%.*]] to i32* 135; CHECK-NEXT: store i32 7500915, i32* [[TMP1]], align 1 136; CHECK-NEXT: ret i32 3 137; 138 %call = call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 32, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) #2 139 ret i32 %call 140} 141 142; snprintf(buf, 32, "") -> memcpy -> store 143define i32 @test_str_ok_size_tail(i8* %buf) { 144; CHECK-LABEL: @test_str_ok_size_tail( 145; CHECK-NEXT: store i8 0, i8* [[BUF:%.*]], align 1 146; CHECK-NEXT: ret i32 0 147; 148 %1 = tail call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 8, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i64 0, i64 0)) 149 ret i32 %1 150} 151 152define i32 @test_str_ok_size_musttail(i8* %buf, i64 %x, i8* %y, ...) { 153; CHECK-LABEL: @test_str_ok_size_musttail( 154; CHECK-NEXT: [[TMP1:%.*]] = musttail call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 8, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i64 0, i64 0), ...) 155; CHECK-NEXT: ret i32 [[TMP1]] 156; 157 %1 = musttail call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 8, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i64 0, i64 0), ...) 158 ret i32 %1 159} 160 161; snprintf(buf, 32, "%s", "str") -> memcpy -> store 162define i32 @test_str_ok_size_tail2(i8* %buf) { 163; CHECK-LABEL: @test_str_ok_size_tail2( 164; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[BUF:%.*]] to i32* 165; CHECK-NEXT: store i32 7500915, i32* [[TMP1]], align 1 166; CHECK-NEXT: ret i32 3 167; 168 %1 = tail call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 8, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0)) 169 ret i32 %1 170} 171 172define i32 @test_str_ok_size_musttail2(i8* %buf, i64 %x, i8* %y, ...) { 173; CHECK-LABEL: @test_str_ok_size_musttail2( 174; CHECK-NEXT: [[TMP1:%.*]] = musttail call i32 (i8*, i64, i8*, ...) @snprintf(i8* [[BUF:%.*]], i64 8, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), ...) 175; CHECK-NEXT: ret i32 [[TMP1]] 176; 177 %1 = musttail call i32 (i8*, i64, i8*, ...) @snprintf(i8* %buf, i64 8, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), ...) 178 ret i32 %1 179} 180