1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE 2*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -mattr=-sse | FileCheck %s -check-prefix=CHECK -check-prefix=NOSSE 3*9880d681SAndroid Build Coastguard Worker; 4*9880d681SAndroid Build Coastguard Worker; Verifies that x32 va_start lowering is sane. To regenerate this test, use 5*9880d681SAndroid Build Coastguard Worker; cat <<EOF | 6*9880d681SAndroid Build Coastguard Worker; #include <stdarg.h> 7*9880d681SAndroid Build Coastguard Worker; 8*9880d681SAndroid Build Coastguard Worker; int foo(float a, const char* fmt, ...) { 9*9880d681SAndroid Build Coastguard Worker; va_list ap; 10*9880d681SAndroid Build Coastguard Worker; va_start(ap, fmt); 11*9880d681SAndroid Build Coastguard Worker; int value = va_arg(ap, int); 12*9880d681SAndroid Build Coastguard Worker; va_end(ap); 13*9880d681SAndroid Build Coastguard Worker; return value; 14*9880d681SAndroid Build Coastguard Worker; } 15*9880d681SAndroid Build Coastguard Worker; EOF 16*9880d681SAndroid Build Coastguard Worker; build/bin/clang -mx32 -O3 -o- -S -emit-llvm -xc - 17*9880d681SAndroid Build Coastguard Worker; 18*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128" 19*9880d681SAndroid Build Coastguard Workertarget triple = "x86_64-unknown-linux-gnux32" 20*9880d681SAndroid Build Coastguard Worker 21*9880d681SAndroid Build Coastguard Worker%struct.__va_list_tag = type { i32, i32, i8*, i8* } 22*9880d681SAndroid Build Coastguard Worker 23*9880d681SAndroid Build Coastguard Workerdefine i32 @foo(float %a, i8* nocapture readnone %fmt, ...) nounwind { 24*9880d681SAndroid Build Coastguard Workerentry: 25*9880d681SAndroid Build Coastguard Worker %ap = alloca [1 x %struct.__va_list_tag], align 16 26*9880d681SAndroid Build Coastguard Worker %0 = bitcast [1 x %struct.__va_list_tag]* %ap to i8* 27*9880d681SAndroid Build Coastguard Worker call void @llvm.lifetime.start(i64 16, i8* %0) #2 28*9880d681SAndroid Build Coastguard Worker call void @llvm.va_start(i8* %0) 29*9880d681SAndroid Build Coastguard Worker; SSE: subl $72, %esp 30*9880d681SAndroid Build Coastguard Worker; SSE: testb %al, %al 31*9880d681SAndroid Build Coastguard Worker; SSE: je .[[NOFP:.*]] 32*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm1 33*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm2 34*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm3 35*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm4 36*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm5 37*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm6 38*9880d681SAndroid Build Coastguard Worker; SSE-DAG: movaps %xmm7 39*9880d681SAndroid Build Coastguard Worker; NOSSE-NOT: xmm 40*9880d681SAndroid Build Coastguard Worker; SSE: .[[NOFP]]: 41*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movq %r9 42*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movq %r8 43*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movq %rcx 44*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movq %rdx 45*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movq %rsi 46*9880d681SAndroid Build Coastguard Worker %gp_offset_p = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0, i32 0 47*9880d681SAndroid Build Coastguard Worker %gp_offset = load i32, i32* %gp_offset_p, align 16 48*9880d681SAndroid Build Coastguard Worker %fits_in_gp = icmp ult i32 %gp_offset, 41 49*9880d681SAndroid Build Coastguard Worker br i1 %fits_in_gp, label %vaarg.in_reg, label %vaarg.in_mem 50*9880d681SAndroid Build Coastguard Worker; CHECK: cmpl $40, [[COUNT:.*]] 51*9880d681SAndroid Build Coastguard Worker; CHECK: ja .[[IN_MEM:.*]] 52*9880d681SAndroid Build Coastguard Worker 53*9880d681SAndroid Build Coastguard Workervaarg.in_reg: ; preds = %entry 54*9880d681SAndroid Build Coastguard Worker %1 = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0, i32 3 55*9880d681SAndroid Build Coastguard Worker %reg_save_area = load i8*, i8** %1, align 4 56*9880d681SAndroid Build Coastguard Worker %2 = getelementptr i8, i8* %reg_save_area, i32 %gp_offset 57*9880d681SAndroid Build Coastguard Worker %3 = add i32 %gp_offset, 8 58*9880d681SAndroid Build Coastguard Worker store i32 %3, i32* %gp_offset_p, align 16 59*9880d681SAndroid Build Coastguard Worker br label %vaarg.end 60*9880d681SAndroid Build Coastguard Worker; CHECK: movl {{[^,]*}}, [[ADDR:.*]] 61*9880d681SAndroid Build Coastguard Worker; CHECK: addl [[COUNT]], [[ADDR]] 62*9880d681SAndroid Build Coastguard Worker; SSE: jmp .[[END:.*]] 63*9880d681SAndroid Build Coastguard Worker; NOSSE: movl ([[ADDR]]), %eax 64*9880d681SAndroid Build Coastguard Worker; NOSSE: retq 65*9880d681SAndroid Build Coastguard Worker; CHECK: .[[IN_MEM]]: 66*9880d681SAndroid Build Coastguard Workervaarg.in_mem: ; preds = %entry 67*9880d681SAndroid Build Coastguard Worker %overflow_arg_area_p = getelementptr inbounds [1 x %struct.__va_list_tag], [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0, i32 2 68*9880d681SAndroid Build Coastguard Worker %overflow_arg_area = load i8*, i8** %overflow_arg_area_p, align 8 69*9880d681SAndroid Build Coastguard Worker %overflow_arg_area.next = getelementptr i8, i8* %overflow_arg_area, i32 8 70*9880d681SAndroid Build Coastguard Worker store i8* %overflow_arg_area.next, i8** %overflow_arg_area_p, align 8 71*9880d681SAndroid Build Coastguard Worker br label %vaarg.end 72*9880d681SAndroid Build Coastguard Worker; CHECK: movl {{[^,]*}}, [[ADDR]] 73*9880d681SAndroid Build Coastguard Worker; NOSSE: movl ([[ADDR]]), %eax 74*9880d681SAndroid Build Coastguard Worker; NOSSE: retq 75*9880d681SAndroid Build Coastguard Worker; SSE: .[[END]]: 76*9880d681SAndroid Build Coastguard Worker 77*9880d681SAndroid Build Coastguard Workervaarg.end: ; preds = %vaarg.in_mem, %vaarg.in_reg 78*9880d681SAndroid Build Coastguard Worker %vaarg.addr.in = phi i8* [ %2, %vaarg.in_reg ], [ %overflow_arg_area, %vaarg.in_mem ] 79*9880d681SAndroid Build Coastguard Worker %vaarg.addr = bitcast i8* %vaarg.addr.in to i32* 80*9880d681SAndroid Build Coastguard Worker %4 = load i32, i32* %vaarg.addr, align 4 81*9880d681SAndroid Build Coastguard Worker call void @llvm.va_end(i8* %0) 82*9880d681SAndroid Build Coastguard Worker call void @llvm.lifetime.end(i64 16, i8* %0) #2 83*9880d681SAndroid Build Coastguard Worker ret i32 %4 84*9880d681SAndroid Build Coastguard Worker; SSE: movl ([[ADDR]]), %eax 85*9880d681SAndroid Build Coastguard Worker; SSE: retq 86*9880d681SAndroid Build Coastguard Worker} 87*9880d681SAndroid Build Coastguard Worker 88*9880d681SAndroid Build Coastguard Worker; Function Attrs: nounwind argmemonly 89*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.start(i64, i8* nocapture) nounwind 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker; Function Attrs: nounwind 92*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.va_start(i8*) nounwind 93*9880d681SAndroid Build Coastguard Worker 94*9880d681SAndroid Build Coastguard Worker; Function Attrs: nounwind 95*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.va_end(i8*) nounwind 96*9880d681SAndroid Build Coastguard Worker 97*9880d681SAndroid Build Coastguard Worker; Function Attrs: nounwind argmemonly 98*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.lifetime.end(i64, i8* nocapture) nounwind 99*9880d681SAndroid Build Coastguard Worker 100