1
0
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:
Arthur Eubanks 2020-11-19 15:52:21 -08:00
parent ca0b0997cf
commit 04d409f2b1
4 changed files with 182 additions and 118 deletions

View File

@ -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();
}

View 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

View File

@ -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);

View File

@ -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"