[CodeGen] Ignore return sext/zext attributes of unused results for tail calls

If the caller's return type does not have a zeroext attribute but the
callee does a tail call zeroext, we won't consider the tail call during
CodeGenPrepare because the attributes don't match.

However, if the result of the tail call has no uses, it makes sense to
drop the sext/zext attributes.

Differential Revision: https://reviews.llvm.org/D56486

llvm-svn: 350753
This commit is contained in:
Francis Visoiu Mistrih 2019-01-09 19:46:15 +00:00
parent 372b240afa
commit 3a33d73f69
2 changed files with 51 additions and 0 deletions

View File

@ -546,6 +546,21 @@ bool llvm::attributesPermitTailCall(const Function *F, const Instruction *I,
CalleeAttrs.removeAttribute(Attribute::SExt);
}
// Drop sext and zext return attributes if the result is not used.
// This enables tail calls for code like:
//
// define void @caller() {
// entry:
// %unused_result = tail call zeroext i1 @callee()
// br label %retlabel
// retlabel:
// ret void
// }
if (I->use_empty()) {
CalleeAttrs.removeAttribute(Attribute::SExt);
CalleeAttrs.removeAttribute(Attribute::ZExt);
}
// If they're still different, there's some facet we don't understand
// (currently only "inreg", but in future who knows). It may be OK but the
// only safe option is to reject the tail call.

View File

@ -0,0 +1,36 @@
; RUN: llc -mtriple=arm64--- -stop-after=expand-isel-pseudos -o - %s | FileCheck %s
; Check that we ignore the zeroext attribute on the return type of the tail
; call, since the return value is unused. This happens during CodeGenPrepare in
; dupRetToEnableTailCallOpts, which calls attributesPermitTailCall to check if
; the attributes of the caller and the callee match.
declare zeroext i1 @zcallee()
define void @zcaller() {
; CHECK-LABEL: name: zcaller
entry:
br i1 undef, label %calllabel, label %retlabel
calllabel:
; CHECK: bb.1.calllabel:
; CHECK-NOT: BL @zcallee
; CHECK-NEXT: TCRETURNdi @zcallee
%unused_result = tail call zeroext i1 @zcallee()
br label %retlabel
retlabel:
ret void
}
declare signext i1 @scallee()
define void @scaller() {
; CHECK-LABEL: name: scaller
entry:
br i1 undef, label %calllabel, label %retlabel
calllabel:
; CHECK: bb.1.calllabel:
; CHECK-NOT: BL @scallee
; CHECK-NEXT: TCRETURNdi @scallee
%unused_result = tail call signext i1 @scallee()
br label %retlabel
retlabel:
ret void
}