Completely replace swift_retain_noresult with swift_retain. this is part of a series of commits

to remove reference forwarding for some of the ARC entry points. rdar://22724641. After this
commit, swift_retain_noresult will be completely replaced by swift_retain and LLVMARCOpts.cpp
will no longer canonicalize swift_retain to swift_retain_noresult as now swift_retain returns no
reference.

Swift SVN r32058
This commit is contained in:
Xin Tong
2015-09-18 01:51:17 +00:00
parent db77b54b3c
commit 4e46dacc3d
22 changed files with 79 additions and 156 deletions

View File

@@ -147,8 +147,6 @@ extern "C" void swift_slowDealloc(void *ptr, size_t bytes, size_t alignMask);
/// It may also prove worthwhile to have this use a custom CC
/// which preserves a larger set of registers.
extern "C" void swift_retain(HeapObject *object);
extern "C" void swift_retain_noresult(HeapObject *object);
extern "C" void swift_retain_n(HeapObject *object, uint32_t n);
static inline void _swift_retain_inlined(HeapObject *object) {

View File

@@ -791,7 +791,7 @@ static void emitStoreWeakLikeCall(IRGenFunction &IGF,
call->setDoesNotThrow();
}
/// Emit a call to swift_retain_noresult. In general, you should not be using
/// Emit a call to swift_retain. In general, you should not be using
/// this routine; instead you should use emitRetain, which properly
/// balances the retain.
void IRGenFunction::emitRetainCall(llvm::Value *value) {
@@ -800,7 +800,7 @@ void IRGenFunction::emitRetainCall(llvm::Value *value) {
value = Builder.CreateBitCast(value, IGM.RefCountedPtrTy);
// Emit the call.
llvm::CallInst *call = Builder.CreateCall(IGM.getRetainNoResultFn(), value);
llvm::CallInst *call = Builder.CreateCall(IGM.getRetainFn(), value);
call->setCallingConv(IGM.RuntimeCC);
call->setDoesNotThrow();
}

View File

@@ -113,8 +113,8 @@ FUNCTION(CopyPOD, swift_copyPOD, RuntimeCC,
ARGS(OpaquePtrTy, OpaquePtrTy, TypeMetadataPtrTy),
ATTRS(NoUnwind))
// void swift_retain_noresult(void *ptr);
FUNCTION(RetainNoResult, swift_retain_noresult, RuntimeCC,
// void swift_retain(void *ptr);
FUNCTION(Retain, swift_retain, RuntimeCC,
RETURNS(VoidTy),
ARGS(RefCountedPtrTy),
ATTRS(NoUnwind))

View File

@@ -41,7 +41,6 @@ class ARCEntryPointBuilder {
// The constant cache.
NullablePtr<Constant> Retain;
NullablePtr<Constant> RetainNoResult;
NullablePtr<Constant> CheckUnowned;
NullablePtr<Constant> RetainN;
NullablePtr<Constant> ReleaseN;
@@ -50,8 +49,7 @@ class ARCEntryPointBuilder {
NullablePtr<Type> ObjectPtrTy;
public:
ARCEntryPointBuilder(Function &F) : B(F.begin()), Retain(), RetainNoResult(),
ObjectPtrTy() {}
ARCEntryPointBuilder(Function &F) : B(F.begin()), Retain(), ObjectPtrTy() {}
~ARCEntryPointBuilder() = default;
ARCEntryPointBuilder(ARCEntryPointBuilder &&) = delete;
ARCEntryPointBuilder(const ARCEntryPointBuilder &) = delete;
@@ -63,11 +61,6 @@ public:
B.SetInsertPoint(I);
}
CallInst *createRetainNoResult(Value *V) {
V = B.CreatePointerCast(V, getObjectPtrTy());
return B.CreateCall(getRetainNoResult(), V);
}
Value *createInsertValue(Value *V1, Value *V2, unsigned Idx) {
return B.CreateInsertValue(V1, V2, Idx);
}
@@ -135,21 +128,6 @@ private:
return Retain.get();
}
/// getRetainNoResult - Return a callable function for swift_retain_noresult.
Constant *getRetainNoResult() {
if (RetainNoResult)
return RetainNoResult.get();
auto *ObjectPtrTy = getObjectPtrTy();
auto &M = getModule();
auto AttrList = AttributeSet::get(M.getContext(), 1, Attribute::NoCapture);
AttrList = AttrList.addAttribute(
M.getContext(), AttributeSet::FunctionIndex, Attribute::NoUnwind);
RetainNoResult = M.getOrInsertFunction(
"swift_retain_noresult", AttrList,
Type::getVoidTy(M.getContext()), ObjectPtrTy, nullptr);
return RetainNoResult.get();
}
Constant *getCheckUnowned() {
if (CheckUnowned)
return CheckUnowned.get();

View File

@@ -138,9 +138,7 @@ bool SwiftARCContractImpl::run() {
Inst.eraseFromParent();
++NumNoopDeleted;
continue;
case RT_Retain:
llvm_unreachable("This should be canonicalized away!");
case RT_RetainNoResult: {
case RT_Retain: {
auto *CI = cast<CallInst>(&Inst);
auto *ArgVal = CI->getArgOperand(0);

View File

@@ -70,7 +70,7 @@ DisableARCOpts("disable-llvm-arc-opts", llvm::cl::init(false));
/// argument as a low-level performance optimization. This makes it difficult
/// to reason about pointer equality though, so undo it as an initial
/// canonicalization step. After this step, all swift_retain's have been
/// replaced with swift_retain_noresult.
/// replaced with swift_retain.
///
/// This also does some trivial peep-hole optimizations as we go.
static bool canonicalizeInputFunction(Function &F, ARCEntryPointBuilder &B) {
@@ -88,41 +88,11 @@ static bool canonicalizeInputFunction(Function &F, ARCEntryPointBuilder &B) {
case RT_RetainUnowned:
case RT_CheckUnowned:
break;
case RT_RetainNoResult: {
CallInst &CI = cast<CallInst>(Inst);
Value *ArgVal = CI.getArgOperand(0);
// retain_noresult(null) is a no-op.
if (isa<ConstantPointerNull>(ArgVal)) {
CI.eraseFromParent();
Changed = true;
++NumNoopDeleted;
continue;
}
break;
}
case RT_Retain: {
// If any x = swift_retain(y)'s got here, canonicalize them into:
// 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);
// Rewrite uses of the result to use the argument.
if (!CI.use_empty())
Inst.replaceAllUsesWith(ArgVal);
B.setInsertPoint(&CI);
I = B.createRetainNoResult(ArgVal);
CI.eraseFromParent();
Changed = true;
break;
}
case RT_Retain:
case RT_Release:
case RT_UnknownRelease: {
CallInst &CI = cast<CallInst>(Inst);
// swift_release(null) is a noop, zap it.
// swift_retain(null), swift_release(null) is a noop, zap it.
Value *ArgVal = CI.getArgOperand(0);
if (isa<ConstantPointerNull>(ArgVal)) {
CI.eraseFromParent();
@@ -203,8 +173,6 @@ static bool performLocalReleaseMotion(CallInst &Release, BasicBlock &BB) {
}
switch (classifyInstruction(*BBI)) {
case RT_Retain: // Canonicalized away, shouldn't exist.
llvm_unreachable("these entrypoints should be canonicalized away");
case RT_NoMemoryAccessed:
// Skip over random instructions that don't touch memory. They don't need
// protection by retain/release.
@@ -234,7 +202,7 @@ static bool performLocalReleaseMotion(CallInst &Release, BasicBlock &BB) {
case RT_UnknownRetain:
case RT_BridgeRetain:
case RT_ObjCRetain:
case RT_RetainNoResult: { // swift_retain_noresult(obj)
case RT_Retain: { // swift_retain(obj)
CallInst &Retain = cast<CallInst>(*BBI);
Value *RetainedObject = Retain.getArgOperand(0);
@@ -321,7 +289,7 @@ OutOfLoop:
/// later in the function if possible, over instructions that provably can't
/// release the object. If we get to a release of the object, zap both.
///
/// NOTE: this handles both objc_retain and swift_retain_noresult.
/// NOTE: this handles both objc_retain and swift_retain.
///
static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB) {
// FIXME: Call classifier should identify the object for us. Too bad C++
@@ -342,8 +310,6 @@ static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB) {
// can be skipped and is interesting, and a "continue" when it is a retain
// of the same pointer.
switch (classifyInstruction(CurInst)) {
case RT_Retain: // Canonicalized away, shouldn't exist.
llvm_unreachable("these entrypoints should be canonicalized away");
case RT_NoMemoryAccessed:
case RT_AllocObject:
case RT_CheckUnowned:
@@ -354,11 +320,11 @@ static bool performLocalRetainMotion(CallInst &Retain, BasicBlock &BB) {
case RT_FixLifetime: // This only stops release motion. Retains can move over it.
break;
case RT_RetainNoResult:
case RT_Retain:
case RT_UnknownRetain:
case RT_BridgeRetain:
case RT_RetainUnowned:
case RT_ObjCRetain: { // swift_retain_noresult(obj)
case RT_ObjCRetain: { // swift_retain(obj)
//CallInst &ThisRetain = cast<CallInst>(CurInst);
//Value *ThisRetainedObject = ThisRetain.getArgOperand(0);
@@ -490,10 +456,9 @@ static DtorKind analyzeDestructor(Value *P) {
// Skip over random instructions that don't touch memory in the caller.
continue;
case RT_Retain: // x = swift_retain(y)
case RT_RetainUnowned:
case RT_BridgeRetain: // x = swift_bridgeRetain(y)
case RT_RetainNoResult: { // swift_retain_noresult(obj)
case RT_Retain: { // swift_retain(obj)
// Ignore retains of the "self" object, no ressurection is possible.
Value *ThisRetainedObject = cast<CallInst>(I).getArgOperand(0);
@@ -587,9 +552,6 @@ static bool performStoreOnlyObjectElimination(CallInst &Allocation,
// Okay, this is the first time we've seen this instruction, proceed.
switch (classifyInstruction(*I)) {
case RT_Retain:
llvm_unreachable("These should be canonicalized away");
case RT_AllocObject:
// If this is a different swift_allocObject than we started with, then
// there is some computation feeding into a size or alignment computation
@@ -608,7 +570,7 @@ static bool performStoreOnlyObjectElimination(CallInst &Allocation,
break;
case RT_Release:
case RT_RetainNoResult:
case RT_Retain:
case RT_FixLifetime:
case RT_CheckUnowned:
// It is perfectly fine to eliminate various retains and releases of this
@@ -761,7 +723,7 @@ static void performRedundantCheckUnownedRemoval(BasicBlock &BB) {
case RT_NoMemoryAccessed:
case RT_AllocObject:
case RT_FixLifetime:
case RT_RetainNoResult:
case RT_Retain:
case RT_UnknownRetain:
case RT_BridgeRetain:
case RT_RetainUnowned:
@@ -821,7 +783,7 @@ static bool performGeneralOptimizations(Function &F, ARCEntryPointBuilder &B) {
Changed |= performLocalReleaseMotion(cast<CallInst>(I), BB);
break;
case RT_BridgeRetain:
case RT_RetainNoResult:
case RT_Retain:
case RT_UnknownRetain:
case RT_ObjCRetain: {
// Retain motion is a forward pass over the block. Make sure we don't

View File

@@ -31,9 +31,6 @@ enum RT_Kind {
/// void swift_checkUnowned(HeapObject *object)
RT_CheckUnowned,
// void swift_retain_noresult(SwiftHeapObject *object)
RT_RetainNoResult,
/// void swift_release(SwiftHeapObject *object)
RT_Release,
@@ -81,7 +78,6 @@ inline RT_Kind classifyInstruction(const llvm::Instruction &I) {
return llvm::StringSwitch<RT_Kind>(F->getName())
.Case("swift_retain", RT_Retain)
.Case("swift_retain_noresult", RT_RetainNoResult)
.Case("swift_release", RT_Release)
.Case("swift_allocObject", RT_AllocObject)
.Case("objc_release", RT_ObjCRelease)

View File

@@ -37,7 +37,6 @@ SwiftAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
case RT_Retain:
case RT_RetainUnowned:
case RT_CheckUnowned:
case RT_RetainNoResult:
case RT_ObjCRetain:
case RT_BridgeRetain:
case RT_UnknownRetain:

View File

@@ -941,7 +941,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
auto object = *(reinterpret_cast<HeapObject**>(srcDynamicValue));
destExistential->Value = object;
if (!canTake || !(flags & DynamicCastFlags::TakeOnSuccess)) {
swift_retain_noresult(object);
swift_retain(object);
}
maybeDeallocateSourceAfterSuccess();
return true;

View File

@@ -276,11 +276,6 @@ extern "C" LLVM_LIBRARY_VISIBILITY
void _swift_release_dealloc(HeapObject *object)
__attribute__((noinline,used));
void
swift::swift_retain_noresult(HeapObject *object) {
swift_retain(object);
}
void swift::swift_retain(HeapObject *object) {
SWIFT_RETAIN();
_swift_retain(object);

View File

@@ -143,7 +143,7 @@ func assign_test(value: Builtin.Int64, ptr: Builtin.RawPointer) {
// CHECK: define hidden %swift.refcounted* @_TF8builtins16load_object_test
func load_object_test(ptr: Builtin.RawPointer) -> Builtin.NativeObject {
// CHECK: [[T0:%.*]] = load [[REFCOUNT]]*, [[REFCOUNT]]**
// CHECK: call void @swift_retain_noresult([[REFCOUNT]]* [[T0]])
// CHECK: call void @swift_retain([[REFCOUNT]]* [[T0]])
// CHECK: ret [[REFCOUNT]]* [[T0]]
return Builtin.load(ptr)
}
@@ -453,7 +453,7 @@ func copyPODArray(dest: Builtin.RawPointer, src: Builtin.RawPointer, count: Buil
// CHECK-LABEL: define hidden void @_TF8builtins11copyBTArray{{.*}}(i8*, i8*, i64) {{.*}} {
// CHECK: iter:
// CHECK: loop:
// CHECK: call {{.*}} @swift_retain_noresult
// CHECK: call {{.*}} @swift_retain
// CHECK: br label %iter
// CHECK: mul nuw i64 8, %2
// CHECK: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 8, i1 false)

View File

@@ -40,7 +40,7 @@ func b<T : Ordinable>(var seq seq: T) -> (Int) -> Int {
// CHECK: [[WITNESS:%.*]] = load i8**, i8*** [[WITNESSADDR]], align 8
// CHECK: [[BOXADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [16 x i8], %swift.refcounted*, %swift.opaque* }>, <{ %swift.refcounted, [16 x i8], %swift.refcounted*, %swift.opaque* }>* [[CONTEXT]], i32 0, i32 2
// CHECK: [[BOX:%.*]] = load %swift.refcounted*, %swift.refcounted** [[BOXADDR]], align 8
// CHECK: call void @swift_retain_noresult(%swift.refcounted* [[BOX]])
// CHECK: call void @swift_retain(%swift.refcounted* [[BOX]])
// CHECK: [[ADDRADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [16 x i8], %swift.refcounted*, %swift.opaque* }>, <{ %swift.refcounted, [16 x i8], %swift.refcounted*, %swift.opaque* }>* [[CONTEXT]], i32 0, i32 3
// CHECK: [[ADDR:%.*]] = load %swift.opaque*, %swift.opaque** [[ADDRADDR]], align 8
// CHECK: call void @swift_release(%swift.refcounted* %1)

View File

@@ -20,7 +20,7 @@ bb0(%0 : $Optional<() -> ()>):
// CHECK: br i1 [[T0]], label
// CHECK: [[FNPTR:%.*]] = inttoptr [[WORD]] %0 to i8*
// CHECK: [[CTX:%.*]] = inttoptr [[WORD]] %1 to %swift.refcounted*
// CHECK: call void @swift_retain_noresult(%swift.refcounted* [[CTX]])
// CHECK: call void @swift_retain(%swift.refcounted* [[CTX]])
// CHECK: br label
retain_value %0 : $Optional<() -> ()>

View File

@@ -124,7 +124,7 @@ bb0(%0 : $SinglePayloadNontrivial):
// CHECK-NEXT: i64 4, label [[NOT_PRESENT]]
// CHECK-NEXT: ]
// CHECK: [[T0:%.*]] = inttoptr i64 [[V:%.*]] to %swift.refcounted*
// CHECK-NEXT: call void @swift_retain_noresult(%swift.refcounted* [[T0]])
// CHECK-NEXT: call void @swift_retain(%swift.refcounted* [[T0]])
// CHECK-NEXT: br label [[NOT_PRESENT]]
// CHECK: switch i64 %0, label [[PRESENT:%.*]] [
// CHECK-NEXT: i64 0, label [[NOT_PRESENT:%.*]]

View File

@@ -30,7 +30,7 @@ enum NullableRefcounted {
// CHECK: %2 = bitcast %O34enum_value_semantics_special_cases18NullableRefcounted* %0 to %swift.refcounted**
// CHECK: %3 = bitcast %O34enum_value_semantics_special_cases18NullableRefcounted* %1 to %swift.refcounted**
// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %3, align 8
// CHECK: call void @swift_retain_noresult(%swift.refcounted* %4) {{#[0-9]+}}
// CHECK: call void @swift_retain(%swift.refcounted* %4) {{#[0-9]+}}
// CHECK: store %swift.refcounted* %4, %swift.refcounted** %2, align 8
// CHECK: %5 = bitcast %O34enum_value_semantics_special_cases18NullableRefcounted* %0 to %swift.opaque*
// CHECK: ret %swift.opaque* %5
@@ -44,7 +44,7 @@ enum NullableRefcounted {
// CHECK: %3 = bitcast %O34enum_value_semantics_special_cases18NullableRefcounted* %1 to %swift.refcounted**
// CHECK: %4 = load %swift.refcounted*, %swift.refcounted** %2, align 8
// CHECK: %5 = load %swift.refcounted*, %swift.refcounted** %3, align 8
// CHECK: call void @swift_retain_noresult(%swift.refcounted* %5) {{#[0-9]+}}
// CHECK: call void @swift_retain(%swift.refcounted* %5) {{#[0-9]+}}
// CHECK: store %swift.refcounted* %5, %swift.refcounted** %2, align 8
// CHECK: call void @swift_release(%swift.refcounted* %4) {{#[0-9]+}}
// CHECK: %6 = bitcast %O34enum_value_semantics_special_cases18NullableRefcounted* %0 to %swift.opaque*
@@ -140,7 +140,7 @@ enum AllRefcounted {
// -- 0x3fffffffffffffff
// CHECK: %4 = and i64 %3, 4611686018427387903
// CHECK: %5 = inttoptr i64 %4 to %swift.refcounted*
// CHECK: call void @swift_retain_noresult(%swift.refcounted* %5) #1
// CHECK: call void @swift_retain(%swift.refcounted* %5) #1
// CHECK: %6 = bitcast %O34enum_value_semantics_special_cases13AllRefcounted* %0 to i64*
// -- NB: The original loaded value is stored, not the masked one.
// CHECK: store i64 %3, i64* %6, align 8

View File

@@ -23,7 +23,7 @@ entry(%x : $@convention(thin) () -> ()):
// CHECK-LABEL: define { i8*, %swift.refcounted* } @thick_func_value(i8*, %swift.refcounted*) {{.*}} {
// CHECK-NEXT: entry:
// CHECK-NEXT: call void @swift_retain_noresult(%swift.refcounted* %1) {{#[0-9]+}}
// CHECK-NEXT: call void @swift_retain(%swift.refcounted* %1) {{#[0-9]+}}
// CHECK-NEXT: call void @swift_release(%swift.refcounted* %1) {{#[0-9]+}}
// CHECK-NEXT: %2 = insertvalue { i8*, %swift.refcounted* } undef, i8* %0, 0
// CHECK-NEXT: %3 = insertvalue { i8*, %swift.refcounted* } %2, %swift.refcounted* %1, 1

View File

@@ -63,7 +63,7 @@ func dupC<T : C>(let x: T) -> (T, T) { return (x, x) }
// CHECK-LABEL: define hidden { %C14generic_tuples1C*, %C14generic_tuples1C* } @_TF14generic_tuples4dupCuRdq_CS_1C_Fq_Tq_q__(%C14generic_tuples1C*, %swift.type* %T)
// CHECK-NEXT: entry:
// CHECK: [[REF:%.*]] = bitcast %C14generic_tuples1C* %0 to %swift.refcounted*
// CHECK-NEXT: call void @swift_retain_noresult(%swift.refcounted* [[REF]])
// CHECK-NEXT: call void @swift_retain(%swift.refcounted* [[REF]])
// CHECK-NEXT: [[TUP1:%.*]] = insertvalue { %C14generic_tuples1C*, %C14generic_tuples1C* } undef, %C14generic_tuples1C* %0, 0
// CHECK-NEXT: [[TUP2:%.*]] = insertvalue { %C14generic_tuples1C*, %C14generic_tuples1C* } [[TUP1:%.*]], %C14generic_tuples1C* %0, 1
// CHECK-NEXT: ret { %C14generic_tuples1C*, %C14generic_tuples1C* } [[TUP2]]
@@ -72,7 +72,7 @@ func callDupC(let c: C) { _ = dupC(c) }
// CHECK-LABEL: define hidden void @_TF14generic_tuples8callDupCFCS_1CT_(%C14generic_tuples1C*)
// CHECK-NEXT: entry:
// CHECK-NEXT: [[REF:%.*]] = bitcast %C14generic_tuples1C* %0 to %swift.refcounted*
// CHECK-NEXT: call void @swift_retain_noresult(%swift.refcounted* [[REF]])
// CHECK-NEXT: call void @swift_retain(%swift.refcounted* [[REF]])
// CHECK-NEXT: [[METATYPE:%.*]] = call %swift.type* @_TMaC14generic_tuples1C()
// CHECK-NEXT: [[TUPLE:%.*]] = call { %C14generic_tuples1C*, %C14generic_tuples1C* } @_TF14generic_tuples4dupCuRdq_CS_1C_Fq_Tq_q__(%C14generic_tuples1C* %0, %swift.type* [[METATYPE]])
// CHECK-NEXT: [[LEFT:%.*]] = extractvalue { %C14generic_tuples1C*, %C14generic_tuples1C* } [[TUPLE]], 0

View File

@@ -127,7 +127,7 @@ entry(%0 : $*@block_storage Builtin.NativeObject):
// CHECK-NEXT: %2 = getelementptr inbounds { %objc_block, %swift.refcounted* }, { %objc_block, %swift.refcounted* }* %0, i32 0, i32 1
// CHECK-NEXT: %3 = getelementptr inbounds { %objc_block, %swift.refcounted* }, { %objc_block, %swift.refcounted* }* %1, i32 0, i32 1
// CHECK-NEXT: %4 = load %swift.refcounted*, %swift.refcounted** %3, align 8
// CHECK-NEXT: call void @swift_retain_noresult(%swift.refcounted* %4) {{#[0-9]+}}
// CHECK-NEXT: call void @swift_retain(%swift.refcounted* %4) {{#[0-9]+}}
// CHECK-NEXT: store %swift.refcounted* %4, %swift.refcounted** %2, align 8
// CHECK-NEXT: ret void

View File

@@ -114,7 +114,7 @@ entry(%c : $ObjCClass):
// CHECK: [[DATA_ADDR:%.*]] = bitcast %swift.refcounted* %0 to [[DATA_TYPE]]*
// CHECK: [[X_ADDR:%.*]] = getelementptr inbounds [[DATA_TYPE]], [[DATA_TYPE]]* [[DATA_ADDR]], i32 0, i32 1
// CHECK: [[SELF:%.*]] = load %C13partial_apply9ObjCClass*, %C13partial_apply9ObjCClass** [[X_ADDR]], align 8
// CHECK: call void @swift_retain_noresult(%swift.refcounted* %4)
// CHECK: call void @swift_retain(%swift.refcounted* %4)
// CHECK: [[CMD:%.*]] = load i8*, i8** @"\01L_selector(initFamily)", align 8
// CHECK: [[I8PTRSELF:%.*]] = bitcast %C13partial_apply9ObjCClass* [[SELF]] to [[OPAQUE4:%.*]]*
// CHECK: call [[OPAQUE3:%.*]]* bitcast (void ()* @objc_msgSend to [[OPAQUE3]]* ([[OPAQUE4:%.*]]*, i8*)*)([[OPAQUE4]]* [[I8PTRSELF]], i8* [[CMD]])

View File

@@ -11,21 +11,20 @@ declare %objc_object* @objc_retain(%objc_object*)
declare void @objc_release(%objc_object*)
declare %swift.refcounted* @swift_allocObject(%swift.heapmetadata* , i64, i64) nounwind
declare void @swift_release(%swift.refcounted* nocapture)
declare %swift.refcounted* @swift_retain(%swift.refcounted* ) nounwind
declare void @swift_retain_noresult(%swift.refcounted* nocapture) nounwind
declare void @swift_retain(%swift.refcounted* ) nounwind
declare { i64, i64, i64 } @swift_retainAndReturnThree(%swift.refcounted* , i64, i64 , i64 )
; rdar://11542743
define i64 @max_test(i64 %x) nounwind {
entry:
%0 = tail call noalias %swift.refcounted* @swift_allocObject(%swift.heapmetadata* null, i64 24, i64 8) nounwind
%1 = tail call %swift.refcounted* @swift_retain(%swift.refcounted* %0) nounwind
tail call void @swift_retain(%swift.refcounted* %0) nounwind
tail call void @swift_release(%swift.refcounted* %0) nounwind
%1 = icmp sgt i64 %x, 0
%x.y.i = select i1 %1, i64 %x, i64 0
tail call void @swift_retain(%swift.refcounted* %0) nounwind
tail call void @swift_release(%swift.refcounted* %0) nounwind
tail call void @swift_release(%swift.refcounted* %0) nounwind
%2 = icmp sgt i64 %x, 0
%x.y.i = select i1 %2, i64 %x, i64 0
%3 = tail call %swift.refcounted* @swift_retain(%swift.refcounted* %1) nounwind
tail call void @swift_release(%swift.refcounted* %3) nounwind
tail call void @swift_release(%swift.refcounted* %1) nounwind
ret i64 %x.y.i
}
; CHECK: @max_test
@@ -68,7 +67,7 @@ define internal i64 @trivial_dtor2(%swift.refcounted* nocapture %this) nounwind
entry:
%0 = getelementptr inbounds %swift.refcounted, %swift.refcounted* %this, i64 1, i32 0
store %swift.heapmetadata* inttoptr (i64 4 to %swift.heapmetadata*), %swift.heapmetadata** %0, align 8
tail call %swift.refcounted* @swift_retain(%swift.refcounted* %this)
tail call void @swift_retain(%swift.refcounted* %this)
ret i64 48
}
define void @trivial_alloc_eliminate2(i64 %x) nounwind {

View File

@@ -14,8 +14,7 @@ declare %objc_object* @objc_retain(%objc_object*)
declare void @objc_release(%objc_object*)
declare %swift.refcounted* @swift_allocObject(%swift.heapmetadata* , i64, i64) nounwind
declare void @swift_release(%swift.refcounted* nocapture)
declare %swift.refcounted* @swift_retain(%swift.refcounted* ) nounwind
declare void @swift_retain_noresult(%swift.refcounted* nocapture) nounwind
declare void @swift_retain(%swift.refcounted* ) nounwind
declare void @swift_fixLifetime(%swift.refcounted* ) nounwind
declare %swift.bridge* @swift_bridgeObjectRetain(%swift.bridge*)
declare void @swift_bridgeObjectRelease(%swift.bridge*)
@@ -31,7 +30,7 @@ declare void @unknown_func()
define void @trivial_retain_release(%swift.refcounted* %P, %objc_object* %O, %swift.bridge * %B) {
entry:
tail call void @swift_retain_noresult(%swift.refcounted* %P)
tail call void @swift_retain(%swift.refcounted* %P)
tail call void @swift_release(%swift.refcounted* %P) nounwind
%0 = tail call %swift.refcounted* @swift_unknownRetain(%swift.refcounted* %P)
tail call void @swift_unknownRelease(%swift.refcounted* %P)
@@ -53,7 +52,7 @@ entry:
define void @retain_motion1(%swift.refcounted* %A) {
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
%B = bitcast %swift.refcounted* %A to i32*
store i32 42, i32* %B
tail call void @swift_release(%swift.refcounted* %A) nounwind
@@ -98,11 +97,11 @@ define void @objc_retain_release_opt(%objc_object* %P, i32* %IP) {
}
; CHECK-LABEL: define void @swift_fixLifetimeTest
; CHECK: swift_retain_noresult
; CHECK: swift_retain
; CHECK: swift_fixLifetime
; CHECK: swift_release
define void @swift_fixLifetimeTest(%swift.refcounted* %A) {
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A) nounwind
call void @swift_fixLifetime(%swift.refcounted* %A)
tail call void @swift_release(%swift.refcounted* %A) nounwind
@@ -115,7 +114,7 @@ define void @swift_fixLifetimeTest(%swift.refcounted* %A) {
; CHECK-NOT: swift_release
; CHECK: ret
define void @move_retain_across_unknown_retain(%swift.refcounted* %A, %swift.refcounted* %B) {
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
tail call %swift.refcounted* @swift_unknownRetain(%swift.refcounted* %B)
tail call void @swift_release(%swift.refcounted* %A) nounwind
ret void
@@ -127,7 +126,7 @@ define void @move_retain_across_unknown_retain(%swift.refcounted* %A, %swift.ref
; CHECK-NOT: swift_release
; CHECK: ret
define void @move_retain_across_objc_retain(%swift.refcounted* %A, %objc_object* %B) {
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
tail call %objc_object* @objc_retain(%objc_object* %B)
tail call void @swift_release(%swift.refcounted* %A) nounwind
ret void
@@ -138,7 +137,7 @@ define void @move_retain_across_objc_retain(%swift.refcounted* %A, %objc_object*
; CHECK-NOT: swift_release
; CHECK: ret
define i32 @move_retain_across_load(%swift.refcounted* %A, i32* %ptr) {
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
%val = load i32, i32* %ptr
tail call void @swift_release(%swift.refcounted* %A) nounwind
ret i32 %val
@@ -146,13 +145,13 @@ define i32 @move_retain_across_load(%swift.refcounted* %A, i32* %ptr) {
; CHECK-LABEL: @move_retain_but_not_release_across_objc_fix_lifetime
; CHECK: call void @swift_fixLifetime
; CHECK-NEXT: tail call void @swift_retain_noresult
; CHECK-NEXT: tail call void @swift_retain
; CHECK-NEXT: call void @user
; CHECK-NEXT: call void @swift_fixLifetime
; CHECK-NEXT: call void @swift_release
; CHECK-NEXT: ret
define void @move_retain_but_not_release_across_objc_fix_lifetime(%swift.refcounted* %A) {
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @swift_fixLifetime(%swift.refcounted* %A) nounwind
call void @user(%swift.refcounted* %A) nounwind
call void @swift_fixLifetime(%swift.refcounted* %A) nounwind
@@ -231,14 +230,14 @@ define void @dont_optimize_retain_unowned3(%swift.refcounted* %A) {
; CHECK-LABEL: @dont_optimize_retain_unowned4
; CHECK-NEXT: call void @swift_retainUnowned
; CHECK-NEXT: call void @swift_retain_noresult
; CHECK-NEXT: call void @swift_retain
; CHECK-NEXT: call void @swift_release
; CHECK-NEXT: ret
define void @dont_optimize_retain_unowned4(%swift.refcounted* %A, %swift.refcounted* %B) {
tail call void @swift_retainUnowned(%swift.refcounted* %A)
; retain of an unknown reference (%B could be equal to %A)
tail call void @swift_retain_noresult(%swift.refcounted* %B)
tail call void @swift_retain(%swift.refcounted* %B)
tail call void @swift_release(%swift.refcounted* %A)
ret void

View File

@@ -9,7 +9,6 @@ target triple = "x86_64-apple-macosx10.9"
declare %swift.refcounted* @swift_allocObject(%swift.heapmetadata* , i64, i64) nounwind
declare void @swift_release(%swift.refcounted* nocapture)
declare void @swift_retain(%swift.refcounted* ) nounwind
declare void @swift_retain_noresult(%swift.refcounted* nocapture) nounwind
declare void @swift_fixLifetime(%swift.refcounted*)
declare void @noread_user(%swift.refcounted*) readnone
declare void @user(%swift.refcounted*)
@@ -33,31 +32,31 @@ entry:
; CHECK-NEXT: br label %bb3
; CHECK: bb2:
; CHECK-NEXT: call void @noread_user(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: call void @noread_user(%swift.refcounted* %A)
; CHECK-NEXT: br label %bb3
; CHECK: bb3:
; CHECK-NEXT: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: ret %swift.refcounted* %A
define %swift.refcounted* @swift_contractRetainN(%swift.refcounted* %A) {
entry:
br i1 undef, label %bb1, label %bb2
bb1:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @noread_user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @noread_user(%swift.refcounted* %A)
br label %bb3
bb2:
call void @noread_user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @noread_user(%swift.refcounted* %A)
br label %bb3
bb3:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
ret %swift.refcounted* %A
}
@@ -109,20 +108,20 @@ entry:
br i1 undef, label %bb1, label %bb2
bb1:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
br label %bb3
bb2:
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
br label %bb3
bb3:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
ret %swift.refcounted* %A
}
@@ -153,7 +152,7 @@ bb3:
; But do make sure that we can form retainN, releaseN in between such uses
; CHECK-LABEL: define %swift.refcounted* @swift_contractRetainNInterleavedWithUnknown(%swift.refcounted* %A) {
; CHECK: bb1:
; CHECK: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: call void @user(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain_n(%swift.refcounted* %A, i32 3)
; CHECK-NEXT: call void @noread_user(%swift.refcounted* %A)
@@ -161,45 +160,45 @@ bb3:
; CHECK-NEXT: call void @user(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain_n(%swift.refcounted* %A, i32 2)
; CHECK-NEXT: call void @user(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: br label %bb3
; CHECK: bb2:
; CHECK-NEXT: call void @user(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: call void @user(%swift.refcounted* %A)
; CHECK-NEXT: br label %bb3
; CHECK: bb3:
; CHECK-NEXT: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: ret %swift.refcounted* %A
define %swift.refcounted* @swift_contractRetainNInterleavedWithUnknown(%swift.refcounted* %A) {
entry:
br i1 undef, label %bb1, label %bb2
bb1:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @noread_user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @noread_user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
br label %bb3
bb2:
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
br label %bb3
bb3:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
ret %swift.refcounted* %A
}
@@ -237,7 +236,7 @@ bb3:
; CHECK-LABEL: define %swift.refcounted* @swift_contractRetainReleaseNInterleavedWithUnknown(%swift.refcounted* %A) {
; CHECK: bb1:
; CHECK-NEXT: tail call void @swift_retain_noresult(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_retain(%swift.refcounted* %A)
; CHECK-NEXT: call void @user(%swift.refcounted* %A)
; CHECK-NEXT: call void @noread_user(%swift.refcounted* %A)
; CHECK-NEXT: tail call void @swift_release_n(%swift.refcounted* %A, i32 2)
@@ -263,14 +262,14 @@ entry:
br i1 undef, label %bb1, label %bb2
bb1:
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_release(%swift.refcounted* %A)
call void @noread_user(%swift.refcounted* %A)
tail call void @swift_release(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain_noresult(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
tail call void @swift_retain(%swift.refcounted* %A)
tail call void @swift_release(%swift.refcounted* %A)
call void @user(%swift.refcounted* %A)
tail call void @swift_release(%swift.refcounted* %A)