Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 4ee8485

Browse files
rnkglandium
authored andcommitted
[X86] Fix Windows i1 zeroext conventions to use i8 instead of i32
Summary: Re-lands r328386 and r328443, reverting r328482. Incorporates fixes from @mstorsjo in D44876 (thanks!) so that small parameters in i8 and i16 do not end up in the SysV register parameters (EDI, ESI, etc). I added tests for how we receive small parameters, since that is the important part. It's always safe to store more bytes than will be read, but the assumptions you make when loading them are what really matter. I also tested this by self-hosting clang and it passed tests on win64. Reviewers: mstorsjo, hans Subscribers: hiraditya, mstorsjo, llvm-commits Differential Revision: https://reviews.llvm.org/D44900 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328570 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 7a5f6ca commit 4ee8485

File tree

5 files changed

+139
-6
lines changed

5 files changed

+139
-6
lines changed

lib/Target/X86/X86CallingConv.td

+11-5
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,8 @@ def CC_X86_Win64_C : CallingConv<[
586586
// FIXME: Handle byval stuff.
587587
// FIXME: Handle varargs.
588588

589-
// Promote i1/i8/i16/v1i1 arguments to i32.
590-
CCIfType<[i1, i8, i16, v1i1], CCPromoteToType<i32>>,
589+
// Promote i1/v1i1 arguments to i8.
590+
CCIfType<[i1, v1i1], CCPromoteToType<i8>>,
591591

592592
// The 'nest' parameter, if any, is passed in R10.
593593
CCIfNest<CCAssignToReg<[R10]>>,
@@ -609,6 +609,10 @@ def CC_X86_Win64_C : CallingConv<[
609609
CCIfType<[x86mmx], CCBitConvertToType<i64>>,
610610

611611
// The first 4 integer arguments are passed in integer registers.
612+
CCIfType<[i8 ], CCAssignToRegWithShadow<[CL , DL , R8B , R9B ],
613+
[XMM0, XMM1, XMM2, XMM3]>>,
614+
CCIfType<[i16], CCAssignToRegWithShadow<[CX , DX , R8W , R9W ],
615+
[XMM0, XMM1, XMM2, XMM3]>>,
612616
CCIfType<[i32], CCAssignToRegWithShadow<[ECX , EDX , R8D , R9D ],
613617
[XMM0, XMM1, XMM2, XMM3]>>,
614618

@@ -628,7 +632,7 @@ def CC_X86_Win64_C : CallingConv<[
628632

629633
// Integer/FP values get stored in stack slots that are 8 bytes in size and
630634
// 8-byte aligned if there are no more registers to hold them.
631-
CCIfType<[i32, i64, f32, f64], CCAssignToStack<8, 8>>,
635+
CCIfType<[i8, i16, i32, i64, f32, f64], CCAssignToStack<8, 8>>,
632636

633637
// Long doubles get stack slots whose size and alignment depends on the
634638
// subtarget.
@@ -841,13 +845,15 @@ def CC_X86_32_MCU : CallingConv<[
841845
]>;
842846

843847
def CC_X86_32_FastCall : CallingConv<[
844-
// Promote i1/i8/i16/v1i1 arguments to i32.
845-
CCIfType<[i1, i8, i16, v1i1], CCPromoteToType<i32>>,
848+
// Promote i1 to i8.
849+
CCIfType<[i1], CCPromoteToType<i8>>,
846850

847851
// The 'nest' parameter, if any, is passed in EAX.
848852
CCIfNest<CCAssignToReg<[EAX]>>,
849853

850854
// The first 2 integer arguments are passed in ECX/EDX
855+
CCIfInReg<CCIfType<[ i8], CCAssignToReg<[ CL, DL]>>>,
856+
CCIfInReg<CCIfType<[i16], CCAssignToReg<[ CX, DX]>>>,
851857
CCIfInReg<CCIfType<[i32], CCAssignToReg<[ECX, EDX]>>>,
852858

853859
// Otherwise, same as everything else.

lib/Target/X86/X86ISelLowering.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -2993,7 +2993,11 @@ SDValue X86TargetLowering::LowerFormalArguments(
29932993
getv64i1Argument(VA, ArgLocs[++I], Chain, DAG, dl, Subtarget);
29942994
} else {
29952995
const TargetRegisterClass *RC;
2996-
if (RegVT == MVT::i32)
2996+
if (RegVT == MVT::i8)
2997+
RC = &X86::GR8RegClass;
2998+
else if (RegVT == MVT::i16)
2999+
RC = &X86::GR16RegClass;
3000+
else if (RegVT == MVT::i32)
29973001
RC = &X86::GR32RegClass;
29983002
else if (Is64Bit && RegVT == MVT::i64)
29993003
RC = &X86::GR64RegClass;

test/CodeGen/X86/win-smallparams.ll

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
; When we accept small parameters on Windows, make sure we do not assume they
2+
; are zero or sign extended in memory or in registers.
3+
4+
; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=WIN64
5+
; RUN: llc < %s -mtriple=x86_64-windows-gnu | FileCheck %s --check-prefix=WIN64
6+
; RUN: llc < %s -mtriple=i686-windows-msvc | FileCheck %s --check-prefix=WIN32
7+
; RUN: llc < %s -mtriple=i686-windows-gnu | FileCheck %s --check-prefix=WIN32
8+
9+
define void @call() {
10+
entry:
11+
%rv = call i32 @manyargs(i8 1, i16 2, i8 3, i16 4, i8 5, i16 6)
12+
ret void
13+
}
14+
15+
define i32 @manyargs(i8 %a, i16 %b, i8 %c, i16 %d, i8 %e, i16 %f) {
16+
entry:
17+
%aa = sext i8 %a to i32
18+
%bb = sext i16 %b to i32
19+
%cc = zext i8 %c to i32
20+
%dd = zext i16 %d to i32
21+
%ee = zext i8 %e to i32
22+
%ff = zext i16 %f to i32
23+
%t0 = add i32 %aa, %bb
24+
%t1 = add i32 %t0, %cc
25+
%t2 = add i32 %t1, %dd
26+
%t3 = add i32 %t2, %ee
27+
%t4 = add i32 %t3, %ff
28+
ret i32 %t4
29+
}
30+
31+
; WIN64-LABEL: call:
32+
; WIN64-DAG: movw $6, 40(%rsp)
33+
; WIN64-DAG: movb $5, 32(%rsp)
34+
; WIN64-DAG: movb $1, %cl
35+
; WIN64-DAG: movw $2, %dx
36+
; WIN64-DAG: movb $3, %r8b
37+
; WIN64-DAG: movw $4, %r9w
38+
; WIN64: callq manyargs
39+
40+
; WIN64-LABEL: manyargs:
41+
; WIN64-DAG: movsbl %cl,
42+
; WIN64-DAG: movswl %dx,
43+
; WIN64-DAG: movzbl %r8b,
44+
; WIN64-DAG: movzwl %r9w,
45+
; WIN64-DAG: movzbl 40(%rsp),
46+
; WIN64-DAG: movzwl 48(%rsp),
47+
; WIN64: retq
48+
49+
50+
; WIN32-LABEL: _call:
51+
; WIN32: pushl $6
52+
; WIN32: pushl $5
53+
; WIN32: pushl $4
54+
; WIN32: pushl $3
55+
; WIN32: pushl $2
56+
; WIN32: pushl $1
57+
; WIN32: calll _manyargs
58+
59+
; WIN32-LABEL: _manyargs:
60+
; WIN32-DAG: movsbl 4(%esp),
61+
; WIN32-DAG: movswl 8(%esp),
62+
; WIN32-DAG: movzbl 12(%esp),
63+
; WIN32-DAG: movzwl 16(%esp),
64+
; WIN32-DAG: movzbl 20(%esp),
65+
; WIN32-DAG: movzwl 24(%esp),
66+
; WIN32: retl
67+

test/CodeGen/X86/win32-bool.ll

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: llc < %s -mtriple=i686-windows-msvc | FileCheck %s
2+
; RUN: llc < %s -mtriple=i686-windows-gnu | FileCheck %s
3+
4+
define x86_fastcallcc i32 @pass_fast_bool(i1 inreg zeroext %b) {
5+
entry:
6+
%cond = select i1 %b, i32 66, i32 0
7+
ret i32 %cond
8+
}
9+
10+
; CHECK-LABEL: @pass_fast_bool@4:
11+
; CHECK-DAG: testb %cl, %cl
12+
; CHECK-DAG: movl $66,
13+
; CHECK: retl
14+
15+
define x86_vectorcallcc i32 @pass_vector_bool(i1 inreg zeroext %b) {
16+
entry:
17+
%cond = select i1 %b, i32 66, i32 0
18+
ret i32 %cond
19+
}
20+
21+
; CHECK-LABEL: pass_vector_bool@@4:
22+
; CHECK-DAG: testb %cl, %cl
23+
; CHECK-DAG: movl $66,
24+
; CHECK: retl
25+
26+
define zeroext i1 @ret_true() {
27+
entry:
28+
ret i1 true
29+
}
30+
31+
; CHECK-LABEL: ret_true:
32+
; CHECK: movb $1, %al
33+
; CHECK: retl

test/CodeGen/X86/win64-bool.ll

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefix=CHECK
2+
; RUN: llc < %s -mtriple=x86_64-windows-gnu | FileCheck %s --check-prefix=CHECK
3+
4+
define i32 @pass_bool(i1 zeroext %b) {
5+
entry:
6+
%cond = select i1 %b, i32 66, i32 0
7+
ret i32 %cond
8+
}
9+
10+
; CHECK-LABEL: pass_bool:
11+
; CHECK-DAG: testb %cl, %cl
12+
; CHECK-DAG: movl $66,
13+
; CHECK: cmovel {{.*}}, %eax
14+
; CHECK: retq
15+
16+
define zeroext i1 @ret_true() {
17+
entry:
18+
ret i1 true
19+
}
20+
21+
; CHECK-LABEL: ret_true:
22+
; CHECK: movb $1, %al
23+
; CHECK: retq

0 commit comments

Comments
 (0)