diff options
| -rw-r--r-- | llvm/lib/Transforms/Utils/DemoteRegToStack.cpp | 34 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/sjlj-prepare-critical-edge.ll | 128 | 
2 files changed, 143 insertions, 19 deletions
| diff --git a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp index 9972b22a07e..003da58ee79 100644 --- a/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp +++ b/llvm/lib/Transforms/Utils/DemoteRegToStack.cpp @@ -39,6 +39,19 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,                            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()); @@ -71,7 +84,6 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,      }    } -    // 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. @@ -79,27 +91,13 @@ AllocaInst *llvm::DemoteRegToStack(Instruction &I, bool VolatileLoads,    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;  } diff --git a/llvm/test/CodeGen/ARM/sjlj-prepare-critical-edge.ll b/llvm/test/CodeGen/ARM/sjlj-prepare-critical-edge.ll index d8241d0dc38..a7bc22fe968 100644 --- a/llvm/test/CodeGen/ARM/sjlj-prepare-critical-edge.ll +++ b/llvm/test/CodeGen/ARM/sjlj-prepare-critical-edge.ll @@ -1,4 +1,4 @@ -; 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. @@ -65,3 +65,129 @@ declare i32 @__gxx_personality_sj0(...)  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*) | 

