#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/InstSimplifyFolder.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsHexagon.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/Local.h"
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
#include <algorithm>
#include <deque>
#include <map>
#include <optional>
#include <set>
#include <utility>
#include <vector>
#define DEBUG_TYPE …
usingnamespacellvm;
namespace {
cl::opt<bool> DumpModule("hvc-dump-module", cl::Hidden);
cl::opt<bool> VAEnabled("hvc-va", cl::Hidden, cl::init(true));
cl::opt<bool> VIEnabled("hvc-vi", cl::Hidden, cl::init(true));
cl::opt<bool> VADoFullStores("hvc-va-full-stores", cl::Hidden);
cl::opt<unsigned> VAGroupCountLimit("hvc-va-group-count-limit", cl::Hidden,
cl::init(~0));
cl::opt<unsigned> VAGroupSizeLimit("hvc-va-group-size-limit", cl::Hidden,
cl::init(~0));
class HexagonVectorCombine { … };
class AlignVectors { … };
LLVM_ATTRIBUTE_UNUSED
raw_ostream &operator<<(raw_ostream &OS, const AlignVectors::AddrInfo &AI) { … }
LLVM_ATTRIBUTE_UNUSED
raw_ostream &operator<<(raw_ostream &OS, const AlignVectors::MoveGroup &MG) { … }
LLVM_ATTRIBUTE_UNUSED
raw_ostream &operator<<(raw_ostream &OS,
const AlignVectors::ByteSpan::Block &B) { … }
LLVM_ATTRIBUTE_UNUSED
raw_ostream &operator<<(raw_ostream &OS, const AlignVectors::ByteSpan &BS) { … }
class HvxIdioms { … };
[[maybe_unused]] raw_ostream &operator<<(raw_ostream &OS,
const HvxIdioms::FxpOp &Op) { … }
}
namespace {
template <typename T> T *getIfUnordered(T *MaybeT) { … }
template <typename T> T *isCandidate(Instruction *In) { … }
template <> LoadInst *isCandidate<LoadInst>(Instruction *In) { … }
template <> StoreInst *isCandidate<StoreInst>(Instruction *In) { … }
#if !defined(_MSC_VER) || _MSC_VER >= 1926
template <typename Pred, typename... Ts>
void erase_if(std::map<Ts...> &map, Pred p)
#else
template <typename Pred, typename T, typename U>
void erase_if(std::map<T, U> &map, Pred p)
#endif
{ … }
template <typename Pred, typename T> void erase_if(T &&container, Pred p) { … }
}
auto AlignVectors::ByteSpan::extent() const -> int { … }
auto AlignVectors::ByteSpan::section(int Start, int Length) const -> ByteSpan { … }
auto AlignVectors::ByteSpan::shift(int Offset) -> ByteSpan & { … }
auto AlignVectors::ByteSpan::values() const -> SmallVector<Value *, 8> { … }
auto AlignVectors::getAlignFromValue(const Value *V) const -> Align { … }
auto AlignVectors::getAddrInfo(Instruction &In) const
-> std::optional<AddrInfo> { … }
auto AlignVectors::isHvx(const AddrInfo &AI) const -> bool { … }
auto AlignVectors::getPayload(Value *Val) const -> Value * { … }
auto AlignVectors::getMask(Value *Val) const -> Value * { … }
auto AlignVectors::getPassThrough(Value *Val) const -> Value * { … }
auto AlignVectors::createAdjustedPointer(IRBuilderBase &Builder, Value *Ptr,
Type *ValTy, int Adjust,
const InstMap &CloneMap) const
-> Value * { … }
auto AlignVectors::createAlignedPointer(IRBuilderBase &Builder, Value *Ptr,
Type *ValTy, int Alignment,
const InstMap &CloneMap) const
-> Value * { … }
auto AlignVectors::createLoad(IRBuilderBase &Builder, Type *ValTy, Value *Ptr,
Value *Predicate, int Alignment, Value *Mask,
Value *PassThru,
ArrayRef<Value *> MDSources) const -> Value * { … }
auto AlignVectors::createSimpleLoad(IRBuilderBase &Builder, Type *ValTy,
Value *Ptr, int Alignment,
ArrayRef<Value *> MDSources) const
-> Value * { … }
auto AlignVectors::createPredicatedLoad(IRBuilderBase &Builder, Type *ValTy,
Value *Ptr, Value *Predicate,
int Alignment,
ArrayRef<Value *> MDSources) const
-> Value * { … }
auto AlignVectors::createStore(IRBuilderBase &Builder, Value *Val, Value *Ptr,
Value *Predicate, int Alignment, Value *Mask,
ArrayRef<Value *> MDSources) const -> Value * { … }
auto AlignVectors::createSimpleStore(IRBuilderBase &Builder, Value *Val,
Value *Ptr, int Alignment,
ArrayRef<Value *> MDSources) const
-> Value * { … }
auto AlignVectors::createPredicatedStore(IRBuilderBase &Builder, Value *Val,
Value *Ptr, Value *Predicate,
int Alignment,
ArrayRef<Value *> MDSources) const
-> Value * { … }
auto AlignVectors::getUpwardDeps(Instruction *In, Instruction *Base) const
-> DepList { … }
auto AlignVectors::createAddressGroups() -> bool { … }
auto AlignVectors::createLoadGroups(const AddrList &Group) const -> MoveList { … }
auto AlignVectors::createStoreGroups(const AddrList &Group) const -> MoveList { … }
auto AlignVectors::moveTogether(MoveGroup &Move) const -> bool { … }
template <typename T>
auto AlignVectors::cloneBefore(Instruction *To, T &&Insts) const -> InstMap { … }
auto AlignVectors::realignLoadGroup(IRBuilderBase &Builder,
const ByteSpan &VSpan, int ScLen,
Value *AlignVal, Value *AlignAddr) const
-> void { … }
auto AlignVectors::realignStoreGroup(IRBuilderBase &Builder,
const ByteSpan &VSpan, int ScLen,
Value *AlignVal, Value *AlignAddr) const
-> void { … }
auto AlignVectors::realignGroup(const MoveGroup &Move) const -> bool { … }
auto AlignVectors::makeTestIfUnaligned(IRBuilderBase &Builder, Value *AlignVal,
int Alignment) const -> Value * { … }
auto AlignVectors::isSectorTy(Type *Ty) const -> bool { … }
auto AlignVectors::run() -> bool { … }
auto HvxIdioms::getNumSignificantBits(Value *V, Instruction *In) const
-> std::pair<unsigned, Signedness> { … }
auto HvxIdioms::canonSgn(SValue X, SValue Y) const
-> std::pair<SValue, SValue> { … }
auto HvxIdioms::matchFxpMul(Instruction &In) const -> std::optional<FxpOp> { … }
auto HvxIdioms::processFxpMul(Instruction &In, const FxpOp &Op) const
-> Value * { … }
auto HvxIdioms::processFxpMulChopped(IRBuilderBase &Builder, Instruction &In,
const FxpOp &Op) const -> Value * { … }
auto HvxIdioms::createMulQ15(IRBuilderBase &Builder, SValue X, SValue Y,
bool Rounding) const -> Value * { … }
auto HvxIdioms::createMulQ31(IRBuilderBase &Builder, SValue X, SValue Y,
bool Rounding) const -> Value * { … }
auto HvxIdioms::createAddCarry(IRBuilderBase &Builder, Value *X, Value *Y,
Value *CarryIn) const
-> std::pair<Value *, Value *> { … }
auto HvxIdioms::createMul16(IRBuilderBase &Builder, SValue X, SValue Y) const
-> Value * { … }
auto HvxIdioms::createMulH16(IRBuilderBase &Builder, SValue X, SValue Y) const
-> Value * { … }
auto HvxIdioms::createMul32(IRBuilderBase &Builder, SValue X, SValue Y) const
-> std::pair<Value *, Value *> { … }
auto HvxIdioms::createAddLong(IRBuilderBase &Builder, ArrayRef<Value *> WordX,
ArrayRef<Value *> WordY) const
-> SmallVector<Value *> { … }
auto HvxIdioms::createMulLong(IRBuilderBase &Builder, ArrayRef<Value *> WordX,
Signedness SgnX, ArrayRef<Value *> WordY,
Signedness SgnY) const -> SmallVector<Value *> { … }
auto HvxIdioms::run() -> bool { … }
auto HexagonVectorCombine::run() -> bool { … }
auto HexagonVectorCombine::getIntTy(unsigned Width) const -> IntegerType * { … }
auto HexagonVectorCombine::getByteTy(int ElemCount) const -> Type * { … }
auto HexagonVectorCombine::getBoolTy(int ElemCount) const -> Type * { … }
auto HexagonVectorCombine::getConstInt(int Val, unsigned Width) const
-> ConstantInt * { … }
auto HexagonVectorCombine::isZero(const Value *Val) const -> bool { … }
auto HexagonVectorCombine::getIntValue(const Value *Val) const
-> std::optional<APInt> { … }
auto HexagonVectorCombine::isUndef(const Value *Val) const -> bool { … }
auto HexagonVectorCombine::isTrue(const Value *Val) const -> bool { … }
auto HexagonVectorCombine::isFalse(const Value *Val) const -> bool { … }
auto HexagonVectorCombine::getHvxTy(Type *ElemTy, bool Pair) const
-> VectorType * { … }
auto HexagonVectorCombine::getSizeOf(const Value *Val, SizeKind Kind) const
-> int { … }
auto HexagonVectorCombine::getSizeOf(const Type *Ty, SizeKind Kind) const
-> int { … }
auto HexagonVectorCombine::getTypeAlignment(Type *Ty) const -> int { … }
auto HexagonVectorCombine::length(Value *Val) const -> size_t { … }
auto HexagonVectorCombine::length(Type *Ty) const -> size_t { … }
auto HexagonVectorCombine::getNullValue(Type *Ty) const -> Constant * { … }
auto HexagonVectorCombine::getFullValue(Type *Ty) const -> Constant * { … }
auto HexagonVectorCombine::getConstSplat(Type *Ty, int Val) const
-> Constant * { … }
auto HexagonVectorCombine::simplify(Value *V) const -> Value * { … }
auto HexagonVectorCombine::insertb(IRBuilderBase &Builder, Value *Dst,
Value *Src, int Start, int Length,
int Where) const -> Value * { … }
auto HexagonVectorCombine::vlalignb(IRBuilderBase &Builder, Value *Lo,
Value *Hi, Value *Amt) const -> Value * { … }
auto HexagonVectorCombine::vralignb(IRBuilderBase &Builder, Value *Lo,
Value *Hi, Value *Amt) const -> Value * { … }
auto HexagonVectorCombine::concat(IRBuilderBase &Builder,
ArrayRef<Value *> Vecs) const -> Value * { … }
auto HexagonVectorCombine::vresize(IRBuilderBase &Builder, Value *Val,
int NewSize, Value *Pad) const -> Value * { … }
auto HexagonVectorCombine::rescale(IRBuilderBase &Builder, Value *Mask,
Type *FromTy, Type *ToTy) const -> Value * { … }
auto HexagonVectorCombine::vlsb(IRBuilderBase &Builder, Value *Val) const
-> Value * { … }
auto HexagonVectorCombine::vbytes(IRBuilderBase &Builder, Value *Val) const
-> Value * { … }
auto HexagonVectorCombine::subvector(IRBuilderBase &Builder, Value *Val,
unsigned Start, unsigned Length) const
-> Value * { … }
auto HexagonVectorCombine::sublo(IRBuilderBase &Builder, Value *Val) const
-> Value * { … }
auto HexagonVectorCombine::subhi(IRBuilderBase &Builder, Value *Val) const
-> Value * { … }
auto HexagonVectorCombine::vdeal(IRBuilderBase &Builder, Value *Val0,
Value *Val1) const -> Value * { … }
auto HexagonVectorCombine::vshuff(IRBuilderBase &Builder, Value *Val0,
Value *Val1) const -> Value * { … }
auto HexagonVectorCombine::createHvxIntrinsic(IRBuilderBase &Builder,
Intrinsic::ID IntID, Type *RetTy,
ArrayRef<Value *> Args,
ArrayRef<Type *> ArgTys,
ArrayRef<Value *> MDSources) const
-> Value * { … }
auto HexagonVectorCombine::splitVectorElements(IRBuilderBase &Builder,
Value *Vec,
unsigned ToWidth) const
-> SmallVector<Value *> { … }
auto HexagonVectorCombine::joinVectorElements(IRBuilderBase &Builder,
ArrayRef<Value *> Values,
VectorType *ToType) const
-> Value * { … }
auto HexagonVectorCombine::calculatePointerDifference(Value *Ptr0,
Value *Ptr1) const
-> std::optional<int> { … }
auto HexagonVectorCombine::getNumSignificantBits(const Value *V,
const Instruction *CtxI) const
-> unsigned { … }
auto HexagonVectorCombine::getKnownBits(const Value *V,
const Instruction *CtxI) const
-> KnownBits { … }
auto HexagonVectorCombine::isSafeToClone(const Instruction &In) const -> bool { … }
template <typename T>
auto HexagonVectorCombine::isSafeToMoveBeforeInBB(const Instruction &In,
BasicBlock::const_iterator To,
const T &IgnoreInsts) const
-> bool { … }
auto HexagonVectorCombine::isByteVecTy(Type *Ty) const -> bool { … }
auto HexagonVectorCombine::getElementRange(IRBuilderBase &Builder, Value *Lo,
Value *Hi, int Start,
int Length) const -> Value * { … }
namespace llvm {
void initializeHexagonVectorCombineLegacyPass(PassRegistry &);
FunctionPass *createHexagonVectorCombineLegacyPass();
}
namespace {
class HexagonVectorCombineLegacy : public FunctionPass { … };
}
char HexagonVectorCombineLegacy::ID = …;
INITIALIZE_PASS_BEGIN(HexagonVectorCombineLegacy, DEBUG_TYPE,
"Hexagon Vector Combine", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_END(HexagonVectorCombineLegacy, DEBUG_TYPE,
"Hexagon Vector Combine", false, false)
FunctionPass *llvm::createHexagonVectorCombineLegacyPass() { … }