From c9c6da61ac027d9818652d417907f84398288b99 Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Thu, 25 Sep 2008 20:47:45 +0000 Subject: [PATCH] Accept 'inreg' attribute on x86 functions as meaning sse_regparm (i.e. float/double values go in XMM0 instead of ST0). Update documentation to reflect reality. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56619 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.html | 8 +++++--- include/llvm/CodeGen/SelectionDAGNodes.h | 4 ++-- .../SelectionDAG/SelectionDAGBuild.cpp | 9 +++++++-- lib/Target/X86/X86CallingConv.td | 12 ++++++++---- test/CodeGen/X86/2008-09-25-sseregparm-1.ll | 19 +++++++++++++++++++ 5 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 test/CodeGen/X86/2008-09-25-sseregparm-1.ll diff --git a/docs/LangRef.html b/docs/LangRef.html index 25ac4cbde1b..8987af254f0 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -845,9 +845,11 @@ declare i32 @atoi(i8*) nounwind readonly a call to this function.
inreg
-
This indicates that the parameter should be placed in register (if - possible) during assembling function call. Support for this attribute is - target-specific
+
This indicates that this parameter or return value should be treated + in a special target-dependent fashion during while emitting code for a + function call or return (usually, by putting it in a register as opposed + to memory; in some places it is used to distinguish between two different + kinds of registers). Use of this attribute is target-specific
byval
This indicates that the pointer parameter should really be passed by diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 04686693622..111d3f849a7 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -480,8 +480,8 @@ namespace ISD { // RET - Return from function. The first operand is the chain, // and any subsequent operands are pairs of return value and return value - // signness for the function. This operation can have variable number of - // operands. + // attributes (see CALL for description of attributes) for the function. + // This operation can have variable number of operands. RET, // INLINEASM - Represents an inline asm block. This node always has two diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index b9f1aa45078..01f1f28b23e 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -913,7 +913,8 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) { MVT VT = ValueVTs[j]; // FIXME: C calling convention requires the return type to be promoted to - // at least 32-bit. But this is not necessary for non-C calling conventions. + // at least 32-bit. But this is not necessary for non-C calling + // conventions. if (VT.isInteger()) { MVT MinVT = TLI.getRegisterType(MVT::i32); if (VT.bitsLT(MinVT)) @@ -934,9 +935,13 @@ void SelectionDAGLowering::visitRet(ReturnInst &I) { getCopyToParts(DAG, SDValue(RetOp.getNode(), RetOp.getResNo() + j), &Parts[0], NumParts, PartVT, ExtendKind); + // 'inreg' on function refers to return value + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (F->paramHasAttr(0, ParamAttr::InReg)) + Flags.setInReg(); for (unsigned i = 0; i < NumParts; ++i) { NewValues.push_back(Parts[i]); - NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy())); + NewValues.push_back(DAG.getArgFlags(Flags)); } } } diff --git a/lib/Target/X86/X86CallingConv.td b/lib/Target/X86/X86CallingConv.td index b98b5d9b495..590bc1015a9 100644 --- a/lib/Target/X86/X86CallingConv.td +++ b/lib/Target/X86/X86CallingConv.td @@ -43,10 +43,14 @@ def RetCC_X86Common : CallingConv<[ // X86-32 C return-value convention. def RetCC_X86_32_C : CallingConv<[ - // The X86-32 calling convention returns FP values in ST0, otherwise it is the - // same as the common X86 calling conv. - CCIfType<[f32], CCAssignToReg<[ST0, ST1]>>, - CCIfType<[f64], CCAssignToReg<[ST0, ST1]>>, + // The X86-32 calling convention returns FP values in ST0, unless marked + // with "inreg" (used here to distinguish one kind of reg from another, + // weirdly; this is really the sse-regparm calling convention) in which + // case they use XMM0, otherwise it is the same as the common X86 calling + // conv. + CCIfInReg>>>, + CCIfType<[f32,f64], CCAssignToReg<[ST0, ST1]>>, CCDelegateTo ]>; diff --git a/test/CodeGen/X86/2008-09-25-sseregparm-1.ll b/test/CodeGen/X86/2008-09-25-sseregparm-1.ll new file mode 100644 index 00000000000..d103f144e28 --- /dev/null +++ b/test/CodeGen/X86/2008-09-25-sseregparm-1.ll @@ -0,0 +1,19 @@ +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | grep movs | count 2 +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 | grep fld | count 2 +; check 'inreg' attribute for sse_regparm + +define double @foo1() inreg nounwind { + ret double 1.0 +} + +define float @foo2() inreg nounwind { + ret float 1.0 +} + +define double @bar() nounwind { + ret double 1.0 +} + +define float @bar2() nounwind { + ret float 1.0 +}