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"
19#include "llvm/IR/Constants.h"
20#include "llvm/IR/DataLayout.h"
22#include "llvm/IR/Dominators.h"
23#include "llvm/IR/IRBuilder.h"
25#include "llvm/IR/Intrinsics.h"
27#include "llvm/IR/Type.h"
28
29using namespace llvm;
30using namespace llvm::PatternMatch;
31
32namespace llvm::slpvectorizer {
33
34static bool matchRdxBop(Instruction *I, Value *&V0, Value *&V1) {
35 if (match(I, m_BinOp(m_Value(V0), m_Value(V1))))
36 return true;
37 if (match(I, m_FMaxNum(m_Value(V0), m_Value(V1))))
38 return true;
39 if (match(I, m_FMinNum(m_Value(V0), m_Value(V1))))
40 return true;
41 if (match(I, m_FMaximum(m_Value(V0), m_Value(V1))))
42 return true;
43 if (match(I, m_FMinimum(m_Value(V0), m_Value(V1))))
44 return true;
46 return true;
48 return true;
50 return true;
52 return true;
53 return false;
54}
55
57 Value *Op0 = nullptr;
58 Value *Op1 = nullptr;
59 if (!matchRdxBop(I, Op0, Op1))
60 return nullptr;
61 return dyn_cast<Instruction>(Op0 == Phi ? Op1 : Op0);
62}
63
65 bool IsSelect = match(I, m_Select(m_Value(), m_Value(), m_Value()));
66 Value *B0 = nullptr, *B1 = nullptr;
67 bool IsBinop = matchRdxBop(I, B0, B1);
68 return IsBinop || IsSelect;
69}
70
71Type *getBoolReduxWideTy(RecurKind RdxKind, Type *RootTy, Type *LeafTy) {
72 if ((RdxKind == RecurKind::And || RdxKind == RecurKind::Or) &&
73 RootTy->isIntegerTy(1) && LeafTy->isIntegerTy() &&
74 !LeafTy->isIntegerTy(1))
75 return LeafTy;
76 return nullptr;
77}
78
80 RecurKind RdxKind,
81 const SmallDenseMap<Value *, NarrowedLeafInfo> &NarrowedLeafShifts,
82 const DataLayout &DL) {
83 if (RdxKind != RecurKind::Or || DL.isBigEndian() ||
84 NarrowedLeafShifts.empty())
85 return BoolBitmask::None;
86 unsigned NumLeaves = NarrowedLeafShifts.size();
87 SmallBitVector Seen(NumLeaves);
88 bool NeedMask = false;
89 for (const auto &[V, L] : NarrowedLeafShifts) {
90 if (L.Shift >= NumLeaves || Seen.test(L.Shift))
91 return BoolBitmask::None;
92 Seen.set(L.Shift);
94 // The masked leaf must be known to be 0 or 1.
95 if ((L.Mask & ~Known.Zero).ugt(1))
96 return BoolBitmask::None;
97 // The mask is redundant if it keeps all not-known-zero bits.
98 NeedMask |= !(Known.Zero | L.Mask).isAllOnes();
99 }
101}
102
103bool matchPackedFields(Value *V, unsigned MaxDepth,
106 auto *PackTy = dyn_cast<IntegerType>(V->getType());
107 if (!PackTy)
108 return false;
110 collectNarrowedLeaves(V, Instruction::Or, PackTy->getBitWidth(), MaxDepth,
111 Leaves, Chain);
112 if (Leaves.size() < 2)
113 return false;
114 Type *FieldTy = Leaves.front().V->getType();
115 if (!FieldTy->isIntegerTy() ||
116 PackTy->getBitWidth() != Leaves.size() * FieldTy->getIntegerBitWidth())
117 return false;
118 llvm::sort(Leaves, [](const NarrowedLeafInfo &A, const NarrowedLeafInfo &B) {
119 return A.Shift < B.Shift;
120 });
121 for (const auto &[Pos, L] : enumerate(Leaves))
122 if (L.V->getType() != FieldTy || !L.Mask.isAllOnes() ||
123 L.Shift != Pos * FieldTy->getIntegerBitWidth())
124 return false;
126 Fields, map_range(Leaves, [](const NarrowedLeafInfo &L) { return L.V; }));
127 return true;
128}
129
132 RecurKind RdxKind, Value *Vec,
133 const Value *Root, FastMathFlags FMF,
135 auto *VecTy = cast<FixedVectorType>(Vec->getType());
136 unsigned VF = VecTy->getNumElements();
137 auto *I1VecTy = FixedVectorType::get(Builder.getInt1Ty(), VF);
138 DebugLoc DL = Builder.getCurrentDebugLocation();
139 Builder.SetCurrentDebugLocation(cast<Instruction>(Root)->getDebugLoc());
140 Value *T = Builder.CreateTrunc(Vec, I1VecTy);
141 Value *BC = Builder.CreateBitCast(T, Builder.getIntNTy(VF));
142 CmpInst::Predicate Pred =
144 Constant *RHS = RdxKind == RecurKind::And
147 Value *Res = Builder.CreateICmp(Pred, BC, RHS);
148 // The costs are evaluated from the emitted instructions; they are dropped
149 // if the wide reduction form is cheaper.
150 auto CastCost = [&](Value *V, unsigned Opcode, Type *SrcTy) {
151 auto *I = dyn_cast<Instruction>(V);
152 if (!I)
153 return InstructionCost(0);
154 return TTI.getCastInstrCost(Opcode, I->getType(), SrcTy,
155 TTI.getCastContextHint(I), CostKind, I);
156 };
157 InstructionCost BitcastCmpCost = CastCost(T, Instruction::Trunc, VecTy) +
158 CastCost(BC, Instruction::BitCast, I1VecTy);
159 if (auto *Cmp = dyn_cast<Instruction>(Res))
160 BitcastCmpCost += TTI.getCmpSelInstrCost(
161 Instruction::ICmp, BC->getType(), /*CondTy=*/nullptr, Pred, CostKind,
162 TTI.getOperandInfo(BC), TTI.getOperandInfo(RHS), Cmp);
163 if (BitcastCmpCost >=
164 getBoolReduxWideRdxCost(TTI, RdxKind, VecTy, Root, FMF, CostKind)) {
165 for (Value *V : {Res, BC, T})
166 if (auto *I = dyn_cast<Instruction>(V))
167 I->eraseFromParent();
168 Builder.SetCurrentDebugLocation(DL);
169 return nullptr;
170 }
171 Builder.SetCurrentDebugLocation(DL);
172 return Res;
173}
174
176 BasicBlock *ParentBB, LoopInfo *LI) {
177 // There are situations where the reduction value is not dominated by the
178 // reduction phi. Vectorizing such cases has been reported to cause
179 // miscompiles. See PR25787.
180 auto DominatedReduxValue = [&](Value *R) {
181 return isa<Instruction>(R) &&
182 DT->dominates(P->getParent(), cast<Instruction>(R)->getParent());
183 };
184
185 Instruction *Rdx = nullptr;
186
187 // Return the incoming value if it comes from the same BB as the phi node.
188 if (P->getIncomingBlock(0) == ParentBB) {
189 Rdx = dyn_cast<Instruction>(P->getIncomingValue(0));
190 } else if (P->getIncomingBlock(1) == ParentBB) {
191 Rdx = dyn_cast<Instruction>(P->getIncomingValue(1));
192 }
193
194 if (Rdx && DominatedReduxValue(Rdx))
195 return Rdx;
196
197 // Otherwise, check whether we have a loop latch to look at.
198 Loop *BBL = LI->getLoopFor(ParentBB);
199 if (!BBL)
200 return nullptr;
201 BasicBlock *BBLatch = BBL->getLoopLatch();
202 if (!BBLatch)
203 return nullptr;
204
205 // There is a loop latch, return the incoming value if it comes from
206 // that. This reduction pattern occasionally turns up.
207 if (P->getIncomingBlock(0) == BBLatch) {
208 Rdx = dyn_cast<Instruction>(P->getIncomingValue(0));
209 } else if (P->getIncomingBlock(1) == BBLatch) {
210 Rdx = dyn_cast<Instruction>(P->getIncomingValue(1));
211 }
212
213 if (Rdx && DominatedReduxValue(Rdx))
214 return Rdx;
215
216 return nullptr;
217}
218
219} // 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
#define P(N)
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.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
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:716
unsigned size() const
Definition DenseMap.h:717
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
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
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
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...
Instruction * getReductionInstr(const DominatorTree *DT, PHINode *P, BasicBlock *ParentBB, LoopInfo *LI)
Try to get a reduction instruction from phi node P in block ParentBB, considering incoming values fro...
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
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
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:450