mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
[Hexagon][NewPM] Port -hexagon-loop-idiom and add to pipeline
Fixes pmpy-mod.ll under NPM Reviewed By: kparzysz Differential Revision: https://reviews.llvm.org/D91829
This commit is contained in:
parent
ca0b0997cf
commit
04d409f2b1
@ -6,6 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonLoopIdiomRecognition.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
@ -16,6 +17,7 @@
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LoopAnalysisManager.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/MemoryLocation.h"
|
||||
@ -40,6 +42,7 @@
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/IntrinsicsHexagon.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/IR/PatternMatch.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/User.h"
|
||||
@ -108,136 +111,152 @@ static const char *HexagonVolatileMemcpyName
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void initializeHexagonLoopIdiomRecognizePass(PassRegistry&);
|
||||
Pass *createHexagonLoopIdiomPass();
|
||||
void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &);
|
||||
Pass *createHexagonLoopIdiomPass();
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace {
|
||||
|
||||
class HexagonLoopIdiomRecognize : public LoopPass {
|
||||
public:
|
||||
static char ID;
|
||||
class HexagonLoopIdiomRecognize {
|
||||
public:
|
||||
explicit HexagonLoopIdiomRecognize(AliasAnalysis *AA, DominatorTree *DT,
|
||||
LoopInfo *LF, const TargetLibraryInfo *TLI,
|
||||
ScalarEvolution *SE)
|
||||
: AA(AA), DT(DT), LF(LF), TLI(TLI), SE(SE) {}
|
||||
|
||||
explicit HexagonLoopIdiomRecognize() : LoopPass(ID) {
|
||||
initializeHexagonLoopIdiomRecognizePass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
bool run(Loop *L);
|
||||
|
||||
StringRef getPassName() const override {
|
||||
return "Recognize Hexagon-specific loop idioms";
|
||||
}
|
||||
private:
|
||||
int getSCEVStride(const SCEVAddRecExpr *StoreEv);
|
||||
bool isLegalStore(Loop *CurLoop, StoreInst *SI);
|
||||
void collectStores(Loop *CurLoop, BasicBlock *BB,
|
||||
SmallVectorImpl<StoreInst *> &Stores);
|
||||
bool processCopyingStore(Loop *CurLoop, StoreInst *SI, const SCEV *BECount);
|
||||
bool coverLoop(Loop *L, SmallVectorImpl<Instruction *> &Insts) const;
|
||||
bool runOnLoopBlock(Loop *CurLoop, BasicBlock *BB, const SCEV *BECount,
|
||||
SmallVectorImpl<BasicBlock *> &ExitBlocks);
|
||||
bool runOnCountableLoop(Loop *L);
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addRequiredID(LoopSimplifyID);
|
||||
AU.addRequiredID(LCSSAID);
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addPreserved<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
AliasAnalysis *AA;
|
||||
const DataLayout *DL;
|
||||
DominatorTree *DT;
|
||||
LoopInfo *LF;
|
||||
const TargetLibraryInfo *TLI;
|
||||
ScalarEvolution *SE;
|
||||
bool HasMemcpy, HasMemmove;
|
||||
};
|
||||
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
class HexagonLoopIdiomRecognizeLegacyPass : public LoopPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
private:
|
||||
int getSCEVStride(const SCEVAddRecExpr *StoreEv);
|
||||
bool isLegalStore(Loop *CurLoop, StoreInst *SI);
|
||||
void collectStores(Loop *CurLoop, BasicBlock *BB,
|
||||
SmallVectorImpl<StoreInst*> &Stores);
|
||||
bool processCopyingStore(Loop *CurLoop, StoreInst *SI, const SCEV *BECount);
|
||||
bool coverLoop(Loop *L, SmallVectorImpl<Instruction*> &Insts) const;
|
||||
bool runOnLoopBlock(Loop *CurLoop, BasicBlock *BB, const SCEV *BECount,
|
||||
SmallVectorImpl<BasicBlock*> &ExitBlocks);
|
||||
bool runOnCountableLoop(Loop *L);
|
||||
explicit HexagonLoopIdiomRecognizeLegacyPass() : LoopPass(ID) {
|
||||
initializeHexagonLoopIdiomRecognizeLegacyPassPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
AliasAnalysis *AA;
|
||||
const DataLayout *DL;
|
||||
DominatorTree *DT;
|
||||
LoopInfo *LF;
|
||||
const TargetLibraryInfo *TLI;
|
||||
ScalarEvolution *SE;
|
||||
bool HasMemcpy, HasMemmove;
|
||||
StringRef getPassName() const override {
|
||||
return "Recognize Hexagon-specific loop idioms";
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addRequiredID(LoopSimplifyID);
|
||||
AU.addRequiredID(LCSSAID);
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addPreserved<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
};
|
||||
|
||||
struct Simplifier {
|
||||
struct Rule {
|
||||
using FuncType = std::function<Value *(Instruction *, LLVMContext &)>;
|
||||
Rule(StringRef N, FuncType F) : Name(N), Fn(F) {}
|
||||
StringRef Name; // For debugging.
|
||||
FuncType Fn;
|
||||
};
|
||||
|
||||
struct Simplifier {
|
||||
struct Rule {
|
||||
using FuncType = std::function<Value* (Instruction*, LLVMContext&)>;
|
||||
Rule(StringRef N, FuncType F) : Name(N), Fn(F) {}
|
||||
StringRef Name; // For debugging.
|
||||
FuncType Fn;
|
||||
};
|
||||
void addRule(StringRef N, const Rule::FuncType &F) {
|
||||
Rules.push_back(Rule(N, F));
|
||||
}
|
||||
|
||||
void addRule(StringRef N, const Rule::FuncType &F) {
|
||||
Rules.push_back(Rule(N, F));
|
||||
private:
|
||||
struct WorkListType {
|
||||
WorkListType() = default;
|
||||
|
||||
void push_back(Value *V) {
|
||||
// Do not push back duplicates.
|
||||
if (!S.count(V)) {
|
||||
Q.push_back(V);
|
||||
S.insert(V);
|
||||
}
|
||||
}
|
||||
|
||||
Value *pop_front_val() {
|
||||
Value *V = Q.front();
|
||||
Q.pop_front();
|
||||
S.erase(V);
|
||||
return V;
|
||||
}
|
||||
|
||||
bool empty() const { return Q.empty(); }
|
||||
|
||||
private:
|
||||
struct WorkListType {
|
||||
WorkListType() = default;
|
||||
std::deque<Value *> Q;
|
||||
std::set<Value *> S;
|
||||
};
|
||||
|
||||
void push_back(Value* V) {
|
||||
// Do not push back duplicates.
|
||||
if (!S.count(V)) { Q.push_back(V); S.insert(V); }
|
||||
}
|
||||
using ValueSetType = std::set<Value *>;
|
||||
|
||||
Value *pop_front_val() {
|
||||
Value *V = Q.front(); Q.pop_front(); S.erase(V);
|
||||
return V;
|
||||
}
|
||||
std::vector<Rule> Rules;
|
||||
|
||||
bool empty() const { return Q.empty(); }
|
||||
public:
|
||||
struct Context {
|
||||
using ValueMapType = DenseMap<Value *, Value *>;
|
||||
|
||||
private:
|
||||
std::deque<Value*> Q;
|
||||
std::set<Value*> S;
|
||||
};
|
||||
Value *Root;
|
||||
ValueSetType Used; // The set of all cloned values used by Root.
|
||||
ValueSetType Clones; // The set of all cloned values.
|
||||
LLVMContext &Ctx;
|
||||
|
||||
using ValueSetType = std::set<Value *>;
|
||||
|
||||
std::vector<Rule> Rules;
|
||||
|
||||
public:
|
||||
struct Context {
|
||||
using ValueMapType = DenseMap<Value *, Value *>;
|
||||
|
||||
Value *Root;
|
||||
ValueSetType Used; // The set of all cloned values used by Root.
|
||||
ValueSetType Clones; // The set of all cloned values.
|
||||
LLVMContext &Ctx;
|
||||
|
||||
Context(Instruction *Exp)
|
||||
Context(Instruction *Exp)
|
||||
: Ctx(Exp->getParent()->getParent()->getContext()) {
|
||||
initialize(Exp);
|
||||
}
|
||||
initialize(Exp);
|
||||
}
|
||||
|
||||
~Context() { cleanup(); }
|
||||
~Context() { cleanup(); }
|
||||
|
||||
void print(raw_ostream &OS, const Value *V) const;
|
||||
Value *materialize(BasicBlock *B, BasicBlock::iterator At);
|
||||
void print(raw_ostream &OS, const Value *V) const;
|
||||
Value *materialize(BasicBlock *B, BasicBlock::iterator At);
|
||||
|
||||
private:
|
||||
friend struct Simplifier;
|
||||
private:
|
||||
friend struct Simplifier;
|
||||
|
||||
void initialize(Instruction *Exp);
|
||||
void cleanup();
|
||||
void initialize(Instruction *Exp);
|
||||
void cleanup();
|
||||
|
||||
template <typename FuncT> void traverse(Value *V, FuncT F);
|
||||
void record(Value *V);
|
||||
void use(Value *V);
|
||||
void unuse(Value *V);
|
||||
template <typename FuncT> void traverse(Value *V, FuncT F);
|
||||
void record(Value *V);
|
||||
void use(Value *V);
|
||||
void unuse(Value *V);
|
||||
|
||||
bool equal(const Instruction *I, const Instruction *J) const;
|
||||
Value *find(Value *Tree, Value *Sub) const;
|
||||
Value *subst(Value *Tree, Value *OldV, Value *NewV);
|
||||
void replace(Value *OldV, Value *NewV);
|
||||
void link(Instruction *I, BasicBlock *B, BasicBlock::iterator At);
|
||||
};
|
||||
|
||||
Value *simplify(Context &C);
|
||||
bool equal(const Instruction *I, const Instruction *J) const;
|
||||
Value *find(Value *Tree, Value *Sub) const;
|
||||
Value *subst(Value *Tree, Value *OldV, Value *NewV);
|
||||
void replace(Value *OldV, Value *NewV);
|
||||
void link(Instruction *I, BasicBlock *B, BasicBlock::iterator At);
|
||||
};
|
||||
|
||||
Value *simplify(Context &C);
|
||||
};
|
||||
|
||||
struct PE {
|
||||
PE(const Simplifier::Context &c, Value *v = nullptr) : C(c), V(v) {}
|
||||
|
||||
@ -253,10 +272,10 @@ namespace {
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
char HexagonLoopIdiomRecognize::ID = 0;
|
||||
char HexagonLoopIdiomRecognizeLegacyPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(HexagonLoopIdiomRecognize, "hexagon-loop-idiom",
|
||||
"Recognize Hexagon-specific loop idioms", false, false)
|
||||
INITIALIZE_PASS_BEGIN(HexagonLoopIdiomRecognizeLegacyPass, "hexagon-loop-idiom",
|
||||
"Recognize Hexagon-specific loop idioms", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
|
||||
INITIALIZE_PASS_DEPENDENCY(LCSSAWrapperPass)
|
||||
@ -264,8 +283,8 @@ INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(HexagonLoopIdiomRecognize, "hexagon-loop-idiom",
|
||||
"Recognize Hexagon-specific loop idioms", false, false)
|
||||
INITIALIZE_PASS_END(HexagonLoopIdiomRecognizeLegacyPass, "hexagon-loop-idiom",
|
||||
"Recognize Hexagon-specific loop idioms", false, false)
|
||||
|
||||
template <typename FuncT>
|
||||
void Simplifier::Context::traverse(Value *V, FuncT F) {
|
||||
@ -2404,14 +2423,11 @@ bool HexagonLoopIdiomRecognize::runOnCountableLoop(Loop *L) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
bool HexagonLoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
bool HexagonLoopIdiomRecognize::run(Loop *L) {
|
||||
const Module &M = *L->getHeader()->getParent()->getParent();
|
||||
if (Triple(M.getTargetTriple()).getArch() != Triple::hexagon)
|
||||
return false;
|
||||
|
||||
if (skipLoop(L))
|
||||
return false;
|
||||
|
||||
// If the loop could not be converted to canonical form, it must have an
|
||||
// indirectbr in it, just give up.
|
||||
if (!L->getLoopPreheader())
|
||||
@ -2422,13 +2438,7 @@ bool HexagonLoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
if (Name == "memset" || Name == "memcpy" || Name == "memmove")
|
||||
return false;
|
||||
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
DL = &L->getHeader()->getModule()->getDataLayout();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
LF = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
|
||||
*L->getHeader()->getParent());
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
|
||||
HasMemcpy = TLI->has(LibFunc_memcpy);
|
||||
HasMemmove = TLI->has(LibFunc_memmove);
|
||||
@ -2438,6 +2448,30 @@ bool HexagonLoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Pass *llvm::createHexagonLoopIdiomPass() {
|
||||
return new HexagonLoopIdiomRecognize();
|
||||
bool HexagonLoopIdiomRecognizeLegacyPass::runOnLoop(Loop *L,
|
||||
LPPassManager &LPM) {
|
||||
if (skipLoop(L))
|
||||
return false;
|
||||
|
||||
auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
auto *LF = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
|
||||
*L->getHeader()->getParent());
|
||||
auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
return HexagonLoopIdiomRecognize(AA, DT, LF, TLI, SE).run(L);
|
||||
}
|
||||
|
||||
Pass *llvm::createHexagonLoopIdiomPass() {
|
||||
return new HexagonLoopIdiomRecognizeLegacyPass();
|
||||
}
|
||||
|
||||
PreservedAnalyses
|
||||
HexagonLoopIdiomRecognitionPass::run(Loop &L, LoopAnalysisManager &AM,
|
||||
LoopStandardAnalysisResults &AR,
|
||||
LPMUpdater &U) {
|
||||
return HexagonLoopIdiomRecognize(&AR.AA, &AR.DT, &AR.LI, &AR.TLI, &AR.SE)
|
||||
.run(&L)
|
||||
? getLoopPassPreservedAnalyses()
|
||||
: PreservedAnalyses::all();
|
||||
}
|
||||
|
24
lib/Target/Hexagon/HexagonLoopIdiomRecognition.h
Normal file
24
lib/Target/Hexagon/HexagonLoopIdiomRecognition.h
Normal file
@ -0,0 +1,24 @@
|
||||
//===- HexagonLoopIdiomRecognition.h --------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONLOOPIDIOMRECOGNITION_H
|
||||
#define LLVM_LIB_TARGET_HEXAGON_HEXAGONLOOPIDIOMRECOGNITION_H
|
||||
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Transforms/Scalar/LoopPassManager.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct HexagonLoopIdiomRecognitionPass
|
||||
: PassInfoMixin<HexagonLoopIdiomRecognitionPass> {
|
||||
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
|
||||
LoopStandardAnalysisResults &AR, LPMUpdater &U);
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONLOOPIDIOMRECOGNITION_H
|
@ -13,6 +13,7 @@
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonISelLowering.h"
|
||||
#include "HexagonLoopIdiomRecognition.h"
|
||||
#include "HexagonMachineScheduler.h"
|
||||
#include "HexagonTargetObjectFile.h"
|
||||
#include "HexagonTargetTransformInfo.h"
|
||||
@ -138,7 +139,7 @@ namespace llvm {
|
||||
void initializeHexagonExpandCondsetsPass(PassRegistry&);
|
||||
void initializeHexagonGenMuxPass(PassRegistry&);
|
||||
void initializeHexagonHardwareLoopsPass(PassRegistry&);
|
||||
void initializeHexagonLoopIdiomRecognizePass(PassRegistry&);
|
||||
void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &);
|
||||
void initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PassRegistry &);
|
||||
void initializeHexagonNewValueJumpPass(PassRegistry&);
|
||||
void initializeHexagonOptAddrModePass(PassRegistry&);
|
||||
@ -197,7 +198,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeHexagonTarget() {
|
||||
initializeHexagonEarlyIfConversionPass(PR);
|
||||
initializeHexagonGenMuxPass(PR);
|
||||
initializeHexagonHardwareLoopsPass(PR);
|
||||
initializeHexagonLoopIdiomRecognizePass(PR);
|
||||
initializeHexagonLoopIdiomRecognizeLegacyPassPass(PR);
|
||||
initializeHexagonVectorLoopCarriedReuseLegacyPassPass(PR);
|
||||
initializeHexagonNewValueJumpPass(PR);
|
||||
initializeHexagonOptAddrModePass(PR);
|
||||
@ -276,6 +277,10 @@ void HexagonTargetMachine::adjustPassManager(PassManagerBuilder &PMB) {
|
||||
|
||||
void HexagonTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB,
|
||||
bool DebugPassManager) {
|
||||
PB.registerLateLoopOptimizationsEPCallback(
|
||||
[=](LoopPassManager &LPM, PassBuilder::OptimizationLevel Level) {
|
||||
LPM.addPass(HexagonLoopIdiomRecognitionPass());
|
||||
});
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
[=](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) {
|
||||
LoopPassManager LPM(DebugPassManager);
|
||||
|
@ -3,6 +3,7 @@
|
||||
; get this opportunity regardless of what happens before.
|
||||
|
||||
; RUN: opt -O2 -march=hexagon -S < %s | FileCheck %s
|
||||
; RUN: opt -aa-pipeline=default -passes='default<O2>' -march=hexagon -S < %s | FileCheck %s
|
||||
|
||||
target triple = "hexagon"
|
||||
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
|
||||
|
Loading…
Reference in New Issue
Block a user