diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index 5d806fe60b86..d770cb0abc16 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -586,8 +586,8 @@ def CC_X86_Win64_C : CallingConv<[ // FIXME: Handle byval stuff. // FIXME: Handle varargs. - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, + // Promote i1/v1i1 arguments to i8. + CCIfType<[i1, v1i1], CCPromoteToType>, // The 'nest' parameter, if any, is passed in R10. CCIfNest>, @@ -609,6 +609,10 @@ def CC_X86_Win64_C : CallingConv<[ CCIfType<[x86mmx], CCBitConvertToType>, // The first 4 integer arguments are passed in integer registers. + CCIfType<[i8 ], CCAssignToRegWithShadow<[CL , DL , R8B , R9B ], + [XMM0, XMM1, XMM2, XMM3]>>, + CCIfType<[i16], CCAssignToRegWithShadow<[CX , DX , R8W , R9W ], + [XMM0, XMM1, XMM2, XMM3]>>, CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ], [XMM0, XMM1, XMM2, XMM3]>>, @@ -628,7 +632,7 @@ def CC_X86_Win64_C : CallingConv<[ // Integer/FP values get stored in stack slots that are 8 bytes in size and // 8-byte aligned if there are no more registers to hold them. - CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>, + CCIfType<[i8, i16, i32, i64, f32, f64], CCAssignToStack<8, 8>>, // Long doubles get stack slots whose size and alignment depends on the // subtarget. @@ -841,13 +845,15 @@ def CC_X86_32_MCU : CallingConv<[ ]>; def CC_X86_32_FastCall : CallingConv<[ - // Promote i1/i8/i16/v1i1 arguments to i32. - CCIfType<[i1, i8, i16, v1i1], CCPromoteToType>, + // Promote i1 to i8. + CCIfType<[i1], CCPromoteToType>, // The 'nest' parameter, if any, is passed in EAX. CCIfNest>, // The first 2 integer arguments are passed in ECX/EDX + CCIfInReg>>, + CCIfInReg>>, CCIfInReg>>, // Otherwise, same as everything else. diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 10e19f92b4a6..1384059b5ed6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2993,7 +2993,11 @@ SDValue X86TargetLowering::LowerFormalArguments( getv64i1Argument(VA, ArgLocs[++I], Chain, DAG, dl, Subtarget); } else { const TargetRegisterClass *RC; - if (RegVT == MVT::i32) + if (RegVT == MVT::i8) + RC = &X86::GR8RegClass; + else if (RegVT == MVT::i16) + RC = &X86::GR16RegClass; + else if (RegVT == MVT::i32) RC = &X86::GR32RegClass; else if (Is64Bit && RegVT == MVT::i64) RC = &X86::GR64RegClass; diff --git a/test/CodeGen/X86/win-smallparams.ll b/test/CodeGen/X86/win-smallparams.ll new file mode 100644 index 000000000000..93b528ac3106 --- /dev/null +++ b/test/CodeGen/X86/win-smallparams.ll @@ -0,0 +1,67 @@ +; When we accept small parameters on Windows, make sure we do not assume they +; are zero or sign extended in memory or in registers. + +; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=WIN64 +; RUN: llc < %s -mtriple=x86_64-windows-gnu | FileCheck %s --check-prefix=WIN64 +; RUN: llc < %s -mtriple=i686-windows-msvc | FileCheck %s --check-prefix=WIN32 +; RUN: llc < %s -mtriple=i686-windows-gnu | FileCheck %s --check-prefix=WIN32 + +define void @call() { +entry: + %rv = call i32 @manyargs(i8 1, i16 2, i8 3, i16 4, i8 5, i16 6) + ret void +} + +define i32 @manyargs(i8 %a, i16 %b, i8 %c, i16 %d, i8 %e, i16 %f) { +entry: + %aa = sext i8 %a to i32 + %bb = sext i16 %b to i32 + %cc = zext i8 %c to i32 + %dd = zext i16 %d to i32 + %ee = zext i8 %e to i32 + %ff = zext i16 %f to i32 + %t0 = add i32 %aa, %bb + %t1 = add i32 %t0, %cc + %t2 = add i32 %t1, %dd + %t3 = add i32 %t2, %ee + %t4 = add i32 %t3, %ff + ret i32 %t4 +} + +; WIN64-LABEL: call: +; WIN64-DAG: movw $6, 40(%rsp) +; WIN64-DAG: movb $5, 32(%rsp) +; WIN64-DAG: movb $1, %cl +; WIN64-DAG: movw $2, %dx +; WIN64-DAG: movb $3, %r8b +; WIN64-DAG: movw $4, %r9w +; WIN64: callq manyargs + +; WIN64-LABEL: manyargs: +; WIN64-DAG: movsbl %cl, +; WIN64-DAG: movswl %dx, +; WIN64-DAG: movzbl %r8b, +; WIN64-DAG: movzwl %r9w, +; WIN64-DAG: movzbl 40(%rsp), +; WIN64-DAG: movzwl 48(%rsp), +; WIN64: retq + + +; WIN32-LABEL: _call: +; WIN32: pushl $6 +; WIN32: pushl $5 +; WIN32: pushl $4 +; WIN32: pushl $3 +; WIN32: pushl $2 +; WIN32: pushl $1 +; WIN32: calll _manyargs + +; WIN32-LABEL: _manyargs: +; WIN32-DAG: movsbl 4(%esp), +; WIN32-DAG: movswl 8(%esp), +; WIN32-DAG: movzbl 12(%esp), +; WIN32-DAG: movzwl 16(%esp), +; WIN32-DAG: movzbl 20(%esp), +; WIN32-DAG: movzwl 24(%esp), +; WIN32: retl + diff --git a/test/CodeGen/X86/win32-bool.ll b/test/CodeGen/X86/win32-bool.ll new file mode 100644 index 000000000000..53607ea06c73 --- /dev/null +++ b/test/CodeGen/X86/win32-bool.ll @@ -0,0 +1,33 @@ +; RUN: llc < %s -mtriple=i686-windows-msvc | FileCheck %s +; RUN: llc < %s -mtriple=i686-windows-gnu | FileCheck %s + +define x86_fastcallcc i32 @pass_fast_bool(i1 inreg zeroext %b) { +entry: + %cond = select i1 %b, i32 66, i32 0 + ret i32 %cond +} + +; CHECK-LABEL: @pass_fast_bool@4: +; CHECK-DAG: testb %cl, %cl +; CHECK-DAG: movl $66, +; CHECK: retl + +define x86_vectorcallcc i32 @pass_vector_bool(i1 inreg zeroext %b) { +entry: + %cond = select i1 %b, i32 66, i32 0 + ret i32 %cond +} + +; CHECK-LABEL: pass_vector_bool@@4: +; CHECK-DAG: testb %cl, %cl +; CHECK-DAG: movl $66, +; CHECK: retl + +define zeroext i1 @ret_true() { +entry: + ret i1 true +} + +; CHECK-LABEL: ret_true: +; CHECK: movb $1, %al +; CHECK: retl diff --git a/test/CodeGen/X86/win64-bool.ll b/test/CodeGen/X86/win64-bool.ll new file mode 100644 index 000000000000..cb77c7ed201e --- /dev/null +++ b/test/CodeGen/X86/win64-bool.ll @@ -0,0 +1,23 @@ +; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=CHECK +; RUN: llc < %s -mtriple=x86_64-windows-gnu | FileCheck %s --check-prefix=CHECK + +define i32 @pass_bool(i1 zeroext %b) { +entry: + %cond = select i1 %b, i32 66, i32 0 + ret i32 %cond +} + +; CHECK-LABEL: pass_bool: +; CHECK-DAG: testb %cl, %cl +; CHECK-DAG: movl $66, +; CHECK: cmovel {{.*}}, %eax +; CHECK: retq + +define zeroext i1 @ret_true() { +entry: + ret i1 true +} + +; CHECK-LABEL: ret_true: +; CHECK: movb $1, %al +; CHECK: retq