Add tests exercising the future enancement of folding library function calls with arguments involving subobjects such as elements of arrays or struct members.
105 lines
6.9 KiB
LLVM
105 lines
6.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; Verify that calls to snprintf with members of constant structs as arguments
|
|
; are folded to constants as expected.
|
|
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
|
|
|
|
declare i32 @snprintf(i8*, i64, i8*, ...)
|
|
|
|
%struct.A = type { [5 x i8], [6 x i8], [7 x i8] }
|
|
|
|
@a = constant [2 x %struct.A] [%struct.A { [5 x i8] c"1\00\00\00\00", [6 x i8] c"12\00\00\00\00", [7 x i8] c"123\00\00\00\00" }, %struct.A { [5 x i8] c"1234\00", [6 x i8] c"12345\00", [7 x i8] c"123456\00" }]
|
|
|
|
@pcnt_s = constant [3 x i8] c"%s\00"
|
|
|
|
|
|
; Fold snprintf(0, 0, "%s", a[I].M + C) for constant I in [0, 1],
|
|
; member M in [a, b, c], and C in a valid range to a constant.
|
|
|
|
define void @fold_snprintf_member_pC(i32* %pi) {
|
|
; CHECK-LABEL: @fold_snprintf_member_pC(
|
|
; CHECK-NEXT: [[IA0A:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0))
|
|
; CHECK-NEXT: store i32 [[IA0A]], i32* [[PI:%.*]], align 4
|
|
; CHECK-NEXT: [[IA0AP1:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 1))
|
|
; CHECK-NEXT: [[PIA0AP1:%.*]] = getelementptr i32, i32* [[PI]], i64 1
|
|
; CHECK-NEXT: store i32 [[IA0AP1]], i32* [[PIA0AP1]], align 4
|
|
; CHECK-NEXT: [[IA0B:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0))
|
|
; CHECK-NEXT: [[PIA0B:%.*]] = getelementptr i32, i32* [[PI]], i64 2
|
|
; CHECK-NEXT: store i32 [[IA0B]], i32* [[PIA0B]], align 4
|
|
; CHECK-NEXT: [[IA0BP1:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1))
|
|
; CHECK-NEXT: [[PIA0BP1:%.*]] = getelementptr i32, i32* [[PI]], i64 3
|
|
; CHECK-NEXT: store i32 [[IA0BP1]], i32* [[PIA0BP1]], align 4
|
|
; CHECK-NEXT: [[IA0BP2:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 2))
|
|
; CHECK-NEXT: [[PIA0BP2:%.*]] = getelementptr i32, i32* [[PI]], i64 4
|
|
; CHECK-NEXT: store i32 [[IA0BP2]], i32* [[PIA0BP2]], align 4
|
|
; CHECK-NEXT: [[IA0C:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 0))
|
|
; CHECK-NEXT: [[PIA0C:%.*]] = getelementptr i32, i32* [[PI]], i64 5
|
|
; CHECK-NEXT: store i32 [[IA0C]], i32* [[PIA0C]], align 4
|
|
; CHECK-NEXT: [[IA1A:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0))
|
|
; CHECK-NEXT: [[PIA1A:%.*]] = getelementptr i32, i32* [[PI]], i64 6
|
|
; CHECK-NEXT: store i32 [[IA1A]], i32* [[PIA1A]], align 4
|
|
; CHECK-NEXT: [[IA1B:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0))
|
|
; CHECK-NEXT: [[PIA1B:%.*]] = getelementptr i32, i32* [[PI]], i64 7
|
|
; CHECK-NEXT: store i32 [[IA1B]], i32* [[PIA1B]], align 4
|
|
; CHECK-NEXT: [[IA1C:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @pcnt_s, i64 0, i64 0), i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 0))
|
|
; CHECK-NEXT: [[PIA1C:%.*]] = getelementptr i32, i32* [[PI]], i64 8
|
|
; CHECK-NEXT: store i32 [[IA1C]], i32* [[PIA1C]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%fmt = getelementptr [3 x i8], [3 x i8]* @pcnt_s, i32 0, i32 0
|
|
; Fold snprintf(0, 0, "%s", a[0].a) to 1.
|
|
%pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
|
|
%ia0a = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0a)
|
|
%pia0a = getelementptr i32, i32* %pi, i32 0
|
|
store i32 %ia0a, i32* %pia0a
|
|
|
|
; Fold snprintf(0, 0, "%s", a[0].a) to 0.
|
|
%pa0ap1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 1
|
|
%ia0ap1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0ap1)
|
|
%pia0ap1 = getelementptr i32, i32* %pi, i32 1
|
|
store i32 %ia0ap1, i32* %pia0ap1
|
|
|
|
; Fold snprintf(0, 0, "%s", a[0].b) to 2.
|
|
%pa0b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0
|
|
%ia0b = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0b)
|
|
%pia0b = getelementptr i32, i32* %pi, i32 2
|
|
store i32 %ia0b, i32* %pia0b
|
|
|
|
; Fold snprintf(0, 0, "%s", a[0].b + 1) to 1.
|
|
%pa0bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1
|
|
%ia0bp1 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0bp1)
|
|
%pia0bp1 = getelementptr i32, i32* %pi, i32 3
|
|
store i32 %ia0bp1, i32* %pia0bp1
|
|
|
|
; Fold snprintf(0, 0, "%s", a[0].b + 2) to 0.
|
|
%pa0bp2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 2
|
|
%ia0bp2 = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0bp2)
|
|
%pia0bp2 = getelementptr i32, i32* %pi, i32 4
|
|
store i32 %ia0bp2, i32* %pia0bp2
|
|
|
|
; Fold snprintf(0, 0, "%s", a[0].c) to 3.
|
|
%pa0c = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 0
|
|
%ia0c = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa0c)
|
|
%pia0c = getelementptr i32, i32* %pi, i32 5
|
|
store i32 %ia0c, i32* %pia0c
|
|
|
|
; Fold snprintf(0, 0, "%s", a[1].a) to 4.
|
|
%pa1a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0
|
|
%ia1a = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa1a)
|
|
%pia1a = getelementptr i32, i32* %pi, i32 6
|
|
store i32 %ia1a, i32* %pia1a
|
|
|
|
; Fold snprintf(0, 0, "%s", a[1].b) to 5.
|
|
%pa1b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0
|
|
%ia1b = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa1b)
|
|
%pia1b = getelementptr i32, i32* %pi, i32 7
|
|
store i32 %ia1b, i32* %pia1b
|
|
|
|
; Fold snprintf(0, 0, "%s", a[1].c) to 6.
|
|
%pa1c = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 0
|
|
%ia1c = call i32 (i8*, i64, i8*, ...) @snprintf(i8* null, i64 0, i8* %fmt, i8* %pa1c)
|
|
%pia1c = getelementptr i32, i32* %pi, i32 8
|
|
store i32 %ia1c, i32* %pia1c
|
|
|
|
ret void
|
|
}
|