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 +}