diff options
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 9 | ||||
-rw-r--r-- | lib/CodeGen/CGCleanup.cpp | 40 | ||||
-rw-r--r-- | lib/CodeGen/CGException.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 15 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 20 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 30 | ||||
-rw-r--r-- | test/CodeGenCXX/blocks.cpp | 2 | ||||
-rw-r--r-- | test/CodeGenCXX/exceptions.cpp | 18 | ||||
-rw-r--r-- | test/CodeGenCXX/goto.cpp | 2 | ||||
-rw-r--r-- | test/CodeGenObjC/arc-blocks.m | 2 |
11 files changed, 104 insertions, 45 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 9825c1ea69..e713492cc0 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -27,7 +27,8 @@ using namespace CodeGen; CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), - HasCXXObject(false), UsesStret(false), StructureType(0), Block(block) { + HasCXXObject(false), UsesStret(false), StructureType(0), Block(block), + DominatingIP(0) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -541,6 +542,10 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address, capture.getIndex()); + // We can use that GEP as the dominating IP. + if (!blockInfo.DominatingIP) + blockInfo.DominatingIP = cast<llvm::Instruction>(addr); + CleanupKind cleanupKind = InactiveNormalCleanup; bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind); if (useArrayEHCleanup) @@ -749,7 +754,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { if (!ci->isByRef()) { EHScopeStack::stable_iterator cleanup = capture.getCleanup(); if (cleanup.isValid()) - ActivateCleanupBlock(cleanup); + ActivateCleanupBlock(cleanup, blockInfo.DominatingIP); } } diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 69f3355084..095cfdb259 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -192,6 +192,15 @@ public: const BlockExpr *BlockExpression; CharUnits BlockSize; CharUnits BlockAlign; + + /// An instruction which dominates the full-expression that the + /// block is inside. + llvm::Instruction *DominatingIP; + + /// The next block in the block-info chain. Invalid if this block + /// info is not part of the CGF's block-info chain, which is true + /// if it corresponds to a global block or a block whose expression + /// has been encountered. CGBlockInfo *NextBlockInfo; const Capture &getCapture(const VarDecl *var) const { diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 9e079c65d2..f9ffc9373f 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -251,8 +251,7 @@ void CodeGenFunction::initFullExprCleanup() { // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - new llvm::StoreInst(Builder.getFalse(), active, &block->back()); + setBeforeOutermostConditional(Builder.getFalse(), active); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -1000,14 +999,15 @@ enum ForActivation_t { /// extra uses *after* the change-over point. static void SetupCleanupBlockActivation(CodeGenFunction &CGF, EHScopeStack::stable_iterator C, - ForActivation_t Kind) { + ForActivation_t kind, + llvm::Instruction *dominatingIP) { EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C)); // We always need the flag if we're activating the cleanup in a // conditional context, because we have to assume that the current // location doesn't necessarily dominate the cleanup's code. bool isActivatedInConditional = - (Kind == ForActivation && CGF.isInConditionalBranch()); + (kind == ForActivation && CGF.isInConditionalBranch()); bool needFlag = false; @@ -1030,32 +1030,44 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF, // If it hasn't yet been used as either, we're done. if (!needFlag) return; - llvm::AllocaInst *Var = Scope.getActiveFlag(); - if (!Var) { - Var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive"); - Scope.setActiveFlag(Var); + llvm::AllocaInst *var = Scope.getActiveFlag(); + if (!var) { + var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive"); + Scope.setActiveFlag(var); + + assert(dominatingIP && "no existing variable and no dominating IP!"); // Initialize to true or false depending on whether it was // active up to this point. - CGF.InitTempAlloca(Var, CGF.Builder.getInt1(Kind == ForDeactivation)); + llvm::Value *value = CGF.Builder.getInt1(kind == ForDeactivation); + + // If we're in a conditional block, ignore the dominating IP and + // use the outermost conditional branch. + if (CGF.isInConditionalBranch()) { + CGF.setBeforeOutermostConditional(value, var); + } else { + new llvm::StoreInst(value, var, dominatingIP); + } } - CGF.Builder.CreateStore(CGF.Builder.getInt1(Kind == ForActivation), Var); + CGF.Builder.CreateStore(CGF.Builder.getInt1(kind == ForActivation), var); } /// Activate a cleanup that was created in an inactivated state. -void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C) { +void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C, + llvm::Instruction *dominatingIP) { assert(C != EHStack.stable_end() && "activating bottom of stack?"); EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); assert(!Scope.isActive() && "double activation"); - SetupCleanupBlockActivation(*this, C, ForActivation); + SetupCleanupBlockActivation(*this, C, ForActivation, dominatingIP); Scope.setActive(true); } /// Deactive a cleanup that was created in an active state. -void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C) { +void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, + llvm::Instruction *dominatingIP) { assert(C != EHStack.stable_end() && "deactivating bottom of stack?"); EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); assert(Scope.isActive() && "double deactivation"); @@ -1071,7 +1083,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C) { } // Otherwise, follow the general case. - SetupCleanupBlockActivation(*this, C, ForDeactivation); + SetupCleanupBlockActivation(*this, C, ForDeactivation, dominatingIP); Scope.setActive(false); } diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 5e4fb98819..15fc6a1e59 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -359,7 +359,7 @@ static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e, /*IsInit*/ true); // Deactivate the cleanup block. - CGF.DeactivateCleanupBlock(cleanup); + CGF.DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr)); } llvm::Value *CodeGenFunction::getExceptionSlot() { diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index f3e86fbb44..bc8b0818ee 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -687,6 +687,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { QualType::DestructionKind dtorKind = elementType.isDestructedType(); llvm::AllocaInst *endOfInit = 0; EHScopeStack::stable_iterator cleanup; + llvm::Instruction *cleanupDominator = 0; if (CGF.needsEHCleanup(dtorKind)) { // In principle we could tell the cleanup where we are more // directly, but the control flow can get so varied here that it @@ -694,7 +695,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // alloca. endOfInit = CGF.CreateTempAlloca(begin->getType(), "arrayinit.endOfInit"); - Builder.CreateStore(begin, endOfInit); + cleanupDominator = Builder.CreateStore(begin, endOfInit); CGF.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType, CGF.getDestroyer(dtorKind)); cleanup = CGF.EHStack.stable_begin(); @@ -794,7 +795,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { } // Leave the partial-array cleanup if we entered one. - if (dtorKind) CGF.DeactivateCleanupBlock(cleanup); + if (dtorKind) CGF.DeactivateCleanupBlock(cleanup, cleanupDominator); return; } @@ -843,6 +844,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // We'll need to enter cleanup scopes in case any of the member // initializers throw an exception. SmallVector<EHScopeStack::stable_iterator, 16> cleanups; + llvm::Instruction *cleanupDominator = 0; // Here we iterate over the fields; this makes it simpler to both // default-initialize fields and skip over unnamed fields. @@ -886,6 +888,9 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { = field->getType().isDestructedType()) { assert(LV.isSimple()); if (CGF.needsEHCleanup(dtorKind)) { + if (!cleanupDominator) + cleanupDominator = CGF.Builder.CreateUnreachable(); // placeholder + CGF.pushDestroy(EHCleanup, LV.getAddress(), field->getType(), CGF.getDestroyer(dtorKind), false); cleanups.push_back(CGF.EHStack.stable_begin()); @@ -905,7 +910,11 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // Deactivate all the partial cleanups in reverse order, which // generally means popping them. for (unsigned i = cleanups.size(); i != 0; --i) - CGF.DeactivateCleanupBlock(cleanups[i-1]); + CGF.DeactivateCleanupBlock(cleanups[i-1], cleanupDominator); + + // Destroy the placeholder if we made one. + if (cleanupDominator) + cleanupDominator->eraseFromParent(); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 78db5903de..99ebad1786 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -816,18 +816,22 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E, // Enter a partial-destruction cleanup if necessary. QualType::DestructionKind dtorKind = elementType.isDestructedType(); EHScopeStack::stable_iterator cleanup; + llvm::Instruction *cleanupDominator = 0; if (needsEHCleanup(dtorKind)) { pushRegularPartialArrayCleanup(beginPtr, curPtr, elementType, getDestroyer(dtorKind)); cleanup = EHStack.stable_begin(); + cleanupDominator = Builder.CreateUnreachable(); } // Emit the initializer into this element. StoreAnyExprIntoOneUnit(*this, E, curPtr); // Leave the cleanup if we entered one. - if (cleanup != EHStack.stable_end()) - DeactivateCleanupBlock(cleanup); + if (cleanup != EHStack.stable_end()) { + DeactivateCleanupBlock(cleanup, cleanupDominator); + cleanupDominator->eraseFromParent(); + } // Advance to the next element. llvm::Value *nextPtr = Builder.CreateConstGEP1_32(curPtr, 1, "array.next"); @@ -1057,7 +1061,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, DominatingValue<RValue>::save(CGF, RValue::get(AllocSize)); CallDeleteDuringConditionalNew *Cleanup = CGF.EHStack - .pushCleanupWithExtra<CallDeleteDuringConditionalNew>(InactiveEHCleanup, + .pushCleanupWithExtra<CallDeleteDuringConditionalNew>(EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(), SavedNewPtr, @@ -1066,7 +1070,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, Cleanup->setPlacementArg(I, DominatingValue<RValue>::save(CGF, NewArgs[I+1].RV)); - CGF.ActivateCleanupBlock(CGF.EHStack.stable_begin()); + CGF.initFullExprCleanup(); } llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { @@ -1168,10 +1172,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // If there's an operator delete, enter a cleanup to call it if an // exception is thrown. EHScopeStack::stable_iterator operatorDeleteCleanup; + llvm::Instruction *cleanupDominator = 0; if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocatorArgs); operatorDeleteCleanup = EHStack.stable_begin(); + cleanupDominator = Builder.CreateUnreachable(); } assert((allocSize == allocSizeWithoutCookie) == @@ -1200,8 +1206,10 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // Deactivate the 'operator delete' cleanup if we finished // initialization. - if (operatorDeleteCleanup.isValid()) - DeactivateCleanupBlock(operatorDeleteCleanup); + if (operatorDeleteCleanup.isValid()) { + DeactivateCleanupBlock(operatorDeleteCleanup, cleanupDominator); + cleanupDominator->eraseFromParent(); + } if (nullCheck) { conditional.end(*this); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index c3aca51555..09b8b2b373 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -630,10 +630,6 @@ public: llvm::BasicBlock *getInvokeDestImpl(); - /// Set up the last cleaup that was pushed as a conditional - /// full-expression cleanup. - void initFullExprCleanup(); - template <class T> typename DominatingValue<T>::saved_type saveValueInCond(T value) { return DominatingValue<T>::save(*this, value); @@ -744,6 +740,10 @@ public: initFullExprCleanup(); } + /// Set up the last cleaup that was pushed as a conditional + /// full-expression cleanup. + void initFullExprCleanup(); + /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the /// given address. Does nothing if T is not a C++ class type with a @@ -763,11 +763,23 @@ public: /// DeactivateCleanupBlock - Deactivates the given cleanup block. /// The block cannot be reactivated. Pops it if it's the top of the /// stack. - void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup); + /// + /// \param DominatingIP - An instruction which is known to + /// dominate the current IP (if set) and which lies along + /// all paths of execution between the current IP and the + /// the point at which the cleanup comes into scope. + void DeactivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, + llvm::Instruction *DominatingIP); /// ActivateCleanupBlock - Activates an initially-inactive cleanup. /// Cannot be used to resurrect a deactivated cleanup. - void ActivateCleanupBlock(EHScopeStack::stable_iterator Cleanup); + /// + /// \param DominatingIP - An instruction which is known to + /// dominate the current IP (if set) and which lies along + /// all paths of execution between the current IP and the + /// the point at which the cleanup comes into scope. + void ActivateCleanupBlock(EHScopeStack::stable_iterator Cleanup, + llvm::Instruction *DominatingIP); /// \brief Enters a new scope for capturing cleanups, all of which /// will be executed once the scope is exited. @@ -923,6 +935,12 @@ public: /// one branch or the other of a conditional expression. bool isInConditionalBranch() const { return OutermostConditional != 0; } + void setBeforeOutermostConditional(llvm::Value *value, llvm::Value *addr) { + assert(isInConditionalBranch()); + llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); + new llvm::StoreInst(value, addr, &block->back()); + } + /// An RAII object to record that we're evaluating a statement /// expression. class StmtExprEvaluation { diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp index e3160a0394..40faf1bf23 100644 --- a/test/CodeGenCXX/blocks.cpp +++ b/test/CodeGenCXX/blocks.cpp @@ -151,13 +151,13 @@ namespace test5 { // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] // CHECK-NEXT: [[T0:%.*]] = zext i1 // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1 // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* [[X]]) // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]], align 1 // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 + // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] // CHECK-NEXT: br i1 [[T1]], // CHECK-NOT: br diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp index 0fbb09c262..2a5cbb4900 100644 --- a/test/CodeGenCXX/exceptions.cpp +++ b/test/CodeGenCXX/exceptions.cpp @@ -53,8 +53,8 @@ namespace test1 { A *c() { // CHECK: define [[A:%.*]]* @_ZN5test11cEv() // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) // CHECK: [[T1:%.*]] = getelementptr inbounds [[B]]* [[T0]], i32 0, i32 0 @@ -72,8 +72,8 @@ namespace test1 { A *d() { // CHECK: define [[A:%.*]]* @_ZN5test11dEv() // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]]) @@ -90,8 +90,8 @@ namespace test1 { A *e() { // CHECK: define [[A:%.*]]* @_ZN5test11eEv() // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test11BC1Ev([[B:%.*]]* [[T0:%.*]]) // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]]) @@ -121,8 +121,8 @@ namespace test1 { // CHECK: define [[A:%.*]]* @_ZN5test11iEv() // CHECK: [[X:%.*]] = alloca [[A]]*, align 8 // CHECK: [[ACTIVE:%.*]] = alloca i1 - // CHECK: store i1 true, i1* [[ACTIVE]] - // CHECK-NEXT: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK: [[NEW:%.*]] = call noalias i8* @_Znwm(i64 8) + // CHECK-NEXT: store i1 true, i1* [[ACTIVE]] // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]* // CHECK-NEXT: invoke void @_ZN5test15makeBEv([[B:%.*]]* sret [[T0:%.*]]) // CHECK: [[T1:%.*]] = invoke i32 @_ZN5test11BcviEv([[B]]* [[T0]]) @@ -196,9 +196,9 @@ namespace test3 { // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1 // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 8 // CHECK: [[TMPACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]] // CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1 + // CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]] // CHECK-NEXT: store i1 false, i1* [[TMPACTIVE]] // CHECK-NEXT: br i1 [[COND]] return (cond ? @@ -330,17 +330,15 @@ namespace test7 { // CHECK-NEXT: alloca [[A]] // CHECK-NEXT: [[INNER_A:%.*]] = alloca i1 - // These entry-block stores are to deactivate the delete cleanups. - // CHECK-NEXT: store i1 false, i1* [[INNER_NEW]] - // CHECK-NEXT: store i1 false, i1* [[OUTER_NEW]] - // Allocate the outer object. // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test71BnwEm( // CHECK-NEXT: icmp eq i8* [[NEW]], null // These stores, emitted before the outermost conditional branch, // deactivate the temporary cleanups. + // CHECK-NEXT: store i1 false, i1* [[OUTER_NEW]] // CHECK-NEXT: store i1 false, i1* [[OUTER_A]] + // CHECK-NEXT: store i1 false, i1* [[INNER_NEW]] // CHECK-NEXT: store i1 false, i1* [[INNER_A]] // CHECK-NEXT: br i1 diff --git a/test/CodeGenCXX/goto.cpp b/test/CodeGenCXX/goto.cpp index f32847d122..77b6166aff 100644 --- a/test/CodeGenCXX/goto.cpp +++ b/test/CodeGenCXX/goto.cpp @@ -16,10 +16,10 @@ namespace test0 { // CHECK-NEXT: [[V:%.*]] = alloca [[V:%.*]]*, // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]] // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1 - // CHECK: store i1 true, i1* [[CLEANUPACTIVE]] // CHECK: call void @_ZN5test01AC1Ev([[A]]* [[Y]]) // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[Z]]) // CHECK: [[NEW:%.*]] = invoke noalias i8* @_Znwm(i64 1) + // CHECK: store i1 true, i1* [[CLEANUPACTIVE]] // CHECK: [[NEWCAST:%.*]] = bitcast i8* [[NEW]] to [[V]]* // CHECK-NEXT: invoke void @_ZN5test01AC1Ev([[A]]* [[TMP]]) // CHECK: invoke void @_ZN5test01VC1ERKNS_1AE([[V]]* [[NEWCAST]], [[A]]* [[TMP]]) diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m index c14380cced..f11a31e468 100644 --- a/test/CodeGenObjC/arc-blocks.m +++ b/test/CodeGenObjC/arc-blocks.m @@ -471,12 +471,12 @@ void test13(id x) { // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 - // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}}) // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8 // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8 // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null + // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] // CHECK-NEXT: br i1 [[T1]], // CHECK-NOT: br |