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:
Chris Lattner
2012-05-28 20:20:07 +00:00
parent 71b4f04ee3
commit 16cf77644f
8 changed files with 36 additions and 37 deletions

View File

@@ -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));
}

View File

@@ -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());

View File

@@ -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,

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;

View File

@@ -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.

View File

@@ -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 {