-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[LTO] enable ObjCARCContractPass
only on optimized build
#101114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ebbba2b
a1604de
4fc7867
a45b3b9
34e6238
c9c15bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
; RUN: opt -thinlto-bc -o %t.o %s | ||
|
||
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t.o \ | ||
; RUN: -o %t2.index \ | ||
; RUN: -r=%t.o,_use_arc,px | ||
|
||
; RUN: %clang_cc1 -O2 -triple x86_64-apple-darwin \ | ||
; RUN: -emit-obj -fthinlto-index=%t.o.thinlto.bc \ | ||
; RUN: -o %t.native.o -x ir %t.o | ||
|
||
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" | ||
target triple = "x86_64-apple-darwin" | ||
|
||
define void @use_arc(ptr %a, ptr %b) { | ||
call void (...) @llvm.objc.clang.arc.use(ptr %a, ptr %b) nounwind | ||
ret void | ||
} | ||
|
||
declare void @llvm.objc.clang.arc.use(...) nounwind |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,26 +41,26 @@ extern bool EnableARCOpts; | |
/// Test if the given module looks interesting to run ARC optimization | ||
/// on. | ||
inline bool ModuleHasARC(const Module &M) { | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're not calling this anymore, I don't think we need this change. |
||
M.getNamedValue("llvm.objc.retain") || | ||
M.getNamedValue("llvm.objc.release") || | ||
M.getNamedValue("llvm.objc.autorelease") || | ||
M.getNamedValue("llvm.objc.retainAutoreleasedReturnValue") || | ||
M.getNamedValue("llvm.objc.unsafeClaimAutoreleasedReturnValue") || | ||
M.getNamedValue("llvm.objc.retainBlock") || | ||
M.getNamedValue("llvm.objc.autoreleaseReturnValue") || | ||
M.getNamedValue("llvm.objc.autoreleasePoolPush") || | ||
M.getNamedValue("llvm.objc.loadWeakRetained") || | ||
M.getNamedValue("llvm.objc.loadWeak") || | ||
M.getNamedValue("llvm.objc.destroyWeak") || | ||
M.getNamedValue("llvm.objc.storeWeak") || | ||
M.getNamedValue("llvm.objc.initWeak") || | ||
M.getNamedValue("llvm.objc.moveWeak") || | ||
M.getNamedValue("llvm.objc.copyWeak") || | ||
M.getNamedValue("llvm.objc.retainedObject") || | ||
M.getNamedValue("llvm.objc.unretainedObject") || | ||
M.getNamedValue("llvm.objc.unretainedPointer") || | ||
M.getNamedValue("llvm.objc.clang.arc.use"); | ||
return M.getNamedValue("llvm.objc.retain") || | ||
M.getNamedValue("llvm.objc.release") || | ||
M.getNamedValue("llvm.objc.autorelease") || | ||
M.getNamedValue("llvm.objc.retainAutoreleasedReturnValue") || | ||
M.getNamedValue("llvm.objc.unsafeClaimAutoreleasedReturnValue") || | ||
M.getNamedValue("llvm.objc.retainBlock") || | ||
M.getNamedValue("llvm.objc.autoreleaseReturnValue") || | ||
M.getNamedValue("llvm.objc.autoreleasePoolPush") || | ||
M.getNamedValue("llvm.objc.loadWeakRetained") || | ||
M.getNamedValue("llvm.objc.loadWeak") || | ||
M.getNamedValue("llvm.objc.destroyWeak") || | ||
M.getNamedValue("llvm.objc.storeWeak") || | ||
M.getNamedValue("llvm.objc.initWeak") || | ||
M.getNamedValue("llvm.objc.moveWeak") || | ||
M.getNamedValue("llvm.objc.copyWeak") || | ||
M.getNamedValue("llvm.objc.retainedObject") || | ||
M.getNamedValue("llvm.objc.unretainedObject") || | ||
M.getNamedValue("llvm.objc.unretainedPointer") || | ||
M.getNamedValue("llvm.objc.clang.arc.noop.use") || | ||
M.getNamedValue("llvm.objc.clang.arc.use"); | ||
} | ||
|
||
/// This is a wrapper around getUnderlyingObject which also knows how to | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
#include "ProvenanceAnalysis.h" | ||
#include "llvm/ADT/Statistic.h" | ||
#include "llvm/Analysis/AliasAnalysis.h" | ||
#include "llvm/Analysis/BasicAliasAnalysis.h" | ||
#include "llvm/Analysis/ObjCARCUtil.h" | ||
#include "llvm/IR/Dominators.h" | ||
#include "llvm/IR/EHPersonalities.h" | ||
|
@@ -71,6 +72,9 @@ class ObjCARCContract { | |
ARCRuntimeEntryPoints EP; | ||
BundledRetainClaimRVs *BundledInsts = nullptr; | ||
|
||
/// A flag indicating whether this optimization pass should run. | ||
bool Run; | ||
|
||
/// The inline asm string to insert between calls and RetainRV calls to make | ||
/// the optimization work on targets which need it. | ||
const MDString *RVInstMarker; | ||
|
@@ -527,6 +531,10 @@ bool ObjCARCContract::tryToPeepholeInstruction( | |
//===----------------------------------------------------------------------===// | ||
|
||
bool ObjCARCContract::init(Module &M) { | ||
Run = ModuleHasARC(M); | ||
if (!Run) | ||
return false; | ||
|
||
EP.init(&M); | ||
|
||
// Initialize RVInstMarker. | ||
|
@@ -536,6 +544,9 @@ bool ObjCARCContract::init(Module &M) { | |
} | ||
|
||
bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) { | ||
if (!Run) | ||
return false; | ||
|
||
if (!EnableARCOpts) | ||
return false; | ||
|
||
|
@@ -730,6 +741,9 @@ INITIALIZE_PASS_END(ObjCARCContractLegacyPass, "objc-arc-contract", | |
void ObjCARCContractLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { | ||
AU.addRequired<AAResultsWrapperPass>(); | ||
AU.addRequired<DominatorTreeWrapperPass>(); | ||
AU.addPreserved<AAResultsWrapperPass>(); | ||
AU.addPreserved<BasicAAWrapperPass>(); | ||
AU.addPreserved<DominatorTreeWrapperPass>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also add AAResultsWrapper and BasicAAWrapperPass here? I think that should avoid some more pipeline diffs. |
||
} | ||
|
||
Pass *llvm::createObjCARCContractPass() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cachemeifyoucan As far as I can tell, it's already the case that for non-LTO builds, this pass is only added for optimization level > 0. Is that ok to do for all builds?
I checked and directly providing clang with IR that contains
llvm.objc.clang.arc.use
and compiling it with-O0
fails instruction selection as a result of not running this pass, so I'm assuming these intrinsics are only introduced at-O1
or higher.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ahatanak probably know better. I think when the arc intrinsics are present, the pass is mandatory but I am not sure if the intrinsics are only produced for -O1 and higher.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't run this optimization on
O0
has been there since LLVM 3.1 (1170b08). The committer @sunfishcode probably did it for a reasonThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intrinsic calls are needed to prevent ARC optimizer from moving releases to an earlier point that can cause objects to be deallocated prematurely. clang doesn't emit the intrinsic calls if
OptimizationLevel
is zero.