LLVM 24.0.0git
SLPReductionUtils.cpp
Go to the documentation of this file.
1//===- SLPReductionUtils.cpp - SLP reduction match helpers ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "SLPReductionUtils.h"
10
11#include "SLPCostAnalysis.h"
12#include "SLPUtils.h"
13
14#include "llvm/ADT/STLExtras.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/DataLayout.h"
20#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/Intrinsics.h"
24#include "llvm/IR/Type.h"
25
26using namespace llvm;
27using namespace llvm::PatternMatch;
28
29namespace llvm::slpvectorizer {
30
31static bool matchRdxBop(Instruction *I, Value *&V0, Value *&V1) {
32 if (match(I, m_BinOp(m_Value(V0), m_Value(V1))))
33 return true;
34 if (match(I, m_FMaxNum(m_Value(V0), m_Value(V1))))
35 return true;
36 if (match(I, m_FMinNum(m_Value(V0), m_Value(V1))))
37 return true;
38 if (match(I, m_FMaximum(m_Value(V0), m_Value(V1))))
39 return true;
40 if (match(I, m_FMinimum(m_Value(V0), m_Value(V1))))
41 return true;
43 return true;
45 return true;
47 return true;
49 return true;
50 return false;
51}
52
54 Value *Op0 = nullptr;
55 Value *Op1 = nullptr;
56 if (!matchRdxBop(I, Op0, Op1))
57 return nullptr;
58 return dyn_cast<Instruction>(Op0 == Phi ? Op1 : Op0);
59}
60
62 bool IsSelect = match(I, m_Select(m_Value(), m_Value(), m_Value()));
63 Value *B0 = nullptr, *B1 = nullptr;
64 bool IsBinop = matchRdxBop(I, B0, B1);
65 return IsBinop || IsSelect;
66}
67
68Type *getBoolReduxWideTy(RecurKind RdxKind, Type *RootTy, Type *LeafTy) {
69 if ((RdxKind == RecurKind::And || RdxKind == RecurKind::Or) &&
70 RootTy->isIntegerTy(1) && LeafTy->isIntegerTy() &&
71 !LeafTy->isIntegerTy(1))
72 return LeafTy;
73 return nullptr;
74}
75
77 RecurKind RdxKind,
78 const SmallDenseMap<Value *, NarrowedLeafInfo> &NarrowedLeafShifts,
79 const DataLayout &DL) {
80 if (RdxKind != RecurKind::Or || DL.isBigEndian() ||
81 NarrowedLeafShifts.empty())
82 return BoolBitmask::None;
83 unsigned NumLeaves = NarrowedLeafShifts.size();
84 SmallBitVector Seen(NumLeaves);
85 bool NeedMask = false;
86 for (const auto &[V, L] : NarrowedLeafShifts) {
87 if (L.Shift >= NumLeaves || Seen.test(L.Shift))
88 return BoolBitmask::None;
89 Seen.set(L.Shift);
91 // The masked leaf must be known to be 0 or 1.
92 if ((L.Mask & ~Known.Zero).ugt(1))
93 return BoolBitmask::None;
94 // The mask is redundant if it keeps all not-known-zero bits.
95 NeedMask |= !(Known.Zero | L.Mask).isAllOnes();
96 }
98}
99
100bool matchPackedFields(Value *V, unsigned MaxDepth,
103 auto *PackTy = dyn_cast<IntegerType>(V->getType());
104 if (!PackTy)
105 return false;
107 collectNarrowedLeaves(V, Instruction::Or, PackTy->getBitWidth(), MaxDepth,
108 Leaves, Chain);
109 if (Leaves.size() < 2)
110 return false;
111 Type *FieldTy = Leaves.front().V->getType();
112 if (!FieldTy->isIntegerTy() ||
113 PackTy->getBitWidth() != Leaves.size() * FieldTy->getIntegerBitWidth())
114 return false;
115 llvm::sort(Leaves, [](const NarrowedLeafInfo &A, const NarrowedLeafInfo &B) {
116 return A.Shift < B.Shift;
117 });
118 for (const auto &[Pos, L] : enumerate(Leaves))
119 if (L.V->getType() != FieldTy || !L.Mask.isAllOnes() ||
120 L.Shift != Pos * FieldTy->getIntegerBitWidth())
121 return false;
123 Fields, map_range(Leaves, [](const NarrowedLeafInfo &L) { return L.V; }));
124 return true;
125}
126
129 RecurKind RdxKind, Value *Vec,
130 const Value *Root, FastMathFlags FMF,
132 auto *VecTy = cast<FixedVectorType>(Vec->getType());
133 unsigned VF = VecTy->getNumElements();
134 auto *I1VecTy = FixedVectorType::get(Builder.getInt1Ty(), VF);
135 DebugLoc DL = Builder.getCurrentDebugLocation();
136 Builder.SetCurrentDebugLocation(cast<Instruction>(Root)->getDebugLoc());
137 Value *T = Builder.CreateTrunc(Vec, I1VecTy);
138 Value *BC = Builder.CreateBitCast(T, Builder.getIntNTy(VF));
139 CmpInst::Predicate Pred =
141 Constant *RHS = RdxKind == RecurKind::And
144 Value *Res = Builder.CreateICmp(Pred, BC, RHS);
145 // The costs are evaluated from the emitted instructions; they are dropped
146 // if the wide reduction form is cheaper.
147 auto CastCost = [&](Value *V, unsigned Opcode, Type *SrcTy) {
148 auto *I = dyn_cast<Instruction>(V);
149 if (!I)
150 return InstructionCost(0);
151 return TTI.getCastInstrCost(Opcode, I->getType(), SrcTy,
152 TTI.getCastContextHint(I), CostKind, I);
153 };
154 InstructionCost BitcastCmpCost = CastCost(T, Instruction::Trunc, VecTy) +
155 CastCost(BC, Instruction::BitCast, I1VecTy);
156 if (auto *Cmp = dyn_cast<Instruction>(Res))
157 BitcastCmpCost += TTI.getCmpSelInstrCost(
158 Instruction::ICmp, BC->getType(), /*CondTy=*/nullptr, Pred, CostKind,
159 TTI.getOperandInfo(BC), TTI.getOperandInfo(RHS), Cmp);
160 if (BitcastCmpCost >=
161 getBoolReduxWideRdxCost(TTI, RdxKind, VecTy, Root, FMF, CostKind)) {
162 for (Value *V : {Res, BC, T})
163 if (auto *I = dyn_cast<Instruction>(V))
164 I->eraseFromParent();
165 Builder.SetCurrentDebugLocation(DL);
166 return nullptr;
167 }
168 Builder.SetCurrentDebugLocation(DL);
169 return Res;
170}
171
172} // namespace llvm::slpvectorizer
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
#define I(x, y, z)
Definition MD5.cpp:57
#define T
static bool IsSelect(unsigned Opcode, bool CheckOnlyCC=false)
Check if the opcode is a SELECT or SELECT_CC variant.
Func MI getDebugLoc()))
This file contains some templates that are useful if you are working with the STL at all.
This file implements the SmallBitVector class.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_NE
not equal
Definition InstrTypes.h:762
This is an important base class in LLVM.
Definition Constant.h:43
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
A debug info location.
Definition DebugLoc.h:126
bool empty() const
Definition DenseMap.h:717
unsigned size() const
Definition DenseMap.h:718
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:843
Common base class shared among various IRBuilders.
Definition IRBuilder.h:111
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
SmallBitVector & set()
bool test(unsigned Idx) const
Returns true if bit Idx is set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
TargetCostKind
The kind of cost model.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
bool match(Val *V, const Pattern &P)
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_FMinimum(const Opnd0 &Op0, const Opnd1 &Op1)
auto m_Value()
Match an arbitrary value and ignore it.
auto m_FMaximum(const Opnd0 &Op0, const Opnd1 &Op1)
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_FMinNum(const Opnd0 &Op0, const Opnd1 &Op1)
auto m_FMaxNum(const Opnd0 &Op0, const Opnd1 &Op1)
A private "module" namespace for types and utilities used by this pass.
bool matchPackedFields(Value *V, unsigned MaxDepth, SmallVectorImpl< Value * > &Fields, SmallVectorImpl< Instruction * > &Chain)
Matches V as the zero-extended fields, placed one after another from the lowest bit and filling V com...
Type * getBoolReduxWideTy(RecurKind RdxKind, Type *RootTy, Type *LeafTy)
Value * tryEmitBoolReduxBitcastCmp(IRBuilderBase &Builder, const TargetTransformInfo &TTI, RecurKind RdxKind, Value *Vec, const Value *Root, FastMathFlags FMF, const TTI::TargetCostKind CostKind)
Emits the booleanized logical and/or reduction of Vec with the i1 root Root as trunc+bitcast+cmp (all...
BoolBitmask isBoolBitmaskRdx(RecurKind RdxKind, const SmallDenseMap< Value *, NarrowedLeafInfo > &NarrowedLeafShifts, const DataLayout &DL)
InstructionCost getBoolReduxWideRdxCost(const TargetTransformInfo &TTI, RecurKind RdxKind, FixedVectorType *VecTy, const Value *Root, FastMathFlags FMF, const TTI::TargetCostKind CostKind)
Returns the cost of the booleanized logical and/or reduction of a vector of type VecTy with the i1 ro...
static bool matchRdxBop(Instruction *I, Value *&V0, Value *&V1)
Instruction * getNonPhiOperand(Instruction *I, PHINode *Phi)
bool isReductionCandidate(Instruction *I)
void collectNarrowedLeaves(Value *V, unsigned RdxOpcode, unsigned WideBW, unsigned MaxDepth, SmallVectorImpl< NarrowedLeafInfo > &Leaves, SmallVectorImpl< Instruction * > &ChainInsts)
Recursively collects the narrow leaves of the widened reduction value V.
BoolBitmask
The result of matching a boolean bitmask reduction over narrowed leaves.
This is an optimization pass for GlobalISel generic memory operations.
@ Known
Known to have no common set bits.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:366
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
TargetTransformInfo TTI
RecurKind
These are the kinds of recurrences that we support.
@ Or
Bitwise or logical OR of integers.
@ And
Bitwise or logical AND of integers.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Narrow reduction leaf: the value, the shift applied after widening and the mask applied in the narrow...
Definition SLPUtils.h:429