Introduce experimental generic intrinsics for horizontal vector reductions.
- This change allows targets to opt-in to using them instead of the log2 shufflevector algorithm. - The SLP and Loop vectorizers have the common code to do shuffle reductions factored out into LoopUtils, and now have a unified interface for generating reductions regardless of the preference of the target. LoopUtils now uses TTI to determine what kind of reductions the target wants to handle. - For CodeGen, basic legalization support is added. Differential Revision: https://reviews.llvm.org/D30086 llvm-svn: 302514
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Utils/LoopUtils.h"
|
||||
#include "llvm/Transforms/Vectorize.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@@ -212,23 +213,6 @@ static unsigned getSameOpcode(ArrayRef<Value *> VL) {
|
||||
return Opcode;
|
||||
}
|
||||
|
||||
/// Get the intersection (logical and) of all of the potential IR flags
|
||||
/// of each scalar operation (VL) that will be converted into a vector (I).
|
||||
/// Flag set: NSW, NUW, exact, and all of fast-math.
|
||||
static void propagateIRFlags(Value *I, ArrayRef<Value *> VL) {
|
||||
if (auto *VecOp = dyn_cast<Instruction>(I)) {
|
||||
if (auto *I0 = dyn_cast<Instruction>(VL[0])) {
|
||||
// VecOVp is initialized to the 0th scalar, so start counting from index
|
||||
// '1'.
|
||||
VecOp->copyIRFlags(I0);
|
||||
for (int i = 1, e = VL.size(); i < e; ++i) {
|
||||
if (auto *Scalar = dyn_cast<Instruction>(VL[i]))
|
||||
VecOp->andIRFlags(Scalar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns true if all of the values in \p VL have the same type or false
|
||||
/// otherwise.
|
||||
static bool allSameType(ArrayRef<Value *> VL) {
|
||||
@@ -4513,7 +4497,7 @@ public:
|
||||
|
||||
// Emit a reduction.
|
||||
Value *ReducedSubTree =
|
||||
emitReduction(VectorizedRoot, Builder, ReduxWidth, ReductionOps);
|
||||
emitReduction(VectorizedRoot, Builder, ReduxWidth, ReductionOps, TTI);
|
||||
if (VectorizedTree) {
|
||||
Builder.SetCurrentDebugLocation(Loc);
|
||||
VectorizedTree = Builder.CreateBinOp(ReductionOpcode, VectorizedTree,
|
||||
@@ -4583,33 +4567,31 @@ private:
|
||||
|
||||
/// \brief Emit a horizontal reduction of the vectorized value.
|
||||
Value *emitReduction(Value *VectorizedValue, IRBuilder<> &Builder,
|
||||
unsigned ReduxWidth, ArrayRef<Value *> RedOps) {
|
||||
unsigned ReduxWidth, ArrayRef<Value *> RedOps,
|
||||
const TargetTransformInfo *TTI) {
|
||||
assert(VectorizedValue && "Need to have a vectorized tree node");
|
||||
assert(isPowerOf2_32(ReduxWidth) &&
|
||||
"We only handle power-of-two reductions for now");
|
||||
|
||||
if (!IsPairwiseReduction)
|
||||
return createSimpleTargetReduction(
|
||||
Builder, TTI, ReductionOpcode, VectorizedValue,
|
||||
TargetTransformInfo::ReductionFlags(), RedOps);
|
||||
|
||||
Value *TmpVec = VectorizedValue;
|
||||
for (unsigned i = ReduxWidth / 2; i != 0; i >>= 1) {
|
||||
if (IsPairwiseReduction) {
|
||||
Value *LeftMask =
|
||||
Value *LeftMask =
|
||||
createRdxShuffleMask(ReduxWidth, i, true, true, Builder);
|
||||
Value *RightMask =
|
||||
Value *RightMask =
|
||||
createRdxShuffleMask(ReduxWidth, i, true, false, Builder);
|
||||
|
||||
Value *LeftShuf = Builder.CreateShuffleVector(
|
||||
Value *LeftShuf = Builder.CreateShuffleVector(
|
||||
TmpVec, UndefValue::get(TmpVec->getType()), LeftMask, "rdx.shuf.l");
|
||||
Value *RightShuf = Builder.CreateShuffleVector(
|
||||
Value *RightShuf = Builder.CreateShuffleVector(
|
||||
TmpVec, UndefValue::get(TmpVec->getType()), (RightMask),
|
||||
"rdx.shuf.r");
|
||||
TmpVec = Builder.CreateBinOp(ReductionOpcode, LeftShuf, RightShuf,
|
||||
"bin.rdx");
|
||||
} else {
|
||||
Value *UpperHalf =
|
||||
createRdxShuffleMask(ReduxWidth, i, false, false, Builder);
|
||||
Value *Shuf = Builder.CreateShuffleVector(
|
||||
TmpVec, UndefValue::get(TmpVec->getType()), UpperHalf, "rdx.shuf");
|
||||
TmpVec = Builder.CreateBinOp(ReductionOpcode, TmpVec, Shuf, "bin.rdx");
|
||||
}
|
||||
TmpVec =
|
||||
Builder.CreateBinOp(ReductionOpcode, LeftShuf, RightShuf, "bin.rdx");
|
||||
propagateIRFlags(TmpVec, RedOps);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user