Skip to content

Commit 456ca04

Browse files
committed
Add CodeGen support for functions that always return arguments via a new parameter attribute 'returned', which is taken advantage of in target-independent tail call opportunity detection and in ARM call lowering (when placed on an integral first parameter).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179925 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 5c34e08 commit 456ca04

20 files changed

+371
-43
lines changed

docs/LangRef.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,17 @@ Currently, only the following parameter attributes are defined:
719719
``nest``
720720
This indicates that the pointer parameter can be excised using the
721721
:ref:`trampoline intrinsics <int_trampoline>`. This is not a valid
722-
attribute for return values.
722+
attribute for return values and can only be applied to one parameter.
723+
724+
``returned``
725+
This indicates that the value of the function always returns the value
726+
of the parameter as its return value. This is an optimization hint to
727+
the code generator when generating the caller, allowing tail call
728+
optimization and omission of register saves and restores in some cases;
729+
it is not checked or enforced when generating the callee. The parameter
730+
and the function return type must be valid operands for the
731+
:ref:`bitcast instruction <i_bitcast>`. This is not a valid attribute for
732+
return values and can only be applied to one parameter.
723733

724734
.. _gc:
725735

include/llvm/IR/Argument.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ class Argument : public Value, public ilist_node<Argument> {
7878
/// containing function.
7979
bool hasStructRetAttr() const;
8080

81+
/// \brief Return true if this argument has the returned attribute on it in
82+
/// its containing function.
83+
bool hasReturnedAttr() const;
84+
8185
/// \brief Add a Attribute to an argument.
8286
void addAttr(AttributeSet AS);
8387

include/llvm/IR/Attributes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class Attribute {
8787
OptimizeForSize, ///< opt_size
8888
ReadNone, ///< Function does not access memory
8989
ReadOnly, ///< Function only reads from memory
90+
Returned, ///< Return value is always equal to this argument
9091
ReturnsTwice, ///< Function can return twice
9192
SExt, ///< Sign extended before/after call
9293
StackAlignment, ///< Alignment of stack for function (3 bits)

include/llvm/Target/TargetCallingConv.h

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ namespace ISD {
3636
static const uint64_t ByValOffs = 4;
3737
static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain
3838
static const uint64_t NestOffs = 5;
39-
static const uint64_t ByValAlign = 0xFULL << 6; ///< Struct alignment
40-
static const uint64_t ByValAlignOffs = 6;
41-
static const uint64_t Split = 1ULL << 10;
42-
static const uint64_t SplitOffs = 10;
39+
static const uint64_t Returned = 1ULL<<6;
40+
static const uint64_t ReturnedOffs = 6;
41+
static const uint64_t ByValAlign = 0xFULL<<7; ///< Struct alignment
42+
static const uint64_t ByValAlignOffs = 7;
43+
static const uint64_t Split = 1ULL<<11;
44+
static const uint64_t SplitOffs = 11;
4345
static const uint64_t OrigAlign = 0x1FULL<<27;
4446
static const uint64_t OrigAlignOffs = 27;
4547
static const uint64_t ByValSize = 0xffffffffULL << 32; ///< Struct size
@@ -51,23 +53,26 @@ namespace ISD {
5153
public:
5254
ArgFlagsTy() : Flags(0) { }
5355

54-
bool isZExt() const { return Flags & ZExt; }
55-
void setZExt() { Flags |= One << ZExtOffs; }
56+
bool isZExt() const { return Flags & ZExt; }
57+
void setZExt() { Flags |= One << ZExtOffs; }
5658

57-
bool isSExt() const { return Flags & SExt; }
58-
void setSExt() { Flags |= One << SExtOffs; }
59+
bool isSExt() const { return Flags & SExt; }
60+
void setSExt() { Flags |= One << SExtOffs; }
5961

60-
bool isInReg() const { return Flags & InReg; }
61-
void setInReg() { Flags |= One << InRegOffs; }
62+
bool isInReg() const { return Flags & InReg; }
63+
void setInReg() { Flags |= One << InRegOffs; }
6264

63-
bool isSRet() const { return Flags & SRet; }
64-
void setSRet() { Flags |= One << SRetOffs; }
65+
bool isSRet() const { return Flags & SRet; }
66+
void setSRet() { Flags |= One << SRetOffs; }
6567

66-
bool isByVal() const { return Flags & ByVal; }
67-
void setByVal() { Flags |= One << ByValOffs; }
68+
bool isByVal() const { return Flags & ByVal; }
69+
void setByVal() { Flags |= One << ByValOffs; }
6870

69-
bool isNest() const { return Flags & Nest; }
70-
void setNest() { Flags |= One << NestOffs; }
71+
bool isNest() const { return Flags & Nest; }
72+
void setNest() { Flags |= One << NestOffs; }
73+
74+
bool isReturned() const { return Flags & Returned; }
75+
void setReturned() { Flags |= One << ReturnedOffs; }
7176

7277
unsigned getByValAlign() const {
7378
return (unsigned)

include/llvm/Target/TargetLowering.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,16 +1910,18 @@ class TargetLowering : public TargetLoweringBase {
19101910
struct ArgListEntry {
19111911
SDValue Node;
19121912
Type* Ty;
1913-
bool isSExt : 1;
1914-
bool isZExt : 1;
1915-
bool isInReg : 1;
1916-
bool isSRet : 1;
1917-
bool isNest : 1;
1918-
bool isByVal : 1;
1913+
bool isSExt : 1;
1914+
bool isZExt : 1;
1915+
bool isInReg : 1;
1916+
bool isSRet : 1;
1917+
bool isNest : 1;
1918+
bool isByVal : 1;
1919+
bool isReturned : 1;
19191920
uint16_t Alignment;
19201921

19211922
ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
1922-
isSRet(false), isNest(false), isByVal(false), Alignment(0) { }
1923+
isSRet(false), isNest(false), isByVal(false), isReturned(false),
1924+
Alignment(0) { }
19231925
};
19241926
typedef std::vector<ArgListEntry> ArgListTy;
19251927

lib/AsmParser/LLLexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ lltok::Kind LLLexer::LexIdentifier() {
582582
KEYWORD(optsize);
583583
KEYWORD(readnone);
584584
KEYWORD(readonly);
585+
KEYWORD(returned);
585586
KEYWORD(returns_twice);
586587
KEYWORD(signext);
587588
KEYWORD(sret);

lib/AsmParser/LLParser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
944944
case lltok::kw_nest:
945945
case lltok::kw_noalias:
946946
case lltok::kw_nocapture:
947+
case lltok::kw_returned:
947948
case lltok::kw_sret:
948949
HaveError |=
949950
Error(Lex.getLoc(),
@@ -1156,6 +1157,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
11561157
case lltok::kw_nest: B.addAttribute(Attribute::Nest); break;
11571158
case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break;
11581159
case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break;
1160+
case lltok::kw_returned: B.addAttribute(Attribute::Returned); break;
11591161
case lltok::kw_signext: B.addAttribute(Attribute::SExt); break;
11601162
case lltok::kw_sret: B.addAttribute(Attribute::StructRet); break;
11611163
case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break;
@@ -1199,6 +1201,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
11991201
case lltok::kw_byval:
12001202
case lltok::kw_nest:
12011203
case lltok::kw_nocapture:
1204+
case lltok::kw_returned:
12021205
case lltok::kw_sret:
12031206
HaveError |= Error(Lex.getLoc(), "invalid use of parameter-only attribute");
12041207
break;

lib/AsmParser/LLToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ namespace lltok {
114114
kw_optsize,
115115
kw_readnone,
116116
kw_readonly,
117+
kw_returned,
117118
kw_returns_twice,
118119
kw_signext,
119120
kw_ssp,

lib/CodeGen/Analysis.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,32 @@ static bool sameNoopInput(const Value *V1, const Value *V2,
261261
TLI.getPointerTy().getSizeInBits() ==
262262
cast<IntegerType>(I->getType())->getBitWidth())
263263
NoopInput = Op;
264+
} else if (isa<CallInst>(I)) {
265+
// Look through call
266+
for (User::const_op_iterator i = I->op_begin(),
267+
// Skip Callee
268+
e = I->op_end() - 1;
269+
i != e; ++i) {
270+
unsigned attrInd = i - I->op_begin() + 1;
271+
if (cast<CallInst>(I)->paramHasAttr(attrInd, Attribute::Returned) &&
272+
isNoopBitcast((*i)->getType(), I->getType(), TLI)) {
273+
NoopInput = *i;
274+
break;
275+
}
276+
}
277+
} else if (isa<InvokeInst>(I)) {
278+
// Look through invoke
279+
for (User::const_op_iterator i = I->op_begin(),
280+
// Skip BB, BB, Callee
281+
e = I->op_end() - 3;
282+
i != e; ++i) {
283+
unsigned attrInd = i - I->op_begin() + 1;
284+
if (cast<InvokeInst>(I)->paramHasAttr(attrInd, Attribute::Returned) &&
285+
isNoopBitcast((*i)->getType(), I->getType(), TLI)) {
286+
NoopInput = *i;
287+
break;
288+
}
289+
}
264290
}
265291
}
266292

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5232,6 +5232,7 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
52325232
Entry.isSRet = true;
52335233
Entry.isNest = false;
52345234
Entry.isByVal = false;
5235+
Entry.isReturned = false;
52355236
Entry.Alignment = Align;
52365237
Args.push_back(Entry);
52375238
RetTy = Type::getVoidTy(FTy->getContext());
@@ -5249,13 +5250,14 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
52495250
Entry.Node = ArgNode; Entry.Ty = V->getType();
52505251

52515252
unsigned attrInd = i - CS.arg_begin() + 1;
5252-
Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt);
5253-
Entry.isZExt = CS.paramHasAttr(attrInd, Attribute::ZExt);
5254-
Entry.isInReg = CS.paramHasAttr(attrInd, Attribute::InReg);
5255-
Entry.isSRet = CS.paramHasAttr(attrInd, Attribute::StructRet);
5256-
Entry.isNest = CS.paramHasAttr(attrInd, Attribute::Nest);
5257-
Entry.isByVal = CS.paramHasAttr(attrInd, Attribute::ByVal);
5258-
Entry.Alignment = CS.getParamAlignment(attrInd);
5253+
Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt);
5254+
Entry.isZExt = CS.paramHasAttr(attrInd, Attribute::ZExt);
5255+
Entry.isInReg = CS.paramHasAttr(attrInd, Attribute::InReg);
5256+
Entry.isSRet = CS.paramHasAttr(attrInd, Attribute::StructRet);
5257+
Entry.isNest = CS.paramHasAttr(attrInd, Attribute::Nest);
5258+
Entry.isByVal = CS.paramHasAttr(attrInd, Attribute::ByVal);
5259+
Entry.isReturned = CS.paramHasAttr(attrInd, Attribute::Returned);
5260+
Entry.Alignment = CS.getParamAlignment(attrInd);
52595261
Args.push_back(Entry);
52605262
}
52615263

@@ -6430,6 +6432,8 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
64306432
}
64316433
if (Args[i].isNest)
64326434
Flags.setNest();
6435+
if (Args[i].isReturned)
6436+
Flags.setReturned();
64336437
Flags.setOrigAlign(OriginalAlignment);
64346438

64356439
MVT PartVT = getRegisterType(CLI.RetTy->getContext(), VT);

0 commit comments

Comments
 (0)