[llvm] r328042 - [ObjCARC] Add funclet token to ARC marker

Shoaib Meenai via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 20 13:45:42 PDT 2018


Author: smeenai
Date: Tue Mar 20 13:45:41 2018
New Revision: 328042

URL: http://llvm.org/viewvc/llvm-project?rev=328042&view=rev
Log:
[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

Added:
    llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll
Modified:
    llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp

Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp?rev=328042&r1=328041&r2=328042&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp (original)
+++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCContract.cpp Tue Mar 20 13:45:41 2018
@@ -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::tryToPeepholeInstr
   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::tryToPeepholeInstr
                               /*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(Func
 
   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(Func
     // 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.

Added: llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll?rev=328042&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll (added)
+++ llvm/trunk/test/Transforms/ObjCARC/contract-marker-funclet.ll Tue Mar 20 13:45:41 2018
@@ -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{{.*}}", ""(){{$}}




More information about the llvm-commits mailing list