mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
switch the frontend to generate swift_retain_noresult calls instead of
swift_retain calls. The pertinent difference is that the former can be marked nocapture, allowing general LLVM optimizations more flexibility. With this change, early-cse is able to zap 9 more instructions, and 3 more functions are able to be marked nocapture by functionattrs in the stdlib. Swift SVN r2043
This commit is contained in:
@@ -478,30 +478,21 @@ static bool doesNotRequireRefCounting(llvm::Value *value) {
|
||||
return isa<llvm::Constant>(value);
|
||||
}
|
||||
|
||||
/// Emit a call to swift_retain. In general, you should not be using
|
||||
/// Emit a call to swift_retain_noresult. In general, you should not be using
|
||||
/// this routine; instead you should use emitRetain, which properly
|
||||
/// balances the retain.
|
||||
llvm::Value *IRGenFunction::emitRetainCall(llvm::Value *value) {
|
||||
// Instead of casting the input, retaining, and casting back, we
|
||||
// cast the function to the right type. This tends to produce less
|
||||
// IR, but it might be evil.
|
||||
llvm::Constant *fn = IGM.getRetainFn();
|
||||
if (value->getType() != IGM.RefCountedPtrTy) {
|
||||
llvm::FunctionType *fnType =
|
||||
llvm::FunctionType::get(value->getType(), value->getType(), false);
|
||||
fn = llvm::ConstantExpr::getBitCast(fn, fnType->getPointerTo());
|
||||
}
|
||||
|
||||
void IRGenFunction::emitRetainCall(llvm::Value *value) {
|
||||
// Make sure the input pointer is the right type.
|
||||
if (value->getType() != IGM.RefCountedPtrTy)
|
||||
value = Builder.CreateBitCast(value, IGM.RefCountedPtrTy);
|
||||
|
||||
// Emit the call.
|
||||
llvm::CallInst *call = Builder.CreateCall(fn, value);
|
||||
call->setDoesNotThrow();
|
||||
|
||||
return call;
|
||||
Builder.CreateCall(IGM.getRetainNoResultFn(), value);
|
||||
}
|
||||
|
||||
static void emitRetainAndManage(IRGenFunction &IGF, llvm::Value *value,
|
||||
Explosion &out) {
|
||||
value = IGF.emitRetainCall(value);
|
||||
IGF.emitRetainCall(value);
|
||||
out.add(IGF.enterReleaseCleanup(value));
|
||||
}
|
||||
|
||||
|
||||
@@ -1304,7 +1304,7 @@ static llvm::Constant *getAssignWithCopyStrongFunction(IRGenModule &IGM) {
|
||||
Address src(it++, IGM.getPointerAlignment());
|
||||
|
||||
llvm::Value *newValue = IGF.Builder.CreateLoad(src, "new");
|
||||
newValue = IGF.emitRetainCall(newValue);
|
||||
IGF.emitRetainCall(newValue);
|
||||
llvm::Value *oldValue = IGF.Builder.CreateLoad(dest, "old");
|
||||
IGF.Builder.CreateStore(newValue, dest);
|
||||
IGF.emitRelease(oldValue);
|
||||
@@ -1362,7 +1362,7 @@ static llvm::Constant *getInitWithCopyStrongFunction(IRGenModule &IGM) {
|
||||
Address src(it++, IGM.getPointerAlignment());
|
||||
|
||||
llvm::Value *newValue = IGF.Builder.CreateLoad(src, "new");
|
||||
newValue = IGF.emitRetainCall(newValue);
|
||||
IGF.emitRetainCall(newValue);
|
||||
IGF.Builder.CreateStore(newValue, dest);
|
||||
|
||||
IGF.Builder.CreateRet(dest.getAddress());
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
IGF.emitRelease(value);
|
||||
}
|
||||
|
||||
llvm::Value *emitScalarRetain(IRGenFunction &IGF, llvm::Value *value) const {
|
||||
return IGF.emitRetainCall(value);
|
||||
void emitScalarRetain(IRGenFunction &IGF, llvm::Value *value) const {
|
||||
IGF.emitRetainCall(value);
|
||||
}
|
||||
|
||||
void enterScalarCleanup(IRGenFunction &IGF, llvm::Value *value,
|
||||
|
||||
@@ -260,7 +260,7 @@ public:
|
||||
void emitAssignRetained(llvm::Value *value, Address addr);
|
||||
void emitInitializeRetained(llvm::Value *value, Address addr);
|
||||
void emitRetain(llvm::Value *value, Explosion &explosion);
|
||||
llvm::Value *emitRetainCall(llvm::Value *value);
|
||||
void emitRetainCall(llvm::Value *value);
|
||||
void emitRelease(llvm::Value *value);
|
||||
ManagedValue enterReleaseCleanup(llvm::Value *value);
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ IRGenModule::IRGenModule(ASTContext &Context,
|
||||
SizeTy = TargetData.getIntPtrType(getLLVMContext());
|
||||
MemCpyFn = nullptr;
|
||||
AllocObjectFn = nullptr;
|
||||
RetainFn = nullptr;
|
||||
RetainNoResultFn = nullptr;
|
||||
ReleaseFn = nullptr;
|
||||
DeallocObjectFn = nullptr;
|
||||
ObjCRetainFn = nullptr;
|
||||
@@ -154,19 +154,24 @@ llvm::Constant *IRGenModule::getSlowRawDeallocFn() {
|
||||
return SlowRawDeallocFn;
|
||||
}
|
||||
|
||||
llvm::Constant *IRGenModule::getRetainFn() {
|
||||
if (RetainFn) return RetainFn;
|
||||
llvm::Constant *IRGenModule::getRetainNoResultFn() {
|
||||
if (RetainNoResultFn) return RetainNoResultFn;
|
||||
|
||||
RetainFn = Module.getOrInsertFunction("swift_retain", RefCountedPtrTy,
|
||||
RefCountedPtrTy, NULL);
|
||||
return RetainFn;
|
||||
llvm::AttributeWithIndex Attrs[] = {
|
||||
{ llvm::Attribute::NoCapture, 1 },
|
||||
{ llvm::Attribute::NoUnwind, ~0U },
|
||||
};
|
||||
auto AttrList = llvm::AttrListPtr::get(Attrs);
|
||||
return RetainNoResultFn =
|
||||
Module.getOrInsertFunction("swift_retain_noresult", AttrList,
|
||||
VoidTy, RefCountedPtrTy, NULL);
|
||||
}
|
||||
|
||||
llvm::Constant *IRGenModule::getReleaseFn() {
|
||||
if (ReleaseFn) return ReleaseFn;
|
||||
|
||||
llvm::AttributeWithIndex AttrList[] = {
|
||||
llvm::AttributeWithIndex::get(1, llvm::Attribute::NoCapture)
|
||||
{ llvm::Attribute::NoCapture, 1 },
|
||||
};
|
||||
auto Attrs = llvm::AttrListPtr::get(AttrList);
|
||||
ReleaseFn = Module.getOrInsertFunction("swift_release", Attrs, VoidTy,
|
||||
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
//--- Runtime ---------------------------------------------------------------
|
||||
public:
|
||||
llvm::Constant *getAllocObjectFn();
|
||||
llvm::Constant *getRetainFn();
|
||||
llvm::Constant *getRetainNoResultFn();
|
||||
llvm::Constant *getReleaseFn();
|
||||
llvm::Constant *getDeallocObjectFn();
|
||||
|
||||
@@ -146,7 +146,7 @@ public:
|
||||
private:
|
||||
llvm::Function *MemCpyFn;
|
||||
llvm::Constant *AllocObjectFn;
|
||||
llvm::Constant *RetainFn;
|
||||
llvm::Constant *RetainNoResultFn;
|
||||
llvm::Constant *ReleaseFn;
|
||||
llvm::Constant *ObjCRetainFn;
|
||||
llvm::Constant *ObjCReleaseFn;
|
||||
|
||||
@@ -157,7 +157,10 @@ static bool canonicalizeArgumentReturnFunctions(Function &F) {
|
||||
}
|
||||
case RT_Retain: {
|
||||
// If any x = swift_retain(y)'s got here, canonicalize them into:
|
||||
// x = y; swift_retain_noresult(y).
|
||||
// x = y; swift_retain_noresult(y).
|
||||
// This is important even though the front-end doesn't generate them,
|
||||
// because inlined functions can be ARC optimized, and thus may contain
|
||||
// swift_retain calls.
|
||||
CallInst &CI = cast<CallInst>(Inst);
|
||||
Value *ArgVal = CI.getArgOperand(0);
|
||||
|
||||
@@ -505,6 +508,7 @@ llvm::FunctionPass *swift::irgen::createSwiftARCOptPass() {
|
||||
|
||||
bool SwiftARCOpt::runOnFunction(Function &F) {
|
||||
bool Changed = false;
|
||||
|
||||
// First thing: canonicalize swift_retain and similar calls so that nothing
|
||||
// uses their result. This exposes the copy that the function does to the
|
||||
// optimizer.
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
// Explosion &out) const;
|
||||
|
||||
// Make the scalar +1.
|
||||
// llvm::Value *emitScalarRetain(IRGenFunction &IGF, llvm::Value *value) const;
|
||||
// void emitScalarRetain(IRGenFunction &IGF, llvm::Value *value) const;
|
||||
|
||||
// Make the scalar -1.
|
||||
// void emitScalarRelease(IRGenFunction &IGF, llvm::Value *value) const;
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
void load(IRGenFunction &IGF, Address addr, Explosion &out) const {
|
||||
addr = asDerived().projectScalar(IGF, addr);
|
||||
llvm::Value *value = IGF.Builder.CreateLoad(addr);
|
||||
value = asDerived().emitScalarRetain(IGF, value);
|
||||
asDerived().emitScalarRetain(IGF, value);
|
||||
asDerived().enterScalarCleanup(IGF, value, out);
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
|
||||
void copy(IRGenFunction &IGF, Explosion &in, Explosion &out) const {
|
||||
llvm::Value *value = in.claimNext().getValue();
|
||||
value = asDerived().emitScalarRetain(IGF, value);
|
||||
asDerived().emitScalarRetain(IGF, value);
|
||||
asDerived().enterScalarCleanup(IGF, value, out);
|
||||
}
|
||||
|
||||
@@ -189,8 +189,7 @@ private:
|
||||
out.addUnmanaged(value);
|
||||
}
|
||||
|
||||
llvm::Value *emitScalarRetain(IRGenFunction &IGF, llvm::Value *value) const {
|
||||
return value;
|
||||
void emitScalarRetain(IRGenFunction &IGF, llvm::Value *value) const {
|
||||
}
|
||||
|
||||
void emitScalarRelease(IRGenFunction &IGF, llvm::Value *value) const {
|
||||
|
||||
Reference in New Issue
Block a user