Teach clang to add metadata tags to calls and invokes in ObjC with

-fno-objc-arc-exceptions. This will allow the optimizer to perform
optimizations which are only safe under that flag.

This is a part of rdar://10803830.

llvm-svn: 150644
This commit is contained in:
Dan Gohman 2012-02-16 00:57:37 +00:00
parent 90e7c12961
commit 515a60daff
5 changed files with 121 additions and 8 deletions

View File

@ -1593,6 +1593,16 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
args.add(EmitAnyExprToTemp(E), type);
}
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges.
void
CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) {
if (CGM.getCodeGenOpts().OptimizationLevel != 0 &&
!CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
Inst->setMetadata("clang.arc.no_objc_arc_exceptions",
CGM.getNoObjCARCExceptionsMetadata());
}
/// Emits a call or invoke instruction to the given function, depending
/// on the current state of the EH stack.
llvm::CallSite
@ -1600,14 +1610,22 @@ CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
ArrayRef<llvm::Value *> Args,
const Twine &Name) {
llvm::BasicBlock *InvokeDest = getInvokeDest();
if (!InvokeDest)
return Builder.CreateCall(Callee, Args, Name);
llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont");
llvm::InvokeInst *Invoke = Builder.CreateInvoke(Callee, ContBB, InvokeDest,
Args, Name);
EmitBlock(ContBB);
return Invoke;
llvm::Instruction *Inst;
if (!InvokeDest)
Inst = Builder.CreateCall(Callee, Args, Name);
else {
llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont");
Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, Name);
EmitBlock(ContBB);
}
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges.
if (CGM.getLangOptions().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(Inst);
return Inst;
}
llvm::CallSite
@ -1916,6 +1934,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges.
if (CGM.getLangOptions().ObjCAutoRefCount)
AddObjCARCExceptionMetadata(CS.getInstruction());
// If the call doesn't return, finish the basic block and clear the
// insertion point; this allows the rest of IRgen to discard
// unreachable code.

View File

@ -2566,6 +2566,8 @@ private:
CodeGenModule::ByrefHelpers *
buildByrefHelpers(llvm::StructType &byrefType,
const AutoVarEmission &emission);
void AddObjCARCExceptionMetadata(llvm::Instruction *Inst);
};
/// Helper class with most of the code for saving a value for a

View File

@ -69,7 +69,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI, CGO),
TBAA(0),
VTables(*this), ObjCRuntime(0), OpenCLRuntime(0), CUDARuntime(0),
DebugInfo(0), ARCData(0), RRData(0), CFConstantStringClassRef(0),
DebugInfo(0), ARCData(0), NoObjCARCExceptionsMetadata(0),
RRData(0), CFConstantStringClassRef(0),
ConstantStringClassRef(0), NSConstantStringType(0),
VMContext(M.getContext()),
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),

View File

@ -233,6 +233,7 @@ class CodeGenModule : public CodeGenTypeCache {
CGCUDARuntime* CUDARuntime;
CGDebugInfo* DebugInfo;
ARCEntrypoints *ARCData;
llvm::MDNode *NoObjCARCExceptionsMetadata;
RREntrypoints *RRData;
// WeakRefReferences - A set of references that have only been seen via
@ -421,6 +422,14 @@ public:
CGDebugInfo *getModuleDebugInfo() { return DebugInfo; }
llvm::MDNode *getNoObjCARCExceptionsMetadata() {
if (!NoObjCARCExceptionsMetadata)
NoObjCARCExceptionsMetadata =
llvm::MDNode::get(getLLVMContext(),
SmallVector<llvm::Value*,1>());
return NoObjCARCExceptionsMetadata;
}
ASTContext &getContext() const { return Context; }
const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; }
const LangOptions &getLangOptions() const { return Features; }

View File

@ -0,0 +1,78 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O0 -disable-llvm-optzns -o - %s | FileCheck -check-prefix=NO-METADATA %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s -fobjc-arc-exceptions | FileCheck -check-prefix=NO-METADATA %s
// The front-end should emit clang.arc.no_objc_arc_exceptions in -fobjc-arc-exceptions
// mode when optimization is enabled, and not otherwise.
void thrower(void);
void not(void) __attribute__((nothrow));
// CHECK: define void @test0(
// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions !0
// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions !0
// NO-METADATA: define void @test0(
// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
// NO-METADATA: }
void test0(void) {
thrower();
not();
}
// CHECK: define void @test1(
// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions !0
// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions !0
// NO-METADATA: define void @test1(
// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
// NO-METADATA: }
void test1(id x) {
id y = x;
thrower();
not();
}
void NSLog(id, ...);
// CHECK: define void @test2(
// CHECK: invoke void (i8*, ...)* @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i32* %x2)
// CHECK: to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
// NO-METADATA: define void @test2(
// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
// NO-METADATA: }
void test2(void) {
@autoreleasepool {
__attribute__((__blocks__(byref))) int x;
NSLog(@"Address of x outside of block: %p", &x);
}
}
// CHECK: define void @test3(
// CHECK: invoke void %9(i8* %7)
// CHECK: to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
// NO-METADATA: define void @test3(
// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
// NO-METADATA: }
void test3(void) {
@autoreleasepool {
__attribute__((__blocks__(byref))) int x;
^{
NSLog(@"Address of x in non-assigned block: %p", &x);
}();
}
}
// CHECK: define void @test4(
// CHECK: invoke void %13(i8* %11)
// CHECK: to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
// NO-METADATA: define void @test4(
// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
// NO-METADATA: }
void test4(void) {
@autoreleasepool {
__attribute__((__blocks__(byref))) int x;
void (^b)(void) = ^{
NSLog(@"Address of x in assigned block: %p", &x);
};
b();
}
}