mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
[PM] Port LoopSink to the new pass manager.
Like several other loop passes (the vectorizer, etc) this pass doesn't really fit the model of a loop pass. The critical distinction is that it isn't intended to be pipelined together with other loop passes. I plan to add some documentation to the loop pass manager to make this more clear on that side. LoopSink is also different because it doesn't really need a lot of the infrastructure of our loop passes. For example, if there aren't loop invariant instructions causing a preheader to exist, there is no need to form a preheader. It also doesn't need LCSSA because this pass is only involved in sinking invariant instructions from a preheader into the loop, not reasoning about live-outs. This allows some nice simplifications to the pass in the new PM where we can directly walk the loops once without restructuring them. Differential Revision: https://reviews.llvm.org/D28921 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292589 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7dc10faea0
commit
017c62c41d
40
include/llvm/Transforms/Scalar/LoopSink.h
Normal file
40
include/llvm/Transforms/Scalar/LoopSink.h
Normal file
@ -0,0 +1,40 @@
|
||||
//===- LoopSink.h - Loop Sink Pass ------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides the interface for the Loop Sink pass.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TRANSFORMS_SCALAR_LOOPSINK_H
|
||||
#define LLVM_TRANSFORMS_SCALAR_LOOPSINK_H
|
||||
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// A pass that does profile-guided sinking of instructions into loops.
|
||||
///
|
||||
/// This is a function pass as it shouldn't be composed into any kind of
|
||||
/// unified loop pass pipeline. The goal of it is to sink code into loops that
|
||||
/// is loop invariant but only required within the loop body when doing so
|
||||
/// reduces the global expected dynamic frequency with which it executes.
|
||||
/// A classic example is an extremely cold branch within a loop body.
|
||||
///
|
||||
/// We do this as a separate pass so that during normal optimization all
|
||||
/// invariant operations can be held outside the loop body to simplify
|
||||
/// fundamental analyses and transforms of the loop.
|
||||
class LoopSinkPass : public PassInfoMixin<LoopSinkPass> {
|
||||
public:
|
||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LLVM_TRANSFORMS_SCALAR_LOOPSINK_H
|
@ -107,6 +107,7 @@
|
||||
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
||||
#include "llvm/Transforms/Scalar/LoopRotation.h"
|
||||
#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"
|
||||
#include "llvm/Transforms/Scalar/LoopSink.h"
|
||||
#include "llvm/Transforms/Scalar/LoopStrengthReduce.h"
|
||||
#include "llvm/Transforms/Scalar/LoopUnrollPass.h"
|
||||
#include "llvm/Transforms/Scalar/LowerAtomic.h"
|
||||
|
@ -159,6 +159,7 @@ FUNCTION_PASS("lower-guard-intrinsic", LowerGuardIntrinsicPass())
|
||||
FUNCTION_PASS("guard-widening", GuardWideningPass())
|
||||
FUNCTION_PASS("gvn", GVN())
|
||||
FUNCTION_PASS("loop-simplify", LoopSimplifyPass())
|
||||
FUNCTION_PASS("loop-sink", LoopSinkPass())
|
||||
FUNCTION_PASS("lowerinvoke", LowerInvokePass())
|
||||
FUNCTION_PASS("mem2reg", PromotePass())
|
||||
FUNCTION_PASS("memcpyopt", MemCpyOptPass())
|
||||
|
@ -31,6 +31,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/Scalar/LoopSink.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
@ -298,6 +299,42 @@ static bool sinkLoopInvariantInstructions(Loop &L, AAResults &AA, LoopInfo &LI,
|
||||
return Changed;
|
||||
}
|
||||
|
||||
PreservedAnalyses LoopSinkPass::run(Function &F, FunctionAnalysisManager &FAM) {
|
||||
LoopInfo &LI = FAM.getResult<LoopAnalysis>(F);
|
||||
// Nothing to do if there are no loops.
|
||||
if (LI.empty())
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
AAResults &AA = FAM.getResult<AAManager>(F);
|
||||
DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
|
||||
BlockFrequencyInfo &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
|
||||
|
||||
// We want to do a postorder walk over the loops. Since loops are a tree this
|
||||
// is equivalent to a reversed preorder walk and preorder is easy to compute
|
||||
// without recursion. Since we reverse the preorder, we will visit siblings
|
||||
// in reverse program order. This isn't expected to matter at all but is more
|
||||
// consistent with sinking algorithms which generally work bottom-up.
|
||||
SmallVector<Loop *, 4> PreorderLoops = LI.getLoopsInPreorder();
|
||||
|
||||
bool Changed = false;
|
||||
do {
|
||||
Loop &L = *PreorderLoops.pop_back_val();
|
||||
|
||||
// Note that we don't pass SCEV here because it is only used to invalidate
|
||||
// loops in SCEV and we don't preserve (or request) SCEV at all making that
|
||||
// unnecessary.
|
||||
Changed |= sinkLoopInvariantInstructions(L, AA, LI, DT, BFI,
|
||||
/*ScalarEvolution*/ nullptr);
|
||||
} while (!PreorderLoops.empty());
|
||||
|
||||
if (!Changed)
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
PreservedAnalyses PA;
|
||||
PA.preserveSet<CFGAnalyses>();
|
||||
return PA;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct LegacyLoopSinkPass : public LoopPass {
|
||||
static char ID;
|
||||
|
@ -1,4 +1,5 @@
|
||||
; RUN: opt -S -loop-sink < %s | FileCheck %s
|
||||
; RUN: opt -S -passes=loop-sink < %s | FileCheck %s
|
||||
|
||||
@g = global i32 0, align 4
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
; RUN: opt -S -licm < %s | FileCheck %s --check-prefix=CHECK-LICM
|
||||
; RUN: opt -S -licm < %s | opt -S -loop-sink | FileCheck %s --check-prefix=CHECK-SINK
|
||||
; RUN: opt -S < %s -passes='require<opt-remark-emit>,loop(licm),loop-sink' \
|
||||
; RUN: | FileCheck %s --check-prefix=CHECK-SINK
|
||||
|
||||
; Original source code:
|
||||
; int g;
|
||||
|
Loading…
Reference in New Issue
Block a user