#ifndef ENZYME_ACTIVE_VAR_H
#define ENZYME_ACTIVE_VAR_H 1
#include <cstdint>
#include <deque>
#include <llvm/Config/llvm-config.h>
#define private public
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
#undef private
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/InstVisitor.h"
#include "TypeAnalysis/TypeAnalysis.h"
#include "Utils.h"
extern "C" {
extern llvm::cl::opt<bool> EnzymePrintActivity;
extern llvm::cl::opt<bool> EnzymeNonmarkedGlobalsInactive;
extern llvm::cl::opt<bool> EnzymeGlobalActivity;
extern llvm::cl::opt<bool> EnzymeEmptyFnInactive;
extern llvm::cl::opt<bool> EnzymeEnableRecursiveHypotheses;
}
class PreProcessCache;
extern const llvm::StringMap<size_t> MPIInactiveCommAllocators;
class ActivityAnalyzer {
PreProcessCache &PPC;
llvm::AAResults &AA;
const llvm::SmallPtrSetImpl<llvm::BasicBlock *> ¬ForAnalysis;
llvm::TargetLibraryInfo &TLI;
public:
const DIFFE_TYPE ActiveReturns;
private:
const uint8_t directions;
static constexpr uint8_t UP = 1;
static constexpr uint8_t DOWN = 2;
llvm::SmallPtrSet<llvm::Instruction *, 4> ConstantInstructions;
llvm::SmallPtrSet<llvm::Instruction *, 20> ActiveInstructions;
llvm::SmallPtrSet<llvm::Value *, 4> ConstantValues;
llvm::SmallPtrSet<llvm::Value *, 2> ActiveValues;
llvm::SmallPtrSet<llvm::Value *, 1> DeducingPointers;
public:
ActivityAnalyzer(
PreProcessCache &PPC, llvm::AAResults &AA_,
const llvm::SmallPtrSetImpl<llvm::BasicBlock *> ¬ForAnalysis_,
llvm::TargetLibraryInfo &TLI_,
const llvm::SmallPtrSetImpl<llvm::Value *> &ConstantValues,
const llvm::SmallPtrSetImpl<llvm::Value *> &ActiveValues,
DIFFE_TYPE ActiveReturns)
: PPC(PPC), AA(AA_), notForAnalysis(notForAnalysis_), TLI(TLI_),
ActiveReturns(ActiveReturns), directions(UP | DOWN),
ConstantValues(ConstantValues.begin(), ConstantValues.end()),
ActiveValues(ActiveValues.begin(), ActiveValues.end()) {
InsertConstValueRecursionHandler = nullptr;
}
bool isConstantInstruction(TypeResults const &TR, llvm::Instruction *inst);
bool isConstantValue(TypeResults const &TR, llvm::Value *val);
private:
llvm::DenseMap<llvm::Instruction *, llvm::SmallPtrSet<llvm::Value *, 4>>
ReEvaluateValueIfInactiveInst;
llvm::DenseMap<llvm::Value *, llvm::SmallPtrSet<llvm::Value *, 4>>
ReEvaluateValueIfInactiveValue;
llvm::DenseMap<llvm::Value *, llvm::SmallPtrSet<llvm::Instruction *, 4>>
ReEvaluateInstIfInactiveValue;
void InsertConstantInstruction(TypeResults const &TR, llvm::Instruction *I);
llvm::SmallVector<llvm::Value *, 1> *InsertConstValueRecursionHandler;
void InsertConstantValue(TypeResults const &TR, llvm::Value *V);
ActivityAnalyzer(ActivityAnalyzer &Other, uint8_t directions)
: PPC(Other.PPC), AA(Other.AA), notForAnalysis(Other.notForAnalysis),
TLI(Other.TLI), ActiveReturns(Other.ActiveReturns),
directions(directions),
ConstantInstructions(Other.ConstantInstructions),
ActiveInstructions(Other.ActiveInstructions),
ConstantValues(Other.ConstantValues), ActiveValues(Other.ActiveValues),
DeducingPointers(Other.DeducingPointers) {
assert(directions != 0);
assert((directions & Other.directions) == directions);
assert((directions & Other.directions) != 0);
InsertConstValueRecursionHandler = nullptr;
}
void insertConstantsFrom(TypeResults const &TR,
ActivityAnalyzer &Hypothesis) {
for (auto I : Hypothesis.ConstantInstructions) {
InsertConstantInstruction(TR, I);
}
for (auto V : Hypothesis.ConstantValues) {
InsertConstantValue(TR, V);
}
}
void insertAllFrom(TypeResults const &TR, ActivityAnalyzer &Hypothesis,
llvm::Value *Orig, llvm::Value *Orig2 = nullptr) {
insertConstantsFrom(TR, Hypothesis);
for (auto I : Hypothesis.ActiveInstructions) {
bool inserted = ActiveInstructions.insert(I).second;
if (inserted && directions == 3 && EnzymeEnableRecursiveHypotheses) {
ReEvaluateInstIfInactiveValue[Orig].insert(I);
if (Orig2 && Orig2 != Orig)
ReEvaluateInstIfInactiveValue[Orig2].insert(I);
}
}
for (auto V : Hypothesis.ActiveValues) {
bool inserted = ActiveValues.insert(V).second;
if (inserted && directions == 3 && EnzymeEnableRecursiveHypotheses) {
ReEvaluateValueIfInactiveValue[Orig].insert(V);
if (Orig2 && Orig2 != Orig)
ReEvaluateValueIfInactiveValue[Orig2].insert(V);
}
}
for (auto &pair : Hypothesis.ReEvaluateValueIfInactiveInst) {
ReEvaluateValueIfInactiveValue[pair.first].insert(pair.second.begin(),
pair.second.end());
if (ConstantInstructions.count(pair.first)) {
InsertConstantInstruction(TR, pair.first);
}
}
for (auto &pair : Hypothesis.ReEvaluateInstIfInactiveValue) {
ReEvaluateInstIfInactiveValue[pair.first].insert(pair.second.begin(),
pair.second.end());
if (ConstantValues.count(pair.first)) {
InsertConstantValue(TR, pair.first);
}
}
for (auto &pair : Hypothesis.ReEvaluateValueIfInactiveValue) {
ReEvaluateValueIfInactiveValue[pair.first].insert(pair.second.begin(),
pair.second.end());
if (ConstantValues.count(pair.first)) {
InsertConstantValue(TR, pair.first);
}
}
}
bool isFunctionArgumentConstant(llvm::CallInst *CI, llvm::Value *val);
bool isInstructionInactiveFromOrigin(TypeResults const &TR, llvm::Value *val,
bool considerValue);
public:
enum class UseActivity {
None = 0,
OnlyLoads = 1,
OnlyStores = 2,
OnlyNonPointerStores = 3,
AllStores = 4
};
bool isValueInactiveFromUsers(TypeResults const &TR, llvm::Value *val,
UseActivity UA,
llvm::Instruction **FoundInst = nullptr,
llvm::Value **FoundValue = nullptr);
bool isValueActivelyStoredOrReturned(TypeResults const &TR, llvm::Value *val,
bool outside = false);
private:
std::map<std::pair<bool, llvm::Value *>, bool> StoredOrReturnedCache;
};
constexpr inline const char *to_string(ActivityAnalyzer::UseActivity UA) {
switch (UA) {
case ActivityAnalyzer::UseActivity::None:
return "None";
case ActivityAnalyzer::UseActivity::OnlyLoads:
return "OnlyLoads";
case ActivityAnalyzer::UseActivity::OnlyStores:
return "OnlyStores";
case ActivityAnalyzer::UseActivity::OnlyNonPointerStores:
return "OnlyNonPointerStores";
case ActivityAnalyzer::UseActivity::AllStores:
return "AllStores";
}
return "<IllegaluseActivity>";
}
#endif