F->getEntryBlock().begin());
}
+ // We cannot demote invoke instructions to the stack if their normal edge
+ // is critical. Therefore, split the critical edge and create a basic block
+ // into which the store can be inserted.
+ if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
+ if (!II->getNormalDest()->getSinglePredecessor()) {
+ unsigned SuccNum = GetSuccessorNumber(II->getParent(), II->getNormalDest());
+ assert(isCriticalEdge(II, SuccNum) && "Expected a critical edge!");
+ BasicBlock *BB = SplitCriticalEdge(II, SuccNum);
+ assert(BB && "Unable to split critical edge.");
+ (void)BB;
+ }
+ }
+
// Change all of the users of the instruction to read from the stack slot.
while (!I.use_empty()) {
Instruction *U = cast<Instruction>(I.user_back());
}
}
-
// Insert stores of the computed value into the stack slot. We have to be
// careful if I is an invoke instruction, because we can't insert the store
// AFTER the terminator instruction.
if (!isa<TerminatorInst>(I)) {
InsertPt = &I;
++InsertPt;
+ for (; isa<PHINode>(InsertPt) || isa<LandingPadInst>(InsertPt); ++InsertPt)
+ /* empty */; // Don't insert before PHI nodes or landingpad instrs.
} else {
InvokeInst &II = cast<InvokeInst>(I);
- if (II.getNormalDest()->getSinglePredecessor())
- InsertPt = II.getNormalDest()->getFirstInsertionPt();
- else {
- // We cannot demote invoke instructions to the stack if their normal edge
- // is critical. Therefore, split the critical edge and insert the store
- // in the newly created basic block.
- unsigned SuccNum = GetSuccessorNumber(I.getParent(), II.getNormalDest());
- TerminatorInst *TI = &cast<TerminatorInst>(I);
- assert (isCriticalEdge(TI, SuccNum) &&
- "Expected a critical edge!");
- BasicBlock *BB = SplitCriticalEdge(TI, SuccNum);
- assert (BB && "Unable to split critical edge.");
- InsertPt = BB->getFirstInsertionPt();
- }
+ InsertPt = II.getNormalDest()->getFirstInsertionPt();
}
- for (; isa<PHINode>(InsertPt) || isa<LandingPadInst>(InsertPt); ++InsertPt)
- /* empty */; // Don't insert before PHI nodes or landingpad instrs.
-
new StoreInst(&I, Slot, InsertPt);
return Slot;
}
-; RUN: llc < %s -O1 -mtriple thumbv7-apple-ios6
+; RUN: llc < %s -O1 -mtriple thumbv7-apple-ios6 | FileCheck %s
; Just make sure no one tries to make the assumption that the normal edge of an
; invoke is never a critical edge. Previously, this code would assert.
declare void @release(i8*)
declare void @terminatev()
+
+; Make sure that the instruction DemoteRegToStack inserts to reload
+; %call.i.i.i14.i.i follows the instruction that saves the value to the stack in
+; basic block %entry.do.body.i.i.i_crit_edge.
+; Previously, DemoteRegToStack would insert a load instruction into the entry
+; block to reload %call.i.i.i14.i.i before the phi instruction (%0) in block
+; %do.body.i.i.i.
+
+; CHECK-LABEL: __Z4foo1c:
+; CHECK: blx __Znwm
+; CHECK: {{.*}}@ %entry.do.body.i.i.i_crit_edge
+; CHECK: str r0, [sp, [[OFFSET:#[0-9]+]]]
+; CHECK: ldr [[R0:r[0-9]+]], [sp, [[OFFSET]]]
+; CHECK: {{.*}}@ %do.body.i.i.i
+; CHECK: cmp [[R0]], #0
+
+%"class.std::__1::basic_string" = type { %"class.std::__1::__compressed_pair" }
+%"class.std::__1::__compressed_pair" = type { %"class.std::__1::__libcpp_compressed_pair_imp" }
+%"class.std::__1::__libcpp_compressed_pair_imp" = type { %"struct.std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep" }
+%"struct.std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__rep" = type { %union.anon }
+%union.anon = type { %"struct.std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__long" }
+%"struct.std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__long" = type { i32, i32, i8* }
+
+@.str = private unnamed_addr constant [12 x i8] c"some_string\00", align 1
+
+define void @_Z4foo1c(i8 signext %a) {
+entry:
+ %s1 = alloca %"class.std::__1::basic_string", align 4
+ call void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm(%"class.std::__1::basic_string"* %s1, i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i32 0), i32 11)
+ %call.i.i.i14.i.i = invoke noalias i8* @_Znwm(i32 1024)
+ to label %do.body.i.i.i unwind label %lpad.body
+
+do.body.i.i.i: ; preds = %entry, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i
+ %lsr.iv = phi i32 [ %lsr.iv.next, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i ], [ -1024, %entry ]
+ %0 = phi i8* [ %incdec.ptr.i.i.i, %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i ], [ %call.i.i.i14.i.i, %entry ]
+ %new.isnull.i.i.i.i = icmp eq i8* %0, null
+ br i1 %new.isnull.i.i.i.i, label %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i, label %new.notnull.i.i.i.i
+
+new.notnull.i.i.i.i: ; preds = %do.body.i.i.i
+ store i8 %a, i8* %0, align 1
+ br label %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i
+
+_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i: ; preds = %new.notnull.i.i.i.i, %do.body.i.i.i
+ %1 = phi i8* [ null, %do.body.i.i.i ], [ %0, %new.notnull.i.i.i.i ]
+ %incdec.ptr.i.i.i = getelementptr inbounds i8* %1, i32 1
+ %lsr.iv.next = add i32 %lsr.iv, 1
+ %cmp.i16.i.i = icmp eq i32 %lsr.iv.next, 0
+ br i1 %cmp.i16.i.i, label %invoke.cont, label %do.body.i.i.i
+
+invoke.cont: ; preds = %_ZNSt3__116allocator_traitsINS_9allocatorIcEEE9constructIccEEvRS2_PT_RKT0_.exit.i.i.i
+ invoke void @_Z4foo2Pci(i8* %call.i.i.i14.i.i, i32 1024)
+ to label %invoke.cont5 unwind label %lpad2
+
+invoke.cont5: ; preds = %invoke.cont
+ %cmp.i.i.i15 = icmp eq i8* %call.i.i.i14.i.i, null
+ br i1 %cmp.i.i.i15, label %invoke.cont6, label %_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i19
+
+_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i19: ; preds = %invoke.cont5
+ call void @_ZdlPv(i8* %call.i.i.i14.i.i)
+ br label %invoke.cont6
+
+invoke.cont6: ; preds = %_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i19, %invoke.cont5
+ %call10 = call %"class.std::__1::basic_string"* @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev(%"class.std::__1::basic_string"* %s1)
+ ret void
+
+lpad.body: ; preds = %entry
+ %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+ cleanup
+ %3 = extractvalue { i8*, i32 } %2, 0
+ %4 = extractvalue { i8*, i32 } %2, 1
+ br label %ehcleanup
+
+lpad2: ; preds = %invoke.cont
+ %5 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+ cleanup
+ %6 = extractvalue { i8*, i32 } %5, 0
+ %7 = extractvalue { i8*, i32 } %5, 1
+ %cmp.i.i.i21 = icmp eq i8* %call.i.i.i14.i.i, null
+ br i1 %cmp.i.i.i21, label %ehcleanup, label %_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i26
+
+_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i26: ; preds = %lpad2
+ call void @_ZdlPv(i8* %call.i.i.i14.i.i)
+ br label %ehcleanup
+
+ehcleanup: ; preds = %_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i26, %lpad2, %lpad.body
+ %exn.slot.0 = phi i8* [ %3, %lpad.body ], [ %6, %lpad2 ], [ %6, %_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i26 ]
+ %ehselector.slot.0 = phi i32 [ %4, %lpad.body ], [ %7, %lpad2 ], [ %7, %_ZNSt3__113__vector_baseIcNS_9allocatorIcEEE5clearEv.exit.i.i.i26 ]
+ %call12 = invoke %"class.std::__1::basic_string"* @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev(%"class.std::__1::basic_string"* %s1)
+ to label %eh.resume unwind label %terminate.lpad
+
+eh.resume: ; preds = %ehcleanup
+ %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0
+ %lpad.val13 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1
+ resume { i8*, i32 } %lpad.val13
+
+terminate.lpad: ; preds = %ehcleanup
+ %8 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*)
+ catch i8* null
+ %9 = extractvalue { i8*, i32 } %8, 0
+ call void @__clang_call_terminate(i8* %9)
+ unreachable
+}
+
+declare void @_Z4foo2Pci(i8*, i32)
+
+define linkonce_odr hidden void @__clang_call_terminate(i8*) {
+ %2 = tail call i8* @__cxa_begin_catch(i8* %0)
+ tail call void @_ZSt9terminatev()
+ unreachable
+}
+
+declare i8* @__cxa_begin_catch(i8*)
+declare void @_ZSt9terminatev()
+declare %"class.std::__1::basic_string"* @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev(%"class.std::__1::basic_string"* returned)
+declare void @_ZdlPv(i8*) #3
+declare noalias i8* @_Znwm(i32)
+declare void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm(%"class.std::__1::basic_string"*, i8*, i32)
+declare void @_Unwind_SjLj_Register({ i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }*)
+declare void @_Unwind_SjLj_Unregister({ i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }*)
+declare i8* @llvm.frameaddress(i32)
+declare i8* @llvm.stacksave()
+declare void @llvm.stackrestore(i8*)
+declare i32 @llvm.eh.sjlj.setjmp(i8*)
+declare i8* @llvm.eh.sjlj.lsda()
+declare void @llvm.eh.sjlj.callsite(i32)
+declare void @llvm.eh.sjlj.functioncontext(i8*)