blob: 8047f78f37501fb26a773e01d73e7088add36ec3 [file] [edit]
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
// RUN: %clang_cc1 -triple mips-none-linux-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR32,GPR32BE
// RUN: %clang_cc1 -triple mipsel-none-linux-gnu -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR32,GPR32LE
// RUN: %clang_cc1 -triple mips64-none-linux-gnu -target-abi n32 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR64N32
// RUN: %clang_cc1 -triple mips64-none-linux-gnu -target-abi n64 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR64N64BE
// RUN: %clang_cc1 -triple mips64el-none-linux-gnu -target-abi n64 -emit-llvm -o - %s \
// RUN: | FileCheck %s --check-prefixes=GPR64N64LE
// Test mips logic for reading aggregates from the variable argument list.
#include <stdarg.h>
extern void sink(int, ...);
struct char_char {
char x, y;
};
struct short_short {
short x, y;
};
struct int_int {
int x, y;
};
struct long_long {
long x, y;
};
struct long_long_long_long {
long long x, y;
};
struct float_float {
float x, y;
};
struct double_double {
double x, y;
};
struct long_double_long_double {
long double x, y;
};
struct aligned_int {
int x;
} __attribute__((aligned(16)));
struct aligned_float {
float x;
} __attribute__((aligned(16)));
struct int_int_int_int {
int a, b, c, d;
};
struct float_float_float_float {
float a, b, c, d;
};
// GPR32-LABEL: define dso_local void @test_complex_char(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0:[0-9]+]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { i8, i8 }, align 1
// GPR32-NEXT: [[COERCE:%.*]] = alloca { i8, i8 }, align 1
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i8, ptr [[ARGP_CUR_REALP]], align 4
// GPR32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i8, ptr [[ARGP_CUR_IMAGP]], align 1
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store i8 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 1
// GPR32-NEXT: store i8 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 1
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load i8, ptr [[X_REALP1]], align 1
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load i8, ptr [[X_IMAGP2]], align 1
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store i8 [[X_REAL]], ptr [[COERCE_REALP]], align 1
// GPR32-NEXT: store i8 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 1
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg noundef [[TMP2]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_char(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0:[0-9]+]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { i8, i8 }, align 1
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { i8, i8 }, align 1
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i8, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i8, ptr [[ARGP_CUR_IMAGP]], align 1
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store i8 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 1
// GPR64N32-NEXT: store i8 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 1
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load i8, ptr [[X_REALP1]], align 1
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load i8, ptr [[X_IMAGP2]], align 1
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store i8 [[X_REAL]], ptr [[COERCE_REALP]], align 1
// GPR64N32-NEXT: store i8 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 1
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg noundef [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_char(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0:[0-9]+]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { i8, i8 }, align 1
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { i8, i8 }, align 1
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i8, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i8, ptr [[ARGP_CUR_IMAGP]], align 1
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store i8 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 1
// GPR64N64BE-NEXT: store i8 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 1
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load i8, ptr [[X_REALP1]], align 1
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load i8, ptr [[X_IMAGP2]], align 1
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store i8 [[X_REAL]], ptr [[COERCE_REALP]], align 1
// GPR64N64BE-NEXT: store i8 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 1
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg noundef [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_char(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0:[0-9]+]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { i8, i8 }, align 1
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { i8, i8 }, align 1
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i8, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i8, ptr [[ARGP_CUR_IMAGP]], align 1
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store i8 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 1
// GPR64N64LE-NEXT: store i8 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 1
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load i8, ptr [[X_REALP1]], align 1
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load i8, ptr [[X_IMAGP2]], align 1
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store i8 [[X_REAL]], ptr [[COERCE_REALP]], align 1
// GPR64N64LE-NEXT: store i8 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 1
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg noundef [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_char(va_list *ap) {
_Complex char x = va_arg(*ap, _Complex char);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_char_char(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_CHAR_CHAR:%.*]], align 1
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[X]], ptr align 4 [[ARGP_CUR]], i32 2, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg [[TMP2]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_char_char(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_CHAR_CHAR:%.*]], align 1
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[X]], ptr align 8 [[ARGP_CUR]], i32 2, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_char_char(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_CHAR_CHAR:%.*]], align 1
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[X]], ptr align 8 [[ARGP_CUR]], i64 2, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_char_char(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_CHAR_CHAR:%.*]], align 1
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[X]], ptr align 8 [[ARGP_CUR]], i64 2, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i16 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 1
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 inreg [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_char_char(va_list *ap) {
struct char_char x = va_arg(*ap, struct char_char);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_short(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { i16, i16 }, align 2
// GPR32-NEXT: [[COERCE:%.*]] = alloca { i16, i16 }, align 2
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i16, ptr [[ARGP_CUR_REALP]], align 4
// GPR32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i16, ptr [[ARGP_CUR_IMAGP]], align 2
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store i16 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 2
// GPR32-NEXT: store i16 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 2
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load i16, ptr [[X_REALP1]], align 2
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load i16, ptr [[X_IMAGP2]], align 2
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store i16 [[X_REAL]], ptr [[COERCE_REALP]], align 2
// GPR32-NEXT: store i16 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 2
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_short(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { i16, i16 }, align 2
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { i16, i16 }, align 2
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i16, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i16, ptr [[ARGP_CUR_IMAGP]], align 2
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store i16 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 2
// GPR64N32-NEXT: store i16 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 2
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load i16, ptr [[X_REALP1]], align 2
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load i16, ptr [[X_IMAGP2]], align 2
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store i16 [[X_REAL]], ptr [[COERCE_REALP]], align 2
// GPR64N32-NEXT: store i16 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 2
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_short(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { i16, i16 }, align 2
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { i16, i16 }, align 2
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i16, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i16, ptr [[ARGP_CUR_IMAGP]], align 2
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store i16 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 2
// GPR64N64BE-NEXT: store i16 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 2
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load i16, ptr [[X_REALP1]], align 2
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load i16, ptr [[X_IMAGP2]], align 2
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store i16 [[X_REAL]], ptr [[COERCE_REALP]], align 2
// GPR64N64BE-NEXT: store i16 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 2
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_short(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { i16, i16 }, align 2
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { i16, i16 }, align 2
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i16, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i16, ptr [[ARGP_CUR_IMAGP]], align 2
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store i16 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 2
// GPR64N64LE-NEXT: store i16 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 2
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load i16, ptr [[X_REALP1]], align 2
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load i16, ptr [[X_IMAGP2]], align 2
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store i16 [[X_REAL]], ptr [[COERCE_REALP]], align 2
// GPR64N64LE-NEXT: store i16 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 2
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_short(va_list *ap) {
_Complex short x = va_arg(*ap, _Complex short);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_short_short(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_SHORT_SHORT:%.*]], align 2
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[X]], ptr align 4 [[ARGP_CUR]], i32 4, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_short_short(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_SHORT_SHORT:%.*]], align 2
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[X]], ptr align 8 [[ARGP_CUR]], i32 4, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_short_short(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_SHORT_SHORT:%.*]], align 2
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 [[X]], ptr align 8 [[ARGP_CUR]], i64 4, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_short_short(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_SHORT_SHORT:%.*]], align 2
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 [[X]], ptr align 8 [[ARGP_CUR]], i64 4, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 2
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_short_short(va_list *ap) {
struct short_short x = va_arg(*ap, struct short_short);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_int(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4
// GPR32-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 4
// GPR32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR32-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR32-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]], i32 inreg noundef [[TMP4]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_int(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N32-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N32-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_int(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N64BE-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N64BE-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_int(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N64LE-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N64LE-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_int(va_list *ap) {
_Complex int x = va_arg(*ap, _Complex int);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_int_int(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT:%.*]], align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[ARGP_CUR]], i32 8, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]], i32 inreg [[TMP4]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_int_int(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT:%.*]], align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i32 8, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_int_int(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT:%.*]], align 4
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_int_int(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT:%.*]], align 4
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_int_int(va_list *ap) {
struct int_int x = va_arg(*ap, struct int_int);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_long(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4
// GPR32-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 4
// GPR32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR32-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR32-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]], i32 inreg noundef [[TMP4]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_long(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N32-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N32-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_long(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N64BE-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N64BE-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_long(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N64LE-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N64LE-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_long(va_list *ap) {
_Complex long x = va_arg(*ap, _Complex long);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_long_long(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG:%.*]], align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[ARGP_CUR]], i32 8, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]], i32 inreg [[TMP4]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_long_long(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG:%.*]], align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i32 8, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_long_long(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG:%.*]], align 8
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_long_long(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG:%.*]], align 8
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_long_long(va_list *ap) {
struct long_long x = va_arg(*ap, struct long_long);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_long_long(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8
// GPR32-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_REAL:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED_REALP]], align 8
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED_IMAGP]], align 8
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store i64 [[ARGP_CUR_ALIGNED_REAL]], ptr [[X_REALP]], align 8
// GPR32-NEXT: store i64 [[ARGP_CUR_ALIGNED_IMAG]], ptr [[X_IMAGP]], align 8
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR32-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 8
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg noundef [[TMP3]], i32 inreg noundef [[TMP5]], i32 inreg noundef [[TMP7]], i32 inreg noundef [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_long_long(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N32-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N32-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_long_long(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N64BE-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N64BE-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_long_long(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N64LE-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N64LE-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_long_long(va_list *ap) {
_Complex long long x = va_arg(*ap, _Complex long long);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_long_long_long_long(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG_LONG_LONG:%.*]], align 8
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 8
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg [[TMP3]], i32 inreg [[TMP5]], i32 inreg [[TMP7]], i32 inreg [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_long_long_long_long(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG_LONG_LONG:%.*]], align 8
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i32 16, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_long_long_long_long(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG_LONG_LONG:%.*]], align 8
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_long_long_long_long(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG_LONG_LONG:%.*]], align 8
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_long_long_long_long(va_list *ap) {
struct long_long_long_long x =
va_arg(*ap, struct long_long_long_long);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_float(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { float, float }, align 4
// GPR32-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_REAL:%.*]] = load float, ptr [[ARGP_CUR_REALP]], align 4
// GPR32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load float, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store float [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR32-NEXT: store float [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP1]], align 4
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP2]], align 4
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR32-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg noundef [[TMP2]], i32 inreg noundef [[TMP4]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_float(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { float, float }, align 4
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load float, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load float, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store float [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N32-NEXT: store float [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP1]], align 4
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP2]], align 4
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N32-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_float(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { float, float }, align 4
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load float, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load float, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store float [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N64BE-NEXT: store float [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP1]], align 4
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP2]], align 4
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N64BE-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_float(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { float, float }, align 4
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load float, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load float, ptr [[ARGP_CUR_IMAGP]], align 4
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store float [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4
// GPR64N64LE-NEXT: store float [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP1]], align 4
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP2]], align 4
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4
// GPR64N64LE-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_float(va_list *ap) {
_Complex float x = va_arg(*ap, _Complex float);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_float_float(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT:%.*]], align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[ARGP_CUR]], i32 8, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]], i32 inreg [[TMP4]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_float_float(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT:%.*]], align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i32 8, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_float_float(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT:%.*]], align 4
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_float_float(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT:%.*]], align 4
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]])
// GPR64N64LE-NEXT: ret void
//
void test_float_float(va_list *ap) {
struct float_float x = va_arg(*ap, struct float_float);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_double(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { double, double }, align 8
// GPR32-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_REAL:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED_REALP]], align 8
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_IMAG:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED_IMAGP]], align 8
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store double [[ARGP_CUR_ALIGNED_REAL]], ptr [[X_REALP]], align 8
// GPR32-NEXT: store double [[ARGP_CUR_ALIGNED_IMAG]], ptr [[X_IMAGP]], align 8
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR32-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 8
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg noundef [[TMP3]], i32 inreg noundef [[TMP5]], i32 inreg noundef [[TMP7]], i32 inreg noundef [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_double(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { double, double }, align 8
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_REAL:%.*]] = load double, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N32-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_IMAG:%.*]] = load double, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store double [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N32-NEXT: store double [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N32-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_double(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { double, double }, align 8
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_REAL:%.*]] = load double, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load double, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store double [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N64BE-NEXT: store double [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N64BE-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_double(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { double, double }, align 8
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_REAL:%.*]] = load double, ptr [[ARGP_CUR_REALP]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_IMAG:%.*]] = load double, ptr [[ARGP_CUR_IMAGP]], align 8
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store double [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8
// GPR64N64LE-NEXT: store double [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR64N64LE-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg noundef [[TMP2]], i64 inreg noundef [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_double(va_list *ap) {
_Complex double x = va_arg(*ap, _Complex double);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_double_double(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_DOUBLE_DOUBLE:%.*]], align 8
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 8
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg [[TMP3]], i32 inreg [[TMP5]], i32 inreg [[TMP7]], i32 inreg [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_double_double(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_DOUBLE_DOUBLE:%.*]], align 8
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i32 16, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, double inreg [[TMP2]], double inreg [[TMP4]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_double_double(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_DOUBLE_DOUBLE:%.*]], align 8
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, double inreg [[TMP2]], double inreg [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_double_double(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_DOUBLE_DOUBLE:%.*]], align 8
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, double inreg [[TMP2]], double inreg [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_double_double(va_list *ap) {
struct double_double x = va_arg(*ap, struct double_double);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_complex_long_double(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca { double, double }, align 8
// GPR32-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 0
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_REAL:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED_REALP]], align 8
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 1
// GPR32-NEXT: [[ARGP_CUR_ALIGNED_IMAG:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED_IMAGP]], align 8
// GPR32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: store double [[ARGP_CUR_ALIGNED_REAL]], ptr [[X_REALP]], align 8
// GPR32-NEXT: store double [[ARGP_CUR_ALIGNED_IMAG]], ptr [[X_IMAGP]], align 8
// GPR32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8
// GPR32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8
// GPR32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8
// GPR32-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 8
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[COERCE]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg noundef [[TMP3]], i32 inreg noundef [[TMP5]], i32 inreg noundef [[TMP7]], i32 inreg noundef [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_complex_long_double(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca { fp128, fp128 }, align 16
// GPR64N32-NEXT: [[COERCE:%.*]] = alloca { fp128, fp128 }, align 16
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -16)
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 32
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 0
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED_REAL:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED_REALP]], align 16
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 1
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED_IMAG:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED_IMAGP]], align 16
// GPR64N32-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: store fp128 [[ARGP_CUR_ALIGNED_REAL]], ptr [[X_REALP]], align 16
// GPR64N32-NEXT: store fp128 [[ARGP_CUR_ALIGNED_IMAG]], ptr [[X_IMAGP]], align 16
// GPR64N32-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[X_REAL:%.*]] = load fp128, ptr [[X_REALP1]], align 16
// GPR64N32-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[X_IMAG:%.*]] = load fp128, ptr [[X_IMAGP2]], align 16
// GPR64N32-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: store fp128 [[X_REAL]], ptr [[COERCE_REALP]], align 16
// GPR64N32-NEXT: store fp128 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 16
// GPR64N32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 2
// GPR64N32-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16
// GPR64N32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 3
// GPR64N32-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg noundef [[TMP3]], i64 inreg noundef [[TMP5]], i64 inreg noundef [[TMP7]], i64 inreg noundef [[TMP9]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_complex_long_double(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca { fp128, fp128 }, align 16
// GPR64N64BE-NEXT: [[COERCE:%.*]] = alloca { fp128, fp128 }, align 16
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 32
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 0
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED_REAL:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED_REALP]], align 16
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 1
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED_IMAG:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED_IMAGP]], align 16
// GPR64N64BE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: store fp128 [[ARGP_CUR_ALIGNED_REAL]], ptr [[X_REALP]], align 16
// GPR64N64BE-NEXT: store fp128 [[ARGP_CUR_ALIGNED_IMAG]], ptr [[X_IMAGP]], align 16
// GPR64N64BE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[X_REAL:%.*]] = load fp128, ptr [[X_REALP1]], align 16
// GPR64N64BE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[X_IMAG:%.*]] = load fp128, ptr [[X_IMAGP2]], align 16
// GPR64N64BE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: store fp128 [[X_REAL]], ptr [[COERCE_REALP]], align 16
// GPR64N64BE-NEXT: store fp128 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 16
// GPR64N64BE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64BE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64BE-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 2
// GPR64N64BE-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16
// GPR64N64BE-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 3
// GPR64N64BE-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg noundef [[TMP3]], i64 inreg noundef [[TMP5]], i64 inreg noundef [[TMP7]], i64 inreg noundef [[TMP9]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_complex_long_double(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca { fp128, fp128 }, align 16
// GPR64N64LE-NEXT: [[COERCE:%.*]] = alloca { fp128, fp128 }, align 16
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 32
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 0
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED_REAL:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED_REALP]], align 16
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[ARGP_CUR_ALIGNED]], i32 0, i32 1
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED_IMAG:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED_IMAGP]], align 16
// GPR64N64LE-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: store fp128 [[ARGP_CUR_ALIGNED_REAL]], ptr [[X_REALP]], align 16
// GPR64N64LE-NEXT: store fp128 [[ARGP_CUR_ALIGNED_IMAG]], ptr [[X_IMAGP]], align 16
// GPR64N64LE-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[X_REAL:%.*]] = load fp128, ptr [[X_REALP1]], align 16
// GPR64N64LE-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[X_IMAG:%.*]] = load fp128, ptr [[X_IMAGP2]], align 16
// GPR64N64LE-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: store fp128 [[X_REAL]], ptr [[COERCE_REALP]], align 16
// GPR64N64LE-NEXT: store fp128 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 16
// GPR64N64LE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64LE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64LE-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 2
// GPR64N64LE-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16
// GPR64N64LE-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[COERCE]], i32 0, i32 3
// GPR64N64LE-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg noundef [[TMP3]], i64 inreg noundef [[TMP5]], i64 inreg noundef [[TMP7]], i64 inreg noundef [[TMP9]])
// GPR64N64LE-NEXT: ret void
//
void test_complex_long_double(va_list *ap) {
_Complex long double x = va_arg(*ap, _Complex long double);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_long_double_long_double(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE:%.*]], align 8
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 8
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg [[TMP3]], i32 inreg [[TMP5]], i32 inreg [[TMP7]], i32 inreg [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_long_double_long_double(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE:%.*]], align 16
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -16)
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 32
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i32 32, i1 false)
// GPR64N32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 2
// GPR64N32-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16
// GPR64N32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 3
// GPR64N32-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]], i64 inreg [[TMP7]], i64 inreg [[TMP9]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_long_double_long_double(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE:%.*]], align 16
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 32
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 32, i1 false)
// GPR64N64BE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64BE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64BE-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 2
// GPR64N64BE-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16
// GPR64N64BE-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 3
// GPR64N64BE-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]], i64 inreg [[TMP7]], i64 inreg [[TMP9]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_long_double_long_double(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE:%.*]], align 16
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 32
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 32, i1 false)
// GPR64N64LE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64LE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64LE-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 2
// GPR64N64LE-NEXT: [[TMP7:%.*]] = load i64, ptr [[TMP6]], align 16
// GPR64N64LE-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i64, i64, i64, i64 }, ptr [[X]], i32 0, i32 3
// GPR64N64LE-NEXT: [[TMP9:%.*]] = load i64, ptr [[TMP8]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]], i64 inreg [[TMP7]], i64 inreg [[TMP9]])
// GPR64N64LE-NEXT: ret void
//
void test_long_double_long_double(va_list *ap) {
struct long_double_long_double x =
va_arg(*ap, struct long_double_long_double);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_aligned_int(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_INT:%.*]], align 16
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 8 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 16
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg [[TMP3]], i32 inreg [[TMP5]], i32 inreg [[TMP7]], i32 inreg [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_aligned_int(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_INT:%.*]], align 16
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -16)
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR64N32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_aligned_int(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_INT:%.*]], align 16
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64BE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_aligned_int(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_INT:%.*]], align 16
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64LE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]])
// GPR64N64LE-NEXT: ret void
//
void test_aligned_int(va_list *ap) {
struct aligned_int x = va_arg(*ap, struct aligned_int);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_aligned_float(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_FLOAT:%.*]], align 16
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7
// GPR32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -8)
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 8 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 16
// GPR32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
// GPR32-NEXT: [[TMP6:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP7:%.*]] = load i32, ptr [[TMP6]], align 8
// GPR32-NEXT: [[TMP8:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 undef, i32 inreg [[TMP3]], i32 inreg [[TMP5]], i32 inreg [[TMP7]], i32 inreg [[TMP9]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_aligned_float(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_FLOAT:%.*]], align 16
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N32-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP1]], i32 -16)
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i32 16, i1 false)
// GPR64N32-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N32-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_aligned_float(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_FLOAT:%.*]], align 16
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64BE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64BE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_aligned_float(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_FLOAT:%.*]], align 16
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15
// GPR64N64LE-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16)
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16
// GPR64N64LE-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 inreg [[TMP3]], i64 inreg [[TMP5]])
// GPR64N64LE-NEXT: ret void
//
void test_aligned_float(va_list *ap) {
struct aligned_float x = va_arg(*ap, struct aligned_float);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_int_int_int_int(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT_INT_INT:%.*]], align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[ARGP_CUR]], i32 16, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
// GPR32-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]], i32 inreg [[TMP4]], i32 inreg [[TMP6]], i32 inreg [[TMP8]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_int_int_int_int(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT_INT_INT:%.*]], align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i32 16, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_int_int_int_int(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT_INT_INT:%.*]], align 4
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_int_int_int_int(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT_INT_INT:%.*]], align 4
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_int_int_int_int(va_list *ap) {
struct int_int_int_int x = va_arg(*ap, struct int_int_int_int);
sink(0, x);
}
// GPR32-LABEL: define dso_local void @test_float_float_float_float(
// GPR32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR32-NEXT: [[ENTRY:.*:]]
// GPR32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR32-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT:%.*]], align 4
// GPR32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[ARGP_CUR]], i32 16, i1 false)
// GPR32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 0
// GPR32-NEXT: [[TMP2:%.*]] = load i32, ptr [[TMP1]], align 4
// GPR32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 1
// GPR32-NEXT: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
// GPR32-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 2
// GPR32-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
// GPR32-NEXT: [[TMP7:%.*]] = getelementptr inbounds nuw { i32, i32, i32, i32 }, ptr [[X]], i32 0, i32 3
// GPR32-NEXT: [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
// GPR32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 inreg [[TMP2]], i32 inreg [[TMP4]], i32 inreg [[TMP6]], i32 inreg [[TMP8]])
// GPR32-NEXT: ret void
//
// GPR64N32-LABEL: define dso_local void @test_float_float_float_float(
// GPR64N32-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N32-NEXT: [[ENTRY:.*:]]
// GPR64N32-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4
// GPR64N32-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT:%.*]], align 4
// GPR64N32-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4
// GPR64N32-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4
// GPR64N32-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 16
// GPR64N32-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4
// GPR64N32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i32 16, i1 false)
// GPR64N32-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N32-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N32-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N32-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// GPR64N32-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N32-NEXT: ret void
//
// GPR64N64BE-LABEL: define dso_local void @test_float_float_float_float(
// GPR64N64BE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64BE-NEXT: [[ENTRY:.*:]]
// GPR64N64BE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64BE-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT:%.*]], align 4
// GPR64N64BE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64BE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64BE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64BE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64BE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64BE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64BE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64BE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// GPR64N64BE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64BE-NEXT: ret void
//
// GPR64N64LE-LABEL: define dso_local void @test_float_float_float_float(
// GPR64N64LE-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] {
// GPR64N64LE-NEXT: [[ENTRY:.*:]]
// GPR64N64LE-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8
// GPR64N64LE-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT:%.*]], align 4
// GPR64N64LE-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8
// GPR64N64LE-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16
// GPR64N64LE-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8
// GPR64N64LE-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false)
// GPR64N64LE-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0
// GPR64N64LE-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// GPR64N64LE-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1
// GPR64N64LE-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// GPR64N64LE-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 inreg [[TMP2]], i64 inreg [[TMP4]])
// GPR64N64LE-NEXT: ret void
//
void test_float_float_float_float(va_list *ap) {
struct float_float_float_float x =
va_arg(*ap, struct float_float_float_float);
sink(0, x);
}
//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
// GPR32BE: {{.*}}
// GPR32LE: {{.*}}