1; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s 2 3%struct.__va_list_tag = type { i32, i32, i8*, i8* } 4 5declare void @llvm.va_end(i8*) #0 6declare void @llvm.va_start(i8*) #10 7 8define void @hardf(i8* %fmt, ...) #1 { 9; CHECK-LABEL: hardf 10; When using XMM registers to pass floating-point parameters, 11; we need to spill those for va_start. 12; CHECK: testb %al, %al 13; CHECK: movaps %xmm0, {{.*}}%rsp 14; CHECK: movaps %xmm1, {{.*}}%rsp 15; CHECK: movaps %xmm2, {{.*}}%rsp 16; CHECK: movaps %xmm3, {{.*}}%rsp 17; CHECK: movaps %xmm4, {{.*}}%rsp 18; CHECK: movaps %xmm5, {{.*}}%rsp 19; CHECK: movaps %xmm6, {{.*}}%rsp 20; CHECK: movaps %xmm7, {{.*}}%rsp 21 %va = alloca [1 x %struct.__va_list_tag], align 16 22 %arraydecay = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %va, i64 0, i64 0 23 %a = bitcast %struct.__va_list_tag* %arraydecay to i8* 24 call void @llvm.va_start(i8* %a) 25 call void @llvm.va_end(i8* nonnull %a) 26 ret void 27} 28 29define void @softf(i8* %fmt, ...) #2 { 30; CHECK-LABEL: softf 31; For software floating point, floats are passed in general 32; purpose registers, so no need to spill XMM registers. 33; CHECK-NOT: %xmm 34; CHECK: retq 35 %va = alloca [1 x %struct.__va_list_tag], align 16 36 %arraydecay = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %va, i64 0, i64 0 37 %a = bitcast %struct.__va_list_tag* %arraydecay to i8* 38 call void @llvm.va_start(i8* %a) 39 call void @llvm.va_end(i8* nonnull %a) 40 ret void 41} 42 43define void @noimplf(i8* %fmt, ...) #3 { 44; CHECK-LABEL: noimplf 45; Even with noimplicitfloat, when using the hardware float API, we 46; need to emit code to spill the XMM registers (PR36507). 47; CHECK: testb %al, %al 48; CHECK: movaps %xmm0, {{.*}}%rsp 49; CHECK: movaps %xmm1, {{.*}}%rsp 50; CHECK: movaps %xmm2, {{.*}}%rsp 51; CHECK: movaps %xmm3, {{.*}}%rsp 52; CHECK: movaps %xmm4, {{.*}}%rsp 53; CHECK: movaps %xmm5, {{.*}}%rsp 54; CHECK: movaps %xmm6, {{.*}}%rsp 55; CHECK: movaps %xmm7, {{.*}}%rsp 56 %va = alloca [1 x %struct.__va_list_tag], align 16 57 %arraydecay = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %va, i64 0, i64 0 58 %a = bitcast %struct.__va_list_tag* %arraydecay to i8* 59 call void @llvm.va_start(i8* %a) 60 call void @llvm.va_end(i8* nonnull %a) 61 ret void 62} 63 64define void @noimplsoftf(i8* %fmt, ...) #4 { 65; CHECK-LABEL: noimplsoftf 66; Combining noimplicitfloat and use-soft-float should not assert (PR48528). 67; CHECK-NOT: %xmm 68; CHECK: retq 69 %va = alloca [1 x %struct.__va_list_tag], align 16 70 %arraydecay = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %va, i64 0, i64 0 71 %a = bitcast %struct.__va_list_tag* %arraydecay to i8* 72 call void @llvm.va_start(i8* %a) 73 call void @llvm.va_end(i8* nonnull %a) 74 ret void 75} 76 77attributes #0 = { nounwind } 78attributes #1 = { nounwind uwtable } 79attributes #2 = { nounwind uwtable "use-soft-float"="true" } 80attributes #3 = { noimplicitfloat nounwind uwtable } 81attributes #4 = { noimplicitfloat nounwind uwtable "use-soft-float"="true" } 82