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';
88 Op.Op->printAsOperand(
dbgs(),
false, M);
89 dbgs() <<
", #" <<
Op.Rank <<
"] ";
106 bool isInvalid()
const {
return SymbolicPart ==
nullptr; }
120 unsigned SymbolicRank;
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);
158 return I->hasAllowReassoc() &&
I->hasNoSignedZeros();
165 if (BO && BO->hasOneUse() && BO->getOpcode() == Opcode)
174 if (BO && BO->hasOneUse() &&
175 (BO->getOpcode() == Opcode1 || BO->getOpcode() == Opcode2))
181void ReassociatePass::BuildRankMap(Function &
F,
182 ReversePostOrderTraversal<Function*> &RPOT) {
186 for (
auto &Arg :
F.args()) {
187 ValueRankMap[&Arg] = ++Rank;
188 LLVM_DEBUG(
dbgs() <<
"Calculated Rank[" << Arg.getName() <<
"] = " << Rank
193 for (BasicBlock *BB : RPOT) {
194 unsigned BBRank = RankMap[BB] = ++Rank << 16;
199 for (Instruction &
I : *BB)
201 ValueRankMap[&
I] = ++BBRank;
205unsigned ReassociatePass::getRank(
Value *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) {
238 assert(
I->isCommutative() &&
"Expected commutative operator.");
253 if (
S1->getType()->isIntOrIntVectorTy())
254 return BinaryOperator::CreateAdd(
S1, S2, Name, InsertBefore);
257 BinaryOperator::CreateFAdd(
S1, S2, Name, InsertBefore);
266 if (
S1->getType()->isIntOrIntVectorTy())
267 return BinaryOperator::CreateMul(
S1, S2, Name, InsertBefore);
270 BinaryOperator::CreateFMul(
S1, S2, Name, InsertBefore);
279 if (
S1->getType()->isIntOrIntVectorTy())
285 return UnaryOperator::CreateFNeg(
S1, Name, InsertBefore);
291 "Expected a Negate!");
295 Constant *NegOne = Ty->isIntOrIntVectorTy() ?
387 "Expected a UnaryOperator or BinaryOperator!");
389 unsigned Opcode =
I->getOpcode();
390 assert(
I->isAssociative() &&
I->isCommutative() &&
391 "Expected an associative and commutative operation!");
430 while (!Worklist.
empty()) {
434 Flags.mergeFlags(*
I);
439 assert((!
Op->hasUseList() || !
Op->use_empty()) &&
440 "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())
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!");
560 Ops.emplace_back(Identity, 1);
568void ReassociatePass::RewriteExprTree(BinaryOperator *
I,
569 SmallVectorImpl<ValueEntry> &
Ops,
570 OverflowTracking Flags) {
571 assert(
Ops.size() > 1 &&
"Single values should be used directly!");
585 unsigned Opcode =
I->getOpcode();
586 BinaryOperator *
Op =
I;
598 SmallPtrSet<Value*, 8> NotRewritable;
606 BinaryOperator *ExpressionChangedStart =
nullptr,
607 *ExpressionChangedEnd =
nullptr;
608 for (
unsigned i = 0; ; ++i) {
612 if (i+2 ==
Ops.size()) {
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;
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)) {
698 BinaryOperator *NewOp;
699 if (NodesToRewrite.
empty()) {
710 Op->setOperand(0, NewOp);
712 ExpressionChangedStart =
Op;
713 if (!ExpressionChangedEnd)
714 ExpressionChangedEnd =
Op;
724 if (ExpressionChangedStart) {
725 bool ClearFlags =
true;
730 FastMathFlags
Flags =
I->getFastMathFlags();
734 Flags.applyFlags(*ExpressionChangedStart);
738 if (ExpressionChangedStart == ExpressionChangedEnd)
740 if (ExpressionChangedStart ==
I)
750 ExpressionChangedStart->
moveBefore(
I->getIterator());
751 ExpressionChangedStart =
757 RedoInsts.insert_range(NodesToRewrite);
771 Constant *Res =
C->getType()->isFPOrFPVectorTy()
792 if (
I->getOpcode() == Instruction::Add) {
793 I->setHasNoUnsignedWrap(
false);
794 I->setHasNoSignedWrap(
false);
803 I->setName(
I->getName()+
".neg");
826 C->containsUndefOrPoisonElement())
836 auto InsertPtOpt = InstInput->getInsertionPointAfterDef();
839 InsertPt = *InsertPtOpt;
850 if (TheNeg->
getParent() != InsertPt->getParent())
852 TheNeg->
moveBefore(*InsertPt->getParent(), InsertPt);
854 if (TheNeg->
getOpcode() == Instruction::Sub) {
883 auto Enqueue = [&](
Value *V) {
897 while (!Worklist.
empty()) {
901 switch (
I->getOpcode()) {
902 case Instruction::Or:
909 case Instruction::Shl:
910 case Instruction::ZExt:
912 if (!Enqueue(
I->getOperand(0)))
916 case Instruction::Load:
934 for (
auto Op : {Instruction::Add, Instruction::Sub, Instruction::Mul,
956 Or->getIterator(),
Or);
957 New->setHasNoSignedWrap();
958 New->setHasNoUnsignedWrap();
962 Or->replaceAllUsesWith(New);
963 New->setDebugLoc(
Or->getDebugLoc());
965 LLVM_DEBUG(
dbgs() <<
"Converted or into an add: " << *New <<
'\n');
990 if (
Sub->hasOneUse() &&
1015 Sub->replaceAllUsesWith(New);
1016 New->setDebugLoc(
Sub->getDebugLoc());
1028 assert(MulCst &&
"Constant folding of immediate constants failed");
1046 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1047 Mul->setHasNoSignedWrap(
true);
1048 Mul->setHasNoUnsignedWrap(NUW);
1057 unsigned XRank =
Ops[i].Rank;
1058 unsigned e =
Ops.size();
1059 for (
unsigned j = i+1; j != e &&
Ops[j].Rank == XRank; ++j) {
1064 if (I1->isIdenticalTo(I2))
1068 for (
unsigned j = i-1; j != ~0U &&
Ops[j].Rank == XRank; --j) {
1073 if (I1->isIdenticalTo(I2))
1083 if (
Ops.size() == 1)
return Ops.back();
1087 auto *NewAdd =
CreateAdd(V2, V1,
"reass.add",
I->getIterator(),
I);
1088 NewAdd->setDebugLoc(
I->getDebugLoc());
1099 BinaryOperator *BO =
isReassociableOp(V, Instruction::Mul, Instruction::FMul);
1104 OverflowTracking
Flags;
1111 bool FoundFactor =
false;
1112 bool NeedsNegate =
false;
1113 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1123 if (FC1->getValue() == -FC2->getValue()) {
1124 FoundFactor = NeedsNegate =
true;
1130 const APFloat &F1 = FC1->getValueAPF();
1131 APFloat F2(FC2->getValueAPF());
1134 FoundFactor = NeedsNegate =
true;
1144 RewriteExprTree(BO, Factors, Flags);
1152 if (Factors.
size() == 1) {
1153 RedoInsts.insert(BO);
1156 RewriteExprTree(BO, Factors, Flags);
1192 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1199 if (Opcode == Instruction::And)
1202 if (Opcode == Instruction::Or)
1210 if (i+1 !=
Ops.size() &&
Ops[i+1].Op ==
Ops[i].Op) {
1211 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1213 Ops.erase(
Ops.begin()+i);
1220 assert(Opcode == Instruction::Xor);
1225 Ops.erase(
Ops.begin()+i,
Ops.begin()+i+2);
1239 const APInt &ConstOpnd) {
1247 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1249 I->setDebugLoc(InsertBefore->getDebugLoc());
1260 APInt &ConstOpnd,
Value *&Res) {
1272 if (C1 != ConstOpnd)
1281 RedoInsts.insert(
T);
1294 XorOpnd *Opnd2, APInt &ConstOpnd,
1301 int DeadInstNum = 1;
1319 APInt C3((~C1) ^ C2);
1322 if (!C3.isZero() && !C3.isAllOnes()) {
1324 if (NewInstNum > DeadInstNum)
1340 if (NewInstNum > DeadInstNum)
1358 RedoInsts.insert(
T);
1360 RedoInsts.insert(
T);
1368Value *ReassociatePass::OptimizeXor(Instruction *
I,
1369 SmallVectorImpl<ValueEntry> &
Ops) {
1373 if (
Ops.size() == 1)
1378 Type *Ty =
Ops[0].Op->getType();
1390 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1417 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1423 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1424 XorOpnd *CurrOpnd = OpndPtrs[i];
1429 if (!ConstOpnd.
isZero() &&
1430 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1440 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1441 PrevOpnd = CurrOpnd;
1447 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1449 PrevOpnd->Invalidate();
1452 PrevOpnd = CurrOpnd;
1464 for (
const XorOpnd &O : Opnds) {
1470 if (!ConstOpnd.
isZero()) {
1471 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1475 unsigned Sz =
Ops.size();
1477 return Ops.back().Op;
1480 return ConstantInt::get(Ty, ConstOpnd);
1490Value *ReassociatePass::OptimizeAdd(Instruction *
I,
1491 SmallVectorImpl<ValueEntry> &
Ops) {
1497 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1502 if (i+1 !=
Ops.size() &&
Ops[i+1].Op == TheOp) {
1504 unsigned NumFound = 0;
1506 Ops.erase(
Ops.begin()+i);
1508 }
while (i !=
Ops.size() &&
Ops[i].Op == TheOp);
1510 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1517 ConstantInt::get(Ty, NumFound) :
ConstantFP::
get(Ty, NumFound);
1519 Mul->setDebugLoc(
I->getDebugLoc());
1524 RedoInsts.insert(
Mul);
1551 if (
Ops.size() == 2 &&
1559 Ops.erase(
Ops.begin()+i);
1564 Ops.erase(
Ops.begin()+FoundX);
1582 DenseMap<Value*, unsigned> FactorOccurrences;
1586 unsigned MaxOcc = 0;
1587 Value *MaxOccVal =
nullptr;
1589 BinaryOperator *BOp =
1595 SmallVector<Value*, 8> Factors;
1597 assert(Factors.
size() > 1 &&
"Bad linearize!");
1600 SmallPtrSet<Value*, 8> Duplicates;
1605 unsigned Occ = ++FactorOccurrences[
Factor];
1615 if (CI->isNegative() && !CI->isMinValue(
true)) {
1616 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1619 unsigned Occ = ++FactorOccurrences[
Factor];
1626 if (CF->isNegative()) {
1629 Factor = ConstantFP::get(CF->getContext(),
F);
1632 unsigned Occ = ++FactorOccurrences[
Factor];
1644 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1653 I->getType()->isIntOrIntVectorTy()
1654 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1655 : BinaryOperator::CreateFAdd(MaxOccVal, MaxOccVal);
1658 for (
unsigned i = 0; i !=
Ops.size(); ++i) {
1660 BinaryOperator *BOp =
1665 if (
Value *V = RemoveFactorFromExpression(
Ops[i].
Op, MaxOccVal,
1666 I->getDebugLoc())) {
1669 for (
unsigned j =
Ops.size(); j != i;) {
1673 Ops.erase(
Ops.begin()+j);
1683 unsigned NumAddedValues = NewMulOps.
size();
1689 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1690 (void)NumAddedValues;
1692 RedoInsts.insert(VI);
1700 RedoInsts.insert(V2);
1731 unsigned FactorPowerSum = 0;
1732 for (
unsigned Idx = 1,
Size =
Ops.size(); Idx <
Size; ++Idx) {
1737 for (; Idx <
Size &&
Ops[Idx].Op ==
Op; ++Idx)
1741 FactorPowerSum +=
Count;
1748 if (FactorPowerSum < 4)
1753 for (
unsigned Idx = 1; Idx <
Ops.size(); ++Idx) {
1758 for (; Idx <
Ops.size() &&
Ops[Idx].
Op ==
Op; ++Idx)
1765 FactorPowerSum +=
Count;
1772 assert(FactorPowerSum >= 4);
1775 return LHS.Power >
RHS.Power;
1783 if (
Ops.size() == 1)
1788 if (
LHS->getType()->isIntOrIntVectorTy())
1789 LHS = Builder.CreateMul(
LHS,
Ops.pop_back_val());
1791 LHS = Builder.CreateFMul(
LHS,
Ops.pop_back_val());
1792 }
while (!
Ops.empty());
1804ReassociatePass::buildMinimalMultiplyDAG(IRBuilderBase &Builder,
1805 SmallVectorImpl<Factor> &Factors) {
1806 assert(Factors[0].Power);
1808 for (
unsigned LastIdx = 0, Idx = 1,
Size = Factors.
size();
1809 Idx <
Size && Factors[Idx].Power > 0; ++Idx) {
1810 if (Factors[Idx].Power != Factors[LastIdx].Power) {
1823 }
while (Idx <
Size && Factors[Idx].Power == Factors[LastIdx].Power);
1829 RedoInsts.insert(
MI);
1837 return LHS.Power ==
RHS.Power;
1849 if (Factors[0].Power) {
1850 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1854 if (OuterProduct.
size() == 1)
1855 return OuterProduct.
front();
1861Value *ReassociatePass::OptimizeMul(BinaryOperator *
I,
1862 SmallVectorImpl<ValueEntry> &
Ops) {
1882 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1891Value *ReassociatePass::OptimizeExpression(BinaryOperator *
I,
1892 SmallVectorImpl<ValueEntry> &
Ops) {
1895 const DataLayout &
DL =
I->getDataLayout();
1897 unsigned Opcode =
I->getOpcode();
1898 while (!
Ops.empty()) {
1926 if (
Ops.size() == 1)
return Ops[0].
Op;
1933 case Instruction::And:
1934 case Instruction::Or:
1939 case Instruction::Xor:
1940 if (
Value *Result = OptimizeXor(
I,
Ops))
1944 case Instruction::Add:
1945 case Instruction::FAdd:
1946 if (
Value *Result = OptimizeAdd(
I,
Ops))
1950 case Instruction::Mul:
1951 case Instruction::FMul:
1952 if (
Value *Result = OptimizeMul(
I,
Ops))
1958 return OptimizeExpression(
I,
Ops);
1964void ReassociatePass::RecursivelyEraseDeadInsts(Instruction *
I,
1965 OrderedSet &Insts) {
1968 ValueRankMap.erase(
I);
1970 RedoInsts.remove(
I);
1972 I->eraseFromParent();
1973 for (
auto *
Op :
Ops)
1975 if (OpInst->use_empty())
1976 Insts.insert(OpInst);
1980void ReassociatePass::EraseInst(Instruction *
I) {
1984 SmallVector<Value *, 8>
Ops(
I->operands());
1986 ValueRankMap.erase(
I);
1987 RedoInsts.remove(
I);
1989 I->eraseFromParent();
1991 SmallPtrSet<Instruction *, 8> Visited;
1996 unsigned Opcode =
Op->getOpcode();
1997 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
1999 Op =
Op->user_back();
2006 if (ValueRankMap.contains(
Op))
2007 RedoInsts.insert(
Op);
2027 switch (
I->getOpcode()) {
2028 case Instruction::FMul:
2040 case Instruction::FDiv:
2062Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *
I,
2065 assert((
I->getOpcode() == Instruction::FAdd ||
2066 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2070 SmallVector<Instruction *, 4> Candidates;
2072 if (Candidates.
empty())
2078 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2079 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2083 for (Instruction *Negatible : Candidates) {
2087 "Expecting only 1 constant operand");
2088 assert(
C->isNegative() &&
"Expected negative FP constant");
2089 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2094 "Expecting only 1 constant operand");
2095 assert(
C->isNegative() &&
"Expected negative FP constant");
2096 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2100 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2103 if (Candidates.size() % 2 == 0)
2108 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2113 RedoInsts.insert(
I);
2125Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *
I) {
2130 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2133 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2136 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2143void ReassociatePass::OptimizeInst(Instruction *
I) {
2156 RedoInsts.insert(
I);
2164 if (
I->isCommutative())
2165 canonicalizeOperands(
I);
2168 if (Instruction *Res = canonicalizeNegFPConstants(
I))
2183 if (
I->getType()->isIntOrIntVectorTy(1))
2188 if (
I->getOpcode() == Instruction::Or &&
2192 SimplifyQuery(
I->getDataLayout(),
2193 nullptr,
nullptr,
I)))) {
2195 RedoInsts.insert(
I);
2202 if (
I->getOpcode() == Instruction::Sub) {
2205 RedoInsts.insert(
I);
2217 for (User *U : NI->
users()) {
2219 RedoInsts.insert(Tmp);
2221 RedoInsts.insert(
I);
2226 }
else if (
I->getOpcode() == Instruction::FNeg ||
2227 I->getOpcode() == Instruction::FSub) {
2230 RedoInsts.insert(
I);
2244 for (User *U : NI->
users()) {
2246 RedoInsts.insert(Tmp);
2248 RedoInsts.insert(
I);
2256 if (!
I->isAssociative())
return;
2281 ReassociateExpression(BO);
2284void ReassociatePass::ReassociateExpression(BinaryOperator *
I) {
2288 OverflowTracking
Flags;
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 &&
2333 Ops.insert(
Ops.begin(), Tmp);
2334 }
else if (
I->getOpcode() == Instruction::FMul &&
2336 Instruction::FAdd &&
2340 Ops.insert(
Ops.begin(), Tmp);
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) {
2390 if (!CurrLeafInstr) {
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) {
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);
2486ReassociatePass::BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT) {
2488 for (BasicBlock *BI : RPOT) {
2489 for (Instruction &
I : *BI) {
2490 if (!
I.isAssociative() || !
I.isBinaryOp())
2494 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2500 SmallVector<Value *, 8> Worklist = {
I.getOperand(0),
I.getOperand(1) };
2501 SmallVector<Value *, 8>
Ops;
2502 while (!Worklist.
empty() &&
Ops.size() <= GlobalReassociateLimit) {
2516 if (
Ops.size() > GlobalReassociateLimit)
2520 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2521 SmallSet<std::pair<Value *, Value*>, 32> Visited;
2522 for (
unsigned i = 0; i <
Ops.size() - 1; ++i) {
2523 for (
unsigned j = i + 1;
j <
Ops.size(); ++
j) {
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);
2578 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2589 while (!ToRedo.
empty()) {
2592 RecursivelyEraseDeadInsts(
I, ToRedo);
2637 if (skipFunction(
F))
2641 auto PA = Impl.run(
F, DummyFAM);
2642 return !PA.areAllPreserved();
2645 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2655char ReassociateLegacyPass::ID = 0;
2658 "Reassociate expressions",
false,
false)
2662 return new ReassociateLegacyPass();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
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,...
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isReassociableOp(Instruction *I, unsigned IntOpcode, unsigned FPOpcode)
MachineInstr unsigned OpIdx
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 bool LinearizeExprTree(Instruction *I, SmallVectorImpl< RepeatedValue > &Ops, ReassociatePass::OrderedSet &ToRedo, OverflowTracking &Flags)
Given an associative binary expression, return the leaf nodes in Ops along with their weights (how ma...
static void PrintOps(Instruction *I, const SmallVectorImpl< ValueEntry > &Ops)
Print out the expression identified in the Ops list.
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 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)
static Value * EmitAddTreeOfValues(Instruction *I, SmallVectorImpl< WeakTrackingVH > &Ops)
Emit a tree of add instructions, summing Ops together and returning the result.
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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
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.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator 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 LLVM_ABI 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 LLVM_ABI 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 LLVM_ABI Constant * getBinOpAbsorber(unsigned Opcode, Type *Ty, bool AllowLHSConstant=false)
Return the absorbing element for the given binary operation, i.e.
static LLVM_ABI Constant * getBinOpIdentity(unsigned Opcode, Type *Ty, bool AllowRHSConstant=false, bool NSZ=false)
Return the identity constant for a binary opcode.
static LLVM_ABI Constant * getNeg(Constant *C, bool HasNSW=false)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
This provides a helper for copying FMF from an instruction or setting specified flags.
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
Module * getParent()
Get the module that this global value is contained inside of...
Common base class shared among various IRBuilders.
Value * CreateFSubFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
void setFastMathFlags(FastMathFlags NewFMF)
Set the fast-math flags to be used with generated fp-math operators.
Value * CreateFAddFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)
LLVM_ABI void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void dropLocation()
Drop the instruction's debug location.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI 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...
LLVM_ABI 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.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI 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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Reassociate commutative expressions.
DenseMap< BasicBlock *, unsigned > RankMap
DenseMap< AssertingVH< Value >, unsigned > ValueRankMap
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
SetVector< AssertingVH< Instruction >, std::deque< AssertingVH< Instruction > > > OrderedSet
DenseMap< std::pair< Value *, Value * >, PairMapValue > PairMap[NumBinaryOps]
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.
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.
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.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI void deleteValue()
Delete a pointer to a generic Value.
LLVM_ABI 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.
@ BasicBlock
Various leaf nodes.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
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)
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...
initializer< Ty > init(const Ty &Val)
A private "module" namespace for types and utilities used by Reassociate.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI 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.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI 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)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI 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.
LLVM_ABI 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)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionAddr VTableAddr Count
LLVM_ABI void initializeReassociateLegacyPassPass(PassRegistry &)
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...
LLVM_ABI Constant * ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL)
Attempt to constant fold a binary operation with the specified operands.
LLVM_ABI 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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI FunctionPass * createReassociatePass()
LLVM_ABI 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...
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
LLVM_ABI bool mayHaveNonDefUseDependency(const Instruction &I)
Returns true if the result or effects of the given instructions I depend values not reachable through...
LLVM_ABI 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.