brintos

brintos / llvm-project-archived public Read only

0
0
Text · 44.9 KiB · 86fba01 Raw
840 lines · c
1// RUN: %clang_cc1 -triple arm64-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LE %s2// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -emit-llvm -o - %s | FileCheck --check-prefix=CHECK --check-prefix=CHECK-BE %s3 4#include <stdarg.h>5 6// Obviously there's more than one way to implement va_arg. This test should at7// least prevent unintentional regressions caused by refactoring.8 9va_list the_list;10 11int simple_int(void) {12// CHECK-LABEL: define{{.*}} i32 @simple_int13  return va_arg(the_list, int);14// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)15// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 016// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]17 18// CHECK: [[VAARG_MAYBE_REG]]19// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 820// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)21// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 022// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]23 24// CHECK: [[VAARG_IN_REG]]25// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)26// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]27// CHECK-BE: [[REG_ADDR_ALIGNED:%[0-9]+]] = getelementptr inbounds i8, ptr [[REG_ADDR]], i64 428// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]29 30// CHECK: [[VAARG_ON_STACK]]31// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list32// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 833// CHECK: store ptr [[NEW_STACK]], ptr @the_list34// CHECK-BE: [[STACK_ALIGNED:%[a-z_0-9]*]] = getelementptr inbounds i8, ptr [[STACK]], i64 435// CHECK: br label %[[VAARG_END]]36 37// CHECK: [[VAARG_END]]38// CHECK-LE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]39// CHECK-BE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR_ALIGNED]], %[[VAARG_IN_REG]] ], [ [[STACK_ALIGNED]], %[[VAARG_ON_STACK]] ]40// CHECK: [[RESULT:%[a-z_0-9]+]] = load i32, ptr [[ADDR]]41// CHECK: ret i32 [[RESULT]]42}43 44__int128 aligned_int(void) {45// CHECK-LABEL: define{{.*}} i128 @aligned_int46  return va_arg(the_list, __int128);47// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)48// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 049// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]50 51// CHECK: [[VAARG_MAYBE_REG]]52// CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 1553// CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -1654// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 1655// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)56// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 057// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]58 59// CHECK: [[VAARG_IN_REG]]60// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)61// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[ALIGNED_REGOFFS]]62// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]63 64// CHECK: [[VAARG_ON_STACK]]65// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list66// CHECK: [[STACKINC:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i32 1567// CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9.]+]] = call ptr @llvm.ptrmask.p0.i64(ptr [[STACKINC]], i64 -16)68// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[ALIGNED_STACK_PTR]], i64 1669// CHECK: store ptr [[NEW_STACK]], ptr @the_list70// CHECK: br label %[[VAARG_END]]71 72// CHECK: [[VAARG_END]]73// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[ALIGNED_STACK_PTR]], %[[VAARG_ON_STACK]] ]74// CHECK: [[RESULT:%[a-z_0-9]+]] = load i128, ptr [[ADDR]]75// CHECK: ret i128 [[RESULT]]76}77 78struct bigstruct {79  int a[10];80};81 82struct bigstruct simple_indirect(void) {83// CHECK-LABEL: define{{.*}} void @simple_indirect84  return va_arg(the_list, struct bigstruct);85// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)86// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 087// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]88 89// CHECK: [[VAARG_MAYBE_REG]]90// CHECK-NOT: and i3291// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 892// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)93// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 094// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]95 96// CHECK: [[VAARG_IN_REG]]97// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)98// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]99// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]100 101// CHECK: [[VAARG_ON_STACK]]102// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list103// CHECK-NOT: and i64104// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8105// CHECK: store ptr [[NEW_STACK]], ptr @the_list106// CHECK: br label %[[VAARG_END]]107 108// CHECK: [[VAARG_END]]109// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]110// CHECK: load ptr, ptr [[ADDR]]111}112 113struct aligned_bigstruct {114  float a;115  long double b;116};117 118struct aligned_bigstruct simple_aligned_indirect(void) {119// CHECK-LABEL: define{{.*}} void @simple_aligned_indirect120  return va_arg(the_list, struct aligned_bigstruct);121// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)122// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0123// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]124 125// CHECK: [[VAARG_MAYBE_REG]]126// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8127// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)128// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0129// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]130 131// CHECK: [[VAARG_IN_REG]]132// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)133// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]134// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]135 136// CHECK: [[VAARG_ON_STACK]]137// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list138// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8139// CHECK: store ptr [[NEW_STACK]], ptr @the_list140// CHECK: br label %[[VAARG_END]]141 142// CHECK: [[VAARG_END]]143// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]144// CHECK: load ptr, ptr [[ADDR]]145}146 147double simple_double(void) {148// CHECK-LABEL: define{{.*}} double @simple_double149  return va_arg(the_list, double);150// CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 4)151// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0152// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG]]153 154// CHECK: [[VAARG_MAYBE_REG]]155// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 16156// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 4)157// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0158// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]159 160// CHECK: [[VAARG_IN_REG]]161// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 2)162// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[VR_OFFS]]163// CHECK-BE: [[REG_ADDR_ALIGNED:%[a-z_0-9]*]] = getelementptr inbounds i8, ptr [[REG_ADDR]], i64 8164// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]165 166// CHECK: [[VAARG_ON_STACK]]167// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list168// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8169// CHECK: store ptr [[NEW_STACK]], ptr @the_list170// CHECK: br label %[[VAARG_END]]171 172// CHECK: [[VAARG_END]]173// CHECK-LE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]174// CHECK-BE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR_ALIGNED]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]175// CHECK: [[RESULT:%[a-z_0-9]+]] = load double, ptr [[ADDR]]176// CHECK: ret double [[RESULT]]177}178 179struct hfa {180  float a, b;181};182 183struct hfa simple_hfa(void) {184// CHECK-LABEL: define{{.*}} %struct.hfa @simple_hfa185  return va_arg(the_list, struct hfa);186// CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 4)187// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0188// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]189 190// CHECK: [[VAARG_MAYBE_REG]]191// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 32192// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 4)193// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0194// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]195 196// CHECK: [[VAARG_IN_REG]]197// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 2)198// CHECK: [[FIRST_REG:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[VR_OFFS]]199// CHECK-LE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[FIRST_REG]], i64 0200// CHECK-BE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[FIRST_REG]], i64 12201// CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float], ptr %[[TMP_HFA:[a-z_.0-9]+]], i64 0, i64 0202// CHECK: [[EL:%[a-z_0-9]+]] = load float, ptr [[EL_ADDR]]203// CHECK: store float [[EL]], ptr [[EL_TMPADDR]]204// CHECK-LE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[FIRST_REG]], i64 16205// CHECK-BE: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[FIRST_REG]], i64 28206// CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float], ptr %[[TMP_HFA]], i64 0, i64 1207// CHECK: [[EL:%[a-z_0-9]+]] = load float, ptr [[EL_ADDR]]208// CHECK: store float [[EL]], ptr [[EL_TMPADDR]]209// CHECK: br label %[[VAARG_END:[a-z_.0-9]+]]210 211// CHECK: [[VAARG_ON_STACK]]212// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list213// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8214// CHECK: store ptr [[NEW_STACK]], ptr @the_list215// CHECK: br label %[[VAARG_END]]216 217// CHECK: [[VAARG_END]]218// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ %[[TMP_HFA]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]219}220 221// Over and under alignment on fundamental types has no effect on parameter222// passing, so the code generated for va_arg should be the same as for223// non-aligned fundamental types.224 225typedef int underaligned_int __attribute__((packed,aligned(2)));226underaligned_int underaligned_int_test(void) {227// CHECK-LABEL: define{{.*}} i32 @underaligned_int_test()228  return va_arg(the_list, underaligned_int);229// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)230// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0231// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]232 233// CHECK: [[VAARG_MAYBE_REG]]234// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8235// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)236// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0237// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]238 239// CHECK: [[VAARG_IN_REG]]240// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)241// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]242// CHECK-BE: [[REG_ADDR_ALIGNED:%[0-9]+]] = getelementptr inbounds i8, ptr [[REG_ADDR]], i64 4243// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]244 245// CHECK: [[VAARG_ON_STACK]]246// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list247// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8248// CHECK: store ptr [[NEW_STACK]], ptr @the_list249// CHECK-BE: [[STACK_ALIGNED:%[a-z_0-9]*]] = getelementptr inbounds i8, ptr [[STACK]], i64 4250// CHECK: br label %[[VAARG_END]]251 252// CHECK: [[VAARG_END]]253// CHECK-LE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]254// CHECK-BE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR_ALIGNED]], %[[VAARG_IN_REG]] ], [ [[STACK_ALIGNED]], %[[VAARG_ON_STACK]] ]255// CHECK: [[RESULT:%[a-z_0-9]+]] = load i32, ptr [[ADDR]]256// CHECK: ret i32 [[RESULT]]257}258 259typedef int overaligned_int __attribute__((aligned(32)));260overaligned_int overaligned_int_test(void) {261// CHECK-LABEL: define{{.*}} i32 @overaligned_int_test()262  return va_arg(the_list, overaligned_int);263// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)264// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0265// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]266 267// CHECK: [[VAARG_MAYBE_REG]]268// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8269// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)270// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0271// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]272 273// CHECK: [[VAARG_IN_REG]]274// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)275// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]276// CHECK-BE: [[REG_ADDR_ALIGNED:%[0-9]+]] = getelementptr inbounds i8, ptr [[REG_ADDR]], i64 4277// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]278 279// CHECK: [[VAARG_ON_STACK]]280// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list281// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8282// CHECK: store ptr [[NEW_STACK]], ptr @the_list283// CHECK-BE: [[STACK_ALIGNED:%[a-z_0-9]*]] = getelementptr inbounds i8, ptr [[STACK]], i64 4284// CHECK: br label %[[VAARG_END]]285 286// CHECK: [[VAARG_END]]287// CHECK-LE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]288// CHECK-BE: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR_ALIGNED]], %[[VAARG_IN_REG]] ], [ [[STACK_ALIGNED]], %[[VAARG_ON_STACK]] ]289// CHECK: [[RESULT:%[a-z_0-9]+]] = load i32, ptr [[ADDR]]290// CHECK: ret i32 [[RESULT]]291}292 293typedef long long underaligned_long_long  __attribute__((packed,aligned(2)));294underaligned_long_long underaligned_long_long_test(void) {295// CHECK-LABEL: define{{.*}} i64 @underaligned_long_long_test()296  return va_arg(the_list, underaligned_long_long);297// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)298// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0299// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]300 301// CHECK: [[VAARG_MAYBE_REG]]302// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8303// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)304// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0305// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]306 307// CHECK: [[VAARG_IN_REG]]308// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)309// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]310// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]311 312// CHECK: [[VAARG_ON_STACK]]313// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list314// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8315// CHECK: store ptr [[NEW_STACK]], ptr @the_list316// CHECK: br label %[[VAARG_END]]317 318// CHECK: [[VAARG_END]]319// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]320// CHECK: [[RESULT:%[a-z_0-9]+]] = load i64, ptr [[ADDR]]321// CHECK: ret i64 [[RESULT]]322}323 324typedef long long overaligned_long_long  __attribute__((aligned(32)));325overaligned_long_long overaligned_long_long_test(void) {326// CHECK-LABEL: define{{.*}} i64 @overaligned_long_long_test()327  return va_arg(the_list, overaligned_long_long);328// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)329// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0330// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]331 332// CHECK: [[VAARG_MAYBE_REG]]333// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8334// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)335// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0336// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]337 338// CHECK: [[VAARG_IN_REG]]339// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)340// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]341// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]342 343// CHECK: [[VAARG_ON_STACK]]344// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list345// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8346// CHECK: store ptr [[NEW_STACK]], ptr @the_list347// CHECK: br label %[[VAARG_END]]348 349// CHECK: [[VAARG_END]]350// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]351// CHECK: [[RESULT:%[a-z_0-9]+]] = load i64, ptr [[ADDR]]352// CHECK: ret i64 [[RESULT]]353}354 355typedef __int128 underaligned_int128  __attribute__((packed,aligned(2)));356underaligned_int128 underaligned_int128_test(void) {357// CHECK-LABEL: define{{.*}} i128 @underaligned_int128_test()358  return va_arg(the_list, underaligned_int128);359// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)360// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0361// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]362 363// CHECK: [[VAARG_MAYBE_REG]]364// CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15365// CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16366// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16367// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)368// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0369// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]370 371// CHECK: [[VAARG_IN_REG]]372// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)373// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[ALIGNED_REGOFFS]]374// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]375 376// CHECK: [[VAARG_ON_STACK]]377// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list378// CHECK: [[STACKINC:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i32 15379// CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9.]+]] = call ptr @llvm.ptrmask.p0.i64(ptr [[STACKINC]], i64 -16)380// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[ALIGNED_STACK_PTR]], i64 16381// CHECK: store ptr [[NEW_STACK]], ptr @the_list382// CHECK: br label %[[VAARG_END]]383 384// CHECK: [[VAARG_END]]385// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[ALIGNED_STACK_PTR]], %[[VAARG_ON_STACK]] ]386// CHECK: [[RESULT:%[a-z_0-9]+]] = load i128, ptr [[ADDR]]387// CHECK: ret i128 [[RESULT]]388}389 390typedef __int128 overaligned_int128  __attribute__((aligned(32)));391overaligned_int128 overaligned_int128_test(void) {392// CHECK-LABEL: define{{.*}} i128 @overaligned_int128_test()393  return va_arg(the_list, overaligned_int128);394// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)395// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0396// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]397 398// CHECK: [[VAARG_MAYBE_REG]]399// CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15400// CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16401// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16402// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)403// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0404// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]405 406// CHECK: [[VAARG_IN_REG]]407// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)408// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[ALIGNED_REGOFFS]]409// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]410 411// CHECK: [[VAARG_ON_STACK]]412// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list413// CHECK: [[STACKINC:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i32 15414// CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9.]+]] = call ptr @llvm.ptrmask.p0.i64(ptr [[STACKINC]], i64 -16)415// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[ALIGNED_STACK_PTR]], i64 16416// CHECK: store ptr [[NEW_STACK]], ptr @the_list417// CHECK: br label %[[VAARG_END]]418 419// CHECK: [[VAARG_END]]420// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[ALIGNED_STACK_PTR]], %[[VAARG_ON_STACK]] ]421// CHECK: [[RESULT:%[a-z_0-9]+]] = load i128, ptr [[ADDR]]422// CHECK: ret i128 [[RESULT]]423}424 425// The way that attributes applied to a struct change parameter passing is a426// little strange, in that the alignment due to attributes is used when427// calculating the size of the struct, but the alignment is based only on the428// alignment of the members (which can be affected by attributes). What this429// means is:430//  * The only effect of the aligned attribute on a struct is to increase its431//    size if the alignment is greater than the member alignment.432//  * The packed attribute is considered as applying to the members, so it will433//    affect the alignment.434// Additionally the alignment can't go below 8 or above 16, so it's only435// __int128 that can be affected by a change in alignment.436 437typedef struct __attribute__((packed,aligned(2))) {438  int val;439} underaligned_int_struct;440underaligned_int_struct underaligned_int_struct_test(void) {441// CHECK-LE-LABEL: define{{.*}} i32 @underaligned_int_struct_test()442// CHECK-BE-LABEL: define{{.*}} i64 @underaligned_int_struct_test()443  return va_arg(the_list, underaligned_int_struct);444// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)445// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0446// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]447 448// CHECK: [[VAARG_MAYBE_REG]]449// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8450// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)451// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0452// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]453 454// CHECK: [[VAARG_IN_REG]]455// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)456// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]457// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]458 459// CHECK: [[VAARG_ON_STACK]]460// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list461// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8462// CHECK: store ptr [[NEW_STACK]], ptr @the_list463// CHECK: br label %[[VAARG_END]]464 465// CHECK: [[VAARG_END]]466// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]467}468 469typedef struct __attribute__((aligned(16))) {470  int val;471} overaligned_int_struct;472overaligned_int_struct overaligned_int_struct_test(void) {473// CHECK-LABEL: define{{.*}} i128 @overaligned_int_struct_test()474  return va_arg(the_list, overaligned_int_struct);475// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)476// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0477// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]478 479// CHECK: [[VAARG_MAYBE_REG]]480// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 16481// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)482// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0483// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]484 485// CHECK: [[VAARG_IN_REG]]486// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)487// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]488// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]489 490// CHECK: [[VAARG_ON_STACK]]491// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list492// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 16493// CHECK: store ptr [[NEW_STACK]], ptr @the_list494// CHECK: br label %[[VAARG_END]]495 496// CHECK: [[VAARG_END]]497// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]498}499 500typedef struct __attribute__((packed,aligned(2))) {501  long long val;502} underaligned_long_long_struct;503underaligned_long_long_struct underaligned_long_long_struct_test(void) {504// CHECK-LABEL: define{{.*}} i64 @underaligned_long_long_struct_test()505  return va_arg(the_list, underaligned_long_long_struct);506// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)507// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0508// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]509 510// CHECK: [[VAARG_MAYBE_REG]]511// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8512// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)513// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0514// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]515 516// CHECK: [[VAARG_IN_REG]]517// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)518// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]519// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]520 521// CHECK: [[VAARG_ON_STACK]]522// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list523// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8524// CHECK: store ptr [[NEW_STACK]], ptr @the_list525// CHECK: br label %[[VAARG_END]]526 527// CHECK: [[VAARG_END]]528// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]529}530 531typedef struct __attribute__((aligned(16))) {532  long long val;533} overaligned_long_long_struct;534overaligned_long_long_struct overaligned_long_long_struct_test(void) {535// CHECK-LABEL: define{{.*}} i128 @overaligned_long_long_struct_test()536  return va_arg(the_list, overaligned_long_long_struct);537// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)538// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0539// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]540 541// CHECK: [[VAARG_MAYBE_REG]]542// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 16543// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)544// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0545// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]546 547// CHECK: [[VAARG_IN_REG]]548// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)549// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]550// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]551 552// CHECK: [[VAARG_ON_STACK]]553// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list554// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 16555// CHECK: store ptr [[NEW_STACK]], ptr @the_list556// CHECK: br label %[[VAARG_END]]557 558// CHECK: [[VAARG_END]]559// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]560}561 562typedef struct __attribute__((packed,aligned(2))) {563  __int128 val;564} underaligned_int128_struct;565underaligned_int128_struct underaligned_int128_struct_test(void) {566// CHECK-LABEL: define{{.*}} [2 x i64] @underaligned_int128_struct_test()567  return va_arg(the_list, underaligned_int128_struct);568// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)569// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0570// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]571 572// CHECK: [[VAARG_MAYBE_REG]]573// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 16574// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)575// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0576// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]577 578// CHECK: [[VAARG_IN_REG]]579// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)580// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]581// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]582 583// CHECK: [[VAARG_ON_STACK]]584// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list585// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 16586// CHECK: store ptr [[NEW_STACK]], ptr @the_list587// CHECK: br label %[[VAARG_END]]588 589// CHECK: [[VAARG_END]]590// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]591}592 593// Overaligning to 32 bytes causes it to be passed indirectly via a pointer594typedef struct __attribute__((aligned(32))) {595  __int128 val;596} overaligned_int128_struct;597overaligned_int128_struct overaligned_int128_struct_test(void) {598// CHECK-LABEL: define{{.*}} void @overaligned_int128_struct_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int128_struct) align 32 %agg.result)599  return va_arg(the_list, overaligned_int128_struct);600// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)601// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0602// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]603 604// CHECK: [[VAARG_MAYBE_REG]]605// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8606// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)607// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0608// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]609 610// CHECK: [[VAARG_IN_REG]]611// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)612// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]613// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]614 615// CHECK: [[VAARG_ON_STACK]]616// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list617// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8618// CHECK: store ptr [[NEW_STACK]], ptr @the_list619// CHECK: br label %[[VAARG_END]]620 621// CHECK: [[VAARG_END]]622// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]623}624 625// Overaligning or underaligning a struct member changes both its alignment and626// size when passed as an argument.627 628typedef struct {629  int val __attribute__((packed,aligned(2)));630} underaligned_int_struct_member;631underaligned_int_struct_member underaligned_int_struct_member_test(void) {632// CHECK-LE-LABEL: define{{.*}} i32 @underaligned_int_struct_member_test()633// CHECK-BE-LABEL: define{{.*}} i64 @underaligned_int_struct_member_test()634  return va_arg(the_list, underaligned_int_struct_member);635// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)636// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0637// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]638 639// CHECK: [[VAARG_MAYBE_REG]]640// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8641// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)642// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0643// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]644 645// CHECK: [[VAARG_IN_REG]]646// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)647// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]648// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]649 650// CHECK: [[VAARG_ON_STACK]]651// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list652// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8653// CHECK: store ptr [[NEW_STACK]], ptr @the_list654// CHECK: br label %[[VAARG_END]]655 656// CHECK: [[VAARG_END]]657// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]658}659 660typedef struct {661  int val __attribute__((aligned(16)));662} overaligned_int_struct_member;663overaligned_int_struct_member overaligned_int_struct_member_test(void) {664// CHECK-LABEL: define{{.*}} i128 @overaligned_int_struct_member_test()665  return va_arg(the_list, overaligned_int_struct_member);666// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)667// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0668// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]669 670// CHECK: [[VAARG_MAYBE_REG]]671// CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15672// CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16673// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16674// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)675// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0676// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]677 678// CHECK: [[VAARG_IN_REG]]679// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)680// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[ALIGNED_REGOFFS]]681// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]682 683// CHECK: [[VAARG_ON_STACK]]684// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list685// CHECK: [[STACKINC:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i32 15686// CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9.]+]] = call ptr @llvm.ptrmask.p0.i64(ptr [[STACKINC]], i64 -16)687// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[ALIGNED_STACK_PTR]], i64 16688// CHECK: store ptr [[NEW_STACK]], ptr @the_list689// CHECK: br label %[[VAARG_END]]690 691// CHECK: [[VAARG_END]]692// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[ALIGNED_STACK_PTR]], %[[VAARG_ON_STACK]] ]693}694 695typedef struct {696  long long val __attribute__((packed,aligned(2)));697} underaligned_long_long_struct_member;698underaligned_long_long_struct_member underaligned_long_long_struct_member_test(void) {699// CHECK-LABEL: define{{.*}} i64 @underaligned_long_long_struct_member_test()700  return va_arg(the_list, underaligned_long_long_struct_member);701// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)702// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0703// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]704 705// CHECK: [[VAARG_MAYBE_REG]]706// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8707// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)708// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0709// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]710 711// CHECK: [[VAARG_IN_REG]]712// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)713// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]714// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]715 716// CHECK: [[VAARG_ON_STACK]]717// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list718// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8719// CHECK: store ptr [[NEW_STACK]], ptr @the_list720// CHECK: br label %[[VAARG_END]]721 722// CHECK: [[VAARG_END]]723// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]724}725 726typedef struct {727  long long val __attribute__((aligned(16)));728} overaligned_long_long_struct_member;729overaligned_long_long_struct_member overaligned_long_long_struct_member_test(void) {730// CHECK-LABEL: define{{.*}} i128 @overaligned_long_long_struct_member_test()731  return va_arg(the_list, overaligned_long_long_struct_member);732// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)733// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0734// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]735 736// CHECK: [[VAARG_MAYBE_REG]]737// CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15738// CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16739// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16740// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)741// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0742// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]743 744// CHECK: [[VAARG_IN_REG]]745// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)746// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[ALIGNED_REGOFFS]]747// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]748 749// CHECK: [[VAARG_ON_STACK]]750// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list751// CHECK: [[STACKINC:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i32 15752// CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9.]+]] = call ptr @llvm.ptrmask.p0.i64(ptr [[STACKINC]], i64 -16)753// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[ALIGNED_STACK_PTR]], i64 16754// CHECK: store ptr [[NEW_STACK]], ptr @the_list755// CHECK: br label %[[VAARG_END]]756 757// CHECK: [[VAARG_END]]758// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[ALIGNED_STACK_PTR]], %[[VAARG_ON_STACK]] ]759}760 761typedef struct {762  __int128 val __attribute__((packed,aligned(2)));763} underaligned_int128_struct_member;764underaligned_int128_struct_member underaligned_int128_struct_member_test(void) {765// CHECK-LABEL: define{{.*}} [2 x i64] @underaligned_int128_struct_member_test()766  return va_arg(the_list, underaligned_int128_struct_member);767// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)768// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0769// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]770 771// CHECK: [[VAARG_MAYBE_REG]]772// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 16773// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)774// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0775// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]776 777// CHECK: [[VAARG_IN_REG]]778// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)779// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]780// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]781 782// CHECK: [[VAARG_ON_STACK]]783// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list784// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 16785// CHECK: store ptr [[NEW_STACK]], ptr @the_list786// CHECK: br label %[[VAARG_END]]787 788// CHECK: [[VAARG_END]]789// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]790}791 792// Overaligning to 32 bytes causes it to be passed indirectly via a pointer793typedef struct {794  __int128 val __attribute__((aligned(32)));795} overaligned_int128_struct_member;796overaligned_int128_struct_member overaligned_int128_struct_member_test(void) {797// CHECK-LABEL: define{{.*}} void @overaligned_int128_struct_member_test(ptr dead_on_unwind noalias writable sret(%struct.overaligned_int128_struct_member) align 32 %agg.result)798  return va_arg(the_list, overaligned_int128_struct_member);799// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)800// CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0801// CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]]802 803// CHECK: [[VAARG_MAYBE_REG]]804// CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8805// CHECK: store i32 [[NEW_REG_OFFS]], ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 3)806// CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0807// CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]]808 809// CHECK: [[VAARG_IN_REG]]810// CHECK: [[REG_TOP:%[a-z_0-9]+]] = load ptr, ptr getelementptr inbounds nuw (%struct.__va_list, ptr @the_list, i32 0, i32 1)811// CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[REG_TOP]], i32 [[GR_OFFS]]812// CHECK: br label %[[VAARG_END:[a-z._0-9]+]]813 814// CHECK: [[VAARG_ON_STACK]]815// CHECK: [[STACK:%[a-z_0-9]+]] = load ptr, ptr @the_list816// CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr inbounds i8, ptr [[STACK]], i64 8817// CHECK: store ptr [[NEW_STACK]], ptr @the_list818// CHECK: br label %[[VAARG_END]]819 820// CHECK: [[VAARG_END]]821// CHECK: [[ADDR:%[a-z._0-9]+]] = phi ptr [ [[REG_ADDR]], %[[VAARG_IN_REG]] ], [ [[STACK]], %[[VAARG_ON_STACK]] ]822}823 824void check_start(int n, ...) {825// CHECK-LABEL: define{{.*}} void @check_start(i32 noundef %n, ...)826 827  va_list the_list;828  va_start(the_list, n);829// CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list830// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]])831}832 833typedef struct {} empty;834empty empty_record_test(void) {835// CHECK-LABEL: define{{.*}} void @empty_record_test()836// CHECK: entry837// CHECK-NEXT: ret void838  return va_arg(the_list, empty);839}840