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"
26
27#include <cstdint>
28#include <utility>
29
30namespace llvm {
31class Constant;
33class Value;
34} // namespace llvm
35
36namespace llvm::slpvectorizer {
37
38/// \returns true if \p Opcode is allowed as part of the main/alternate
39/// instruction for SLP vectorization.
40///
41/// Example of unsupported opcode is SDIV that can potentially cause UB if the
42/// "shuffled out" lane would result in division by zero.
43bool isValidForAlternation(unsigned Opcode);
44
45/// Helper class that determines VL can use the same opcode.
46/// Alternate instruction is supported. In addition, it supports interchangeable
47/// instruction. An interchangeable instruction is an instruction that can be
48/// converted to another instruction with same semantics. For example, x << 1 is
49/// equal to x * 2. x * 1 is equal to x | 0.
51 using MaskType = std::uint_fast32_t;
52 /// Sort SupportedOp because it is used by binary_search.
53 constexpr static unsigned SupportedOp[] = {
54 Instruction::Add, Instruction::FAdd, Instruction::Sub, Instruction::FSub,
55 Instruction::Mul, Instruction::Shl, Instruction::AShr, Instruction::And,
56 Instruction::Or, Instruction::Xor};
57 static_assert(llvm::is_sorted_constexpr(SupportedOp) &&
58 "SupportedOp is not sorted.");
59 enum : MaskType {
60 ShlBIT = 1,
61 AShrBIT = 1 << 1,
62 MulBIT = 1 << 2,
63 AddBIT = 1 << 3,
64 SubBIT = 1 << 4,
65 AndBIT = 1 << 5,
66 OrBIT = 1 << 6,
67 XorBIT = 1 << 7,
68 FAddBIT = 1 << 8,
69 FSubBIT = 1 << 9,
70 MainOpBIT = 1 << 10,
72 };
73 /// Return a non-nullptr if either operand of I is a ConstantInt (for the
74 /// integer opcodes) or a ConstantFP (for FAdd/FSub).
75 /// The second return value represents the operand position. We check the
76 /// right-hand side first (1). If the right hand side is not a constant and
77 /// the instruction is neither Sub, FSub, Shl, nor AShr, we then check the
78 /// left hand side (0).
79 static std::pair<Constant *, unsigned>
80 isBinOpWithConstant(const Instruction *I);
81 struct InterchangeableInfo {
82 const Instruction *I = nullptr;
83 /// The bit it sets represents whether MainOp can be converted to.
84 MaskType Mask = MainOpBIT | XorBIT | OrBIT | AndBIT | SubBIT | AddBIT |
85 MulBIT | AShrBIT | ShlBIT | FSubBIT | FAddBIT;
86 /// We cannot create an interchangeable instruction that does not exist in
87 /// VL. For example, VL [x + 0, y * 1] can be converted to [x << 0, y << 0],
88 /// but << does not exist in VL. In the end, we convert VL to [x * 1, y *
89 /// 1]. SeenBefore is used to know what operations have been seen before.
90 MaskType SeenBefore = 0;
91 InterchangeableInfo(const Instruction *I) : I(I) {}
92 /// Return false allows BinOpSameOpcodeHelper to find an alternate
93 /// instruction. Directly setting the mask will destroy the mask state,
94 /// preventing us from determining which instruction it should convert to.
95 bool trySet(MaskType OpcodeInMaskForm, MaskType InterchangeableMask);
96 bool equal(unsigned Opcode) {
97 return Opcode == I->getOpcode() && trySet(MainOpBIT, MainOpBIT);
98 }
99 unsigned getOpcode() const;
100 bool hasDefinedOpcode() const { return (Mask & SeenBefore) > 0; }
101 /// Return true if the instruction can be converted to \p Opcode.
102 bool hasCandidateOpcode(unsigned Opcode) const;
104 };
105 InterchangeableInfo MainOp;
106 InterchangeableInfo AltOp;
107 bool isValidForAlternation(const Instruction *I) const;
108 bool initializeAltOp(const Instruction *I);
109
110public:
112 const Instruction *AltOp = nullptr)
113 : MainOp(MainOp), AltOp(AltOp) {}
114 bool add(const Instruction *I);
115 unsigned getMainOpcode() const { return MainOp.getOpcode(); }
116 bool hasDefinedMainOpcode() const { return MainOp.hasDefinedOpcode(); }
117 /// Checks if the list of potential opcodes includes \p Opcode.
118 bool hasCandidateOpcode(unsigned Opcode) const {
119 return MainOp.hasCandidateOpcode(Opcode);
120 }
121 bool hasAltOp() const { return AltOp.I; }
122 unsigned getAltOpcode() const {
123 return hasAltOp() ? AltOp.getOpcode() : getMainOpcode();
124 }
125 bool hasDefinedAltOpcode() const {
126 return !hasAltOp() || AltOp.hasDefinedOpcode();
127 }
129 return MainOp.getOperand(I);
130 }
131};
132
133/// Main data required for vectorization of instructions.
135 /// MainOp and AltOp are primarily determined by getSameOpcode. Currently,
136 /// only BinaryOperator, CastInst, and CmpInst support alternate instructions
137 /// (i.e., AltOp is not equal to MainOp; this can be checked using
138 /// isAltShuffle).
139 /// A rare exception is TrySplitNode, where the InstructionsState is derived
140 /// from getMainAltOpsNoStateVL.
141 /// For those InstructionsState that use alternate instructions, the resulting
142 /// vectorized output ultimately comes from a shufflevector. For example,
143 /// given a vector list (VL):
144 /// VL[0] = add i32 a, e
145 /// VL[1] = sub i32 b, f
146 /// VL[2] = add i32 c, g
147 /// VL[3] = sub i32 d, h
148 /// The vectorized result would be:
149 /// intermediated_0 = add <4 x i32> <a, b, c, d>, <e, f, g, h>
150 /// intermediated_1 = sub <4 x i32> <a, b, c, d>, <e, f, g, h>
151 /// result = shufflevector <4 x i32> intermediated_0,
152 /// <4 x i32> intermediated_1,
153 /// <4 x i32> <i32 0, i32 5, i32 2, i32 7>
154 /// Since shufflevector is used in the final result, when calculating the cost
155 /// (getEntryCost), we must account for the usage of shufflevector in
156 /// GetVectorCost.
157 Instruction *MainOp = nullptr;
158 Instruction *AltOp = nullptr;
159 /// Whether the instruction state represents copyable instructions.
160 bool HasCopyables = false;
161 /// Index of the operand modeling the copyable values: the addend for
162 /// fmuladd (retried with a multiplicand), the first operand otherwise.
163 unsigned CopyableOpIdx = 0;
164 /// Whether copyable single-use fmuls/fadds are modeled as
165 /// fmuladd(a, b, -0.0)/fmuladd(1.0, a, b), absorbing the binop instead of
166 /// computing and gathering its result.
167 bool AbsorbCopyableFMulOrFAdd = false;
168
169public:
171 assert(valid() && "InstructionsState is invalid.");
172 return MainOp;
173 }
174
176 assert(valid() && "InstructionsState is invalid.");
177 return AltOp;
178 }
179
180 /// The main/alternate opcodes for the list of instructions.
181 unsigned getOpcode() const { return getMainOp()->getOpcode(); }
182
183 unsigned getAltOpcode() const { return getAltOp()->getOpcode(); }
184
185 /// Some of the instructions in the list have alternate opcodes.
186 bool isAltShuffle() const { return getMainOp() != getAltOp(); }
187
188 /// Checks if \p I is the same operation as \p Op, distinguishing calls by
189 /// intrinsic ID (all calls share the Call opcode, so e.g. umax != smax).
190 static bool isSameOperation(const Instruction *I, const Instruction *Op);
191
192 /// Checks if the instruction matches either the main or alternate opcode.
193 /// \returns
194 /// - MainOp if \param I matches MainOp's opcode directly or can be converted
195 /// to it
196 /// - AltOp if \param I matches AltOp's opcode directly or can be converted to
197 /// it
198 /// - nullptr if \param I cannot be matched or converted to either opcode
200
201 /// Checks if main/alt instructions are shift operations.
202 bool isShiftOp() const {
203 return getMainOp()->isShift() && getAltOp()->isShift();
204 }
205
206 /// Checks if main/alt instructions are bitwise logic operations.
207 bool isBitwiseLogicOp() const {
209 }
210
211 /// Checks if main/alt instructions are mul/div/rem/fmul/fdiv/frem operations.
212 bool isMulDivLikeOp() const;
213
214 /// Checks if main/alt instructions are add/sub/fadd/fsub operations.
215 bool isAddSubLikeOp() const;
216
217 /// Checks if main/alt instructions are cmp operations.
218 bool isCmpOp() const {
219 return (getOpcode() == Instruction::ICmp ||
220 getOpcode() == Instruction::FCmp) &&
221 getAltOpcode() == getOpcode();
222 }
223
224 /// Checks if the current state is valid, i.e. has non-null MainOp
225 bool valid() const { return MainOp && AltOp; }
226
227 explicit operator bool() const { return valid(); }
228
231 bool HasCopyables = false)
232 : MainOp(MainOp), AltOp(AltOp), HasCopyables(HasCopyables),
233 CopyableOpIdx(MainOp && RecurrenceDescriptor::isFMulAddIntrinsic(MainOp)
234 ? 2
235 : 0) {}
236 static InstructionsState invalid() { return {nullptr, nullptr}; }
237
238 /// Checks if the value is a copyable element.
239 bool isCopyableElement(Value *V) const;
240
241 /// Checks if the value \p V is a transformed instruction, compatible either
242 /// with main or alternate ops.
243 bool isExpandedBinOp(Value *V) const;
244
245 /// Checks if the operand at index \p Idx of instruction \p I is an expanded
246 /// operand.
247 bool isExpandedOperand(Instruction *I, unsigned Idx) const;
248
249 /// Checks if the value is non-schedulable.
250 bool isNonSchedulable(Value *V) const;
251
252 /// Checks if the state represents copyable instructions.
254 assert(valid() && "InstructionsState is invalid.");
255 return HasCopyables;
256 }
257
258 /// Returns the index of the operand the copyable value is modeled in.
259 unsigned getCopyableOpIdx() const {
260 assert(valid() && "InstructionsState is invalid.");
261 return CopyableOpIdx;
262 }
263
264 /// Sets the index of the operand the copyable value is modeled in.
265 void setCopyableOpIdx(unsigned Idx) {
266 assert((Idx == 0 || Idx == 2) && "Unexpected copyable operand index.");
267 CopyableOpIdx = Idx;
268 }
269
270 /// Checks if copyable fmuls/fadds are absorbed as fmuladd(a, b, -0.0) or
271 /// fmuladd(1.0, a, b).
273 assert(valid() && "InstructionsState is invalid.");
274 return AbsorbCopyableFMulOrFAdd;
275 }
276
277 /// Sets the absorbed-fmul/fadd modeling for copyable fmuls/fadds.
278 void setAbsorbCopyableFMulOrFAdd(bool Absorb) {
279 AbsorbCopyableFMulOrFAdd = Absorb;
280 }
281};
282
283/// Checks if \p V is a single-use fmul/fadd with operands outside \p VL.
285
286/// Checks if \p V is a copyable single-use fmul/fadd, absorbable as
287/// fmuladd(a, b, -0.0) or fmuladd(1.0, a, b).
288bool isAbsorbableCopyableFMulOrFAdd(const InstructionsState &S, Value *V);
289
290/// Checks if every copyable in \p VL is an absorbable fmul/fadd: the binops
291/// die instead of being computed and gathered. Operand order is normalized
292/// when the operands are built.
294
295/// \returns analysis of the Instructions in \p VL described in
296/// InstructionsState, the Opcode that we suppose the whole list
297/// could be vectorized even if its structure is diverse.
298InstructionsState getSameOpcode(ArrayRef<Value *> VL,
299 const TargetLibraryInfo &TLI);
300
301/// \returns the main or alternate operation from \p S matching \p I, together
302/// with the operands of \p I adjusted to the selected operation.
303std::pair<Instruction *, SmallVector<Value *>>
304convertTo(Instruction *I, const InstructionsState &S);
305
306/// Checks if the specified instruction \p I is an alternate operation for
307/// the given \p MainOp and \p AltOp instructions.
309 Instruction *AltOp, const TargetLibraryInfo &TLI);
310
311/// Peel the per-lane associative chains of an alternate node into operand
312/// columns. Lanes peel in lockstep and only chain links with the lane's own
313/// opcode, so every combine level keeps the root's main/alt opcode pattern
314/// and a subtract lane never becomes an add of a negated leaf. Only the
315/// leading (running) column peels: peeling a subtracted subtract would flip
316/// signs. \p SubLanes records the subtract lanes for the realignment sign
317/// query. Returns the flattened columns, empty when no level peels.
319 const InstructionsState &S, const TargetLibraryInfo &TLI,
321 SmallVectorImpl<Value *> &ReassocScalars, SmallBitVector &SubLanes);
322} // namespace llvm::slpvectorizer
323
324#endif // LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPCOMPATIBILITYANALYSIS_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define I(x, y, z)
Definition MD5.cpp:57
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
This is an important base class in LLVM.
Definition Constant.h:43
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)
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