32std::pair<Constant *, unsigned>
33BinOpSameOpcodeHelper::isBinOpWithConstant(
const Instruction *
I) {
34 [[maybe_unused]]
unsigned Opcode =
I->getOpcode();
43 if (
Constant *
C = GetConstant(BinOp->getOperand(1)))
47 if (Constant *
C = GetConstant(BinOp->getOperand(0)))
52bool BinOpSameOpcodeHelper::InterchangeableInfo::trySet(
53 MaskType OpcodeInMaskForm, MaskType InterchangeableMask) {
54 if (Mask & InterchangeableMask) {
55 SeenBefore |= OpcodeInMaskForm;
56 Mask &= InterchangeableMask;
62unsigned BinOpSameOpcodeHelper::InterchangeableInfo::getOpcode()
const {
63 MaskType Candidate =
Mask & SeenBefore;
64 if (Candidate & MainOpBIT)
65 return I->getOpcode();
66 if (Candidate & ShlBIT)
67 return Instruction::Shl;
68 if (Candidate & AShrBIT)
69 return Instruction::AShr;
70 if (Candidate & MulBIT)
71 return Instruction::Mul;
72 if (Candidate & AddBIT)
73 return Instruction::Add;
74 if (Candidate & SubBIT)
75 return Instruction::Sub;
76 if (Candidate & FAddBIT)
77 return Instruction::FAdd;
78 if (Candidate & FSubBIT)
79 return Instruction::FSub;
80 if (Candidate & AndBIT)
81 return Instruction::And;
82 if (Candidate & OrBIT)
83 return Instruction::Or;
84 if (Candidate & XorBIT)
85 return Instruction::Xor;
89bool BinOpSameOpcodeHelper::InterchangeableInfo::hasCandidateOpcode(
90 unsigned Opcode)
const {
91 MaskType Candidate =
Mask & SeenBefore;
93 case Instruction::Shl:
94 return Candidate & ShlBIT;
95 case Instruction::AShr:
96 return Candidate & AShrBIT;
97 case Instruction::Mul:
98 return Candidate & MulBIT;
99 case Instruction::Add:
100 return Candidate & AddBIT;
101 case Instruction::Sub:
102 return Candidate & SubBIT;
103 case Instruction::And:
104 return Candidate & AndBIT;
105 case Instruction::Or:
106 return Candidate & OrBIT;
107 case Instruction::Xor:
108 return Candidate & XorBIT;
109 case Instruction::FAdd:
110 return Candidate & FAddBIT;
111 case Instruction::FSub:
112 return Candidate & FSubBIT;
113 case Instruction::LShr:
114 case Instruction::FMul:
115 case Instruction::SDiv:
116 case Instruction::UDiv:
117 case Instruction::FDiv:
118 case Instruction::SRem:
119 case Instruction::URem:
120 case Instruction::FRem:
129 const Instruction *To)
const {
131 unsigned FromOpcode =
I->getOpcode();
132 if (FromOpcode == ToOpcode)
135 auto [
C, Pos] = isBinOpWithConstant(
I);
136 Type *RHSType =
I->getOperand(Pos)->getType();
142 "Cannot convert the instruction.");
143 RHS = ConstantFP::get(RHSType, -CFP->getValueAPF());
146 const APInt &FromCIValue = CI->getValue();
147 unsigned FromCIValueBitWidth = FromCIValue.
getBitWidth();
148 switch (FromOpcode) {
149 case Instruction::Shl:
150 if (ToOpcode == Instruction::Add && FromCIValue.
isOne())
151 return {
I->getOperand(0),
I->getOperand(0)};
152 if (ToOpcode == Instruction::Mul) {
153 RHS = ConstantInt::get(RHSType,
157 assert(FromCIValue.
isZero() &&
"Cannot convert the instruction.");
162 case Instruction::Mul:
164 if (ToOpcode == Instruction::Shl) {
165 RHS = ConstantInt::get(
166 RHSType, APInt(FromCIValueBitWidth, FromCIValue.
logBase2()));
168 assert(FromCIValue.
isOne() &&
"Cannot convert the instruction.");
173 case Instruction::Add:
174 case Instruction::Sub:
175 if (FromCIValue.
isZero()) {
180 "Cannot convert the instruction.");
181 APInt NegatedVal = APInt(FromCIValue);
183 RHS = ConstantInt::get(RHSType, NegatedVal);
186 case Instruction::And:
192 assert(FromCIValue.
isZero() &&
"Cannot convert the instruction.");
207bool BinOpSameOpcodeHelper::isValidForAlternation(
const Instruction *
I)
const {
212bool BinOpSameOpcodeHelper::initializeAltOp(
const Instruction *
I) {
215 if (!isValidForAlternation(
I))
223 "BinOpSameOpcodeHelper only accepts BinaryOperator.");
224 unsigned Opcode =
I->getOpcode();
225 MaskType OpcodeInMaskForm;
229 case Instruction::Shl:
230 OpcodeInMaskForm = ShlBIT;
232 case Instruction::AShr:
233 OpcodeInMaskForm = AShrBIT;
235 case Instruction::Mul:
236 OpcodeInMaskForm = MulBIT;
238 case Instruction::Add:
239 OpcodeInMaskForm = AddBIT;
241 case Instruction::Sub:
242 OpcodeInMaskForm = SubBIT;
244 case Instruction::And:
245 OpcodeInMaskForm = AndBIT;
247 case Instruction::Or:
248 OpcodeInMaskForm = OrBIT;
250 case Instruction::Xor:
251 OpcodeInMaskForm = XorBIT;
253 case Instruction::FAdd:
254 OpcodeInMaskForm = FAddBIT;
256 case Instruction::FSub:
257 OpcodeInMaskForm = FSubBIT;
260 return MainOp.equal(Opcode) || (initializeAltOp(
I) && AltOp.equal(Opcode));
262 MaskType InterchangeableMask = OpcodeInMaskForm;
263 auto [
C, Pos] = isBinOpWithConstant(
I);
265 constexpr MaskType CanBeAll =
266 XorBIT | OrBIT | AndBIT | SubBIT | AddBIT | MulBIT | AShrBIT | ShlBIT;
267 const APInt &CIValue = CI->getValue();
269 case Instruction::Shl:
271 InterchangeableMask = CIValue.
isZero() ? CanBeAll : MulBIT | ShlBIT;
273 InterchangeableMask |= AddBIT;
275 case Instruction::Mul:
276 if (CIValue.
isOne()) {
277 InterchangeableMask = CanBeAll;
281 InterchangeableMask = MulBIT | ShlBIT;
283 case Instruction::Add:
284 case Instruction::Sub:
285 InterchangeableMask = CIValue.
isZero() ? CanBeAll : SubBIT | AddBIT;
287 case Instruction::And:
289 InterchangeableMask = CanBeAll;
291 case Instruction::Xor:
293 InterchangeableMask = XorBIT | OrBIT | SubBIT | AddBIT;
297 InterchangeableMask = CanBeAll;
300 }
else if (
C && Pos == 1) {
308 InterchangeableMask = FSubBIT | FAddBIT;
310 return MainOp.trySet(OpcodeInMaskForm, InterchangeableMask) ||
311 (initializeAltOp(
I) &&
312 AltOp.trySet(OpcodeInMaskForm, InterchangeableMask));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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.
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.
bool add(const Instruction *I)
#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.
@ C
The default llvm calling convention, compatible with C.
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)
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)
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...
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.