mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[IRCE] Create llvm::Loop instances for cloned out loops
llvm-svn: 278618
This commit is contained in:
parent
343d0f7307
commit
a96642d92a
@ -515,6 +515,11 @@ class LoopConstrainer {
|
||||
//
|
||||
void cloneLoop(ClonedLoop &CLResult, const char *Tag) const;
|
||||
|
||||
// Create the appropriate loop structure needed to describe a cloned copy of
|
||||
// `Original`. The clone is described by `VM`.
|
||||
Loop *createClonedLoopStructure(Loop *Original, Loop *Parent,
|
||||
ValueToValueMapTy &VM);
|
||||
|
||||
// Rewrite the iteration space of the loop denoted by (LS, Preheader). The
|
||||
// iteration space of the rewritten loop ends at ExitLoopAt. The start of the
|
||||
// iteration space is not changed. `ExitLoopAt' is assumed to be slt
|
||||
@ -567,6 +572,7 @@ class LoopConstrainer {
|
||||
LLVMContext &Ctx;
|
||||
ScalarEvolution &SE;
|
||||
DominatorTree &DT;
|
||||
LPPassManager &LPM;
|
||||
|
||||
// Information about the original loop we started out with.
|
||||
Loop &OriginalLoop;
|
||||
@ -586,13 +592,13 @@ class LoopConstrainer {
|
||||
LoopStructure MainLoopStructure;
|
||||
|
||||
public:
|
||||
LoopConstrainer(Loop &L, LoopInfo &LI, const LoopStructure &LS,
|
||||
ScalarEvolution &SE, DominatorTree &DT,
|
||||
InductiveRangeCheck::Range R)
|
||||
LoopConstrainer(Loop &L, LoopInfo &LI, LPPassManager &LPM,
|
||||
const LoopStructure &LS, ScalarEvolution &SE,
|
||||
DominatorTree &DT, InductiveRangeCheck::Range R)
|
||||
: F(*L.getHeader()->getParent()), Ctx(L.getHeader()->getContext()),
|
||||
SE(SE), DT(DT), OriginalLoop(L), LI(LI), LatchTakenCount(nullptr),
|
||||
OriginalPreheader(nullptr), MainLoopPreheader(nullptr), Range(R),
|
||||
MainLoopStructure(LS) {}
|
||||
SE(SE), DT(DT), LPM(LPM), OriginalLoop(L), LI(LI),
|
||||
LatchTakenCount(nullptr), OriginalPreheader(nullptr),
|
||||
MainLoopPreheader(nullptr), Range(R), MainLoopStructure(LS) {}
|
||||
|
||||
// Entry point for the algorithm. Returns true on success.
|
||||
bool run();
|
||||
@ -1159,6 +1165,22 @@ void LoopConstrainer::addToParentLoopIfNeeded(ArrayRef<BasicBlock *> BBs) {
|
||||
ParentLoop->addBasicBlockToLoop(BB, LI);
|
||||
}
|
||||
|
||||
Loop *LoopConstrainer::createClonedLoopStructure(Loop *Original, Loop *Parent,
|
||||
ValueToValueMapTy &VM) {
|
||||
Loop &New = LPM.addLoop(Parent);
|
||||
|
||||
// Add all of the blocks in Original to the new loop.
|
||||
for (auto *BB : Original->blocks())
|
||||
if (LI.getLoopFor(BB) == Original)
|
||||
New.addBasicBlockToLoop(cast<BasicBlock>(VM[BB]), LI);
|
||||
|
||||
// Add all of the subloops to the new loop.
|
||||
for (Loop *SubLoop : *Original)
|
||||
createClonedLoopStructure(SubLoop, &New, VM);
|
||||
|
||||
return &New;
|
||||
}
|
||||
|
||||
bool LoopConstrainer::run() {
|
||||
BasicBlock *Preheader = nullptr;
|
||||
LatchTakenCount = SE.getExitCount(&OriginalLoop, MainLoopStructure.Latch);
|
||||
@ -1280,10 +1302,23 @@ bool LoopConstrainer::run() {
|
||||
std::remove(std::begin(NewBlocks), std::end(NewBlocks), nullptr);
|
||||
|
||||
addToParentLoopIfNeeded(makeArrayRef(std::begin(NewBlocks), NewBlocksEnd));
|
||||
addToParentLoopIfNeeded(PreLoop.Blocks);
|
||||
addToParentLoopIfNeeded(PostLoop.Blocks);
|
||||
|
||||
DT.recalculate(F);
|
||||
|
||||
if (!PreLoop.Blocks.empty()) {
|
||||
auto *L = createClonedLoopStructure(
|
||||
&OriginalLoop, OriginalLoop.getParentLoop(), PreLoop.Map);
|
||||
formLCSSARecursively(*L, DT, &LI, &SE);
|
||||
simplifyLoop(L, &DT, &LI, &SE, nullptr, true);
|
||||
}
|
||||
|
||||
if (!PostLoop.Blocks.empty()) {
|
||||
auto *L = createClonedLoopStructure(
|
||||
&OriginalLoop, OriginalLoop.getParentLoop(), PostLoop.Map);
|
||||
formLCSSARecursively(*L, DT, &LI, &SE);
|
||||
simplifyLoop(L, &DT, &LI, &SE, nullptr, true);
|
||||
}
|
||||
|
||||
formLCSSARecursively(OriginalLoop, DT, &LI, &SE);
|
||||
simplifyLoop(&OriginalLoop, &DT, &LI, &SE, nullptr, true);
|
||||
|
||||
@ -1458,8 +1493,8 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
return false;
|
||||
|
||||
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
LoopConstrainer LC(*L, getAnalysis<LoopInfoWrapperPass>().getLoopInfo(), LS,
|
||||
SE, DT, SafeIterRange.getValue());
|
||||
LoopConstrainer LC(*L, getAnalysis<LoopInfoWrapperPass>().getLoopInfo(), LPM,
|
||||
LS, SE, DT, SafeIterRange.getValue());
|
||||
bool Changed = LC.run();
|
||||
|
||||
if (Changed) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce-print-changed-loops -S -irce -verify < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -irce-print-changed-loops -S -verify-loop-info -irce -verify < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK-NOT: constrained loop
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
; RUN: opt -irce -S < %s
|
||||
; RUN: opt -verify-loop-info -irce -S < %s
|
||||
|
||||
; These test cases don't check the correctness of the transform, but
|
||||
; that the -irce does not crash in the presence of certain things in
|
||||
; that -irce does not crash in the presence of certain things in
|
||||
; the IR:
|
||||
|
||||
define void @mismatched_types_1() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -S -irce < %s | FileCheck %s
|
||||
; RUN: opt -S -verify-loop-info -irce < %s | FileCheck %s
|
||||
|
||||
define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) {
|
||||
; CHECK-LABEL: @f_0(
|
||||
@ -34,7 +34,7 @@ define void @f_0(i32 *%arr, i32 *%a_len_ptr, i32 %n, i1* %cond_buf) {
|
||||
; CHECK: loop:
|
||||
; CHECK: %cond = load volatile i1, i1* %cond_buf
|
||||
; CHECK: %abc = and i1 %cond, true
|
||||
; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit, !prof !1
|
||||
; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit3, !prof !1
|
||||
|
||||
; CHECK: out.of.bounds.loopexit:
|
||||
; CHECK: br label %out.of.bounds
|
||||
@ -84,7 +84,7 @@ define void @f_1(
|
||||
|
||||
; CHECK: loop:
|
||||
; CHECK: %abc = and i1 true, true
|
||||
; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit, !prof !1
|
||||
; CHECK: br i1 %abc, label %in.bounds, label %out.of.bounds.loopexit4, !prof !1
|
||||
|
||||
; CHECK: out.of.bounds.loopexit:
|
||||
; CHECK-NEXT: br label %out.of.bounds
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce -S < %s | FileCheck %s
|
||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||
|
||||
define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
||||
entry:
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK-NOT: constrained Loop
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce -S < %s | FileCheck %s
|
||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||
|
||||
define void @multiple_access_no_preloop(
|
||||
i32* %arr_a, i32* %a_len_ptr, i32* %arr_b, i32* %b_len_ptr, i32 %n) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce-print-range-checks -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -irce-print-range-checks -irce-print-changed-loops -verify-loop-info -irce < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: irce: loop has 1 inductive range checks:
|
||||
; CHECK-NEXT: InductiveRangeCheck:
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
|
||||
; RUN: opt -verify-loop-info -irce -irce-print-range-checks -irce-print-changed-loops %s -S 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK: irce: loop has 1 inductive range checks:
|
||||
; CHECK-NEXT:InductiveRangeCheck:
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce -S < %s | FileCheck %s
|
||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||
|
||||
define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
||||
entry:
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce -S < %s | FileCheck %s
|
||||
; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s
|
||||
|
||||
define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {
|
||||
entry:
|
||||
@ -61,7 +61,7 @@ define void @single_access_with_preloop(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32
|
||||
; CHECK: br i1 [[continue_preloop_cond]], label %loop.preloop, label %preloop.exit.selector
|
||||
|
||||
; CHECK: preloop.exit.selector:
|
||||
; CHECK: [[preloop_its_left:[^ ]+]] = icmp slt i32 %idx.next.preloop, %n
|
||||
; CHECK: [[preloop_its_left:[^ ]+]] = icmp slt i32 %idx.next.preloop.lcssa, %n
|
||||
; CHECK: br i1 [[preloop_its_left]], label %preloop.pseudo.exit, label %exit.loopexit
|
||||
|
||||
; CHECK: in.bounds.postloop:
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce-skip-profitability-checks -S -irce < %s | FileCheck %s
|
||||
; RUN: opt -irce-skip-profitability-checks -S -verify-loop-info -irce < %s | FileCheck %s
|
||||
|
||||
define void @single_access_no_preloop_no_offset(i32 *%arr, i32 *%a_len_ptr, i32 %n) {
|
||||
; CHECK-LABEL: @single_access_no_preloop_no_offset(
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s
|
||||
; RUN: opt -irce-print-changed-loops -verify-loop-info -irce -S < %s 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK-NOT: constrained Loop at depth
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user