mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
1981a68b4b
This patch moves some helper functions related to interleaved access vectorization out of LoopVectorize.cpp and into VectorUtils.cpp. We would like to use these functions in a follow-on patch that improves interleaved load and store lowering in (ARM/AArch64)ISelLowering.cpp. One of the functions was already duplicated there and has been removed. Differential Revision: https://reviews.llvm.org/D29398 llvm-svn: 293788
182 lines
7.3 KiB
C++
182 lines
7.3 KiB
C++
//===- llvm/Analysis/VectorUtils.h - Vector utilities -----------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines some vectorizer utilities.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_ANALYSIS_VECTORUTILS_H
|
|
#define LLVM_ANALYSIS_VECTORUTILS_H
|
|
|
|
#include "llvm/ADT/MapVector.h"
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
#include "llvm/IR/IRBuilder.h"
|
|
|
|
namespace llvm {
|
|
|
|
template <typename T> class ArrayRef;
|
|
class DemandedBits;
|
|
class GetElementPtrInst;
|
|
class Loop;
|
|
class ScalarEvolution;
|
|
class TargetTransformInfo;
|
|
class Type;
|
|
class Value;
|
|
|
|
namespace Intrinsic {
|
|
enum ID : unsigned;
|
|
}
|
|
|
|
/// \brief Identify if the intrinsic is trivially vectorizable.
|
|
/// This method returns true if the intrinsic's argument types are all
|
|
/// scalars for the scalar form of the intrinsic and all vectors for
|
|
/// the vector form of the intrinsic.
|
|
bool isTriviallyVectorizable(Intrinsic::ID ID);
|
|
|
|
/// \brief Identifies if the intrinsic has a scalar operand. It checks for
|
|
/// ctlz,cttz and powi special intrinsics whose argument is scalar.
|
|
bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx);
|
|
|
|
/// \brief Returns intrinsic ID for call.
|
|
/// For the input call instruction it finds mapping intrinsic and returns
|
|
/// its intrinsic ID, in case it does not found it return not_intrinsic.
|
|
Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI,
|
|
const TargetLibraryInfo *TLI);
|
|
|
|
/// \brief Find the operand of the GEP that should be checked for consecutive
|
|
/// stores. This ignores trailing indices that have no effect on the final
|
|
/// pointer.
|
|
unsigned getGEPInductionOperand(const GetElementPtrInst *Gep);
|
|
|
|
/// \brief If the argument is a GEP, then returns the operand identified by
|
|
/// getGEPInductionOperand. However, if there is some other non-loop-invariant
|
|
/// operand, it returns that instead.
|
|
Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp);
|
|
|
|
/// \brief If a value has only one user that is a CastInst, return it.
|
|
Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty);
|
|
|
|
/// \brief Get the stride of a pointer access in a loop. Looks for symbolic
|
|
/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise.
|
|
Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp);
|
|
|
|
/// \brief Given a vector and an element number, see if the scalar value is
|
|
/// already around as a register, for example if it were inserted then extracted
|
|
/// from the vector.
|
|
Value *findScalarElement(Value *V, unsigned EltNo);
|
|
|
|
/// \brief Get splat value if the input is a splat vector or return nullptr.
|
|
/// The value may be extracted from a splat constants vector or from
|
|
/// a sequence of instructions that broadcast a single value into a vector.
|
|
const Value *getSplatValue(const Value *V);
|
|
|
|
/// \brief Compute a map of integer instructions to their minimum legal type
|
|
/// size.
|
|
///
|
|
/// C semantics force sub-int-sized values (e.g. i8, i16) to be promoted to int
|
|
/// type (e.g. i32) whenever arithmetic is performed on them.
|
|
///
|
|
/// For targets with native i8 or i16 operations, usually InstCombine can shrink
|
|
/// the arithmetic type down again. However InstCombine refuses to create
|
|
/// illegal types, so for targets without i8 or i16 registers, the lengthening
|
|
/// and shrinking remains.
|
|
///
|
|
/// Most SIMD ISAs (e.g. NEON) however support vectors of i8 or i16 even when
|
|
/// their scalar equivalents do not, so during vectorization it is important to
|
|
/// remove these lengthens and truncates when deciding the profitability of
|
|
/// vectorization.
|
|
///
|
|
/// This function analyzes the given range of instructions and determines the
|
|
/// minimum type size each can be converted to. It attempts to remove or
|
|
/// minimize type size changes across each def-use chain, so for example in the
|
|
/// following code:
|
|
///
|
|
/// %1 = load i8, i8*
|
|
/// %2 = add i8 %1, 2
|
|
/// %3 = load i16, i16*
|
|
/// %4 = zext i8 %2 to i32
|
|
/// %5 = zext i16 %3 to i32
|
|
/// %6 = add i32 %4, %5
|
|
/// %7 = trunc i32 %6 to i16
|
|
///
|
|
/// Instruction %6 must be done at least in i16, so computeMinimumValueSizes
|
|
/// will return: {%1: 16, %2: 16, %3: 16, %4: 16, %5: 16, %6: 16, %7: 16}.
|
|
///
|
|
/// If the optional TargetTransformInfo is provided, this function tries harder
|
|
/// to do less work by only looking at illegal types.
|
|
MapVector<Instruction*, uint64_t>
|
|
computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks,
|
|
DemandedBits &DB,
|
|
const TargetTransformInfo *TTI=nullptr);
|
|
|
|
/// Specifically, let Kinds = [MD_tbaa, MD_alias_scope, MD_noalias, MD_fpmath,
|
|
/// MD_nontemporal]. For K in Kinds, we get the MDNode for K from each of the
|
|
/// elements of VL, compute their "intersection" (i.e., the most generic
|
|
/// metadata value that covers all of the individual values), and set I's
|
|
/// metadata for M equal to the intersection value.
|
|
///
|
|
/// This function always sets a (possibly null) value for each K in Kinds.
|
|
Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
|
|
|
|
/// \brief Create an interleave shuffle mask.
|
|
///
|
|
/// This function creates a shuffle mask for interleaving \p NumVecs vectors of
|
|
/// vectorization factor \p VF into a single wide vector. The mask is of the
|
|
/// form:
|
|
///
|
|
/// <0, VF, VF * 2, ..., VF * (NumVecs - 1), 1, VF + 1, VF * 2 + 1, ...>
|
|
///
|
|
/// For example, the mask for VF = 4 and NumVecs = 2 is:
|
|
///
|
|
/// <0, 4, 1, 5, 2, 6, 3, 7>.
|
|
Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF,
|
|
unsigned NumVecs);
|
|
|
|
/// \brief Create a stride shuffle mask.
|
|
///
|
|
/// This function creates a shuffle mask whose elements begin at \p Start and
|
|
/// are incremented by \p Stride. The mask can be used to deinterleave an
|
|
/// interleaved vector into separate vectors of vectorization factor \p VF. The
|
|
/// mask is of the form:
|
|
///
|
|
/// <Start, Start + Stride, ..., Start + Stride * (VF - 1)>
|
|
///
|
|
/// For example, the mask for Start = 0, Stride = 2, and VF = 4 is:
|
|
///
|
|
/// <0, 2, 4, 6>
|
|
Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start,
|
|
unsigned Stride, unsigned VF);
|
|
|
|
/// \brief Create a sequential shuffle mask.
|
|
///
|
|
/// This function creates shuffle mask whose elements are sequential and begin
|
|
/// at \p Start. The mask contains \p NumInts integers and is padded with \p
|
|
/// NumUndefs undef values. The mask is of the form:
|
|
///
|
|
/// <Start, Start + 1, ... Start + NumInts - 1, undef_1, ... undef_NumUndefs>
|
|
///
|
|
/// For example, the mask for Start = 0, NumInsts = 4, and NumUndefs = 4 is:
|
|
///
|
|
/// <0, 1, 2, 3, undef, undef, undef, undef>
|
|
Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start,
|
|
unsigned NumInts, unsigned NumUndefs);
|
|
|
|
/// \brief Concatenate a list of vectors.
|
|
///
|
|
/// This function generates code that concatenate the vectors in \p Vecs into a
|
|
/// single large vector. The number of vectors should be greater than one, and
|
|
/// their element types should be the same. The number of elements in the
|
|
/// vectors should also be the same; however, if the last vector has fewer
|
|
/// elements, it will be padded with undefs.
|
|
Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs);
|
|
|
|
} // llvm namespace
|
|
|
|
#endif
|