mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
[PM/LoopUnswitch] Detect irreducible control flow within loops and skip unswitching non-trivial edges.
Summary: This fixes the bug pointed out in review with non-trivial unswitching. This also provides a basis that should make it pretty easy to finish fleshing out a routine to scan an entire function body for irreducible control flow, but this patch remains minimal for disabling loop unswitch. Reviewers: sanjoy, fedor.sergeev Subscribers: mcrosier, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D45754 llvm-svn: 330357
This commit is contained in:
parent
52289d96c4
commit
a806fbf4b8
@ -17,9 +17,11 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
#include "llvm/Analysis/LoopAnalysisManager.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopIterator.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
@ -1938,6 +1940,17 @@ unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC,
|
||||
if (UnswitchCandidates.empty())
|
||||
return Changed;
|
||||
|
||||
// Check if there are irreducible CFG cycles in this loop. If so, we cannot
|
||||
// easily unswitch non-trivial edges out of the loop. Doing so might turn the
|
||||
// irreducible control flow into reducible control flow and introduce new
|
||||
// loops "out of thin air". If we ever discover important use cases for doing
|
||||
// this, we can add support to loop unswitch, but it is a lot of complexity
|
||||
// for what seems little or no real world benifit.
|
||||
LoopBlocksRPO RPOT(&L);
|
||||
RPOT.perform(&LI);
|
||||
if (containsIrreducibleCFG<const BasicBlock *>(RPOT, LI))
|
||||
return Changed;
|
||||
|
||||
DEBUG(dbgs() << "Considering " << UnswitchCandidates.size()
|
||||
<< " non-trivial loop invariant conditions for unswitching.\n");
|
||||
|
||||
|
@ -2350,3 +2350,33 @@ loop_exit:
|
||||
; CHECK-NEXT: %[[LCSSA:.*]] = phi i32 [ %[[V]], %loop_begin ]
|
||||
; CHECK-NEXT: ret i32 %[[LCSSA]]
|
||||
}
|
||||
|
||||
; Negative test: we do not switch when the loop contains unstructured control
|
||||
; flows as it would significantly complicate the process as novel loops might
|
||||
; be formed, etc.
|
||||
define void @test_no_unswitch_unstructured_cfg(i1* %ptr, i1 %cond) {
|
||||
; CHECK-LABEL: @test_no_unswitch_unstructured_cfg(
|
||||
entry:
|
||||
br label %loop_begin
|
||||
|
||||
loop_begin:
|
||||
br i1 %cond, label %loop_left, label %loop_right
|
||||
|
||||
loop_left:
|
||||
%v1 = load i1, i1* %ptr
|
||||
br i1 %v1, label %loop_right, label %loop_merge
|
||||
|
||||
loop_right:
|
||||
%v2 = load i1, i1* %ptr
|
||||
br i1 %v2, label %loop_left, label %loop_merge
|
||||
|
||||
loop_merge:
|
||||
%v3 = load i1, i1* %ptr
|
||||
br i1 %v3, label %loop_latch, label %loop_exit
|
||||
|
||||
loop_latch:
|
||||
br label %loop_begin
|
||||
|
||||
loop_exit:
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user