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);
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');
978 if (MulUser->getOpcode() != Instruction::Add &&
979 MulUser->getOpcode() != Instruction::Sub)
982 for (
Value *Sibling : MulUser->operands()) {
983 if (Sibling ==
Mul || !Sibling->hasOneUse())
1006 "Mul1",
Mul->getIterator());
1007 BinaryOperator *M2 = BinaryOperator::CreateMul(AddSub->getOperand(1), C2,
1008 "Mul2",
Mul->getIterator());
1010 BinaryOperator::CreateAdd(
M1, M2,
"DistAdd",
Mul->getIterator());
1012 Mul->replaceAllUsesWith(Result);
1013 Result->setDebugLoc(
Mul->getDebugLoc());
1043 if (
Sub->hasOneUse() &&
1068 Sub->replaceAllUsesWith(New);
1069 New->setDebugLoc(
Sub->getDebugLoc());
1081 assert(MulCst &&
"Constant folding of immediate constants failed");
1099 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1100 Mul->setHasNoSignedWrap(
true);
1101 Mul->setHasNoUnsignedWrap(NUW);
1110 unsigned XRank =
Ops[i].Rank;
1111 unsigned e =
Ops.size();
1112 for (
unsigned j = i+1; j != e &&
Ops[j].Rank == XRank; ++j) {
1117 if (I1->isIdenticalTo(I2))
1121 for (
unsigned j = i-1; j != ~0U &&
Ops[j].Rank == XRank; --j) {
1126 if (I1->isIdenticalTo(I2))
1136 if (
Ops.size() == 1)
return Ops.back();
1140 auto *NewAdd =
CreateAdd(V2,
V1,
"reass.add",
I->getIterator(),
I);
1141 NewAdd->setDebugLoc(
I->getDebugLoc());
1152 BinaryOperator *BO =
isReassociableOp(V, Instruction::Mul, Instruction::FMul);
1157 OverflowTracking
Flags;
1164 bool FoundFactor =
false;
1165 bool NeedsNegate =
false;
1166 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1176 if (FC1->getValue() == -FC2->getValue()) {
1177 FoundFactor = NeedsNegate =
true;
1183 const APFloat &F1 = FC1->getValueAPF();
1184 APFloat F2(FC2->getValueAPF());
1187 FoundFactor = NeedsNegate =
true;
1197 RewriteExprTree(BO, Factors, Flags);
1205 if (Factors.
size() == 1) {
1206 RedoInsts.insert(BO);
1209 RewriteExprTree(BO, Factors, Flags);
1245 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1252 if (Opcode == Instruction::And)
1255 if (Opcode == Instruction::Or)
1263 if (i+1 !=
Ops.size() &&
Ops[i+1].Op ==
Ops[i].Op) {
1264 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1266 Ops.erase(
Ops.begin()+i);
1273 assert(Opcode == Instruction::Xor);
1278 Ops.erase(
Ops.begin()+i,
Ops.begin()+i+2);
1292 const APInt &ConstOpnd) {
1300 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1302 I->setDebugLoc(InsertBefore->getDebugLoc());
1313 APInt &ConstOpnd,
Value *&Res) {
1325 if (C1 != ConstOpnd)
1334 RedoInsts.insert(
T);
1347 XorOpnd *Opnd2, APInt &ConstOpnd,
1354 int DeadInstNum = 1;
1372 APInt C3((~C1) ^ C2);
1375 if (!C3.isZero() && !C3.isAllOnes()) {
1377 if (NewInstNum > DeadInstNum)
1393 if (NewInstNum > DeadInstNum)
1411 RedoInsts.insert(
T);
1413 RedoInsts.insert(
T);
1421Value *ReassociatePass::OptimizeXor(Instruction *
I,
1422 SmallVectorImpl<ValueEntry> &
Ops) {
1426 if (
Ops.size() == 1)
1431 Type *Ty =
Ops[0].Op->getType();
1443 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1470 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1476 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1477 XorOpnd *CurrOpnd = OpndPtrs[i];
1482 if (!ConstOpnd.
isZero() &&
1483 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1493 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1494 PrevOpnd = CurrOpnd;
1500 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1502 PrevOpnd->Invalidate();
1505 PrevOpnd = CurrOpnd;
1517 for (
const XorOpnd &O : Opnds) {
1523 if (!ConstOpnd.
isZero()) {
1524 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1528 unsigned Sz =
Ops.size();
1530 return Ops.back().Op;
1533 return ConstantInt::get(Ty, ConstOpnd);
1543Value *ReassociatePass::OptimizeAdd(Instruction *
I,
1544 SmallVectorImpl<ValueEntry> &
Ops) {
1550 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1555 if (i+1 !=
Ops.size() &&
Ops[i+1].Op == TheOp) {
1557 unsigned NumFound = 0;
1559 Ops.erase(
Ops.begin()+i);
1561 }
while (i !=
Ops.size() &&
Ops[i].Op == TheOp);
1563 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1571 ? ConstantInt::get(Ty, NumFound,
false,
1575 Mul->setDebugLoc(
I->getDebugLoc());
1580 RedoInsts.insert(
Mul);
1607 if (
Ops.size() == 2 &&
1615 Ops.erase(
Ops.begin()+i);
1620 Ops.erase(
Ops.begin()+FoundX);
1638 DenseMap<Value*, unsigned> FactorOccurrences;
1642 unsigned MaxOcc = 0;
1643 Value *MaxOccVal =
nullptr;
1650 return Occ > MaxOcc ||
1656 BinaryOperator *BOp =
1662 SmallVector<Value*, 8> Factors;
1664 assert(Factors.
size() > 1 &&
"Bad linearize!");
1667 SmallPtrSet<Value*, 8> Duplicates;
1672 unsigned Occ = ++FactorOccurrences[
Factor];
1673 if (IsBetterFactor(
Factor, MaxOccVal, Occ, MaxOcc)) {
1682 if (CI->isNegative() && !CI->isMinValue(
true)) {
1683 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1686 unsigned Occ = ++FactorOccurrences[
Factor];
1687 if (IsBetterFactor(
Factor, MaxOccVal, Occ, MaxOcc)) {
1693 if (CF->isNegative()) {
1696 Factor = ConstantFP::get(CF->getType(),
F);
1699 unsigned Occ = ++FactorOccurrences[
Factor];
1700 if (IsBetterFactor(
Factor, MaxOccVal, Occ, MaxOcc)) {
1711 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1720 I->getType()->isIntOrIntVectorTy()
1721 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1722 : BinaryOperator::CreateFAdd(MaxOccVal, MaxOccVal);
1725 for (
unsigned i = 0; i !=
Ops.size(); ++i) {
1727 BinaryOperator *BOp =
1732 if (
Value *V = RemoveFactorFromExpression(
Ops[i].
Op, MaxOccVal,
1733 I->getDebugLoc())) {
1736 for (
unsigned j =
Ops.size(); j != i;) {
1740 Ops.erase(
Ops.begin()+j);
1750 unsigned NumAddedValues = NewMulOps.
size();
1756 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1757 (void)NumAddedValues;
1759 RedoInsts.insert(VI);
1767 RedoInsts.insert(V2);
1798 unsigned FactorPowerSum = 0;
1799 for (
unsigned Idx = 1,
Size =
Ops.size(); Idx <
Size; ++Idx) {
1804 for (; Idx <
Size &&
Ops[Idx].Op ==
Op; ++Idx)
1808 FactorPowerSum +=
Count;
1815 if (FactorPowerSum < 4)
1820 for (
unsigned Idx = 1; Idx <
Ops.size(); ++Idx) {
1825 for (; Idx <
Ops.size() &&
Ops[Idx].
Op ==
Op; ++Idx)
1832 FactorPowerSum +=
Count;
1839 assert(FactorPowerSum >= 4);
1842 return LHS.Power >
RHS.Power;
1850 if (
Ops.size() == 1)
1855 if (
LHS->getType()->isIntOrIntVectorTy())
1856 LHS = Builder.CreateMul(
LHS,
Ops.pop_back_val());
1858 LHS = Builder.CreateFMul(
LHS,
Ops.pop_back_val());
1859 }
while (!
Ops.empty());
1871ReassociatePass::buildMinimalMultiplyDAG(IRBuilderBase &Builder,
1872 SmallVectorImpl<Factor> &Factors) {
1873 assert(Factors[0].Power);
1874 SmallVector<Value *, 4> OuterProduct;
1875 for (
unsigned LastIdx = 0, Idx = 1,
Size = Factors.
size();
1876 Idx <
Size && Factors[Idx].Power > 0; ++Idx) {
1877 if (Factors[Idx].Power != Factors[LastIdx].Power) {
1885 SmallVector<Value *, 4> InnerProduct;
1890 }
while (Idx <
Size && Factors[Idx].Power == Factors[LastIdx].Power);
1896 RedoInsts.insert(
MI);
1904 return LHS.Power ==
RHS.Power;
1916 if (Factors[0].Power) {
1917 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1921 if (OuterProduct.
size() == 1)
1922 return OuterProduct.
front();
1928Value *ReassociatePass::OptimizeMul(BinaryOperator *
I,
1929 SmallVectorImpl<ValueEntry> &
Ops) {
1949 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1958Value *ReassociatePass::OptimizeExpression(BinaryOperator *
I,
1959 SmallVectorImpl<ValueEntry> &
Ops) {
1962 const DataLayout &
DL =
I->getDataLayout();
1964 unsigned Opcode =
I->getOpcode();
1965 while (!
Ops.empty()) {
1993 if (
Ops.size() == 1)
return Ops[0].
Op;
2000 case Instruction::And:
2001 case Instruction::Or:
2006 case Instruction::Xor:
2007 if (
Value *Result = OptimizeXor(
I,
Ops))
2011 case Instruction::Add:
2012 case Instruction::FAdd:
2013 if (
Value *Result = OptimizeAdd(
I,
Ops))
2017 case Instruction::Mul:
2018 case Instruction::FMul:
2019 if (
Value *Result = OptimizeMul(
I,
Ops))
2025 return OptimizeExpression(
I,
Ops);
2031void ReassociatePass::RecursivelyEraseDeadInsts(Instruction *
I,
2032 OrderedSet &Insts) {
2034 SmallVector<Value *, 4>
Ops(
I->operands());
2035 ValueRankMap.erase(
I);
2037 RedoInsts.remove(
I);
2039 I->eraseFromParent();
2040 for (
auto *
Op :
Ops)
2042 if (OpInst->use_empty())
2043 Insts.insert(OpInst);
2047void ReassociatePass::EraseInst(Instruction *
I) {
2051 SmallVector<Value *, 8>
Ops(
I->operands());
2053 ValueRankMap.erase(
I);
2054 RedoInsts.remove(
I);
2056 I->eraseFromParent();
2058 SmallPtrSet<Instruction *, 8> Visited;
2063 unsigned Opcode =
Op->getOpcode();
2064 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
2066 Op =
Op->user_back();
2073 if (ValueRankMap.contains(
Op))
2074 RedoInsts.insert(
Op);
2094 switch (
I->getOpcode()) {
2095 case Instruction::FMul:
2107 case Instruction::FDiv:
2129Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *
I,
2132 assert((
I->getOpcode() == Instruction::FAdd ||
2133 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2137 SmallVector<Instruction *, 4> Candidates;
2139 if (Candidates.
empty())
2145 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2146 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2150 for (Instruction *Negatible : Candidates) {
2154 "Expecting only 1 constant operand");
2155 assert(
C->isNegative() &&
"Expected negative FP constant");
2156 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2161 "Expecting only 1 constant operand");
2162 assert(
C->isNegative() &&
"Expected negative FP constant");
2163 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2167 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2170 if (Candidates.size() % 2 == 0)
2175 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2180 RedoInsts.insert(
I);
2192Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *
I) {
2197 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2200 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2203 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2210void ReassociatePass::OptimizeInst(Instruction *
I) {
2223 RedoInsts.insert(
I);
2231 if (
I->isCommutative())
2232 canonicalizeOperands(
I);
2235 if (Instruction *Res = canonicalizeNegFPConstants(
I))
2250 if (
I->getType()->isIntOrIntVectorTy(1))
2255 if (
I->getOpcode() == Instruction::Or &&
2259 SimplifyQuery(
I->getDataLayout(),
2260 nullptr,
nullptr,
I)))) {
2262 RedoInsts.insert(
I);
2270 RedoInsts.insert(
I);
2271 RedoInsts.insert(MulUser);
2278 if (
I->getOpcode() == Instruction::Sub) {
2281 RedoInsts.insert(
I);
2293 for (User *U : NI->
users()) {
2295 RedoInsts.insert(Tmp);
2297 RedoInsts.insert(
I);
2302 }
else if (
I->getOpcode() == Instruction::FNeg ||
2303 I->getOpcode() == Instruction::FSub) {
2306 RedoInsts.insert(
I);
2320 for (User *U : NI->
users()) {
2322 RedoInsts.insert(Tmp);
2324 RedoInsts.insert(
I);
2332 if (!
I->isAssociative())
return;
2357 ReassociateExpression(BO);
2360void ReassociatePass::ReassociateExpression(BinaryOperator *
I) {
2364 OverflowTracking
Flags;
2383 if (
Value *V = OptimizeExpression(
I,
Ops)) {
2390 I->replaceAllUsesWith(V);
2392 if (
I->getDebugLoc())
2393 VI->setDebugLoc(
I->getDebugLoc());
2394 RedoInsts.insert(
I);
2403 if (
I->hasOneUse()) {
2404 if (
I->getOpcode() == Instruction::Mul &&
2409 Ops.insert(
Ops.begin(), Tmp);
2410 }
else if (
I->getOpcode() == Instruction::FMul &&
2412 Instruction::FAdd &&
2416 Ops.insert(
Ops.begin(), Tmp);
2422 if (
Ops.size() == 1) {
2429 I->replaceAllUsesWith(
Ops[0].
Op);
2431 OI->setDebugLoc(
I->getDebugLoc());
2432 RedoInsts.insert(
I);
2436 if (
Ops.size() > 2 &&
Ops.size() <= GlobalReassociateLimit) {
2444 unsigned BestRank = 0;
2445 std::pair<unsigned, unsigned> BestPair;
2446 unsigned Idx =
I->getOpcode() - Instruction::BinaryOpsBegin;
2447 unsigned LimitIdx = 0;
2457 int StartIdx =
Ops.size() - 1;
2462 for (
int i = StartIdx - 1; i != -1; --i) {
2466 if (!CurrLeafInstr) {
2491 FirstSeenBB = SeenBB;
2494 if (FirstSeenBB != SeenBB) {
2500 << LimitIdx <<
", " << StartIdx <<
"]\n");
2505 for (
unsigned i =
Ops.size() - 1; i > LimitIdx; --i) {
2507 for (
int j = i - 1;
j >= (int)LimitIdx; --
j) {
2511 if (std::less<Value *>()(Op1, Op0))
2513 auto it = PairMap[Idx].find({Op0, Op1});
2514 if (it != PairMap[Idx].
end()) {
2520 if (it->second.isValid())
2521 Score += it->second.Score;
2524 unsigned MaxRank = std::max(
Ops[i].Rank,
Ops[j].Rank);
2538 if (Score > Max || (Score == Max && MaxRank < BestRank)) {
2546 auto Op0 =
Ops[BestPair.first];
2547 auto Op1 =
Ops[BestPair.second];
2548 Ops.erase(&
Ops[BestPair.second]);
2549 Ops.erase(&
Ops[BestPair.first]);
2558 RewriteExprTree(
I,
Ops, Flags);
2562ReassociatePass::BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT) {
2564 for (BasicBlock *BI : RPOT) {
2565 for (Instruction &
I : *BI) {
2566 if (!
I.isAssociative() || !
I.isBinaryOp())
2570 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2576 SmallVector<Value *, 8> Worklist = {
I.getOperand(0),
I.getOperand(1) };
2577 SmallVector<Value *, 8>
Ops;
2578 while (!Worklist.
empty() &&
Ops.size() <= GlobalReassociateLimit) {
2592 if (
Ops.size() > GlobalReassociateLimit)
2596 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2597 SmallSet<std::pair<Value *, Value*>, 32> Visited;
2598 for (
unsigned i = 0; i <
Ops.size() - 1; ++i) {
2599 for (
unsigned j = i + 1;
j <
Ops.size(); ++
j) {
2603 if (std::less<Value *>()(Op1, Op0))
2605 if (!Visited.
insert({Op0, Op1}).second)
2607 auto res = PairMap[BinaryIdx].insert({{Op0, Op1}, {Op0, Op1, 1}});
2613 assert(res.first->second.isValid() &&
"WeakVH invalidated");
2614 ++res.first->second.Score;
2630 BuildRankMap(
F, RPOT);
2654 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2665 while (!ToRedo.
empty()) {
2668 RecursivelyEraseDeadInsts(
I, ToRedo);
2713 if (skipFunction(
F))
2717 auto PA = Impl.run(
F, DummyFAM);
2718 return !PA.areAllPreserved();
2721 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2731char ReassociateLegacyPass::ID = 0;
2734 "Reassociate expressions",
false,
false)
2738 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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-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 bool ShouldBreakUpDistribution(Instruction *Mul)
Return true if Mul is of the form (X+Y)*C or (X-Y)*C where C is a constant, and there exists a siblin...
static BinaryOperator * CreateAdd(Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static BinaryOperator * BreakUpDistribute(Instruction *Mul, ReassociatePass::OrderedSet &ToRedo)
Distribute Mul of the form (X+Y)*C into X*C + Y*C.
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)
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
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)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
auto m_Constant()
Match an arbitrary Constant and ignore it.
match_immconstant_ty m_ImmConstant()
Match an arbitrary immediate Constant and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
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)
unsigned M1(unsigned Val)
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.