[ObjCARC] Add funclet token to ARC marker

The inline assembly generated for the ARC autorelease elision marker
must have a funclet token if it's emitted inside a funclet, otherwise
the inline assembly (and all subsequent code in the funclet) will be
marked unreachable by WinEHPrepare.

Note that this only applies for the non-O0 case, since at O0, clang
emits the autorelease elision marker itself rather than deferring to the
backend. The fix for clang is handled in a separate change.

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

llvm-svn: 328042
This commit is contained in:
Shoaib Meenai 2018-03-20 20:45:41 +00:00
parent 8ef820a6ed
commit 3f689c8632
2 changed files with 88 additions and 8 deletions

View File

@ -31,6 +31,7 @@
#include "ObjCARC.h"
#include "ProvenanceAnalysis.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Operator.h"
@ -74,11 +75,13 @@ namespace {
SmallPtrSet<CallInst *, 8> StoreStrongCalls;
/// Returns true if we eliminated Inst.
bool tryToPeepholeInstruction(Function &F, Instruction *Inst,
inst_iterator &Iter,
SmallPtrSetImpl<Instruction *> &DepInsts,
SmallPtrSetImpl<const BasicBlock *> &Visited,
bool &TailOkForStoreStrong);
bool
tryToPeepholeInstruction(Function &F, Instruction *Inst,
inst_iterator &Iter,
SmallPtrSetImpl<Instruction *> &DepInsts,
SmallPtrSetImpl<const BasicBlock *> &Visited,
bool &TailOkForStoreStrong,
DenseMap<BasicBlock *, ColorVector> &BlockColors);
bool optimizeRetainCall(Function &F, Instruction *Retain);
@ -407,7 +410,8 @@ bool ObjCARCContract::tryToPeepholeInstruction(
Function &F, Instruction *Inst, inst_iterator &Iter,
SmallPtrSetImpl<Instruction *> &DependingInsts,
SmallPtrSetImpl<const BasicBlock *> &Visited,
bool &TailOkForStoreStrongs) {
bool &TailOkForStoreStrongs,
DenseMap<BasicBlock *, ColorVector> &BlockColors) {
// Only these library routines return their argument. In particular,
// objc_retainBlock does not necessarily return its argument.
ARCInstKind Class = GetBasicARCInstKind(Inst);
@ -457,7 +461,17 @@ bool ObjCARCContract::tryToPeepholeInstruction(
/*isVarArg=*/false),
RVInstMarker->getString(),
/*Constraints=*/"", /*hasSideEffects=*/true);
CallInst::Create(IA, "", Inst);
SmallVector<OperandBundleDef, 1> OpBundles;
if (!BlockColors.empty()) {
const ColorVector &CV = BlockColors.find(Inst->getParent())->second;
assert(CV.size() == 1 && "non-unique color for block!");
Instruction *EHPad = CV.front()->getFirstNonPHI();
if (EHPad->isEHPad())
OpBundles.emplace_back("funclet", EHPad);
}
CallInst::Create(IA, None, OpBundles, "", Inst);
}
decline_rv_optimization:
return false;
@ -518,6 +532,11 @@ bool ObjCARCContract::runOnFunction(Function &F) {
PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
DenseMap<BasicBlock *, ColorVector> BlockColors;
if (F.hasPersonalityFn() &&
isFuncletEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
BlockColors = colorEHFunclets(F);
DEBUG(llvm::dbgs() << "**** ObjCARC Contract ****\n");
// Track whether it's ok to mark objc_storeStrong calls with the "tail"
@ -541,7 +560,7 @@ bool ObjCARCContract::runOnFunction(Function &F) {
// First try to peephole Inst. If there is nothing further we can do in
// terms of undoing objc-arc-expand, process the next inst.
if (tryToPeepholeInstruction(F, Inst, I, DependingInstructions, Visited,
TailOkForStoreStrongs))
TailOkForStoreStrongs, BlockColors))
continue;
// Otherwise, try to undo objc-arc-expand.

View File

@ -0,0 +1,61 @@
; RUN: opt -mtriple=i686-unknown-windows-msvc -objc-arc-contract -S -o - %s | FileCheck %s
; Generated (and lightly modified and cleaned up) from the following source:
; id f();
; void g() {
; try {
; f();
; } catch (...) {
; f();
; }
; }
define void @"\01?g@@YAXXZ"() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
entry:
%call = invoke i8* @"\01?f@@YAPAUobjc_object@@XZ"()
to label %invoke.cont unwind label %catch.dispatch
catch.dispatch: ; preds = %entry
%0 = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
%1 = catchpad within %0 [i8* null, i32 64, i8* null]
%call1 = call i8* @"\01?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
%2 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call1) [ "funclet"(token %1) ]
call void @objc_release(i8* %2) [ "funclet"(token %1) ]
br label %catch.1
catch.1: ; preds = %catch
%call2 = call i8* @"\01?f@@YAPAUobjc_object@@XZ"() [ "funclet"(token %1) ]
%3 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call2) [ "funclet"(token %1) ]
call void @objc_release(i8* %3) [ "funclet"(token %1) ]
catchret from %1 to label %catchret.dest
catchret.dest: ; preds = %catch.1
ret void
invoke.cont: ; preds = %entry
%4 = call i8* @objc_retainAutoreleasedReturnValue(i8* %call)
call void @objc_release(i8* %4)
ret void
}
declare i8* @"\01?f@@YAPAUobjc_object@@XZ"()
declare i32 @__CxxFrameHandler3(...)
declare dllimport i8* @objc_retainAutoreleasedReturnValue(i8*)
declare dllimport void @objc_release(i8*)
!clang.arc.retainAutoreleasedReturnValueMarker = !{!0}
!0 = !{!"movl\09%ebp, %ebp\09\09// marker for objc_retainAutoreleaseReturnValue"}
; CHECK-LABEL: catch
; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
; CHECK-LABEL: catch.1
; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]
; CHECK-LABEL: invoke.cont
; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}}