Index: llvm/trunk/lib/CodeGen/Analysis.cpp =================================================================== --- llvm/trunk/lib/CodeGen/Analysis.cpp +++ llvm/trunk/lib/CodeGen/Analysis.cpp @@ -546,6 +546,21 @@ 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. Index: llvm/trunk/test/CodeGen/AArch64/tail-call-unused-zext.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/tail-call-unused-zext.ll +++ llvm/trunk/test/CodeGen/AArch64/tail-call-unused-zext.ll @@ -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 +}