llvm.org GIT mirror llvm / 6e5bbb5
ArgumentPromotion: Drop sret attribute on functions that are only called directly. If the first argument to a function is a 'this' argument and the second has the sret attribute, the ArgumentPromotion pass may promote the 'this' argument to more than one argument, violating the IR constraint that 'sret' may only be applied to the first or second argument. Although this IR constraint is arguably unnecessary, it highlighted the fact that ArgPromotion does not need to preserve this attribute. Dropping the attribute reduces register pressure in the backend by avoiding the register copy required by sret. Because sret implies noalias, we also replace the former with the latter. Differential Revision: http://reviews.llvm.org/D10353 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239488 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 4 years ago
3 changed file(s) with 47 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
153153 /// it in its containing function.
154154 bool Argument::hasStructRetAttr() const {
155155 if (!getType()->isPointerTy()) return false;
156 if (this != getParent()->arg_begin())
157 return false; // StructRet param must be first param
158156 return getParent()->getAttributes().
159 hasAttribute(1, Attribute::StructRet);
157 hasAttribute(getArgNo()+1, Attribute::StructRet);
160158 }
161159
162160 /// hasReturnedAttr - Return true if this argument has the returned attribute on
243243 for (unsigned i = 0, e = PointerArgs.size(); i != e; ++i) {
244244 Argument *PtrArg = PointerArgs[i];
245245 Type *AgTy = cast(PtrArg->getType())->getElementType();
246
247 // Replace sret attribute with noalias. This reduces register pressure by
248 // avoiding a register copy.
249 if (PtrArg->hasStructRetAttr()) {
250 unsigned ArgNo = PtrArg->getArgNo();
251 F->setAttributes(
252 F->getAttributes()
253 .removeAttribute(F->getContext(), ArgNo + 1, Attribute::StructRet)
254 .addAttribute(F->getContext(), ArgNo + 1, Attribute::NoAlias));
255 for (Use &U : F->uses()) {
256 CallSite CS(U.getUser());
257 CS.setAttributes(
258 CS.getAttributes()
259 .removeAttribute(F->getContext(), ArgNo + 1,
260 Attribute::StructRet)
261 .addAttribute(F->getContext(), ArgNo + 1, Attribute::NoAlias));
262 }
263 }
246264
247265 // If this is a byval argument, and if the aggregate type is small, just
248266 // pass the elements, which is always safe, if the passed value is densely
0 ; RUN: opt < %s -argpromotion -S | FileCheck %s
1
2 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-pc-windows-msvc"
4
5 ; CHECK: define internal void @add(i32 %[[THIS1:.*]], i32 %[[THIS2:.*]], i32* noalias %[[SR:.*]])
6 define internal void @add({i32, i32}* %this, i32* sret %r) {
7 %ap = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 0
8 %bp = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 1
9 %a = load i32, i32* %ap
10 %b = load i32, i32* %bp
11 ; CHECK: %[[AB:.*]] = add i32 %[[THIS1]], %[[THIS2]]
12 %ab = add i32 %a, %b
13 ; CHECK: store i32 %[[AB]], i32* %[[SR]]
14 store i32 %ab, i32* %r
15 ret void
16 }
17
18 ; CHECK: define void @f()
19 define void @f() {
20 ; CHECK: %[[R:.*]] = alloca i32
21 %r = alloca i32
22 %pair = alloca {i32, i32}
23
24 ; CHECK: call void @add(i32 %{{.*}}, i32 %{{.*}}, i32* noalias %[[R]])
25 call void @add({i32, i32}* %pair, i32* sret %r)
26 ret void
27 }