38std::pair<Constant *, unsigned>
39BinOpSameOpcodeHelper::isBinOpWithConstant(
const Instruction *
I) {
40 [[maybe_unused]]
unsigned Opcode =
I->getOpcode();
49 if (
Constant *
C = GetConstant(BinOp->getOperand(1)))
53 if (Constant *
C = GetConstant(BinOp->getOperand(0)))
58bool BinOpSameOpcodeHelper::InterchangeableInfo::trySet(
59 MaskType OpcodeInMaskForm, MaskType InterchangeableMask) {
60 if (Mask & InterchangeableMask) {
61 SeenBefore |= OpcodeInMaskForm;
62 Mask &= InterchangeableMask;
68unsigned BinOpSameOpcodeHelper::InterchangeableInfo::getOpcode()
const {
69 MaskType Candidate =
Mask & SeenBefore;
70 if (Candidate & MainOpBIT)
71 return I->getOpcode();
72 if (Candidate & ShlBIT)
73 return Instruction::Shl;
74 if (Candidate & AShrBIT)
75 return Instruction::AShr;
76 if (Candidate & MulBIT)
77 return Instruction::Mul;
78 if (Candidate & AddBIT)
79 return Instruction::Add;
80 if (Candidate & SubBIT)
81 return Instruction::Sub;
82 if (Candidate & FAddBIT)
83 return Instruction::FAdd;
84 if (Candidate & FSubBIT)
85 return Instruction::FSub;
86 if (Candidate & AndBIT)
87 return Instruction::And;
88 if (Candidate & OrBIT)
89 return Instruction::Or;
90 if (Candidate & XorBIT)
91 return Instruction::Xor;
95bool BinOpSameOpcodeHelper::InterchangeableInfo::hasCandidateOpcode(
96 unsigned Opcode)
const {
97 MaskType Candidate =
Mask & SeenBefore;
99 case Instruction::Shl:
100 return Candidate & ShlBIT;
101 case Instruction::AShr:
102 return Candidate & AShrBIT;
103 case Instruction::Mul:
104 return Candidate & MulBIT;
105 case Instruction::Add:
106 return Candidate & AddBIT;
107 case Instruction::Sub:
108 return Candidate & SubBIT;
109 case Instruction::And:
110 return Candidate & AndBIT;
111 case Instruction::Or:
112 return Candidate & OrBIT;
113 case Instruction::Xor:
114 return Candidate & XorBIT;
115 case Instruction::FAdd:
116 return Candidate & FAddBIT;
117 case Instruction::FSub:
118 return Candidate & FSubBIT;
119 case Instruction::LShr:
120 case Instruction::FMul:
121 case Instruction::SDiv:
122 case Instruction::UDiv:
123 case Instruction::FDiv:
124 case Instruction::SRem:
125 case Instruction::URem:
126 case Instruction::FRem:
135 const Instruction *To)
const {
137 unsigned FromOpcode =
I->getOpcode();
138 if (FromOpcode == ToOpcode)
141 auto [
C, Pos] = isBinOpWithConstant(
I);
142 Type *RHSType =
I->getOperand(Pos)->getType();
148 "Cannot convert the instruction.");
149 RHS = ConstantFP::get(RHSType, -CFP->getValueAPF());
152 const APInt &FromCIValue = CI->getValue();
153 unsigned FromCIValueBitWidth = FromCIValue.
getBitWidth();
154 switch (FromOpcode) {
155 case Instruction::Shl:
156 if (ToOpcode == Instruction::Add && FromCIValue.
isOne())
157 return {
I->getOperand(0),
I->getOperand(0)};
158 if (ToOpcode == Instruction::Mul) {
159 RHS = ConstantInt::get(RHSType,
163 assert(FromCIValue.
isZero() &&
"Cannot convert the instruction.");
168 case Instruction::Mul:
170 if (ToOpcode == Instruction::Shl) {
171 RHS = ConstantInt::get(
172 RHSType, APInt(FromCIValueBitWidth, FromCIValue.
logBase2()));
174 assert(FromCIValue.
isOne() &&
"Cannot convert the instruction.");
179 case Instruction::Add:
180 case Instruction::Sub:
181 if (FromCIValue.
isZero()) {
186 "Cannot convert the instruction.");
187 APInt NegatedVal = APInt(FromCIValue);
189 RHS = ConstantInt::get(RHSType, NegatedVal);
192 case Instruction::And:
198 assert(FromCIValue.
isZero() &&
"Cannot convert the instruction.");
213bool BinOpSameOpcodeHelper::isValidForAlternation(
const Instruction *
I)
const {
218bool BinOpSameOpcodeHelper::initializeAltOp(
const Instruction *
I) {
221 if (!isValidForAlternation(
I))
229 "BinOpSameOpcodeHelper only accepts BinaryOperator.");
230 unsigned Opcode =
I->getOpcode();
231 MaskType OpcodeInMaskForm;
235 case Instruction::Shl:
236 OpcodeInMaskForm = ShlBIT;
238 case Instruction::AShr:
239 OpcodeInMaskForm = AShrBIT;
241 case Instruction::Mul:
242 OpcodeInMaskForm = MulBIT;
244 case Instruction::Add:
245 OpcodeInMaskForm = AddBIT;
247 case Instruction::Sub:
248 OpcodeInMaskForm = SubBIT;
250 case Instruction::And:
251 OpcodeInMaskForm = AndBIT;
253 case Instruction::Or:
254 OpcodeInMaskForm = OrBIT;
256 case Instruction::Xor:
257 OpcodeInMaskForm = XorBIT;
259 case Instruction::FAdd:
260 OpcodeInMaskForm = FAddBIT;
262 case Instruction::FSub:
263 OpcodeInMaskForm = FSubBIT;
266 return MainOp.equal(Opcode) || (initializeAltOp(
I) && AltOp.equal(Opcode));
268 MaskType InterchangeableMask = OpcodeInMaskForm;
269 auto [
C, Pos] = isBinOpWithConstant(
I);
271 constexpr MaskType CanBeAll =
272 XorBIT | OrBIT | AndBIT | SubBIT | AddBIT | MulBIT | AShrBIT | ShlBIT;
273 const APInt &CIValue = CI->getValue();
275 case Instruction::Shl:
277 InterchangeableMask = CIValue.
isZero() ? CanBeAll : MulBIT | ShlBIT;
279 InterchangeableMask |= AddBIT;
281 case Instruction::Mul:
282 if (CIValue.
isOne()) {
283 InterchangeableMask = CanBeAll;
287 InterchangeableMask = MulBIT | ShlBIT;
289 case Instruction::Add:
290 case Instruction::Sub:
291 InterchangeableMask = CIValue.
isZero() ? CanBeAll : SubBIT | AddBIT;
293 case Instruction::And:
295 InterchangeableMask = CanBeAll;
297 case Instruction::Xor:
299 InterchangeableMask = XorBIT | OrBIT | SubBIT | AddBIT;
303 InterchangeableMask = CanBeAll;
306 }
else if (
C && Pos == 1) {
314 InterchangeableMask = FSubBIT | FAddBIT;
316 return MainOp.trySet(OpcodeInMaskForm, InterchangeableMask) ||
317 (initializeAltOp(
I) &&
318 AltOp.trySet(OpcodeInMaskForm, InterchangeableMask));
323 if (
I->getOpcode() !=
Op->getOpcode())
330 IOp->getIntrinsicID()) !=
336 assert(MainOp &&
"MainOp cannot be nullptr.");
339 if (MainOp->getOpcode() == Instruction::Select &&
343 assert(AltOp &&
"AltOp cannot be nullptr.");
347 if (!
I->isBinaryOp() || !MainOp->isBinaryOp())
354 if (AltConverter.
add(
I) && AltConverter.
add(AltOp) &&
360 return Converter.hasAltOp() ? AltOp : MainOp;
364 constexpr std::array<unsigned, 8> MulDiv = {
365 Instruction::Mul, Instruction::FMul, Instruction::SDiv,
366 Instruction::UDiv, Instruction::FDiv, Instruction::SRem,
367 Instruction::URem, Instruction::FRem};
373 constexpr std::array<unsigned, 4> AddSub = {
374 Instruction::Add, Instruction::Sub, Instruction::FAdd, Instruction::FSub};
380 assert(
valid() &&
"InstructionsState is invalid.");
388 if (
I->getParent() != MainOp->getParent() &&
395 if (!
I->isBinaryOp() || !MainOp->isBinaryOp())
404 return I &&
I->getOpcode() == Instruction::FMul &&
I->hasOneUse() &&
406 [&](
Value *
Op) { return is_contained(VL, Op); });
416 assert(
valid() &&
"InstructionsState is invalid.");
422 auto CheckForTransformedOpcode = [](
const Instruction *RefOp,
425 case Instruction::Add:
426 switch (ExpandingOp->getOpcode()) {
427 case Instruction::Shl:
444 return CheckForTransformedOpcode(MainOp, ExpandingOp);
449 switch (
I->getOpcode()) {
450 case Instruction::Shl:
459 assert(
valid() &&
"InstructionsState is invalid.");
469 auto IsNonSchedulableCopyableElement = [
this](
Value *V) {
471 return !
I ||
isa<PHINode>(
I) ||
I->getParent() != MainOp->getParent() ||
476 !MainOp->comesBefore(
I));
479 return IsNonSchedulableCopyableElement(V);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
uint64_t IntrinsicInst * II
This file defines the SmallVector class.
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned logBase2() const
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
bool isOne() const
Determine if this is a value of 1.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static LLVM_ABI Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
This is an important base class in LLVM.
LLVM_ABI bool isCommutative() const LLVM_READONLY
Return true if the instruction is commutative:
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
LLVM Value Representation.
Helper class that determines VL can use the same opcode.
unsigned getAltOpcode() const
bool add(const Instruction *I)
bool hasCandidateOpcode(unsigned Opcode) const
Checks if the list of potential opcodes includes Opcode.
Main data required for vectorization of instructions.
Instruction * getMainOp() const
Instruction * getMatchingMainOpOrAltOp(Instruction *I) const
Checks if the instruction matches either the main or alternate opcode.
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 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 isAltShuffle() const
Some of the instructions in the list have alternate opcodes.
bool isNonSchedulable(Value *V) const
Checks if the value is non-schedulable.
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
A private "module" namespace for types and utilities used by this pass.
bool isValidForAlternation(unsigned Opcode)
bool isCommutative(const Instruction *I, const Value *ValWithUses, bool IsCopyable)
Intrinsic::ID isEquivalentIntrinsicID(Intrinsic::ID LHS, Intrinsic::ID RHS)
Checks if LHS and RHS are the same intrinsic, or one is llvm.fma and the other is llvm....
bool isVectorLikeInstWithConstOps(Value *V)
Checks if V is one of vector-like instructions, i.e.
bool isAbsorbableFMul(ArrayRef< Value * > VL, Value *V)
Checks if V is a single-use fmul with operands outside VL.
bool isAbsorbableCopyableFMul(const InstructionsState &S, Value *V)
Checks if V is a copyable single-use fmul, absorbable as fmuladd(a, b, -0.0).
bool doesNotNeedToBeScheduled(Value *V)
Checks if the specified value does not require scheduling.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto binary_search(R &&Range, T &&Value)
Provide wrappers to std::binary_search which take ranges instead of having to pass begin/end explicit...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.