533 lines · c
1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 22// RUN: %clang_cc1 -triple loongarch64 -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LA643// RUN: %clang_cc1 -triple loongarch32 -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-LA324 5struct bfloat1 {6 __bf16 a;7};8 9// CHECK-LABEL: define dso_local bfloat @h110// CHECK-SAME: (bfloat noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {11// CHECK-NEXT: entry:12// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT1:%.*]], align 213// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 214// CHECK-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 215// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 216// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT1]], ptr [[RETVAL]], i32 0, i32 017// CHECK-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 218// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw { bfloat }, ptr [[RETVAL]], i32 0, i32 019// CHECK-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[TMP1]], align 220// CHECK-NEXT: ret bfloat [[TMP2]]21//22struct bfloat1 h1(__bf16 a) {23 struct bfloat1 x;24 x.a = a;25 return x;26}27 28struct bfloat2 {29 __bf16 a;30 __bf16 b;31};32 33// CHECK-LABEL: define dso_local { bfloat, bfloat } @h234// CHECK-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]]) #[[ATTR0]] {35// CHECK-NEXT: entry:36// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT2:%.*]], align 237// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 238// CHECK-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 239// CHECK-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 240// CHECK-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 241// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 242// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2]], ptr [[RETVAL]], i32 0, i32 043// CHECK-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 244// CHECK-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 245// CHECK-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2]], ptr [[RETVAL]], i32 0, i32 146// CHECK-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 247// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { bfloat, bfloat }, ptr [[RETVAL]], i32 0, i32 048// CHECK-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[TMP2]], align 249// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { bfloat, bfloat }, ptr [[RETVAL]], i32 0, i32 150// CHECK-NEXT: [[TMP5:%.*]] = load bfloat, ptr [[TMP4]], align 251// CHECK-NEXT: [[TMP6:%.*]] = insertvalue { bfloat, bfloat } poison, bfloat [[TMP3]], 052// CHECK-NEXT: [[TMP7:%.*]] = insertvalue { bfloat, bfloat } [[TMP6]], bfloat [[TMP5]], 153// CHECK-NEXT: ret { bfloat, bfloat } [[TMP7]]54//55struct bfloat2 h2(__bf16 a, __bf16 b) {56 struct bfloat2 x;57 x.a = a;58 x.b = b;59 return x;60}61 62struct bfloat3 {63 __bf16 a;64 __bf16 b;65 __bf16 c;66};67 68// CHECK-LA64-LABEL: define dso_local i64 @h369// CHECK-LA64-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]]) #[[ATTR0]] {70// CHECK-LA64-NEXT: entry:71// CHECK-LA64-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT3:%.*]], align 272// CHECK-LA64-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 273// CHECK-LA64-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 274// CHECK-LA64-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 275// CHECK-LA64-NEXT: [[RETVAL_COERCE:%.*]] = alloca i64, align 876// CHECK-LA64-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 277// CHECK-LA64-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 278// CHECK-LA64-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 279// CHECK-LA64-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 280// CHECK-LA64-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT3]], ptr [[RETVAL]], i32 0, i32 081// CHECK-LA64-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 282// CHECK-LA64-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 283// CHECK-LA64-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT3]], ptr [[RETVAL]], i32 0, i32 184// CHECK-LA64-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 285// CHECK-LA64-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 286// CHECK-LA64-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT3]], ptr [[RETVAL]], i32 0, i32 287// CHECK-LA64-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 288// CHECK-LA64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL_COERCE]], ptr align 2 [[RETVAL]], i64 6, i1 false)89// CHECK-LA64-NEXT: [[TMP3:%.*]] = load i64, ptr [[RETVAL_COERCE]], align 890// CHECK-LA64-NEXT: ret i64 [[TMP3]]91//92// CHECK-LA32-LABEL: define dso_local [2 x i32] @h393// CHECK-LA32-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]]) #[[ATTR0]] {94// CHECK-LA32-NEXT: entry:95// CHECK-LA32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT3:%.*]], align 296// CHECK-LA32-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 297// CHECK-LA32-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 298// CHECK-LA32-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 299// CHECK-LA32-NEXT: [[RETVAL_COERCE:%.*]] = alloca [2 x i32], align 4100// CHECK-LA32-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2101// CHECK-LA32-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2102// CHECK-LA32-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2103// CHECK-LA32-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2104// CHECK-LA32-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT3]], ptr [[RETVAL]], i32 0, i32 0105// CHECK-LA32-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 2106// CHECK-LA32-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2107// CHECK-LA32-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT3]], ptr [[RETVAL]], i32 0, i32 1108// CHECK-LA32-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2109// CHECK-LA32-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2110// CHECK-LA32-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT3]], ptr [[RETVAL]], i32 0, i32 2111// CHECK-LA32-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2112// CHECK-LA32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[RETVAL_COERCE]], ptr align 2 [[RETVAL]], i32 6, i1 false)113// CHECK-LA32-NEXT: [[TMP3:%.*]] = load [2 x i32], ptr [[RETVAL_COERCE]], align 4114// CHECK-LA32-NEXT: ret [2 x i32] [[TMP3]]115//116struct bfloat3 h3(__bf16 a, __bf16 b, __bf16 c) {117 struct bfloat3 x;118 x.a = a;119 x.b = b;120 x.c = c;121 return x;122}123 124struct bfloat4 {125 __bf16 a;126 __bf16 b;127 __bf16 c;128 __bf16 d;129};130 131// CHECK-LA64-LABEL: define dso_local i64 @h4132// CHECK-LA64-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]]) #[[ATTR0]] {133// CHECK-LA64-NEXT: entry:134// CHECK-LA64-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT4:%.*]], align 2135// CHECK-LA64-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2136// CHECK-LA64-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2137// CHECK-LA64-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2138// CHECK-LA64-NEXT: [[D_ADDR:%.*]] = alloca bfloat, align 2139// CHECK-LA64-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2140// CHECK-LA64-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2141// CHECK-LA64-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2142// CHECK-LA64-NEXT: store bfloat [[D]], ptr [[D_ADDR]], align 2143// CHECK-LA64-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2144// CHECK-LA64-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 0145// CHECK-LA64-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 2146// CHECK-LA64-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2147// CHECK-LA64-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 1148// CHECK-LA64-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2149// CHECK-LA64-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2150// CHECK-LA64-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 2151// CHECK-LA64-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2152// CHECK-LA64-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[D_ADDR]], align 2153// CHECK-LA64-NEXT: [[D4:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 3154// CHECK-LA64-NEXT: store bfloat [[TMP3]], ptr [[D4]], align 2155// CHECK-LA64-NEXT: [[TMP4:%.*]] = load i64, ptr [[RETVAL]], align 2156// CHECK-LA64-NEXT: ret i64 [[TMP4]]157//158// CHECK-LA32-LABEL: define dso_local [2 x i32] @h4159// CHECK-LA32-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]]) #[[ATTR0]] {160// CHECK-LA32-NEXT: entry:161// CHECK-LA32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT4:%.*]], align 2162// CHECK-LA32-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2163// CHECK-LA32-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2164// CHECK-LA32-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2165// CHECK-LA32-NEXT: [[D_ADDR:%.*]] = alloca bfloat, align 2166// CHECK-LA32-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2167// CHECK-LA32-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2168// CHECK-LA32-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2169// CHECK-LA32-NEXT: store bfloat [[D]], ptr [[D_ADDR]], align 2170// CHECK-LA32-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2171// CHECK-LA32-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 0172// CHECK-LA32-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 2173// CHECK-LA32-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2174// CHECK-LA32-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 1175// CHECK-LA32-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2176// CHECK-LA32-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2177// CHECK-LA32-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 2178// CHECK-LA32-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2179// CHECK-LA32-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[D_ADDR]], align 2180// CHECK-LA32-NEXT: [[D4:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT4]], ptr [[RETVAL]], i32 0, i32 3181// CHECK-LA32-NEXT: store bfloat [[TMP3]], ptr [[D4]], align 2182// CHECK-LA32-NEXT: [[TMP4:%.*]] = load [2 x i32], ptr [[RETVAL]], align 2183// CHECK-LA32-NEXT: ret [2 x i32] [[TMP4]]184//185struct bfloat4 h4(__bf16 a, __bf16 b, __bf16 c, __bf16 d) {186 struct bfloat4 x;187 x.a = a;188 x.b = b;189 x.c = c;190 x.d = d;191 return x;192}193 194struct floatbfloat {195 float a;196 __bf16 b;197};198 199// CHECK-LABEL: define dso_local { float, bfloat } @fh200// CHECK-SAME: (float noundef [[A:%.*]], bfloat noundef [[B:%.*]]) #[[ATTR0]] {201// CHECK-NEXT: entry:202// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOATBFLOAT:%.*]], align 4203// CHECK-NEXT: [[A_ADDR:%.*]] = alloca float, align 4204// CHECK-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2205// CHECK-NEXT: store float [[A]], ptr [[A_ADDR]], align 4206// CHECK-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2207// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4208// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT]], ptr [[RETVAL]], i32 0, i32 0209// CHECK-NEXT: store float [[TMP0]], ptr [[A1]], align 4210// CHECK-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2211// CHECK-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT]], ptr [[RETVAL]], i32 0, i32 1212// CHECK-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 4213// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { float, bfloat }, ptr [[RETVAL]], i32 0, i32 0214// CHECK-NEXT: [[TMP3:%.*]] = load float, ptr [[TMP2]], align 4215// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { float, bfloat }, ptr [[RETVAL]], i32 0, i32 1216// CHECK-NEXT: [[TMP5:%.*]] = load bfloat, ptr [[TMP4]], align 4217// CHECK-NEXT: [[TMP6:%.*]] = insertvalue { float, bfloat } poison, float [[TMP3]], 0218// CHECK-NEXT: [[TMP7:%.*]] = insertvalue { float, bfloat } [[TMP6]], bfloat [[TMP5]], 1219// CHECK-NEXT: ret { float, bfloat } [[TMP7]]220//221struct floatbfloat fh(float a, __bf16 b) {222 struct floatbfloat x;223 x.a = a;224 x.b = b;225 return x;226}227 228struct floatbfloat2 {229 float a;230 __bf16 b;231 __bf16 c;232};233 234// CHECK-LA64-LABEL: define dso_local i64 @fh2235// CHECK-LA64-SAME: (float noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]]) #[[ATTR0]] {236// CHECK-LA64-NEXT: entry:237// CHECK-LA64-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOATBFLOAT2:%.*]], align 4238// CHECK-LA64-NEXT: [[A_ADDR:%.*]] = alloca float, align 4239// CHECK-LA64-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2240// CHECK-LA64-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2241// CHECK-LA64-NEXT: store float [[A]], ptr [[A_ADDR]], align 4242// CHECK-LA64-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2243// CHECK-LA64-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2244// CHECK-LA64-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4245// CHECK-LA64-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT2]], ptr [[RETVAL]], i32 0, i32 0246// CHECK-LA64-NEXT: store float [[TMP0]], ptr [[A1]], align 4247// CHECK-LA64-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2248// CHECK-LA64-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT2]], ptr [[RETVAL]], i32 0, i32 1249// CHECK-LA64-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 4250// CHECK-LA64-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2251// CHECK-LA64-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT2]], ptr [[RETVAL]], i32 0, i32 2252// CHECK-LA64-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2253// CHECK-LA64-NEXT: [[TMP3:%.*]] = load i64, ptr [[RETVAL]], align 4254// CHECK-LA64-NEXT: ret i64 [[TMP3]]255//256// CHECK-LA32-LABEL: define dso_local [2 x i32] @fh2257// CHECK-LA32-SAME: (float noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]]) #[[ATTR0]] {258// CHECK-LA32-NEXT: entry:259// CHECK-LA32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOATBFLOAT2:%.*]], align 4260// CHECK-LA32-NEXT: [[A_ADDR:%.*]] = alloca float, align 4261// CHECK-LA32-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2262// CHECK-LA32-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2263// CHECK-LA32-NEXT: store float [[A]], ptr [[A_ADDR]], align 4264// CHECK-LA32-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2265// CHECK-LA32-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2266// CHECK-LA32-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4267// CHECK-LA32-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT2]], ptr [[RETVAL]], i32 0, i32 0268// CHECK-LA32-NEXT: store float [[TMP0]], ptr [[A1]], align 4269// CHECK-LA32-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2270// CHECK-LA32-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT2]], ptr [[RETVAL]], i32 0, i32 1271// CHECK-LA32-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 4272// CHECK-LA32-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2273// CHECK-LA32-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT2]], ptr [[RETVAL]], i32 0, i32 2274// CHECK-LA32-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2275// CHECK-LA32-NEXT: [[TMP3:%.*]] = load [2 x i32], ptr [[RETVAL]], align 4276// CHECK-LA32-NEXT: ret [2 x i32] [[TMP3]]277//278struct floatbfloat2 fh2(float a, __bf16 b, __bf16 c) {279 struct floatbfloat2 x;280 x.a = a;281 x.b = b;282 x.c = c;283 return x;284}285 286struct bfloatfloat {287 __bf16 a;288 float b;289};290 291// CHECK-LABEL: define dso_local { bfloat, float } @hf292// CHECK-SAME: (bfloat noundef [[A:%.*]], float noundef [[B:%.*]]) #[[ATTR0]] {293// CHECK-NEXT: entry:294// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOATFLOAT:%.*]], align 4295// CHECK-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2296// CHECK-NEXT: [[B_ADDR:%.*]] = alloca float, align 4297// CHECK-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2298// CHECK-NEXT: store float [[B]], ptr [[B_ADDR]], align 4299// CHECK-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2300// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOATFLOAT]], ptr [[RETVAL]], i32 0, i32 0301// CHECK-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 4302// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[B_ADDR]], align 4303// CHECK-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOATFLOAT]], ptr [[RETVAL]], i32 0, i32 1304// CHECK-NEXT: store float [[TMP1]], ptr [[B2]], align 4305// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw { bfloat, float }, ptr [[RETVAL]], i32 0, i32 0306// CHECK-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[TMP2]], align 4307// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw { bfloat, float }, ptr [[RETVAL]], i32 0, i32 1308// CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[TMP4]], align 4309// CHECK-NEXT: [[TMP6:%.*]] = insertvalue { bfloat, float } poison, bfloat [[TMP3]], 0310// CHECK-NEXT: [[TMP7:%.*]] = insertvalue { bfloat, float } [[TMP6]], float [[TMP5]], 1311// CHECK-NEXT: ret { bfloat, float } [[TMP7]]312//313struct bfloatfloat hf(__bf16 a, float b) {314 struct bfloatfloat x;315 x.a = a;316 x.b = b;317 return x;318}319 320struct bfloat2float {321 __bf16 a;322 __bf16 b;323 float c;324};325 326// CHECK-LA64-LABEL: define dso_local i64 @h2f327// CHECK-LA64-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], float noundef [[C:%.*]]) #[[ATTR0]] {328// CHECK-LA64-NEXT: entry:329// CHECK-LA64-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT2FLOAT:%.*]], align 4330// CHECK-LA64-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2331// CHECK-LA64-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2332// CHECK-LA64-NEXT: [[C_ADDR:%.*]] = alloca float, align 4333// CHECK-LA64-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2334// CHECK-LA64-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2335// CHECK-LA64-NEXT: store float [[C]], ptr [[C_ADDR]], align 4336// CHECK-LA64-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2337// CHECK-LA64-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2FLOAT]], ptr [[RETVAL]], i32 0, i32 0338// CHECK-LA64-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 4339// CHECK-LA64-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2340// CHECK-LA64-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2FLOAT]], ptr [[RETVAL]], i32 0, i32 1341// CHECK-LA64-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2342// CHECK-LA64-NEXT: [[TMP2:%.*]] = load float, ptr [[C_ADDR]], align 4343// CHECK-LA64-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2FLOAT]], ptr [[RETVAL]], i32 0, i32 2344// CHECK-LA64-NEXT: store float [[TMP2]], ptr [[C3]], align 4345// CHECK-LA64-NEXT: [[TMP3:%.*]] = load i64, ptr [[RETVAL]], align 4346// CHECK-LA64-NEXT: ret i64 [[TMP3]]347//348// CHECK-LA32-LABEL: define dso_local [2 x i32] @h2f349// CHECK-LA32-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], float noundef [[C:%.*]]) #[[ATTR0]] {350// CHECK-LA32-NEXT: entry:351// CHECK-LA32-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT2FLOAT:%.*]], align 4352// CHECK-LA32-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2353// CHECK-LA32-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2354// CHECK-LA32-NEXT: [[C_ADDR:%.*]] = alloca float, align 4355// CHECK-LA32-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2356// CHECK-LA32-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2357// CHECK-LA32-NEXT: store float [[C]], ptr [[C_ADDR]], align 4358// CHECK-LA32-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2359// CHECK-LA32-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2FLOAT]], ptr [[RETVAL]], i32 0, i32 0360// CHECK-LA32-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 4361// CHECK-LA32-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2362// CHECK-LA32-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2FLOAT]], ptr [[RETVAL]], i32 0, i32 1363// CHECK-LA32-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2364// CHECK-LA32-NEXT: [[TMP2:%.*]] = load float, ptr [[C_ADDR]], align 4365// CHECK-LA32-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT2FLOAT]], ptr [[RETVAL]], i32 0, i32 2366// CHECK-LA32-NEXT: store float [[TMP2]], ptr [[C3]], align 4367// CHECK-LA32-NEXT: [[TMP3:%.*]] = load [2 x i32], ptr [[RETVAL]], align 4368// CHECK-LA32-NEXT: ret [2 x i32] [[TMP3]]369//370struct bfloat2float h2f(__bf16 a, __bf16 b, float c) {371 struct bfloat2float x;372 x.a = a;373 x.b = b;374 x.c = c;375 return x;376}377 378struct floatbfloat3 {379 float a;380 __bf16 b;381 __bf16 c;382 __bf16 d;383};384 385// CHECK-LA64-LABEL: define dso_local [2 x i64] @fh3386// CHECK-LA64-SAME: (float noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]]) #[[ATTR0]] {387// CHECK-LA64-NEXT: entry:388// CHECK-LA64-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_FLOATBFLOAT3:%.*]], align 4389// CHECK-LA64-NEXT: [[A_ADDR:%.*]] = alloca float, align 4390// CHECK-LA64-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2391// CHECK-LA64-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2392// CHECK-LA64-NEXT: [[D_ADDR:%.*]] = alloca bfloat, align 2393// CHECK-LA64-NEXT: [[RETVAL_COERCE:%.*]] = alloca [2 x i64], align 8394// CHECK-LA64-NEXT: store float [[A]], ptr [[A_ADDR]], align 4395// CHECK-LA64-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2396// CHECK-LA64-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2397// CHECK-LA64-NEXT: store bfloat [[D]], ptr [[D_ADDR]], align 2398// CHECK-LA64-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4399// CHECK-LA64-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[RETVAL]], i32 0, i32 0400// CHECK-LA64-NEXT: store float [[TMP0]], ptr [[A1]], align 4401// CHECK-LA64-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2402// CHECK-LA64-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[RETVAL]], i32 0, i32 1403// CHECK-LA64-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 4404// CHECK-LA64-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2405// CHECK-LA64-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[RETVAL]], i32 0, i32 2406// CHECK-LA64-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2407// CHECK-LA64-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[D_ADDR]], align 2408// CHECK-LA64-NEXT: [[D4:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[RETVAL]], i32 0, i32 3409// CHECK-LA64-NEXT: store bfloat [[TMP3]], ptr [[D4]], align 4410// CHECK-LA64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL_COERCE]], ptr align 4 [[RETVAL]], i64 12, i1 false)411// CHECK-LA64-NEXT: [[TMP4:%.*]] = load [2 x i64], ptr [[RETVAL_COERCE]], align 8412// CHECK-LA64-NEXT: ret [2 x i64] [[TMP4]]413//414// CHECK-LA32-LABEL: define dso_local void @fh3415// CHECK-LA32-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_FLOATBFLOAT3:%.*]]) align 4 [[AGG_RESULT:%.*]], float noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]]) #[[ATTR0]] {416// CHECK-LA32-NEXT: entry:417// CHECK-LA32-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4418// CHECK-LA32-NEXT: [[A_ADDR:%.*]] = alloca float, align 4419// CHECK-LA32-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2420// CHECK-LA32-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2421// CHECK-LA32-NEXT: [[D_ADDR:%.*]] = alloca bfloat, align 2422// CHECK-LA32-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 4423// CHECK-LA32-NEXT: store float [[A]], ptr [[A_ADDR]], align 4424// CHECK-LA32-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2425// CHECK-LA32-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2426// CHECK-LA32-NEXT: store bfloat [[D]], ptr [[D_ADDR]], align 2427// CHECK-LA32-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4428// CHECK-LA32-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[AGG_RESULT]], i32 0, i32 0429// CHECK-LA32-NEXT: store float [[TMP0]], ptr [[A1]], align 4430// CHECK-LA32-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2431// CHECK-LA32-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[AGG_RESULT]], i32 0, i32 1432// CHECK-LA32-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 4433// CHECK-LA32-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2434// CHECK-LA32-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[AGG_RESULT]], i32 0, i32 2435// CHECK-LA32-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2436// CHECK-LA32-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[D_ADDR]], align 2437// CHECK-LA32-NEXT: [[D4:%.*]] = getelementptr inbounds nuw [[STRUCT_FLOATBFLOAT3]], ptr [[AGG_RESULT]], i32 0, i32 3438// CHECK-LA32-NEXT: store bfloat [[TMP3]], ptr [[D4]], align 4439// CHECK-LA32-NEXT: ret void440//441struct floatbfloat3 fh3(float a, __bf16 b, __bf16 c, __bf16 d) {442 struct floatbfloat3 x;443 x.a = a;444 x.b = b;445 x.c = c;446 x.d = d;447 return x;448}449 450struct bfloat5 {451 __bf16 a;452 __bf16 b;453 __bf16 c;454 __bf16 d;455 __bf16 e;456};457 458// CHECK-LA64-LABEL: define dso_local [2 x i64] @h5459// CHECK-LA64-SAME: (bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]], bfloat noundef [[E:%.*]]) #[[ATTR0]] {460// CHECK-LA64-NEXT: entry:461// CHECK-LA64-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_BFLOAT5:%.*]], align 2462// CHECK-LA64-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2463// CHECK-LA64-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2464// CHECK-LA64-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2465// CHECK-LA64-NEXT: [[D_ADDR:%.*]] = alloca bfloat, align 2466// CHECK-LA64-NEXT: [[E_ADDR:%.*]] = alloca bfloat, align 2467// CHECK-LA64-NEXT: [[RETVAL_COERCE:%.*]] = alloca [2 x i64], align 8468// CHECK-LA64-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2469// CHECK-LA64-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2470// CHECK-LA64-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2471// CHECK-LA64-NEXT: store bfloat [[D]], ptr [[D_ADDR]], align 2472// CHECK-LA64-NEXT: store bfloat [[E]], ptr [[E_ADDR]], align 2473// CHECK-LA64-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2474// CHECK-LA64-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[RETVAL]], i32 0, i32 0475// CHECK-LA64-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 2476// CHECK-LA64-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2477// CHECK-LA64-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[RETVAL]], i32 0, i32 1478// CHECK-LA64-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2479// CHECK-LA64-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2480// CHECK-LA64-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[RETVAL]], i32 0, i32 2481// CHECK-LA64-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2482// CHECK-LA64-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[D_ADDR]], align 2483// CHECK-LA64-NEXT: [[D4:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[RETVAL]], i32 0, i32 3484// CHECK-LA64-NEXT: store bfloat [[TMP3]], ptr [[D4]], align 2485// CHECK-LA64-NEXT: [[TMP4:%.*]] = load bfloat, ptr [[E_ADDR]], align 2486// CHECK-LA64-NEXT: [[E5:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[RETVAL]], i32 0, i32 4487// CHECK-LA64-NEXT: store bfloat [[TMP4]], ptr [[E5]], align 2488// CHECK-LA64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL_COERCE]], ptr align 2 [[RETVAL]], i64 10, i1 false)489// CHECK-LA64-NEXT: [[TMP5:%.*]] = load [2 x i64], ptr [[RETVAL_COERCE]], align 8490// CHECK-LA64-NEXT: ret [2 x i64] [[TMP5]]491//492// CHECK-LA32-LABEL: define dso_local void @h5493// CHECK-LA32-SAME: (ptr dead_on_unwind noalias writable sret([[STRUCT_BFLOAT5:%.*]]) align 2 [[AGG_RESULT:%.*]], bfloat noundef [[A:%.*]], bfloat noundef [[B:%.*]], bfloat noundef [[C:%.*]], bfloat noundef [[D:%.*]], bfloat noundef [[E:%.*]]) #[[ATTR0]] {494// CHECK-LA32-NEXT: entry:495// CHECK-LA32-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4496// CHECK-LA32-NEXT: [[A_ADDR:%.*]] = alloca bfloat, align 2497// CHECK-LA32-NEXT: [[B_ADDR:%.*]] = alloca bfloat, align 2498// CHECK-LA32-NEXT: [[C_ADDR:%.*]] = alloca bfloat, align 2499// CHECK-LA32-NEXT: [[D_ADDR:%.*]] = alloca bfloat, align 2500// CHECK-LA32-NEXT: [[E_ADDR:%.*]] = alloca bfloat, align 2501// CHECK-LA32-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 4502// CHECK-LA32-NEXT: store bfloat [[A]], ptr [[A_ADDR]], align 2503// CHECK-LA32-NEXT: store bfloat [[B]], ptr [[B_ADDR]], align 2504// CHECK-LA32-NEXT: store bfloat [[C]], ptr [[C_ADDR]], align 2505// CHECK-LA32-NEXT: store bfloat [[D]], ptr [[D_ADDR]], align 2506// CHECK-LA32-NEXT: store bfloat [[E]], ptr [[E_ADDR]], align 2507// CHECK-LA32-NEXT: [[TMP0:%.*]] = load bfloat, ptr [[A_ADDR]], align 2508// CHECK-LA32-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[AGG_RESULT]], i32 0, i32 0509// CHECK-LA32-NEXT: store bfloat [[TMP0]], ptr [[A1]], align 2510// CHECK-LA32-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[B_ADDR]], align 2511// CHECK-LA32-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[AGG_RESULT]], i32 0, i32 1512// CHECK-LA32-NEXT: store bfloat [[TMP1]], ptr [[B2]], align 2513// CHECK-LA32-NEXT: [[TMP2:%.*]] = load bfloat, ptr [[C_ADDR]], align 2514// CHECK-LA32-NEXT: [[C3:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[AGG_RESULT]], i32 0, i32 2515// CHECK-LA32-NEXT: store bfloat [[TMP2]], ptr [[C3]], align 2516// CHECK-LA32-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[D_ADDR]], align 2517// CHECK-LA32-NEXT: [[D4:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[AGG_RESULT]], i32 0, i32 3518// CHECK-LA32-NEXT: store bfloat [[TMP3]], ptr [[D4]], align 2519// CHECK-LA32-NEXT: [[TMP4:%.*]] = load bfloat, ptr [[E_ADDR]], align 2520// CHECK-LA32-NEXT: [[E5:%.*]] = getelementptr inbounds nuw [[STRUCT_BFLOAT5]], ptr [[AGG_RESULT]], i32 0, i32 4521// CHECK-LA32-NEXT: store bfloat [[TMP4]], ptr [[E5]], align 2522// CHECK-LA32-NEXT: ret void523//524struct bfloat5 h5(__bf16 a, __bf16 b, __bf16 c, __bf16 d, __bf16 e) {525 struct bfloat5 x;526 x.a = a;527 x.b = b;528 x.c = c;529 x.d = d;530 x.e = e;531 return x;532}533