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) {
209 struct RankWorkItem {
221 RankWorkItem &Item = Worklist.
back();
227 }
else if (ValueRankMap[
I]) {
229 Rank = ValueRankMap[
I];
230 }
else if (Item.OpNo ==
I->getNumOperands() ||
231 Item.Rank == RankMap[
I->getParent()]) {
240 LLVM_DEBUG(
dbgs() <<
"Calculated Rank[" <<
I->getName() <<
"] = " << Rank
243 ValueRankMap[
I] = Rank;
245 Worklist.
push_back(RankWorkItem{
I->getOperand(Item.OpNo), 0, 0});
252 if (Worklist.
empty())
255 RankWorkItem &Parent = Worklist.
back();
256 Parent.Rank = std::max(Parent.Rank, Rank);
262void ReassociatePass::canonicalizeOperands(Instruction *
I) {
264 assert(
I->isCommutative() &&
"Expected commutative operator.");
279 if (
S1->getType()->isIntOrIntVectorTy())
280 return BinaryOperator::CreateAdd(
S1, S2, Name, InsertBefore);
283 BinaryOperator::CreateFAdd(
S1, S2, Name, InsertBefore);
292 if (
S1->getType()->isIntOrIntVectorTy())
293 return BinaryOperator::CreateMul(
S1, S2, Name, InsertBefore);
296 BinaryOperator::CreateFMul(
S1, S2, Name, InsertBefore);
305 if (
S1->getType()->isIntOrIntVectorTy())
311 return UnaryOperator::CreateFNeg(
S1, Name, InsertBefore);
317 "Expected a Negate!");
321 Constant *NegOne = Ty->isIntOrIntVectorTy() ?
413 "Expected a UnaryOperator or BinaryOperator!");
415 unsigned Opcode =
I->getOpcode();
416 assert(
I->isAssociative() &&
I->isCommutative() &&
417 "Expected an associative and commutative operation!");
456 while (!Worklist.
empty()) {
460 Flags.mergeFlags(*
I);
465 assert((!
Op->hasUseList() || !
Op->use_empty()) &&
466 "No uses, so how did we get to it?!");
473 Worklist.
push_back(std::make_pair(BO, Weight));
478 LeafMap::iterator It = Leaves.find(
Op);
479 if (It == Leaves.end()) {
482 if (!
Op->hasOneUse()) {
486 <<
"ADD USES LEAF: " << *
Op <<
" (" << Weight <<
")\n");
495 "In leaf map but not visited!");
498 It->second += Weight;
499 assert(It->second >= Weight &&
"Weight overflows");
503 if (!
Op->hasOneUse())
519 "Should have been handled above!");
520 assert(
Op->hasOneUse() &&
"Has uses outside the expression tree!");
532 <<
"MORPH LEAF: " << *
Op <<
" (" << Weight <<
") TO ");
556 for (
Value *V : LeafOrder) {
557 LeafMap::iterator It = Leaves.find(V);
558 if (It == Leaves.end())
565 Ops.push_back(std::make_pair(V, Weight));
566 if (Opcode == Instruction::Add && Flags.AllKnownNonNegative && Flags.HasNSW)
568 else if (Opcode == Instruction::Mul) {
571 if (Flags.AllKnownNonZero &&
572 (Flags.HasNUW || (Flags.HasNSW && Flags.AllKnownNonNegative))) {
574 if (Flags.HasNSW && Flags.AllKnownNonNegative)
585 assert(Identity &&
"Associative operation without identity!");
586 Ops.emplace_back(Identity, 1);
594void ReassociatePass::RewriteExprTree(BinaryOperator *
I,
595 SmallVectorImpl<ValueEntry> &
Ops,
596 OverflowTracking Flags) {
597 assert(
Ops.size() > 1 &&
"Single values should be used directly!");
611 unsigned Opcode =
I->getOpcode();
612 BinaryOperator *
Op =
I;
624 SmallPtrSet<Value*, 8> NotRewritable;
632 BinaryOperator *ExpressionChangedStart =
nullptr,
633 *ExpressionChangedEnd =
nullptr;
634 for (
unsigned i = 0; ; ++i) {
638 if (i+2 ==
Ops.size()) {
641 Value *OldLHS =
Op->getOperand(0);
642 Value *OldRHS =
Op->getOperand(1);
644 if (NewLHS == OldLHS && NewRHS == OldRHS)
648 if (NewLHS == OldRHS && NewRHS == OldLHS) {
661 if (NewLHS != OldLHS) {
663 if (BO && !NotRewritable.
count(BO))
666 Op->setOperand(0, NewLHS);
668 if (NewRHS != OldRHS) {
670 if (BO && !NotRewritable.
count(BO))
673 Op->setOperand(1, NewRHS);
677 ExpressionChangedStart =
Op;
678 if (!ExpressionChangedEnd)
679 ExpressionChangedEnd =
Op;
689 if (NewRHS !=
Op->getOperand(1)) {
691 if (NewRHS ==
Op->getOperand(0)) {
698 if (BO && !NotRewritable.
count(BO))
701 Op->setOperand(1, NewRHS);
702 ExpressionChangedStart =
Op;
703 if (!ExpressionChangedEnd)
704 ExpressionChangedEnd =
Op;
715 if (BO && !NotRewritable.
count(BO)) {
727 BinaryOperator *NewOp;
728 if (NodesToRewrite.
empty()) {
740 Op->setOperand(0, NewOp);
742 ExpressionChangedStart =
Op;
743 if (!ExpressionChangedEnd)
744 ExpressionChangedEnd =
Op;
754 if (ExpressionChangedStart) {
755 bool ClearFlags =
true;
762 Flags.applyFlags(*ExpressionChangedStart);
766 if (ExpressionChangedStart == ExpressionChangedEnd)
768 if (ExpressionChangedStart ==
I)
771 ExpressionChangedStart->
moveBefore(
I->getIterator());
772 ExpressionChangedStart =
778 RedoInsts.insert_range(NodesToRewrite);
792 Constant *Res =
C->getType()->isFPOrFPVectorTy()
813 if (
I->getOpcode() == Instruction::Add) {
814 I->setHasNoUnsignedWrap(
false);
815 I->setHasNoSignedWrap(
false);
824 I->setName(
I->getName()+
".neg");
847 C->containsUndefOrPoisonElement())
857 auto InsertPtOpt = InstInput->getInsertionPointAfterDef();
860 InsertPt = *InsertPtOpt;
871 if (TheNeg->
getParent() != InsertPt->getParent())
873 TheNeg->
moveBefore(*InsertPt->getParent(), InsertPt);
875 if (TheNeg->
getOpcode() == Instruction::Sub) {
904 auto Enqueue = [&](
Value *V) {
918 while (!Worklist.
empty()) {
922 switch (
I->getOpcode()) {
923 case Instruction::Or:
930 case Instruction::Shl:
931 case Instruction::ZExt:
933 if (!Enqueue(
I->getOperand(0)))
937 case Instruction::Load:
955 for (
auto Op : {Instruction::Add, Instruction::Sub, Instruction::Mul,
977 Or->getIterator(),
Or);
978 New->setHasNoSignedWrap();
979 New->setHasNoUnsignedWrap();
983 Or->replaceAllUsesWith(New);
984 New->setDebugLoc(
Or->getDebugLoc());
986 LLVM_DEBUG(
dbgs() <<
"Converted or into an add: " << *New <<
'\n');
1004 if (MulUser->getOpcode() != Instruction::Add &&
1005 MulUser->getOpcode() != Instruction::Sub)
1008 for (
Value *Sibling : MulUser->operands()) {
1009 if (Sibling ==
Mul || !Sibling->hasOneUse())
1032 "Mul1",
Mul->getIterator());
1033 BinaryOperator *M2 = BinaryOperator::CreateMul(AddSub->getOperand(1), C2,
1034 "Mul2",
Mul->getIterator());
1036 BinaryOperator::CreateAdd(
M1, M2,
"DistAdd",
Mul->getIterator());
1038 Mul->replaceAllUsesWith(Result);
1039 Result->setDebugLoc(
Mul->getDebugLoc());
1069 if (
Sub->hasOneUse() &&
1094 Sub->replaceAllUsesWith(New);
1095 New->setDebugLoc(
Sub->getDebugLoc());
1107 assert(MulCst &&
"Constant folding of immediate constants failed");
1125 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1126 Mul->setHasNoSignedWrap(
true);
1127 Mul->setHasNoUnsignedWrap(NUW);
1136 unsigned XRank =
Ops[i].Rank;
1137 unsigned e =
Ops.size();
1138 for (
unsigned j = i+1; j != e &&
Ops[j].Rank == XRank; ++j) {
1143 if (I1->isIdenticalTo(I2))
1147 for (
unsigned j = i-1; j != ~0U &&
Ops[j].Rank == XRank; --j) {
1152 if (I1->isIdenticalTo(I2))
1162 if (
Ops.size() == 1)
return Ops.back();
1166 auto *NewAdd =
CreateAdd(V2,
V1,
"reass.add",
I->getIterator(),
I);
1167 NewAdd->setDebugLoc(
I->getDebugLoc());
1178 BinaryOperator *BO =
isReassociableOp(V, Instruction::Mul, Instruction::FMul);
1183 OverflowTracking
Flags;
1190 bool FoundFactor =
false;
1191 bool NeedsNegate =
false;
1192 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1202 if (FC1->getValue() == -FC2->getValue()) {
1203 FoundFactor = NeedsNegate =
true;
1209 const APFloat &F1 = FC1->getValueAPF();
1210 APFloat F2(FC2->getValueAPF());
1213 FoundFactor = NeedsNegate =
true;
1223 RewriteExprTree(BO, Factors, Flags);
1231 if (Factors.
size() == 1) {
1232 RedoInsts.insert(BO);
1235 RewriteExprTree(BO, Factors, Flags);
1271 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1278 if (Opcode == Instruction::And)
1281 if (Opcode == Instruction::Or)
1289 if (i+1 !=
Ops.size() &&
Ops[i+1].Op ==
Ops[i].Op) {
1290 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1292 Ops.erase(
Ops.begin()+i);
1299 assert(Opcode == Instruction::Xor);
1304 Ops.erase(
Ops.begin()+i,
Ops.begin()+i+2);
1318 const APInt &ConstOpnd) {
1326 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1328 I->setDebugLoc(InsertBefore->getDebugLoc());
1339 APInt &ConstOpnd,
Value *&Res) {
1351 if (C1 != ConstOpnd)
1360 RedoInsts.insert(
T);
1373 XorOpnd *Opnd2, APInt &ConstOpnd,
1380 int DeadInstNum = 1;
1398 APInt C3((~C1) ^ C2);
1401 if (!C3.isZero() && !C3.isAllOnes()) {
1403 if (NewInstNum > DeadInstNum)
1419 if (NewInstNum > DeadInstNum)
1437 RedoInsts.insert(
T);
1439 RedoInsts.insert(
T);
1447Value *ReassociatePass::OptimizeXor(Instruction *
I,
1448 SmallVectorImpl<ValueEntry> &
Ops) {
1452 if (
Ops.size() == 1)
1457 Type *Ty =
Ops[0].Op->getType();
1469 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1496 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1502 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1503 XorOpnd *CurrOpnd = OpndPtrs[i];
1508 if (!ConstOpnd.
isZero() &&
1509 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1519 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1520 PrevOpnd = CurrOpnd;
1526 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1528 PrevOpnd->Invalidate();
1531 PrevOpnd = CurrOpnd;
1543 for (
const XorOpnd &O : Opnds) {
1549 if (!ConstOpnd.
isZero()) {
1550 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1554 unsigned Sz =
Ops.size();
1556 return Ops.back().Op;
1559 return ConstantInt::get(Ty, ConstOpnd);
1569Value *ReassociatePass::OptimizeAdd(Instruction *
I,
1570 SmallVectorImpl<ValueEntry> &
Ops) {
1576 for (
unsigned i = 0, e =
Ops.size(); i != e; ++i) {
1581 if (i+1 !=
Ops.size() &&
Ops[i+1].Op == TheOp) {
1583 unsigned NumFound = 0;
1585 Ops.erase(
Ops.begin()+i);
1587 }
while (i !=
Ops.size() &&
Ops[i].Op == TheOp);
1589 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1597 ? ConstantInt::get(Ty, NumFound,
false,
1601 Mul->setDebugLoc(
I->getDebugLoc());
1606 RedoInsts.insert(
Mul);
1633 if (
Ops.size() == 2 &&
1641 Ops.erase(
Ops.begin()+i);
1646 Ops.erase(
Ops.begin()+FoundX);
1664 DenseMap<Value*, unsigned> FactorOccurrences;
1668 unsigned MaxOcc = 0;
1669 Value *MaxOccVal =
nullptr;
1676 return Occ > MaxOcc ||
1682 BinaryOperator *BOp =
1688 SmallVector<Value*, 8> Factors;
1690 assert(Factors.
size() > 1 &&
"Bad linearize!");
1693 SmallPtrSet<Value*, 8> Duplicates;
1698 unsigned Occ = ++FactorOccurrences[
Factor];
1699 if (IsBetterFactor(
Factor, MaxOccVal, Occ, MaxOcc)) {
1708 if (CI->isNegative() && !CI->isMinValue(
true)) {
1709 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1712 unsigned Occ = ++FactorOccurrences[
Factor];
1713 if (IsBetterFactor(
Factor, MaxOccVal, Occ, MaxOcc)) {
1719 if (CF->isNegative()) {
1722 Factor = ConstantFP::get(CF->getType(),
F);
1725 unsigned Occ = ++FactorOccurrences[
Factor];
1726 if (IsBetterFactor(
Factor, MaxOccVal, Occ, MaxOcc)) {
1737 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1746 I->getType()->isIntOrIntVectorTy()
1747 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1748 : BinaryOperator::CreateFAdd(MaxOccVal, MaxOccVal);
1751 for (
unsigned i = 0; i !=
Ops.size(); ++i) {
1753 BinaryOperator *BOp =
1758 if (
Value *V = RemoveFactorFromExpression(
Ops[i].
Op, MaxOccVal,
1759 I->getDebugLoc())) {
1762 for (
unsigned j =
Ops.size(); j != i;) {
1766 Ops.erase(
Ops.begin()+j);
1776 unsigned NumAddedValues = NewMulOps.
size();
1782 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1783 (void)NumAddedValues;
1785 RedoInsts.insert(VI);
1793 RedoInsts.insert(V2);
1824 unsigned FactorPowerSum = 0;
1825 for (
unsigned Idx = 1,
Size =
Ops.size(); Idx <
Size; ++Idx) {
1830 for (; Idx <
Size &&
Ops[Idx].Op ==
Op; ++Idx)
1834 FactorPowerSum +=
Count;
1841 if (FactorPowerSum < 4)
1846 for (
unsigned Idx = 1; Idx <
Ops.size(); ++Idx) {
1851 for (; Idx <
Ops.size() &&
Ops[Idx].
Op ==
Op; ++Idx)
1858 FactorPowerSum +=
Count;
1865 assert(FactorPowerSum >= 4);
1868 return LHS.Power >
RHS.Power;
1876 if (
Ops.size() == 1)
1881 if (
LHS->getType()->isIntOrIntVectorTy())
1882 LHS = Builder.CreateMul(
LHS,
Ops.pop_back_val());
1884 LHS = Builder.CreateFMul(
LHS,
Ops.pop_back_val());
1885 }
while (!
Ops.empty());
1897ReassociatePass::buildMinimalMultiplyDAG(IRBuilderBase &Builder,
1898 SmallVectorImpl<Factor> &Factors) {
1899 assert(Factors[0].Power);
1900 SmallVector<Value *, 4> OuterProduct;
1901 for (
unsigned LastIdx = 0, Idx = 1,
Size = Factors.
size();
1902 Idx <
Size && Factors[Idx].Power > 0; ++Idx) {
1903 if (Factors[Idx].Power != Factors[LastIdx].Power) {
1911 SmallVector<Value *, 4> InnerProduct;
1916 }
while (Idx <
Size && Factors[Idx].Power == Factors[LastIdx].Power);
1922 RedoInsts.insert(
MI);
1930 return LHS.Power ==
RHS.Power;
1942 if (Factors[0].Power) {
1943 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1947 if (OuterProduct.
size() == 1)
1948 return OuterProduct.
front();
1954Value *ReassociatePass::OptimizeMul(BinaryOperator *
I,
1955 SmallVectorImpl<ValueEntry> &
Ops) {
1975 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1984Value *ReassociatePass::OptimizeExpression(BinaryOperator *
I,
1985 SmallVectorImpl<ValueEntry> &
Ops) {
1988 const DataLayout &
DL =
I->getDataLayout();
1990 unsigned Opcode =
I->getOpcode();
1991 while (!
Ops.empty()) {
2019 if (
Ops.size() == 1)
return Ops[0].
Op;
2026 case Instruction::And:
2027 case Instruction::Or:
2032 case Instruction::Xor:
2033 if (
Value *Result = OptimizeXor(
I,
Ops))
2037 case Instruction::Add:
2038 case Instruction::FAdd:
2039 if (
Value *Result = OptimizeAdd(
I,
Ops))
2043 case Instruction::Mul:
2044 case Instruction::FMul:
2045 if (
Value *Result = OptimizeMul(
I,
Ops))
2051 return OptimizeExpression(
I,
Ops);
2057void ReassociatePass::RecursivelyEraseDeadInsts(Instruction *
I,
2058 OrderedSet &Insts) {
2060 SmallVector<Value *, 4>
Ops(
I->operands());
2061 ValueRankMap.erase(
I);
2063 RedoInsts.remove(
I);
2065 I->eraseFromParent();
2066 for (
auto *
Op :
Ops)
2068 if (OpInst->use_empty())
2069 Insts.insert(OpInst);
2073void ReassociatePass::EraseInst(Instruction *
I) {
2077 SmallVector<Value *, 8>
Ops(
I->operands());
2079 ValueRankMap.erase(
I);
2080 RedoInsts.remove(
I);
2082 I->eraseFromParent();
2084 SmallPtrSet<Instruction *, 8> Visited;
2089 unsigned Opcode =
Op->getOpcode();
2090 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
2092 Op =
Op->user_back();
2099 if (ValueRankMap.contains(
Op))
2100 RedoInsts.insert(
Op);
2120 switch (
I->getOpcode()) {
2121 case Instruction::FMul:
2133 case Instruction::FDiv:
2155Instruction *ReassociatePass::canonicalizeNegFPConstantsForOp(Instruction *
I,
2158 assert((
I->getOpcode() == Instruction::FAdd ||
2159 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2163 SmallVector<Instruction *, 4> Candidates;
2165 if (Candidates.
empty())
2171 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2172 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2176 for (Instruction *Negatible : Candidates) {
2180 "Expecting only 1 constant operand");
2181 assert(
C->isNegative() &&
"Expected negative FP constant");
2182 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2187 "Expecting only 1 constant operand");
2188 assert(
C->isNegative() &&
"Expected negative FP constant");
2189 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2193 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2196 if (Candidates.size() % 2 == 0)
2201 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2206 RedoInsts.insert(
I);
2218Instruction *ReassociatePass::canonicalizeNegFPConstants(Instruction *
I) {
2223 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2226 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2229 if (Instruction *R = canonicalizeNegFPConstantsForOp(
I,
Op,
X))
2236void ReassociatePass::OptimizeInst(Instruction *
I) {
2249 RedoInsts.insert(
I);
2257 if (
I->isCommutative())
2258 canonicalizeOperands(
I);
2261 if (Instruction *Res = canonicalizeNegFPConstants(
I))
2276 if (
I->getType()->isIntOrIntVectorTy(1))
2281 if (
I->getOpcode() == Instruction::Or &&
2285 SimplifyQuery(
I->getDataLayout(),
2286 nullptr,
nullptr,
I)))) {
2288 RedoInsts.insert(
I);
2296 RedoInsts.insert(
I);
2297 RedoInsts.insert(MulUser);
2304 if (
I->getOpcode() == Instruction::Sub) {
2307 RedoInsts.insert(
I);
2319 for (User *U : NI->
users()) {
2321 RedoInsts.insert(Tmp);
2323 RedoInsts.insert(
I);
2328 }
else if (
I->getOpcode() == Instruction::FNeg ||
2329 I->getOpcode() == Instruction::FSub) {
2332 RedoInsts.insert(
I);
2346 for (User *U : NI->
users()) {
2348 RedoInsts.insert(Tmp);
2350 RedoInsts.insert(
I);
2358 if (!
I->isAssociative())
return;
2383 ReassociateExpression(BO);
2386void ReassociatePass::ReassociateExpression(BinaryOperator *
I) {
2390 OverflowTracking
Flags;
2409 if (
Value *V = OptimizeExpression(
I,
Ops)) {
2416 I->replaceAllUsesWith(V);
2418 if (
I->getDebugLoc())
2419 VI->setDebugLoc(
I->getDebugLoc());
2420 RedoInsts.insert(
I);
2429 if (
I->hasOneUse()) {
2430 if (
I->getOpcode() == Instruction::Mul &&
2435 Ops.insert(
Ops.begin(), Tmp);
2436 }
else if (
I->getOpcode() == Instruction::FMul &&
2438 Instruction::FAdd &&
2442 Ops.insert(
Ops.begin(), Tmp);
2448 if (
Ops.size() == 1) {
2455 I->replaceAllUsesWith(
Ops[0].
Op);
2457 OI->setDebugLoc(
I->getDebugLoc());
2458 RedoInsts.insert(
I);
2462 if (
Ops.size() > 2 &&
Ops.size() <= GlobalReassociateLimit) {
2470 unsigned BestRank = 0;
2471 std::pair<unsigned, unsigned> BestPair;
2472 unsigned Idx =
I->getOpcode() - Instruction::BinaryOpsBegin;
2473 unsigned LimitIdx = 0;
2483 int StartIdx =
Ops.size() - 1;
2488 for (
int i = StartIdx - 1; i != -1; --i) {
2492 if (!CurrLeafInstr) {
2517 FirstSeenBB = SeenBB;
2520 if (FirstSeenBB != SeenBB) {
2526 << LimitIdx <<
", " << StartIdx <<
"]\n");
2531 for (
unsigned i =
Ops.size() - 1; i > LimitIdx; --i) {
2533 for (
int j = i - 1;
j >= (int)LimitIdx; --
j) {
2537 if (std::less<Value *>()(Op1, Op0))
2539 auto it = PairMap[Idx].find({Op0, Op1});
2540 if (it != PairMap[Idx].
end()) {
2546 if (it->second.isValid())
2547 Score += it->second.Score;
2550 unsigned MaxRank = std::max(
Ops[i].Rank,
Ops[j].Rank);
2564 if (Score > Max || (Score == Max && MaxRank < BestRank)) {
2572 auto Op0 =
Ops[BestPair.first];
2573 auto Op1 =
Ops[BestPair.second];
2574 Ops.erase(&
Ops[BestPair.second]);
2575 Ops.erase(&
Ops[BestPair.first]);
2584 RewriteExprTree(
I,
Ops, Flags);
2588ReassociatePass::BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT) {
2590 for (BasicBlock *BI : RPOT) {
2591 for (Instruction &
I : *BI) {
2592 if (!
I.isAssociative() || !
I.isBinaryOp())
2596 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2602 SmallVector<Value *, 8> Worklist = {
I.getOperand(0),
I.getOperand(1) };
2603 SmallVector<Value *, 8>
Ops;
2604 while (!Worklist.
empty() &&
Ops.size() <= GlobalReassociateLimit) {
2618 if (
Ops.size() > GlobalReassociateLimit)
2622 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2623 SmallSet<std::pair<Value *, Value*>, 32> Visited;
2624 for (
unsigned i = 0; i <
Ops.size() - 1; ++i) {
2625 for (
unsigned j = i + 1;
j <
Ops.size(); ++
j) {
2629 if (std::less<Value *>()(Op1, Op0))
2631 if (!Visited.
insert({Op0, Op1}).second)
2633 auto res = PairMap[BinaryIdx].insert({{Op0, Op1}, {Op0, Op1, 1}});
2639 assert(res.first->second.isValid() &&
"WeakVH invalidated");
2640 ++res.first->second.Score;
2656 BuildRankMap(
F, RPOT);
2680 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2691 while (!ToRedo.
empty()) {
2694 RecursivelyEraseDeadInsts(
I, ToRedo);
2739 if (skipFunction(
F))
2743 auto PA = Impl.run(
F, DummyFAM);
2744 return !PA.areAllPreserved();
2747 void getAnalysisUsage(AnalysisUsage &AU)
const override {
2757char ReassociateLegacyPass::ID = 0;
2760 "Reassociate expressions",
false,
false)
2764 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,...
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.
static unsigned getFastMathFlags(const MachineInstr &I, const SPIRVSubtarget &ST)
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.
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)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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.