; 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: store i32 1, i32* [[PI:%.*]], align 4 ; CHECK-NEXT: [[PIA0AP1:%.*]] = getelementptr i32, i32* [[PI]], i64 1 ; CHECK-NEXT: store i32 0, i32* [[PIA0AP1]], align 4 ; CHECK-NEXT: [[PIA0B:%.*]] = getelementptr i32, i32* [[PI]], i64 2 ; CHECK-NEXT: store i32 2, i32* [[PIA0B]], align 4 ; CHECK-NEXT: [[PIA0BP1:%.*]] = getelementptr i32, i32* [[PI]], i64 3 ; CHECK-NEXT: store i32 1, i32* [[PIA0BP1]], align 4 ; CHECK-NEXT: [[PIA0BP2:%.*]] = getelementptr i32, i32* [[PI]], i64 4 ; CHECK-NEXT: store i32 0, i32* [[PIA0BP2]], align 4 ; CHECK-NEXT: [[PIA0C:%.*]] = getelementptr i32, i32* [[PI]], i64 5 ; CHECK-NEXT: store i32 3, i32* [[PIA0C]], align 4 ; CHECK-NEXT: [[PIA1A:%.*]] = getelementptr i32, i32* [[PI]], i64 6 ; CHECK-NEXT: store i32 4, i32* [[PIA1A]], align 4 ; CHECK-NEXT: [[PIA1B:%.*]] = getelementptr i32, i32* [[PI]], i64 7 ; CHECK-NEXT: store i32 5, i32* [[PIA1B]], align 4 ; CHECK-NEXT: [[PIA1C:%.*]] = getelementptr i32, i32* [[PI]], i64 8 ; CHECK-NEXT: store i32 6, 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 }