5074 ScalarEvolution &SE, LoopInfo &LI,
5075 const DataLayout &DL) {
5076 auto push = [&](llvm::Value *V) {
5080 if (
auto I = dyn_cast<Instruction>(V)) {
5082 for (
auto U : I->users()) {
5083 if (
auto I2 = dyn_cast<Instruction>(U)) {
5092 auto pushcse = [&](llvm::Value *V) -> llvm::Value * {
5093 if (
auto I = dyn_cast<Instruction>(V)) {
5094 for (
size_t i = 0; i < I->getNumOperands(); i++) {
5095 if (
auto I2 = dyn_cast<Instruction>(I->getOperand(i))) {
5096 Instruction *candidate =
nullptr;
5097 for (
auto U : I2->users()) {
5098 candidate = dyn_cast<Instruction>(U);
5101 if (candidate == I && candidate->getType() != I->getType()) {
5102 candidate =
nullptr;
5105 bool isSame = candidate->isIdenticalTo(I);
5109 std::multiset<llvm::Value *> s1;
5110 std::multiset<llvm::Value *> s2;
5117 if (
auto P1 =
isSum(I))
5118 if (
auto P2 =
isSum(I2)) {
5119 std::multiset<llvm::Value *> s1;
5120 std::multiset<llvm::Value *> s2;
5129 candidate =
nullptr;
5133 if (DT.dominates(candidate, I)) {
5136 candidate =
nullptr;
5139 I->eraseFromParent();
5149 auto replaceAndErase = [&](llvm::Instruction *I, llvm::Value *candidate) {
5150 for (
auto U : I->users())
5152 I->replaceAllUsesWith(candidate);
5155 SetVector<Instruction *> operands;
5156 for (
size_t i = 0; i < I->getNumOperands(); i++) {
5157 if (
auto I2 = dyn_cast<Instruction>(I->getOperand(i))) {
5158 if ((!I2->mayWriteToMemory() ||
5159 (isa<CallInst>(I2) &&
isReadOnly(cast<CallInst>(I2)))))
5160 operands.insert(I2);
5167 I->eraseFromParent();
5168 for (
auto op : operands)
5169 if (op->getNumUses() == 0) {
5172 op->eraseFromParent();
5175 if (!cur->getType()->isVoidTy() &&
5176 (!cur->mayWriteToMemory() ||
5177 (isa<CallInst>(cur) &&
isReadOnly(cast<CallInst>(cur))))) {
5179 if (cur->getNumUses() == 0) {
5180 for (
size_t i = 0; i < cur->getNumOperands(); i++)
5181 push(cur->getOperand(i));
5183 cur->eraseFromParent();
5188 for (
size_t i = 0; i < cur->getNumOperands(); i++) {
5189 if (
auto I = dyn_cast<Instruction>(cur->getOperand(i))) {
5190 Instruction *candidate =
nullptr;
5191 bool reverse =
false;
5192 for (
auto U : I->users()) {
5193 candidate = dyn_cast<Instruction>(U);
5196 if (candidate == cur && candidate->getType() != cur->getType()) {
5197 candidate =
nullptr;
5200 bool isSame = candidate->isIdenticalTo(cur);
5204 std::multiset<llvm::Value *> s1;
5205 std::multiset<llvm::Value *> s2;
5212 if (
auto P1 =
isSum(candidate))
5213 if (
auto P2 =
isSum(cur)) {
5214 std::multiset<llvm::Value *> s1;
5215 std::multiset<llvm::Value *> s2;
5225 candidate =
nullptr;
5229 if (DT.dominates(candidate, cur)) {
5231 }
else if (DT.dominates(cur, candidate)) {
5235 candidate =
nullptr;
5241 auto tmp = candidate;
5245 replaceAndErase(cur, candidate);
5254 if (
auto SI = dyn_cast<SelectInst>(cur))
5255 if (
auto CI = dyn_cast<ConstantInt>(SI->getCondition())) {
5257 replaceAndErase(cur, SI->getTrueValue());
5258 return "SelectToTrue";
5260 replaceAndErase(cur, SI->getFalseValue());
5261 return "SelectToFalse";
5264 if (cur->getOpcode() == Instruction::Or) {
5265 for (
int i = 0; i < 2; i++) {
5266 if (
auto C = dyn_cast<ConstantInt>(cur->getOperand(i))) {
5269 replaceAndErase(cur, cur->getOperand(1 - i));
5273 if (C->isOne() && cur->getType()->isIntegerTy(1)) {
5274 replaceAndErase(cur, C);
5280 if (cur->getOpcode() == Instruction::And) {
5281 for (
int i = 0; i < 2; i++) {
5282 if (
auto C = dyn_cast<ConstantInt>(cur->getOperand(i))) {
5284 if (C->isOne() && cur->getType()->isIntegerTy(1)) {
5285 replaceAndErase(cur, cur->getOperand(1 - i));
5290 replaceAndErase(cur, C);
5298 if (
auto CI = dyn_cast<CastInst>(cur))
5299 if (
auto C = dyn_cast<Constant>(CI->getOperand(0))) {
5301 cur, cast<Constant>(B.CreateCast(CI->getOpcode(), C, CI->getType())));
5302 return "CastConstProp";
5304 std::function<Value *(Value *, Value *, Value *)> replace = [&](Value *val,
5310 if (
isNot(val, orig)) {
5311 return pushcse(B.CreateNot(with));
5313 if (isa<PHINode>(val))
5316 if (
auto I = dyn_cast<Instruction>(val)) {
5317 if (I->mayWriteToMemory() &&
5318 !(isa<CallInst>(I) &&
isReadOnly(cast<CallInst>(I))))
5321 if (I->getOpcode() == Instruction::Add) {
5322 Value *lhs = replace(I->getOperand(0), orig, with);
5323 Value *rhs = replace(I->getOperand(1), orig, with);
5324 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5327 return pushcse(B.CreateAdd(lhs, rhs,
"sel." + I->getName(),
5328 I->hasNoUnsignedWrap(),
5329 I->hasNoSignedWrap()));
5332 if (I->getOpcode() == Instruction::Sub) {
5333 Value *lhs = replace(I->getOperand(0), orig, with);
5334 Value *rhs = replace(I->getOperand(1), orig, with);
5335 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5338 return pushcse(B.CreateSub(lhs, rhs,
"sel." + I->getName(),
5339 I->hasNoUnsignedWrap(),
5340 I->hasNoSignedWrap()));
5343 if (I->getOpcode() == Instruction::Mul) {
5344 Value *lhs = replace(I->getOperand(0), orig, with);
5345 Value *rhs = replace(I->getOperand(1), orig, with);
5346 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5349 return pushcse(B.CreateMul(lhs, rhs,
"sel." + I->getName(),
5350 I->hasNoUnsignedWrap(),
5351 I->hasNoSignedWrap()));
5354 if (I->getOpcode() == Instruction::And) {
5355 Value *lhs = replace(I->getOperand(0), orig, with);
5356 Value *rhs = replace(I->getOperand(1), orig, with);
5357 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5360 return pushcse(B.CreateAnd(lhs, rhs,
"sel." + I->getName()));
5363 if (I->getOpcode() == Instruction::Or) {
5364 Value *lhs = replace(I->getOperand(0), orig, with);
5365 Value *rhs = replace(I->getOperand(1), orig, with);
5366 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5369 return pushcse(B.CreateOr(lhs, rhs,
"sel." + I->getName()));
5372 if (I->getOpcode() == Instruction::Xor) {
5373 Value *lhs = replace(I->getOperand(0), orig, with);
5374 Value *rhs = replace(I->getOperand(1), orig, with);
5375 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5378 return pushcse(B.CreateXor(lhs, rhs,
"sel." + I->getName()));
5381 if (I->getOpcode() == Instruction::FAdd) {
5382 Value *lhs = replace(I->getOperand(0), orig, with);
5383 Value *rhs = replace(I->getOperand(1), orig, with);
5384 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5387 return pushcse(B.CreateFAddFMF(lhs, rhs, I,
"sel." + I->getName()));
5390 if (I->getOpcode() == Instruction::FSub) {
5391 Value *lhs = replace(I->getOperand(0), orig, with);
5392 Value *rhs = replace(I->getOperand(1), orig, with);
5393 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5396 return pushcse(B.CreateFSubFMF(lhs, rhs, I,
"sel." + I->getName()));
5399 if (I->getOpcode() == Instruction::FMul) {
5400 Value *lhs = replace(I->getOperand(0), orig, with);
5401 Value *rhs = replace(I->getOperand(1), orig, with);
5402 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5405 return pushcse(B.CreateFMulFMF(lhs, rhs, I,
"sel." + I->getName()));
5408 if (I->getOpcode() == Instruction::ZExt) {
5409 Value *op = replace(I->getOperand(0), orig, with);
5410 if (op == I->getOperand(0))
5413 return pushcse(B.CreateZExt(op, I->getType(),
"sel." + I->getName()));
5416 if (I->getOpcode() == Instruction::SExt) {
5417 Value *op = replace(I->getOperand(0), orig, with);
5418 if (op == I->getOperand(0))
5421 return pushcse(B.CreateSExt(op, I->getType(),
"sel." + I->getName()));
5424 if (I->getOpcode() == Instruction::UIToFP) {
5425 Value *op = replace(I->getOperand(0), orig, with);
5426 if (op == I->getOperand(0))
5429 return pushcse(B.CreateUIToFP(op, I->getType(),
"sel." + I->getName()));
5432 if (I->getOpcode() == Instruction::SIToFP) {
5433 Value *op = replace(I->getOperand(0), orig, with);
5434 if (op == I->getOperand(0))
5437 return pushcse(B.CreateSIToFP(op, I->getType(),
"sel." + I->getName()));
5440 if (
auto CI = dyn_cast<CmpInst>(I)) {
5441 Value *lhs = replace(I->getOperand(0), orig, with);
5442 Value *rhs = replace(I->getOperand(1), orig, with);
5443 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
5447 B.CreateCmp(CI->getPredicate(), lhs, rhs,
"sel." + I->getName()));
5450 if (
auto SI = dyn_cast<SelectInst>(I)) {
5451 Value *cond = replace(SI->getCondition(), orig, with);
5452 Value *tval = replace(SI->getTrueValue(), orig, with);
5453 Value *fval = replace(SI->getFalseValue(), orig, with);
5454 if (cond == SI->getCondition() && tval == SI->getTrueValue() &&
5455 fval == SI->getFalseValue())
5458 if (
auto CI = dyn_cast<ConstantInt>(cond)) {
5464 return pushcse(B.CreateSelect(cond, tval, fval,
"sel." + I->getName()));
5468 auto C = cast<CallBase>(I);
5470 bool changed =
false;
5471 for (
auto &op : ops) {
5472 auto next = replace(op, orig, with);
5488 if (
auto II = dyn_cast<IntrinsicInst>(cur))
5489 if (II->getIntrinsicID() == Intrinsic::fmuladd ||
5490 II->getIntrinsicID() == Intrinsic::fma) {
5491 B.setFastMathFlags(
getFast());
5492 auto mul = pushcse(B.CreateFMul(II->getOperand(0), II->getOperand(1)));
5493 auto add = pushcse(B.CreateFAdd(mul, II->getOperand(2)));
5494 replaceAndErase(cur, add);
5495 return "FMulAddExpand";
5498 if (
auto BO = dyn_cast<BinaryOperator>(cur)) {
5499 if (BO->getOpcode() == Instruction::FMul && BO->isFast()) {
5500 Value *args[2] = {BO->getOperand(0), BO->getOperand(1)};
5504 replaceAndErase(cur, mul);
5505 return "FMulToProduct";
5507 if (BO->getOpcode() == Instruction::FDiv && BO->isFast()) {
5508 auto c0 = dyn_cast<ConstantFP>(BO->getOperand(0));
5509 if (!c0 || !c0->isExactlyValue(1.0)) {
5510 B.setFastMathFlags(
getFast());
5511 auto div = pushcse(B.CreateFDivFMF(ConstantFP::get(BO->getType(), 1.0),
5512 BO->getOperand(1), BO));
5514 B.CreateFMulFMF(BO->getOperand(0), div, BO, cur->getName()));
5515 replaceAndErase(cur, mul);
5516 return "FDivToFMul";
5519 if (BO->getOpcode() == Instruction::FAdd && BO->isFast()) {
5520 Value *args[2] = {BO->getOperand(0), BO->getOperand(1)};
5523 replaceAndErase(cur, mul);
5526 if (BO->getOpcode() == Instruction::FSub && BO->isFast()) {
5527 B.setFastMathFlags(
getFast());
5528 Value *args[2] = {BO->getOperand(0),
5529 pushcse(B.CreateFNeg(BO->getOperand(1)))};
5532 args, cur->getName()));
5533 replaceAndErase(cur, mul);
5537 if (cur->getOpcode() == Instruction::FNeg) {
5538 B.setFastMathFlags(
getFast());
5540 pushcse(B.CreateFMulFMF(ConstantFP::get(cur->getType(), -1.0),
5541 cur->getOperand(0), cur, cur->getName()));
5542 replaceAndErase(cur, mul);
5546 if (
auto SI = dyn_cast<SelectInst>(cur)) {
5547 if (
auto tc = dyn_cast<ConstantFP>(SI->getTrueValue()))
5548 if (
auto fc = dyn_cast<ConstantFP>(SI->getFalseValue()))
5550 if (tc->isExactlyValue(1.0)) {
5552 pushcse(B.CreateUIToFP(SI->getCondition(), tc->getType()));
5553 replaceAndErase(cur, res);
5556 if (tc->isExactlyValue(-1.0)) {
5558 pushcse(B.CreateSIToFP(SI->getCondition(), tc->getType()));
5559 replaceAndErase(cur, res);
5566 SmallVector<Value *, 1> operands;
5567 std::optional<APFloat> constval;
5568 bool changed =
false;
5575 operands.push_back(v2);
5581 if (
auto C = dyn_cast<ConstantFP>(v)) {
5582 if (C->isExactlyValue(1.0)) {
5587 replaceAndErase(cur, C);
5588 return "ZeroProduct";
5591 constval = C->getValue();
5594 constval = (*constval) * C->getValue();
5598 if (
auto op = dyn_cast<SelectInst>(v)) {
5599 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
5601 operands.push_back(pushcse(B.CreateUIToFP(
5602 pushcse(B.CreateNot(op->getCondition())), op->getType())));
5603 operands.push_back(op->getFalseValue());
5607 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
5610 pushcse(B.CreateUIToFP(op->getCondition(), op->getType())));
5611 operands.push_back(op->getTrueValue());
5616 operands.push_back(v);
5619 operands.push_back(ConstantFP::get(cur->getType(), *constval));
5621 if (operands.size() == 0) {
5622 replaceAndErase(cur, ConstantFP::get(cur->getType(), 1.0));
5623 return "EmptyProduct";
5625 if (operands.size() == 1) {
5626 replaceAndErase(cur, operands[0]);
5627 return "SingleProduct";
5632 operands, cur->getName()));
5633 replaceAndErase(cur, mul);
5634 return "ProductSimplification";
5638 if (
auto P =
isSum(cur)) {
5640 std::map<Value *, unsigned> operands;
5641 std::optional<APFloat> constval;
5642 bool changed =
false;
5644 if (
auto P2 =
isSum(v)) {
5653 if (
auto C = dyn_cast<ConstantFP>(v)) {
5654 if (C->isExactlyValue(0.0)) {
5659 constval = C->getValue();
5662 constval = (*constval) + C->getValue();
5669 operands[ConstantFP::get(cur->getType(), *constval)]++;
5671 if (operands.size() == 0) {
5672 replaceAndErase(cur, ConstantFP::get(cur->getType(), 0.0));
5675 SmallVector<Value *, 1> args;
5676 for (
auto &pair : operands) {
5677 if (pair.second == 1) {
5678 args.push_back(pair.first);
5682 Value *sargs[] = {pair.first,
5683 ConstantFP::get(cur->getType(), (
double)pair.second)};
5684 args.push_back(pushcse(B.CreateCall(
5687 if (args.size() == 1) {
5688 replaceAndErase(cur, args[0]);
5694 args, cur->getName()));
5695 replaceAndErase(cur, sum);
5696 return "SumSimplification";
5701 SmallVector<Value *, 1> operands;
5702 SmallVector<Value *, 1> conditions;
5705 if (
auto op = dyn_cast<UIToFPInst>(v)) {
5706 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
5707 conditions.push_back(op->getOperand(0));
5712 if (
auto op = dyn_cast<SIToFPInst>(v)) {
5713 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
5714 conditions.push_back(op->getOperand(0));
5715 operands.push_back(ConstantFP::get(cur->getType(), -1.0));
5719 if (
auto op = dyn_cast<SelectInst>(v)) {
5720 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
5722 conditions.push_back(pushcse(B.CreateNot(op->getCondition())));
5723 operands.push_back(op->getFalseValue());
5726 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
5728 conditions.push_back(op->getCondition());
5729 operands.push_back(op->getTrueValue());
5733 operands.push_back(v);
5736 if (conditions.size()) {
5737 auto mul = pushcse(B.CreateCall(
5739 Value *condition =
nullptr;
5740 for (
auto v : conditions) {
5741 assert(v->getType()->isIntegerTy(1));
5742 if (condition ==
nullptr) {
5746 condition = pushcse(B.CreateAnd(condition, v));
5748 auto zero = ConstantFP::get(cur->getType(), 0.0);
5749 auto sel = pushcse(B.CreateSelect(condition, mul, zero, cur->getName()));
5750 replaceAndErase(cur, sel);
5751 return "ProductSelect";
5756 if (
auto P =
isSum(cur)) {
5758 SmallVector<std::pair<Value *, bool>, 1> conditions;
5762 if (
auto op = dyn_cast<UIToFPInst>(v)) {
5763 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
5764 conditions.emplace_back(op->getOperand(0),
false);
5769 if (
auto op = dyn_cast<SIToFPInst>(v)) {
5770 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
5771 conditions.emplace_back(op->getOperand(0),
false);
5775 if (
auto op = dyn_cast<SelectInst>(v)) {
5776 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
5778 conditions.emplace_back(op->getCondition(),
true);
5781 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
5783 conditions.emplace_back(op->getCondition(),
false);
5790 Value *condition =
nullptr;
5792 for (
size_t i = 0; i < conditions.size(); i++) {
5794 for (
size_t j = 0; j < conditions.size(); j++) {
5795 if (((conditions[i].first == conditions[j].first) &&
5796 (conditions[i].second == conditions[i].second)) ||
5797 ((
isNot(conditions[i].first, conditions[j].first) &&
5798 (conditions[i].second != conditions[i].second))))
5801 if (count == conditions.size() && count > 1) {
5802 condition = conditions[i].first;
5803 if (conditions[i].second)
5804 condition = pushcse(B.CreateNot(condition,
"sumpnot"));
5811 SmallVector<Value *, 1> operands;
5814 if (
auto op = dyn_cast<UIToFPInst>(v)) {
5815 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
5816 operands.push_back(ConstantFP::get(cur->getType(), 1.0));
5821 if (
auto op = dyn_cast<SIToFPInst>(v)) {
5822 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
5823 operands.push_back(ConstantFP::get(cur->getType(), -1.0));
5827 if (
auto op = dyn_cast<SelectInst>(v)) {
5828 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
5830 operands.push_back(op->getFalseValue());
5833 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
5835 operands.push_back(op->getTrueValue());
5839 llvm::errs() <<
" unhandled call op sumselect: " << *v <<
"\n";
5843 if (conditions.size()) {
5844 auto sum = pushcse(B.CreateCall(
5846 auto zero = ConstantFP::get(cur->getType(), 0.0);
5848 pushcse(B.CreateSelect(condition, sum, zero, cur->getName()));
5849 replaceAndErase(cur, sel);
5855 if (
auto S =
isSum(cur)) {
5856 SmallVector<Value *, 1> allOps;
5857 auto combine = [](
const SmallVector<Value *, 1> &lhs,
5858 SmallVector<Value *, 1> rhs) {
5859 SmallVector<Value *, 1> out;
5860 for (
auto v : lhs) {
5862 for (
auto &v2 : rhs) {
5875 auto subtract = [](SmallVector<Value *, 1> lhs,
5876 const SmallVector<Value *, 1> &rhs) {
5877 for (
auto v : rhs) {
5878 auto found = find(lhs, v);
5879 assert(found != lhs.end());
5900 if (legal && allOps.size() > 0) {
5901 SmallVector<Value *, 1> operands;
5906 auto newprod = pushcse(B.CreateCall(
5908 operands.push_back(newprod);
5910 auto newsum = pushcse(B.CreateCall(
5912 allOps.push_back(newsum);
5913 auto fprod = pushcse(B.CreateCall(
5915 replaceAndErase(cur, fprod);
5956 if (
auto fcmp = dyn_cast<FCmpInst>(cur)) {
5957 auto predicate = fcmp->getPredicate();
5958 if (predicate == FCmpInst::FCMP_OEQ || predicate == FCmpInst::FCMP_UEQ ||
5959 predicate == FCmpInst::FCMP_UNE || predicate == FCmpInst::FCMP_ONE) {
5960 for (
int i = 0; i < 2; i++)
5961 if (
auto C = dyn_cast<ConstantFP>(fcmp->getOperand(i))) {
5967 if (
auto P =
isProduct(fcmp->getOperand(1 - i))) {
5968 Value *res =
nullptr;
5970 auto eq_predicate = predicate;
5971 if (predicate == FCmpInst::FCMP_UNE ||
5972 predicate == FCmpInst::FCMP_ONE)
5973 eq_predicate = fcmp->getInversePredicate();
5976 auto ncmp1 = pushcse(B.CreateFCmp(eq_predicate, v, C));
5980 res = pushcse(B.CreateOr(res, ncmp1));
5983 if (predicate == FCmpInst::FCMP_UNE ||
5984 predicate == FCmpInst::FCMP_ONE) {
5985 res = pushcse(B.CreateNot(res));
5988 replaceAndErase(cur, res);
5989 return "CmpProductSplit";
5994 if (
auto S =
isSum(fcmp->getOperand(1 - i))) {
5995 SmallVector<Value *, 1> allOps;
5996 auto combine = [](
const SmallVector<Value *, 1> &lhs,
5997 SmallVector<Value *, 1> rhs) {
5998 SmallVector<Value *, 1> out;
5999 for (
auto v : lhs) {
6001 for (
auto &v2 : rhs) {
6014 auto subtract = [](SmallVector<Value *, 1> lhs,
6015 const SmallVector<Value *, 1> &rhs) {
6016 for (
auto v : rhs) {
6017 auto found = find(lhs, v);
6018 assert(found != lhs.end());
6039 if (legal && allOps.size() > 0) {
6040 SmallVector<Value *, 1> operands;
6045 auto newprod = pushcse(B.CreateCall(
6047 operands.push_back(newprod);
6049 auto newsum = pushcse(B.CreateCall(
6051 allOps.push_back(newsum);
6052 auto fprod = pushcse(B.CreateCall(
6054 auto fcmp = pushcse(B.CreateCmp(predicate, fprod, C));
6055 replaceAndErase(cur, fcmp);
6056 return "CmpSumFactor";
6064 if (
auto fcmp = dyn_cast<FCmpInst>(cur)) {
6065 auto predicate = fcmp->getPredicate();
6066 if (predicate == FCmpInst::FCMP_OEQ || predicate == FCmpInst::FCMP_UEQ ||
6067 predicate == FCmpInst::FCMP_UNE || predicate == FCmpInst::FCMP_ONE) {
6068 for (
int i = 0; i < 2; i++)
6069 if (
auto C = dyn_cast<ConstantFP>(fcmp->getOperand(i))) {
6072 if (
auto S =
isSum(fcmp->getOperand(1 - i))) {
6075 auto eq_predicate = predicate;
6076 if (predicate == FCmpInst::FCMP_UNE ||
6077 predicate == FCmpInst::FCMP_ONE)
6078 eq_predicate = fcmp->getInversePredicate();
6080 Value *op_checks =
nullptr;
6081 for (
auto a : allOps) {
6082 auto a_e0 = pushcse(B.CreateFCmp(eq_predicate, a, C));
6083 if (op_checks ==
nullptr)
6086 op_checks = pushcse(B.CreateAnd(op_checks, a_e0));
6088 SmallVector<Value *, 1> slice;
6089 for (
size_t i = 1; i < allOps.size(); i++)
6090 slice.push_back(allOps[i]);
6093 auto negOp = pushcse(B.CreateFNeg(allOps[0]));
6095 pushcse(B.CreateFCmp(eq_predicate, negOp, sliceCall));
6096 auto ori = pushcse(B.CreateOr(op_checks, ane));
6097 if (predicate == FCmpInst::FCMP_UNE ||
6098 predicate == FCmpInst::FCMP_ONE) {
6099 ori = pushcse(B.CreateNot(ori));
6101 replaceAndErase(cur, ori);
6102 return "Sum2ZeroSplit";
6111 if (
auto icmp = dyn_cast<CmpInst>(cur)) {
6112 if (icmp->getPredicate() == CmpInst::ICMP_EQ ||
6113 icmp->getPredicate() == CmpInst::ICMP_NE) {
6114 for (
int i = 0; i < 2; i++)
6115 if (
auto C = dyn_cast<ConstantInt>(icmp->getOperand(i)))
6117 if (
auto add = dyn_cast<BinaryOperator>(icmp->getOperand(1 - i)))
6118 if (add->getOpcode() == Instruction::Add)
6119 if (
auto a0 = dyn_cast<CastInst>(add->getOperand(0)))
6120 if (
auto a1 = dyn_cast<CastInst>(add->getOperand(1)))
6121 if (a0->getOperand(0)->getType() ==
6122 a1->getOperand(0)->getType() &&
6123 (isa<ZExtInst>(a0) || isa<SExtInst>(a0))) {
6124 auto cmp2 = pushcse(B.CreateCmp(
6125 icmp->getPredicate(), a0, pushcse(B.CreateNeg(a1))));
6126 replaceAndErase(cur, cmp2);
6127 return "CmpExt0Shuffle";
6134 if (
auto sub = dyn_cast<BinaryOperator>(cur))
6135 if (sub->getOpcode() == Instruction::Sub)
6136 if (
auto C = dyn_cast<ConstantInt>(sub->getOperand(0)))
6138 if (
auto a0 = dyn_cast<CastInst>(sub->getOperand(1)))
6139 if (a0->getOperand(0)->getType()->isIntegerTy(1)) {
6141 Value *tmp =
nullptr;
6142 if (isa<ZExtInst>(a0))
6143 tmp = pushcse(B.CreateSExt(a0->getOperand(0), a0->getType()));
6144 else if (isa<SExtInst>(a0))
6145 tmp = pushcse(B.CreateZExt(a0->getOperand(0), a0->getType()));
6148 replaceAndErase(cur, tmp);
6149 return "NegSZExtI1";
6152 if ((cur->getOpcode() == Instruction::LShr ||
6153 cur->getOpcode() == Instruction::SDiv ||
6154 cur->getOpcode() == Instruction::UDiv) &&
6156 if (
auto C2 = dyn_cast<ConstantInt>(cur->getOperand(1)))
6157 if (
auto mul = dyn_cast<BinaryOperator>(cur->getOperand(0))) {
6160 if (mul->getOpcode() == Instruction::Mul)
6161 for (
int i0 = 0; i0 < 2; i0++)
6162 if (
auto C1 = dyn_cast<ConstantInt>(mul->getOperand(i0))) {
6163 auto lhs = C1->getValue();
6164 APInt rhs = C2->getValue();
6165 if (cur->getOpcode() == Instruction::LShr) {
6166 rhs = APInt(rhs.getBitWidth(), 1) << rhs;
6170 if (cur->getOpcode() == Instruction::LShr ||
6171 cur->getOpcode() == Instruction::UDiv)
6172 APInt::udivrem(lhs, rhs, div, rem);
6174 APInt::sdivrem(lhs, rhs, div, rem);
6176 auto res = pushcse(B.CreateMul(
6177 mul->getOperand(1 - i0),
6178 ConstantInt::get(cur->getType(), div),
6179 "mdiv." + cur->getName(), mul->hasNoUnsignedWrap(),
6180 mul->hasNoSignedWrap()));
6182 replaceAndErase(cur, res);
6183 return "IMulDivConst";
6188 if (mul->getOpcode() == Instruction::Add)
6189 for (
int i0 = 0; i0 < 2; i0++)
6190 if (
auto C1 = dyn_cast<ConstantInt>(mul->getOperand(i0))) {
6191 auto lhs = C1->getValue();
6192 APInt rhs = C2->getValue();
6193 if (cur->getOpcode() == Instruction::LShr) {
6194 rhs = APInt(rhs.getBitWidth(), 1) << rhs;
6198 if (cur->getOpcode() == Instruction::LShr ||
6199 cur->getOpcode() == Instruction::UDiv)
6200 APInt::udivrem(lhs, rhs, div, rem);
6202 APInt::sdivrem(lhs, rhs, div, rem);
6203 if (rem == 0 && ((mul->hasNoUnsignedWrap() &&
6204 (cur->getOpcode() == Instruction::LShr ||
6205 cur->getOpcode() == Instruction::UDiv)) ||
6206 (mul->hasNoSignedWrap() &&
6207 (cur->getOpcode() == Instruction::AShr ||
6208 cur->getOpcode() == Instruction::SDiv)))) {
6209 auto res = pushcse(B.CreateAdd(
6210 mul->getOperand(1 - i0),
6211 ConstantInt::get(cur->getType(), div),
6212 "madd." + cur->getName(), mul->hasNoUnsignedWrap(),
6213 mul->hasNoSignedWrap()));
6215 replaceAndErase(cur, res);
6216 return "IAddDivConst";
6222 if (cur->getOpcode() == Instruction::FMul)
6224 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
6225 if (mul1->getOpcode() == Instruction::FMul && mul1->isFast())
6226 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1)))
6227 if (mul2->getOpcode() == Instruction::FMul && mul2->isFast()) {
6228 for (
auto i1 = 0; i1 < 2; i1++)
6229 for (
auto i2 = 0; i2 < 2; i2++)
6230 if (isa<Constant>(mul1->getOperand(i1)))
6231 if (isa<Constant>(mul2->getOperand(i2))) {
6234 B.CreateFMulFMF(mul1->getOperand(1 - i1),
6235 mul2->getOperand(1 - i2), cur));
6236 auto n1 = pushcse(B.CreateFMulFMF(
6237 mul1->getOperand(i1), mul2->getOperand(i2), cur));
6238 auto n2 = pushcse(B.CreateFMulFMF(n0, n1, cur));
6241 replaceAndErase(cur, n2);
6242 return "MulMulConstConst";
6247 if ((cur->getOpcode() == Instruction::FMul && cur->isFast()) ||
6248 cur->getOpcode() == Instruction::Mul)
6249 for (
auto i1 = 0; i1 < 2; i1++)
6250 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(i1)))
6251 if (((mul1->getOpcode() == Instruction::FMul && mul1->isFast())) ||
6252 mul1->getOpcode() == Instruction::FMul)
6253 if (
auto const2 = dyn_cast<Constant>(cur->getOperand(1 - i1)))
6254 for (
auto i2 = 0; i2 < 2; i2++)
6255 if (
auto const1 = dyn_cast<Constant>(mul1->getOperand(i2))) {
6256 Value *res =
nullptr;
6257 if (cur->getOpcode() == Instruction::FMul) {
6258 auto const3 = pushcse(B.CreateFMulFMF(const1, const2, mul1));
6260 B.CreateFMulFMF(mul1->getOperand(1 - i2), const3, cur));
6262 auto const3 = pushcse(B.CreateMul(const1, const2));
6263 res = pushcse(B.CreateMul(mul1->getOperand(1 - i2), const3));
6266 replaceAndErase(cur, res);
6267 return "MulConstConst";
6270 if (
auto fcmp = dyn_cast<FCmpInst>(cur)) {
6271 if (fcmp->getPredicate() == FCmpInst::FCMP_OEQ) {
6272 for (
int i = 0; i < 2; i++)
6273 if (
auto C = dyn_cast<ConstantFP>(fcmp->getOperand(i))) {
6275 if (
auto fmul = dyn_cast<BinaryOperator>(fcmp->getOperand(1 - i))) {
6277 if (fmul->getOpcode() == Instruction::FMul) {
6278 auto ncmp1 = pushcse(
6279 B.CreateFCmp(fcmp->getPredicate(), fmul->getOperand(0), C));
6280 auto ncmp2 = pushcse(
6281 B.CreateFCmp(fcmp->getPredicate(), fmul->getOperand(1), C));
6282 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
6283 replaceAndErase(cur, ori);
6284 return "CmpFMulSplit";
6287 if (fmul->getOpcode() == Instruction::FDiv) {
6288 auto ncmp1 = pushcse(
6289 B.CreateFCmp(fcmp->getPredicate(), fmul->getOperand(0), C));
6290 replaceAndErase(cur, ncmp1);
6291 return "CmpFDivSplit";
6294 if (fmul->getOpcode() == Instruction::FSub) {
6295 auto ncmp1 = pushcse(B.CreateFCmp(fcmp->getPredicate(),
6296 fmul->getOperand(0),
6297 fmul->getOperand(1)));
6298 replaceAndErase(cur, ncmp1);
6299 return "CmpFSubSplit";
6302 if (
auto cast = dyn_cast<SIToFPInst>(fcmp->getOperand(1 - i))) {
6303 auto ncmp1 = pushcse(B.CreateICmp(
6304 ICmpInst::ICMP_EQ, cast->getOperand(0),
6305 ConstantInt::get(cast->getOperand(0)->getType(), 0)));
6306 replaceAndErase(cur, ncmp1);
6307 return "SFCmpToICmp";
6309 if (
auto cast = dyn_cast<UIToFPInst>(fcmp->getOperand(1 - i))) {
6310 auto ncmp1 = pushcse(B.CreateICmp(
6311 ICmpInst::ICMP_EQ, cast->getOperand(0),
6312 ConstantInt::get(cast->getOperand(0)->getType(), 0)));
6313 replaceAndErase(cur, ncmp1);
6314 return "UFCmpToICmp";
6316 if (
auto SI = dyn_cast<SelectInst>(fcmp->getOperand(1 - i))) {
6317 auto falseCmp = pushcse(
6318 B.CreateCmp(fcmp->getPredicate(), C, SI->getFalseValue()));
6319 auto trueCmp = pushcse(
6320 B.CreateCmp(fcmp->getPredicate(), C, SI->getTrueValue()));
6322 B.CreateSelect(SI->getCondition(), trueCmp, falseCmp));
6323 replaceAndErase(cur, res);
6324 return "FCmpSelect";
6330 if (
auto fcmp = dyn_cast<CmpInst>(cur)) {
6331 if (fcmp->getPredicate() == CmpInst::ICMP_EQ ||
6332 fcmp->getPredicate() == CmpInst::ICMP_NE ||
6333 fcmp->getPredicate() == CmpInst::FCMP_OEQ ||
6334 fcmp->getPredicate() == CmpInst::FCMP_ONE) {
6337 for (
int i = 0; i < 2; i++)
6338 if (
auto inst = dyn_cast<Instruction>(fcmp->getOperand(i)))
6339 if (inst->getOpcode() == Instruction::FAdd && inst->isFast())
6340 for (
int i2 = 0; i2 < 2; i2++)
6341 if (inst->getOperand(i2) == fcmp->getOperand(1 - i)) {
6343 B.CreateCmp(fcmp->getPredicate(), inst->getOperand(1 - i2),
6344 ConstantFP::get(inst->getType(), 0)));
6345 replaceAndErase(cur, res);
6346 return "CmpFAddSame";
6351 if (fcmp->getOperand(0)->getType()->isIntegerTy(1)) {
6352 auto a = fcmp->getOperand(0);
6353 auto b = fcmp->getOperand(1);
6354 if (fcmp->getPredicate() == CmpInst::ICMP_EQ) {
6355 auto notB = pushcse(B.CreateNot(b));
6356 auto notA = pushcse(B.CreateNot(a));
6357 auto neitherAB = pushcse(B.CreateAnd(notA, notB));
6358 auto bothAB = pushcse(B.CreateAnd(a, b));
6359 auto res = pushcse(B.CreateOr(bothAB, neitherAB));
6360 replaceAndErase(cur, res);
6363 if (fcmp->getPredicate() == CmpInst::ICMP_NE) {
6364 auto notB = pushcse(B.CreateNot(b));
6365 auto aNotB = pushcse(B.CreateAnd(a, notB));
6366 auto notA = pushcse(B.CreateNot(a));
6367 auto notAB = pushcse(B.CreateAnd(notA, b));
6368 auto res = pushcse(B.CreateOr(notAB, aNotB));
6369 replaceAndErase(cur, res);
6374 for (
int i = 0; i < 2; i++)
6375 if (
auto CI = dyn_cast<ConstantInt>(fcmp->getOperand(i)))
6378 if (
auto addI = dyn_cast<Instruction>(fcmp->getOperand(1 - i))) {
6379 if (addI->getOpcode() == Instruction::Add &&
6380 addI->getOperand(0) == addI->getOperand(1)) {
6381 Value *res = pushcse(
6382 B.CreateCmp(fcmp->getPredicate(), addI->getOperand(0), CI));
6383 replaceAndErase(cur, res);
6387 if (addI->getOpcode() == Instruction::Sub) {
6388 auto ncmp1 = pushcse(B.CreateICmp(fcmp->getPredicate(),
6389 addI->getOperand(0),
6390 addI->getOperand(1)));
6391 replaceAndErase(cur, ncmp1);
6392 return "CmpISubSplit";
6404 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
6405 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1))) {
6406 if (mul1->getOpcode() == Instruction::Mul &&
6407 mul2->getOpcode() == Instruction::Mul &&
6408 mul1->hasNoUnsignedWrap() && mul1->hasNoSignedWrap() &&
6409 mul2->hasNoUnsignedWrap() && mul2->hasNoSignedWrap()) {
6410 for (
int i = 0; i < 2; i++) {
6411 if (mul1->getOperand(i) == mul2->getOperand(i)) {
6412 Value *res = pushcse(B.CreateICmp(fcmp->getPredicate(),
6413 mul1->getOperand(1 - i),
6414 mul2->getOperand(1 - i)));
6415 auto b = mul1->getOperand(i);
6416 if (fcmp->getPredicate() == CmpInst::ICMP_EQ) {
6417 Value *bZero = pushcse(B.CreateICmp(
6418 CmpInst::ICMP_EQ, b, ConstantInt::get(b->getType(), 0)));
6419 res = pushcse(B.CreateOr(res, bZero));
6421 Value *bZero = pushcse(B.CreateICmp(
6422 ICmpInst::ICMP_NE, b, ConstantInt::get(b->getType(), 0)));
6423 res = pushcse(B.CreateAnd(res, bZero));
6425 replaceAndErase(cur, res);
6426 return "CmpMulCommon";
6431 if (mul1->getOpcode() == Instruction::FMul &&
6432 mul2->getOpcode() == Instruction::FMul && mul1->isFast() &&
6434 for (
int i = 0; i < 2; i++) {
6435 if (mul1->getOperand(i) == mul2->getOperand(i)) {
6436 Value *res = pushcse(B.CreateFCmp(fcmp->getPredicate(),
6437 mul1->getOperand(1 - i),
6438 mul2->getOperand(1 - i)));
6439 auto b = mul1->getOperand(i);
6440 if (fcmp->getPredicate() == CmpInst::FCMP_OEQ) {
6441 Value *bZero = pushcse(B.CreateCmp(
6442 CmpInst::FCMP_OEQ, b, ConstantFP::get(b->getType(), 0)));
6443 res = pushcse(B.CreateOr(res, bZero));
6445 Value *bZero = pushcse(B.CreateCmp(
6446 CmpInst::FCMP_ONE, b, ConstantFP::get(b->getType(), 0)));
6447 res = pushcse(B.CreateAnd(res, bZero));
6449 replaceAndErase(cur, res);
6450 return "CmpMulfCommon";
6456 for (
auto cond : {Instruction::UIToFP, Instruction::SIToFP})
6457 if (mul1->getOpcode() == cond && mul2->getOpcode() == cond &&
6458 mul1->getOperand(0)->getType() ==
6459 mul2->getOperand(0)->getType()) {
6460 Value *res = pushcse(B.CreateICmp(
6461 fcmp->getPredicate() == CmpInst::FCMP_OEQ ? CmpInst::ICMP_EQ
6463 mul1->getOperand(0), mul2->getOperand(0)));
6464 replaceAndErase(cur, res);
6469 if (mul1->getOpcode() == Instruction::ZExt &&
6470 mul2->getOpcode() == Instruction::ZExt &&
6471 mul1->getOperand(0)->getType() ==
6472 mul2->getOperand(0)->getType()) {
6474 pushcse(B.CreateICmp(fcmp->getPredicate(), mul1->getOperand(0),
6475 mul2->getOperand(0)));
6476 replaceAndErase(cur, res);
6482 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
6483 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1)))
6484 if (((mul1->getOpcode() == Instruction::ZExt &&
6485 mul2->getOpcode() == Instruction::SExt) ||
6486 (mul1->getOpcode() == Instruction::SExt &&
6487 mul2->getOpcode() == Instruction::ZExt)) &&
6488 mul1->getOperand(0)->getType() ==
6489 mul2->getOperand(0)->getType() &&
6490 mul1->getOperand(0)->getType()->isIntegerTy(1)) {
6492 Value *na = mul1->getOperand(0);
6493 Value *nb = mul2->getOperand(0);
6495 if (fcmp->getPredicate() == ICmpInst::ICMP_EQ) {
6496 na = pushcse(B.CreateNot(na));
6497 nb = pushcse(B.CreateNot(nb));
6500 Value *res =
nullptr;
6501 if (fcmp->getPredicate() == ICmpInst::ICMP_EQ)
6502 res = pushcse(B.CreateAnd(na, nb));
6504 res = pushcse(B.CreateOr(na, nb));
6506 replaceAndErase(cur, res);
6507 return "CmpZExtSExt";
6511 if (fcmp->getPredicate() == ICmpInst::ICMP_EQ) {
6512 for (
int i = 0; i < 2; i++) {
6513 if (
auto C = dyn_cast<ConstantInt>(fcmp->getOperand(i))) {
6515 if (
auto fmul = dyn_cast<BinaryOperator>(fcmp->getOperand(1 - i))) {
6517 if (fmul->getOpcode() == Instruction::Mul) {
6518 auto ncmp1 = pushcse(
6519 B.CreateICmp(fcmp->getPredicate(), fmul->getOperand(0), C));
6520 auto ncmp2 = pushcse(
6521 B.CreateICmp(fcmp->getPredicate(), fmul->getOperand(1), C));
6522 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
6523 replaceAndErase(cur, ori);
6524 return "CmpIMulSplit";
6533 if (cur->getOpcode() == Instruction::FAdd) {
6535 if (cur->getOperand(0) == cur->getOperand(1) && cur->isFast()) {
6536 auto res = pushcse(B.CreateFMulFMF(
6537 cur->getOperand(0), ConstantFP::get(cur->getType(), 2.0), cur));
6538 replaceAndErase(cur, res);
6543 if (cur->getOpcode() == Instruction::Add) {
6545 for (
int i = 0; i < 2; i++) {
6546 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(i)))
6547 if (mul1->getOpcode() == Instruction::Mul) {
6548 for (
int j = 0; j < 2; j++) {
6549 if (
auto C = dyn_cast<ConstantInt>(mul1->getOperand(j))) {
6550 if (C->isMinusOne()) {
6551 auto res = pushcse(B.CreateSub(cur->getOperand(1 - i),
6552 mul1->getOperand(1 - j)));
6555 replaceAndErase(cur, res);
6564 if (
auto SI = dyn_cast<SelectInst>(cur)) {
6565 auto shouldMove = [](Value *v) {
return isa<Constant>(v); };
6594 for (
int i = 0; i < 2; i++)
6595 if (
auto inst = dyn_cast<Instruction>(SI->getOperand(1 + i)))
6596 if (inst->getOpcode() == Instruction::Mul)
6598 if (
auto C = dyn_cast<Constant>(SI->getOperand(1 + (1 - i))))
6599 if ((isa<ConstantInt>(C) && cast<ConstantInt>(C)->
isZero()) ||
6600 (isa<ConstantFP>(C) && cast<ConstantFP>(C)->
isZero()))
6601 for (
int j = 0; j < 2; j++)
6602 if (shouldMove(inst->getOperand(j))) {
6603 auto x = inst->getOperand(j);
6604 auto y = inst->getOperand(1 - j);
6605 auto isel = pushcse(B.CreateSelect(
6606 SI->getCondition(), (i == 0) ? y : C, (i == 0) ? C : y,
6607 "smulmove." + SI->getName()));
6609 if (cur->getType()->isIntegerTy())
6610 imul = pushcse(B.CreateMul(isel, x,
"",
6611 inst->hasNoUnsignedWrap(),
6612 inst->hasNoSignedWrap()));
6614 imul = pushcse(B.CreateFMulFMF(isel, x, inst,
""));
6616 replaceAndErase(cur, imul);
6617 return "SelMulMove";
6623 Value *ops[2] = {
nullptr,
nullptr};
6625 for (
int i = 0; i < 2; i++) {
6626 if (isa<ConstantFP>(SI->getOperand(1 + i))) {
6630 if (
auto CI = dyn_cast<CastInst>(SI->getOperand(1 + i))) {
6631 if (CI->getOpcode() == Instruction::SIToFP) {
6632 ops[i] = CI->getOperand(0);
6639 for (
int i = 0; i < 2; i++) {
6640 if (!ops[i] && ops[1 - i])
6641 ops[i] = ConstantInt::get(ops[1 - i]->getType(), 0);
6643 for (
int i = 0; i < 2; i++) {
6644 if (ops[i] ==
nullptr || ops[i]->getType() != ops[0]->getType()) {
6650 auto isel = pushcse(B.CreateSelect(SI->getCondition(), ops[0], ops[1],
6651 "seltofp." + SI->getName()));
6652 auto res = pushcse(B.CreateSIToFP(isel, SI->getType()));
6654 replaceAndErase(cur, res);
6655 return "SelSIMerge";
6660 if (cur->getOpcode() == Instruction::Mul) {
6661 for (
int i = 0; i < 2; i++) {
6663 if (
auto C = dyn_cast<ConstantInt>(cur->getOperand(i)))
6665 replaceAndErase(cur, cur->getOperand(1 - i));
6670 if (
auto Z = dyn_cast<ZExtInst>(cur->getOperand(i)))
6671 if (Z->getOperand(0)->getType()->isIntegerTy(1)) {
6672 auto prev = cur->getOperand(1 - i);
6673 auto next = replace(prev, Z->getOperand(0),
6674 ConstantInt::getTrue(cur->getContext()));
6676 auto res = pushcse(B.CreateMul(Z, next,
"postmul." + cur->getName(),
6677 cur->hasNoUnsignedWrap(),
6678 cur->hasNoSignedWrap()));
6679 replaceAndErase(cur, res);
6680 return "MulReplaceZExt";
6707 for (
int i = 0; i < 2; i++)
6708 if (
auto inst = dyn_cast<Instruction>(cur->getOperand(i)))
6709 if (inst->getOpcode() == Instruction::Sub)
6710 if (
auto CI = dyn_cast<ConstantInt>(cur->getOperand(1 - i)))
6711 if (CI->isNegative()) {
6712 auto sub2 = pushcse(B.CreateSub(
6713 inst->getOperand(1), inst->getOperand(0),
"",
6714 inst->hasNoUnsignedWrap(), inst->hasNoSignedWrap()));
6715 auto mul2 = pushcse(B.CreateMul(
6716 sub2, ConstantInt::get(CI->getType(), -CI->getValue()),
"",
6717 cur->hasNoUnsignedWrap(), cur->hasNoSignedWrap()));
6719 replaceAndErase(cur, mul2);
6720 return "MulSubNegConst";
6724 if (cur->getOpcode() == Instruction::Sub)
6725 if (
auto CI = dyn_cast<ConstantInt>(cur->getOperand(0)))
6727 if (
auto zext = dyn_cast<Instruction>(cur->getOperand(1))) {
6729 if (zext->getOpcode() == Instruction::ZExt &&
6730 zext->getOperand(0)->getType()->isIntegerTy(1)) {
6732 pushcse(B.CreateSExt(zext->getOperand(0), cur->getType()));
6733 replaceAndErase(cur, res);
6737 if (zext->getOpcode() == Instruction::Mul &&
6738 zext->hasNoUnsignedWrap() && zext->hasNoSignedWrap()) {
6739 for (
int i = 0; i < 2; i++)
6740 if (
auto CI = dyn_cast<ConstantInt>(zext->getOperand(i))) {
6741 auto res = pushcse(B.CreateMul(
6742 zext->getOperand(1 - i),
6743 ConstantInt::get(CI->getType(), -CI->getValue()),
6744 "neg." + zext->getName(),
true,
true));
6745 replaceAndErase(cur, res);
6746 return "SubMulConstant";
6794 if (cur->getOpcode() == Instruction::Add ||
6795 cur->getOpcode() == Instruction::Sub ||
6796 cur->getOpcode() == Instruction::Mul ||
6797 cur->getOpcode() == Instruction::FAdd ||
6798 cur->getOpcode() == Instruction::FSub ||
6799 cur->getOpcode() == Instruction::FMul ||
6802 cur->getOpcode() == Instruction::ICmp ||
6803 cur->getOpcode() == Instruction::FCmp) {
6805 Value *SI1cond =
nullptr;
6806 Value *SI1tval =
nullptr;
6807 Value *SI1fval =
nullptr;
6808 if (
auto SI1 = dyn_cast<SelectInst>(cur->getOperand(0))) {
6809 SI1cond = SI1->getCondition();
6810 SI1tval = SI1->getTrueValue();
6811 SI1fval = SI1->getFalseValue();
6813 if (
auto SI1 = dyn_cast<ZExtInst>(cur->getOperand(0)))
6814 if (SI1->getOperand(0)->getType()->isIntegerTy(1)) {
6815 SI1cond = SI1->getOperand(0);
6817 SI1fval = ConstantInt::get(SI1->getType(), 0);
6819 if (
auto SI1 = dyn_cast<SExtInst>(cur->getOperand(0)))
6820 if (SI1->getOperand(0)->getType()->isIntegerTy(1)) {
6821 SI1cond = SI1->getOperand(0);
6823 SI1fval = ConstantInt::get(SI1->getType(), 0);
6825 Value *SI2cond =
nullptr;
6826 Value *SI2tval =
nullptr;
6827 Value *SI2fval =
nullptr;
6829 auto op2 = cur->getOperand((cur->getOpcode() == Instruction::SIToFP ||
6830 cur->getOpcode() == Instruction::UIToFP)
6833 if (
auto SI2 = dyn_cast<SelectInst>(op2)) {
6834 SI2cond = SI2->getCondition();
6835 SI2tval = SI2->getTrueValue();
6836 SI2fval = SI2->getFalseValue();
6838 if (
auto SI2 = dyn_cast<ZExtInst>(op2))
6839 if (SI2->getOperand(0)->getType()->isIntegerTy(1)) {
6840 SI2cond = SI2->getOperand(0);
6842 SI2fval = ConstantInt::get(SI2->getType(), 0);
6844 if (
auto SI2 = dyn_cast<SExtInst>(op2))
6845 if (SI2->getOperand(0)->getType()->isIntegerTy(1)) {
6846 SI2cond = SI2->getOperand(0);
6848 SI2fval = ConstantInt::get(SI2->getType(), 0);
6851 if (SI1cond && SI2cond && (SI1cond == SI2cond ||
isNot(SI1cond, SI2cond)))
6852 if ((SI1cond == SI2cond &&
6853 ((isa<Constant>(SI1tval) && isa<Constant>(SI2tval)) ||
6854 (isa<Constant>(SI1fval) && isa<Constant>(SI2fval)))) ||
6855 (SI1cond != SI2cond &&
6856 ((isa<Constant>(SI1tval) && isa<Constant>(SI2fval)) ||
6857 (isa<Constant>(SI1fval) && isa<Constant>(SI2tval))))
6860 Value *tval =
nullptr;
6861 Value *fval =
nullptr;
6862 bool inverted = SI1cond != SI2cond;
6863 switch (cur->getOpcode()) {
6864 case Instruction::SIToFP:
6866 B.CreateSIToFP(SI1tval, cur->getType(),
"tval." + cur->getName());
6868 B.CreateSIToFP(SI1fval, cur->getType(),
"fval." + cur->getName());
6870 case Instruction::UIToFP:
6872 B.CreateUIToFP(SI1tval, cur->getType(),
"tval." + cur->getName());
6874 B.CreateUIToFP(SI1fval, cur->getType(),
"fval." + cur->getName());
6876 case Instruction::FAdd:
6877 tval = B.CreateFAddFMF(SI1tval, inverted ? SI2fval : SI2tval, cur,
6878 "tval." + cur->getName());
6879 fval = B.CreateFAddFMF(SI1fval, inverted ? SI2tval : SI2fval, cur,
6880 "fval." + cur->getName());
6882 case Instruction::FSub:
6883 tval = B.CreateFSubFMF(SI1tval, inverted ? SI2fval : SI2tval, cur,
6884 "tval." + cur->getName());
6885 fval = B.CreateFSubFMF(SI1fval, inverted ? SI2tval : SI2fval, cur,
6886 "fval." + cur->getName());
6888 case Instruction::FMul:
6889 tval = B.CreateFMulFMF(SI1tval, inverted ? SI2fval : SI2tval, cur,
6890 "tval." + cur->getName());
6891 fval = B.CreateFMulFMF(SI1fval, inverted ? SI2tval : SI2fval, cur,
6892 "fval." + cur->getName());
6894 case Instruction::Add:
6895 tval = B.CreateAdd(SI1tval, inverted ? SI2fval : SI2tval,
6896 "tval." + cur->getName(), cur->hasNoUnsignedWrap(),
6897 cur->hasNoSignedWrap());
6898 fval = B.CreateAdd(SI1fval, inverted ? SI2tval : SI2fval,
6899 "fval." + cur->getName(), cur->hasNoUnsignedWrap(),
6900 cur->hasNoSignedWrap());
6902 case Instruction::Sub:
6903 tval = B.CreateSub(SI1tval, inverted ? SI2fval : SI2tval,
6904 "tval." + cur->getName(), cur->hasNoUnsignedWrap(),
6905 cur->hasNoSignedWrap());
6906 fval = B.CreateSub(SI1fval, inverted ? SI2tval : SI2fval,
6907 "fval." + cur->getName(), cur->hasNoUnsignedWrap(),
6908 cur->hasNoSignedWrap());
6910 case Instruction::Mul:
6911 tval = B.CreateMul(SI1tval, inverted ? SI2fval : SI2tval,
6912 "tval." + cur->getName(), cur->hasNoUnsignedWrap(),
6913 cur->hasNoSignedWrap());
6914 fval = B.CreateMul(SI1fval, inverted ? SI2tval : SI2fval,
6915 "fval." + cur->getName(), cur->hasNoUnsignedWrap(),
6916 cur->hasNoSignedWrap());
6918 case Instruction::ICmp:
6919 case Instruction::FCmp:
6920 tval = B.CreateCmp(cast<CmpInst>(cur)->getPredicate(), SI1tval,
6921 inverted ? SI2fval : SI2tval,
6922 "tval." + cur->getName());
6923 fval = B.CreateCmp(cast<CmpInst>(cur)->getPredicate(), SI1fval,
6924 inverted ? SI2tval : SI2fval,
6925 "fval." + cur->getName());
6928 llvm_unreachable(
"illegal opcode");
6930 tval = pushcse(tval);
6931 fval = pushcse(fval);
6934 B.CreateSelect(SI1cond, tval, fval,
"selmerge." + cur->getName()));
6936 push(cur->getOperand(0));
6937 push(cur->getOperand(1));
6938 replaceAndErase(cur, res);
6939 return "BinopSelFuse";
6959 if (cur->getOpcode() == Instruction::And) {
6960 for (
size_t i1 = 0; i1 < 2; i1++)
6961 if (
auto inst2 = dyn_cast<Instruction>(cur->getOperand(1 - i1)))
6962 if (inst2->getOpcode() == Instruction::Or)
6963 for (
size_t i2 = 0; i2 < 2; i2++)
6964 if (
isNot(cur->getOperand(i1), inst2->getOperand(i2))) {
6965 auto q = inst2->getOperand(1 - i2);
6966 cur->setOperand(1 - i1, q);
6970 push(cur->getOperand(i1));
6971 push(inst2->getOperand(i2));
6973 for (
auto U : cur->users())
6980 if (cur->getOpcode() == Instruction::And) {
6981 for (
size_t i1 = 0; i1 < 2; i1++)
6982 if (
auto inst2 = dyn_cast<Instruction>(cur->getOperand(i1)))
6983 if (inst2->getOpcode() == Instruction::And)
6984 for (
size_t i2 = 0; i2 < 2; i2++)
6985 if (inst2->getOperand(i2) == cur->getOperand(1 - i1)) {
6986 replaceAndErase(cur, inst2);
6987 return "AndAndProp";
6992 if (cur->getOpcode() == Instruction::And) {
6993 for (
size_t i1 = 0; i1 < 2; i1++)
6994 if (
auto inst2 = dyn_cast<Instruction>(cur->getOperand(1 - i1)))
6995 if (inst2->getOpcode() == Instruction::Or)
6996 for (
size_t i2 = 0; i2 < 2; i2++)
6997 if (
isNot(cur->getOperand(i1), inst2->getOperand(i2))) {
6998 auto q = inst2->getOperand(1 - i2);
6999 cur->setOperand(1 - i1, q);
7003 push(cur->getOperand(i1));
7004 push(inst2->getOperand(i2));
7006 for (
auto U : cur->users())
7015 if (cur->getOpcode() == Instruction::And ||
7016 cur->getOpcode() == Instruction::Or) {
7017 for (
auto cmpOp : {ICmpInst::ICMP_EQ, ICmpInst::ICMP_NE})
7018 for (
auto interOp : {Instruction::Add, Instruction::Sub})
7019 if (
auto cmp1 = dyn_cast<ICmpInst>(cur->getOperand(0)))
7020 if (
auto cmp2 = dyn_cast<ICmpInst>(cur->getOperand(1)))
7021 for (
size_t i1 = 0; i1 < 2; i1++)
7022 for (
size_t i2 = 0; i2 < 2; i2++)
7023 if (cmp1->getOperand(1 - i1) == cmp2->getOperand(1 - i2) &&
7024 cmp1->getPredicate() == cmpOp &&
7025 cmp2->getPredicate() == cmpOp)
7026 if (
auto add1 = dyn_cast<Instruction>(cmp1->getOperand(i1)))
7027 if (
auto add2 = dyn_cast<Instruction>(cmp2->getOperand(i2)))
7028 if (add1->getOpcode() == interOp &&
7029 add2->getOpcode() == interOp)
7030 for (
size_t ia = 0; ia < 2; ia++)
7031 if (add1->getOperand(ia) == add2->getOperand(ia)) {
7033 auto b = add1->getOperand(ia);
7034 auto c = cmp1->getOperand(1 - i1);
7035 auto a = add1->getOperand(1 - ia);
7036 auto d = add2->getOperand(1 - ia);
7038 Value *res =
nullptr;
7039 if (interOp == Instruction::Add)
7041 res = pushcse(B.CreateSub(c, b));
7044 res = pushcse(B.CreateSub(b, c));
7047 res = pushcse(B.CreateAdd(c, b));
7049 auto lhs = pushcse(B.CreateCmp(cmpOp, a, res));
7050 auto rhs = pushcse(B.CreateCmp(cmpOp, d, res));
7052 Value *fres =
nullptr;
7053 if (cur->getOpcode() == Instruction::And)
7054 fres = pushcse(B.CreateAnd(lhs, rhs));
7056 fres = pushcse(B.CreateOr(lhs, rhs));
7058 replaceAndErase(cur, fres);
7059 return "AndLinearShift";
7064 if (cur->getOpcode() == Instruction::And) {
7065 for (
auto cmpOp : {ICmpInst::ICMP_EQ})
7066 if (
auto cmp1 = dyn_cast<ICmpInst>(cur->getOperand(0)))
7067 if (
auto cmp2 = dyn_cast<ICmpInst>(cur->getOperand(1)))
7068 for (
size_t i1 = 0; i1 < 2; i1++)
7069 for (
size_t i2 = 0; i2 < 2; i2++)
7070 if (cmp1->getOperand(1 - i1) == cmp2->getOperand(1 - i2) &&
7071 cmp1->getPredicate() == cmpOp &&
7072 cmp2->getPredicate() == cmpOp) {
7073 auto c1 = SE.getSCEV(cmp1->getOperand(i1));
7074 auto c2 = SE.getSCEV(cmp2->getOperand(i2));
7075#if LLVM_VERSION_MAJOR >= 24
7076 auto m = SE.getMinusSCEV(c1, c2, SCEV::FlagsMask);
7078 auto m = SE.getMinusSCEV(c1, c2, SCEV::NoWrapMask);
7080 if (
auto C = dyn_cast<SCEVConstant>(m)) {
7082 if (C->getValue()->isZero()) {
7085 replaceAndErase(cur, cmp1);
7089 replaceAndErase(cur,
7090 ConstantInt::getFalse(cur->getContext()));
7098 if (
auto icmp = dyn_cast<ICmpInst>(cur))
7099 if (icmp->getPredicate() == ICmpInst::ICMP_EQ &&
7100 cur->getType()->isIntegerTy(1))
7101 for (
int i = 0; i < 2; i++)
7102 if (
auto C = dyn_cast<ConstantInt>(icmp->getOperand(i)))
7104 if (
auto z = dyn_cast<BinaryOperator>(icmp->getOperand(1 - i)))
7105 if (z->getOpcode() == BinaryOperator::Or) {
7106 auto a0 = pushcse(B.CreateICmpEQ(z->getOperand(0), C));
7107 auto b0 = pushcse(B.CreateICmpEQ(z->getOperand(1), C));
7108 auto res = pushcse(B.CreateAnd(a0, b0));
7111 replaceAndErase(cur, res);
7116 if (cur->getOpcode() == Instruction::Sub ||
7117 cur->getOpcode() == Instruction::Add) {
7118 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
7119 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1)))
7120 if ((mul1->getOpcode() == Instruction::Mul &&
7121 mul2->getOpcode() == Instruction::Mul) ||
7122 (mul1->getOpcode() == Instruction::FMul &&
7123 mul2->getOpcode() == Instruction::FMul && mul1->isFast() &&
7124 mul2->isFast() && cur->isFast())) {
7125 for (
int i1 = 0; i1 < 2; i1++)
7126 for (
int i2 = 0; i2 < 2; i2++) {
7127 if (mul1->getOperand(i1) == mul2->getOperand(i2)) {
7128 Value *res =
nullptr;
7129 switch (cur->getOpcode()) {
7130 case Instruction::Add:
7131 res = B.CreateAdd(mul1->getOperand(1 - i1),
7132 mul2->getOperand(1 - i2));
7134 case Instruction::Sub:
7135 res = B.CreateSub(mul1->getOperand(1 - i1),
7136 mul2->getOperand(1 - i2));
7138 case Instruction::FAdd:
7139 res = B.CreateFAddFMF(mul1->getOperand(1 - i1),
7140 mul2->getOperand(1 - i2), cur);
7142 case Instruction::FSub:
7143 res = B.CreateFSubFMF(mul1->getOperand(1 - i1),
7144 mul2->getOperand(1 - i2), cur);
7147 llvm_unreachable(
"Illegal opcode");
7150 Value *res2 =
nullptr;
7151 if (cur->getType()->isIntegerTy())
7153 res, mul1->getOperand(i1),
"",
7154 mul1->hasNoUnsignedWrap() && mul1->hasNoUnsignedWrap(),
7155 mul2->hasNoSignedWrap() && mul2->hasNoSignedWrap());
7157 res2 = B.CreateFMulFMF(res, mul1->getOperand(i1), cur);
7159 res2 = pushcse(res2);
7161 replaceAndErase(cur, res2);
7162 return "InvDistributive";
7171 if (cur->getOpcode() == Instruction::FSub ||
7172 cur->getOpcode() == Instruction::FAdd ||
7173 cur->getOpcode() == Instruction::FMul ||
7174 cur->getOpcode() == Instruction::FNeg ||
7176 auto opcode = cur->getOpcode();
7178 opcode = Instruction::FAdd;
7179 auto Ty = B.getInt64Ty();
7180 SmallPtrSet<Instruction *, 1> temporaries;
7181 SmallVector<Instruction *, 1> precasts;
7182 Value *lhs =
nullptr;
7184 Value *prelhs = (cur->getOpcode() == Instruction::FNeg)
7185 ? ConstantFP::get(cur->getType(), 0.0)
7186 : cur->getOperand(0);
7187 Value *prerhs = (cur->getOpcode() == Instruction::FNeg)
7188 ? cur->getOperand(0)
7189 : cur->getOperand(1);
7191 APInt minval(64, 0);
7192 APInt maxval(64, 0);
7193 if (
auto C = dyn_cast<ConstantFP>(prelhs)) {
7195 bool isExact =
false;
7196 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
7198 if (isExact || C->isZero()) {
7199 minval = maxval = Tmp;
7200 lhs = ConstantInt::get(Ty, Tmp);
7203 if (
auto ext = dyn_cast<CastInst>(prelhs)) {
7204 if (ext->getOpcode() == Instruction::UIToFP ||
7205 ext->getOpcode() == Instruction::SIToFP) {
7206 precasts.push_back(ext);
7207 auto ity = cast<IntegerType>(ext->getOperand(0)->getType());
7209 if (
auto I = dyn_cast<Instruction>(ext->getOperand(0)))
7210 if (
auto MD =
hasMetadata(I, LLVMContext::MD_range)) {
7214 cast<ConstantAsMetadata>(MD->getOperand(0))->getValue())
7219 cast<ConstantAsMetadata>(MD->getOperand(1))->getValue())
7224 if (ext->getOpcode() == Instruction::UIToFP)
7225 maxval = APInt::getMaxValue(ity->getBitWidth()).zextOrTrunc(64);
7228 APInt::getSignedMaxValue(ity->getBitWidth()).zextOrTrunc(64);
7230 APInt::getSignedMinValue(ity->getBitWidth()).zextOrTrunc(64);
7233 if (ext->getOperand(0)->getType() == Ty)
7234 lhs = ext->getOperand(0);
7235 else if (ity->getBitWidth() < Ty->getBitWidth()) {
7236 if (ext->getOpcode() == Instruction::UIToFP)
7237 lhs = B.CreateZExt(ext->getOperand(0), Ty);
7239 lhs = B.CreateSExt(ext->getOperand(0), Ty);
7240 if (
auto I = dyn_cast<Instruction>(lhs))
7241 if (I != ext->getOperand(0))
7242 temporaries.insert(I);
7247 Value *rhs =
nullptr;
7249 if (
auto C = dyn_cast<ConstantFP>(prerhs)) {
7251 bool isExact =
false;
7252 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
7254 if (isExact || C->isZero()) {
7255 rhs = ConstantInt::get(Ty, Tmp);
7257 case Instruction::FAdd:
7261 case Instruction::FSub:
7262 case Instruction::FNeg:
7266 case Instruction::FMul:
7271 llvm_unreachable(
"Illegal opcode");
7275 if (
auto ext = dyn_cast<CastInst>(prerhs)) {
7276 if (ext->getOpcode() == Instruction::UIToFP ||
7277 ext->getOpcode() == Instruction::SIToFP) {
7278 precasts.push_back(ext);
7279 auto ity = cast<IntegerType>(ext->getOperand(0)->getType());
7281 APInt rhsMin(64, 0);
7282 APInt rhsMax(64, 0);
7283 if (
auto I = dyn_cast<Instruction>(ext->getOperand(0)))
7284 if (
auto MD =
hasMetadata(I, LLVMContext::MD_range)) {
7288 cast<ConstantAsMetadata>(MD->getOperand(0))->getValue())
7293 cast<ConstantAsMetadata>(MD->getOperand(1))->getValue())
7298 if (ext->getOpcode() == Instruction::UIToFP) {
7299 rhsMax = APInt::getMaxValue(ity->getBitWidth()).zextOrTrunc(64);
7300 rhsMin = APInt(64, 0);
7303 APInt::getSignedMaxValue(ity->getBitWidth()).zextOrTrunc(64);
7305 APInt::getSignedMinValue(ity->getBitWidth()).zextOrTrunc(64);
7309 case Instruction::FAdd:
7313 case Instruction::FSub:
7314 case Instruction::FNeg:
7318 case Instruction::FMul: {
7319 auto minf = [&](APInt a, APInt b) {
return a.sle(b) ? a : b; };
7320 auto maxf = [&](APInt a, APInt b) {
return a.sle(b) ? b : b; };
7323 minf(minval * rhsMax, minf(maxval * rhsMin, maxval * rhsMax)));
7326 maxf(minval * rhsMax, maxf(maxval * rhsMin, maxval * rhsMax)));
7330 llvm_unreachable(
"Illegal opcode");
7332 if (ext->getOperand(0)->getType() == Ty)
7333 rhs = ext->getOperand(0);
7334 else if (ity->getBitWidth() < Ty->getBitWidth()) {
7335 if (ext->getOpcode() == Instruction::UIToFP)
7336 rhs = B.CreateZExt(ext->getOperand(0), Ty);
7338 rhs = B.CreateSExt(ext->getOperand(0), Ty);
7339 if (
auto I = dyn_cast<Instruction>(rhs))
7340 if (I != ext->getOperand(0))
7341 temporaries.insert(I);
7347 Value *res =
nullptr;
7348 if (temporaries.count(dyn_cast<Instruction>(lhs)))
7350 if (temporaries.count(dyn_cast<Instruction>(rhs)))
7353 case Instruction::FAdd:
7354 res = B.CreateAdd(lhs, rhs,
"",
false,
true);
7356 case Instruction::FSub:
7357 case Instruction::FNeg:
7358 res = B.CreateSub(lhs, rhs,
"",
false,
true);
7360 case Instruction::FMul:
7361 res = B.CreateMul(lhs, rhs,
"",
false,
true);
7364 llvm_unreachable(
"Illegal opcode");
7367 for (
auto I : precasts)
7380 auto ext = pushcse(B.CreateSIToFP(res, cur->getType()));
7381 replaceAndErase(cur, ext);
7382 return "BinopExtToExtBinop";
7385 for (
auto I : temporaries)
7386 I->eraseFromParent();
7392 if (
auto fcmp = dyn_cast<FCmpInst>(cur))
7393 for (
int i = 0; i < 2; i++)
7394 if (
auto const2 = dyn_cast<Constant>(fcmp->getOperand(i)))
7395 if (
auto sel = dyn_cast<SelectInst>(fcmp->getOperand(1 - i)))
7396 if (isa<Constant>(sel->getTrueValue()) ||
7397 isa<Constant>(sel->getFalseValue())) {
7398 auto tval = pushcse(B.CreateFCmp(fcmp->getPredicate(),
7399 sel->getTrueValue(), const2));
7400 auto fval = pushcse(B.CreateFCmp(fcmp->getPredicate(),
7401 sel->getFalseValue(), const2));
7402 auto res = pushcse(B.CreateSelect(sel->getCondition(), tval, fval));
7403 replaceAndErase(cur, res);
7404 return "FCmpSelectConst";
7412 if (cur->getOpcode() == Instruction::FMul)
7413 if (cur->isFast() && cur->getOperand(0) != cur->getOperand(1))
7414 for (
auto ic = 0; ic < 2; ic++)
7415 if (
auto mul = dyn_cast<Instruction>(cur->getOperand(ic)))
7416 if (mul->getOpcode() == Instruction::FMul && mul->isFast()) {
7417 auto b = cur->getOperand(1 - ic);
7420 for (
int i = 0; i < 2; i++)
7421 if (
auto C = dyn_cast<Constant>(mul->getOperand(i))) {
7423 pushcse(B.CreateFMulFMF(mul->getOperand(1 - i), b, mul));
7424 auto n1 = pushcse(B.CreateFMulFMF(n0, C, cur));
7427 replaceAndErase(cur, n1);
7428 return "MulMulConst";
7434 if (cur->getOpcode() == Instruction::FAdd ||
7435 cur->getOpcode() == Instruction::FSub) {
7436 if (
auto mul1 = dyn_cast<BinaryOperator>(cur->getOperand(0))) {
7437 if (mul1->getOpcode() == Instruction::FMul && mul1->isFast()) {
7438 if (
auto mul2 = dyn_cast<BinaryOperator>(cur->getOperand(1))) {
7439 if (mul2->getOpcode() == Instruction::FMul && mul2->isFast()) {
7440 for (
int i = 0; i < 2; i++) {
7441 for (
int j = 0; j < 2; j++) {
7442 if (mul1->getOperand(i) == mul2->getOperand(j)) {
7443 auto c = mul1->getOperand(i);
7444 auto a = mul1->getOperand(1 - i);
7445 auto b = mul2->getOperand(1 - j);
7446 Value *intermediate =
nullptr;
7448 if (cur->getOpcode() == Instruction::FAdd)
7449 intermediate = pushcse(B.CreateFAddFMF(a, b, cur));
7451 intermediate = pushcse(B.CreateFSubFMF(a, b, cur));
7453 auto res = pushcse(B.CreateFMulFMF(c, intermediate, cur));
7456 replaceAndErase(cur, res);
7457 return "FAddMulConstMulConst";
7470 if (cur->getOpcode() == Instruction::FMul && cur->isFast()) {
7471 for (
int i = 0; i < 2; i++)
7472 if (
auto z = dyn_cast<Instruction>(cur->getOperand(i)))
7473 if (isa<SIToFPInst>(z) || isa<UIToFPInst>(z))
7474 if (
auto imul = dyn_cast<BinaryOperator>(z->getOperand(0)))
7475 if (imul->getOpcode() == Instruction::Mul)
7476 for (
int j = 0; j < 2; j++)
7477 if (
auto c = dyn_cast<Constant>(imul->getOperand(j))) {
7478 auto b = imul->getOperand(1 - j);
7479 auto a = cur->getOperand(1 - i);
7481 auto c_fp = pushcse(B.CreateSIToFP(c, cur->getType()));
7482 auto b_fp = pushcse(B.CreateSIToFP(b, cur->getType()));
7483 auto n_mul = pushcse(B.CreateFMulFMF(a, c_fp, cur));
7485 B.CreateFMulFMF(n_mul, b_fp, cur, cur->getName()));
7488 replaceAndErase(cur, res);
7489 return "FMulIMulConstRotate";
7493 if (cur->getOpcode() == Instruction::FDiv) {
7494 Value *prelhs = cur->getOperand(0);
7495 Value *b = cur->getOperand(1);
7498 if (
auto ext = dyn_cast<CastInst>(prelhs)) {
7499 if (ext->getOpcode() == Instruction::UIToFP ||
7500 ext->getOpcode() == Instruction::SIToFP) {
7503 Value *condition = pushcse(
7504 B.CreateICmpEQ(ext->getOperand(0),
7505 ConstantInt::get(ext->getOperand(0)->getType(), 0),
7506 "sdivcmp." + cur->getName()));
7508 Value *fdiv = pushcse(
7509 B.CreateFMulFMF(pushcse(B.CreateFDivFMF(
7510 ConstantFP::get(cur->getType(), 1.0), b, cur)),
7513 Value *sel = pushcse(
7514 B.CreateSelect(condition, ConstantFP::get(cur->getType(), 0.0),
7515 fdiv,
"sfdiv." + cur->getName()));
7517 replaceAndErase(cur, sel);
7518 return "FDivSIToFPProp";
7522 if (
auto SI = dyn_cast<SelectInst>(prelhs)) {
7523 auto tvalC = dyn_cast<ConstantFP>(SI->getTrueValue());
7524 auto fvalC = dyn_cast<ConstantFP>(SI->getFalseValue());
7525 if ((tvalC && tvalC->isZero()) || (fvalC && fvalC->isZero())) {
7528 (tvalC && tvalC->isZero())
7530 : pushcse(B.CreateFDivFMF(SI->getTrueValue(), b, cur,
7531 "sfdiv2_t." + cur->getName()));
7533 (fvalC && fvalC->isZero())
7535 : pushcse(B.CreateFDivFMF(SI->getFalseValue(), b, cur,
7536 "sfdiv2_f." + cur->getName()));
7540#if LLVM_VERSION_MAJOR < 16
7541 for (
auto v : {ntval, nfval})
7542 if (
auto I = dyn_cast<Instruction>(v))
7543 I->setFastMathFlags(cur->getFastMathFlags());
7546 auto res = pushcse(B.CreateSelect(SI->getCondition(), ntval, nfval,
7547 "sfdiv2." + cur->getName()));
7549 replaceAndErase(cur, res);
7550 return "FDivSelectProp";
7556 if (cur->getOpcode() == Instruction::FDiv) {
7557 auto c = cur->getOperand(1);
7558 if (
auto z = dyn_cast<BinaryOperator>(cur->getOperand(0))) {
7559 if (z->getOpcode() == Instruction::FMul) {
7560 for (
int i = 0; i < 2; i++) {
7562 Value *a = z->getOperand(i);
7563 Value *b = z->getOperand(1 - i);
7569 Value *inner_fdiv = pushcse(B.CreateFDivFMF(a, c, cur));
7570 Value *outer_fmul = pushcse(B.CreateFMulFMF(inner_fdiv, b, z));
7572 replaceAndErase(cur, outer_fmul);
7573 return "FDivFMulSparseProp";
7579 if (cur->getOpcode() == Instruction::FMul)
7580 for (
int i = 0; i < 2; i++) {
7582 Value *prelhs = cur->getOperand(i);
7583 Value *b = cur->getOperand(1 - i);
7586 if (isa<Constant>(b))
7587 if (
auto z = dyn_cast<BinaryOperator>(prelhs)) {
7588 if (z->getOpcode() == Instruction::FMul) {
7589 for (
int j = 0; j < 2; j++) {
7590 auto x = z->getOperand(i);
7591 if (!isa<Constant>(x))
7593 auto y = z->getOperand(1 - i);
7594 Value *inner_fmul = pushcse(B.CreateFMulFMF(x, b, cur));
7595 Value *outer_fmul = pushcse(B.CreateFMulFMF(inner_fmul, y, z));
7597 replaceAndErase(cur, outer_fmul);
7598 return "FMulFMulConstantReorder";
7603 auto integralFloat = [](Value *z) {
7604 if (
auto C = dyn_cast<ConstantFP>(z)) {
7606 bool isExact =
false;
7607 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
7609 if (isExact || C->isZero()) {
7624 if (
auto z = dyn_cast<BinaryOperator>(prelhs)) {
7625 if (z->getOpcode() == Instruction::FMul) {
7626 for (
int j = 0; j < 2; j++) {
7627 auto x = z->getOperand(j);
7630 auto y = z->getOperand(1 - j);
7636 Value *inner_fmul = pushcse(
7637 B.CreateFMulFMF(x, b, cur,
"mulisr." + cur->getName()));
7638 Value *outer_fmul = pushcse(
7639 B.CreateFMulFMF(inner_fmul, y, z,
"mulisr." + z->getName()));
7640 replaceAndErase(cur, outer_fmul);
7641 return "FMulFMulSparseReorder";
7644 Value *inner_fmul = pushcse(
7645 B.CreateFMulFMF(y, b, cur,
"mulisp." + cur->getName()));
7646 Value *outer_fmul = pushcse(
7647 B.CreateFMulFMF(inner_fmul, x, z,
"mulisp." + z->getName()));
7648 replaceAndErase(cur, outer_fmul);
7649 return "FMulFMulSparsePush";
7703 if (
auto SI = dyn_cast<SelectInst>(prelhs)) {
7704 auto tvalC = dyn_cast<ConstantFP>(SI->getTrueValue());
7705 auto fvalC = dyn_cast<ConstantFP>(SI->getFalseValue());
7706 if ((tvalC && tvalC->isZero()) || (fvalC && fvalC->isZero())) {
7709 (tvalC && tvalC->isZero())
7711 : pushcse(B.CreateFMulFMF(SI->getTrueValue(), b, cur));
7713 (fvalC && fvalC->isZero())
7715 : pushcse(B.CreateFMulFMF(SI->getFalseValue(), b, cur));
7716 auto res = pushcse(B.CreateSelect(SI->getCondition(), ntval, nfval,
7717 "mulsi." + cur->getName()));
7719 replaceAndErase(cur, res);
7720 return "FMulSelectProp";
7725 if (
auto icmp = dyn_cast<BinaryOperator>(cur)) {
7726 if (icmp->getOpcode() == Instruction::Xor) {
7727 for (
int i = 0; i < 2; i++) {
7728 if (
auto C = dyn_cast<ConstantInt>(icmp->getOperand(i))) {
7731 if (
auto scmp = dyn_cast<CmpInst>(icmp->getOperand(1 - i))) {
7732 auto next = pushcse(
7733 B.CreateCmp(scmp->getInversePredicate(), scmp->getOperand(0),
7734 scmp->getOperand(1),
"not." + scmp->getName()));
7735 replaceAndErase(cur, next);
7745 if (
auto SI = dyn_cast<SelectInst>(cur)) {
7747 Value *trueVal =
nullptr;
7748 if (
auto C = dyn_cast<ConstantFP>(SI->getTrueValue())) {
7750 trueVal = ConstantInt::getFalse(SI->getContext());
7752 if (C->isExactlyValue(1.0)) {
7753 trueVal = ConstantInt::getTrue(SI->getContext());
7756 if (
auto ext = dyn_cast<CastInst>(SI->getTrueValue())) {
7757 if (ext->getOperand(0)->getType()->isIntegerTy(1))
7758 trueVal = ext->getOperand(0);
7760 Value *falseVal =
nullptr;
7761 if (
auto C = dyn_cast<ConstantFP>(SI->getFalseValue())) {
7763 falseVal = ConstantInt::getFalse(SI->getContext());
7765 if (C->isExactlyValue(1.0)) {
7766 falseVal = ConstantInt::getTrue(SI->getContext());
7769 if (
auto ext = dyn_cast<CastInst>(SI->getFalseValue())) {
7770 if (ext->getOperand(0)->getType()->isIntegerTy(1))
7771 falseVal = ext->getOperand(0);
7773 if (trueVal && falseVal) {
7774 auto ncmp1 = pushcse(B.CreateAnd(SI->getCondition(), trueVal));
7775 auto notV = pushcse(B.CreateNot(SI->getCondition()));
7776 auto ncmp2 = pushcse(B.CreateAnd(notV, falseVal));
7777 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
7778 auto ext = pushcse(B.CreateUIToFP(ori, SI->getType()));
7779 replaceAndErase(cur, ext);
7780 return "SelectI1Ext";
7784 if (cur->getType()->isIntegerTy(1))
7785 if (
auto SI = dyn_cast<SelectInst>(cur)) {
7786 auto ncmp1 = pushcse(B.CreateAnd(SI->getCondition(), SI->getTrueValue()));
7787 auto notV = pushcse(B.CreateNot(SI->getCondition()));
7788 auto ncmp2 = pushcse(B.CreateAnd(notV, SI->getFalseValue()));
7789 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
7790 replaceAndErase(cur, ori);
7794 if (
auto PN = dyn_cast<PHINode>(cur)) {
7796 if (SE.isSCEVable(PN->getType())) {
7797 auto S = SE.getSCEV(PN);
7800 if (
auto SV = dyn_cast<SCEVUnknown>(S)) {
7801 auto val = SV->getValue();
7802 legal |= isa<Constant>(val) || isa<Argument>(val);
7803 if (
auto I = dyn_cast<Instruction>(val)) {
7804 auto L = LI.getLoopFor(I->getParent());
7805 if ((!L || L->getCanonicalInductionVariable() != I) && I != PN)
7809 if (isa<SCEVAddRecExpr>(S)) {
7810 auto L = LI.getLoopFor(PN->getParent());
7812 if (L->getCanonicalInductionVariable() != PN)
7817 for (
auto U : cur->users()) {
7821 auto tmp = cast<PHINode>(pushcse(B.CreatePHI(cur->getType(), 1)));
7822 cur->replaceAllUsesWith(tmp);
7823 cur->eraseFromParent();
7825 Value *newIV =
nullptr;
7827#if LLVM_VERSION_MAJOR >= 22
7828 SCEVExpander Exp(SE,
"sparseenzyme");
7830 SCEVExpander Exp(SE, DL,
"sparseenzyme");
7834 newIV = Exp.expandCodeFor(S, tmp->getType(), point);
7836 for (
auto I : Exp.getAllInsertedInstructions())
7840 tmp->replaceAllUsesWith(newIV);
7841 tmp->eraseFromParent();
7842 return "InductVarSCEV";
7848 for (
size_t i = 1; i < PN->getNumIncomingValues(); i++) {
7849 auto v = PN->getIncomingValue(i);
7850 if (v != PN->getIncomingValue(0)) {
7856 auto val = PN->getIncomingValue(0);
7857 replaceAndErase(cur, val);
7862 if (
auto L = LI.getLoopFor(PN->getParent()))
7863 if (L->getHeader() == PN->getParent())
7864 if (
auto idx = L->getCanonicalInductionVariable())
7865 if (
auto PH = L->getLoopPreheader()) {
7866 bool legal = idx != PN;
7867 auto ph_idx = PN->getBasicBlockIndex(PH);
7868 assert(ph_idx >= 0);
7869 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
7870 if ((
int)i == ph_idx)
7872 auto v = PN->getIncomingValue(i);
7873 if (v != PN->getIncomingValue(1 - ph_idx)) {
7878 if (isa<Constant>(v))
7880 if (isa<Argument>(v))
7885 auto I = cast<Instruction>(v);
7886 if (!DT.dominates(I, PN)) {
7892 auto val = PN->getIncomingValue(1 - ph_idx);
7896 B.CreateSub(idx, ConstantInt::get(idx->getType(), 1)));
7899 auto val2 = PN->getIncomingValue(ph_idx);
7902 auto c0 = ConstantInt::get(idx->getType(), 0);
7906 auto eq = pushcse(B.CreateICmpEQ(idx, c0));
7908 B.CreateSelect(eq, val2, val,
"phisel." + cur->getName()));
7911 replaceAndErase(cur, val);
7912 return "PhiLoop0Sel";
7917 SmallVector<Value *, 1> negOps;
7918 SmallVector<Instruction *, 1> prevNegOps;
7920 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
7921 auto v = PN->getIncomingValue(i);
7922 if (
auto C = dyn_cast<ConstantFP>(v)) {
7924 bool isExact =
false;
7925 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
7927 if (isExact || C->isZero()) {
7928 negOps.push_back(ConstantInt::get(B.getInt64Ty(), Tmp));
7932 if (
auto fneg = dyn_cast<Instruction>(v)) {
7933 if (fneg->getOpcode() == Instruction::SIToFP &&
7934 cast<IntegerType>(fneg->getOperand(0)->getType())
7935 ->getBitWidth() == 64) {
7936 negOps.push_back(fneg->getOperand(0));
7937 prevNegOps.push_back(fneg);
7944 auto PN2 = cast<PHINode>(
7945 pushcse(B.CreatePHI(B.getInt64Ty(), PN->getNumIncomingValues())));
7947 for (
auto val : llvm::enumerate(negOps))
7948 PN2->addIncoming(val.value(), PN->getIncomingBlock(val.index()));
7952 auto fneg = pushcse(B.CreateSIToFP(PN2, PN->getType()));
7954 for (
auto I : prevNegOps)
7956 replaceAndErase(cur, fneg);
7962 SmallVector<Value *, 1> negOps;
7963 SmallVector<Instruction *, 1> prevNegOps;
7965 bool hasNeg =
false;
7966 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
7967 auto v = PN->getIncomingValue(i);
7968 if (
auto C = dyn_cast<ConstantFP>(v)) {
7969 negOps.push_back(C->isZero() ? C : pushcse(B.CreateFNeg(C)));
7972 if (
auto fneg = dyn_cast<Instruction>(v)) {
7973 if (fneg->getOpcode() == Instruction::FNeg) {
7974 negOps.push_back(fneg->getOperand(0));
7975 prevNegOps.push_back(fneg);
7981 if (legal && hasNeg) {
7982 for (
auto val : llvm::enumerate(negOps))
7983 PN->setIncomingValue(val.index(), val.value());
7987 auto fneg = pushcse(B.CreateFNeg(PN));
7989 for (
auto &U : cur->uses()) {
7990 if (U.getUser() == fneg)
7995 for (
auto I : prevNegOps)
8002 SmallVector<Value *, 1> negOps;
8003 SmallVector<Instruction *, 1> prevNegOps;
8005 bool hasNeg =
false;
8006 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
8007 auto v = PN->getIncomingValue(i);
8008 if (
auto C = dyn_cast<ConstantInt>(v)) {
8009 negOps.push_back(pushcse(B.CreateNeg(C)));
8012 if (
auto fneg = dyn_cast<BinaryOperator>(v)) {
8013 if (
auto CI = dyn_cast<ConstantInt>(fneg->getOperand(0)))
8014 if (fneg->getOpcode() == Instruction::Sub && CI->isZero()) {
8015 negOps.push_back(fneg->getOperand(1));
8016 prevNegOps.push_back(fneg);
8023 if (legal && hasNeg) {
8024 for (
auto val : llvm::enumerate(negOps))
8025 PN->setIncomingValue(val.index(), val.value());
8029 auto fneg = pushcse(B.CreateNeg(PN));
8031 for (
auto &U : cur->uses()) {
8032 if (U.getUser() == fneg)
8037 for (
auto I : prevNegOps)
8046 {(unsigned)Instruction::Mul, (
unsigned)Instruction::Sub,
8047 (unsigned)Instruction::Add, (
unsigned)Instruction::ZExt,
8048 (unsigned)Instruction::UIToFP, (
unsigned)Instruction::ICmp,
8049 (unsigned)Instruction::FMul, (
unsigned)Instruction::Or,
8050 (unsigned)Instruction::And}) {
8051 SmallVector<Value *, 1> lhsOps;
8052 SmallVector<Value *, 1> rhsOps;
8053 SmallVector<Instruction *, 1> prevOps;
8059 std::optional<llvm::CmpInst::Predicate> cmpPredicate;
8061 case Instruction::FMul:
8062 case Instruction::FSub:
8063 case Instruction::FAdd:
8067 case Instruction::Mul:
8068 case Instruction::Add:
8072 case Instruction::Sub:
8076 case Instruction::ICmp:
8077 case Instruction::FCmp:
8078 case Instruction::Or:
8079 case Instruction::And:
8082 case Instruction::ZExt:
8083 case Instruction::UIToFP:
8087 llvm_unreachable(
"unknown opcode");
8089 bool changed =
false;
8090 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
8091 auto v = PN->getIncomingValue(i);
8092 if (
auto C = dyn_cast<ConstantInt>(v)) {
8093 if (code == Instruction::ZExt) {
8094 lhsOps.push_back(ConstantInt::getFalse(C->getContext()));
8096 }
else if (C->isZero()) {
8097 rhsOps.push_back(C);
8098 lhsOps.push_back(C);
8102 if (
auto C = dyn_cast<ConstantFP>(v)) {
8103 if (code == Instruction::UIToFP) {
8105 lhsOps.push_back(ConstantInt::getFalse(C->getContext()));
8107 }
else if (code == Instruction::FMul || code == Instruction::FSub ||
8108 code == Instruction::FAdd) {
8110 rhsOps.push_back(C);
8111 lhsOps.push_back(C);
8116 if (
auto fneg = dyn_cast<Instruction>(v)) {
8117 if (fneg->getOpcode() == code) {
8119 case Instruction::FMul:
8120 case Instruction::FSub:
8121 case Instruction::FAdd:
8122 fast &= fneg->isFast();
8123 if (fneg->getOperand(0) == PN)
8125 if (fneg->getOperand(1) == PN)
8127 lhsOps.push_back(fneg->getOperand(0));
8128 rhsOps.push_back(fneg->getOperand(1));
8130 case Instruction::Mul:
8131 case Instruction::Sub:
8132 case Instruction::Add:
8133 NUW &= fneg->hasNoUnsignedWrap();
8134 NSW &= fneg->hasNoSignedWrap();
8135 if (fneg->getOperand(0) == PN)
8137 if (fneg->getOperand(1) == PN)
8139 lhsOps.push_back(fneg->getOperand(0));
8140 rhsOps.push_back(fneg->getOperand(1));
8142 case Instruction::Or:
8143 case Instruction::And:
8144 if (fneg->getOperand(0) == PN)
8146 if (fneg->getOperand(1) == PN)
8148 lhsOps.push_back(fneg->getOperand(0));
8149 rhsOps.push_back(fneg->getOperand(1));
8151 case Instruction::ICmp:
8152 case Instruction::FCmp:
8153 if (fneg->getOperand(0) == PN)
8155 if (fneg->getOperand(1) == PN)
8158 if (*cmpPredicate != cast<CmpInst>(fneg)->getPredicate())
8161 cmpPredicate = cast<CmpInst>(fneg)->getPredicate();
8163 lhsOps.push_back(fneg->getOperand(0));
8164 rhsOps.push_back(fneg->getOperand(1));
8166 case Instruction::ZExt:
8167 case Instruction::UIToFP:
8168 if (cast<IntegerType>(fneg->getOperand(0)->getType())
8169 ->getBitWidth() != 1)
8171 lhsOps.push_back(fneg->getOperand(0));
8174 llvm_unreachable(
"unhandled opcode");
8176 prevOps.push_back(fneg);
8184 int preheader_fix = -1;
8186 if (code == Instruction::ICmp || code == Instruction::FCmp) {
8189 auto L = LI.getLoopFor(PN->getParent());
8190 if (legal && L && L->getLoopPreheader() &&
8191 L->getCanonicalInductionVariable() &&
8192 L->getHeader() == PN->getParent()) {
8193 auto ph_idx = PN->getBasicBlockIndex(L->getLoopPreheader());
8194 if (isa<ConstantInt>(PN->getIncomingValue(ph_idx))) {
8196 Constant::getNullValue(lhsOps[1 - ph_idx]->getType());
8198 Constant::getNullValue(rhsOps[1 - ph_idx]->getType());
8199 preheader_fix = ph_idx;
8202 for (
auto v : lhsOps)
8203 if (v->getType() != lhsOps[0]->getType())
8205 for (
auto v : rhsOps)
8206 if (v->getType() != rhsOps[0]->getType())
8210 if (legal && changed) {
8211 auto lhsPN = cast<PHINode>(pushcse(
8212 B.CreatePHI(lhsOps[0]->getType(), PN->getNumIncomingValues())));
8213 PHINode *rhsPN =
nullptr;
8215 rhsPN = cast<PHINode>(pushcse(
8216 B.CreatePHI(rhsOps[0]->getType(), PN->getNumIncomingValues())));
8218 for (
auto val : llvm::enumerate(lhsOps))
8219 lhsPN->addIncoming(val.value(), PN->getIncomingBlock(val.index()));
8222 for (
auto val : llvm::enumerate(rhsOps))
8223 rhsPN->addIncoming(val.value(),
8224 PN->getIncomingBlock(val.index()));
8227 Value *fneg =
nullptr;
8229 case Instruction::FMul:
8230 fneg = B.CreateFMul(lhsPN, rhsPN);
8231 if (
auto I = dyn_cast<Instruction>(fneg))
8234 case Instruction::FAdd:
8235 fneg = B.CreateFAdd(lhsPN, rhsPN);
8236 if (
auto I = dyn_cast<Instruction>(fneg))
8239 case Instruction::FSub:
8240 fneg = B.CreateFSub(lhsPN, rhsPN);
8241 if (
auto I = dyn_cast<Instruction>(fneg))
8244 case Instruction::Mul:
8245 fneg = B.CreateMul(lhsPN, rhsPN,
"", NUW, NSW);
8247 case Instruction::Add:
8248 fneg = B.CreateAdd(lhsPN, rhsPN,
"", NUW, NSW);
8250 case Instruction::Sub:
8251 fneg = B.CreateSub(lhsPN, rhsPN,
"", NUW, NSW);
8253 case Instruction::ZExt:
8254 fneg = B.CreateZExt(lhsPN, PN->getType());
8256 case Instruction::FCmp:
8257 case Instruction::ICmp:
8258 fneg = B.CreateCmp(*cmpPredicate, lhsPN, rhsPN);
8260 case Instruction::UIToFP:
8261 fneg = B.CreateUIToFP(lhsPN, PN->getType());
8263 case Instruction::Or:
8264 fneg = B.CreateOr(lhsPN, rhsPN);
8266 case Instruction::And:
8267 fneg = B.CreateAnd(lhsPN, rhsPN);
8270 llvm_unreachable(
"unhandled opcode");
8275 if (preheader_fix != -1) {
8276 auto L = LI.getLoopFor(PN->getParent());
8277 auto idx = L->getCanonicalInductionVariable();
8279 B.CreateICmpEQ(idx, ConstantInt::get(idx->getType(), 0)));
8281 pushcse(B.CreateSelect(eq, PN->getIncomingValue(preheader_fix),
8282 fneg,
"phphisel." + cur->getName()));
8285 replaceAndErase(cur, fneg);
8291 if (PN->getNumIncomingValues() == 2) {
8292 for (
int i = 0; i < 2; i++) {
8293 auto prev = PN->getIncomingBlock(i);
8294 if (!DT.dominates(prev, PN->getParent())) {
8298 ? cast<Instruction>(prev->getTerminator())
8306 if (br->getSuccessor(0) != PN->getParent()) {
8309 if (br->getSuccessor(1) != PN->getIncomingBlock(1 - i)) {
8313 Value *specVal = PN->getIncomingValue(1 - i);
8314 SetVector<Value *, std::deque<Value *>> todo;
8315 todo.insert(specVal);
8316 SetVector<Instruction *> toMove;
8318 while (!todo.empty()) {
8319 auto cur = *todo.begin();
8320 todo.erase(todo.begin());
8321 auto I = dyn_cast<Instruction>(cur);
8324 if (I->mayReadOrWriteMemory()) {
8328 if (DT.dominates(I, PN))
8330 for (
size_t i = 0; i < I->getNumOperands(); i++)
8331 todo.insert(I->getOperand(i));
8336 for (
auto iter = toMove.rbegin(), end = toMove.rend(); iter != end;
8340 auto sel = pushcse(B.CreateSelect(
8342 PN->getIncomingValueForBlock(br->getSuccessor(1)),
8343 "tphisel." + cur->getName()));
8345 replaceAndErase(cur, sel);
8351 if (
auto SI = dyn_cast<SelectInst>(cur)) {
8352 auto tval = replace(SI->getTrueValue(), SI->getCondition(),
8353 ConstantInt::getTrue(SI->getContext()));
8354 auto fval = replace(SI->getFalseValue(), SI->getCondition(),
8355 ConstantInt::getFalse(SI->getContext()));
8356 if (tval != SI->getTrueValue() || fval != SI->getFalseValue()) {
8357 auto res = pushcse(B.CreateSelect(SI->getCondition(), tval, fval,
8358 "postsel." + SI->getName()));
8359 replaceAndErase(cur, res);
8360 return "SelectReplace";
8365 if (cur->getOpcode() == Instruction::And) {
8366 auto lhs = replace(cur->getOperand(0), cur->getOperand(1),
8367 ConstantInt::getTrue(cur->getContext()));
8368 if (lhs != cur->getOperand(0)) {
8370 B.CreateAnd(lhs, cur->getOperand(1),
"postand." + cur->getName()));
8371 replaceAndErase(cur, res);
8372 return "AndReplaceLHS";
8374 auto rhs = replace(cur->getOperand(1), cur->getOperand(0),
8375 ConstantInt::getTrue(cur->getContext()));
8376 if (rhs != cur->getOperand(1)) {
8378 B.CreateAnd(cur->getOperand(0), rhs,
"postand." + cur->getName()));
8379 replaceAndErase(cur, res);
8380 return "AndReplaceRHS";
8385 if (cur->getOpcode() == Instruction::Or) {
8386 auto lhs = replace(cur->getOperand(0), cur->getOperand(1),
8387 ConstantInt::getFalse(cur->getContext()));
8388 if (lhs != cur->getOperand(0)) {
8390 B.CreateOr(lhs, cur->getOperand(1),
"postor." + cur->getName()));
8391 replaceAndErase(cur, res);
8392 return "OrReplaceLHS";
8394 auto rhs = replace(cur->getOperand(1), cur->getOperand(0),
8395 ConstantInt::getFalse(cur->getContext()));
8396 if (rhs != cur->getOperand(1)) {
8398 B.CreateOr(cur->getOperand(0), rhs,
"postor." + cur->getName()));
8399 replaceAndErase(cur, res);
8400 return "OrReplaceRHS";