66using namespace PatternMatch;
68#define DEBUG_TYPE "reassociate"
70STATISTIC(NumChanged,
"Number of insts reassociated");
71STATISTIC(NumAnnihil,
"Number of expr tree annihilated");
72STATISTIC(NumFactor ,
"Number of multiplies factored");
76 cl::desc(
"Only reorder expressions within a basic block "
77 "when exposing CSE opportunities"),
85 << *Ops[0].Op->getType() <<
'\t';
86 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
88 Ops[i].Op->printAsOperand(
dbgs(),
false, M);
89 dbgs() <<
", #" << Ops[i].Rank <<
"] ";
106 bool isInvalid()
const {
return SymbolicPart ==
nullptr; }
120 unsigned SymbolicRank;
125 assert(!isa<ConstantInt>(V) &&
"No ConstantInt");
130 if (
I && (
I->getOpcode() == Instruction::Or ||
131 I->getOpcode() == Instruction::And)) {
132 Value *V0 =
I->getOperand(0);
133 Value *V1 =
I->getOperand(1);
141 isOr = (
I->getOpcode() == Instruction::Or);
157 assert(
I && isa<FPMathOperator>(
I) &&
"Should only check FP ops");
158 return I->hasAllowReassoc() &&
I->hasNoSignedZeros();
164 auto *BO = dyn_cast<BinaryOperator>(V);
165 if (BO && BO->hasOneUse() && BO->getOpcode() == Opcode)
173 auto *BO = dyn_cast<BinaryOperator>(V);
174 if (BO && BO->hasOneUse() &&
175 (BO->getOpcode() == Opcode1 || BO->getOpcode() == Opcode2))
181void ReassociatePass::BuildRankMap(
Function &
F,
186 for (
auto &Arg :
F.args()) {
187 ValueRankMap[&Arg] = ++Rank;
188 LLVM_DEBUG(
dbgs() <<
"Calculated Rank[" << Arg.getName() <<
"] = " << Rank
194 unsigned BBRank = RankMap[BB] = ++Rank << 16;
201 ValueRankMap[&
I] = ++BBRank;
205unsigned ReassociatePass::getRank(
Value *V) {
208 if (isa<Argument>(V))
return ValueRankMap[
V];
212 if (
unsigned Rank = ValueRankMap[
I])
219 unsigned Rank = 0, MaxRank = RankMap[
I->getParent()];
220 for (
unsigned i = 0, e =
I->getNumOperands(); i != e && Rank != MaxRank; ++i)
221 Rank = std::max(Rank, getRank(
I->getOperand(i)));
229 LLVM_DEBUG(
dbgs() <<
"Calculated Rank[" <<
V->getName() <<
"] = " << Rank
232 return ValueRankMap[
I] = Rank;
236void ReassociatePass::canonicalizeOperands(
Instruction *
I) {
237 assert(isa<BinaryOperator>(
I) &&
"Expected binary operator.");
238 assert(
I->isCommutative() &&
"Expected commutative operator.");
242 if (LHS == RHS || isa<Constant>(RHS))
244 if (isa<Constant>(LHS) || getRank(RHS) < getRank(LHS))
245 cast<BinaryOperator>(
I)->swapOperands();
251 if (
S1->getType()->isIntOrIntVectorTy())
252 return BinaryOperator::CreateAdd(
S1, S2,
Name, InsertBefore);
255 BinaryOperator::CreateFAdd(
S1, S2,
Name, InsertBefore);
264 if (
S1->getType()->isIntOrIntVectorTy())
265 return BinaryOperator::CreateMul(
S1, S2,
Name, InsertBefore);
268 BinaryOperator::CreateFMul(
S1, S2,
Name, InsertBefore);
277 if (
S1->getType()->isIntOrIntVectorTy())
280 if (
auto *FMFSource = dyn_cast<Instruction>(FlagsOp))
283 return UnaryOperator::CreateFNeg(
S1,
Name, InsertBefore);
288 assert((isa<UnaryOperator>(Neg) || isa<BinaryOperator>(Neg)) &&
289 "Expected a Negate!");
291 unsigned OpNo = isa<BinaryOperator>(Neg) ? 1 : 0;
384 assert((isa<UnaryOperator>(
I) || isa<BinaryOperator>(
I)) &&
385 "Expected a UnaryOperator or BinaryOperator!");
387 unsigned Opcode =
I->getOpcode();
388 assert(
I->isAssociative() &&
I->isCommutative() &&
389 "Expected an associative and commutative operation!");
403 bool Changed =
false;
428 while (!Worklist.
empty()) {
432 if (isa<OverflowingBinaryOperator>(
I)) {
433 Flags.HasNUW &=
I->hasNoUnsignedWrap();
434 Flags.HasNSW &=
I->hasNoSignedWrap();
437 for (
unsigned OpIdx = 0; OpIdx <
I->getNumOperands(); ++OpIdx) {
440 assert(!
Op->use_empty() &&
"No uses, so how did we get to it?!");
447 Worklist.
push_back(std::make_pair(BO, Weight));
452 LeafMap::iterator It = Leaves.find(
Op);
453 if (It == Leaves.end()) {
456 if (!
Op->hasOneUse()) {
460 <<
"ADD USES LEAF: " << *
Op <<
" (" << Weight <<
")\n");
469 "In leaf map but not visited!");
472 It->second += Weight;
473 assert(It->second >= Weight &&
"Weight overflows");
477 if (!
Op->hasOneUse())
491 || (isa<FPMathOperator>(
Op) &&
493 "Should have been handled above!");
494 assert(
Op->hasOneUse() &&
"Has uses outside the expression tree!");
506 <<
"MORPH LEAF: " << *
Op <<
" (" << Weight <<
") TO ");
530 for (
Value *V : LeafOrder) {
531 LeafMap::iterator It = Leaves.find(V);
532 if (It == Leaves.end())
539 Ops.
push_back(std::make_pair(V, Weight));
540 if (Opcode == Instruction::Add && Flags.AllKnownNonNegative && Flags.HasNSW)
542 else if (Opcode == Instruction::Mul) {
545 if (Flags.AllKnownNonZero &&
546 (Flags.HasNUW || (Flags.HasNSW && Flags.AllKnownNonNegative))) {
548 if (Flags.HasNSW && Flags.AllKnownNonNegative)
559 assert(Identity &&
"Associative operation without identity!");
571 assert(Ops.
size() > 1 &&
"Single values should be used directly!");
585 unsigned Opcode =
I->getOpcode();
607 *ExpressionChangedEnd =
nullptr;
608 for (
unsigned i = 0; ; ++i) {
612 if (i+2 == Ops.size()) {
613 Value *NewLHS = Ops[i].Op;
614 Value *NewRHS = Ops[i+1].Op;
615 Value *OldLHS =
Op->getOperand(0);
616 Value *OldRHS =
Op->getOperand(1);
618 if (NewLHS == OldLHS && NewRHS == OldRHS)
622 if (NewLHS == OldRHS && NewRHS == OldLHS) {
635 if (NewLHS != OldLHS) {
637 if (BO && !NotRewritable.
count(BO))
639 Op->setOperand(0, NewLHS);
641 if (NewRHS != OldRHS) {
643 if (BO && !NotRewritable.
count(BO))
645 Op->setOperand(1, NewRHS);
649 ExpressionChangedStart =
Op;
650 if (!ExpressionChangedEnd)
651 ExpressionChangedEnd =
Op;
660 Value *NewRHS = Ops[i].Op;
661 if (NewRHS !=
Op->getOperand(1)) {
663 if (NewRHS ==
Op->getOperand(0)) {
670 if (BO && !NotRewritable.
count(BO))
672 Op->setOperand(1, NewRHS);
673 ExpressionChangedStart =
Op;
674 if (!ExpressionChangedEnd)
675 ExpressionChangedEnd =
Op;
686 if (BO && !NotRewritable.
count(BO)) {
699 if (NodesToRewrite.
empty()) {
703 if (isa<FPMathOperator>(NewOp))
710 Op->setOperand(0, NewOp);
712 ExpressionChangedStart =
Op;
713 if (!ExpressionChangedEnd)
714 ExpressionChangedEnd =
Op;
724 if (ExpressionChangedStart) {
725 bool ClearFlags =
true;
729 if (isa<FPMathOperator>(
I)) {
735 if (ExpressionChangedStart->
getOpcode() == Instruction::Add ||
736 (ExpressionChangedStart->
getOpcode() == Instruction::Mul &&
737 Flags.AllKnownNonZero)) {
746 if (ExpressionChangedStart == ExpressionChangedEnd)
748 if (ExpressionChangedStart ==
I)
759 ExpressionChangedStart =
760 cast<BinaryOperator>(*ExpressionChangedStart->
user_begin());
766 RedoInsts.insert(BO);
778 if (
auto *
C = dyn_cast<Constant>(V)) {
780 Constant *Res =
C->getType()->isFPOrFPVectorTy()
801 if (
I->getOpcode() == Instruction::Add) {
802 I->setHasNoUnsignedWrap(
false);
803 I->setHasNoSignedWrap(
false);
812 I->setName(
I->getName()+
".neg");
822 for (
User *U : V->users()) {
835 C->containsUndefOrPoisonElement())
844 if (
Instruction *InstInput = dyn_cast<Instruction>(V)) {
845 auto InsertPtOpt = InstInput->getInsertionPointAfterDef();
848 InsertPt = *InsertPtOpt;
859 if (TheNeg->
getParent() != InsertPt->getParent())
861 TheNeg->
moveBefore(*InsertPt->getParent(), InsertPt);
863 if (TheNeg->
getOpcode() == Instruction::Sub) {
890 auto Enqueue = [&](
Value *V) {
891 auto *
I = dyn_cast<Instruction>(V);
904 while (!Worklist.
empty()) {
908 switch (
I->getOpcode()) {
909 case Instruction::Or:
916 case Instruction::Shl:
917 case Instruction::ZExt:
919 if (!Enqueue(
I->getOperand(0)))
923 case Instruction::Load:
941 for (
auto Op : {Instruction::Add, Instruction::Sub, Instruction::Mul,
963 Or->getIterator(),
Or);
964 New->setHasNoSignedWrap();
965 New->setHasNoUnsignedWrap();
969 Or->replaceAllUsesWith(New);
970 New->setDebugLoc(
Or->getDebugLoc());
972 LLVM_DEBUG(
dbgs() <<
"Converted or into an add: " << *New <<
'\n');
1033 auto *SA = cast<ConstantInt>(Shl->
getOperand(1));
1035 assert(MulCst &&
"Constant folding of immediate constants failed");
1050 bool NSW = cast<BinaryOperator>(Shl)->hasNoSignedWrap();
1051 bool NUW = cast<BinaryOperator>(Shl)->hasNoUnsignedWrap();
1053 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1054 Mul->setHasNoSignedWrap(
true);
1055 Mul->setHasNoUnsignedWrap(NUW);
1064 unsigned XRank = Ops[i].Rank;
1065 unsigned e = Ops.
size();
1066 for (
unsigned j = i+1; j != e && Ops[j].Rank == XRank; ++j) {
1071 if (I1->isIdenticalTo(I2))
1075 for (
unsigned j = i-1; j != ~0U && Ops[j].Rank == XRank; --j) {
1080 if (I1->isIdenticalTo(I2))
1090 if (Ops.
size() == 1)
return Ops.
back();
1094 return CreateAdd(V2, V1,
"reass.add", It, &*It);
1110 for (
unsigned i = 0, e = Tree.
size(); i != e; ++i) {
1115 bool FoundFactor =
false;
1116 bool NeedsNegate =
false;
1117 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1126 if (
ConstantInt *FC2 = dyn_cast<ConstantInt>(Factors[i].
Op))
1127 if (FC1->getValue() == -FC2->getValue()) {
1128 FoundFactor = NeedsNegate =
true;
1133 if (
ConstantFP *FC2 = dyn_cast<ConstantFP>(Factors[i].
Op)) {
1134 const APFloat &F1 = FC1->getValueAPF();
1135 APFloat F2(FC2->getValueAPF());
1138 FoundFactor = NeedsNegate =
true;
1148 RewriteExprTree(BO, Factors, Flags);
1156 if (Factors.
size() == 1) {
1157 RedoInsts.insert(BO);
1160 RewriteExprTree(BO, Factors, Flags);
1194 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1201 if (Opcode == Instruction::And)
1204 if (Opcode == Instruction::Or)
1212 if (i+1 != Ops.
size() && Ops[i+1].Op == Ops[i].Op) {
1213 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1222 assert(Opcode == Instruction::Xor);
1241 const APInt &ConstOpnd) {
1249 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1251 I->setDebugLoc(InsertBefore->getDebugLoc());
1274 if (C1 != ConstOpnd)
1283 RedoInsts.insert(
T);
1303 int DeadInstNum = 1;
1321 APInt C3((~C1) ^ C2);
1324 if (!C3.isZero() && !C3.isAllOnes()) {
1326 if (NewInstNum > DeadInstNum)
1342 if (NewInstNum > DeadInstNum)
1360 RedoInsts.insert(
T);
1362 RedoInsts.insert(
T);
1375 if (Ops.
size() == 1)
1380 Type *Ty = Ops[0].Op->getType();
1384 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1392 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1419 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1424 bool Changed =
false;
1425 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1426 XorOpnd *CurrOpnd = OpndPtrs[i];
1431 if (!ConstOpnd.
isZero() &&
1432 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1442 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1443 PrevOpnd = CurrOpnd;
1449 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1454 PrevOpnd = CurrOpnd;
1466 for (
const XorOpnd &O : Opnds) {
1472 if (!ConstOpnd.
isZero()) {
1473 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1477 unsigned Sz = Ops.
size();
1479 return Ops.
back().Op;
1482 return ConstantInt::get(Ty, ConstOpnd);
1499 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1500 Value *TheOp = Ops[i].Op;
1504 if (i+1 != Ops.
size() && Ops[i+1].Op == TheOp) {
1506 unsigned NumFound = 0;
1510 }
while (i != Ops.
size() && Ops[i].Op == TheOp);
1512 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1519 ConstantInt::get(Ty, NumFound) :
ConstantFP::
get(Ty, NumFound);
1525 RedoInsts.insert(
Mul);
1552 if (Ops.
size() == 2 &&
1587 unsigned MaxOcc = 0;
1588 Value *MaxOccVal =
nullptr;
1589 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1598 assert(Factors.
size() > 1 &&
"Bad linearize!");
1606 unsigned Occ = ++FactorOccurrences[
Factor];
1616 if (CI->isNegative() && !CI->isMinValue(
true)) {
1617 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1620 unsigned Occ = ++FactorOccurrences[
Factor];
1627 if (CF->isNegative()) {
1630 Factor = ConstantFP::get(CF->getContext(),
F);
1633 unsigned Occ = ++FactorOccurrences[
Factor];
1645 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1654 I->getType()->isIntOrIntVectorTy()
1655 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1659 for (
unsigned i = 0; i != Ops.
size(); ++i) {
1666 if (
Value *V = RemoveFactorFromExpression(Ops[i].
Op, MaxOccVal)) {
1669 for (
unsigned j = Ops.
size(); j != i;) {
1671 if (Ops[j].
Op == Ops[i].
Op) {
1683 unsigned NumAddedValues = NewMulOps.
size();
1689 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1690 (void)NumAddedValues;
1692 RedoInsts.insert(VI);
1699 RedoInsts.insert(V2);
1730 unsigned FactorPowerSum = 0;
1740 FactorPowerSum += Count;
1747 if (FactorPowerSum < 4)
1764 FactorPowerSum += Count;
1771 assert(FactorPowerSum >= 4);
1774 return LHS.Power >
RHS.Power;
1782 if (Ops.
size() == 1)
1791 }
while (!Ops.
empty());
1803ReassociatePass::buildMinimalMultiplyDAG(
IRBuilderBase &Builder,
1805 assert(Factors[0].Power);
1807 for (
unsigned LastIdx = 0,
Idx = 1,
Size = Factors.
size();
1809 if (Factors[
Idx].Power != Factors[LastIdx].Power) {
1822 }
while (
Idx <
Size && Factors[
Idx].Power == Factors[LastIdx].Power);
1828 RedoInsts.insert(
MI);
1836 return LHS.Power ==
RHS.Power;
1848 if (Factors[0].Power) {
1849 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1853 if (OuterProduct.
size() == 1)
1854 return OuterProduct.
front();
1878 if (
auto FPI = dyn_cast<FPMathOperator>(
I))
1881 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1896 unsigned Opcode =
I->getOpcode();
1897 while (!Ops.
empty()) {
1898 if (
auto *
C = dyn_cast<Constant>(Ops.
back().Op)) {
1925 if (Ops.
size() == 1)
return Ops[0].Op;
1929 unsigned NumOps = Ops.
size();
1932 case Instruction::And:
1933 case Instruction::Or:
1938 case Instruction::Xor:
1939 if (
Value *Result = OptimizeXor(
I, Ops))
1943 case Instruction::Add:
1944 case Instruction::FAdd:
1945 if (
Value *Result = OptimizeAdd(
I, Ops))
1949 case Instruction::Mul:
1950 case Instruction::FMul:
1951 if (
Value *Result = OptimizeMul(
I, Ops))
1956 if (Ops.
size() != NumOps)
1957 return OptimizeExpression(
I, Ops);
1963void ReassociatePass::RecursivelyEraseDeadInsts(
Instruction *
I,
1964 OrderedSet &Insts) {
1967 ValueRankMap.erase(
I);
1969 RedoInsts.remove(
I);
1971 I->eraseFromParent();
1972 for (
auto *
Op : Ops)
1974 if (OpInst->use_empty())
1975 Insts.insert(OpInst);
1985 ValueRankMap.erase(
I);
1986 RedoInsts.remove(
I);
1988 I->eraseFromParent();
1991 for (
Value *V : Ops)
1995 unsigned Opcode =
Op->getOpcode();
1996 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
1998 Op =
Op->user_back();
2005 if (ValueRankMap.contains(
Op))
2006 RedoInsts.insert(
Op);
2026 switch (
I->getOpcode()) {
2027 case Instruction::FMul:
2039 case Instruction::FDiv:
2064 assert((
I->getOpcode() == Instruction::FAdd ||
2065 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2071 if (Candidates.
empty())
2077 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2078 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2086 "Expecting only 1 constant operand");
2087 assert(
C->isNegative() &&
"Expected negative FP constant");
2088 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2093 "Expecting only 1 constant operand");
2094 assert(
C->isNegative() &&
"Expected negative FP constant");
2095 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2099 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2102 if (Candidates.size() % 2 == 0)
2107 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2111 I->replaceAllUsesWith(NewInst);
2112 RedoInsts.insert(
I);
2113 return dyn_cast<Instruction>(NewInst);
2144 if (!isa<UnaryOperator>(
I) && !isa<BinaryOperator>(
I))
2147 if (
I->getOpcode() == Instruction::Shl && isa<ConstantInt>(
I->getOperand(1)))
2155 RedoInsts.insert(
I);
2163 if (
I->isCommutative())
2164 canonicalizeOperands(
I);
2181 if (
I->getType()->isIntegerTy(1))
2186 if (
I->getOpcode() == Instruction::Or &&
2188 (cast<PossiblyDisjointInst>(
I)->isDisjoint() ||
2191 nullptr,
nullptr,
I)))) {
2193 RedoInsts.insert(
I);
2200 if (
I->getOpcode() == Instruction::Sub) {
2203 RedoInsts.insert(
I);
2217 RedoInsts.insert(Tmp);
2219 RedoInsts.insert(
I);
2224 }
else if (
I->getOpcode() == Instruction::FNeg ||
2225 I->getOpcode() == Instruction::FSub) {
2228 RedoInsts.insert(
I);
2234 Value *
Op = isa<BinaryOperator>(
I) ?
I->getOperand(1) :
2244 RedoInsts.insert(Tmp);
2246 RedoInsts.insert(
I);
2254 if (!
I->isAssociative())
return;
2273 cast<Instruction>(BO->
user_back())->getOpcode() == Instruction::Sub)
2276 cast<Instruction>(BO->
user_back())->getOpcode() == Instruction::FSub)
2279 ReassociateExpression(BO);
2305 if (
Value *V = OptimizeExpression(
I, Ops)) {
2312 I->replaceAllUsesWith(V);
2314 if (
I->getDebugLoc())
2315 VI->setDebugLoc(
I->getDebugLoc());
2316 RedoInsts.insert(
I);
2325 if (
I->hasOneUse()) {
2326 if (
I->getOpcode() == Instruction::Mul &&
2327 cast<Instruction>(
I->user_back())->getOpcode() == Instruction::Add &&
2328 isa<ConstantInt>(Ops.
back().Op) &&
2329 cast<ConstantInt>(Ops.
back().Op)->isMinusOne()) {
2332 }
else if (
I->getOpcode() == Instruction::FMul &&
2333 cast<Instruction>(
I->user_back())->getOpcode() ==
2334 Instruction::FAdd &&
2335 isa<ConstantFP>(Ops.
back().Op) &&
2336 cast<ConstantFP>(Ops.
back().Op)->isExactlyValue(-1.0)) {
2344 if (Ops.
size() == 1) {
2351 I->replaceAllUsesWith(Ops[0].
Op);
2353 OI->setDebugLoc(
I->getDebugLoc());
2354 RedoInsts.insert(
I);
2358 if (Ops.
size() > 2 && Ops.
size() <= GlobalReassociateLimit) {
2366 unsigned BestRank = 0;
2367 std::pair<unsigned, unsigned> BestPair;
2368 unsigned Idx =
I->getOpcode() - Instruction::BinaryOpsBegin;
2369 unsigned LimitIdx = 0;
2379 int StartIdx = Ops.
size() - 1;
2384 for (
int i = StartIdx - 1; i != -1; --i) {
2385 const Value *Val = Ops[i].Op;
2386 const auto *CurrLeafInstr = dyn_cast<Instruction>(Val);
2388 if (!CurrLeafInstr) {
2407 SeenBB = &
I->getParent()->getParent()->getEntryBlock();
2413 FirstSeenBB = SeenBB;
2416 if (FirstSeenBB != SeenBB) {
2422 << LimitIdx <<
", " << StartIdx <<
"]\n");
2427 for (
unsigned i = Ops.
size() - 1; i > LimitIdx; --i) {
2429 for (
int j = i - 1;
j >= (int)LimitIdx; --
j) {
2431 Value *Op0 = Ops[i].Op;
2433 if (std::less<Value *>()(Op1, Op0))
2435 auto it = PairMap[
Idx].find({Op0, Op1});
2436 if (it != PairMap[
Idx].
end()) {
2442 if (it->second.isValid())
2443 Score += it->second.Score;
2446 unsigned MaxRank = std::max(Ops[i].Rank, Ops[j].Rank);
2460 if (Score > Max || (Score == Max && MaxRank < BestRank)) {
2468 auto Op0 = Ops[BestPair.first];
2469 auto Op1 = Ops[BestPair.second];
2470 Ops.
erase(&Ops[BestPair.second]);
2471 Ops.
erase(&Ops[BestPair.first]);
2480 RewriteExprTree(
I, Ops, Flags);
2488 if (!
I.isAssociative() || !
I.isBinaryOp())
2492 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2500 while (!Worklist.
empty() && Ops.
size() <= GlobalReassociateLimit) {
2514 if (Ops.
size() > GlobalReassociateLimit)
2518 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2520 for (
unsigned i = 0; i < Ops.
size() - 1; ++i) {
2521 for (
unsigned j = i + 1;
j < Ops.
size(); ++
j) {
2523 Value *Op0 = Ops[i];
2525 if (std::less<Value *>()(Op1, Op0))
2527 if (!Visited.
insert({Op0, Op1}).second)
2529 auto res = PairMap[BinaryIdx].insert({{Op0, Op1}, {Op0, Op1, 1}});
2535 assert(res.first->second.isValid() &&
"WeakVH invalidated");
2536 ++res.first->second.Score;
2552 BuildRankMap(
F, RPOT);
2569 assert(RankMap.count(&*BI) &&
"BB should be ranked.");
2576 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2587 while (!ToRedo.
empty()) {
2590 RecursivelyEraseDeadInsts(
I, ToRedo);
2597 while (!RedoInsts.empty()) {
2599 RedoInsts.erase(RedoInsts.begin());
2609 ValueRankMap.clear();
2610 for (
auto &Entry : PairMap)
2635 if (skipFunction(
F))
2639 auto PA = Impl.
run(
F, DummyFAM);
2653char ReassociateLegacyPass::ID = 0;
2656 "Reassociate expressions",
false,
false)
2660 return new ReassociateLegacyPass();
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This is the interface for LLVM's primary stateless and local alias analysis.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This is the interface for a simple mod/ref and alias analysis over globals.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
static bool isReassociableOp(Instruction *I, unsigned IntOpcode, unsigned FPOpcode)
uint64_t IntrinsicInst * II
This header defines various interfaces for pass management in LLVM.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static void PrintOps(Instruction *I, const SmallVectorImpl< ValueEntry > &Ops)
Print out the expression identified in the Ops list.
static Value * EmitAddTreeOfValues(BasicBlock::iterator It, SmallVectorImpl< WeakTrackingVH > &Ops)
Emit a tree of add instructions, summing Ops together and returning the result.
static bool ShouldBreakUpSubtract(Instruction *Sub)
Return true if we should break up this subtract of X-Y into (X + -Y).
static Value * buildMultiplyTree(IRBuilderBase &Builder, SmallVectorImpl< Value * > &Ops)
Build a tree of multiplies, computing the product of Ops.
static void getNegatibleInsts(Value *V, SmallVectorImpl< Instruction * > &Candidates)
Recursively analyze an expression to build a list of instructions that have negative floating-point c...
static BinaryOperator * CreateMul(Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static BinaryOperator * BreakUpSubtract(Instruction *Sub, ReassociatePass::OrderedSet &ToRedo)
If we have (X-Y), and if either X is an add, or if this is only used by an add, transform this into (...
static void FindSingleUseMultiplyFactors(Value *V, SmallVectorImpl< Value * > &Factors)
If V is a single-use multiply, recursively add its operands as factors, otherwise add V to the list o...
std::pair< Value *, uint64_t > RepeatedValue
static Value * OptimizeAndOrXor(unsigned Opcode, SmallVectorImpl< ValueEntry > &Ops)
Optimize a series of operands to an 'and', 'or', or 'xor' instruction.
static BinaryOperator * convertOrWithNoCommonBitsToAdd(Instruction *Or)
If we have (X|Y), and iff X and Y have no common bits set, transform this into (X+Y) to allow arithme...
static BinaryOperator * CreateAdd(Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static bool LinearizeExprTree(Instruction *I, SmallVectorImpl< RepeatedValue > &Ops, ReassociatePass::OrderedSet &ToRedo, reassociate::OverflowTracking &Flags)
Given an associative binary expression, return the leaf nodes in Ops along with their weights (how ma...
static bool collectMultiplyFactors(SmallVectorImpl< ValueEntry > &Ops, SmallVectorImpl< Factor > &Factors)
Build up a vector of value/power pairs factoring a product.
static BinaryOperator * ConvertShiftToMul(Instruction *Shl)
If this is a shift of a reassociable multiply or is used by one, change this into a multiply by a con...
static cl::opt< bool > UseCSELocalOpt(DEBUG_TYPE "-use-cse-local", cl::desc("Only reorder expressions within a basic block " "when exposing CSE opportunities"), cl::init(true), cl::Hidden)
static unsigned FindInOperandList(const SmallVectorImpl< ValueEntry > &Ops, unsigned i, Value *X)
Scan backwards and forwards among values with the same rank as element i to see if X exists.
static BinaryOperator * LowerNegateToMultiply(Instruction *Neg)
Replace 0-X with X*-1.
static Instruction * CreateNeg(Value *S1, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static bool hasFPAssociativeFlags(Instruction *I)
Return true if I is an instruction with the FastMathFlags that are needed for general reassociation s...
static Value * createAndInstr(BasicBlock::iterator InsertBefore, Value *Opnd, const APInt &ConstOpnd)
Helper function of CombineXorOpnd().
static Value * NegateValue(Value *V, Instruction *BI, ReassociatePass::OrderedSet &ToRedo)
Insert instructions before the instruction pointed to by BI, that computes the negative version of th...
static bool shouldConvertOrWithNoCommonBitsToAdd(Instruction *Or)
Return true if it may be profitable to convert this (X|Y) into (X+Y).
static bool isLoadCombineCandidate(Instruction *Or)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getFastMathFlags(const MachineInstr &I)
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
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.
bool getBoolValue() const
Convert APInt to a boolean value.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Legacy wrapper pass to provide the BasicAAResult object.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction * getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
InstListType::iterator iterator
Instruction iterators...
static BinaryOperator * CreateNeg(Value *Op, const Twine &Name="", InsertPosition InsertBefore=nullptr)
Helper functions to construct and inspect unary operations (NEG and NOT) via binary operators SUB and...
BinaryOps getOpcode() const
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), InsertPosition InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
Represents analyses that only rely on functions' control flow.
static Constant * getBinOpAbsorber(unsigned Opcode, Type *Ty)
Return the absorbing element for the given binary operation, i.e.
static Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
static Constant * getNeg(Constant *C, bool HasNSW=false)
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Convenience struct for specifying and reasoning about fast-math flags.
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
Legacy wrapper pass to provide the GlobalsAAResult object.
Common base class shared among various IRBuilders.
Value * CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name="")
Copy fast-math-flags from an instruction rather than using the builder's default FMF.
Value * CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource, const Twine &Name="")
Copy fast-math-flags from an instruction rather than using the builder's default FMF.
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
void dropLocation()
Drop the instruction's debug location.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
void setFastMathFlags(FastMathFlags FMF)
Convenience function for setting multiple fast-math flags on this instruction, which must be an opera...
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
const Function * getFunction() const
Return the function this instruction belongs to.
const char * getOpcodeName() const
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
Reassociate commutative expressions.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
static UnaryOperator * CreateFNegFMF(Value *Op, Instruction *FMFSource, const Twine &Name="", InsertPosition InsertBefore=nullptr)
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
void clearSubclassOptionalData()
Clear the optional flags contained in this value.
void deleteValue()
Delete a pointer to a generic Value.
void takeName(Value *V)
Transfer the name from V to this value.
const ParentTy * getParent() const
self_iterator getIterator()
Utility class representing a non-constant Xor-operand.
Value * getSymbolicPart() const
unsigned getSymbolicRank() const
void setSymbolicRank(unsigned R)
const APInt & getConstPart() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)
class_match< Constant > m_Constant()
Match an arbitrary Constant and ignore it.
bool match(Val *V, const Pattern &P)
bind_ty< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
BinaryOp_match< LHS, RHS, Instruction::FAdd > m_FAdd(const LHS &L, const RHS &R)
OneUse_match< T > m_OneUse(const T &SubPattern)
BinaryOp_match< cst_pred_ty< is_zero_int >, ValTy, Instruction::Sub > m_Neg(const ValTy &V)
Matches a 'Neg' as 'sub 0, V'.
apint_match m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
apfloat_match m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
BinaryOp_match< cst_pred_ty< is_all_ones >, ValTy, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
initializer< Ty > init(const Ty &Val)
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
bool haveNoCommonBitsSet(const WithCache< const Value * > &LHSCache, const WithCache< const Value * > &RHSCache, const SimplifyQuery &SQ)
Return true if LHS and RHS have no common bits set.
void stable_sort(R &&Range)
void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
auto unique(Range &&R, Predicate P)
FunctionPass * createReassociatePass()
void initializeReassociateLegacyPassPass(PassRegistry &)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
Constant * ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, const DataLayout &DL)
Attempt to constant fold a unary operation with the specified operand.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Constant * ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL)
Attempt to constant fold a binary operation with the specified operands.
bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
bool replaceDbgUsesWithUndef(Instruction *I)
Replace all the uses of an SSA value in @llvm.dbg intrinsics with undef.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
bool mayHaveNonDefUseDependency(const Instruction &I)
Returns true if the result or effects of the given instructions I depend values not reachable through...
Constant * ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1, Constant *V2)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Utility class representing a base and exponent pair which form one factor of some product.