569 lines · c
1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 22// RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - | FileCheck %s3// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \4// RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-ILP32F5// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-feature +f -target-abi ilp32d -emit-llvm %s -o - \6// RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-ILP32D7// RUN: %clang_cc1 -triple riscv32 -target-abi ilp32e -emit-llvm %s -o - \8// RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-ILP32E9 10#include <stddef.h>11#include <stdint.h>12 13struct tiny {14 uint8_t a, b, c, d;15};16struct small {17 int32_t a, *b;18};19struct small_aligned {20 int64_t a;21};22struct large {23 int32_t a, b, c, d;24};25 26// Ensure that ABI lowering happens as expected for vararg calls. For RV3227// with the base integer calling convention there will be no observable28// differences in the lowered IR for a call with varargs vs without.29 30int f_va_callee(int, ...);31 32// CHECK-LABEL: define dso_local void @f_va_caller33// CHECK-SAME: () #[[ATTR0:[0-9]+]] {34// CHECK-NEXT: entry:35// CHECK-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca [[STRUCT_TINY:%.*]], align 136// CHECK-NEXT: [[DOTCOMPOUNDLITERAL1:%.*]] = alloca [[STRUCT_SMALL:%.*]], align 437// CHECK-NEXT: [[DOTCOMPOUNDLITERAL4:%.*]] = alloca [[STRUCT_SMALL_ALIGNED:%.*]], align 838// CHECK-NEXT: [[DOTCOMPOUNDLITERAL6:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 439// CHECK-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LARGE]], align 440// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 041// CHECK-NEXT: store i8 6, ptr [[A]], align 142// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 143// CHECK-NEXT: store i8 7, ptr [[B]], align 144// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 245// CHECK-NEXT: store i8 8, ptr [[C]], align 146// CHECK-NEXT: [[D:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 347// CHECK-NEXT: store i8 9, ptr [[D]], align 148// CHECK-NEXT: [[A2:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[DOTCOMPOUNDLITERAL1]], i32 0, i32 049// CHECK-NEXT: store i32 10, ptr [[A2]], align 450// CHECK-NEXT: [[B3:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[DOTCOMPOUNDLITERAL1]], i32 0, i32 151// CHECK-NEXT: store ptr null, ptr [[B3]], align 452// CHECK-NEXT: [[A5:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL_ALIGNED]], ptr [[DOTCOMPOUNDLITERAL4]], i32 0, i32 053// CHECK-NEXT: store i64 11, ptr [[A5]], align 854// CHECK-NEXT: [[A7:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[DOTCOMPOUNDLITERAL6]], i32 0, i32 055// CHECK-NEXT: store i32 12, ptr [[A7]], align 456// CHECK-NEXT: [[B8:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[DOTCOMPOUNDLITERAL6]], i32 0, i32 157// CHECK-NEXT: store i32 13, ptr [[B8]], align 458// CHECK-NEXT: [[C9:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[DOTCOMPOUNDLITERAL6]], i32 0, i32 259// CHECK-NEXT: store i32 14, ptr [[C9]], align 460// CHECK-NEXT: [[D10:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[DOTCOMPOUNDLITERAL6]], i32 0, i32 361// CHECK-NEXT: store i32 15, ptr [[D10]], align 462// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTCOMPOUNDLITERAL]], align 163// CHECK-NEXT: [[TMP1:%.*]] = load [2 x i32], ptr [[DOTCOMPOUNDLITERAL1]], align 464// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL_ALIGNED]], ptr [[DOTCOMPOUNDLITERAL4]], i32 0, i32 065// CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[COERCE_DIVE]], align 866// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[BYVAL_TEMP]], ptr align 4 [[DOTCOMPOUNDLITERAL6]], i32 16, i1 false)67// CHECK-NEXT: [[CALL:%.*]] = call i32 (i32, ...) @f_va_callee(i32 noundef 1, i32 noundef 2, i64 noundef 3, double noundef 4.000000e+00, double noundef 5.000000e+00, i32 [[TMP0]], [2 x i32] [[TMP1]], i64 [[TMP2]], ptr dead_on_return noundef [[BYVAL_TEMP]])68// CHECK-NEXT: ret void69//70void f_va_caller(void) {71 f_va_callee(1, 2, 3LL, 4.0f, 5.0, (struct tiny){6, 7, 8, 9},72 (struct small){10, NULL}, (struct small_aligned){11},73 (struct large){12, 13, 14, 15});74}75 76// CHECK-LABEL: define dso_local i32 @f_va_177// CHECK-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {78// CHECK-NEXT: entry:79// CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 480// CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 481// CHECK-NEXT: [[V:%.*]] = alloca i32, align 482// CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 483// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]])84// CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 485// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 486// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 487// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 488// CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 489// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]])90// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 491// CHECK-NEXT: ret i32 [[TMP1]]92//93int f_va_1(char *fmt, ...) {94 __builtin_va_list va;95 96 __builtin_va_start(va, fmt);97 int v = __builtin_va_arg(va, int);98 __builtin_va_end(va);99 100 return v;101}102 103// An "aligned" register pair (where the first register is even-numbered) is104// used to pass varargs with 2x xlen alignment and 2x xlen size. Ensure the105// correct offsets are used.106 107// CHECK-ILP32F-LABEL: define dso_local double @f_va_2108// CHECK-ILP32F-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {109// CHECK-ILP32F-NEXT: entry:110// CHECK-ILP32F-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4111// CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4112// CHECK-ILP32F-NEXT: [[V:%.*]] = alloca double, align 8113// CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4114// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]])115// CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4116// CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7117// CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)118// CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8119// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4120// CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8121// CHECK-ILP32F-NEXT: store double [[TMP1]], ptr [[V]], align 8122// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]])123// CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8124// CHECK-ILP32F-NEXT: ret double [[TMP2]]125//126// CHECK-ILP32D-LABEL: define dso_local double @f_va_2127// CHECK-ILP32D-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {128// CHECK-ILP32D-NEXT: entry:129// CHECK-ILP32D-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4130// CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4131// CHECK-ILP32D-NEXT: [[V:%.*]] = alloca double, align 8132// CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4133// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]])134// CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4135// CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7136// CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)137// CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8138// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4139// CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8140// CHECK-ILP32D-NEXT: store double [[TMP1]], ptr [[V]], align 8141// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]])142// CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8143// CHECK-ILP32D-NEXT: ret double [[TMP2]]144//145// CHECK-ILP32E-LABEL: define dso_local double @f_va_2146// CHECK-ILP32E-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {147// CHECK-ILP32E-NEXT: entry:148// CHECK-ILP32E-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4149// CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4150// CHECK-ILP32E-NEXT: [[V:%.*]] = alloca double, align 8151// CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4152// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]])153// CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4154// CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8155// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4156// CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load double, ptr [[ARGP_CUR]], align 4157// CHECK-ILP32E-NEXT: store double [[TMP0]], ptr [[V]], align 8158// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]])159// CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load double, ptr [[V]], align 8160// CHECK-ILP32E-NEXT: ret double [[TMP1]]161//162double f_va_2(char *fmt, ...) {163 __builtin_va_list va;164 165 __builtin_va_start(va, fmt);166 double v = __builtin_va_arg(va, double);167 __builtin_va_end(va);168 169 return v;170}171 172// Two "aligned" register pairs.173 174// CHECK-ILP32F-LABEL: define dso_local double @f_va_3175// CHECK-ILP32F-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {176// CHECK-ILP32F-NEXT: entry:177// CHECK-ILP32F-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4178// CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4179// CHECK-ILP32F-NEXT: [[V:%.*]] = alloca double, align 8180// CHECK-ILP32F-NEXT: [[W:%.*]] = alloca i32, align 4181// CHECK-ILP32F-NEXT: [[X:%.*]] = alloca double, align 8182// CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4183// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]])184// CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4185// CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7186// CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)187// CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8188// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4189// CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8190// CHECK-ILP32F-NEXT: store double [[TMP1]], ptr [[V]], align 8191// CHECK-ILP32F-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VA]], align 4192// CHECK-ILP32F-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i32 4193// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4194// CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARGP_CUR1]], align 4195// CHECK-ILP32F-NEXT: store i32 [[TMP2]], ptr [[W]], align 4196// CHECK-ILP32F-NEXT: [[ARGP_CUR3:%.*]] = load ptr, ptr [[VA]], align 4197// CHECK-ILP32F-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i32 7198// CHECK-ILP32F-NEXT: [[ARGP_CUR3_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP3]], i32 -8)199// CHECK-ILP32F-NEXT: [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3_ALIGNED]], i32 8200// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4201// CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8202// CHECK-ILP32F-NEXT: store double [[TMP4]], ptr [[X]], align 8203// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]])204// CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8205// CHECK-ILP32F-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8206// CHECK-ILP32F-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]]207// CHECK-ILP32F-NEXT: ret double [[ADD]]208//209// CHECK-ILP32D-LABEL: define dso_local double @f_va_3210// CHECK-ILP32D-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {211// CHECK-ILP32D-NEXT: entry:212// CHECK-ILP32D-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4213// CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4214// CHECK-ILP32D-NEXT: [[V:%.*]] = alloca double, align 8215// CHECK-ILP32D-NEXT: [[W:%.*]] = alloca i32, align 4216// CHECK-ILP32D-NEXT: [[X:%.*]] = alloca double, align 8217// CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4218// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]])219// CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4220// CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7221// CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8)222// CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 8223// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4224// CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8225// CHECK-ILP32D-NEXT: store double [[TMP1]], ptr [[V]], align 8226// CHECK-ILP32D-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VA]], align 4227// CHECK-ILP32D-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i32 4228// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4229// CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARGP_CUR1]], align 4230// CHECK-ILP32D-NEXT: store i32 [[TMP2]], ptr [[W]], align 4231// CHECK-ILP32D-NEXT: [[ARGP_CUR3:%.*]] = load ptr, ptr [[VA]], align 4232// CHECK-ILP32D-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i32 7233// CHECK-ILP32D-NEXT: [[ARGP_CUR3_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP3]], i32 -8)234// CHECK-ILP32D-NEXT: [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3_ALIGNED]], i32 8235// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4236// CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8237// CHECK-ILP32D-NEXT: store double [[TMP4]], ptr [[X]], align 8238// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]])239// CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8240// CHECK-ILP32D-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8241// CHECK-ILP32D-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]]242// CHECK-ILP32D-NEXT: ret double [[ADD]]243//244// CHECK-ILP32E-LABEL: define dso_local double @f_va_3245// CHECK-ILP32E-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {246// CHECK-ILP32E-NEXT: entry:247// CHECK-ILP32E-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4248// CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4249// CHECK-ILP32E-NEXT: [[V:%.*]] = alloca double, align 8250// CHECK-ILP32E-NEXT: [[W:%.*]] = alloca i32, align 4251// CHECK-ILP32E-NEXT: [[X:%.*]] = alloca double, align 8252// CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4253// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]])254// CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4255// CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8256// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4257// CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load double, ptr [[ARGP_CUR]], align 4258// CHECK-ILP32E-NEXT: store double [[TMP0]], ptr [[V]], align 8259// CHECK-ILP32E-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VA]], align 4260// CHECK-ILP32E-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i32 4261// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4262// CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARGP_CUR1]], align 4263// CHECK-ILP32E-NEXT: store i32 [[TMP1]], ptr [[W]], align 4264// CHECK-ILP32E-NEXT: [[ARGP_CUR3:%.*]] = load ptr, ptr [[VA]], align 4265// CHECK-ILP32E-NEXT: [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i32 8266// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4267// CHECK-ILP32E-NEXT: [[TMP2:%.*]] = load double, ptr [[ARGP_CUR3]], align 4268// CHECK-ILP32E-NEXT: store double [[TMP2]], ptr [[X]], align 8269// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]])270// CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load double, ptr [[V]], align 8271// CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load double, ptr [[X]], align 8272// CHECK-ILP32E-NEXT: [[ADD:%.*]] = fadd double [[TMP3]], [[TMP4]]273// CHECK-ILP32E-NEXT: ret double [[ADD]]274//275double f_va_3(char *fmt, ...) {276 __builtin_va_list va;277 278 __builtin_va_start(va, fmt);279 double v = __builtin_va_arg(va, double);280 int w = __builtin_va_arg(va, int);281 double x = __builtin_va_arg(va, double);282 __builtin_va_end(va);283 284 return v + x;285}286 287// CHECK-ILP32F-LABEL: define dso_local i32 @f_va_4288// CHECK-ILP32F-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {289// CHECK-ILP32F-NEXT: entry:290// CHECK-ILP32F-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4291// CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4292// CHECK-ILP32F-NEXT: [[V:%.*]] = alloca i32, align 4293// CHECK-ILP32F-NEXT: [[LD:%.*]] = alloca fp128, align 16294// CHECK-ILP32F-NEXT: [[TS:%.*]] = alloca [[STRUCT_TINY:%.*]], align 1295// CHECK-ILP32F-NEXT: [[SS:%.*]] = alloca [[STRUCT_SMALL:%.*]], align 4296// CHECK-ILP32F-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4297// CHECK-ILP32F-NEXT: [[RET:%.*]] = alloca i32, align 4298// CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4299// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]])300// CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4301// CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4302// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4303// CHECK-ILP32F-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4304// CHECK-ILP32F-NEXT: store i32 [[TMP0]], ptr [[V]], align 4305// CHECK-ILP32F-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VA]], align 4306// CHECK-ILP32F-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i32 4307// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4308// CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4309// CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load fp128, ptr [[TMP1]], align 16310// CHECK-ILP32F-NEXT: store fp128 [[TMP2]], ptr [[LD]], align 16311// CHECK-ILP32F-NEXT: [[ARGP_CUR3:%.*]] = load ptr, ptr [[VA]], align 4312// CHECK-ILP32F-NEXT: [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i32 4313// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4314// CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TS]], ptr align 4 [[ARGP_CUR3]], i32 4, i1 false)315// CHECK-ILP32F-NEXT: [[ARGP_CUR5:%.*]] = load ptr, ptr [[VA]], align 4316// CHECK-ILP32F-NEXT: [[ARGP_NEXT6:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR5]], i32 8317// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 4318// CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[SS]], ptr align 4 [[ARGP_CUR5]], i32 8, i1 false)319// CHECK-ILP32F-NEXT: [[ARGP_CUR7:%.*]] = load ptr, ptr [[VA]], align 4320// CHECK-ILP32F-NEXT: [[ARGP_NEXT8:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR7]], i32 4321// CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4322// CHECK-ILP32F-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4323// CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false)324// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]])325// CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4326// CHECK-ILP32F-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128327// CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16328// CHECK-ILP32F-NEXT: [[ADD:%.*]] = fadd fp128 [[CONV]], [[TMP5]]329// CHECK-ILP32F-NEXT: [[CONV9:%.*]] = fptosi fp128 [[ADD]] to i32330// CHECK-ILP32F-NEXT: store i32 [[CONV9]], ptr [[RET]], align 4331// CHECK-ILP32F-NEXT: [[TMP6:%.*]] = load i32, ptr [[RET]], align 4332// CHECK-ILP32F-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0333// CHECK-ILP32F-NEXT: [[TMP7:%.*]] = load i8, ptr [[A]], align 1334// CHECK-ILP32F-NEXT: [[CONV10:%.*]] = zext i8 [[TMP7]] to i32335// CHECK-ILP32F-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP6]], [[CONV10]]336// CHECK-ILP32F-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 1337// CHECK-ILP32F-NEXT: [[TMP8:%.*]] = load i8, ptr [[B]], align 1338// CHECK-ILP32F-NEXT: [[CONV12:%.*]] = zext i8 [[TMP8]] to i32339// CHECK-ILP32F-NEXT: [[ADD13:%.*]] = add nsw i32 [[ADD11]], [[CONV12]]340// CHECK-ILP32F-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 2341// CHECK-ILP32F-NEXT: [[TMP9:%.*]] = load i8, ptr [[C]], align 1342// CHECK-ILP32F-NEXT: [[CONV14:%.*]] = zext i8 [[TMP9]] to i32343// CHECK-ILP32F-NEXT: [[ADD15:%.*]] = add nsw i32 [[ADD13]], [[CONV14]]344// CHECK-ILP32F-NEXT: [[D:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 3345// CHECK-ILP32F-NEXT: [[TMP10:%.*]] = load i8, ptr [[D]], align 1346// CHECK-ILP32F-NEXT: [[CONV16:%.*]] = zext i8 [[TMP10]] to i32347// CHECK-ILP32F-NEXT: [[ADD17:%.*]] = add nsw i32 [[ADD15]], [[CONV16]]348// CHECK-ILP32F-NEXT: store i32 [[ADD17]], ptr [[RET]], align 4349// CHECK-ILP32F-NEXT: [[TMP11:%.*]] = load i32, ptr [[RET]], align 4350// CHECK-ILP32F-NEXT: [[A18:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[SS]], i32 0, i32 0351// CHECK-ILP32F-NEXT: [[TMP12:%.*]] = load i32, ptr [[A18]], align 4352// CHECK-ILP32F-NEXT: [[ADD19:%.*]] = add nsw i32 [[TMP11]], [[TMP12]]353// CHECK-ILP32F-NEXT: [[B20:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[SS]], i32 0, i32 1354// CHECK-ILP32F-NEXT: [[TMP13:%.*]] = load ptr, ptr [[B20]], align 4355// CHECK-ILP32F-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i32356// CHECK-ILP32F-NEXT: [[ADD21:%.*]] = add nsw i32 [[ADD19]], [[TMP14]]357// CHECK-ILP32F-NEXT: store i32 [[ADD21]], ptr [[RET]], align 4358// CHECK-ILP32F-NEXT: [[TMP15:%.*]] = load i32, ptr [[RET]], align 4359// CHECK-ILP32F-NEXT: [[A22:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 0360// CHECK-ILP32F-NEXT: [[TMP16:%.*]] = load i32, ptr [[A22]], align 4361// CHECK-ILP32F-NEXT: [[ADD23:%.*]] = add nsw i32 [[TMP15]], [[TMP16]]362// CHECK-ILP32F-NEXT: [[B24:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 1363// CHECK-ILP32F-NEXT: [[TMP17:%.*]] = load i32, ptr [[B24]], align 4364// CHECK-ILP32F-NEXT: [[ADD25:%.*]] = add nsw i32 [[ADD23]], [[TMP17]]365// CHECK-ILP32F-NEXT: [[C26:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 2366// CHECK-ILP32F-NEXT: [[TMP18:%.*]] = load i32, ptr [[C26]], align 4367// CHECK-ILP32F-NEXT: [[ADD27:%.*]] = add nsw i32 [[ADD25]], [[TMP18]]368// CHECK-ILP32F-NEXT: [[D28:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 3369// CHECK-ILP32F-NEXT: [[TMP19:%.*]] = load i32, ptr [[D28]], align 4370// CHECK-ILP32F-NEXT: [[ADD29:%.*]] = add nsw i32 [[ADD27]], [[TMP19]]371// CHECK-ILP32F-NEXT: store i32 [[ADD29]], ptr [[RET]], align 4372// CHECK-ILP32F-NEXT: [[TMP20:%.*]] = load i32, ptr [[RET]], align 4373// CHECK-ILP32F-NEXT: ret i32 [[TMP20]]374//375// CHECK-ILP32D-LABEL: define dso_local i32 @f_va_4376// CHECK-ILP32D-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {377// CHECK-ILP32D-NEXT: entry:378// CHECK-ILP32D-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4379// CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4380// CHECK-ILP32D-NEXT: [[V:%.*]] = alloca i32, align 4381// CHECK-ILP32D-NEXT: [[LD:%.*]] = alloca fp128, align 16382// CHECK-ILP32D-NEXT: [[TS:%.*]] = alloca [[STRUCT_TINY:%.*]], align 1383// CHECK-ILP32D-NEXT: [[SS:%.*]] = alloca [[STRUCT_SMALL:%.*]], align 4384// CHECK-ILP32D-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4385// CHECK-ILP32D-NEXT: [[RET:%.*]] = alloca i32, align 4386// CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4387// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]])388// CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4389// CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4390// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4391// CHECK-ILP32D-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4392// CHECK-ILP32D-NEXT: store i32 [[TMP0]], ptr [[V]], align 4393// CHECK-ILP32D-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VA]], align 4394// CHECK-ILP32D-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i32 4395// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4396// CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4397// CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load fp128, ptr [[TMP1]], align 16398// CHECK-ILP32D-NEXT: store fp128 [[TMP2]], ptr [[LD]], align 16399// CHECK-ILP32D-NEXT: [[ARGP_CUR3:%.*]] = load ptr, ptr [[VA]], align 4400// CHECK-ILP32D-NEXT: [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i32 4401// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4402// CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TS]], ptr align 4 [[ARGP_CUR3]], i32 4, i1 false)403// CHECK-ILP32D-NEXT: [[ARGP_CUR5:%.*]] = load ptr, ptr [[VA]], align 4404// CHECK-ILP32D-NEXT: [[ARGP_NEXT6:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR5]], i32 8405// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 4406// CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[SS]], ptr align 4 [[ARGP_CUR5]], i32 8, i1 false)407// CHECK-ILP32D-NEXT: [[ARGP_CUR7:%.*]] = load ptr, ptr [[VA]], align 4408// CHECK-ILP32D-NEXT: [[ARGP_NEXT8:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR7]], i32 4409// CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4410// CHECK-ILP32D-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4411// CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false)412// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]])413// CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4414// CHECK-ILP32D-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128415// CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16416// CHECK-ILP32D-NEXT: [[ADD:%.*]] = fadd fp128 [[CONV]], [[TMP5]]417// CHECK-ILP32D-NEXT: [[CONV9:%.*]] = fptosi fp128 [[ADD]] to i32418// CHECK-ILP32D-NEXT: store i32 [[CONV9]], ptr [[RET]], align 4419// CHECK-ILP32D-NEXT: [[TMP6:%.*]] = load i32, ptr [[RET]], align 4420// CHECK-ILP32D-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0421// CHECK-ILP32D-NEXT: [[TMP7:%.*]] = load i8, ptr [[A]], align 1422// CHECK-ILP32D-NEXT: [[CONV10:%.*]] = zext i8 [[TMP7]] to i32423// CHECK-ILP32D-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP6]], [[CONV10]]424// CHECK-ILP32D-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 1425// CHECK-ILP32D-NEXT: [[TMP8:%.*]] = load i8, ptr [[B]], align 1426// CHECK-ILP32D-NEXT: [[CONV12:%.*]] = zext i8 [[TMP8]] to i32427// CHECK-ILP32D-NEXT: [[ADD13:%.*]] = add nsw i32 [[ADD11]], [[CONV12]]428// CHECK-ILP32D-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 2429// CHECK-ILP32D-NEXT: [[TMP9:%.*]] = load i8, ptr [[C]], align 1430// CHECK-ILP32D-NEXT: [[CONV14:%.*]] = zext i8 [[TMP9]] to i32431// CHECK-ILP32D-NEXT: [[ADD15:%.*]] = add nsw i32 [[ADD13]], [[CONV14]]432// CHECK-ILP32D-NEXT: [[D:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 3433// CHECK-ILP32D-NEXT: [[TMP10:%.*]] = load i8, ptr [[D]], align 1434// CHECK-ILP32D-NEXT: [[CONV16:%.*]] = zext i8 [[TMP10]] to i32435// CHECK-ILP32D-NEXT: [[ADD17:%.*]] = add nsw i32 [[ADD15]], [[CONV16]]436// CHECK-ILP32D-NEXT: store i32 [[ADD17]], ptr [[RET]], align 4437// CHECK-ILP32D-NEXT: [[TMP11:%.*]] = load i32, ptr [[RET]], align 4438// CHECK-ILP32D-NEXT: [[A18:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[SS]], i32 0, i32 0439// CHECK-ILP32D-NEXT: [[TMP12:%.*]] = load i32, ptr [[A18]], align 4440// CHECK-ILP32D-NEXT: [[ADD19:%.*]] = add nsw i32 [[TMP11]], [[TMP12]]441// CHECK-ILP32D-NEXT: [[B20:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[SS]], i32 0, i32 1442// CHECK-ILP32D-NEXT: [[TMP13:%.*]] = load ptr, ptr [[B20]], align 4443// CHECK-ILP32D-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i32444// CHECK-ILP32D-NEXT: [[ADD21:%.*]] = add nsw i32 [[ADD19]], [[TMP14]]445// CHECK-ILP32D-NEXT: store i32 [[ADD21]], ptr [[RET]], align 4446// CHECK-ILP32D-NEXT: [[TMP15:%.*]] = load i32, ptr [[RET]], align 4447// CHECK-ILP32D-NEXT: [[A22:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 0448// CHECK-ILP32D-NEXT: [[TMP16:%.*]] = load i32, ptr [[A22]], align 4449// CHECK-ILP32D-NEXT: [[ADD23:%.*]] = add nsw i32 [[TMP15]], [[TMP16]]450// CHECK-ILP32D-NEXT: [[B24:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 1451// CHECK-ILP32D-NEXT: [[TMP17:%.*]] = load i32, ptr [[B24]], align 4452// CHECK-ILP32D-NEXT: [[ADD25:%.*]] = add nsw i32 [[ADD23]], [[TMP17]]453// CHECK-ILP32D-NEXT: [[C26:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 2454// CHECK-ILP32D-NEXT: [[TMP18:%.*]] = load i32, ptr [[C26]], align 4455// CHECK-ILP32D-NEXT: [[ADD27:%.*]] = add nsw i32 [[ADD25]], [[TMP18]]456// CHECK-ILP32D-NEXT: [[D28:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 3457// CHECK-ILP32D-NEXT: [[TMP19:%.*]] = load i32, ptr [[D28]], align 4458// CHECK-ILP32D-NEXT: [[ADD29:%.*]] = add nsw i32 [[ADD27]], [[TMP19]]459// CHECK-ILP32D-NEXT: store i32 [[ADD29]], ptr [[RET]], align 4460// CHECK-ILP32D-NEXT: [[TMP20:%.*]] = load i32, ptr [[RET]], align 4461// CHECK-ILP32D-NEXT: ret i32 [[TMP20]]462//463// CHECK-ILP32E-LABEL: define dso_local i32 @f_va_4464// CHECK-ILP32E-SAME: (ptr noundef [[FMT:%.*]], ...) #[[ATTR0]] {465// CHECK-ILP32E-NEXT: entry:466// CHECK-ILP32E-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4467// CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4468// CHECK-ILP32E-NEXT: [[V:%.*]] = alloca i32, align 4469// CHECK-ILP32E-NEXT: [[LD:%.*]] = alloca fp128, align 16470// CHECK-ILP32E-NEXT: [[TS:%.*]] = alloca [[STRUCT_TINY:%.*]], align 1471// CHECK-ILP32E-NEXT: [[SS:%.*]] = alloca [[STRUCT_SMALL:%.*]], align 4472// CHECK-ILP32E-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4473// CHECK-ILP32E-NEXT: [[RET:%.*]] = alloca i32, align 4474// CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4475// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]])476// CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4477// CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4478// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4479// CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4480// CHECK-ILP32E-NEXT: store i32 [[TMP0]], ptr [[V]], align 4481// CHECK-ILP32E-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VA]], align 4482// CHECK-ILP32E-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i32 4483// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4484// CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4485// CHECK-ILP32E-NEXT: [[TMP2:%.*]] = load fp128, ptr [[TMP1]], align 4486// CHECK-ILP32E-NEXT: store fp128 [[TMP2]], ptr [[LD]], align 16487// CHECK-ILP32E-NEXT: [[ARGP_CUR3:%.*]] = load ptr, ptr [[VA]], align 4488// CHECK-ILP32E-NEXT: [[ARGP_NEXT4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR3]], i32 4489// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4490// CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TS]], ptr align 4 [[ARGP_CUR3]], i32 4, i1 false)491// CHECK-ILP32E-NEXT: [[ARGP_CUR5:%.*]] = load ptr, ptr [[VA]], align 4492// CHECK-ILP32E-NEXT: [[ARGP_NEXT6:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR5]], i32 8493// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 4494// CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[SS]], ptr align 4 [[ARGP_CUR5]], i32 8, i1 false)495// CHECK-ILP32E-NEXT: [[ARGP_CUR7:%.*]] = load ptr, ptr [[VA]], align 4496// CHECK-ILP32E-NEXT: [[ARGP_NEXT8:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR7]], i32 4497// CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4498// CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4499// CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false)500// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]])501// CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4502// CHECK-ILP32E-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128503// CHECK-ILP32E-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16504// CHECK-ILP32E-NEXT: [[ADD:%.*]] = fadd fp128 [[CONV]], [[TMP5]]505// CHECK-ILP32E-NEXT: [[CONV9:%.*]] = fptosi fp128 [[ADD]] to i32506// CHECK-ILP32E-NEXT: store i32 [[CONV9]], ptr [[RET]], align 4507// CHECK-ILP32E-NEXT: [[TMP6:%.*]] = load i32, ptr [[RET]], align 4508// CHECK-ILP32E-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0509// CHECK-ILP32E-NEXT: [[TMP7:%.*]] = load i8, ptr [[A]], align 1510// CHECK-ILP32E-NEXT: [[CONV10:%.*]] = zext i8 [[TMP7]] to i32511// CHECK-ILP32E-NEXT: [[ADD11:%.*]] = add nsw i32 [[TMP6]], [[CONV10]]512// CHECK-ILP32E-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 1513// CHECK-ILP32E-NEXT: [[TMP8:%.*]] = load i8, ptr [[B]], align 1514// CHECK-ILP32E-NEXT: [[CONV12:%.*]] = zext i8 [[TMP8]] to i32515// CHECK-ILP32E-NEXT: [[ADD13:%.*]] = add nsw i32 [[ADD11]], [[CONV12]]516// CHECK-ILP32E-NEXT: [[C:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 2517// CHECK-ILP32E-NEXT: [[TMP9:%.*]] = load i8, ptr [[C]], align 1518// CHECK-ILP32E-NEXT: [[CONV14:%.*]] = zext i8 [[TMP9]] to i32519// CHECK-ILP32E-NEXT: [[ADD15:%.*]] = add nsw i32 [[ADD13]], [[CONV14]]520// CHECK-ILP32E-NEXT: [[D:%.*]] = getelementptr inbounds nuw [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 3521// CHECK-ILP32E-NEXT: [[TMP10:%.*]] = load i8, ptr [[D]], align 1522// CHECK-ILP32E-NEXT: [[CONV16:%.*]] = zext i8 [[TMP10]] to i32523// CHECK-ILP32E-NEXT: [[ADD17:%.*]] = add nsw i32 [[ADD15]], [[CONV16]]524// CHECK-ILP32E-NEXT: store i32 [[ADD17]], ptr [[RET]], align 4525// CHECK-ILP32E-NEXT: [[TMP11:%.*]] = load i32, ptr [[RET]], align 4526// CHECK-ILP32E-NEXT: [[A18:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[SS]], i32 0, i32 0527// CHECK-ILP32E-NEXT: [[TMP12:%.*]] = load i32, ptr [[A18]], align 4528// CHECK-ILP32E-NEXT: [[ADD19:%.*]] = add nsw i32 [[TMP11]], [[TMP12]]529// CHECK-ILP32E-NEXT: [[B20:%.*]] = getelementptr inbounds nuw [[STRUCT_SMALL]], ptr [[SS]], i32 0, i32 1530// CHECK-ILP32E-NEXT: [[TMP13:%.*]] = load ptr, ptr [[B20]], align 4531// CHECK-ILP32E-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i32532// CHECK-ILP32E-NEXT: [[ADD21:%.*]] = add nsw i32 [[ADD19]], [[TMP14]]533// CHECK-ILP32E-NEXT: store i32 [[ADD21]], ptr [[RET]], align 4534// CHECK-ILP32E-NEXT: [[TMP15:%.*]] = load i32, ptr [[RET]], align 4535// CHECK-ILP32E-NEXT: [[A22:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 0536// CHECK-ILP32E-NEXT: [[TMP16:%.*]] = load i32, ptr [[A22]], align 4537// CHECK-ILP32E-NEXT: [[ADD23:%.*]] = add nsw i32 [[TMP15]], [[TMP16]]538// CHECK-ILP32E-NEXT: [[B24:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 1539// CHECK-ILP32E-NEXT: [[TMP17:%.*]] = load i32, ptr [[B24]], align 4540// CHECK-ILP32E-NEXT: [[ADD25:%.*]] = add nsw i32 [[ADD23]], [[TMP17]]541// CHECK-ILP32E-NEXT: [[C26:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 2542// CHECK-ILP32E-NEXT: [[TMP18:%.*]] = load i32, ptr [[C26]], align 4543// CHECK-ILP32E-NEXT: [[ADD27:%.*]] = add nsw i32 [[ADD25]], [[TMP18]]544// CHECK-ILP32E-NEXT: [[D28:%.*]] = getelementptr inbounds nuw [[STRUCT_LARGE]], ptr [[LS]], i32 0, i32 3545// CHECK-ILP32E-NEXT: [[TMP19:%.*]] = load i32, ptr [[D28]], align 4546// CHECK-ILP32E-NEXT: [[ADD29:%.*]] = add nsw i32 [[ADD27]], [[TMP19]]547// CHECK-ILP32E-NEXT: store i32 [[ADD29]], ptr [[RET]], align 4548// CHECK-ILP32E-NEXT: [[TMP20:%.*]] = load i32, ptr [[RET]], align 4549// CHECK-ILP32E-NEXT: ret i32 [[TMP20]]550//551int f_va_4(char *fmt, ...) {552 __builtin_va_list va;553 554 __builtin_va_start(va, fmt);555 int v = __builtin_va_arg(va, int);556 long double ld = __builtin_va_arg(va, long double);557 struct tiny ts = __builtin_va_arg(va, struct tiny);558 struct small ss = __builtin_va_arg(va, struct small);559 struct large ls = __builtin_va_arg(va, struct large);560 __builtin_va_end(va);561 562 int ret = (int)((long double)v + ld);563 ret = ret + ts.a + ts.b + ts.c + ts.d;564 ret = ret + ss.a + (int)ss.b;565 ret = ret + ls.a + ls.b + ls.c + ls.d;566 567 return ret;568}569