blob: 36c81d94b9e0053f153606641ddbd4a2c9037f60 [file] [log] [blame] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -mtriple=spirv64-- --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s
%struct.agg = type { i32, double }
define spir_func void @variadic_sink(i32 noundef %tag, ...) {
; CHECK-LABEL: define spir_func void @variadic_sink(
; CHECK-SAME: i32 noundef [[TAG:%.*]], ptr [[VARARGS:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 8
; CHECK-NEXT: store ptr [[VARARGS]], ptr [[AP]], align 8
; CHECK-NEXT: switch i32 [[TAG]], label %[[SW_DEFAULT:.*]] [
; CHECK-NEXT: i32 0, label %[[SW_BB:.*]]
; CHECK-NEXT: i32 1, label %[[SW_BB1:.*]]
; CHECK-NEXT: i32 2, label %[[SW_BB4:.*]]
; CHECK-NEXT: i32 3, label %[[SW_BB7:.*]]
; CHECK-NEXT: i32 4, label %[[SW_BB10:.*]]
; CHECK-NEXT: ]
; CHECK: [[SW_BB]]:
; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[AP]], align 8
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 3
; CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -4)
; CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 4
; CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[AP]], align 8
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARGP_CUR_ALIGNED]], align 4
; CHECK-NEXT: br label %[[SW_EPILOG:.*]]
; CHECK: [[SW_BB1]]:
; CHECK-NEXT: [[ARGP_CUR2:%.*]] = load ptr, ptr [[AP]], align 8
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR2]], i32 7
; CHECK-NEXT: [[ARGP_CUR2_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP2]], i64 -8)
; CHECK-NEXT: [[ARGP_NEXT3:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR2_ALIGNED]], i64 8
; CHECK-NEXT: store ptr [[ARGP_NEXT3]], ptr [[AP]], align 8
; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[ARGP_CUR2_ALIGNED]], align 8
; CHECK-NEXT: br label %[[SW_EPILOG]]
; CHECK: [[SW_BB4]]:
; CHECK-NEXT: [[ARGP_CUR5:%.*]] = load ptr, ptr [[AP]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR5]], i32 7
; CHECK-NEXT: [[ARGP_CUR5_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP4]], i64 -8)
; CHECK-NEXT: [[ARGP_NEXT6:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR5_ALIGNED]], i64 8
; CHECK-NEXT: store ptr [[ARGP_NEXT6]], ptr [[AP]], align 8
; CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[ARGP_CUR5_ALIGNED]], align 8
; CHECK-NEXT: br label %[[SW_EPILOG]]
; CHECK: [[SW_BB7]]:
; CHECK-NEXT: [[ARGP_CUR8:%.*]] = load ptr, ptr [[AP]], align 8
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR8]], i32 7
; CHECK-NEXT: [[ARGP_CUR8_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP6]], i64 -8)
; CHECK-NEXT: [[ARGP_NEXT9:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR8_ALIGNED]], i64 16
; CHECK-NEXT: store ptr [[ARGP_NEXT9]], ptr [[AP]], align 8
; CHECK-NEXT: br label %[[SW_EPILOG]]
; CHECK: [[SW_BB10]]:
; CHECK-NEXT: [[ARGP_CUR11:%.*]] = load ptr, ptr [[AP]], align 8
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR11]], i32 15
; CHECK-NEXT: [[ARGP_CUR11_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP7]], i64 -16)
; CHECK-NEXT: [[ARGP_NEXT12:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR11_ALIGNED]], i64 16
; CHECK-NEXT: store ptr [[ARGP_NEXT12]], ptr [[AP]], align 8
; CHECK-NEXT: [[TMP8:%.*]] = load <4 x float>, ptr [[ARGP_CUR11_ALIGNED]], align 16
; CHECK-NEXT: br label %[[SW_EPILOG]]
; CHECK: [[SW_DEFAULT]]:
; CHECK-NEXT: br label %[[SW_EPILOG]]
; CHECK: [[SW_EPILOG]]:
; CHECK-NEXT: ret void
;
entry:
%ap = alloca ptr, align 8
call void @llvm.va_start.p0(ptr %ap)
switch i32 %tag, label %sw.default [
i32 0, label %sw.bb
i32 1, label %sw.bb1
i32 2, label %sw.bb4
i32 3, label %sw.bb7
i32 4, label %sw.bb10
]
sw.bb: ; preds = %entry
%argp.cur = load ptr, ptr %ap, align 8
%0 = getelementptr inbounds i8, ptr %argp.cur, i32 3
%argp.cur.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %0, i64 -4)
%argp.next = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 4
store ptr %argp.next, ptr %ap, align 8
%1 = load i32, ptr %argp.cur.aligned, align 4
br label %sw.epilog
sw.bb1: ; preds = %entry
%argp.cur2 = load ptr, ptr %ap, align 8
%2 = getelementptr inbounds i8, ptr %argp.cur2, i32 7
%argp.cur2.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %2, i64 -8)
%argp.next3 = getelementptr inbounds i8, ptr %argp.cur2.aligned, i64 8
store ptr %argp.next3, ptr %ap, align 8
%3 = load i64, ptr %argp.cur2.aligned, align 8
br label %sw.epilog
sw.bb4: ; preds = %entry
%argp.cur5 = load ptr, ptr %ap, align 8
%4 = getelementptr inbounds i8, ptr %argp.cur5, i32 7
%argp.cur5.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %4, i64 -8)
%argp.next6 = getelementptr inbounds i8, ptr %argp.cur5.aligned, i64 8
store ptr %argp.next6, ptr %ap, align 8
%5 = load double, ptr %argp.cur5.aligned, align 8
br label %sw.epilog
sw.bb7: ; preds = %entry
%argp.cur8 = load ptr, ptr %ap, align 8
%6 = getelementptr inbounds i8, ptr %argp.cur8, i32 7
%argp.cur8.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %6, i64 -8)
%argp.next9 = getelementptr inbounds i8, ptr %argp.cur8.aligned, i64 16
store ptr %argp.next9, ptr %ap, align 8
br label %sw.epilog
sw.bb10: ; preds = %entry
%argp.cur11 = load ptr, ptr %ap, align 8
%7 = getelementptr inbounds i8, ptr %argp.cur11, i32 15
%argp.cur11.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %7, i64 -16)
%argp.next12 = getelementptr inbounds i8, ptr %argp.cur11.aligned, i64 16
store ptr %argp.next12, ptr %ap, align 8
%8 = load <4 x float>, ptr %argp.cur11.aligned, align 16
br label %sw.epilog
sw.default: ; preds = %entry
br label %sw.epilog
sw.epilog: ; preds = %sw.default, %sw.bb10, %sw.bb7, %sw.bb4, %sw.bb1, %sw.bb
call void @llvm.va_end.p0(ptr %ap)
ret void
}
define spir_func void @call_i32() {
; CHECK-LABEL: define spir_func void @call_i32() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[CALL_I32_VARARG:%.*]], align 4
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CALL_I32_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
; CHECK-NEXT: store i32 1, ptr [[TMP0]], align 4
; CHECK-NEXT: call spir_func void @variadic_sink(i32 noundef 0, ptr [[VARARG_BUFFER]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: ret void
;
entry:
call spir_func void (i32, ...) @variadic_sink(i32 noundef 0, i32 noundef 1)
ret void
}
define spir_func void @call_i64() {
; CHECK-LABEL: define spir_func void @call_i64() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[CALL_I64_VARARG:%.*]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CALL_I64_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
; CHECK-NEXT: store i64 1, ptr [[TMP0]], align 8
; CHECK-NEXT: call spir_func void @variadic_sink(i32 noundef 1, ptr [[VARARG_BUFFER]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: ret void
;
entry:
call spir_func void (i32, ...) @variadic_sink(i32 noundef 1, i64 noundef 1)
ret void
}
define spir_func void @call_f64() {
; CHECK-LABEL: define spir_func void @call_f64() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[CALL_F64_VARARG:%.*]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CALL_F64_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
; CHECK-NEXT: store double 1.000000e+00, ptr [[TMP0]], align 8
; CHECK-NEXT: call spir_func void @variadic_sink(i32 noundef 2, ptr [[VARARG_BUFFER]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: ret void
;
entry:
call spir_func void (i32, ...) @variadic_sink(i32 noundef 2, double noundef 1.000000e+00)
ret void
}
define spir_func void @call_struct() {
; CHECK-LABEL: define spir_func void @call_struct() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[DOTCOMPOUNDLITERAL:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[CALL_STRUCT_VARARG:%.*]], align 8
; CHECK-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 0
; CHECK-NEXT: store i32 1, ptr [[A]], align 8
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[DOTCOMPOUNDLITERAL]], i64 4
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 4, i1 false)
; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[DOTCOMPOUNDLITERAL]], i32 0, i32 1
; CHECK-NEXT: store double 2.000000e+00, ptr [[B]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[CALL_STRUCT_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[TMP1]], ptr [[DOTCOMPOUNDLITERAL]], i64 16, i1 false)
; CHECK-NEXT: call spir_func void @variadic_sink(i32 noundef 3, ptr [[VARARG_BUFFER]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: ret void
;
entry:
%.compoundliteral = alloca %struct.agg, align 8
%a = getelementptr inbounds nuw %struct.agg, ptr %.compoundliteral, i32 0, i32 0
store i32 1, ptr %a, align 8
%0 = getelementptr i8, ptr %.compoundliteral, i64 4
call void @llvm.memset.p0.i64(ptr align 4 %0, i8 0, i64 4, i1 false)
%b = getelementptr inbounds nuw %struct.agg, ptr %.compoundliteral, i32 0, i32 1
store double 2.000000e+00, ptr %b, align 8
call spir_func void (i32, ...) @variadic_sink(i32 noundef 3, ptr noundef byval(%struct.agg) align 8 %.compoundliteral)
ret void
}
define spir_func void @call_vector() {
; CHECK-LABEL: define spir_func void @call_vector() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[CALL_VECTOR_VARARG:%.*]], align 16
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CALL_VECTOR_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0
; CHECK-NEXT: store <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>, ptr [[TMP0]], align 16
; CHECK-NEXT: call spir_func void @variadic_sink(i32 noundef 4, ptr [[VARARG_BUFFER]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VARARG_BUFFER]])
; CHECK-NEXT: ret void
;
entry:
call spir_func void (i32, ...) @variadic_sink(i32 noundef 4, <4 x float> noundef <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>)
ret void
}