LLVM 24.0.0git
SLPCompatibilityAnalysis.h
Go to the documentation of this file.
1//===- SLPCompatibilityAnalysis.h - SLP same-opcode helpers ----*- C++ -*-===//
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// Internal header used by SLPVectorizer.cpp. It declares the same-opcode
10// compatibility primitives that decide whether a group of values can be
11// treated as sharing the same (or an interchangeable/alternate) opcode. These
12// do not depend on BoUpSLP or any other SLP-private type.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPCOMPATIBILITYANALYSIS_H
17#define LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPCOMPATIBILITYANALYSIS_H
18
19#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/STLExtras.h"
25#include "llvm/IR/Instruction.h"
27
28#include <cstdint>
29#include <utility>
30
31namespace llvm {
32class APInt;
33class Constant;
34class ConstantInt;
36class Value;
37} // namespace llvm
38
39namespace llvm::slpvectorizer {
40
41/// \returns true if \p Opcode is allowed as part of the main/alternate
42/// instruction for SLP vectorization.
43///
44/// Example of unsupported opcode is SDIV that can potentially cause UB if the
45/// "shuffled out" lane would result in division by zero.
46bool isValidForAlternation(unsigned Opcode);
47
48/// Helper class that determines VL can use the same opcode.
49/// Alternate instruction is supported. In addition, it supports interchangeable
50/// instruction. An interchangeable instruction is an instruction that can be
51/// converted to another instruction with same semantics. For example, x << 1 is
52/// equal to x * 2. x * 1 is equal to x | 0.
54 using MaskType = std::uint_fast32_t;
55 /// Sort SupportedOp because it is used by binary_search.
56 constexpr static unsigned SupportedOp[] = {
57 Instruction::Add, Instruction::FAdd, Instruction::Sub, Instruction::FSub,
58 Instruction::Mul, Instruction::Shl, Instruction::AShr, Instruction::And,
59 Instruction::Or, Instruction::Xor};
60 static_assert(llvm::is_sorted_constexpr(SupportedOp) &&
61 "SupportedOp is not sorted.");
62 enum : MaskType {
63 ShlBIT = 1,
64 AShrBIT = 1 << 1,
65 MulBIT = 1 << 2,
66 AddBIT = 1 << 3,
67 SubBIT = 1 << 4,
68 AndBIT = 1 << 5,
69 OrBIT = 1 << 6,
70 XorBIT = 1 << 7,
71 FAddBIT = 1 << 8,
72 FSubBIT = 1 << 9,
73 MainOpBIT = 1 << 10,
75 };
76 /// Return a non-nullptr if either operand of I is a ConstantInt (for the
77 /// integer opcodes) or a ConstantFP (for FAdd/FSub).
78 /// The second return value represents the operand position. We check the
79 /// right-hand side first (1). If the right hand side is not a constant and
80 /// the instruction is neither Sub, FSub, Shl, nor AShr, we then check the
81 /// left hand side (0).
82 static std::pair<Constant *, unsigned>
83 isBinOpWithConstant(const Instruction *I);
84 struct InterchangeableInfo {
85 const Instruction *I = nullptr;
86 /// The bit it sets represents whether MainOp can be converted to.
87 MaskType Mask = MainOpBIT | XorBIT | OrBIT | AndBIT | SubBIT | AddBIT |
88 MulBIT | AShrBIT | ShlBIT | FSubBIT | FAddBIT;
89 /// We cannot create an interchangeable instruction that does not exist in
90 /// VL. For example, VL [x + 0, y * 1] can be converted to [x << 0, y << 0],
91 /// but << does not exist in VL. In the end, we convert VL to [x * 1, y *
92 /// 1]. SeenBefore is used to know what operations have been seen before.
93 MaskType SeenBefore = 0;
94 InterchangeableInfo(const Instruction *I) : I(I) {}
95 /// Return false allows BinOpSameOpcodeHelper to find an alternate
96 /// instruction. Directly setting the mask will destroy the mask state,
97 /// preventing us from determining which instruction it should convert to.
98 bool trySet(MaskType OpcodeInMaskForm, MaskType InterchangeableMask);
99 bool equal(unsigned Opcode) {
100 return Opcode == I->getOpcode() && trySet(MainOpBIT, MainOpBIT);
101 }
102 unsigned getOpcode() const;
103 bool hasDefinedOpcode() const { return (Mask & SeenBefore) > 0; }
104 /// Return true if the instruction can be converted to \p Opcode.
105 bool hasCandidateOpcode(unsigned Opcode) const;
107 };
108 InterchangeableInfo MainOp;
109 InterchangeableInfo AltOp;
110 bool isValidForAlternation(const Instruction *I) const;
111 bool initializeAltOp(const Instruction *I);
112
113public:
115 const Instruction *AltOp = nullptr)
116 : MainOp(MainOp), AltOp(AltOp) {}
117 bool add(const Instruction *I);
118 unsigned getMainOpcode() const { return MainOp.getOpcode(); }
119 bool hasDefinedMainOpcode() const { return MainOp.hasDefinedOpcode(); }
120 /// Checks if the list of potential opcodes includes \p Opcode.
121 bool hasCandidateOpcode(unsigned Opcode) const {
122 return MainOp.hasCandidateOpcode(Opcode);
123 }
124 bool hasAltOp() const { return AltOp.I; }
125 unsigned getAltOpcode() const {
126 return hasAltOp() ? AltOp.getOpcode() : getMainOpcode();
127 }
128 bool hasDefinedAltOpcode() const {
129 return !hasAltOp() || AltOp.hasDefinedOpcode();
130 }
132 return MainOp.getOperand(I);
133 }
134};
135
136/// Helper class that determines whether a list of integer comparisons can
137/// share a single predicate. InstCombine canonicalizes single-element and
138/// single-complement range comparisons to eq/ne at the type boundaries
139/// (e.g. x <u 1 becomes x == 0); such lanes are interchangeable with the
140/// rest of the list by adjusting the compared constant.
142 using MaskType = std::uint16_t;
143 /// Bit i represents predicate ICMP_EQ + i.
144 static constexpr unsigned NumPreds = CmpInst::ICMP_SLE - CmpInst::ICMP_EQ + 1;
145 static constexpr MaskType AllPreds = (1 << NumPreds) - 1;
146 /// Intersection of the per-lane convertible predicate sets.
147 MaskType Mask = AllPreds;
148 /// Predicates present in the list natively. The shared predicate must be
149 /// one of them: the main op must be an actual instruction with this
150 /// predicate.
151 MaskType SeenBefore = 0;
152
153 static constexpr MaskType getBit(CmpInst::Predicate P) {
154 return static_cast<MaskType>(1) << (P - CmpInst::ICMP_EQ);
155 }
156 /// Returns the mask of the predicates that can express the comparison
157 /// (Pred, X, C) with an adjusted constant C, including Pred itself.
158 static MaskType getFormsMask(CmpInst::Predicate Pred, const APInt &C);
159 /// Returns the constant of the (Pred, X, C') form equivalent to the
160 /// boundary family (IsComplement, K). Pred must be in the family mask.
161 static APInt getFamilyConstant(bool IsComplement, const APInt &K,
162 CmpInst::Predicate Pred);
163
164public:
165 /// Intersects the convertible predicate set of \p CI with the running
166 /// set. Returns false when the intersection becomes empty.
167 bool add(const ICmpInst *CI);
168 /// Returns the shared predicate, preferring the predicate of
169 /// \p Preferred when the whole list can use it, or BAD_ICMP_PREDICATE
170 /// when the list cannot share a natively present predicate.
171 CmpInst::Predicate getPredicate(const ICmpInst *Preferred) const;
172 /// Returns the predicate the whole list can share, or BAD_ICMP_PREDICATE
173 /// when it cannot share a natively present predicate.
175 const ICmpInst *Preferred);
176 /// Checks if the comparison \p CI can be expressed with the predicate
177 /// \p Pred by adjusting its constant operand.
178 static bool canConvertTo(const CmpInst *CI, CmpInst::Predicate Pred);
179 /// Returns the adjusted constant operand expressing \p CI with the
180 /// predicate \p Pred, or nullptr if not convertible or if \p CI already
181 /// uses \p Pred.
182 static ConstantInt *getAdjustedConstant(const CmpInst *CI,
183 CmpInst::Predicate Pred);
184};
185
186/// Main data required for vectorization of instructions.
188 /// MainOp and AltOp are primarily determined by getSameOpcode. Currently,
189 /// only BinaryOperator, CastInst, and CmpInst support alternate instructions
190 /// (i.e., AltOp is not equal to MainOp; this can be checked using
191 /// isAltShuffle).
192 /// A rare exception is TrySplitNode, where the InstructionsState is derived
193 /// from getMainAltOpsNoStateVL.
194 /// For those InstructionsState that use alternate instructions, the resulting
195 /// vectorized output ultimately comes from a shufflevector. For example,
196 /// given a vector list (VL):
197 /// VL[0] = add i32 a, e
198 /// VL[1] = sub i32 b, f
199 /// VL[2] = add i32 c, g
200 /// VL[3] = sub i32 d, h
201 /// The vectorized result would be:
202 /// intermediated_0 = add <4 x i32> <a, b, c, d>, <e, f, g, h>
203 /// intermediated_1 = sub <4 x i32> <a, b, c, d>, <e, f, g, h>
204 /// result = shufflevector <4 x i32> intermediated_0,
205 /// <4 x i32> intermediated_1,
206 /// <4 x i32> <i32 0, i32 5, i32 2, i32 7>
207 /// Since shufflevector is used in the final result, when calculating the cost
208 /// (getEntryCost), we must account for the usage of shufflevector in
209 /// GetVectorCost.
210 Instruction *MainOp = nullptr;
211 Instruction *AltOp = nullptr;
212 /// Whether the instruction state represents copyable instructions.
213 bool HasCopyables = false;
214 /// Index of the operand modeling the copyable values: the addend for
215 /// fmuladd (retried with a multiplicand), the first operand otherwise.
216 unsigned CopyableOpIdx = 0;
217 /// Whether copyable single-use fmuls/fadds are modeled as
218 /// fmuladd(a, b, -0.0)/fmuladd(1.0, a, b), absorbing the binop instead of
219 /// computing and gathering its result.
220 bool AbsorbCopyableFMulOrFAdd = false;
221
222public:
224 assert(valid() && "InstructionsState is invalid.");
225 return MainOp;
226 }
227
229 assert(valid() && "InstructionsState is invalid.");
230 return AltOp;
231 }
232
233 /// The main/alternate opcodes for the list of instructions.
234 unsigned getOpcode() const { return getMainOp()->getOpcode(); }
235
236 unsigned getAltOpcode() const { return getAltOp()->getOpcode(); }
237
238 /// Some of the instructions in the list have alternate opcodes.
239 bool isAltShuffle() const { return getMainOp() != getAltOp(); }
240
241 /// Checks if \p I is the same operation as \p Op, distinguishing calls by
242 /// intrinsic ID (all calls share the Call opcode, so e.g. umax != smax).
243 static bool isSameOperation(const Instruction *I, const Instruction *Op);
244
245 /// Checks if the instruction matches either the main or alternate opcode.
246 /// \returns
247 /// - MainOp if \param I matches MainOp's opcode directly or can be converted
248 /// to it
249 /// - AltOp if \param I matches AltOp's opcode directly or can be converted to
250 /// it
251 /// - nullptr if \param I cannot be matched or converted to either opcode
253
254 /// Checks if main/alt instructions are shift operations.
255 bool isShiftOp() const {
256 return getMainOp()->isShift() && getAltOp()->isShift();
257 }
258
259 /// Checks if main/alt instructions are bitwise logic operations.
260 bool isBitwiseLogicOp() const {
262 }
263
264 /// Checks if main/alt instructions are mul/div/rem/fmul/fdiv/frem operations.
265 bool isMulDivLikeOp() const;
266
267 /// Checks if main/alt instructions are add/sub/fadd/fsub operations.
268 bool isAddSubLikeOp() const;
269
270 /// Checks if main/alt instructions are cmp operations.
271 bool isCmpOp() const {
272 return (getOpcode() == Instruction::ICmp ||
273 getOpcode() == Instruction::FCmp) &&
274 getAltOpcode() == getOpcode();
275 }
276
277 /// Checks if the current state is valid, i.e. has non-null MainOp
278 bool valid() const { return MainOp && AltOp; }
279
280 explicit operator bool() const { return valid(); }
281
284 bool HasCopyables = false)
285 : MainOp(MainOp), AltOp(AltOp), HasCopyables(HasCopyables),
286 CopyableOpIdx(MainOp && RecurrenceDescriptor::isFMulAddIntrinsic(MainOp)
287 ? 2
288 : 0) {}
289 static InstructionsState invalid() { return {nullptr, nullptr}; }
290
291 /// Checks if the value is a copyable element.
292 bool isCopyableElement(Value *V) const;
293
294 /// Checks if the value \p V is a transformed instruction, compatible either
295 /// with main or alternate ops.
296 bool isExpandedBinOp(Value *V) const;
297
298 /// Checks if the operand at index \p Idx of instruction \p I is an expanded
299 /// operand.
300 bool isExpandedOperand(Instruction *I, unsigned Idx) const;
301
302 /// Checks if the value is non-schedulable.
303 bool isNonSchedulable(Value *V) const;
304
305 /// Checks if the state represents copyable instructions.
307 assert(valid() && "InstructionsState is invalid.");
308 return HasCopyables;
309 }
310
311 /// Returns the index of the operand the copyable value is modeled in.
312 unsigned getCopyableOpIdx() const {
313 assert(valid() && "InstructionsState is invalid.");
314 return CopyableOpIdx;
315 }
316
317 /// Sets the index of the operand the copyable value is modeled in.
318 void setCopyableOpIdx(unsigned Idx) {
319 assert((Idx == 0 || Idx == 2) && "Unexpected copyable operand index.");
320 CopyableOpIdx = Idx;
321 }
322
323 /// Checks if copyable fmuls/fadds are absorbed as fmuladd(a, b, -0.0) or
324 /// fmuladd(1.0, a, b).
326 assert(valid() && "InstructionsState is invalid.");
327 return AbsorbCopyableFMulOrFAdd;
328 }
329
330 /// Sets the absorbed-fmul/fadd modeling for copyable fmuls/fadds.
331 void setAbsorbCopyableFMulOrFAdd(bool Absorb) {
332 AbsorbCopyableFMulOrFAdd = Absorb;
333 }
334};
335
336/// Checks if \p V is a single-use fmul/fadd with operands outside \p VL.
338
339/// Checks if \p V is a copyable single-use fmul/fadd, absorbable as
340/// fmuladd(a, b, -0.0) or fmuladd(1.0, a, b).
341bool isAbsorbableCopyableFMulOrFAdd(const InstructionsState &S, Value *V);
342
343/// Checks if every copyable in \p VL is an absorbable fmul/fadd: the binops
344/// die instead of being computed and gathered. Operand order is normalized
345/// when the operands are built.
347
348/// \returns analysis of the Instructions in \p VL described in
349/// InstructionsState, the Opcode that we suppose the whole list
350/// could be vectorized even if its structure is diverse.
351InstructionsState getSameOpcode(ArrayRef<Value *> VL,
352 const TargetLibraryInfo &TLI);
353
354/// \returns the main or alternate operation from \p S matching \p I, together
355/// with the operands of \p I adjusted to the selected operation.
356std::pair<Instruction *, SmallVector<Value *>>
357convertTo(Instruction *I, const InstructionsState &S);
358
359/// Checks if the specified instruction \p I is an alternate operation for
360/// the given \p MainOp and \p AltOp instructions.
362 Instruction *AltOp, const TargetLibraryInfo &TLI);
363
364/// Peel the per-lane associative chains of an alternate node into operand
365/// columns. Lanes peel in lockstep and only chain links with the lane's own
366/// opcode, so every combine level keeps the root's main/alt opcode pattern
367/// and a subtract lane never becomes an add of a negated leaf. Only the
368/// leading (running) column peels: peeling a subtracted subtract would flip
369/// signs. \p SubLanes records the subtract lanes for the realignment sign
370/// query. Returns the flattened columns, empty when no level peels.
372 const InstructionsState &S, const TargetLibraryInfo &TLI,
374 SmallVectorImpl<Value *> &ReassocScalars, SmallBitVector &SubLanes);
375} // namespace llvm::slpvectorizer
376
377#endif // LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPCOMPATIBILITYANALYSIS_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define I(x, y, z)
Definition MD5.cpp:57
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
This file implements the SmallBitVector class.
This file defines the SmallVector class.
Class for arbitrary precision integers.
Definition APInt.h:78
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This class is the base class for the comparison instructions.
Definition InstrTypes.h:728
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
This is the shared class of boolean and integer constants.
Definition Constants.h:87
This is an important base class in LLVM.
Definition Constant.h:43
This instruction compares its operands according to the predicate given to the constructor.
static bool isBitwiseLogicOp(unsigned Opcode)
Determine if the Opcode is and/or/xor.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool isShift() const
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
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.
Provides information about what library functions are available for the current target.
LLVM Value Representation.
Definition Value.h:75
SmallVector< Value * > getOperand(const Instruction *I) const
bool hasCandidateOpcode(unsigned Opcode) const
Checks if the list of potential opcodes includes Opcode.
BinOpSameOpcodeHelper(const Instruction *MainOp, const Instruction *AltOp=nullptr)
Helper class that determines whether a list of integer comparisons can share a single predicate.
static CmpInst::Predicate getSharedPredicate(ArrayRef< Value * > VL, const ICmpInst *Preferred)
Returns the predicate the whole list can share, or BAD_ICMP_PREDICATE when it cannot share a natively...
CmpInst::Predicate getPredicate(const ICmpInst *Preferred) const
Returns the shared predicate, preferring the predicate of Preferred when the whole list can use it,...
bool add(const ICmpInst *CI)
Intersects the convertible predicate set of CI with the running set.
static ConstantInt * getAdjustedConstant(const CmpInst *CI, CmpInst::Predicate Pred)
Returns the adjusted constant operand expressing CI with the predicate Pred, or nullptr if not conver...
static bool canConvertTo(const CmpInst *CI, CmpInst::Predicate Pred)
Checks if the comparison CI can be expressed with the predicate Pred by adjusting its constant operan...
Instruction * getMatchingMainOpOrAltOp(Instruction *I) const
Checks if the instruction matches either the main or alternate opcode.
bool areInstructionsWithCopyableElements() const
Checks if the state represents copyable instructions.
void setAbsorbCopyableFMulOrFAdd(bool Absorb)
Sets the absorbed-fmul/fadd modeling for copyable fmuls/fadds.
bool isCmpOp() const
Checks if main/alt instructions are cmp operations.
static bool isSameOperation(const Instruction *I, const Instruction *Op)
Checks if I is the same operation as Op, distinguishing calls by intrinsic ID (all calls share the Ca...
bool valid() const
Checks if the current state is valid, i.e. has non-null MainOp.
bool isExpandedBinOp(Value *V) const
Checks if the value V is a transformed instruction, compatible either with main or alternate ops.
bool isAddSubLikeOp() const
Checks if main/alt instructions are add/sub/fadd/fsub operations.
bool isShiftOp() const
Checks if main/alt instructions are shift operations.
bool isExpandedOperand(Instruction *I, unsigned Idx) const
Checks if the operand at index Idx of instruction I is an expanded operand.
bool isCopyableElement(Value *V) const
Checks if the value is a copyable element.
bool hasAbsorbedCopyableFMulOrFAdd() const
Checks if copyable fmuls/fadds are absorbed as fmuladd(a, b, -0.0) or fmuladd(1.0,...
bool isAltShuffle() const
Some of the instructions in the list have alternate opcodes.
void setCopyableOpIdx(unsigned Idx)
Sets the index of the operand the copyable value is modeled in.
InstructionsState(Instruction *MainOp, Instruction *AltOp, bool HasCopyables=false)
bool isNonSchedulable(Value *V) const
Checks if the value is non-schedulable.
unsigned getCopyableOpIdx() const
Returns the index of the operand the copyable value is modeled in.
bool isBitwiseLogicOp() const
Checks if main/alt instructions are bitwise logic operations.
bool isMulDivLikeOp() const
Checks if main/alt instructions are mul/div/rem/fmul/fdiv/frem operations.
unsigned getOpcode() const
The main/alternate opcodes for the list of instructions.
A private "module" namespace for types and utilities used by this pass.
SmallVector< SmallVector< Value * > > scanAltAssociativeOperands(const InstructionsState &S, const TargetLibraryInfo &TLI, ArrayRef< Value * > VL, ArrayRef< Value * > Op0, ArrayRef< Value * > Op1, SmallVectorImpl< Value * > &ReassocScalars, SmallBitVector &SubLanes)
Peel the per-lane associative chains of an alternate node into operand columns.
std::pair< Instruction *, SmallVector< Value * > > convertTo(Instruction *I, const InstructionsState &S)
bool isAlternateInstruction(Instruction *I, Instruction *MainOp, Instruction *AltOp, const TargetLibraryInfo &TLI)
Checks if the specified instruction I is an alternate operation for the given MainOp and AltOp instru...
bool isValidForAlternation(unsigned Opcode)
bool hasOnlyAbsorbableCopyableFMulOrFAdds(ArrayRef< Value * > VL)
Checks if every copyable in VL is an absorbable fmul/fadd: the binops die instead of being computed a...
InstructionsState getSameOpcode(ArrayRef< Value * > VL, const TargetLibraryInfo &TLI)
bool isAbsorbableCopyableFMulOrFAdd(const InstructionsState &S, Value *V)
Checks if V is a copyable single-use fmul/fadd, absorbable as fmuladd(a, b, -0.0) or fmuladd(1....
bool isAbsorbableFMulOrFAdd(ArrayRef< Value * > VL, Value *V)
Checks if V is a single-use fmul/fadd with operands outside VL.
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool is_sorted_constexpr(R &&Range, Cmp C=Cmp{})
Check if elements in a range R are sorted with respect to a comparator C.
Definition STLExtras.h:1984
DWARFExpression::Operation Op
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
Definition STLExtras.h:2146