[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / snprintf-4.ll
blob7006838ae9b58a0d7d293ad63474666c921a3a5c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
3 ; Verify that snprintf calls with a constant size not exceeding INT_MAX
4 ; and a "%c" format string are transformed into a store of the character.
5 ; Also verify that a size in excess of INT_MAX prevents the transformation.
7 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
9 @pcnt_c = constant [3 x i8] c"%c\00"
11 @adst = external global [0 x ptr]
12 @asiz = external global [0 x i32]
14 declare i32 @snprintf(ptr, i64, ptr, ...)
17 ; Verify that all snprintf calls with a bound between INT_MAX and down
18 ; to 0 are transformed to memcpy.
20 define void @fold_snprintf_pcnt_c(i32 %c) {
21 ; CHECK-LABEL: @fold_snprintf_pcnt_c(
22 ; CHECK-NEXT:    [[PDIMAX:%.*]] = load ptr, ptr @adst, align 8
23 ; CHECK-NEXT:    store i8 1, ptr [[PDIMAX]], align 1
24 ; CHECK-NEXT:    [[NUL:%.*]] = getelementptr inbounds i8, ptr [[PDIMAX]], i64 1
25 ; CHECK-NEXT:    store i8 0, ptr [[NUL]], align 1
26 ; CHECK-NEXT:    store i32 1, ptr @asiz, align 4
27 ; CHECK-NEXT:    [[PD2:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8
28 ; CHECK-NEXT:    store i8 2, ptr [[PD2]], align 1
29 ; CHECK-NEXT:    [[NUL1:%.*]] = getelementptr inbounds i8, ptr [[PD2]], i64 1
30 ; CHECK-NEXT:    store i8 0, ptr [[NUL1]], align 1
31 ; CHECK-NEXT:    store i32 1, ptr getelementptr (i8, ptr @asiz, i64 4), align 4
32 ; CHECK-NEXT:    [[PD2_0:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8
33 ; CHECK-NEXT:    store i8 0, ptr [[PD2_0]], align 1
34 ; CHECK-NEXT:    [[NUL2:%.*]] = getelementptr inbounds i8, ptr [[PD2_0]], i64 1
35 ; CHECK-NEXT:    store i8 0, ptr [[NUL2]], align 1
36 ; CHECK-NEXT:    store i32 1, ptr getelementptr (i8, ptr @asiz, i64 8), align 4
37 ; CHECK-NEXT:    [[PD1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 24), align 8
38 ; CHECK-NEXT:    store i8 0, ptr [[PD1]], align 1
39 ; CHECK-NEXT:    store i32 1, ptr getelementptr (i8, ptr @asiz, i64 12), align 4
40 ; CHECK-NEXT:    store i32 1, ptr getelementptr (i8, ptr @asiz, i64 16), align 4
41 ; CHECK-NEXT:    [[PD2_C:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 32), align 8
42 ; CHECK-NEXT:    [[CHAR:%.*]] = trunc i32 [[C:%.*]] to i8
43 ; CHECK-NEXT:    store i8 [[CHAR]], ptr [[PD2_C]], align 1
44 ; CHECK-NEXT:    [[NUL3:%.*]] = getelementptr inbounds i8, ptr [[PD2_C]], i64 1
45 ; CHECK-NEXT:    store i8 0, ptr [[NUL3]], align 1
46 ; CHECK-NEXT:    store i32 1, ptr getelementptr (i8, ptr @asiz, i64 16), align 4
47 ; CHECK-NEXT:    [[PD1_C:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 40), align 8
48 ; CHECK-NEXT:    store i8 0, ptr [[PD1_C]], align 1
49 ; CHECK-NEXT:    store i32 1, ptr getelementptr (i8, ptr @asiz, i64 20), align 4
50 ; CHECK-NEXT:    ret void
53   ; Transform snprintf(dst, INT_MAX, "%c", 1) to memcpy(dst, "1", 2), 1.
54   %pdimax = load ptr, ptr @adst
55   %nimax = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdimax, i64 2147483647, ptr @pcnt_c, i32 1)
56   store i32 %nimax, ptr @asiz
58   ; Transform snprintf(dst, 2, "%c", '\2') to memcpy(dst, "2", 2), 1.
59   %pd2 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 1)
60   %n2 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd2, i64 2, ptr @pcnt_c, i8 2)
61   store i32 %n2, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 1)
63   ; Transform snprintf(dst, 2, "%c", '\0') to memcpy(dst, "\0", 2), 1.
64   %pd2_0 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 2)
65   %n2_0 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd2_0, i64 2, ptr @pcnt_c, i8 0)
66   store i32 %n2_0, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 2)
68   ; Transform snprintf(dst, 1, "%c", (short)3) to memcpy(dst, "\3", 2), 1.
69   %pd1 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 3)
70   %n1 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd1, i64 1, ptr @pcnt_c, i16 3)
71   store i32 %n1, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 3)
73   ; Fold snprintf(dst, 0, "%c", 4) to 1.
74   %pd0 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 4)
75   %n0 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd0, i64 0, ptr @pcnt_c, i32 4)
76   store i32 %n0, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 4)
79   ; Transform snprintf(dst, 2, "%c", c) with a nonconstant c to
80   ;   dst[0] = c, dst[1] = '\0', 1.
81   %pd2_c = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 4)
82   %n2_c = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd2_c, i64 2, ptr @pcnt_c, i32 %c)
83   store i32 %n2_c, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 4)
85   ; Transform snprintf(dst, 1, "%c", c) with a nonconstant c to *dst = '\0', 0.
86   %pd1_c = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 5)
87   %n1_c = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pd1_c, i64 1, ptr @pcnt_c, i32 %c)
88   store i32 %n1_c, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 5)
90   ret void
94 ; Verify that snprintf calls with a bound greater than INT_MAX are not
95 ; transformed.  POSIX requires implementations to set errno to EOVERFLOW
96 ; so such calls could be folded to just that followed by returning -1.
98 define void @call_snprintf_pcnt_c_ximax(i32 %c) {
99 ; CHECK-LABEL: @call_snprintf_pcnt_c_ximax(
100 ; CHECK-NEXT:    [[PDM1:%.*]] = load ptr, ptr @adst, align 8
101 ; CHECK-NEXT:    [[NM1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1]], i64 -1, ptr nonnull @pcnt_c, i8 0)
102 ; CHECK-NEXT:    store i32 [[NM1]], ptr @asiz, align 4
103 ; CHECK-NEXT:    [[PDIMAXP1:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 8), align 8
104 ; CHECK-NEXT:    [[NIMAXP1:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDIMAXP1]], i64 2147483648, ptr nonnull @pcnt_c, i8 1)
105 ; CHECK-NEXT:    store i32 [[NIMAXP1]], ptr getelementptr (i8, ptr @asiz, i64 4), align 4
106 ; CHECK-NEXT:    [[PDM1SL32:%.*]] = load ptr, ptr getelementptr (i8, ptr @adst, i64 16), align 8
107 ; CHECK-NEXT:    [[NM1SL32:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr noundef nonnull dereferenceable(1) [[PDM1SL32]], i64 -4294967296, ptr nonnull @pcnt_c, i8 1)
108 ; CHECK-NEXT:    store i32 [[NM1SL32]], ptr getelementptr (i8, ptr @asiz, i64 8), align 4
109 ; CHECK-NEXT:    ret void
112   %pdm1 = load ptr, ptr @adst
113   %nm1 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdm1, i64 -1, ptr @pcnt_c, i8 0)
114   store i32 %nm1, ptr @asiz
117   %pdimaxp1 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 1)
118   %nimaxp1 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdimaxp1, i64 2147483648, ptr @pcnt_c, i8 1)
119   store i32 %nimaxp1, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 1)
121   ; Exercise snprintf(dst, -1LU << 32, "%c", c).
122   %pdm1sl32 = load ptr, ptr getelementptr ([0 x ptr], ptr @adst, i32 0, i32 2)
123   %nm1sl32 = call i32 (ptr, i64, ptr, ...) @snprintf(ptr %pdm1sl32, i64 18446744069414584320, ptr @pcnt_c, i8 1)
124   store i32 %nm1sl32, ptr getelementptr ([0 x i32], ptr @asiz, i32 0, i32 2)
126   ret void