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))
640 Op->setOperand(0, NewLHS);
642 if (NewRHS != OldRHS) {
644 if (BO && !NotRewritable.
count(BO))
647 Op->setOperand(1, NewRHS);
651 ExpressionChangedStart =
Op;
652 if (!ExpressionChangedEnd)
653 ExpressionChangedEnd =
Op;
663 if (NewRHS !=
Op->getOperand(1)) {
665 if (NewRHS ==
Op->getOperand(0)) {
672 if (BO && !NotRewritable.
count(BO))
675 Op->setOperand(1, NewRHS);
676 ExpressionChangedStart =
Op;
677 if (!ExpressionChangedEnd)
678 ExpressionChangedEnd =
Op;
689 if (BO && !NotRewritable.
count(BO)) {
701 BinaryOperator *NewOp;
702 if (NodesToRewrite.
empty()) {
714 Op->setOperand(0, NewOp);
716 ExpressionChangedStart =
Op;
717 if (!ExpressionChangedEnd)
718 ExpressionChangedEnd =
Op;
728 if (ExpressionChangedStart) {
729 bool ClearFlags =
true;
736 Flags.applyFlags(*ExpressionChangedStart);
740 if (ExpressionChangedStart == ExpressionChangedEnd)
742 if (ExpressionChangedStart ==
I)
745 ExpressionChangedStart->
moveBefore(
I->getIterator());
746 ExpressionChangedStart =
752 RedoInsts.insert_range(NodesToRewrite);
766 Constant *Res =
C->getType()->isFPOrFPVectorTy()
787 if (
I->getOpcode() == Instruction::Add) {
788 I->setHasNoUnsignedWrap(
false);
789 I->setHasNoSignedWrap(
false);
798 I->setName(
I->getName()+
".neg");
821 C->containsUndefOrPoisonElement())
831 auto InsertPtOpt = InstInput->getInsertionPointAfterDef();
834 InsertPt = *InsertPtOpt;
845 if (TheNeg->
getParent() != InsertPt->getParent())
847 TheNeg->
moveBefore(*InsertPt->getParent(), InsertPt);
849 if (TheNeg->
getOpcode() == Instruction::Sub) {
878 auto Enqueue = [&](
Value *V) {
892 while (!Worklist.
empty()) {
896 switch (
I->getOpcode()) {
897 case Instruction::Or:
904 case Instruction::Shl:
905 case Instruction::ZExt:
907 if (!Enqueue(
I->getOperand(0)))
911 case Instruction::Load:
929 for (
auto Op : {Instruction::Add, Instruction::Sub, Instruction::Mul,
951 Or->getIterator(),
Or);
952 New->setHasNoSignedWrap();
953 New->setHasNoUnsignedWrap();
957 Or->replaceAllUsesWith(New);
958 New->setDebugLoc(
Or->getDebugLoc());
960 LLVM_DEBUG(
dbgs() <<
"Converted or into an add: " << *New <<
'\n');
985 if (
Sub->hasOneUse() &&
1010 Sub->replaceAllUsesWith(New);
1011 New->setDebugLoc(
Sub->getDebugLoc());
1023 assert(MulCst &&
"Constant folding of immediate constants failed");
1041 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1042 Mul->setHasNoSignedWrap(
true);
1043 Mul->setHasNoUnsignedWrap(NUW);
1052 unsigned XRank =
Ops[i].Rank;
1053 unsigned e =
Ops.size();
1054 for (
unsigned j = i+1; j != e &&
Ops[j].Rank == XRank; ++j) {
1059 if (I1->isIdenticalTo(I2))
1063 for (
unsigned j = i-1; j != ~0U &&
Ops[j].Rank == XRank; --j) {
1068 if (I1->isIdenticalTo(I2))
1078 if (
Ops.size() == 1)
return Ops.back();
1082 auto *NewAdd =
CreateAdd(V2, V1,
"reass.add",
I->getIterator(),
I);
1083 NewAdd->setDebugLoc(
I->getDebugLoc());
1094 BinaryOperator *BO =
isReassociableOp(V, Instruction::Mul, Instruction::FMul);
1099 OverflowTracking
Flags;
1106 bool FoundFactor =
false;
1107 bool NeedsNegate =
false;
1108 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1118 if (FC1->getValue() == -FC2->getValue()) {
1119 FoundFactor = NeedsNegate =
true;
1125 const APFloat &F1 = FC1->getValueAPF();
1126 APFloat F2(FC2->getValueAPF());
1129 FoundFactor = NeedsNegate =
true;
1139 RewriteExprTree(BO, Factors, Flags);
1147 if (Factors.
size() == 1) {
1148 RedoInsts.insert(BO);
1151 RewriteExprTree(BO, Factors, Flags);
1187 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1194 if (Opcode == Instruction::And)
1197 if (Opcode == Instruction::Or)
1205 if (i+1 !=
Ops.size() &&
Ops[i+1].Op ==
Ops[i].Op) {
1206 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1208 Ops.erase(
Ops.begin()+i);
1215 assert(Opcode == Instruction::Xor);
1220 Ops.erase(
Ops.begin()+i,
Ops.begin()+i+2);
1234 const APInt &ConstOpnd) {
1242 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1244 I->setDebugLoc(InsertBefore->getDebugLoc());
1255 APInt &ConstOpnd,
Value *&Res) {
1267 if (C1 != ConstOpnd)
1276 RedoInsts.insert(
T);
1289 XorOpnd *Opnd2, APInt &ConstOpnd,
1296 int DeadInstNum = 1;
1314 APInt C3((~C1) ^ C2);
1317 if (!C3.isZero() && !C3.isAllOnes()) {
1319 if (NewInstNum > DeadInstNum)
1335 if (NewInstNum > DeadInstNum)
1353 RedoInsts.insert(
T);
1355 RedoInsts.insert(
T);
1363Value *ReassociatePass::OptimizeXor(Instruction *
I,
1364 SmallVectorImpl<ValueEntry> &
Ops) {
1368 if (
Ops.size() == 1)
1373 Type *Ty =
Ops[0].Op->getType();
1385 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1412 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1418 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1419 XorOpnd *CurrOpnd = OpndPtrs[i];
1424 if (!ConstOpnd.
isZero() &&
1425 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1435 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1436 PrevOpnd = CurrOpnd;
1442 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1444 PrevOpnd->Invalidate();
1447 PrevOpnd = CurrOpnd;
1459 for (
const XorOpnd &O : Opnds) {
1465 if (!ConstOpnd.
isZero()) {
1466 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1470 unsigned Sz =
Ops.size();
1472 return Ops.back().Op;
1475 return ConstantInt::get(Ty, ConstOpnd);
1485Value *ReassociatePass::OptimizeAdd(Instruction *
I,
1486 SmallVectorImpl<ValueEntry> &
Ops) {
1492 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1497 if (i+1 !=
Ops.size() &&
Ops[i+1].Op == TheOp) {
1499 unsigned NumFound = 0;
1501 Ops.erase(
Ops.begin()+i);
1503 }
while (i !=
Ops.size() &&
Ops[i].Op == TheOp);
1505 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1513 ? ConstantInt::get(Ty, NumFound,
false,
1517 Mul->setDebugLoc(
I->getDebugLoc());
1522 RedoInsts.insert(
Mul);
1549 if (
Ops.size() == 2 &&
1557 Ops.erase(
Ops.begin()+i);
1562 Ops.erase(
Ops.begin()+FoundX);
1580 DenseMap<Value*, unsigned> FactorOccurrences;
1584 unsigned MaxOcc = 0;
1585 Value *MaxOccVal =
nullptr;
1587 BinaryOperator *BOp =
1593 SmallVector<Value*, 8> Factors;
1595 assert(Factors.
size() > 1 &&
"Bad linearize!");
1598 SmallPtrSet<Value*, 8> Duplicates;
1603 unsigned Occ = ++FactorOccurrences[
Factor];
1613 if (CI->isNegative() && !CI->isMinValue(
true)) {
1614 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1617 unsigned Occ = ++FactorOccurrences[
Factor];
1624 if (CF->isNegative()) {
1627 Factor = ConstantFP::get(CF->getType(),
F);
1630 unsigned Occ = ++FactorOccurrences[
Factor];
1642 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1651 I->getType()->isIntOrIntVectorTy()
1652 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1653 : BinaryOperator::CreateFAdd(MaxOccVal, MaxOccVal);
1656 for (
unsigned i = 0; i !=
Ops.size(); ++i) {
1658 BinaryOperator *BOp =
1663 if (
Value *V = RemoveFactorFromExpression(
Ops[i].
Op, MaxOccVal,
1664 I->getDebugLoc())) {
1667 for (
unsigned j =
Ops.size(); j != i;) {
1671 Ops.erase(
Ops.begin()+j);
1681 unsigned NumAddedValues = NewMulOps.
size();
1687 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1688 (void)NumAddedValues;
1690 RedoInsts.insert(VI);
1698 RedoInsts.insert(V2);
1729 unsigned FactorPowerSum = 0;
1730 for (
unsigned Idx = 1,
Size =
Ops.size(); Idx <
Size; ++Idx) {
1735 for (; Idx <
Size &&
Ops[Idx].Op ==
Op; ++Idx)
1739 FactorPowerSum +=
Count;
1746 if (FactorPowerSum < 4)
1751 for (
unsigned Idx = 1; Idx <
Ops.size(); ++Idx) {
1756 for (; Idx <
Ops.size() &&
Ops[Idx].
Op ==
Op; ++Idx)
1763 FactorPowerSum +=
Count;
1770 assert(FactorPowerSum >= 4);
1773 return LHS.Power >
RHS.Power;
1781 if (
Ops.size() == 1)
1786 if (
LHS->getType()->isIntOrIntVectorTy())
1787 LHS = Builder.CreateMul(
LHS,
Ops.pop_back_val());
1789 LHS = Builder.CreateFMul(
LHS,
Ops.pop_back_val());
1790 }
while (!
Ops.empty());
1802ReassociatePass::buildMinimalMultiplyDAG(IRBuilderBase &Builder,
1803 SmallVectorImpl<Factor> &Factors) {
1804 assert(Factors[0].Power);
1805 SmallVector<Value *, 4> OuterProduct;
1806 for (
unsigned LastIdx = 0, Idx = 1,
Size = Factors.
size();
1807 Idx <
Size && Factors[Idx].Power > 0; ++Idx) {
1808 if (Factors[Idx].Power != Factors[LastIdx].Power) {
1816 SmallVector<Value *, 4> InnerProduct;
1821 }
while (Idx <
Size && Factors[Idx].Power == Factors[LastIdx].Power);
1827 RedoInsts.insert(
MI);
1835 return LHS.Power ==
RHS.Power;
1847 if (Factors[0].Power) {
1848 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1852 if (OuterProduct.
size() == 1)
1853 return OuterProduct.
front();
1859Value *ReassociatePass::OptimizeMul(BinaryOperator *
I,
1860 SmallVectorImpl<ValueEntry> &
Ops) {
1880 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1889Value *ReassociatePass::OptimizeExpression(BinaryOperator *
I,
1890 SmallVectorImpl<ValueEntry> &
Ops) {
1893 const DataLayout &
DL =
I->getDataLayout();
1895 unsigned Opcode =
I->getOpcode();
1896 while (!
Ops.empty()) {
1924 if (
Ops.size() == 1)
return Ops[0].
Op;
1931 case Instruction::And:
1932 case Instruction::Or:
1937 case Instruction::Xor:
1938 if (
Value *Result = OptimizeXor(
I,
Ops))
1942 case Instruction::Add:
1943 case Instruction::FAdd:
1944 if (
Value *Result = OptimizeAdd(
I,
Ops))
1948 case Instruction::Mul:
1949 case Instruction::FMul:
1950 if (
Value *Result = OptimizeMul(
I,
Ops))
1956 return OptimizeExpression(
I,
Ops);
1962void ReassociatePass::RecursivelyEraseDeadInsts(Instruction *
I,
1963 OrderedSet &Insts) {
1965 SmallVector<Value *, 4>
Ops(
I->operands());
1966 ValueRankMap.erase(
I);
1968 RedoInsts.remove(
I);
1970 I->eraseFromParent();
1971 for (
auto *
Op :
Ops)
1973 if (OpInst->use_empty())
1974 Insts.insert(OpInst);
1978void ReassociatePass::EraseInst(Instruction *
I) {
1982 SmallVector<Value *, 8>
Ops(
I->operands());
1984 ValueRankMap.erase(
I);
1985 RedoInsts.remove(
I);
1987 I->eraseFromParent();
1989 SmallPtrSet<Instruction *, 8> Visited;
1994 unsigned Opcode =
Op->getOpcode();
1995 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
1997 Op =
Op->user_back();
2004 if (ValueRankMap.contains(
Op))
2005 RedoInsts.insert(
Op);
2025 switch (
I->getOpcode()) {
2026 case Instruction::FMul:
2038 case Instruction::FDiv:
2060Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *
I,
2063 assert((
I->getOpcode() == Instruction::FAdd ||
2064 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2068 SmallVector<Instruction *, 4> Candidates;
2070 if (Candidates.
empty())
2076 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2077 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2081 for (Instruction *Negatible : Candidates) {
2085 "Expecting only 1 constant operand");
2086 assert(
C->isNegative() &&
"Expected negative FP constant");
2087 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2092 "Expecting only 1 constant operand");
2093 assert(
C->isNegative() &&
"Expected negative FP constant");
2094 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2098 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2101 if (Candidates.size() % 2 == 0)
2106 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2111 RedoInsts.insert(
I);
2123Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *
I) {
2128 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2131 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2134 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2141void ReassociatePass::OptimizeInst(Instruction *
I) {
2154 RedoInsts.insert(
I);
2162 if (
I->isCommutative())
2163 canonicalizeOperands(
I);
2166 if (Instruction *Res = canonicalizeNegFPConstants(
I))
2181 if (
I->getType()->isIntOrIntVectorTy(1))
2186 if (
I->getOpcode() == Instruction::Or &&
2190 SimplifyQuery(
I->getDataLayout(),
2191 nullptr,
nullptr,
I)))) {
2193 RedoInsts.insert(
I);
2200 if (
I->getOpcode() == Instruction::Sub) {
2203 RedoInsts.insert(
I);
2215 for (User *U : NI->
users()) {
2217 RedoInsts.insert(Tmp);
2219 RedoInsts.insert(
I);
2224 }
else if (
I->getOpcode() == Instruction::FNeg ||
2225 I->getOpcode() == Instruction::FSub) {
2228 RedoInsts.insert(
I);
2242 for (User *U : NI->
users()) {
2244 RedoInsts.insert(Tmp);
2246 RedoInsts.insert(
I);
2254 if (!
I->isAssociative())
return;
2279 ReassociateExpression(BO);
2282void ReassociatePass::ReassociateExpression(BinaryOperator *
I) {
2286 OverflowTracking
Flags;
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 &&
2331 Ops.insert(
Ops.begin(), Tmp);
2332 }
else if (
I->getOpcode() == Instruction::FMul &&
2334 Instruction::FAdd &&
2338 Ops.insert(
Ops.begin(), Tmp);
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) {
2388 if (!CurrLeafInstr) {
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) {
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);
2484ReassociatePass::BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT) {
2486 for (BasicBlock *BI : RPOT) {
2487 for (Instruction &
I : *BI) {
2488 if (!
I.isAssociative() || !
I.isBinaryOp())
2492 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2498 SmallVector<Value *, 8> Worklist = {
I.getOperand(0),
I.getOperand(1) };
2499 SmallVector<Value *, 8>
Ops;
2500 while (!Worklist.
empty() &&
Ops.size() <= GlobalReassociateLimit) {
2514 if (
Ops.size() > GlobalReassociateLimit)
2518 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2519 SmallSet<std::pair<Value *, Value*>, 32> Visited;
2520 for (
unsigned i = 0; i <
Ops.size() - 1; ++i) {
2521 for (
unsigned j = i + 1;
j <
Ops.size(); ++
j) {
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);
2576 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2587 while (!ToRedo.
empty()) {
2590 RecursivelyEraseDeadInsts(
I, ToRedo);
2635 if (skipFunction(
F))
2639 auto PA = Impl.run(
F, DummyFAM);
2640 return !PA.areAllPreserved();
2643 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2653char ReassociateLegacyPass::ID = 0;
2656 "Reassociate expressions",
false,
false)
2660 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,...
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
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)
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 copyFastMathFlags(FastMathFlags FMF)
Convenience function for transferring all fast-math flag values to this instruction,...
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()
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)
BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
ap_match< APFloat > m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
auto m_BinOp()
Match an arbitrary binary operation and ignore it.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::FAdd > m_FAdd(const LHS &L, const RHS &R)
auto m_Constant()
Match an arbitrary Constant and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
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()
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.