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) {
892 auto Enqueue = [&](
Value *V) {
893 auto *
I = dyn_cast<Instruction>(V);
906 while (!Worklist.
empty()) {
910 switch (
I->getOpcode()) {
911 case Instruction::Or:
918 case Instruction::Shl:
919 case Instruction::ZExt:
921 if (!Enqueue(
I->getOperand(0)))
925 case Instruction::Load:
943 for (
auto Op : {Instruction::Add, Instruction::Sub, Instruction::Mul,
965 Or->getIterator(),
Or);
966 New->setHasNoSignedWrap();
967 New->setHasNoUnsignedWrap();
971 Or->replaceAllUsesWith(New);
972 New->setDebugLoc(
Or->getDebugLoc());
974 LLVM_DEBUG(
dbgs() <<
"Converted or into an add: " << *New <<
'\n');
1035 auto *SA = cast<ConstantInt>(Shl->
getOperand(1));
1037 assert(MulCst &&
"Constant folding of immediate constants failed");
1052 bool NSW = cast<BinaryOperator>(Shl)->hasNoSignedWrap();
1053 bool NUW = cast<BinaryOperator>(Shl)->hasNoUnsignedWrap();
1055 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1056 Mul->setHasNoSignedWrap(
true);
1057 Mul->setHasNoUnsignedWrap(NUW);
1066 unsigned XRank = Ops[i].Rank;
1067 unsigned e = Ops.
size();
1068 for (
unsigned j = i+1; j != e && Ops[j].Rank == XRank; ++j) {
1073 if (I1->isIdenticalTo(I2))
1077 for (
unsigned j = i-1; j != ~0U && Ops[j].Rank == XRank; --j) {
1082 if (I1->isIdenticalTo(I2))
1092 if (Ops.
size() == 1)
return Ops.
back();
1096 return CreateAdd(V2, V1,
"reass.add", It, &*It);
1112 for (
unsigned i = 0, e = Tree.
size(); i != e; ++i) {
1117 bool FoundFactor =
false;
1118 bool NeedsNegate =
false;
1119 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1128 if (
ConstantInt *FC2 = dyn_cast<ConstantInt>(Factors[i].
Op))
1129 if (FC1->getValue() == -FC2->getValue()) {
1130 FoundFactor = NeedsNegate =
true;
1135 if (
ConstantFP *FC2 = dyn_cast<ConstantFP>(Factors[i].
Op)) {
1136 const APFloat &F1 = FC1->getValueAPF();
1137 APFloat F2(FC2->getValueAPF());
1140 FoundFactor = NeedsNegate =
true;
1150 RewriteExprTree(BO, Factors, Flags);
1158 if (Factors.
size() == 1) {
1159 RedoInsts.insert(BO);
1162 RewriteExprTree(BO, Factors, Flags);
1196 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1203 if (Opcode == Instruction::And)
1206 if (Opcode == Instruction::Or)
1214 if (i+1 != Ops.
size() && Ops[i+1].Op == Ops[i].Op) {
1215 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1224 assert(Opcode == Instruction::Xor);
1243 const APInt &ConstOpnd) {
1251 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1253 I->setDebugLoc(InsertBefore->getDebugLoc());
1276 if (C1 != ConstOpnd)
1285 RedoInsts.insert(
T);
1305 int DeadInstNum = 1;
1323 APInt C3((~C1) ^ C2);
1326 if (!C3.isZero() && !C3.isAllOnes()) {
1328 if (NewInstNum > DeadInstNum)
1344 if (NewInstNum > DeadInstNum)
1362 RedoInsts.insert(
T);
1364 RedoInsts.insert(
T);
1377 if (Ops.
size() == 1)
1382 Type *Ty = Ops[0].Op->getType();
1386 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1394 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1421 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1426 bool Changed =
false;
1427 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1428 XorOpnd *CurrOpnd = OpndPtrs[i];
1433 if (!ConstOpnd.
isZero() &&
1434 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1444 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1445 PrevOpnd = CurrOpnd;
1451 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1456 PrevOpnd = CurrOpnd;
1468 for (
const XorOpnd &O : Opnds) {
1474 if (!ConstOpnd.
isZero()) {
1475 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1479 unsigned Sz = Ops.
size();
1481 return Ops.
back().Op;
1484 return ConstantInt::get(Ty, ConstOpnd);
1501 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1502 Value *TheOp = Ops[i].Op;
1506 if (i+1 != Ops.
size() && Ops[i+1].Op == TheOp) {
1508 unsigned NumFound = 0;
1512 }
while (i != Ops.
size() && Ops[i].Op == TheOp);
1514 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1521 ConstantInt::get(Ty, NumFound) :
ConstantFP::
get(Ty, NumFound);
1527 RedoInsts.insert(
Mul);
1554 if (Ops.
size() == 2 &&
1589 unsigned MaxOcc = 0;
1590 Value *MaxOccVal =
nullptr;
1591 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1600 assert(Factors.
size() > 1 &&
"Bad linearize!");
1608 unsigned Occ = ++FactorOccurrences[
Factor];
1618 if (CI->isNegative() && !CI->isMinValue(
true)) {
1619 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1622 unsigned Occ = ++FactorOccurrences[
Factor];
1629 if (CF->isNegative()) {
1632 Factor = ConstantFP::get(CF->getContext(),
F);
1635 unsigned Occ = ++FactorOccurrences[
Factor];
1647 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1656 I->getType()->isIntOrIntVectorTy()
1657 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1661 for (
unsigned i = 0; i != Ops.
size(); ++i) {
1668 if (
Value *V = RemoveFactorFromExpression(Ops[i].
Op, MaxOccVal)) {
1671 for (
unsigned j = Ops.
size(); j != i;) {
1673 if (Ops[j].
Op == Ops[i].
Op) {
1685 unsigned NumAddedValues = NewMulOps.
size();
1691 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1692 (void)NumAddedValues;
1694 RedoInsts.insert(VI);
1701 RedoInsts.insert(V2);
1732 unsigned FactorPowerSum = 0;
1742 FactorPowerSum += Count;
1749 if (FactorPowerSum < 4)
1766 FactorPowerSum += Count;
1773 assert(FactorPowerSum >= 4);
1776 return LHS.Power >
RHS.Power;
1784 if (Ops.
size() == 1)
1793 }
while (!Ops.
empty());
1805ReassociatePass::buildMinimalMultiplyDAG(
IRBuilderBase &Builder,
1807 assert(Factors[0].Power);
1809 for (
unsigned LastIdx = 0,
Idx = 1,
Size = Factors.
size();
1811 if (Factors[
Idx].Power != Factors[LastIdx].Power) {
1824 }
while (
Idx <
Size && Factors[
Idx].Power == Factors[LastIdx].Power);
1830 RedoInsts.insert(
MI);
1838 return LHS.Power ==
RHS.Power;
1850 if (Factors[0].Power) {
1851 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1855 if (OuterProduct.
size() == 1)
1856 return OuterProduct.
front();
1880 if (
auto FPI = dyn_cast<FPMathOperator>(
I))
1883 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1898 unsigned Opcode =
I->getOpcode();
1899 while (!Ops.
empty()) {
1900 if (
auto *
C = dyn_cast<Constant>(Ops.
back().Op)) {
1927 if (Ops.
size() == 1)
return Ops[0].Op;
1931 unsigned NumOps = Ops.
size();
1934 case Instruction::And:
1935 case Instruction::Or:
1940 case Instruction::Xor:
1941 if (
Value *Result = OptimizeXor(
I, Ops))
1945 case Instruction::Add:
1946 case Instruction::FAdd:
1947 if (
Value *Result = OptimizeAdd(
I, Ops))
1951 case Instruction::Mul:
1952 case Instruction::FMul:
1953 if (
Value *Result = OptimizeMul(
I, Ops))
1958 if (Ops.
size() != NumOps)
1959 return OptimizeExpression(
I, Ops);
1965void ReassociatePass::RecursivelyEraseDeadInsts(
Instruction *
I,
1966 OrderedSet &Insts) {
1969 ValueRankMap.erase(
I);
1971 RedoInsts.remove(
I);
1973 I->eraseFromParent();
1974 for (
auto *
Op : Ops)
1976 if (OpInst->use_empty())
1977 Insts.insert(OpInst);
1987 ValueRankMap.erase(
I);
1988 RedoInsts.remove(
I);
1990 I->eraseFromParent();
1993 for (
Value *V : Ops)
1997 unsigned Opcode =
Op->getOpcode();
1998 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
2000 Op =
Op->user_back();
2007 if (ValueRankMap.contains(
Op))
2008 RedoInsts.insert(
Op);
2028 switch (
I->getOpcode()) {
2029 case Instruction::FMul:
2041 case Instruction::FDiv:
2066 assert((
I->getOpcode() == Instruction::FAdd ||
2067 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2073 if (Candidates.
empty())
2079 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2080 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2088 "Expecting only 1 constant operand");
2089 assert(
C->isNegative() &&
"Expected negative FP constant");
2090 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2095 "Expecting only 1 constant operand");
2096 assert(
C->isNegative() &&
"Expected negative FP constant");
2097 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2101 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2104 if (Candidates.size() % 2 == 0)
2109 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2113 I->replaceAllUsesWith(NewInst);
2114 RedoInsts.insert(
I);
2115 return dyn_cast<Instruction>(NewInst);
2146 if (!isa<UnaryOperator>(
I) && !isa<BinaryOperator>(
I))
2149 if (
I->getOpcode() == Instruction::Shl && isa<ConstantInt>(
I->getOperand(1)))
2157 RedoInsts.insert(
I);
2165 if (
I->isCommutative())
2166 canonicalizeOperands(
I);
2183 if (
I->getType()->isIntegerTy(1))
2188 if (
I->getOpcode() == Instruction::Or &&
2190 (cast<PossiblyDisjointInst>(
I)->isDisjoint() ||
2193 nullptr,
nullptr,
I)))) {
2195 RedoInsts.insert(
I);
2202 if (
I->getOpcode() == Instruction::Sub) {
2205 RedoInsts.insert(
I);
2219 RedoInsts.insert(Tmp);
2221 RedoInsts.insert(
I);
2226 }
else if (
I->getOpcode() == Instruction::FNeg ||
2227 I->getOpcode() == Instruction::FSub) {
2230 RedoInsts.insert(
I);
2236 Value *
Op = isa<BinaryOperator>(
I) ?
I->getOperand(1) :
2246 RedoInsts.insert(Tmp);
2248 RedoInsts.insert(
I);
2256 if (!
I->isAssociative())
return;
2275 cast<Instruction>(BO->
user_back())->getOpcode() == Instruction::Sub)
2278 cast<Instruction>(BO->
user_back())->getOpcode() == Instruction::FSub)
2281 ReassociateExpression(BO);
2307 if (
Value *V = OptimizeExpression(
I, Ops)) {
2314 I->replaceAllUsesWith(V);
2316 if (
I->getDebugLoc())
2317 VI->setDebugLoc(
I->getDebugLoc());
2318 RedoInsts.insert(
I);
2327 if (
I->hasOneUse()) {
2328 if (
I->getOpcode() == Instruction::Mul &&
2329 cast<Instruction>(
I->user_back())->getOpcode() == Instruction::Add &&
2330 isa<ConstantInt>(Ops.
back().Op) &&
2331 cast<ConstantInt>(Ops.
back().Op)->isMinusOne()) {
2334 }
else if (
I->getOpcode() == Instruction::FMul &&
2335 cast<Instruction>(
I->user_back())->getOpcode() ==
2336 Instruction::FAdd &&
2337 isa<ConstantFP>(Ops.
back().Op) &&
2338 cast<ConstantFP>(Ops.
back().Op)->isExactlyValue(-1.0)) {
2346 if (Ops.
size() == 1) {
2353 I->replaceAllUsesWith(Ops[0].
Op);
2355 OI->setDebugLoc(
I->getDebugLoc());
2356 RedoInsts.insert(
I);
2360 if (Ops.
size() > 2 && Ops.
size() <= GlobalReassociateLimit) {
2368 unsigned BestRank = 0;
2369 std::pair<unsigned, unsigned> BestPair;
2370 unsigned Idx =
I->getOpcode() - Instruction::BinaryOpsBegin;
2371 unsigned LimitIdx = 0;
2381 int StartIdx = Ops.
size() - 1;
2386 for (
int i = StartIdx - 1; i != -1; --i) {
2387 const Value *Val = Ops[i].Op;
2388 const auto *CurrLeafInstr = dyn_cast<Instruction>(Val);
2390 if (!CurrLeafInstr) {
2409 SeenBB = &
I->getParent()->getParent()->getEntryBlock();
2415 FirstSeenBB = SeenBB;
2418 if (FirstSeenBB != SeenBB) {
2424 << LimitIdx <<
", " << StartIdx <<
"]\n");
2429 for (
unsigned i = Ops.
size() - 1; i > LimitIdx; --i) {
2431 for (
int j = i - 1;
j >= (int)LimitIdx; --
j) {
2433 Value *Op0 = Ops[i].Op;
2435 if (std::less<Value *>()(Op1, Op0))
2437 auto it = PairMap[
Idx].find({Op0, Op1});
2438 if (it != PairMap[
Idx].
end()) {
2444 if (it->second.isValid())
2445 Score += it->second.Score;
2448 unsigned MaxRank = std::max(Ops[i].Rank, Ops[j].Rank);
2462 if (Score > Max || (Score == Max && MaxRank < BestRank)) {
2470 auto Op0 = Ops[BestPair.first];
2471 auto Op1 = Ops[BestPair.second];
2472 Ops.
erase(&Ops[BestPair.second]);
2473 Ops.
erase(&Ops[BestPair.first]);
2482 RewriteExprTree(
I, Ops, Flags);
2490 if (!
I.isAssociative() || !
I.isBinaryOp())
2494 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2502 while (!Worklist.
empty() && Ops.
size() <= GlobalReassociateLimit) {
2516 if (Ops.
size() > GlobalReassociateLimit)
2520 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2522 for (
unsigned i = 0; i < Ops.
size() - 1; ++i) {
2523 for (
unsigned j = i + 1;
j < Ops.
size(); ++
j) {
2525 Value *Op0 = Ops[i];
2527 if (std::less<Value *>()(Op1, Op0))
2529 if (!Visited.
insert({Op0, Op1}).second)
2531 auto res = PairMap[BinaryIdx].insert({{Op0, Op1}, {Op0, Op1, 1}});
2537 assert(res.first->second.isValid() &&
"WeakVH invalidated");
2538 ++res.first->second.Score;
2554 BuildRankMap(
F, RPOT);
2571 assert(RankMap.count(&*BI) &&
"BB should be ranked.");
2578 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2589 while (!ToRedo.
empty()) {
2592 RecursivelyEraseDeadInsts(
I, ToRedo);
2599 while (!RedoInsts.empty()) {
2601 RedoInsts.erase(RedoInsts.begin());
2611 ValueRankMap.clear();
2612 for (
auto &Entry : PairMap)
2637 if (skipFunction(
F))
2641 auto PA = Impl.
run(
F, DummyFAM);
2655char ReassociateLegacyPass::ID = 0;
2658 "Reassociate expressions",
false,
false)
2662 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...
This header defines various interfaces for pass management in LLVM.
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
#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, bool AllowLHSConstant=false)
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
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.