summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorDavid Green <david.green@arm.com>2018-09-26 10:46:18 +0000
committerDavid Green <david.green@arm.com>2018-09-26 10:46:18 +0000
commit353cb3d4e524555c3bc9b7e0b4f857675c08ea41 (patch)
tree5a02391c7e707ec05d041c5d55a03ce3daaff6ab /llvm
parent67572004df09bb342fc8ef92be96b5963071b3a6 (diff)
downloadbcm5719-llvm-353cb3d4e524555c3bc9b7e0b4f857675c08ea41.tar.gz
bcm5719-llvm-353cb3d4e524555c3bc9b7e0b4f857675c08ea41.zip
[CodeGen] Enable tail calls for functions with NonNull attributes.
Adding NonNull as attributes to returned pointers has the unfortunate side effect of disabling tail calls. This patch ignores the NonNull attribute when we decide whether to tail merge, in the same way that we ignore the NoAlias attribute, as it has no affect on the call sequence. Differential Revision: https://reviews.llvm.org/D52238 llvm-svn: 343091
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/CodeGen/Analysis.cpp6
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp9
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp4
-rw-r--r--llvm/test/CodeGen/ARM/tail-call.ll12
-rw-r--r--llvm/test/Transforms/CodeGenPrepare/ARM/tailcall-dup.ll77
5 files changed, 96 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 7c1fb6879a6..b769e92590f 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -519,10 +519,12 @@ bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
AttrBuilder CalleeAttrs(cast<CallInst>(I)->getAttributes(),
AttributeList::ReturnIndex);
- // Noalias is completely benign as far as calling convention goes, it
- // shouldn't affect whether the call is a tail call.
+ // NoAlias and NonNull are completely benign as far as calling convention
+ // goes, they shouldn't affect whether the call is a tail call.
CallerAttrs.removeAttribute(Attribute::NoAlias);
CalleeAttrs.removeAttribute(Attribute::NoAlias);
+ CallerAttrs.removeAttribute(Attribute::NonNull);
+ CalleeAttrs.removeAttribute(Attribute::NonNull);
if (CallerAttrs.contains(Attribute::ZExt)) {
if (!CalleeAttrs.contains(Attribute::ZExt))
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp
index ec4451ffa75..d69e9589976 100644
--- a/llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1871,15 +1871,6 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB) {
CallInst *CI = TailCalls[i];
CallSite CS(CI);
- // Conservatively require the attributes of the call to match those of the
- // return. Ignore noalias because it doesn't affect the call sequence.
- AttributeList CalleeAttrs = CS.getAttributes();
- if (AttrBuilder(CalleeAttrs, AttributeList::ReturnIndex)
- .removeAttribute(Attribute::NoAlias) !=
- AttrBuilder(CalleeAttrs, AttributeList::ReturnIndex)
- .removeAttribute(Attribute::NoAlias))
- continue;
-
// Make sure the call instruction is followed by an unconditional branch to
// the return block.
BasicBlock *CallBB = CI->getParent();
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index d7d4bef8d3c..46c2f8ebfb8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -55,10 +55,12 @@ bool TargetLowering::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
const Function &F = DAG.getMachineFunction().getFunction();
// Conservatively require the attributes of the call to match those of
- // the return. Ignore noalias because it doesn't affect the call sequence.
+ // the return. Ignore NoAlias and NonNull because they don't affect the
+ // call sequence.
AttributeList CallerAttrs = F.getAttributes();
if (AttrBuilder(CallerAttrs, AttributeList::ReturnIndex)
.removeAttribute(Attribute::NoAlias)
+ .removeAttribute(Attribute::NonNull)
.hasAttributes())
return false;
diff --git a/llvm/test/CodeGen/ARM/tail-call.ll b/llvm/test/CodeGen/ARM/tail-call.ll
index 15ce4d791e8..abf0c988c9e 100644
--- a/llvm/test/CodeGen/ARM/tail-call.ll
+++ b/llvm/test/CodeGen/ARM/tail-call.ll
@@ -98,3 +98,15 @@ entry:
%call = tail call i32 (i32, ...) @variadic(i32 %y, i64 %z, i64 %z)
ret void
}
+
+; Check that NonNull attributes don't inhibit tailcalls.
+
+declare nonnull i8* @nonnull_callee(i8* %p, i32 %val)
+define i8* @nonnull_caller(i8* %p, i32 %val) {
+; CHECK-LABEL: nonnull_caller:
+; CHECK-TAIL: b nonnull_callee
+; CHECK-NO-TAIL: bl nonnull_callee
+entry:
+ %call = tail call i8* @nonnull_callee(i8* %p, i32 %val)
+ ret i8* %call
+}
diff --git a/llvm/test/Transforms/CodeGenPrepare/ARM/tailcall-dup.ll b/llvm/test/Transforms/CodeGenPrepare/ARM/tailcall-dup.ll
new file mode 100644
index 00000000000..09658ae75ac
--- /dev/null
+++ b/llvm/test/Transforms/CodeGenPrepare/ARM/tailcall-dup.ll
@@ -0,0 +1,77 @@
+; RUN: opt -codegenprepare -S < %s | FileCheck %s
+
+target triple = "armv8m.main-none-eabi"
+
+declare i8* @f0()
+declare i8* @f1()
+
+define i8* @tail_dup() {
+; CHECK-LABEL: tail_dup
+; CHECK: tail call i8* @f0()
+; CHECK-NEXT: ret i8*
+; CHECK: tail call i8* @f1()
+; CHECK-NEXT: ret i8*
+bb0:
+ %tmp0 = tail call i8* @f0()
+ br label %return
+bb1:
+ %tmp1 = tail call i8* @f1()
+ br label %return
+return:
+ %retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
+ ret i8* %retval
+}
+
+define nonnull i8* @nonnull_dup() {
+; CHECK-LABEL: nonnull_dup
+; CHECK: tail call i8* @f0()
+; CHECK-NEXT: ret i8*
+; CHECK: tail call i8* @f1()
+; CHECK-NEXT: ret i8*
+bb0:
+ %tmp0 = tail call i8* @f0()
+ br label %return
+bb1:
+ %tmp1 = tail call i8* @f1()
+ br label %return
+return:
+ %retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
+ ret i8* %retval
+}
+
+define i8* @noalias_dup() {
+; CHECK-LABEL: noalias_dup
+; CHECK: tail call noalias i8* @f0()
+; CHECK-NEXT: ret i8*
+; CHECK: tail call noalias i8* @f1()
+; CHECK-NEXT: ret i8*
+bb0:
+ %tmp0 = tail call noalias i8* @f0()
+ br label %return
+bb1:
+ %tmp1 = tail call noalias i8* @f1()
+ br label %return
+return:
+ %retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
+ ret i8* %retval
+}
+
+; Use inreg as a way of testing that attributes (other than nonnull and
+; noalias) disable the tailcall duplication in cgp.
+
+define inreg i8* @inreg_nodup() {
+; CHECK-LABEL: inreg_nodup
+; CHECK: tail call i8* @f0()
+; CHECK-NEXT: br label %return
+; CHECK: tail call i8* @f1()
+; CHECK-NEXT: br label %return
+bb0:
+ %tmp0 = tail call i8* @f0()
+ br label %return
+bb1:
+ %tmp1 = tail call i8* @f1()
+ br label %return
+return:
+ %retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
+ ret i8* %retval
+}
OpenPOWER on IntegriCloud