~ninjin/julia-nix

e126fcdeaaa8e5732abaecc1af73ed387245b0ff — Valentin Churavy 2 years ago 86184db
[LLVM][PM] Make LowerSIMDLoop NewPM compatible (#40884)

* [LLVM][PM] Make LowerSIMDLoop NewPM compatible
* [LLVM][PM] Make DemoteFloat16 NewPM compatible
* [LLVM][PM] Make MulAdd NewPM compatible
* [LLVM][PM] Make RemoveNI NewPM compatible
4 files changed, 170 insertions(+), 91 deletions(-)

M src/llvm-demote-float16.cpp
M src/llvm-muladd.cpp
M src/llvm-remove-ni.cpp
M src/llvm-simdloop.cpp
M src/llvm-demote-float16.cpp => src/llvm-demote-float16.cpp +30 -13
@@ 20,6 20,7 @@

#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/Debug.h>



@@ 27,15 28,7 @@ using namespace llvm;

namespace {

struct DemoteFloat16Pass : public FunctionPass {
    static char ID;
    DemoteFloat16Pass() : FunctionPass(ID){};

private:
    bool runOnFunction(Function &F) override;
};

bool DemoteFloat16Pass::runOnFunction(Function &F)
static bool demoteFloat16(Function &F)
{
    auto &ctx = F.getContext();
    auto T_float16 = Type::getHalfTy(ctx);


@@ 132,17 125,41 @@ bool DemoteFloat16Pass::runOnFunction(Function &F)
        return false;
}

char DemoteFloat16Pass::ID = 0;
static RegisterPass<DemoteFloat16Pass>
} // end anonymous namespace

struct DemoteFloat16 : PassInfoMixin<DemoteFloat16> {
    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};

PreservedAnalyses DemoteFloat16::run(Function &F, FunctionAnalysisManager &AM)
{
    demoteFloat16(F);
    return PreservedAnalyses::all();
}

namespace {

struct DemoteFloat16Legacy : public FunctionPass {
    static char ID;
    DemoteFloat16Legacy() : FunctionPass(ID){};

private:
    bool runOnFunction(Function &F) override {
        return demoteFloat16(F);
    }
};

char DemoteFloat16Legacy::ID = 0;
static RegisterPass<DemoteFloat16Legacy>
        Y("DemoteFloat16",
          "Demote Float16 operations to Float32 equivalents.",
          false,
          false);
}
} // end anonymous namespac

Pass *createDemoteFloat16Pass()
{
    return new DemoteFloat16Pass();
    return new DemoteFloat16Legacy();
}

extern "C" JL_DLLEXPORT void LLVMExtraAddDemoteFloat16Pass(LLVMPassManagerRef PM)

M src/llvm-muladd.cpp => src/llvm-muladd.cpp +27 -13
@@ 9,6 9,7 @@

#include <llvm/IR/Value.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IntrinsicInst.h>


@@ 34,15 35,6 @@ using namespace llvm;
 * when `%v0` has no other use
 */

struct CombineMulAdd : public FunctionPass {
    static char ID;
    CombineMulAdd() : FunctionPass(ID)
    {}

private:
    bool runOnFunction(Function &F) override;
};

// Return true if this function shouldn't be called again on the other operand
// This will always return false on LLVM 5.0+
static bool checkCombine(Module *m, Instruction *addOp, Value *maybeMul, Value *addend,


@@ 60,7 52,7 @@ static bool checkCombine(Module *m, Instruction *addOp, Value *maybeMul, Value *
    return false;
}

bool CombineMulAdd::runOnFunction(Function &F)
static bool combineMulAdd(Function &F)
{
    Module *m = F.getParent();
    for (auto &BB: F) {


@@ 90,14 82,36 @@ bool CombineMulAdd::runOnFunction(Function &F)
    return true;
}

char CombineMulAdd::ID = 0;
static RegisterPass<CombineMulAdd> X("CombineMulAdd", "Combine mul and add to muladd",
struct CombineMulAdd : PassInfoMixin<CombineMulAdd> {
    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};

PreservedAnalyses CombineMulAdd::run(Function &F, FunctionAnalysisManager &AM)
{
    combineMulAdd(F);
    return PreservedAnalyses::all();
}


struct CombineMulAddLegacy : public FunctionPass {
    static char ID;
    CombineMulAddLegacy() : FunctionPass(ID)
    {}

private:
    bool runOnFunction(Function &F) override {
        return combineMulAdd(F);
    }
};

char CombineMulAddLegacy::ID = 0;
static RegisterPass<CombineMulAddLegacy> X("CombineMulAdd", "Combine mul and add to muladd",
                                     false /* Only looks at CFG */,
                                     false /* Analysis Pass */);

Pass *createCombineMulAddPass()
{
    return new CombineMulAdd();
    return new CombineMulAddLegacy();
}

extern "C" JL_DLLEXPORT void LLVMExtraAddCombineMulAddPass(LLVMPassManagerRef PM)

M src/llvm-remove-ni.cpp => src/llvm-remove-ni.cpp +37 -19
@@ 3,6 3,7 @@
#include "llvm-version.h"

#include <llvm/IR/Module.h>
#include <llvm/IR/PassManager.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/Support/Debug.h>



@@ 14,31 15,48 @@ using namespace llvm;

namespace {

struct RemoveNIPass : public ModulePass {
static bool removeNI(Module &M)
{
    auto dlstr = M.getDataLayoutStr();
    auto nistart = dlstr.find("-ni:");
    if (nistart == std::string::npos)
        return false;
    auto len = dlstr.size();
    auto niend = nistart + 1;
    for (; niend < len; niend++) {
        if (dlstr[niend] == '-') {
            break;
        }
    }
    dlstr.erase(nistart, niend - nistart);
    M.setDataLayout(dlstr);
    return true;
}
}

struct RemoveNI : PassInfoMixin<RemoveNI> {
    PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};

PreservedAnalyses RemoveNI::run(Module &M, ModuleAnalysisManager &AM)
{
    removeNI(M);
    return PreservedAnalyses::all();
}

namespace {
struct RemoveNILegacy : public ModulePass {
    static char ID;
    RemoveNIPass() : ModulePass(ID) {};
    RemoveNILegacy() : ModulePass(ID) {};

    bool runOnModule(Module &M)
    {
        auto dlstr = M.getDataLayoutStr();
        auto nistart = dlstr.find("-ni:");
        if (nistart == std::string::npos)
            return false;
        auto len = dlstr.size();
        auto niend = nistart + 1;
        for (; niend < len; niend++) {
            if (dlstr[niend] == '-') {
                break;
            }
        }
        dlstr.erase(nistart, niend - nistart);
        M.setDataLayout(dlstr);
        return true;
        return removeNI(M);
    }
};

char RemoveNIPass::ID = 0;
static RegisterPass<RemoveNIPass>
char RemoveNILegacy::ID = 0;
static RegisterPass<RemoveNILegacy>
        Y("RemoveNI",
          "Remove non-integral address space.",
          false,


@@ 47,7 65,7 @@ static RegisterPass<RemoveNIPass>

Pass *createRemoveNIPass()
{
    return new RemoveNIPass();
    return new RemoveNILegacy();
}

extern "C" JL_DLLEXPORT void LLVMExtraAddRemoveNIPass(LLVMPassManagerRef PM)

M src/llvm-simdloop.cpp => src/llvm-simdloop.cpp +76 -46
@@ 30,35 30,7 @@

namespace llvm {


/// This pass should run after reduction variables have been converted to phi nodes,
/// otherwise floating-point reductions might not be recognized as such and
/// prevent SIMDization.
struct LowerSIMDLoop : public ModulePass {
    static char ID;
    LowerSIMDLoop() : ModulePass(ID)
    {
    }

    protected:
    void getAnalysisUsage(AnalysisUsage &AU) const override
    {
        ModulePass::getAnalysisUsage(AU);
        AU.addRequired<LoopInfoWrapperPass>();
        AU.addPreserved<LoopInfoWrapperPass>();
        AU.setPreservesCFG();
    }

    private:
    bool runOnModule(Module &M) override;

    bool markLoopInfo(Module &M, Function *marker);

    /// If Phi is part of a reduction cycle of FAdd, FSub, FMul or FDiv,
    /// mark the ops as permitting reassociation/commuting.
    /// As of LLVM 4.0, FDiv is not handled by the loop vectorizer
    void enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const;
};
namespace {

static unsigned getReduceOpcode(Instruction *J, Instruction *operand)
{


@@ 80,7 52,10 @@ static unsigned getReduceOpcode(Instruction *J, Instruction *operand)
    }
}

void LowerSIMDLoop::enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const
/// If Phi is part of a reduction cycle of FAdd, FSub, FMul or FDiv,
/// mark the ops as permitting reassociation/commuting.
/// As of LLVM 4.0, FDiv is not handled by the loop vectorizer
static void enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L)
{
    typedef SmallVector<Instruction*, 8> chainVector;
    chainVector chain;


@@ 130,18 105,7 @@ void LowerSIMDLoop::enableUnsafeAlgebraIfReduction(PHINode *Phi, Loop *L) const
    }
}

bool LowerSIMDLoop::runOnModule(Module &M)
{
    Function *loopinfo_marker = M.getFunction("julia.loopinfo_marker");

    bool Changed = false;
    if (loopinfo_marker)
        Changed |= markLoopInfo(M, loopinfo_marker);

    return Changed;
}

bool LowerSIMDLoop::markLoopInfo(Module &M, Function *marker)
static bool markLoopInfo(Module &M, Function *marker, function_ref<LoopInfo &(Function &)> GetLI)
{
    bool Changed = false;
    std::vector<Instruction*> ToDelete;


@@ 149,7 113,7 @@ bool LowerSIMDLoop::markLoopInfo(Module &M, Function *marker)
        Instruction *I = cast<Instruction>(U);
        ToDelete.push_back(I);

        LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>(*I->getParent()->getParent()).getLoopInfo();
        LoopInfo &LI = GetLI(*I->getParent()->getParent());
        Loop *L = LI.getLoopFor(I->getParent());
        I->removeFromParent();
        if (!L)


@@ 243,15 207,81 @@ bool LowerSIMDLoop::markLoopInfo(Module &M, Function *marker)
    return Changed;
}

char LowerSIMDLoop::ID = 0;
} // end anonymous namespace


/// This pass should run after reduction variables have been converted to phi nodes,
/// otherwise floating-point reductions might not be recognized as such and
/// prevent SIMDization.
struct LowerSIMDLoop : PassInfoMixin<LowerSIMDLoop> {
    PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};


PreservedAnalyses LowerSIMDLoop::run(Module &M, ModuleAnalysisManager &AM)
{
    Function *loopinfo_marker = M.getFunction("julia.loopinfo_marker");

    if (!loopinfo_marker)
        return PreservedAnalyses::all();

    FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();

    auto GetLI = [&FAM](Function &F) -> LoopInfo & {
        return FAM.getResult<LoopAnalysis>(F);
    };

    markLoopInfo(M, loopinfo_marker, GetLI);

    return PreservedAnalyses::all();
}

namespace {
class LowerSIMDLoopLegacy : public ModulePass {
    LowerSIMDLoop Impl;

public:
  static char ID;

  LowerSIMDLoopLegacy() : ModulePass(ID) {
  }

  bool runOnModule(Module &M) override {
    bool Changed = false;

    Function *loopinfo_marker = M.getFunction("julia.loopinfo_marker");

    auto GetLI = [this](Function &F) -> LoopInfo & {
        return getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
    };

    if (loopinfo_marker)
        Changed |= markLoopInfo(M, loopinfo_marker, GetLI);

    return Changed;
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override
  {
      ModulePass::getAnalysisUsage(AU);
      AU.addRequired<LoopInfoWrapperPass>();
      AU.addPreserved<LoopInfoWrapperPass>();
      AU.setPreservesCFG();
  }
};

} // end anonymous namespace

char LowerSIMDLoopLegacy::ID = 0;

static RegisterPass<LowerSIMDLoop> X("LowerSIMDLoop", "LowerSIMDLoop Pass",
static RegisterPass<LowerSIMDLoopLegacy> X("LowerSIMDLoop", "LowerSIMDLoop Pass",
                                     false /* Only looks at CFG */,
                                     false /* Analysis Pass */);

JL_DLLEXPORT Pass *createLowerSimdLoopPass()
{
    return new LowerSIMDLoop();
    return new LowerSIMDLoopLegacy();
}

extern "C" JL_DLLEXPORT void LLVMExtraAddLowerSimdLoopPass(LLVMPassManagerRef PM)