| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 | |
| // RUN: %clang_cc1 -triple sparc -emit-llvm -o - %s \ | |
| // RUN: | FileCheck %s --check-prefixes=SPARC | |
| // | |
| // RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm -o - %s \ | |
| // RUN: | FileCheck %s --check-prefixes=SPARC64 | |
| #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; | |
| }; | |
| // SPARC-LABEL: define dso_local void @test_complex_char( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0:[0-9]+]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { i8, i8 }, align 1 | |
| // SPARC-NEXT: [[COERCE:%.*]] = alloca { i8, i8 }, align 1 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 2 | |
| // SPARC-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC-NEXT: [[DOTREAL:%.*]] = load i8, ptr [[DOTREALP]], align 2 | |
| // SPARC-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC-NEXT: [[DOTIMAG:%.*]] = load i8, ptr [[DOTIMAGP]], align 1 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store i8 [[DOTREAL]], ptr [[X_REALP]], align 1 | |
| // SPARC-NEXT: store i8 [[DOTIMAG]], ptr [[X_IMAGP]], align 1 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load i8, ptr [[X_REALP1]], align 1 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load i8, ptr [[X_IMAGP2]], align 1 | |
| // SPARC-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC-NEXT: store i8 [[X_REAL]], ptr [[COERCE_REALP]], align 1 | |
| // SPARC-NEXT: store i8 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 1 | |
| // SPARC-NEXT: [[TMP2:%.*]] = load i16, ptr [[COERCE]], align 1 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, i16 noundef [[TMP2]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_char( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0:[0-9]+]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { i8, i8 }, align 1 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { i8, i8 }, align 1 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 6 | |
| // SPARC64-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[DOTREAL:%.*]] = load i8, ptr [[DOTREALP]], align 2 | |
| // SPARC64-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[DOTIMAG:%.*]] = load i8, ptr [[DOTIMAGP]], align 1 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i8 [[DOTREAL]], ptr [[X_REALP]], align 1 | |
| // SPARC64-NEXT: store i8 [[DOTIMAG]], ptr [[X_IMAGP]], align 1 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load i8, ptr [[X_REALP1]], align 1 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load i8, ptr [[X_IMAGP2]], align 1 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i8, i8 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i8 [[X_REAL]], ptr [[COERCE_REALP]], align 1 | |
| // SPARC64-NEXT: store i8 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 1 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i16, ptr [[COERCE]], align 1 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i16 noundef [[TMP2]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_char(va_list *ap) { | |
| _Complex char x = va_arg(*ap, _Complex char); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_char_char( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_CHAR_CHAR:%.*]], align 1 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[X]], ptr align 1 [[TMP1]], i32 2, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_CHAR_CHAR]]) align 1 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_char_char( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_CHAR_CHAR:%.*]], align 1 | |
| // SPARC64-NEXT: [[X_COERCE:%.*]] = alloca i64, align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[X]], ptr align 8 [[ARGP_CUR]], i64 2, i1 false) | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X_COERCE]], ptr align 1 [[X]], i64 2, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load i64, ptr [[X_COERCE]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP1]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_char_char(va_list *ap) { | |
| struct char_char x = va_arg(*ap, struct char_char); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_short( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { i16, i16 }, align 2 | |
| // SPARC-NEXT: [[COERCE:%.*]] = alloca { i16, i16 }, align 2 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC-NEXT: [[ARGP_CUR_REAL:%.*]] = load i16, ptr [[ARGP_CUR_REALP]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i16, ptr [[ARGP_CUR_IMAGP]], align 2 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store i16 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 2 | |
| // SPARC-NEXT: store i16 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 2 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load i16, ptr [[X_REALP1]], align 2 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load i16, ptr [[X_IMAGP2]], align 2 | |
| // SPARC-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC-NEXT: store i16 [[X_REAL]], ptr [[COERCE_REALP]], align 2 | |
| // SPARC-NEXT: store i16 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 2 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load i32, ptr [[COERCE]], align 2 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, i32 noundef [[TMP1]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_short( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { i16, i16 }, align 2 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { i16, i16 }, align 2 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 4 | |
| // SPARC64-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[DOTREAL:%.*]] = load i16, ptr [[DOTREALP]], align 4 | |
| // SPARC64-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[DOTIMAG:%.*]] = load i16, ptr [[DOTIMAGP]], align 2 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i16 [[DOTREAL]], ptr [[X_REALP]], align 2 | |
| // SPARC64-NEXT: store i16 [[DOTIMAG]], ptr [[X_IMAGP]], align 2 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load i16, ptr [[X_REALP1]], align 2 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load i16, ptr [[X_IMAGP2]], align 2 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i16, i16 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i16 [[X_REAL]], ptr [[COERCE_REALP]], align 2 | |
| // SPARC64-NEXT: store i16 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 2 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i32, ptr [[COERCE]], align 2 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i32 noundef [[TMP2]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_short(va_list *ap) { | |
| _Complex short x = va_arg(*ap, _Complex short); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_short_short( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_SHORT_SHORT:%.*]], align 2 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 2 [[X]], ptr align 2 [[TMP1]], i32 4, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_SHORT_SHORT]]) align 2 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_short_short( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_SHORT_SHORT:%.*]], align 2 | |
| // SPARC64-NEXT: [[X_COERCE:%.*]] = alloca i64, align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 2 [[X]], ptr align 8 [[ARGP_CUR]], i64 4, i1 false) | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X_COERCE]], ptr align 2 [[X]], i64 4, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load i64, ptr [[X_COERCE]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP1]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_short_short(va_list *ap) { | |
| struct short_short x = va_arg(*ap, struct short_short); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_int( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4 | |
| // SPARC-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4 | |
| // SPARC-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4 | |
| // SPARC-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4 | |
| // SPARC-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load i64, ptr [[COERCE]], align 4 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, i64 noundef [[TMP1]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_int( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4 | |
| // SPARC64-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4 | |
| // SPARC64-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load i64, ptr [[COERCE]], align 4 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 noundef [[TMP1]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_int(va_list *ap) { | |
| _Complex int x = va_arg(*ap, _Complex int); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_int_int( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT:%.*]], align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[TMP1]], i32 8, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_INT_INT]]) align 4 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_int_int( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT:%.*]], align 4 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load i64, ptr [[X]], align 4 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP1]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_int_int(va_list *ap) { | |
| struct int_int x = va_arg(*ap, struct int_int); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_long( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { i32, i32 }, align 4 | |
| // SPARC-NEXT: [[COERCE:%.*]] = alloca { i32, i32 }, align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC-NEXT: [[ARGP_CUR_REAL:%.*]] = load i32, ptr [[ARGP_CUR_REALP]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i32, ptr [[ARGP_CUR_IMAGP]], align 4 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store i32 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4 | |
| // SPARC-NEXT: store i32 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load i32, ptr [[X_REALP1]], align 4 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load i32, ptr [[X_IMAGP2]], align 4 | |
| // SPARC-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i32, i32 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC-NEXT: store i32 [[X_REAL]], ptr [[COERCE_REALP]], align 4 | |
| // SPARC-NEXT: store i32 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load i64, ptr [[COERCE]], align 4 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, i64 noundef [[TMP1]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_long( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8 | |
| // SPARC64-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8 | |
| // SPARC64-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 noundef [[TMP2]], i64 noundef [[TMP4]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_long(va_list *ap) { | |
| _Complex long x = va_arg(*ap, _Complex long); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_long_long( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG:%.*]], align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[TMP1]], i32 8, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_LONG_LONG]]) align 4 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_long_long( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG:%.*]], align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_LONG_LONG]], ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[STRUCT_LONG_LONG]], ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP2]], i64 [[TMP4]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_long_long(va_list *ap) { | |
| struct long_long x = va_arg(*ap, struct long_long); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_long_long( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8 | |
| // SPARC-NEXT: [[BYVAL_TEMP:%.*]] = alloca { i64, i64 }, align 8 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC-NEXT: [[DOTREAL:%.*]] = load i64, ptr [[DOTREALP]], align 8 | |
| // SPARC-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC-NEXT: [[DOTIMAG:%.*]] = load i64, ptr [[DOTIMAGP]], align 8 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store i64 [[DOTREAL]], ptr [[X_REALP]], align 8 | |
| // SPARC-NEXT: store i64 [[DOTIMAG]], ptr [[X_IMAGP]], align 8 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8 | |
| // SPARC-NEXT: [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[BYVAL_TEMP]], i32 0, i32 0 | |
| // SPARC-NEXT: [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[BYVAL_TEMP]], i32 0, i32 1 | |
| // SPARC-NEXT: store i64 [[X_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8 | |
| // SPARC-NEXT: store i64 [[X_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval({ i64, i64 }) align 8 [[BYVAL_TEMP]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_long_long( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { i64, i64 }, align 8 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { i64, i64 }, align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[ARGP_CUR_REAL:%.*]] = load i64, ptr [[ARGP_CUR_REALP]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAG:%.*]] = load i64, ptr [[ARGP_CUR_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i64 [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8 | |
| // SPARC64-NEXT: store i64 [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load i64, ptr [[X_REALP1]], align 8 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load i64, ptr [[X_IMAGP2]], align 8 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store i64 [[X_REAL]], ptr [[COERCE_REALP]], align 8 | |
| // SPARC64-NEXT: store i64 [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 noundef [[TMP2]], i64 noundef [[TMP4]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_long_long(va_list *ap) { | |
| _Complex long long x = va_arg(*ap, _Complex long long); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_long_long_long_long( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG_LONG_LONG:%.*]], align 8 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[TMP1]], i32 16, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_LONG_LONG_LONG_LONG]]) align 8 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_long_long_long_long( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_LONG_LONG_LONG:%.*]], align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_LONG_LONG_LONG_LONG]], ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[STRUCT_LONG_LONG_LONG_LONG]], ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP2]], i64 [[TMP4]]) | |
| // SPARC64-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); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_float( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { float, float }, align 4 | |
| // SPARC-NEXT: [[BYVAL_TEMP:%.*]] = alloca { float, float }, align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC-NEXT: [[DOTREAL:%.*]] = load float, ptr [[DOTREALP]], align 4 | |
| // SPARC-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC-NEXT: [[DOTIMAG:%.*]] = load float, ptr [[DOTIMAGP]], align 4 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store float [[DOTREAL]], ptr [[X_REALP]], align 4 | |
| // SPARC-NEXT: store float [[DOTIMAG]], ptr [[X_IMAGP]], align 4 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP1]], align 4 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP2]], align 4 | |
| // SPARC-NEXT: [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[BYVAL_TEMP]], i32 0, i32 0 | |
| // SPARC-NEXT: [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[BYVAL_TEMP]], i32 0, i32 1 | |
| // SPARC-NEXT: store float [[X_REAL]], ptr [[BYVAL_TEMP_REALP]], align 4 | |
| // SPARC-NEXT: store float [[X_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 4 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval({ float, float }) align 4 [[BYVAL_TEMP]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_float( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { float, float }, align 4 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[ARGP_CUR_REAL:%.*]] = load float, ptr [[ARGP_CUR_REALP]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAG:%.*]] = load float, ptr [[ARGP_CUR_IMAGP]], align 4 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store float [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 4 | |
| // SPARC64-NEXT: store float [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 4 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load float, ptr [[X_REALP1]], align 4 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load float, ptr [[X_IMAGP2]], align 4 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store float [[X_REAL]], ptr [[COERCE_REALP]], align 4 | |
| // SPARC64-NEXT: store float [[X_IMAG]], ptr [[COERCE_IMAGP]], align 4 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load i64, ptr [[COERCE]], align 4 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 noundef [[TMP1]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_float(va_list *ap) { | |
| _Complex float x = va_arg(*ap, _Complex float); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_float_float( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT:%.*]], align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[TMP1]], i32 8, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_FLOAT_FLOAT]]) align 4 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_float_float( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT:%.*]], align 4 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 8, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load i64, ptr [[X]], align 4 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP1]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_float_float(va_list *ap) { | |
| struct float_float x = va_arg(*ap, struct float_float); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_double( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { double, double }, align 8 | |
| // SPARC-NEXT: [[BYVAL_TEMP:%.*]] = alloca { double, double }, align 8 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC-NEXT: [[DOTREAL:%.*]] = load double, ptr [[DOTREALP]], align 8 | |
| // SPARC-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC-NEXT: [[DOTIMAG:%.*]] = load double, ptr [[DOTIMAGP]], align 8 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store double [[DOTREAL]], ptr [[X_REALP]], align 8 | |
| // SPARC-NEXT: store double [[DOTIMAG]], ptr [[X_IMAGP]], align 8 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8 | |
| // SPARC-NEXT: [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0 | |
| // SPARC-NEXT: [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1 | |
| // SPARC-NEXT: store double [[X_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8 | |
| // SPARC-NEXT: store double [[X_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_double( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { double, double }, align 8 | |
| // SPARC64-NEXT: [[COERCE:%.*]] = alloca { double, double }, align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[ARGP_CUR_REAL:%.*]] = load double, ptr [[ARGP_CUR_REALP]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[ARGP_CUR]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[ARGP_CUR_IMAG:%.*]] = load double, ptr [[ARGP_CUR_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store double [[ARGP_CUR_REAL]], ptr [[X_REALP]], align 8 | |
| // SPARC64-NEXT: store double [[ARGP_CUR_IMAG]], ptr [[X_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load double, ptr [[X_REALP1]], align 8 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load double, ptr [[X_IMAGP2]], align 8 | |
| // SPARC64-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: store double [[X_REAL]], ptr [[COERCE_REALP]], align 8 | |
| // SPARC64-NEXT: store double [[X_IMAG]], ptr [[COERCE_IMAGP]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[COERCE]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 noundef [[TMP2]], i64 noundef [[TMP4]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_double(va_list *ap) { | |
| _Complex double x = va_arg(*ap, _Complex double); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_double_double( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_DOUBLE_DOUBLE:%.*]], align 8 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[TMP1]], i32 16, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_DOUBLE_DOUBLE]]) align 8 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_double_double( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_DOUBLE_DOUBLE:%.*]], align 8 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP2]], i64 [[TMP4]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_double_double(va_list *ap) { | |
| struct double_double x = va_arg(*ap, struct double_double); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_complex_long_double( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca { fp128, fp128 }, align 8 | |
| // SPARC-NEXT: [[BYVAL_TEMP:%.*]] = alloca { fp128, fp128 }, align 8 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC-NEXT: [[DOTREAL:%.*]] = load fp128, ptr [[DOTREALP]], align 8 | |
| // SPARC-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC-NEXT: [[DOTIMAG:%.*]] = load fp128, ptr [[DOTIMAGP]], align 8 | |
| // SPARC-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: store fp128 [[DOTREAL]], ptr [[X_REALP]], align 8 | |
| // SPARC-NEXT: store fp128 [[DOTIMAG]], ptr [[X_IMAGP]], align 8 | |
| // SPARC-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC-NEXT: [[X_REAL:%.*]] = load fp128, ptr [[X_REALP1]], align 8 | |
| // SPARC-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC-NEXT: [[X_IMAG:%.*]] = load fp128, ptr [[X_IMAGP2]], align 8 | |
| // SPARC-NEXT: [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[BYVAL_TEMP]], i32 0, i32 0 | |
| // SPARC-NEXT: [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[BYVAL_TEMP]], i32 0, i32 1 | |
| // SPARC-NEXT: store fp128 [[X_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8 | |
| // SPARC-NEXT: store fp128 [[X_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8 | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval({ fp128, fp128 }) align 8 [[BYVAL_TEMP]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_complex_long_double( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca { fp128, fp128 }, align 16 | |
| // SPARC64-NEXT: [[BYVAL_TEMP:%.*]] = alloca { fp128, fp128 }, align 16 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 8 | |
| // SPARC64-NEXT: [[DOTREALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[TMP1]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[DOTREAL:%.*]] = load fp128, ptr [[DOTREALP]], align 16 | |
| // SPARC64-NEXT: [[DOTIMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[TMP1]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[DOTIMAG:%.*]] = load fp128, ptr [[DOTIMAGP]], align 16 | |
| // SPARC64-NEXT: [[X_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: store fp128 [[DOTREAL]], ptr [[X_REALP]], align 16 | |
| // SPARC64-NEXT: store fp128 [[DOTIMAG]], ptr [[X_IMAGP]], align 16 | |
| // SPARC64-NEXT: [[X_REALP1:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[X_REAL:%.*]] = load fp128, ptr [[X_REALP1]], align 16 | |
| // SPARC64-NEXT: [[X_IMAGP2:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[X_IMAG:%.*]] = load fp128, ptr [[X_IMAGP2]], align 16 | |
| // SPARC64-NEXT: [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[BYVAL_TEMP]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { fp128, fp128 }, ptr [[BYVAL_TEMP]], i32 0, i32 1 | |
| // SPARC64-NEXT: store fp128 [[X_REAL]], ptr [[BYVAL_TEMP_REALP]], align 16 | |
| // SPARC64-NEXT: store fp128 [[X_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 16 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, ptr nofreeobj noundef align 16 dead_on_return dereferenceable(32) [[BYVAL_TEMP]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_complex_long_double(va_list *ap) { | |
| _Complex long double x = va_arg(*ap, _Complex long double); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_long_double_long_double( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE:%.*]], align 8 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 [[X]], ptr align 8 [[TMP1]], i32 32, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_LONG_DOUBLE_LONG_DOUBLE]]) align 8 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_long_double_long_double( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE:%.*]], align 16 | |
| // SPARC64-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_LONG_DOUBLE_LONG_DOUBLE]], align 16 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[TMP1]], i64 32, i1 false) | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[BYVAL_TEMP]], ptr align 16 [[X]], i64 32, i1 false) | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, ptr nofreeobj noundef align 16 dead_on_return dereferenceable(32) [[BYVAL_TEMP]]) | |
| // SPARC64-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); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_aligned_int( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_INT:%.*]], align 16 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 16 [[TMP1]], i32 16, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_ALIGNED_INT]]) align 16 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_aligned_int( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_INT:%.*]], align 16 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 | |
| // SPARC64-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16) | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 [[TMP3]], i64 [[TMP5]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_aligned_int(va_list *ap) { | |
| struct aligned_int x = va_arg(*ap, struct aligned_int); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_aligned_float( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_FLOAT:%.*]], align 16 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 16 [[X]], ptr align 16 [[TMP1]], i32 16, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_ALIGNED_FLOAT]]) align 16 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_aligned_float( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_ALIGNED_FLOAT:%.*]], align 16 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 | |
| // SPARC64-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP1]], i64 -16) | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[X]], ptr align 16 [[ARGP_CUR_ALIGNED]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 16 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP5:%.*]] = load i64, ptr [[TMP4]], align 8 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 undef, i64 [[TMP3]], i64 [[TMP5]]) | |
| // SPARC64-NEXT: ret void | |
| // | |
| void test_aligned_float(va_list *ap) { | |
| struct aligned_float x = va_arg(*ap, struct aligned_float); | |
| sink(0, x); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_int_int_int_int( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT_INT_INT:%.*]], align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[TMP1]], i32 16, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_INT_INT_INT_INT]]) align 4 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_int_int_int_int( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_INT_INT_INT_INT:%.*]], align 4 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP2]], i64 [[TMP4]]) | |
| // SPARC64-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); | |
| } | |
| // SPARC-LABEL: define dso_local void @test_float_float_float_float( | |
| // SPARC-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC-NEXT: [[ENTRY:.*:]] | |
| // SPARC-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 4 | |
| // SPARC-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT:%.*]], align 4 | |
| // SPARC-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 4 | |
| // SPARC-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 | |
| // SPARC-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 4 | |
| // SPARC-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 | |
| // SPARC-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[X]], ptr align 4 [[TMP1]], i32 16, i1 false) | |
| // SPARC-NEXT: call void (i32, ...) @sink(i32 noundef 0, ptr noundef byval([[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT]]) align 4 [[X]]) | |
| // SPARC-NEXT: ret void | |
| // | |
| // SPARC64-LABEL: define dso_local void @test_float_float_float_float( | |
| // SPARC64-SAME: ptr noundef [[AP:%.*]]) #[[ATTR0]] { | |
| // SPARC64-NEXT: [[ENTRY:.*:]] | |
| // SPARC64-NEXT: [[AP_ADDR:%.*]] = alloca ptr, align 8 | |
| // SPARC64-NEXT: [[X:%.*]] = alloca [[STRUCT_FLOAT_FLOAT_FLOAT_FLOAT:%.*]], align 4 | |
| // SPARC64-NEXT: store ptr [[AP]], ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[TMP0:%.*]] = load ptr, ptr [[AP_ADDR]], align 8 | |
| // SPARC64-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 16 | |
| // SPARC64-NEXT: store ptr [[ARGP_NEXT]], ptr [[TMP0]], align 8 | |
| // SPARC64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[X]], ptr align 8 [[ARGP_CUR]], i64 16, i1 false) | |
| // SPARC64-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 0 | |
| // SPARC64-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 | |
| // SPARC64-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[X]], i32 0, i32 1 | |
| // SPARC64-NEXT: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4 | |
| // SPARC64-NEXT: call void (i32, ...) @sink(i32 noundef signext 0, i64 [[TMP2]], i64 [[TMP4]]) | |
| // SPARC64-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); | |
| } |