66using namespace PatternMatch;
68#define DEBUG_TYPE "reassociate"
70STATISTIC(NumChanged,
"Number of insts reassociated");
71STATISTIC(NumAnnihil,
"Number of expr tree annihilated");
72STATISTIC(NumFactor ,
"Number of multiplies factored");
76 cl::desc(
"Only reorder expressions within a basic block "
77 "when exposing CSE opportunities"),
85 << *Ops[0].Op->getType() <<
'\t';
88 Op.Op->printAsOperand(
dbgs(),
false, M);
89 dbgs() <<
", #" <<
Op.Rank <<
"] ";
106 bool isInvalid()
const {
return SymbolicPart ==
nullptr; }
120 unsigned SymbolicRank;
125 assert(!isa<ConstantInt>(V) &&
"No ConstantInt");
130 if (
I && (
I->getOpcode() == Instruction::Or ||
131 I->getOpcode() == Instruction::And)) {
132 Value *V0 =
I->getOperand(0);
133 Value *V1 =
I->getOperand(1);
141 isOr = (
I->getOpcode() == Instruction::Or);
157 assert(
I && isa<FPMathOperator>(
I) &&
"Should only check FP ops");
158 return I->hasAllowReassoc() &&
I->hasNoSignedZeros();
164 auto *BO = dyn_cast<BinaryOperator>(V);
165 if (BO && BO->hasOneUse() && BO->getOpcode() == Opcode)
173 auto *BO = dyn_cast<BinaryOperator>(V);
174 if (BO && BO->hasOneUse() &&
175 (BO->getOpcode() == Opcode1 || BO->getOpcode() == Opcode2))
181void ReassociatePass::BuildRankMap(
Function &
F,
186 for (
auto &Arg :
F.args()) {
187 ValueRankMap[&Arg] = ++Rank;
188 LLVM_DEBUG(
dbgs() <<
"Calculated Rank[" << Arg.getName() <<
"] = " << Rank
194 unsigned BBRank = RankMap[BB] = ++Rank << 16;
201 ValueRankMap[&
I] = ++BBRank;
205unsigned ReassociatePass::getRank(
Value *V) {
208 if (isa<Argument>(V))
return ValueRankMap[
V];
212 if (
unsigned Rank = ValueRankMap[
I])
219 unsigned Rank = 0, MaxRank = RankMap[
I->getParent()];
220 for (
unsigned i = 0, e =
I->getNumOperands(); i != e && Rank != MaxRank; ++i)
221 Rank = std::max(Rank, getRank(
I->getOperand(i)));
229 LLVM_DEBUG(
dbgs() <<
"Calculated Rank[" <<
V->getName() <<
"] = " << Rank
232 return ValueRankMap[
I] = Rank;
236void ReassociatePass::canonicalizeOperands(
Instruction *
I) {
237 assert(isa<BinaryOperator>(
I) &&
"Expected binary operator.");
238 assert(
I->isCommutative() &&
"Expected commutative operator.");
242 if (LHS == RHS || isa<Constant>(RHS))
244 if (isa<Constant>(LHS) || getRank(RHS) < getRank(LHS)) {
245 cast<BinaryOperator>(
I)->swapOperands();
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())
282 if (
auto *
FMFSource = dyn_cast<Instruction>(FlagsOp))
285 return UnaryOperator::CreateFNeg(
S1,
Name, InsertBefore);
290 assert((isa<UnaryOperator>(Neg) || isa<BinaryOperator>(Neg)) &&
291 "Expected a Negate!");
293 unsigned OpNo = isa<BinaryOperator>(Neg) ? 1 : 0;
386 assert((isa<UnaryOperator>(
I) || isa<BinaryOperator>(
I)) &&
387 "Expected a UnaryOperator or BinaryOperator!");
389 unsigned Opcode =
I->getOpcode();
390 assert(
I->isAssociative() &&
I->isCommutative() &&
391 "Expected an associative and commutative operation!");
405 bool Changed =
false;
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())
491 || (isa<FPMathOperator>(
Op) &&
493 "Should have been handled above!");
494 assert(
Op->hasOneUse() &&
"Has uses outside the expression tree!");
506 <<
"MORPH LEAF: " << *
Op <<
" (" << Weight <<
") TO ");
530 for (
Value *V : LeafOrder) {
531 LeafMap::iterator It = Leaves.find(V);
532 if (It == Leaves.end())
539 Ops.
push_back(std::make_pair(V, Weight));
540 if (Opcode == Instruction::Add && Flags.AllKnownNonNegative && Flags.HasNSW)
542 else if (Opcode == Instruction::Mul) {
545 if (Flags.AllKnownNonZero &&
546 (Flags.HasNUW || (Flags.HasNSW && Flags.AllKnownNonNegative))) {
548 if (Flags.HasNSW && Flags.AllKnownNonNegative)
559 assert(Identity &&
"Associative operation without identity!");
571 assert(Ops.
size() > 1 &&
"Single values should be used directly!");
585 unsigned Opcode =
I->getOpcode();
607 *ExpressionChangedEnd =
nullptr;
608 for (
unsigned i = 0; ; ++i) {
612 if (i+2 == Ops.size()) {
613 Value *NewLHS = Ops[i].Op;
614 Value *NewRHS = Ops[i+1].Op;
615 Value *OldLHS =
Op->getOperand(0);
616 Value *OldRHS =
Op->getOperand(1);
618 if (NewLHS == OldLHS && NewRHS == OldRHS)
622 if (NewLHS == OldRHS && NewRHS == OldLHS) {
635 if (NewLHS != OldLHS) {
637 if (BO && !NotRewritable.
count(BO))
639 Op->setOperand(0, NewLHS);
641 if (NewRHS != OldRHS) {
643 if (BO && !NotRewritable.
count(BO))
645 Op->setOperand(1, NewRHS);
649 ExpressionChangedStart =
Op;
650 if (!ExpressionChangedEnd)
651 ExpressionChangedEnd =
Op;
660 Value *NewRHS = Ops[i].Op;
661 if (NewRHS !=
Op->getOperand(1)) {
663 if (NewRHS ==
Op->getOperand(0)) {
670 if (BO && !NotRewritable.
count(BO))
672 Op->setOperand(1, NewRHS);
673 ExpressionChangedStart =
Op;
674 if (!ExpressionChangedEnd)
675 ExpressionChangedEnd =
Op;
686 if (BO && !NotRewritable.
count(BO)) {
699 if (NodesToRewrite.
empty()) {
703 if (isa<FPMathOperator>(NewOp))
710 Op->setOperand(0, NewOp);
712 ExpressionChangedStart =
Op;
713 if (!ExpressionChangedEnd)
714 ExpressionChangedEnd =
Op;
724 if (ExpressionChangedStart) {
725 bool ClearFlags =
true;
729 if (isa<FPMathOperator>(
I)) {
734 Flags.applyFlags(*ExpressionChangedStart);
738 if (ExpressionChangedStart == ExpressionChangedEnd)
740 if (ExpressionChangedStart ==
I)
750 ExpressionChangedStart->
moveBefore(
I->getIterator());
751 ExpressionChangedStart =
752 cast<BinaryOperator>(*ExpressionChangedStart->
user_begin());
757 RedoInsts.insert_range(NodesToRewrite);
769 if (
auto *
C = dyn_cast<Constant>(V)) {
771 Constant *Res =
C->getType()->isFPOrFPVectorTy()
792 if (
I->getOpcode() == Instruction::Add) {
793 I->setHasNoUnsignedWrap(
false);
794 I->setHasNoSignedWrap(
false);
803 I->setName(
I->getName()+
".neg");
813 for (
User *U : V->users()) {
826 C->containsUndefOrPoisonElement())
835 if (
Instruction *InstInput = dyn_cast<Instruction>(V)) {
836 auto InsertPtOpt = InstInput->getInsertionPointAfterDef();
839 InsertPt = *InsertPtOpt;
850 if (TheNeg->
getParent() != InsertPt->getParent())
852 TheNeg->
moveBefore(*InsertPt->getParent(), InsertPt);
854 if (TheNeg->
getOpcode() == Instruction::Sub) {
883 auto Enqueue = [&](
Value *V) {
884 auto *
I = dyn_cast<Instruction>(V);
897 while (!Worklist.
empty()) {
901 switch (
I->getOpcode()) {
902 case Instruction::Or:
909 case Instruction::Shl:
910 case Instruction::ZExt:
912 if (!Enqueue(
I->getOperand(0)))
916 case Instruction::Load:
934 for (
auto Op : {Instruction::Add, Instruction::Sub, Instruction::Mul,
956 Or->getIterator(),
Or);
957 New->setHasNoSignedWrap();
958 New->setHasNoUnsignedWrap();
962 Or->replaceAllUsesWith(New);
963 New->setDebugLoc(
Or->getDebugLoc());
965 LLVM_DEBUG(
dbgs() <<
"Converted or into an add: " << *New <<
'\n');
976 if (isa<UndefValue>(
Sub->getOperand(1)))
990 if (
Sub->hasOneUse() &&
1015 Sub->replaceAllUsesWith(New);
1016 New->setDebugLoc(
Sub->getDebugLoc());
1026 auto *SA = cast<ConstantInt>(Shl->
getOperand(1));
1028 assert(MulCst &&
"Constant folding of immediate constants failed");
1043 bool NSW = cast<BinaryOperator>(Shl)->hasNoSignedWrap();
1044 bool NUW = cast<BinaryOperator>(Shl)->hasNoUnsignedWrap();
1046 if (NSW && (NUW || SA->getValue().ult(
BitWidth - 1)))
1047 Mul->setHasNoSignedWrap(
true);
1048 Mul->setHasNoUnsignedWrap(NUW);
1057 unsigned XRank = Ops[i].Rank;
1058 unsigned e = Ops.
size();
1059 for (
unsigned j = i+1; j != e && Ops[j].Rank == XRank; ++j) {
1064 if (I1->isIdenticalTo(I2))
1068 for (
unsigned j = i-1; j != ~0U && Ops[j].Rank == XRank; --j) {
1073 if (I1->isIdenticalTo(I2))
1083 if (Ops.
size() == 1)
return Ops.
back();
1087 auto *NewAdd =
CreateAdd(V2, V1,
"reass.add",
I->getIterator(),
I);
1088 NewAdd->setDebugLoc(
I->getDebugLoc());
1111 bool FoundFactor =
false;
1112 bool NeedsNegate =
false;
1113 for (
unsigned i = 0, e = Factors.
size(); i != e; ++i) {
1122 if (
ConstantInt *FC2 = dyn_cast<ConstantInt>(Factors[i].
Op))
1123 if (FC1->getValue() == -FC2->getValue()) {
1124 FoundFactor = NeedsNegate =
true;
1129 if (
ConstantFP *FC2 = dyn_cast<ConstantFP>(Factors[i].
Op)) {
1130 const APFloat &F1 = FC1->getValueAPF();
1131 APFloat F2(FC2->getValueAPF());
1134 FoundFactor = NeedsNegate =
true;
1144 RewriteExprTree(BO, Factors, Flags);
1152 if (Factors.
size() == 1) {
1153 RedoInsts.insert(BO);
1156 RewriteExprTree(BO, Factors, Flags);
1162 cast<Instruction>(V)->setDebugLoc(
DL);
1192 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1199 if (Opcode == Instruction::And)
1202 if (Opcode == Instruction::Or)
1210 if (i+1 != Ops.
size() && Ops[i+1].Op == Ops[i].Op) {
1211 if (Opcode == Instruction::And || Opcode == Instruction::Or) {
1220 assert(Opcode == Instruction::Xor);
1239 const APInt &ConstOpnd) {
1247 Opnd, ConstantInt::get(Opnd->
getType(), ConstOpnd),
"and.ra",
1249 I->setDebugLoc(InsertBefore->getDebugLoc());
1272 if (C1 != ConstOpnd)
1281 RedoInsts.insert(
T);
1301 int DeadInstNum = 1;
1319 APInt C3((~C1) ^ C2);
1322 if (!C3.isZero() && !C3.isAllOnes()) {
1324 if (NewInstNum > DeadInstNum)
1340 if (NewInstNum > DeadInstNum)
1358 RedoInsts.insert(
T);
1360 RedoInsts.insert(
T);
1373 if (Ops.
size() == 1)
1378 Type *Ty = Ops[0].Op->getType();
1390 O.setSymbolicRank(getRank(
O.getSymbolicPart()));
1417 return LHS->getSymbolicRank() <
RHS->getSymbolicRank();
1422 bool Changed =
false;
1423 for (
unsigned i = 0, e = Opnds.size(); i < e; i++) {
1424 XorOpnd *CurrOpnd = OpndPtrs[i];
1429 if (!ConstOpnd.
isZero() &&
1430 CombineXorOpnd(
I->getIterator(), CurrOpnd, ConstOpnd, CV)) {
1440 if (!PrevOpnd || CurrOpnd->
getSymbolicPart() != PrevOpnd->getSymbolicPart()) {
1441 PrevOpnd = CurrOpnd;
1447 if (CombineXorOpnd(
I->getIterator(), CurrOpnd, PrevOpnd, ConstOpnd, CV)) {
1452 PrevOpnd = CurrOpnd;
1464 for (
const XorOpnd &O : Opnds) {
1470 if (!ConstOpnd.
isZero()) {
1471 Value *
C = ConstantInt::get(Ty, ConstOpnd);
1475 unsigned Sz = Ops.size();
1477 return Ops.back().Op;
1480 return ConstantInt::get(Ty, ConstOpnd);
1497 for (
unsigned i = 0, e = Ops.
size(); i != e; ++i) {
1498 Value *TheOp = Ops[i].Op;
1502 if (i+1 != Ops.
size() && Ops[i+1].Op == TheOp) {
1504 unsigned NumFound = 0;
1508 }
while (i != Ops.
size() && Ops[i].Op == TheOp);
1510 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << NumFound <<
"]: " << *TheOp
1517 ConstantInt::get(Ty, NumFound) :
ConstantFP::
get(Ty, NumFound);
1519 Mul->setDebugLoc(
I->getDebugLoc());
1524 RedoInsts.insert(
Mul);
1551 if (Ops.
size() == 2 &&
1586 unsigned MaxOcc = 0;
1587 Value *MaxOccVal =
nullptr;
1597 assert(Factors.
size() > 1 &&
"Bad linearize!");
1605 unsigned Occ = ++FactorOccurrences[
Factor];
1615 if (CI->isNegative() && !CI->isMinValue(
true)) {
1616 Factor = ConstantInt::get(CI->getContext(), -CI->getValue());
1619 unsigned Occ = ++FactorOccurrences[
Factor];
1626 if (CF->isNegative()) {
1629 Factor = ConstantFP::get(CF->getContext(),
F);
1632 unsigned Occ = ++FactorOccurrences[
Factor];
1644 LLVM_DEBUG(
dbgs() <<
"\nFACTORING [" << MaxOcc <<
"]: " << *MaxOccVal
1653 I->getType()->isIntOrIntVectorTy()
1654 ? BinaryOperator::CreateAdd(MaxOccVal, MaxOccVal)
1658 for (
unsigned i = 0; i != Ops.size(); ++i) {
1665 if (
Value *V = RemoveFactorFromExpression(Ops[i].
Op, MaxOccVal,
1666 I->getDebugLoc())) {
1669 for (
unsigned j = Ops.size(); j != i;) {
1671 if (Ops[j].
Op == Ops[i].
Op) {
1673 Ops.erase(Ops.begin()+j);
1683 unsigned NumAddedValues = NewMulOps.
size();
1689 assert(NumAddedValues > 1 &&
"Each occurrence should contribute a value");
1690 (void)NumAddedValues;
1692 RedoInsts.insert(VI);
1700 RedoInsts.insert(V2);
1710 Ops.insert(Ops.begin(),
ValueEntry(getRank(V2), V2));
1731 unsigned FactorPowerSum = 0;
1741 FactorPowerSum += Count;
1748 if (FactorPowerSum < 4)
1765 FactorPowerSum += Count;
1772 assert(FactorPowerSum >= 4);
1775 return LHS.Power >
RHS.Power;
1783 if (Ops.
size() == 1)
1792 }
while (!Ops.
empty());
1804ReassociatePass::buildMinimalMultiplyDAG(
IRBuilderBase &Builder,
1806 assert(Factors[0].Power);
1808 for (
unsigned LastIdx = 0,
Idx = 1,
Size = Factors.
size();
1810 if (Factors[
Idx].Power != Factors[LastIdx].Power) {
1823 }
while (
Idx <
Size && Factors[
Idx].Power == Factors[LastIdx].Power);
1829 RedoInsts.insert(
MI);
1837 return LHS.Power ==
RHS.Power;
1849 if (Factors[0].Power) {
1850 Value *SquareRoot = buildMinimalMultiplyDAG(Builder, Factors);
1854 if (OuterProduct.
size() == 1)
1855 return OuterProduct.
front();
1879 if (
auto FPI = dyn_cast<FPMathOperator>(
I))
1882 Value *
V = buildMinimalMultiplyDAG(Builder, Factors);
1897 unsigned Opcode =
I->getOpcode();
1898 while (!Ops.
empty()) {
1899 if (
auto *
C = dyn_cast<Constant>(Ops.
back().Op)) {
1926 if (Ops.
size() == 1)
return Ops[0].Op;
1930 unsigned NumOps = Ops.
size();
1933 case Instruction::And:
1934 case Instruction::Or:
1939 case Instruction::Xor:
1940 if (
Value *Result = OptimizeXor(
I, Ops))
1944 case Instruction::Add:
1945 case Instruction::FAdd:
1946 if (
Value *Result = OptimizeAdd(
I, Ops))
1950 case Instruction::Mul:
1951 case Instruction::FMul:
1952 if (
Value *Result = OptimizeMul(
I, Ops))
1957 if (Ops.
size() != NumOps)
1958 return OptimizeExpression(
I, Ops);
1964void ReassociatePass::RecursivelyEraseDeadInsts(
Instruction *
I,
1965 OrderedSet &Insts) {
1968 ValueRankMap.erase(
I);
1970 RedoInsts.remove(
I);
1972 I->eraseFromParent();
1973 for (
auto *
Op : Ops)
1975 if (OpInst->use_empty())
1976 Insts.insert(OpInst);
1986 ValueRankMap.erase(
I);
1987 RedoInsts.remove(
I);
1989 I->eraseFromParent();
1992 for (
Value *V : Ops)
1996 unsigned Opcode =
Op->getOpcode();
1997 while (
Op->hasOneUse() &&
Op->user_back()->getOpcode() == Opcode &&
1999 Op =
Op->user_back();
2006 if (ValueRankMap.contains(
Op))
2007 RedoInsts.insert(
Op);
2027 switch (
I->getOpcode()) {
2028 case Instruction::FMul:
2040 case Instruction::FDiv:
2065 assert((
I->getOpcode() == Instruction::FAdd ||
2066 I->getOpcode() == Instruction::FSub) &&
"Expected fadd/fsub");
2072 if (Candidates.
empty())
2078 bool IsFSub =
I->getOpcode() == Instruction::FSub;
2079 bool NeedsSubtract = !IsFSub && Candidates.
size() % 2 == 1;
2087 "Expecting only 1 constant operand");
2088 assert(
C->isNegative() &&
"Expected negative FP constant");
2089 Negatible->setOperand(0, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2094 "Expecting only 1 constant operand");
2095 assert(
C->isNegative() &&
"Expected negative FP constant");
2096 Negatible->setOperand(1, ConstantFP::get(Negatible->getType(),
abs(*
C)));
2100 assert(MadeChange ==
true &&
"Negative constant candidate was not changed");
2103 if (Candidates.size() % 2 == 0)
2108 assert(Candidates.size() % 2 == 1 &&
"Expected odd number");
2112 I->replaceAllUsesWith(NewInst);
2113 RedoInsts.insert(
I);
2114 return dyn_cast<Instruction>(NewInst);
2145 if (!isa<UnaryOperator>(
I) && !isa<BinaryOperator>(
I))
2148 if (
I->getOpcode() == Instruction::Shl && isa<ConstantInt>(
I->getOperand(1)))
2156 RedoInsts.insert(
I);
2164 if (
I->isCommutative())
2165 canonicalizeOperands(
I);
2183 if (
I->getType()->isIntOrIntVectorTy(1))
2188 if (
I->getOpcode() == Instruction::Or &&
2190 (cast<PossiblyDisjointInst>(
I)->isDisjoint() ||
2193 nullptr,
nullptr,
I)))) {
2195 RedoInsts.insert(
I);
2202 if (
I->getOpcode() == Instruction::Sub) {
2205 RedoInsts.insert(
I);
2219 RedoInsts.insert(Tmp);
2221 RedoInsts.insert(
I);
2226 }
else if (
I->getOpcode() == Instruction::FNeg ||
2227 I->getOpcode() == Instruction::FSub) {
2230 RedoInsts.insert(
I);
2236 Value *
Op = isa<BinaryOperator>(
I) ?
I->getOperand(1) :
2246 RedoInsts.insert(Tmp);
2248 RedoInsts.insert(
I);
2256 if (!
I->isAssociative())
return;
2275 cast<Instruction>(BO->
user_back())->getOpcode() == Instruction::Sub)
2278 cast<Instruction>(BO->
user_back())->getOpcode() == Instruction::FSub)
2281 ReassociateExpression(BO);
2307 if (
Value *V = OptimizeExpression(
I, Ops)) {
2314 I->replaceAllUsesWith(V);
2316 if (
I->getDebugLoc())
2317 VI->setDebugLoc(
I->getDebugLoc());
2318 RedoInsts.insert(
I);
2327 if (
I->hasOneUse()) {
2328 if (
I->getOpcode() == Instruction::Mul &&
2329 cast<Instruction>(
I->user_back())->getOpcode() == Instruction::Add &&
2330 isa<ConstantInt>(Ops.
back().Op) &&
2331 cast<ConstantInt>(Ops.
back().Op)->isMinusOne()) {
2334 }
else if (
I->getOpcode() == Instruction::FMul &&
2335 cast<Instruction>(
I->user_back())->getOpcode() ==
2336 Instruction::FAdd &&
2337 isa<ConstantFP>(Ops.
back().Op) &&
2338 cast<ConstantFP>(Ops.
back().Op)->isExactlyValue(-1.0)) {
2346 if (Ops.
size() == 1) {
2353 I->replaceAllUsesWith(Ops[0].
Op);
2355 OI->setDebugLoc(
I->getDebugLoc());
2356 RedoInsts.insert(
I);
2360 if (Ops.
size() > 2 && Ops.
size() <= GlobalReassociateLimit) {
2368 unsigned BestRank = 0;
2369 std::pair<unsigned, unsigned> BestPair;
2370 unsigned Idx =
I->getOpcode() - Instruction::BinaryOpsBegin;
2371 unsigned LimitIdx = 0;
2381 int StartIdx = Ops.
size() - 1;
2386 for (
int i = StartIdx - 1; i != -1; --i) {
2387 const Value *Val = Ops[i].Op;
2388 const auto *CurrLeafInstr = dyn_cast<Instruction>(Val);
2390 if (!CurrLeafInstr) {
2409 SeenBB = &
I->getParent()->getParent()->getEntryBlock();
2415 FirstSeenBB = SeenBB;
2418 if (FirstSeenBB != SeenBB) {
2424 << LimitIdx <<
", " << StartIdx <<
"]\n");
2429 for (
unsigned i = Ops.
size() - 1; i > LimitIdx; --i) {
2431 for (
int j = i - 1;
j >= (int)LimitIdx; --
j) {
2433 Value *Op0 = Ops[i].Op;
2435 if (std::less<Value *>()(Op1, Op0))
2437 auto it = PairMap[
Idx].find({Op0, Op1});
2438 if (it != PairMap[
Idx].
end()) {
2444 if (it->second.isValid())
2445 Score += it->second.Score;
2448 unsigned MaxRank = std::max(Ops[i].Rank, Ops[j].Rank);
2462 if (Score > Max || (Score == Max && MaxRank < BestRank)) {
2470 auto Op0 = Ops[BestPair.first];
2471 auto Op1 = Ops[BestPair.second];
2472 Ops.
erase(&Ops[BestPair.second]);
2473 Ops.
erase(&Ops[BestPair.first]);
2482 RewriteExprTree(
I, Ops, Flags);
2490 if (!
I.isAssociative() || !
I.isBinaryOp())
2494 if (
I.hasOneUse() &&
I.user_back()->getOpcode() ==
I.getOpcode())
2502 while (!Worklist.
empty() && Ops.
size() <= GlobalReassociateLimit) {
2516 if (Ops.
size() > GlobalReassociateLimit)
2520 unsigned BinaryIdx =
I.getOpcode() - Instruction::BinaryOpsBegin;
2522 for (
unsigned i = 0; i < Ops.
size() - 1; ++i) {
2523 for (
unsigned j = i + 1;
j < Ops.
size(); ++
j) {
2525 Value *Op0 = Ops[i];
2527 if (std::less<Value *>()(Op1, Op0))
2529 if (!Visited.
insert({Op0, Op1}).second)
2531 auto res = PairMap[BinaryIdx].insert({{Op0, Op1}, {Op0, Op1, 1}});
2537 assert(res.first->second.isValid() &&
"WeakVH invalidated");
2538 ++res.first->second.Score;
2554 BuildRankMap(
F, RPOT);
2571 assert(RankMap.count(&*BI) &&
"BB should be ranked.");
2578 assert(
II->getParent() == &*BI &&
"Moved to a different block!");
2589 while (!ToRedo.
empty()) {
2592 RecursivelyEraseDeadInsts(
I, ToRedo);
2599 while (!RedoInsts.empty()) {
2601 RedoInsts.erase(RedoInsts.begin());
2611 ValueRankMap.clear();
2612 for (
auto &Entry : PairMap)
2637 if (skipFunction(
F))
2641 auto PA = Impl.
run(
F, DummyFAM);
2655char ReassociateLegacyPass::ID = 0;
2658 "Reassociate expressions",
false,
false)
2662 return new ReassociateLegacyPass();
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.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This is the interface for a simple mod/ref and alias analysis over globals.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
static bool isReassociableOp(Instruction *I, unsigned IntOpcode, unsigned FPOpcode)
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
static bool LinearizeExprTree(Instruction *I, SmallVectorImpl< RepeatedValue > &Ops, ReassociatePass::OrderedSet &ToRedo, OverflowTracking &Flags)
Given an associative binary expression, return the leaf nodes in Ops along with their weights (how ma...
static void PrintOps(Instruction *I, const SmallVectorImpl< ValueEntry > &Ops)
Print out the expression identified in the Ops list.
static bool ShouldBreakUpSubtract(Instruction *Sub)
Return true if we should break up this subtract of X-Y into (X + -Y).
static Value * buildMultiplyTree(IRBuilderBase &Builder, SmallVectorImpl< Value * > &Ops)
Build a tree of multiplies, computing the product of Ops.
static void getNegatibleInsts(Value *V, SmallVectorImpl< Instruction * > &Candidates)
Recursively analyze an expression to build a list of instructions that have negative floating-point c...
static BinaryOperator * CreateMul(Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static BinaryOperator * BreakUpSubtract(Instruction *Sub, ReassociatePass::OrderedSet &ToRedo)
If we have (X-Y), and if either X is an add, or if this is only used by an add, transform this into (...
static void FindSingleUseMultiplyFactors(Value *V, SmallVectorImpl< Value * > &Factors)
If V is a single-use multiply, recursively add its operands as factors, otherwise add V to the list o...
std::pair< Value *, uint64_t > RepeatedValue
static Value * OptimizeAndOrXor(unsigned Opcode, SmallVectorImpl< ValueEntry > &Ops)
Optimize a series of operands to an 'and', 'or', or 'xor' instruction.
static BinaryOperator * convertOrWithNoCommonBitsToAdd(Instruction *Or)
If we have (X|Y), and iff X and Y have no common bits set, transform this into (X+Y) to allow arithme...
static BinaryOperator * CreateAdd(Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static bool collectMultiplyFactors(SmallVectorImpl< ValueEntry > &Ops, SmallVectorImpl< Factor > &Factors)
Build up a vector of value/power pairs factoring a product.
static BinaryOperator * ConvertShiftToMul(Instruction *Shl)
If this is a shift of a reassociable multiply or is used by one, change this into a multiply by a con...
static cl::opt< bool > UseCSELocalOpt(DEBUG_TYPE "-use-cse-local", cl::desc("Only reorder expressions within a basic block " "when exposing CSE opportunities"), cl::init(true), cl::Hidden)
static unsigned FindInOperandList(const SmallVectorImpl< ValueEntry > &Ops, unsigned i, Value *X)
Scan backwards and forwards among values with the same rank as element i to see if X exists.
static BinaryOperator * LowerNegateToMultiply(Instruction *Neg)
Replace 0-X with X*-1.
static Instruction * CreateNeg(Value *S1, const Twine &Name, BasicBlock::iterator InsertBefore, Value *FlagsOp)
static bool hasFPAssociativeFlags(Instruction *I)
Return true if I is an instruction with the FastMathFlags that are needed for general reassociation s...
static Value * createAndInstr(BasicBlock::iterator InsertBefore, Value *Opnd, const APInt &ConstOpnd)
Helper function of CombineXorOpnd().
static Value * NegateValue(Value *V, Instruction *BI, ReassociatePass::OrderedSet &ToRedo)
Insert instructions before the instruction pointed to by BI, that computes the negative version of th...
static bool shouldConvertOrWithNoCommonBitsToAdd(Instruction *Or)
Return true if it may be profitable to convert this (X|Y) into (X+Y).
static bool isLoadCombineCandidate(Instruction *Or)
static Value * EmitAddTreeOfValues(Instruction *I, SmallVectorImpl< WeakTrackingVH > &Ops)
Emit a tree of add instructions, summing Ops together and returning the result.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Class for arbitrary precision integers.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
bool getBoolValue() const
Convert APInt to a boolean value.
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Legacy wrapper pass to provide the BasicAAResult object.
LLVM Basic Block Representation.
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,...
const Function * getParent() const
Return the enclosing method, or null if none.
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)
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
This provides a helper for copying FMF from an instruction or setting specified flags.
Convenience struct for specifying and reasoning about fast-math flags.
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & getEntryBlock() const
Legacy wrapper pass to provide the GlobalsAAResult object.
Common base class shared among various IRBuilders.
Value * 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)
Value * CreateFMul(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void setHasNoUnsignedWrap(bool b=true)
Set or clear the nuw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag.
LLVM_ABI void dropLocation()
Drop the instruction's debug location.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void andIRFlags(const Value *V)
Logical 'and' of any supported wrapping, exact, and fast-math flags of V and this instruction.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI void setFastMathFlags(FastMathFlags FMF)
Convenience function for setting multiple fast-math flags on this instruction, which must be an opera...
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
const char * getOpcodeName() const
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
bool areAllPreserved() const
Test whether all analyses are preserved (and none are abandoned).
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Reassociate commutative expressions.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
static UnaryOperator * CreateFNegFMF(Value *Op, Instruction *FMFSource, const Twine &Name="", InsertPosition InsertBefore=nullptr)
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
void clearSubclassOptionalData()
Clear the optional flags contained in this value.
LLVM_ABI void deleteValue()
Delete a pointer to a generic Value.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
const ParentTy * getParent() const
self_iterator getIterator()
Utility class representing a non-constant Xor-operand.
Value * getSymbolicPart() const
unsigned getSymbolicRank() const
void setSymbolicRank(unsigned R)
const APInt & getConstPart() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
BinaryOp_match< SpecificConstantMatch, SrcTy, TargetOpcode::G_SUB > m_Neg(const SrcTy &&Src)
Matches a register negated by a G_SUB.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
class_match< BinaryOperator > m_BinOp()
Match an arbitrary binary operation and ignore it.
BinaryOp_match< LHS, RHS, Instruction::FSub > m_FSub(const LHS &L, const RHS &R)
class_match< Constant > m_Constant()
Match an arbitrary Constant and ignore it.
bool match(Val *V, const Pattern &P)
bind_ty< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
BinaryOp_match< LHS, RHS, Instruction::FAdd > m_FAdd(const LHS &L, const RHS &R)
apint_match m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
apfloat_match m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
initializer< Ty > init(const Ty &Val)
LLVM_ABI const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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)
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.
LLVM_ABI void initializeReassociateLegacyPassPass(PassRegistry &)
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.
LLVM_ABI FunctionPass * createReassociatePass()
LLVM_ABI bool replaceDbgUsesWithUndef(Instruction *I)
Replace all the uses of an SSA value in @llvm.dbg intrinsics with undef.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
@ Mul
Product of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
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.