diff options
-rw-r--r-- | llvm/lib/CodeGen/ShrinkWrap.cpp | 30 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/arm64-shrink-wrapping.ll | 29 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/arm-shrink-wrapping.ll | 28 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/x86-shrink-wrapping.ll | 30 |
4 files changed, 111 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/ShrinkWrap.cpp b/llvm/lib/CodeGen/ShrinkWrap.cpp index f8ec1f358c4..261b8402bc0 100644 --- a/llvm/lib/CodeGen/ShrinkWrap.cpp +++ b/llvm/lib/CodeGen/ShrinkWrap.cpp @@ -309,12 +309,30 @@ void ShrinkWrap::updateSaveRestorePoints(MachineBasicBlock &MBB) { // Fix (C). if (Save && Restore && Save != Restore && MLI->getLoopFor(Save) != MLI->getLoopFor(Restore)) { - if (MLI->getLoopDepth(Save) > MLI->getLoopDepth(Restore)) - // Push Save outside of this loop. - Save = FindIDom<>(*Save, Save->predecessors(), *MDT); - else - // Push Restore outside of this loop. - Restore = FindIDom<>(*Restore, Restore->successors(), *MPDT); + if (MLI->getLoopDepth(Save) > MLI->getLoopDepth(Restore)) { + // Push Save outside of this loop if immediate dominator is different + // from save block. If immediate dominator is not different, bail out. + MachineBasicBlock *IDom = FindIDom<>(*Save, Save->predecessors(), *MDT); + if (IDom != Save) + Save = IDom; + else { + Save = nullptr; + break; + } + } + else { + // Push Restore outside of this loop if immediate post-dominator is + // different from restore block. If immediate post-dominator is not + // different, bail out. + MachineBasicBlock *IPdom = + FindIDom<>(*Restore, Restore->successors(), *MPDT); + if (IPdom != Restore) + Restore = IPdom; + else { + Restore = nullptr; + break; + } + } } } } diff --git a/llvm/test/CodeGen/AArch64/arm64-shrink-wrapping.ll b/llvm/test/CodeGen/AArch64/arm64-shrink-wrapping.ll index 599712be401..c547e8eceba 100644 --- a/llvm/test/CodeGen/AArch64/arm64-shrink-wrapping.ll +++ b/llvm/test/CodeGen/AArch64/arm64-shrink-wrapping.ll @@ -539,3 +539,32 @@ if.end: declare void @abort() #0 attributes #0 = { noreturn nounwind } + +; Make sure that we handle infinite loops properly When checking that the Save +; and Restore blocks are control flow equivalent, the loop searches for the +; immediate (post) dominator for the (restore) save blocks. When either the Save +; or Restore block is located in an infinite loop the only immediate (post) +; dominator is itself. In this case, we cannot perform shrink wrapping, but we +; should return gracefully and continue compilation. +; The only condition for this test is the compilation finishes correctly. +; +; CHECK-LABEL: infiniteloop +; CHECK: ret +define void @infiniteloop() { +entry: + br i1 undef, label %if.then, label %if.end + +if.then: + %ptr = alloca i32, i32 4 + br label %for.body + +for.body: ; preds = %for.body, %entry + %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] + %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() + %add = add nsw i32 %call, %sum.03 + store i32 %add, i32* %ptr + br label %for.body + +if.end: + ret void +} diff --git a/llvm/test/CodeGen/ARM/arm-shrink-wrapping.ll b/llvm/test/CodeGen/ARM/arm-shrink-wrapping.ll index f033ac47309..28ffca8344e 100644 --- a/llvm/test/CodeGen/ARM/arm-shrink-wrapping.ll +++ b/llvm/test/CodeGen/ARM/arm-shrink-wrapping.ll @@ -534,3 +534,31 @@ if.end: declare void @abort() #0 attributes #0 = { noreturn nounwind } + +; Make sure that we handle infinite loops properly When checking that the Save +; and Restore blocks are control flow equivalent, the loop searches for the +; immediate (post) dominator for the (restore) save blocks. When either the Save +; or Restore block is located in an infinite loop the only immediate (post) +; dominator is itself. In this case, we cannot perform shrink wrapping, but we +; should return gracefully and continue compilation. +; The only condition for this test is the compilation finishes correctly. +; CHECK-LABEL: infiniteloop +; CHECK: pop +define void @infiniteloop() { +entry: + br i1 undef, label %if.then, label %if.end + +if.then: + %ptr = alloca i32, i32 4 + br label %for.body + +for.body: ; preds = %for.body, %entry + %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] + %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() + %add = add nsw i32 %call, %sum.03 + store i32 %add, i32* %ptr + br label %for.body + +if.end: + ret void +} diff --git a/llvm/test/CodeGen/X86/x86-shrink-wrapping.ll b/llvm/test/CodeGen/X86/x86-shrink-wrapping.ll index 8c91335d91a..c6d20d5835d 100644 --- a/llvm/test/CodeGen/X86/x86-shrink-wrapping.ll +++ b/llvm/test/CodeGen/X86/x86-shrink-wrapping.ll @@ -637,3 +637,33 @@ if.end: declare void @abort() #0 attributes #0 = { noreturn nounwind } + + +; Make sure that we handle infinite loops properly When checking that the Save +; and Restore blocks are control flow equivalent, the loop searches for the +; immediate (post) dominator for the (restore) save blocks. When either the Save +; or Restore block is located in an infinite loop the only immediate (post) +; dominator is itself. In this case, we cannot perform shrink wrapping, but we +; should return gracefully and continue compilation. +; The only condition for this test is the compilation finishes correctly. +; +; CHECK-LABEL: infiniteloop +; CHECK: retq +define void @infiniteloop() { +entry: + br i1 undef, label %if.then, label %if.end + +if.then: + %ptr = alloca i32, i32 4 + br label %for.body + +for.body: ; preds = %for.body, %entry + %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] + %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() + %add = add nsw i32 %call, %sum.03 + store i32 %add, i32* %ptr + br label %for.body + +if.end: + ret void +} |