1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; 3; Verify that snprintf calls with a constant size not exceeding INT_MAX 4; and a "%s" format string and a const string argument are transformed 5; into memcpy. Also verify that a size in excess of INT_MAX prevents 6; the transformation. 7; 8; RUN: opt < %s -passes=instcombine -S -data-layout="E" | FileCheck %s -check-prefixes=ANY,BE 9; RUN: opt < %s -passes=instcombine -S -data-layout="e" | FileCheck %s -check-prefixes=ANY,LE 10 11@pcnt_s = constant [3 x i8] c"%s\00" 12@s = constant [4 x i8] c"123\00" 13 14@adst = external global [0 x ptr] 15@asiz = external global [0 x i32] 16 17declare i32 @snprintf(ptr, i64, ptr, ...) 18 19 20; Verify that all snprintf calls with a bound between INT_MAX and down 21; to 0 are transformed to memcpy. 22 23define void @fold_snprintf_pcnt_s() { 24; BE-LABEL: @fold_snprintf_pcnt_s( 25; BE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 17179869176), align 8 26; BE-NEXT: store i32 825373440, ptr [[PDIMAX]], align 1 27; BE-NEXT: store i32 3, ptr @asiz, align 4 28; BE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 29; BE-NEXT: store i32 825373440, ptr [[PD5]], align 1 30; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 31; BE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 32; BE-NEXT: store i32 825373440, ptr [[PD4]], align 1 33; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 34; BE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 35; BE-NEXT: store i16 12594, ptr [[PD3]], align 1 36; BE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[PD3]], i64 2 37; BE-NEXT: store i8 0, ptr [[ENDPTR]], align 1 38; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 39; BE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 40; BE-NEXT: store i8 49, ptr [[PD2]], align 1 41; BE-NEXT: [[ENDPTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[PD2]], i64 1 42; BE-NEXT: store i8 0, ptr [[ENDPTR1]], align 1 43; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 44; BE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 45; BE-NEXT: store i8 0, ptr [[PD1]], align 1 46; BE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 47; BE-NEXT: store i32 3, ptr @asiz, align 4 48; BE-NEXT: ret void 49; 50; LE-LABEL: @fold_snprintf_pcnt_s( 51; LE-NEXT: [[PDIMAX:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 17179869176), align 8 52; LE-NEXT: store i32 3355185, ptr [[PDIMAX]], align 1 53; LE-NEXT: store i32 3, ptr @asiz, align 4 54; LE-NEXT: [[PD5:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8 55; LE-NEXT: store i32 3355185, ptr [[PD5]], align 1 56; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 20), align 4 57; LE-NEXT: [[PD4:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8 58; LE-NEXT: store i32 3355185, ptr [[PD4]], align 1 59; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 16), align 4 60; LE-NEXT: [[PD3:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8 61; LE-NEXT: store i16 12849, ptr [[PD3]], align 1 62; LE-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[PD3]], i64 2 63; LE-NEXT: store i8 0, ptr [[ENDPTR]], align 1 64; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 12), align 4 65; LE-NEXT: [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8 66; LE-NEXT: store i8 49, ptr [[PD2]], align 1 67; LE-NEXT: [[ENDPTR1:%.*]] = getelementptr inbounds nuw i8, ptr [[PD2]], i64 1 68; LE-NEXT: store i8 0, ptr [[ENDPTR1]], align 1 69; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 8), align 4 70; LE-NEXT: [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 71; LE-NEXT: store i8 0, ptr [[PD1]], align 1 72; LE-NEXT: store i32 3, ptr getelementptr (i8, ptr @asiz, i64 4), align 4 73; LE-NEXT: store i32 3, ptr @asiz, align 4 74; LE-NEXT: ret void 75; 76 77 %pdimax = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 2147483647) 78 %nimax = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdimax, i64 2147483647, ptr @pcnt_s, ptr @s) 79 store i32 %nimax, ptr @asiz 80 81 %pd5 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 5) 82 %n5 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd5, i64 5, ptr @pcnt_s, ptr @s) 83 store i32 %n5, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 5) 84 85 %pd4 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 4) 86 %n4 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd4, i64 4, ptr @pcnt_s, ptr @s) 87 store i32 %n4, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 4) 88 89 %pd3 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 3) 90 %n3 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd3, i64 3, ptr @pcnt_s, ptr @s) 91 store i32 %n3, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 3) 92 93 %pd2 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 2) 94 %n2 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd2, i64 2, ptr @pcnt_s, ptr @s) 95 store i32 %n2, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 2) 96 97 %pd1 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 1) 98 %n1 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd1, i64 1, ptr @pcnt_s, ptr @s) 99 store i32 %n1, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 1) 100 101 %pd0 = load ptr, ptr @adst 102 %n0 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd0, i64 0, ptr @pcnt_s, ptr @s) 103 store i32 %n0, ptr @asiz 104 105 ret void 106} 107 108 109; Verify that snprintf calls with a bound greater than INT_MAX are not 110; transformed. POSIX requires implementations to set errno to EOVERFLOW 111; so such calls could be folded to just that followed by returning -1. 112 113define void @call_snprintf_pcnt_s_ximax() { 114; ANY-LABEL: @call_snprintf_pcnt_s_ximax( 115; ANY-NEXT: [[PDM1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8 116; ANY-NEXT: [[NM1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1]], i64 -1, ptr nonnull @pcnt_s, ptr nonnull @s) 117; ANY-NEXT: store i32 [[NM1]], ptr getelementptr (i8, ptr @asiz, i64 4), align 4 118; ANY-NEXT: [[PDIMAXP1:%.*]] = load ptr, ptr @adst, align 8 119; ANY-NEXT: [[NIMAXP1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDIMAXP1]], i64 2147483648, ptr nonnull @pcnt_s, ptr nonnull @s) 120; ANY-NEXT: store i32 [[NIMAXP1]], ptr @asiz, align 4 121; ANY-NEXT: ret void 122; 123 124 %pdm1 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 1) 125 %nm1 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdm1, i64 -1, ptr @pcnt_s, ptr @s) 126 store i32 %nm1, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 1) 127 128 %pdimaxp1 = load ptr, ptr @adst 129 %nimaxp1 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdimaxp1, i64 2147483648, ptr @pcnt_s, ptr @s) 130 store i32 %nimaxp1, ptr @asiz 131 132 ret void 133} 134