3689 ScalarEvolution &SE, LoopInfo &LI,
3690 const DataLayout &DL) {
3691 auto push = [&](llvm::Value *V) {
3695 if (
auto I = dyn_cast<Instruction>(V)) {
3697 for (
auto U : I->users()) {
3698 if (
auto I2 = dyn_cast<Instruction>(U)) {
3707 auto pushcse = [&](llvm::Value *V) -> llvm::Value * {
3708 if (
auto I = dyn_cast<Instruction>(V)) {
3709 for (
size_t i = 0; i < I->getNumOperands(); i++) {
3710 if (
auto I2 = dyn_cast<Instruction>(I->getOperand(i))) {
3711 Instruction *candidate =
nullptr;
3712 for (
auto U : I2->users()) {
3713 candidate = dyn_cast<Instruction>(U);
3716 if (candidate == I && candidate->getType() != I->getType()) {
3717 candidate =
nullptr;
3720 bool isSame = candidate->isIdenticalTo(I);
3724 std::multiset<llvm::Value *> s1;
3725 std::multiset<llvm::Value *> s2;
3732 if (
auto P1 =
isSum(I))
3733 if (
auto P2 =
isSum(I2)) {
3734 std::multiset<llvm::Value *> s1;
3735 std::multiset<llvm::Value *> s2;
3744 candidate =
nullptr;
3748 if (DT.dominates(candidate, I)) {
3751 candidate =
nullptr;
3754 I->eraseFromParent();
3764 auto replaceAndErase = [&](llvm::Instruction *I, llvm::Value *candidate) {
3765 for (
auto U : I->users())
3767 I->replaceAllUsesWith(candidate);
3770 SetVector<Instruction *> operands;
3771 for (
size_t i = 0; i < I->getNumOperands(); i++) {
3772 if (
auto I2 = dyn_cast<Instruction>(I->getOperand(i))) {
3773 if ((!I2->mayWriteToMemory() ||
3774 (isa<CallInst>(I2) &&
isReadOnly(cast<CallInst>(I2)))))
3775 operands.insert(I2);
3782 I->eraseFromParent();
3783 for (
auto op : operands)
3784 if (op->getNumUses() == 0) {
3787 op->eraseFromParent();
3790 if (!cur->getType()->isVoidTy() &&
3791 (!cur->mayWriteToMemory() ||
3792 (isa<CallInst>(cur) &&
isReadOnly(cast<CallInst>(cur))))) {
3794 if (cur->getNumUses() == 0) {
3795 for (
size_t i = 0; i < cur->getNumOperands(); i++)
3796 push(cur->getOperand(i));
3798 cur->eraseFromParent();
3803 for (
size_t i = 0; i < cur->getNumOperands(); i++) {
3804 if (
auto I = dyn_cast<Instruction>(cur->getOperand(i))) {
3805 Instruction *candidate =
nullptr;
3806 bool reverse =
false;
3807 for (
auto U : I->users()) {
3808 candidate = dyn_cast<Instruction>(U);
3811 if (candidate == cur && candidate->getType() != cur->getType()) {
3812 candidate =
nullptr;
3815 bool isSame = candidate->isIdenticalTo(cur);
3819 std::multiset<llvm::Value *> s1;
3820 std::multiset<llvm::Value *> s2;
3827 if (
auto P1 =
isSum(candidate))
3828 if (
auto P2 =
isSum(cur)) {
3829 std::multiset<llvm::Value *> s1;
3830 std::multiset<llvm::Value *> s2;
3840 candidate =
nullptr;
3844 if (DT.dominates(candidate, cur)) {
3846 }
else if (DT.dominates(cur, candidate)) {
3850 candidate =
nullptr;
3856 auto tmp = candidate;
3860 replaceAndErase(cur, candidate);
3869 if (
auto SI = dyn_cast<SelectInst>(cur))
3870 if (
auto CI = dyn_cast<ConstantInt>(SI->getCondition())) {
3872 replaceAndErase(cur, SI->getTrueValue());
3873 return "SelectToTrue";
3875 replaceAndErase(cur, SI->getFalseValue());
3876 return "SelectToFalse";
3879 if (cur->getOpcode() == Instruction::Or) {
3880 for (
int i = 0; i < 2; i++) {
3881 if (
auto C = dyn_cast<ConstantInt>(cur->getOperand(i))) {
3884 replaceAndErase(cur, cur->getOperand(1 - i));
3888 if (C->isOne() && cur->getType()->isIntegerTy(1)) {
3889 replaceAndErase(cur, C);
3895 if (cur->getOpcode() == Instruction::And) {
3896 for (
int i = 0; i < 2; i++) {
3897 if (
auto C = dyn_cast<ConstantInt>(cur->getOperand(i))) {
3899 if (C->isOne() && cur->getType()->isIntegerTy(1)) {
3900 replaceAndErase(cur, cur->getOperand(1 - i));
3905 replaceAndErase(cur, C);
3913 if (
auto CI = dyn_cast<CastInst>(cur))
3914 if (
auto C = dyn_cast<Constant>(CI->getOperand(0))) {
3916 cur, cast<Constant>(B.CreateCast(CI->getOpcode(), C, CI->getType())));
3917 return "CastConstProp";
3919 std::function<Value *(Value *, Value *, Value *)> replace = [&](Value *val,
3925 if (
isNot(val, orig)) {
3926 return pushcse(B.CreateNot(with));
3928 if (isa<PHINode>(val))
3931 if (
auto I = dyn_cast<Instruction>(val)) {
3932 if (I->mayWriteToMemory() &&
3933 !(isa<CallInst>(I) &&
isReadOnly(cast<CallInst>(I))))
3936 if (I->getOpcode() == Instruction::Add) {
3937 Value *lhs = replace(I->getOperand(0), orig, with);
3938 Value *rhs = replace(I->getOperand(1), orig, with);
3939 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
3942 return pushcse(B.CreateAdd(lhs, rhs,
"sel." + I->getName(),
3943 I->hasNoUnsignedWrap(),
3944 I->hasNoSignedWrap()));
3947 if (I->getOpcode() == Instruction::Sub) {
3948 Value *lhs = replace(I->getOperand(0), orig, with);
3949 Value *rhs = replace(I->getOperand(1), orig, with);
3950 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
3953 return pushcse(B.CreateSub(lhs, rhs,
"sel." + I->getName(),
3954 I->hasNoUnsignedWrap(),
3955 I->hasNoSignedWrap()));
3958 if (I->getOpcode() == Instruction::Mul) {
3959 Value *lhs = replace(I->getOperand(0), orig, with);
3960 Value *rhs = replace(I->getOperand(1), orig, with);
3961 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
3964 return pushcse(B.CreateMul(lhs, rhs,
"sel." + I->getName(),
3965 I->hasNoUnsignedWrap(),
3966 I->hasNoSignedWrap()));
3969 if (I->getOpcode() == Instruction::And) {
3970 Value *lhs = replace(I->getOperand(0), orig, with);
3971 Value *rhs = replace(I->getOperand(1), orig, with);
3972 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
3975 return pushcse(B.CreateAnd(lhs, rhs,
"sel." + I->getName()));
3978 if (I->getOpcode() == Instruction::Or) {
3979 Value *lhs = replace(I->getOperand(0), orig, with);
3980 Value *rhs = replace(I->getOperand(1), orig, with);
3981 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
3984 return pushcse(B.CreateOr(lhs, rhs,
"sel." + I->getName()));
3987 if (I->getOpcode() == Instruction::Xor) {
3988 Value *lhs = replace(I->getOperand(0), orig, with);
3989 Value *rhs = replace(I->getOperand(1), orig, with);
3990 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
3993 return pushcse(B.CreateXor(lhs, rhs,
"sel." + I->getName()));
3996 if (I->getOpcode() == Instruction::FAdd) {
3997 Value *lhs = replace(I->getOperand(0), orig, with);
3998 Value *rhs = replace(I->getOperand(1), orig, with);
3999 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
4002 return pushcse(B.CreateFAddFMF(lhs, rhs, I,
"sel." + I->getName()));
4005 if (I->getOpcode() == Instruction::FSub) {
4006 Value *lhs = replace(I->getOperand(0), orig, with);
4007 Value *rhs = replace(I->getOperand(1), orig, with);
4008 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
4011 return pushcse(B.CreateFSubFMF(lhs, rhs, I,
"sel." + I->getName()));
4014 if (I->getOpcode() == Instruction::FMul) {
4015 Value *lhs = replace(I->getOperand(0), orig, with);
4016 Value *rhs = replace(I->getOperand(1), orig, with);
4017 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
4020 return pushcse(B.CreateFMulFMF(lhs, rhs, I,
"sel." + I->getName()));
4023 if (I->getOpcode() == Instruction::ZExt) {
4024 Value *op = replace(I->getOperand(0), orig, with);
4025 if (op == I->getOperand(0))
4028 return pushcse(B.CreateZExt(op, I->getType(),
"sel." + I->getName()));
4031 if (I->getOpcode() == Instruction::SExt) {
4032 Value *op = replace(I->getOperand(0), orig, with);
4033 if (op == I->getOperand(0))
4036 return pushcse(B.CreateSExt(op, I->getType(),
"sel." + I->getName()));
4039 if (I->getOpcode() == Instruction::UIToFP) {
4040 Value *op = replace(I->getOperand(0), orig, with);
4041 if (op == I->getOperand(0))
4044 return pushcse(B.CreateUIToFP(op, I->getType(),
"sel." + I->getName()));
4047 if (I->getOpcode() == Instruction::SIToFP) {
4048 Value *op = replace(I->getOperand(0), orig, with);
4049 if (op == I->getOperand(0))
4052 return pushcse(B.CreateSIToFP(op, I->getType(),
"sel." + I->getName()));
4055 if (
auto CI = dyn_cast<CmpInst>(I)) {
4056 Value *lhs = replace(I->getOperand(0), orig, with);
4057 Value *rhs = replace(I->getOperand(1), orig, with);
4058 if (lhs == I->getOperand(0) && rhs == I->getOperand(1))
4062 B.CreateCmp(CI->getPredicate(), lhs, rhs,
"sel." + I->getName()));
4065 if (
auto SI = dyn_cast<SelectInst>(I)) {
4066 Value *cond = replace(SI->getCondition(), orig, with);
4067 Value *tval = replace(SI->getTrueValue(), orig, with);
4068 Value *fval = replace(SI->getFalseValue(), orig, with);
4069 if (cond == SI->getCondition() && tval == SI->getTrueValue() &&
4070 fval == SI->getFalseValue())
4073 if (
auto CI = dyn_cast<ConstantInt>(cond)) {
4079 return pushcse(B.CreateSelect(cond, tval, fval,
"sel." + I->getName()));
4083 auto C = cast<CallBase>(I);
4085 bool changed =
false;
4086 for (
auto &op : ops) {
4087 auto next = replace(op, orig, with);
4103 if (
auto II = dyn_cast<IntrinsicInst>(cur))
4104 if (II->getIntrinsicID() == Intrinsic::fmuladd ||
4105 II->getIntrinsicID() == Intrinsic::fma) {
4106 B.setFastMathFlags(
getFast());
4107 auto mul = pushcse(B.CreateFMul(II->getOperand(0), II->getOperand(1)));
4108 auto add = pushcse(B.CreateFAdd(mul, II->getOperand(2)));
4109 replaceAndErase(cur, add);
4110 return "FMulAddExpand";
4113 if (
auto BO = dyn_cast<BinaryOperator>(cur)) {
4114 if (BO->getOpcode() == Instruction::FMul && BO->isFast()) {
4115 Value *args[2] = {BO->getOperand(0), BO->getOperand(1)};
4119 replaceAndErase(cur, mul);
4120 return "FMulToProduct";
4122 if (BO->getOpcode() == Instruction::FDiv && BO->isFast()) {
4123 auto c0 = dyn_cast<ConstantFP>(BO->getOperand(0));
4124 if (!c0 || !c0->isExactlyValue(1.0)) {
4125 B.setFastMathFlags(
getFast());
4126 auto div = pushcse(B.CreateFDivFMF(ConstantFP::get(BO->getType(), 1.0),
4127 BO->getOperand(1), BO));
4129 B.CreateFMulFMF(BO->getOperand(0), div, BO, cur->getName()));
4130 replaceAndErase(cur, mul);
4131 return "FDivToFMul";
4134 if (BO->getOpcode() == Instruction::FAdd && BO->isFast()) {
4135 Value *args[2] = {BO->getOperand(0), BO->getOperand(1)};
4138 replaceAndErase(cur, mul);
4141 if (BO->getOpcode() == Instruction::FSub && BO->isFast()) {
4142 B.setFastMathFlags(
getFast());
4143 Value *args[2] = {BO->getOperand(0),
4144 pushcse(B.CreateFNeg(BO->getOperand(1)))};
4147 args, cur->getName()));
4148 replaceAndErase(cur, mul);
4152 if (cur->getOpcode() == Instruction::FNeg) {
4153 B.setFastMathFlags(
getFast());
4155 pushcse(B.CreateFMulFMF(ConstantFP::get(cur->getType(), -1.0),
4156 cur->getOperand(0), cur, cur->getName()));
4157 replaceAndErase(cur, mul);
4161 if (
auto SI = dyn_cast<SelectInst>(cur)) {
4162 if (
auto tc = dyn_cast<ConstantFP>(SI->getTrueValue()))
4163 if (
auto fc = dyn_cast<ConstantFP>(SI->getFalseValue()))
4165 if (tc->isExactlyValue(1.0)) {
4167 pushcse(B.CreateUIToFP(SI->getCondition(), tc->getType()));
4168 replaceAndErase(cur, res);
4171 if (tc->isExactlyValue(-1.0)) {
4173 pushcse(B.CreateSIToFP(SI->getCondition(), tc->getType()));
4174 replaceAndErase(cur, res);
4181 SmallVector<Value *, 1> operands;
4182 std::optional<APFloat> constval;
4183 bool changed =
false;
4190 operands.push_back(v2);
4196 if (
auto C = dyn_cast<ConstantFP>(v)) {
4197 if (C->isExactlyValue(1.0)) {
4202 replaceAndErase(cur, C);
4203 return "ZeroProduct";
4206 constval = C->getValue();
4209 constval = (*constval) * C->getValue();
4213 if (
auto op = dyn_cast<SelectInst>(v)) {
4214 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
4216 operands.push_back(pushcse(B.CreateUIToFP(
4217 pushcse(B.CreateNot(op->getCondition())), op->getType())));
4218 operands.push_back(op->getFalseValue());
4222 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
4225 pushcse(B.CreateUIToFP(op->getCondition(), op->getType())));
4226 operands.push_back(op->getTrueValue());
4231 operands.push_back(v);
4234 operands.push_back(ConstantFP::get(cur->getType(), *constval));
4236 if (operands.size() == 0) {
4237 replaceAndErase(cur, ConstantFP::get(cur->getType(), 1.0));
4238 return "EmptyProduct";
4240 if (operands.size() == 1) {
4241 replaceAndErase(cur, operands[0]);
4242 return "SingleProduct";
4247 operands, cur->getName()));
4248 replaceAndErase(cur, mul);
4249 return "ProductSimplification";
4253 if (
auto P =
isSum(cur)) {
4255 std::map<Value *, unsigned> operands;
4256 std::optional<APFloat> constval;
4257 bool changed =
false;
4259 if (
auto P2 =
isSum(v)) {
4268 if (
auto C = dyn_cast<ConstantFP>(v)) {
4269 if (C->isExactlyValue(0.0)) {
4274 constval = C->getValue();
4277 constval = (*constval) + C->getValue();
4284 operands[ConstantFP::get(cur->getType(), *constval)]++;
4286 if (operands.size() == 0) {
4287 replaceAndErase(cur, ConstantFP::get(cur->getType(), 0.0));
4290 SmallVector<Value *, 1> args;
4291 for (
auto &pair : operands) {
4292 if (pair.second == 1) {
4293 args.push_back(pair.first);
4297 Value *sargs[] = {pair.first,
4298 ConstantFP::get(cur->getType(), (
double)pair.second)};
4299 args.push_back(pushcse(B.CreateCall(
4302 if (args.size() == 1) {
4303 replaceAndErase(cur, args[0]);
4309 args, cur->getName()));
4310 replaceAndErase(cur, sum);
4311 return "SumSimplification";
4316 SmallVector<Value *, 1> operands;
4317 SmallVector<Value *, 1> conditions;
4320 if (
auto op = dyn_cast<UIToFPInst>(v)) {
4321 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
4322 conditions.push_back(op->getOperand(0));
4327 if (
auto op = dyn_cast<SIToFPInst>(v)) {
4328 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
4329 conditions.push_back(op->getOperand(0));
4330 operands.push_back(ConstantFP::get(cur->getType(), -1.0));
4334 if (
auto op = dyn_cast<SelectInst>(v)) {
4335 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
4337 conditions.push_back(pushcse(B.CreateNot(op->getCondition())));
4338 operands.push_back(op->getFalseValue());
4341 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
4343 conditions.push_back(op->getCondition());
4344 operands.push_back(op->getTrueValue());
4348 operands.push_back(v);
4351 if (conditions.size()) {
4352 auto mul = pushcse(B.CreateCall(
4354 Value *condition =
nullptr;
4355 for (
auto v : conditions) {
4356 assert(v->getType()->isIntegerTy(1));
4357 if (condition ==
nullptr) {
4361 condition = pushcse(B.CreateAnd(condition, v));
4363 auto zero = ConstantFP::get(cur->getType(), 0.0);
4364 auto sel = pushcse(B.CreateSelect(condition, mul, zero, cur->getName()));
4365 replaceAndErase(cur, sel);
4366 return "ProductSelect";
4371 if (
auto P =
isSum(cur)) {
4373 SmallVector<std::pair<Value *, bool>, 1> conditions;
4377 if (
auto op = dyn_cast<UIToFPInst>(v)) {
4378 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
4379 conditions.emplace_back(op->getOperand(0),
false);
4384 if (
auto op = dyn_cast<SIToFPInst>(v)) {
4385 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
4386 conditions.emplace_back(op->getOperand(0),
false);
4390 if (
auto op = dyn_cast<SelectInst>(v)) {
4391 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
4393 conditions.emplace_back(op->getCondition(),
true);
4396 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
4398 conditions.emplace_back(op->getCondition(),
false);
4405 Value *condition =
nullptr;
4407 for (
size_t i = 0; i < conditions.size(); i++) {
4409 for (
size_t j = 0; j < conditions.size(); j++) {
4410 if (((conditions[i].first == conditions[j].first) &&
4411 (conditions[i].second == conditions[i].second)) ||
4412 ((
isNot(conditions[i].first, conditions[j].first) &&
4413 (conditions[i].second != conditions[i].second))))
4416 if (count == conditions.size() && count > 1) {
4417 condition = conditions[i].first;
4418 if (conditions[i].second)
4419 condition = pushcse(B.CreateNot(condition,
"sumpnot"));
4426 SmallVector<Value *, 1> operands;
4429 if (
auto op = dyn_cast<UIToFPInst>(v)) {
4430 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
4431 operands.push_back(ConstantFP::get(cur->getType(), 1.0));
4436 if (
auto op = dyn_cast<SIToFPInst>(v)) {
4437 if (op->getOperand(0)->getType()->isIntegerTy(1)) {
4438 operands.push_back(ConstantFP::get(cur->getType(), -1.0));
4442 if (
auto op = dyn_cast<SelectInst>(v)) {
4443 if (
auto tc = dyn_cast<ConstantFP>(op->getTrueValue()))
4445 operands.push_back(op->getFalseValue());
4448 if (
auto tc = dyn_cast<ConstantFP>(op->getFalseValue()))
4450 operands.push_back(op->getTrueValue());
4454 llvm::errs() <<
" unhandled call op sumselect: " << *v <<
"\n";
4458 if (conditions.size()) {
4459 auto sum = pushcse(B.CreateCall(
4461 auto zero = ConstantFP::get(cur->getType(), 0.0);
4463 pushcse(B.CreateSelect(condition, sum, zero, cur->getName()));
4464 replaceAndErase(cur, sel);
4470 if (
auto S =
isSum(cur)) {
4471 SmallVector<Value *, 1> allOps;
4472 auto combine = [](
const SmallVector<Value *, 1> &lhs,
4473 SmallVector<Value *, 1> rhs) {
4474 SmallVector<Value *, 1> out;
4475 for (
auto v : lhs) {
4477 for (
auto &v2 : rhs) {
4490 auto subtract = [](SmallVector<Value *, 1> lhs,
4491 const SmallVector<Value *, 1> &rhs) {
4492 for (
auto v : rhs) {
4493 auto found = find(lhs, v);
4494 assert(found != lhs.end());
4515 if (legal && allOps.size() > 0) {
4516 SmallVector<Value *, 1> operands;
4521 auto newprod = pushcse(B.CreateCall(
4523 operands.push_back(newprod);
4525 auto newsum = pushcse(B.CreateCall(
4527 allOps.push_back(newsum);
4528 auto fprod = pushcse(B.CreateCall(
4530 replaceAndErase(cur, fprod);
4567 if (
auto fcmp = dyn_cast<FCmpInst>(cur)) {
4568 auto predicate = fcmp->getPredicate();
4569 if (predicate == FCmpInst::FCMP_OEQ || predicate == FCmpInst::FCMP_UEQ ||
4570 predicate == FCmpInst::FCMP_UNE || predicate == FCmpInst::FCMP_ONE) {
4571 for (
int i = 0; i < 2; i++)
4572 if (
auto C = dyn_cast<ConstantFP>(fcmp->getOperand(i))) {
4578 if (
auto P =
isProduct(fcmp->getOperand(1 - i))) {
4579 Value *res =
nullptr;
4581 auto eq_predicate = predicate;
4582 if (predicate == FCmpInst::FCMP_UNE ||
4583 predicate == FCmpInst::FCMP_ONE)
4584 eq_predicate = fcmp->getInversePredicate();
4587 auto ncmp1 = pushcse(B.CreateFCmp(eq_predicate, v, C));
4591 res = pushcse(B.CreateOr(res, ncmp1));
4594 if (predicate == FCmpInst::FCMP_UNE ||
4595 predicate == FCmpInst::FCMP_ONE) {
4596 res = pushcse(B.CreateNot(res));
4599 replaceAndErase(cur, res);
4600 return "CmpProductSplit";
4605 if (
auto S =
isSum(fcmp->getOperand(1 - i))) {
4606 SmallVector<Value *, 1> allOps;
4607 auto combine = [](
const SmallVector<Value *, 1> &lhs,
4608 SmallVector<Value *, 1> rhs) {
4609 SmallVector<Value *, 1> out;
4610 for (
auto v : lhs) {
4612 for (
auto &v2 : rhs) {
4625 auto subtract = [](SmallVector<Value *, 1> lhs,
4626 const SmallVector<Value *, 1> &rhs) {
4627 for (
auto v : rhs) {
4628 auto found = find(lhs, v);
4629 assert(found != lhs.end());
4650 if (legal && allOps.size() > 0) {
4651 SmallVector<Value *, 1> operands;
4656 auto newprod = pushcse(B.CreateCall(
4658 operands.push_back(newprod);
4660 auto newsum = pushcse(B.CreateCall(
4662 allOps.push_back(newsum);
4663 auto fprod = pushcse(B.CreateCall(
4665 auto fcmp = pushcse(B.CreateCmp(predicate, fprod, C));
4666 replaceAndErase(cur, fcmp);
4667 return "CmpSumFactor";
4675 if (
auto fcmp = dyn_cast<FCmpInst>(cur)) {
4676 auto predicate = fcmp->getPredicate();
4677 if (predicate == FCmpInst::FCMP_OEQ || predicate == FCmpInst::FCMP_UEQ ||
4678 predicate == FCmpInst::FCMP_UNE || predicate == FCmpInst::FCMP_ONE) {
4679 for (
int i = 0; i < 2; i++)
4680 if (
auto C = dyn_cast<ConstantFP>(fcmp->getOperand(i))) {
4683 if (
auto S =
isSum(fcmp->getOperand(1 - i))) {
4686 auto eq_predicate = predicate;
4687 if (predicate == FCmpInst::FCMP_UNE ||
4688 predicate == FCmpInst::FCMP_ONE)
4689 eq_predicate = fcmp->getInversePredicate();
4691 Value *op_checks =
nullptr;
4692 for (
auto a : allOps) {
4693 auto a_e0 = pushcse(B.CreateFCmp(eq_predicate, a, C));
4694 if (op_checks ==
nullptr)
4697 op_checks = pushcse(B.CreateAnd(op_checks, a_e0));
4699 SmallVector<Value *, 1> slice;
4700 for (
size_t i = 1; i < allOps.size(); i++)
4701 slice.push_back(allOps[i]);
4702 auto ane = pushcse(B.CreateFCmp(
4703 eq_predicate, pushcse(B.CreateFNeg(allOps[0])),
4705 auto ori = pushcse(B.CreateOr(op_checks, ane));
4706 if (predicate == FCmpInst::FCMP_UNE ||
4707 predicate == FCmpInst::FCMP_ONE) {
4708 ori = pushcse(B.CreateNot(ori));
4710 replaceAndErase(cur, ori);
4711 return "Sum2ZeroSplit";
4720 if (
auto icmp = dyn_cast<CmpInst>(cur)) {
4721 if (icmp->getPredicate() == CmpInst::ICMP_EQ ||
4722 icmp->getPredicate() == CmpInst::ICMP_NE) {
4723 for (
int i = 0; i < 2; i++)
4724 if (
auto C = dyn_cast<ConstantInt>(icmp->getOperand(i)))
4726 if (
auto add = dyn_cast<BinaryOperator>(icmp->getOperand(1 - i)))
4727 if (add->getOpcode() == Instruction::Add)
4728 if (
auto a0 = dyn_cast<CastInst>(add->getOperand(0)))
4729 if (
auto a1 = dyn_cast<CastInst>(add->getOperand(1)))
4730 if (a0->getOperand(0)->getType() ==
4731 a1->getOperand(0)->getType() &&
4732 (isa<ZExtInst>(a0) || isa<SExtInst>(a0))) {
4733 auto cmp2 = pushcse(B.CreateCmp(
4734 icmp->getPredicate(), a0, pushcse(B.CreateNeg(a1))));
4735 replaceAndErase(cur, cmp2);
4736 return "CmpExt0Shuffle";
4743 if (
auto sub = dyn_cast<BinaryOperator>(cur))
4744 if (sub->getOpcode() == Instruction::Sub)
4745 if (
auto C = dyn_cast<ConstantInt>(sub->getOperand(0)))
4747 if (
auto a0 = dyn_cast<CastInst>(sub->getOperand(1)))
4748 if (a0->getOperand(0)->getType()->isIntegerTy(1)) {
4750 Value *tmp =
nullptr;
4751 if (isa<ZExtInst>(a0))
4752 tmp = pushcse(B.CreateSExt(a0->getOperand(0), a0->getType()));
4753 else if (isa<SExtInst>(a0))
4754 tmp = pushcse(B.CreateZExt(a0->getOperand(0), a0->getType()));
4757 replaceAndErase(cur, tmp);
4758 return "NegSZExtI1";
4761 if ((cur->getOpcode() == Instruction::LShr ||
4762 cur->getOpcode() == Instruction::SDiv ||
4763 cur->getOpcode() == Instruction::UDiv) &&
4765 if (
auto C2 = dyn_cast<ConstantInt>(cur->getOperand(1)))
4766 if (
auto mul = dyn_cast<BinaryOperator>(cur->getOperand(0))) {
4769 if (mul->getOpcode() == Instruction::Mul)
4770 for (
int i0 = 0; i0 < 2; i0++)
4771 if (
auto C1 = dyn_cast<ConstantInt>(mul->getOperand(i0))) {
4772 auto lhs = C1->getValue();
4773 APInt rhs = C2->getValue();
4774 if (cur->getOpcode() == Instruction::LShr) {
4775 rhs = APInt(rhs.getBitWidth(), 1) << rhs;
4779 if (cur->getOpcode() == Instruction::LShr ||
4780 cur->getOpcode() == Instruction::UDiv)
4781 APInt::udivrem(lhs, rhs, div, rem);
4783 APInt::sdivrem(lhs, rhs, div, rem);
4785 auto res = pushcse(B.CreateMul(
4786 mul->getOperand(1 - i0),
4787 ConstantInt::get(cur->getType(), div),
4788 "mdiv." + cur->getName(), mul->hasNoUnsignedWrap(),
4789 mul->hasNoSignedWrap()));
4791 replaceAndErase(cur, res);
4792 return "IMulDivConst";
4797 if (mul->getOpcode() == Instruction::Add)
4798 for (
int i0 = 0; i0 < 2; i0++)
4799 if (
auto C1 = dyn_cast<ConstantInt>(mul->getOperand(i0))) {
4800 auto lhs = C1->getValue();
4801 APInt rhs = C2->getValue();
4802 if (cur->getOpcode() == Instruction::LShr) {
4803 rhs = APInt(rhs.getBitWidth(), 1) << rhs;
4807 if (cur->getOpcode() == Instruction::LShr ||
4808 cur->getOpcode() == Instruction::UDiv)
4809 APInt::udivrem(lhs, rhs, div, rem);
4811 APInt::sdivrem(lhs, rhs, div, rem);
4812 if (rem == 0 && ((mul->hasNoUnsignedWrap() &&
4813 (cur->getOpcode() == Instruction::LShr ||
4814 cur->getOpcode() == Instruction::UDiv)) ||
4815 (mul->hasNoSignedWrap() &&
4816 (cur->getOpcode() == Instruction::AShr ||
4817 cur->getOpcode() == Instruction::SDiv)))) {
4818 auto res = pushcse(B.CreateAdd(
4819 mul->getOperand(1 - i0),
4820 ConstantInt::get(cur->getType(), div),
4821 "madd." + cur->getName(), mul->hasNoUnsignedWrap(),
4822 mul->hasNoSignedWrap()));
4824 replaceAndErase(cur, res);
4825 return "IAddDivConst";
4831 if (cur->getOpcode() == Instruction::FMul)
4833 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
4834 if (mul1->getOpcode() == Instruction::FMul && mul1->isFast())
4835 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1)))
4836 if (mul2->getOpcode() == Instruction::FMul && mul2->isFast()) {
4837 for (
auto i1 = 0; i1 < 2; i1++)
4838 for (
auto i2 = 0; i2 < 2; i2++)
4839 if (isa<Constant>(mul1->getOperand(i1)))
4840 if (isa<Constant>(mul2->getOperand(i2))) {
4843 B.CreateFMulFMF(mul1->getOperand(1 - i1),
4844 mul2->getOperand(1 - i2), cur));
4845 auto n1 = pushcse(B.CreateFMulFMF(
4846 mul1->getOperand(i1), mul2->getOperand(i2), cur));
4847 auto n2 = pushcse(B.CreateFMulFMF(n0, n1, cur));
4850 replaceAndErase(cur, n2);
4851 return "MulMulConstConst";
4856 if ((cur->getOpcode() == Instruction::FMul && cur->isFast()) ||
4857 cur->getOpcode() == Instruction::Mul)
4858 for (
auto i1 = 0; i1 < 2; i1++)
4859 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(i1)))
4860 if (((mul1->getOpcode() == Instruction::FMul && mul1->isFast())) ||
4861 mul1->getOpcode() == Instruction::FMul)
4862 if (
auto const2 = dyn_cast<Constant>(cur->getOperand(1 - i1)))
4863 for (
auto i2 = 0; i2 < 2; i2++)
4864 if (
auto const1 = dyn_cast<Constant>(mul1->getOperand(i2))) {
4865 Value *res =
nullptr;
4866 if (cur->getOpcode() == Instruction::FMul) {
4867 auto const3 = pushcse(B.CreateFMulFMF(const1, const2, mul1));
4869 B.CreateFMulFMF(mul1->getOperand(1 - i2), const3, cur));
4871 auto const3 = pushcse(B.CreateMul(const1, const2));
4872 res = pushcse(B.CreateMul(mul1->getOperand(1 - i2), const3));
4875 replaceAndErase(cur, res);
4876 return "MulConstConst";
4879 if (
auto fcmp = dyn_cast<FCmpInst>(cur)) {
4880 if (fcmp->getPredicate() == FCmpInst::FCMP_OEQ) {
4881 for (
int i = 0; i < 2; i++)
4882 if (
auto C = dyn_cast<ConstantFP>(fcmp->getOperand(i))) {
4884 if (
auto fmul = dyn_cast<BinaryOperator>(fcmp->getOperand(1 - i))) {
4886 if (fmul->getOpcode() == Instruction::FMul) {
4887 auto ncmp1 = pushcse(
4888 B.CreateFCmp(fcmp->getPredicate(), fmul->getOperand(0), C));
4889 auto ncmp2 = pushcse(
4890 B.CreateFCmp(fcmp->getPredicate(), fmul->getOperand(1), C));
4891 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
4892 replaceAndErase(cur, ori);
4893 return "CmpFMulSplit";
4896 if (fmul->getOpcode() == Instruction::FDiv) {
4897 auto ncmp1 = pushcse(
4898 B.CreateFCmp(fcmp->getPredicate(), fmul->getOperand(0), C));
4899 replaceAndErase(cur, ncmp1);
4900 return "CmpFDivSplit";
4903 if (fmul->getOpcode() == Instruction::FSub) {
4904 auto ncmp1 = pushcse(B.CreateFCmp(fcmp->getPredicate(),
4905 fmul->getOperand(0),
4906 fmul->getOperand(1)));
4907 replaceAndErase(cur, ncmp1);
4908 return "CmpFSubSplit";
4911 if (
auto cast = dyn_cast<SIToFPInst>(fcmp->getOperand(1 - i))) {
4912 auto ncmp1 = pushcse(B.CreateICmp(
4913 ICmpInst::ICMP_EQ, cast->getOperand(0),
4914 ConstantInt::get(cast->getOperand(0)->getType(), 0)));
4915 replaceAndErase(cur, ncmp1);
4916 return "SFCmpToICmp";
4918 if (
auto cast = dyn_cast<UIToFPInst>(fcmp->getOperand(1 - i))) {
4919 auto ncmp1 = pushcse(B.CreateICmp(
4920 ICmpInst::ICMP_EQ, cast->getOperand(0),
4921 ConstantInt::get(cast->getOperand(0)->getType(), 0)));
4922 replaceAndErase(cur, ncmp1);
4923 return "UFCmpToICmp";
4925 if (
auto SI = dyn_cast<SelectInst>(fcmp->getOperand(1 - i))) {
4927 B.CreateSelect(SI->getCondition(),
4928 pushcse(B.CreateCmp(fcmp->getPredicate(), C,
4929 SI->getTrueValue())),
4930 pushcse(B.CreateCmp(fcmp->getPredicate(), C,
4931 SI->getFalseValue()))));
4932 replaceAndErase(cur, res);
4933 return "FCmpSelect";
4939 if (
auto fcmp = dyn_cast<CmpInst>(cur)) {
4940 if (fcmp->getPredicate() == CmpInst::ICMP_EQ ||
4941 fcmp->getPredicate() == CmpInst::ICMP_NE ||
4942 fcmp->getPredicate() == CmpInst::FCMP_OEQ ||
4943 fcmp->getPredicate() == CmpInst::FCMP_ONE) {
4946 for (
int i = 0; i < 2; i++)
4947 if (
auto inst = dyn_cast<Instruction>(fcmp->getOperand(i)))
4948 if (inst->getOpcode() == Instruction::FAdd && inst->isFast())
4949 for (
int i2 = 0; i2 < 2; i2++)
4950 if (inst->getOperand(i2) == fcmp->getOperand(1 - i)) {
4952 B.CreateCmp(fcmp->getPredicate(), inst->getOperand(1 - i2),
4953 ConstantFP::get(inst->getType(), 0)));
4954 replaceAndErase(cur, res);
4955 return "CmpFAddSame";
4960 if (fcmp->getOperand(0)->getType()->isIntegerTy(1)) {
4961 auto a = fcmp->getOperand(0);
4962 auto b = fcmp->getOperand(1);
4963 if (fcmp->getPredicate() == CmpInst::ICMP_EQ) {
4965 B.CreateOr(pushcse(B.CreateAnd(a, b)),
4966 pushcse(B.CreateAnd(pushcse(B.CreateNot(a)),
4967 pushcse(B.CreateNot(b))))));
4968 replaceAndErase(cur, res);
4971 if (fcmp->getPredicate() == CmpInst::ICMP_NE) {
4973 B.CreateOr(pushcse(B.CreateAnd(pushcse(B.CreateNot(a)), b)),
4974 pushcse(B.CreateAnd(a, pushcse(B.CreateNot(b))))));
4975 replaceAndErase(cur, res);
4980 for (
int i = 0; i < 2; i++)
4981 if (
auto CI = dyn_cast<ConstantInt>(fcmp->getOperand(i)))
4984 if (
auto addI = dyn_cast<Instruction>(fcmp->getOperand(1 - i))) {
4985 if (addI->getOpcode() == Instruction::Add &&
4986 addI->getOperand(0) == addI->getOperand(1)) {
4987 Value *res = pushcse(
4988 B.CreateCmp(fcmp->getPredicate(), addI->getOperand(0), CI));
4989 replaceAndErase(cur, res);
4993 if (addI->getOpcode() == Instruction::Sub) {
4994 auto ncmp1 = pushcse(B.CreateICmp(fcmp->getPredicate(),
4995 addI->getOperand(0),
4996 addI->getOperand(1)));
4997 replaceAndErase(cur, ncmp1);
4998 return "CmpISubSplit";
5010 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
5011 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1))) {
5012 if (mul1->getOpcode() == Instruction::Mul &&
5013 mul2->getOpcode() == Instruction::Mul &&
5014 mul1->hasNoUnsignedWrap() && mul1->hasNoSignedWrap() &&
5015 mul2->hasNoUnsignedWrap() && mul2->hasNoSignedWrap()) {
5016 for (
int i = 0; i < 2; i++) {
5017 if (mul1->getOperand(i) == mul2->getOperand(i)) {
5018 Value *res = pushcse(B.CreateICmp(fcmp->getPredicate(),
5019 mul1->getOperand(1 - i),
5020 mul2->getOperand(1 - i)));
5021 auto b = mul1->getOperand(i);
5022 if (fcmp->getPredicate() == CmpInst::ICMP_EQ) {
5023 Value *bZero = pushcse(B.CreateICmp(
5024 CmpInst::ICMP_EQ, b, ConstantInt::get(b->getType(), 0)));
5025 res = pushcse(B.CreateOr(res, bZero));
5027 Value *bZero = pushcse(B.CreateICmp(
5028 ICmpInst::ICMP_NE, b, ConstantInt::get(b->getType(), 0)));
5029 res = pushcse(B.CreateAnd(res, bZero));
5031 replaceAndErase(cur, res);
5032 return "CmpMulCommon";
5037 if (mul1->getOpcode() == Instruction::FMul &&
5038 mul2->getOpcode() == Instruction::FMul && mul1->isFast() &&
5040 for (
int i = 0; i < 2; i++) {
5041 if (mul1->getOperand(i) == mul2->getOperand(i)) {
5042 Value *res = pushcse(B.CreateFCmp(fcmp->getPredicate(),
5043 mul1->getOperand(1 - i),
5044 mul2->getOperand(1 - i)));
5045 auto b = mul1->getOperand(i);
5046 if (fcmp->getPredicate() == CmpInst::FCMP_OEQ) {
5047 Value *bZero = pushcse(B.CreateCmp(
5048 CmpInst::FCMP_OEQ, b, ConstantFP::get(b->getType(), 0)));
5049 res = pushcse(B.CreateOr(res, bZero));
5051 Value *bZero = pushcse(B.CreateCmp(
5052 CmpInst::FCMP_ONE, b, ConstantFP::get(b->getType(), 0)));
5053 res = pushcse(B.CreateAnd(res, bZero));
5055 replaceAndErase(cur, res);
5056 return "CmpMulfCommon";
5062 for (
auto cond : {Instruction::UIToFP, Instruction::SIToFP})
5063 if (mul1->getOpcode() == cond && mul2->getOpcode() == cond &&
5064 mul1->getOperand(0)->getType() ==
5065 mul2->getOperand(0)->getType()) {
5066 Value *res = pushcse(B.CreateICmp(
5067 fcmp->getPredicate() == CmpInst::FCMP_OEQ ? CmpInst::ICMP_EQ
5069 mul1->getOperand(0), mul2->getOperand(0)));
5070 replaceAndErase(cur, res);
5075 if (mul1->getOpcode() == Instruction::ZExt &&
5076 mul2->getOpcode() == Instruction::ZExt &&
5077 mul1->getOperand(0)->getType() ==
5078 mul2->getOperand(0)->getType()) {
5080 pushcse(B.CreateICmp(fcmp->getPredicate(), mul1->getOperand(0),
5081 mul2->getOperand(0)));
5082 replaceAndErase(cur, res);
5088 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
5089 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1)))
5090 if (((mul1->getOpcode() == Instruction::ZExt &&
5091 mul2->getOpcode() == Instruction::SExt) ||
5092 (mul1->getOpcode() == Instruction::SExt &&
5093 mul2->getOpcode() == Instruction::ZExt)) &&
5094 mul1->getOperand(0)->getType() ==
5095 mul2->getOperand(0)->getType() &&
5096 mul1->getOperand(0)->getType()->isIntegerTy(1)) {
5098 Value *na = mul1->getOperand(0);
5099 Value *nb = mul2->getOperand(0);
5101 if (fcmp->getPredicate() == ICmpInst::ICMP_EQ) {
5102 na = pushcse(B.CreateNot(na));
5103 nb = pushcse(B.CreateNot(nb));
5106 Value *res =
nullptr;
5107 if (fcmp->getPredicate() == ICmpInst::ICMP_EQ)
5108 res = pushcse(B.CreateAnd(na, nb));
5110 res = pushcse(B.CreateOr(na, nb));
5112 replaceAndErase(cur, res);
5113 return "CmpZExtSExt";
5117 if (fcmp->getPredicate() == ICmpInst::ICMP_EQ) {
5118 for (
int i = 0; i < 2; i++) {
5119 if (
auto C = dyn_cast<ConstantInt>(fcmp->getOperand(i))) {
5121 if (
auto fmul = dyn_cast<BinaryOperator>(fcmp->getOperand(1 - i))) {
5123 if (fmul->getOpcode() == Instruction::Mul) {
5124 auto ncmp1 = pushcse(
5125 B.CreateICmp(fcmp->getPredicate(), fmul->getOperand(0), C));
5126 auto ncmp2 = pushcse(
5127 B.CreateICmp(fcmp->getPredicate(), fmul->getOperand(1), C));
5128 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
5129 replaceAndErase(cur, ori);
5130 return "CmpIMulSplit";
5139 if (cur->getOpcode() == Instruction::FAdd) {
5141 if (cur->getOperand(0) == cur->getOperand(1) && cur->isFast()) {
5142 auto res = pushcse(B.CreateFMulFMF(
5143 cur->getOperand(0), ConstantFP::get(cur->getType(), 2.0), cur));
5144 replaceAndErase(cur, res);
5149 if (cur->getOpcode() == Instruction::Add) {
5151 for (
int i = 0; i < 2; i++) {
5152 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(i)))
5153 if (mul1->getOpcode() == Instruction::Mul) {
5154 for (
int j = 0; j < 2; j++) {
5155 if (
auto C = dyn_cast<ConstantInt>(mul1->getOperand(j))) {
5156 if (C->isMinusOne()) {
5157 auto res = pushcse(B.CreateSub(cur->getOperand(1 - i),
5158 mul1->getOperand(1 - j)));
5161 replaceAndErase(cur, res);
5170 if (
auto SI = dyn_cast<SelectInst>(cur)) {
5171 auto shouldMove = [](Value *v) {
return isa<Constant>(v); };
5200 for (
int i = 0; i < 2; i++)
5201 if (
auto inst = dyn_cast<Instruction>(SI->getOperand(1 + i)))
5202 if (inst->getOpcode() == Instruction::Mul)
5204 if (
auto C = dyn_cast<Constant>(SI->getOperand(1 + (1 - i))))
5205 if ((isa<ConstantInt>(C) && cast<ConstantInt>(C)->
isZero()) ||
5206 (isa<ConstantFP>(C) && cast<ConstantFP>(C)->
isZero()))
5207 for (
int j = 0; j < 2; j++)
5208 if (shouldMove(inst->getOperand(j))) {
5209 auto x = inst->getOperand(j);
5210 auto y = inst->getOperand(1 - j);
5211 auto isel = pushcse(B.CreateSelect(
5212 SI->getCondition(), (i == 0) ? y : C, (i == 0) ? C : y,
5213 "smulmove." + SI->getName()));
5215 if (cur->getType()->isIntegerTy())
5216 imul = pushcse(B.CreateMul(isel, x,
"",
5217 inst->hasNoUnsignedWrap(),
5218 inst->hasNoSignedWrap()));
5220 imul = pushcse(B.CreateFMulFMF(isel, x, inst,
""));
5222 replaceAndErase(cur, imul);
5223 return "SelMulMove";
5229 Value *ops[2] = {
nullptr,
nullptr};
5231 for (
int i = 0; i < 2; i++) {
5232 if (isa<ConstantFP>(SI->getOperand(1 + i))) {
5236 if (
auto CI = dyn_cast<CastInst>(SI->getOperand(1 + i))) {
5237 if (CI->getOpcode() == Instruction::SIToFP) {
5238 ops[i] = CI->getOperand(0);
5245 for (
int i = 0; i < 2; i++) {
5246 if (!ops[i] && ops[1 - i])
5247 ops[i] = ConstantInt::get(ops[1 - i]->getType(), 0);
5249 for (
int i = 0; i < 2; i++) {
5250 if (ops[i] ==
nullptr || ops[i]->getType() != ops[0]->getType()) {
5256 auto isel = pushcse(B.CreateSelect(SI->getCondition(), ops[0], ops[1],
5257 "seltofp." + SI->getName()));
5258 auto res = pushcse(B.CreateSIToFP(isel, SI->getType()));
5260 replaceAndErase(cur, res);
5261 return "SelSIMerge";
5266 if (cur->getOpcode() == Instruction::Mul) {
5267 for (
int i = 0; i < 2; i++) {
5269 if (
auto C = dyn_cast<ConstantInt>(cur->getOperand(i)))
5271 replaceAndErase(cur, cur->getOperand(1 - i));
5276 if (
auto Z = dyn_cast<ZExtInst>(cur->getOperand(i)))
5277 if (Z->getOperand(0)->getType()->isIntegerTy(1)) {
5278 auto prev = cur->getOperand(1 - i);
5279 auto next = replace(prev, Z->getOperand(0),
5280 ConstantInt::getTrue(cur->getContext()));
5282 auto res = pushcse(B.CreateMul(Z, next,
"postmul." + cur->getName(),
5283 cur->hasNoUnsignedWrap(),
5284 cur->hasNoSignedWrap()));
5285 replaceAndErase(cur, res);
5286 return "MulReplaceZExt";
5313 for (
int i = 0; i < 2; i++)
5314 if (
auto inst = dyn_cast<Instruction>(cur->getOperand(i)))
5315 if (inst->getOpcode() == Instruction::Sub)
5316 if (
auto CI = dyn_cast<ConstantInt>(cur->getOperand(1 - i)))
5317 if (CI->isNegative()) {
5318 auto sub2 = pushcse(B.CreateSub(
5319 inst->getOperand(1), inst->getOperand(0),
"",
5320 inst->hasNoUnsignedWrap(), inst->hasNoSignedWrap()));
5321 auto mul2 = pushcse(B.CreateMul(
5322 sub2, ConstantInt::get(CI->getType(), -CI->getValue()),
"",
5323 cur->hasNoUnsignedWrap(), cur->hasNoSignedWrap()));
5325 replaceAndErase(cur, mul2);
5326 return "MulSubNegConst";
5330 if (cur->getOpcode() == Instruction::Sub)
5331 if (
auto CI = dyn_cast<ConstantInt>(cur->getOperand(0)))
5333 if (
auto zext = dyn_cast<Instruction>(cur->getOperand(1))) {
5335 if (zext->getOpcode() == Instruction::ZExt &&
5336 zext->getOperand(0)->getType()->isIntegerTy(1)) {
5338 pushcse(B.CreateSExt(zext->getOperand(0), cur->getType()));
5339 replaceAndErase(cur, res);
5343 if (zext->getOpcode() == Instruction::Mul &&
5344 zext->hasNoUnsignedWrap() && zext->hasNoSignedWrap()) {
5345 for (
int i = 0; i < 2; i++)
5346 if (
auto CI = dyn_cast<ConstantInt>(zext->getOperand(i))) {
5347 auto res = pushcse(B.CreateMul(
5348 zext->getOperand(1 - i),
5349 ConstantInt::get(CI->getType(), -CI->getValue()),
5350 "neg." + zext->getName(),
true,
true));
5351 replaceAndErase(cur, res);
5352 return "SubMulConstant";
5400 if (cur->getOpcode() == Instruction::Add ||
5401 cur->getOpcode() == Instruction::Sub ||
5402 cur->getOpcode() == Instruction::Mul ||
5403 cur->getOpcode() == Instruction::FAdd ||
5404 cur->getOpcode() == Instruction::FSub ||
5405 cur->getOpcode() == Instruction::FMul ||
5408 cur->getOpcode() == Instruction::ICmp ||
5409 cur->getOpcode() == Instruction::FCmp) {
5411 Value *SI1cond =
nullptr;
5412 Value *SI1tval =
nullptr;
5413 Value *SI1fval =
nullptr;
5414 if (
auto SI1 = dyn_cast<SelectInst>(cur->getOperand(0))) {
5415 SI1cond = SI1->getCondition();
5416 SI1tval = SI1->getTrueValue();
5417 SI1fval = SI1->getFalseValue();
5419 if (
auto SI1 = dyn_cast<ZExtInst>(cur->getOperand(0)))
5420 if (SI1->getOperand(0)->getType()->isIntegerTy(1)) {
5421 SI1cond = SI1->getOperand(0);
5423 SI1fval = ConstantInt::get(SI1->getType(), 0);
5425 if (
auto SI1 = dyn_cast<SExtInst>(cur->getOperand(0)))
5426 if (SI1->getOperand(0)->getType()->isIntegerTy(1)) {
5427 SI1cond = SI1->getOperand(0);
5429 SI1fval = ConstantInt::get(SI1->getType(), 0);
5431 Value *SI2cond =
nullptr;
5432 Value *SI2tval =
nullptr;
5433 Value *SI2fval =
nullptr;
5435 auto op2 = cur->getOperand((cur->getOpcode() == Instruction::SIToFP ||
5436 cur->getOpcode() == Instruction::UIToFP)
5439 if (
auto SI2 = dyn_cast<SelectInst>(op2)) {
5440 SI2cond = SI2->getCondition();
5441 SI2tval = SI2->getTrueValue();
5442 SI2fval = SI2->getFalseValue();
5444 if (
auto SI2 = dyn_cast<ZExtInst>(op2))
5445 if (SI2->getOperand(0)->getType()->isIntegerTy(1)) {
5446 SI2cond = SI2->getOperand(0);
5448 SI2fval = ConstantInt::get(SI2->getType(), 0);
5450 if (
auto SI2 = dyn_cast<SExtInst>(op2))
5451 if (SI2->getOperand(0)->getType()->isIntegerTy(1)) {
5452 SI2cond = SI2->getOperand(0);
5454 SI2fval = ConstantInt::get(SI2->getType(), 0);
5457 if (SI1cond && SI2cond && (SI1cond == SI2cond ||
isNot(SI1cond, SI2cond)))
5458 if ((SI1cond == SI2cond &&
5459 ((isa<Constant>(SI1tval) && isa<Constant>(SI2tval)) ||
5460 (isa<Constant>(SI1fval) && isa<Constant>(SI2fval)))) ||
5461 (SI1cond != SI2cond &&
5462 ((isa<Constant>(SI1tval) && isa<Constant>(SI2fval)) ||
5463 (isa<Constant>(SI1fval) && isa<Constant>(SI2tval))))
5466 Value *tval =
nullptr;
5467 Value *fval =
nullptr;
5468 bool inverted = SI1cond != SI2cond;
5469 switch (cur->getOpcode()) {
5470 case Instruction::SIToFP:
5472 B.CreateSIToFP(SI1tval, cur->getType(),
"tval." + cur->getName());
5474 B.CreateSIToFP(SI1fval, cur->getType(),
"fval." + cur->getName());
5476 case Instruction::UIToFP:
5478 B.CreateUIToFP(SI1tval, cur->getType(),
"tval." + cur->getName());
5480 B.CreateUIToFP(SI1fval, cur->getType(),
"fval." + cur->getName());
5482 case Instruction::FAdd:
5483 tval = B.CreateFAddFMF(SI1tval, inverted ? SI2fval : SI2tval, cur,
5484 "tval." + cur->getName());
5485 fval = B.CreateFAddFMF(SI1fval, inverted ? SI2tval : SI2fval, cur,
5486 "fval." + cur->getName());
5488 case Instruction::FSub:
5489 tval = B.CreateFSubFMF(SI1tval, inverted ? SI2fval : SI2tval, cur,
5490 "tval." + cur->getName());
5491 fval = B.CreateFSubFMF(SI1fval, inverted ? SI2tval : SI2fval, cur,
5492 "fval." + cur->getName());
5494 case Instruction::FMul:
5495 tval = B.CreateFMulFMF(SI1tval, inverted ? SI2fval : SI2tval, cur,
5496 "tval." + cur->getName());
5497 fval = B.CreateFMulFMF(SI1fval, inverted ? SI2tval : SI2fval, cur,
5498 "fval." + cur->getName());
5500 case Instruction::Add:
5501 tval = B.CreateAdd(SI1tval, inverted ? SI2fval : SI2tval,
5502 "tval." + cur->getName(), cur->hasNoUnsignedWrap(),
5503 cur->hasNoSignedWrap());
5504 fval = B.CreateAdd(SI1fval, inverted ? SI2tval : SI2fval,
5505 "fval." + cur->getName(), cur->hasNoUnsignedWrap(),
5506 cur->hasNoSignedWrap());
5508 case Instruction::Sub:
5509 tval = B.CreateSub(SI1tval, inverted ? SI2fval : SI2tval,
5510 "tval." + cur->getName(), cur->hasNoUnsignedWrap(),
5511 cur->hasNoSignedWrap());
5512 fval = B.CreateSub(SI1fval, inverted ? SI2tval : SI2fval,
5513 "fval." + cur->getName(), cur->hasNoUnsignedWrap(),
5514 cur->hasNoSignedWrap());
5516 case Instruction::Mul:
5517 tval = B.CreateMul(SI1tval, inverted ? SI2fval : SI2tval,
5518 "tval." + cur->getName(), cur->hasNoUnsignedWrap(),
5519 cur->hasNoSignedWrap());
5520 fval = B.CreateMul(SI1fval, inverted ? SI2tval : SI2fval,
5521 "fval." + cur->getName(), cur->hasNoUnsignedWrap(),
5522 cur->hasNoSignedWrap());
5524 case Instruction::ICmp:
5525 case Instruction::FCmp:
5526 tval = B.CreateCmp(cast<CmpInst>(cur)->getPredicate(), SI1tval,
5527 inverted ? SI2fval : SI2tval,
5528 "tval." + cur->getName());
5529 fval = B.CreateCmp(cast<CmpInst>(cur)->getPredicate(), SI1fval,
5530 inverted ? SI2tval : SI2fval,
5531 "fval." + cur->getName());
5534 llvm_unreachable(
"illegal opcode");
5536 tval = pushcse(tval);
5537 fval = pushcse(fval);
5540 B.CreateSelect(SI1cond, tval, fval,
"selmerge." + cur->getName()));
5542 push(cur->getOperand(0));
5543 push(cur->getOperand(1));
5544 replaceAndErase(cur, res);
5545 return "BinopSelFuse";
5565 if (cur->getOpcode() == Instruction::And) {
5566 for (
size_t i1 = 0; i1 < 2; i1++)
5567 if (
auto inst2 = dyn_cast<Instruction>(cur->getOperand(1 - i1)))
5568 if (inst2->getOpcode() == Instruction::Or)
5569 for (
size_t i2 = 0; i2 < 2; i2++)
5570 if (
isNot(cur->getOperand(i1), inst2->getOperand(i2))) {
5571 auto q = inst2->getOperand(1 - i2);
5572 cur->setOperand(1 - i1, q);
5576 push(cur->getOperand(i1));
5577 push(inst2->getOperand(i2));
5579 for (
auto U : cur->users())
5586 if (cur->getOpcode() == Instruction::And) {
5587 for (
size_t i1 = 0; i1 < 2; i1++)
5588 if (
auto inst2 = dyn_cast<Instruction>(cur->getOperand(i1)))
5589 if (inst2->getOpcode() == Instruction::And)
5590 for (
size_t i2 = 0; i2 < 2; i2++)
5591 if (inst2->getOperand(i2) == cur->getOperand(1 - i1)) {
5592 replaceAndErase(cur, inst2);
5593 return "AndAndProp";
5598 if (cur->getOpcode() == Instruction::And) {
5599 for (
size_t i1 = 0; i1 < 2; i1++)
5600 if (
auto inst2 = dyn_cast<Instruction>(cur->getOperand(1 - i1)))
5601 if (inst2->getOpcode() == Instruction::Or)
5602 for (
size_t i2 = 0; i2 < 2; i2++)
5603 if (
isNot(cur->getOperand(i1), inst2->getOperand(i2))) {
5604 auto q = inst2->getOperand(1 - i2);
5605 cur->setOperand(1 - i1, q);
5609 push(cur->getOperand(i1));
5610 push(inst2->getOperand(i2));
5612 for (
auto U : cur->users())
5621 if (cur->getOpcode() == Instruction::And ||
5622 cur->getOpcode() == Instruction::Or) {
5623 for (
auto cmpOp : {ICmpInst::ICMP_EQ, ICmpInst::ICMP_NE})
5624 for (
auto interOp : {Instruction::Add, Instruction::Sub})
5625 if (
auto cmp1 = dyn_cast<ICmpInst>(cur->getOperand(0)))
5626 if (
auto cmp2 = dyn_cast<ICmpInst>(cur->getOperand(1)))
5627 for (
size_t i1 = 0; i1 < 2; i1++)
5628 for (
size_t i2 = 0; i2 < 2; i2++)
5629 if (cmp1->getOperand(1 - i1) == cmp2->getOperand(1 - i2) &&
5630 cmp1->getPredicate() == cmpOp &&
5631 cmp2->getPredicate() == cmpOp)
5632 if (
auto add1 = dyn_cast<Instruction>(cmp1->getOperand(i1)))
5633 if (
auto add2 = dyn_cast<Instruction>(cmp2->getOperand(i2)))
5634 if (add1->getOpcode() == interOp &&
5635 add2->getOpcode() == interOp)
5636 for (
size_t ia = 0; ia < 2; ia++)
5637 if (add1->getOperand(ia) == add2->getOperand(ia)) {
5639 auto b = add1->getOperand(ia);
5640 auto c = cmp1->getOperand(1 - i1);
5641 auto a = add1->getOperand(1 - ia);
5642 auto d = add2->getOperand(1 - ia);
5644 Value *res =
nullptr;
5645 if (interOp == Instruction::Add)
5646 res = pushcse(B.CreateSub(ia == 0 ? b : c,
5649 res = pushcse(B.CreateAdd(ia == 0 ? b : c,
5652 auto lhs = pushcse(B.CreateCmp(cmpOp, a, res));
5653 auto rhs = pushcse(B.CreateCmp(cmpOp, d, res));
5655 Value *fres =
nullptr;
5656 if (cur->getOpcode() == Instruction::And)
5657 fres = pushcse(B.CreateAnd(lhs, rhs));
5659 fres = pushcse(B.CreateOr(lhs, rhs));
5661 replaceAndErase(cur, fres);
5662 return "AndLinearShift";
5667 if (cur->getOpcode() == Instruction::And) {
5668 for (
auto cmpOp : {ICmpInst::ICMP_EQ})
5669 if (
auto cmp1 = dyn_cast<ICmpInst>(cur->getOperand(0)))
5670 if (
auto cmp2 = dyn_cast<ICmpInst>(cur->getOperand(1)))
5671 for (
size_t i1 = 0; i1 < 2; i1++)
5672 for (
size_t i2 = 0; i2 < 2; i2++)
5673 if (cmp1->getOperand(1 - i1) == cmp2->getOperand(1 - i2) &&
5674 cmp1->getPredicate() == cmpOp &&
5675 cmp2->getPredicate() == cmpOp) {
5676 auto c1 = SE.getSCEV(cmp1->getOperand(i1));
5677 auto c2 = SE.getSCEV(cmp2->getOperand(i2));
5678 auto m = SE.getMinusSCEV(c1, c2, SCEV::NoWrapMask);
5679 if (
auto C = dyn_cast<SCEVConstant>(m)) {
5681 if (C->getValue()->isZero()) {
5684 replaceAndErase(cur, cmp1);
5688 replaceAndErase(cur,
5689 ConstantInt::getFalse(cur->getContext()));
5697 if (
auto icmp = dyn_cast<ICmpInst>(cur))
5698 if (icmp->getPredicate() == ICmpInst::ICMP_EQ &&
5699 cur->getType()->isIntegerTy(1))
5700 for (
int i = 0; i < 2; i++)
5701 if (
auto C = dyn_cast<ConstantInt>(icmp->getOperand(i)))
5703 if (
auto z = dyn_cast<BinaryOperator>(icmp->getOperand(1 - i)))
5704 if (z->getOpcode() == BinaryOperator::Or) {
5705 auto a0 = pushcse(B.CreateICmpEQ(z->getOperand(0), C));
5706 auto b0 = pushcse(B.CreateICmpEQ(z->getOperand(1), C));
5707 auto res = pushcse(B.CreateAnd(a0, b0));
5710 replaceAndErase(cur, res);
5715 if (cur->getOpcode() == Instruction::Sub ||
5716 cur->getOpcode() == Instruction::Add) {
5717 if (
auto mul1 = dyn_cast<Instruction>(cur->getOperand(0)))
5718 if (
auto mul2 = dyn_cast<Instruction>(cur->getOperand(1)))
5719 if ((mul1->getOpcode() == Instruction::Mul &&
5720 mul2->getOpcode() == Instruction::Mul) ||
5721 (mul1->getOpcode() == Instruction::FMul &&
5722 mul2->getOpcode() == Instruction::FMul && mul1->isFast() &&
5723 mul2->isFast() && cur->isFast())) {
5724 for (
int i1 = 0; i1 < 2; i1++)
5725 for (
int i2 = 0; i2 < 2; i2++) {
5726 if (mul1->getOperand(i1) == mul2->getOperand(i2)) {
5727 Value *res =
nullptr;
5728 switch (cur->getOpcode()) {
5729 case Instruction::Add:
5730 res = B.CreateAdd(mul1->getOperand(1 - i1),
5731 mul2->getOperand(1 - i2));
5733 case Instruction::Sub:
5734 res = B.CreateSub(mul1->getOperand(1 - i1),
5735 mul2->getOperand(1 - i2));
5737 case Instruction::FAdd:
5738 res = B.CreateFAddFMF(mul1->getOperand(1 - i1),
5739 mul2->getOperand(1 - i2), cur);
5741 case Instruction::FSub:
5742 res = B.CreateFSubFMF(mul1->getOperand(1 - i1),
5743 mul2->getOperand(1 - i2), cur);
5746 llvm_unreachable(
"Illegal opcode");
5749 Value *res2 =
nullptr;
5750 if (cur->getType()->isIntegerTy())
5752 res, mul1->getOperand(i1),
"",
5753 mul1->hasNoUnsignedWrap() && mul1->hasNoUnsignedWrap(),
5754 mul2->hasNoSignedWrap() && mul2->hasNoSignedWrap());
5756 res2 = B.CreateFMulFMF(res, mul1->getOperand(i1), cur);
5758 res2 = pushcse(res2);
5760 replaceAndErase(cur, res2);
5761 return "InvDistributive";
5770 if (cur->getOpcode() == Instruction::FSub ||
5771 cur->getOpcode() == Instruction::FAdd ||
5772 cur->getOpcode() == Instruction::FMul ||
5773 cur->getOpcode() == Instruction::FNeg ||
5775 auto opcode = cur->getOpcode();
5777 opcode = Instruction::FAdd;
5778 auto Ty = B.getInt64Ty();
5779 SmallPtrSet<Instruction *, 1> temporaries;
5780 SmallVector<Instruction *, 1> precasts;
5781 Value *lhs =
nullptr;
5783 Value *prelhs = (cur->getOpcode() == Instruction::FNeg)
5784 ? ConstantFP::get(cur->getType(), 0.0)
5785 : cur->getOperand(0);
5786 Value *prerhs = (cur->getOpcode() == Instruction::FNeg)
5787 ? cur->getOperand(0)
5788 : cur->getOperand(1);
5790 APInt minval(64, 0);
5791 APInt maxval(64, 0);
5792 if (
auto C = dyn_cast<ConstantFP>(prelhs)) {
5794 bool isExact =
false;
5795 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
5797 if (isExact || C->isZero()) {
5798 minval = maxval = Tmp;
5799 lhs = ConstantInt::get(Ty, Tmp);
5802 if (
auto ext = dyn_cast<CastInst>(prelhs)) {
5803 if (ext->getOpcode() == Instruction::UIToFP ||
5804 ext->getOpcode() == Instruction::SIToFP) {
5805 precasts.push_back(ext);
5806 auto ity = cast<IntegerType>(ext->getOperand(0)->getType());
5808 if (
auto I = dyn_cast<Instruction>(ext->getOperand(0)))
5809 if (
auto MD =
hasMetadata(I, LLVMContext::MD_range)) {
5813 cast<ConstantAsMetadata>(MD->getOperand(0))->getValue())
5818 cast<ConstantAsMetadata>(MD->getOperand(1))->getValue())
5823 if (ext->getOpcode() == Instruction::UIToFP)
5824 maxval = APInt::getMaxValue(ity->getBitWidth()).zextOrTrunc(64);
5827 APInt::getSignedMaxValue(ity->getBitWidth()).zextOrTrunc(64);
5829 APInt::getSignedMinValue(ity->getBitWidth()).zextOrTrunc(64);
5832 if (ext->getOperand(0)->getType() == Ty)
5833 lhs = ext->getOperand(0);
5834 else if (ity->getBitWidth() < Ty->getBitWidth()) {
5835 if (ext->getOpcode() == Instruction::UIToFP)
5836 lhs = B.CreateZExt(ext->getOperand(0), Ty);
5838 lhs = B.CreateSExt(ext->getOperand(0), Ty);
5839 if (
auto I = dyn_cast<Instruction>(lhs))
5840 if (I != ext->getOperand(0))
5841 temporaries.insert(I);
5846 Value *rhs =
nullptr;
5848 if (
auto C = dyn_cast<ConstantFP>(prerhs)) {
5850 bool isExact =
false;
5851 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
5853 if (isExact || C->isZero()) {
5854 rhs = ConstantInt::get(Ty, Tmp);
5856 case Instruction::FAdd:
5860 case Instruction::FSub:
5861 case Instruction::FNeg:
5865 case Instruction::FMul:
5870 llvm_unreachable(
"Illegal opcode");
5874 if (
auto ext = dyn_cast<CastInst>(prerhs)) {
5875 if (ext->getOpcode() == Instruction::UIToFP ||
5876 ext->getOpcode() == Instruction::SIToFP) {
5877 precasts.push_back(ext);
5878 auto ity = cast<IntegerType>(ext->getOperand(0)->getType());
5880 APInt rhsMin(64, 0);
5881 APInt rhsMax(64, 0);
5882 if (
auto I = dyn_cast<Instruction>(ext->getOperand(0)))
5883 if (
auto MD =
hasMetadata(I, LLVMContext::MD_range)) {
5887 cast<ConstantAsMetadata>(MD->getOperand(0))->getValue())
5892 cast<ConstantAsMetadata>(MD->getOperand(1))->getValue())
5897 if (ext->getOpcode() == Instruction::UIToFP) {
5898 rhsMax = APInt::getMaxValue(ity->getBitWidth()).zextOrTrunc(64);
5899 rhsMin = APInt(64, 0);
5902 APInt::getSignedMaxValue(ity->getBitWidth()).zextOrTrunc(64);
5904 APInt::getSignedMinValue(ity->getBitWidth()).zextOrTrunc(64);
5908 case Instruction::FAdd:
5912 case Instruction::FSub:
5913 case Instruction::FNeg:
5917 case Instruction::FMul: {
5918 auto minf = [&](APInt a, APInt b) {
return a.sle(b) ? a : b; };
5919 auto maxf = [&](APInt a, APInt b) {
return a.sle(b) ? b : b; };
5922 minf(minval * rhsMax, minf(maxval * rhsMin, maxval * rhsMax)));
5925 maxf(minval * rhsMax, maxf(maxval * rhsMin, maxval * rhsMax)));
5929 llvm_unreachable(
"Illegal opcode");
5931 if (ext->getOperand(0)->getType() == Ty)
5932 rhs = ext->getOperand(0);
5933 else if (ity->getBitWidth() < Ty->getBitWidth()) {
5934 if (ext->getOpcode() == Instruction::UIToFP)
5935 rhs = B.CreateZExt(ext->getOperand(0), Ty);
5937 rhs = B.CreateSExt(ext->getOperand(0), Ty);
5938 if (
auto I = dyn_cast<Instruction>(rhs))
5939 if (I != ext->getOperand(0))
5940 temporaries.insert(I);
5946 Value *res =
nullptr;
5947 if (temporaries.count(dyn_cast<Instruction>(lhs)))
5949 if (temporaries.count(dyn_cast<Instruction>(rhs)))
5952 case Instruction::FAdd:
5953 res = B.CreateAdd(lhs, rhs,
"",
false,
true);
5955 case Instruction::FSub:
5956 case Instruction::FNeg:
5957 res = B.CreateSub(lhs, rhs,
"",
false,
true);
5959 case Instruction::FMul:
5960 res = B.CreateMul(lhs, rhs,
"",
false,
true);
5963 llvm_unreachable(
"Illegal opcode");
5966 for (
auto I : precasts)
5979 auto ext = pushcse(B.CreateSIToFP(res, cur->getType()));
5980 replaceAndErase(cur, ext);
5981 return "BinopExtToExtBinop";
5984 for (
auto I : temporaries)
5985 I->eraseFromParent();
5991 if (
auto fcmp = dyn_cast<FCmpInst>(cur))
5992 for (
int i = 0; i < 2; i++)
5993 if (
auto const2 = dyn_cast<Constant>(fcmp->getOperand(i)))
5994 if (
auto sel = dyn_cast<SelectInst>(fcmp->getOperand(1 - i)))
5995 if (isa<Constant>(sel->getTrueValue()) ||
5996 isa<Constant>(sel->getFalseValue())) {
5997 auto tval = pushcse(B.CreateFCmp(fcmp->getPredicate(),
5998 sel->getTrueValue(), const2));
5999 auto fval = pushcse(B.CreateFCmp(fcmp->getPredicate(),
6000 sel->getFalseValue(), const2));
6001 auto res = pushcse(B.CreateSelect(sel->getCondition(), tval, fval));
6002 replaceAndErase(cur, res);
6003 return "FCmpSelectConst";
6011 if (cur->getOpcode() == Instruction::FMul)
6012 if (cur->isFast() && cur->getOperand(0) != cur->getOperand(1))
6013 for (
auto ic = 0; ic < 2; ic++)
6014 if (
auto mul = dyn_cast<Instruction>(cur->getOperand(ic)))
6015 if (mul->getOpcode() == Instruction::FMul && mul->isFast()) {
6016 auto b = cur->getOperand(1 - ic);
6019 for (
int i = 0; i < 2; i++)
6020 if (
auto C = dyn_cast<Constant>(mul->getOperand(i))) {
6022 pushcse(B.CreateFMulFMF(mul->getOperand(1 - i), b, mul));
6023 auto n1 = pushcse(B.CreateFMulFMF(n0, C, cur));
6026 replaceAndErase(cur, n1);
6027 return "MulMulConst";
6033 if (cur->getOpcode() == Instruction::FAdd ||
6034 cur->getOpcode() == Instruction::FSub) {
6035 if (
auto mul1 = dyn_cast<BinaryOperator>(cur->getOperand(0))) {
6036 if (mul1->getOpcode() == Instruction::FMul && mul1->isFast()) {
6037 if (
auto mul2 = dyn_cast<BinaryOperator>(cur->getOperand(1))) {
6038 if (mul2->getOpcode() == Instruction::FMul && mul2->isFast()) {
6039 for (
int i = 0; i < 2; i++) {
6040 for (
int j = 0; j < 2; j++) {
6041 if (mul1->getOperand(i) == mul2->getOperand(j)) {
6042 auto c = mul1->getOperand(i);
6043 auto a = mul1->getOperand(1 - i);
6044 auto b = mul2->getOperand(1 - j);
6045 Value *intermediate =
nullptr;
6047 if (cur->getOpcode() == Instruction::FAdd)
6048 intermediate = pushcse(B.CreateFAddFMF(a, b, cur));
6050 intermediate = pushcse(B.CreateFSubFMF(a, b, cur));
6052 auto res = pushcse(B.CreateFMulFMF(c, intermediate, cur));
6055 replaceAndErase(cur, res);
6056 return "FAddMulConstMulConst";
6069 if (cur->getOpcode() == Instruction::FMul && cur->isFast()) {
6070 for (
int i = 0; i < 2; i++)
6071 if (
auto z = dyn_cast<Instruction>(cur->getOperand(i)))
6072 if (isa<SIToFPInst>(z) || isa<UIToFPInst>(z))
6073 if (
auto imul = dyn_cast<BinaryOperator>(z->getOperand(0)))
6074 if (imul->getOpcode() == Instruction::Mul)
6075 for (
int j = 0; j < 2; j++)
6076 if (
auto c = dyn_cast<Constant>(imul->getOperand(j))) {
6077 auto b = imul->getOperand(1 - j);
6078 auto a = cur->getOperand(1 - i);
6080 auto c_fp = pushcse(B.CreateSIToFP(c, cur->getType()));
6081 auto b_fp = pushcse(B.CreateSIToFP(b, cur->getType()));
6082 auto n_mul = pushcse(B.CreateFMulFMF(a, c_fp, cur));
6084 B.CreateFMulFMF(n_mul, b_fp, cur, cur->getName()));
6087 replaceAndErase(cur, res);
6088 return "FMulIMulConstRotate";
6092 if (cur->getOpcode() == Instruction::FDiv) {
6093 Value *prelhs = cur->getOperand(0);
6094 Value *b = cur->getOperand(1);
6097 if (
auto ext = dyn_cast<CastInst>(prelhs)) {
6098 if (ext->getOpcode() == Instruction::UIToFP ||
6099 ext->getOpcode() == Instruction::SIToFP) {
6102 Value *condition = pushcse(
6103 B.CreateICmpEQ(ext->getOperand(0),
6104 ConstantInt::get(ext->getOperand(0)->getType(), 0),
6105 "sdivcmp." + cur->getName()));
6107 Value *fdiv = pushcse(
6108 B.CreateFMulFMF(pushcse(B.CreateFDivFMF(
6109 ConstantFP::get(cur->getType(), 1.0), b, cur)),
6112 Value *sel = pushcse(
6113 B.CreateSelect(condition, ConstantFP::get(cur->getType(), 0.0),
6114 fdiv,
"sfdiv." + cur->getName()));
6116 replaceAndErase(cur, sel);
6117 return "FDivSIToFPProp";
6121 if (
auto SI = dyn_cast<SelectInst>(prelhs)) {
6122 auto tvalC = dyn_cast<ConstantFP>(SI->getTrueValue());
6123 auto fvalC = dyn_cast<ConstantFP>(SI->getFalseValue());
6124 if ((tvalC && tvalC->isZero()) || (fvalC && fvalC->isZero())) {
6127 (tvalC && tvalC->isZero())
6129 : pushcse(B.CreateFDivFMF(SI->getTrueValue(), b, cur,
6130 "sfdiv2_t." + cur->getName()));
6132 (fvalC && fvalC->isZero())
6134 : pushcse(B.CreateFDivFMF(SI->getFalseValue(), b, cur,
6135 "sfdiv2_f." + cur->getName()));
6139#if LLVM_VERSION_MAJOR < 16
6140 for (
auto v : {ntval, nfval})
6141 if (
auto I = dyn_cast<Instruction>(v))
6142 I->setFastMathFlags(cur->getFastMathFlags());
6145 auto res = pushcse(B.CreateSelect(SI->getCondition(), ntval, nfval,
6146 "sfdiv2." + cur->getName()));
6148 replaceAndErase(cur, res);
6149 return "FDivSelectProp";
6155 if (cur->getOpcode() == Instruction::FDiv) {
6156 auto c = cur->getOperand(1);
6157 if (
auto z = dyn_cast<BinaryOperator>(cur->getOperand(0))) {
6158 if (z->getOpcode() == Instruction::FMul) {
6159 for (
int i = 0; i < 2; i++) {
6161 Value *a = z->getOperand(i);
6162 Value *b = z->getOperand(1 - i);
6168 Value *inner_fdiv = pushcse(B.CreateFDivFMF(a, c, cur));
6169 Value *outer_fmul = pushcse(B.CreateFMulFMF(inner_fdiv, b, z));
6171 replaceAndErase(cur, outer_fmul);
6172 return "FDivFMulSparseProp";
6178 if (cur->getOpcode() == Instruction::FMul)
6179 for (
int i = 0; i < 2; i++) {
6181 Value *prelhs = cur->getOperand(i);
6182 Value *b = cur->getOperand(1 - i);
6185 if (isa<Constant>(b))
6186 if (
auto z = dyn_cast<BinaryOperator>(prelhs)) {
6187 if (z->getOpcode() == Instruction::FMul) {
6188 for (
int j = 0; j < 2; j++) {
6189 auto x = z->getOperand(i);
6190 if (!isa<Constant>(x))
6192 auto y = z->getOperand(1 - i);
6193 Value *inner_fmul = pushcse(B.CreateFMulFMF(x, b, cur));
6194 Value *outer_fmul = pushcse(B.CreateFMulFMF(inner_fmul, y, z));
6196 replaceAndErase(cur, outer_fmul);
6197 return "FMulFMulConstantReorder";
6202 auto integralFloat = [](Value *z) {
6203 if (
auto C = dyn_cast<ConstantFP>(z)) {
6205 bool isExact =
false;
6206 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
6208 if (isExact || C->isZero()) {
6223 if (
auto z = dyn_cast<BinaryOperator>(prelhs)) {
6224 if (z->getOpcode() == Instruction::FMul) {
6225 for (
int j = 0; j < 2; j++) {
6226 auto x = z->getOperand(j);
6229 auto y = z->getOperand(1 - j);
6235 Value *inner_fmul = pushcse(
6236 B.CreateFMulFMF(x, b, cur,
"mulisr." + cur->getName()));
6237 Value *outer_fmul = pushcse(
6238 B.CreateFMulFMF(inner_fmul, y, z,
"mulisr." + z->getName()));
6239 replaceAndErase(cur, outer_fmul);
6240 return "FMulFMulSparseReorder";
6243 Value *inner_fmul = pushcse(
6244 B.CreateFMulFMF(y, b, cur,
"mulisp." + cur->getName()));
6245 Value *outer_fmul = pushcse(
6246 B.CreateFMulFMF(inner_fmul, x, z,
"mulisp." + z->getName()));
6247 replaceAndErase(cur, outer_fmul);
6248 return "FMulFMulSparsePush";
6302 if (
auto SI = dyn_cast<SelectInst>(prelhs)) {
6303 auto tvalC = dyn_cast<ConstantFP>(SI->getTrueValue());
6304 auto fvalC = dyn_cast<ConstantFP>(SI->getFalseValue());
6305 if ((tvalC && tvalC->isZero()) || (fvalC && fvalC->isZero())) {
6308 (tvalC && tvalC->isZero())
6310 : pushcse(B.CreateFMulFMF(SI->getTrueValue(), b, cur));
6312 (fvalC && fvalC->isZero())
6314 : pushcse(B.CreateFMulFMF(SI->getFalseValue(), b, cur));
6315 auto res = pushcse(B.CreateSelect(SI->getCondition(), ntval, nfval,
6316 "mulsi." + cur->getName()));
6318 replaceAndErase(cur, res);
6319 return "FMulSelectProp";
6324 if (
auto icmp = dyn_cast<BinaryOperator>(cur)) {
6325 if (icmp->getOpcode() == Instruction::Xor) {
6326 for (
int i = 0; i < 2; i++) {
6327 if (
auto C = dyn_cast<ConstantInt>(icmp->getOperand(i))) {
6330 if (
auto scmp = dyn_cast<CmpInst>(icmp->getOperand(1 - i))) {
6331 auto next = pushcse(
6332 B.CreateCmp(scmp->getInversePredicate(), scmp->getOperand(0),
6333 scmp->getOperand(1),
"not." + scmp->getName()));
6334 replaceAndErase(cur, next);
6344 if (
auto SI = dyn_cast<SelectInst>(cur)) {
6346 Value *trueVal =
nullptr;
6347 if (
auto C = dyn_cast<ConstantFP>(SI->getTrueValue())) {
6349 trueVal = ConstantInt::getFalse(SI->getContext());
6351 if (C->isExactlyValue(1.0)) {
6352 trueVal = ConstantInt::getTrue(SI->getContext());
6355 if (
auto ext = dyn_cast<CastInst>(SI->getTrueValue())) {
6356 if (ext->getOperand(0)->getType()->isIntegerTy(1))
6357 trueVal = ext->getOperand(0);
6359 Value *falseVal =
nullptr;
6360 if (
auto C = dyn_cast<ConstantFP>(SI->getFalseValue())) {
6362 falseVal = ConstantInt::getFalse(SI->getContext());
6364 if (C->isExactlyValue(1.0)) {
6365 falseVal = ConstantInt::getTrue(SI->getContext());
6368 if (
auto ext = dyn_cast<CastInst>(SI->getFalseValue())) {
6369 if (ext->getOperand(0)->getType()->isIntegerTy(1))
6370 falseVal = ext->getOperand(0);
6372 if (trueVal && falseVal) {
6373 auto ncmp1 = pushcse(B.CreateAnd(SI->getCondition(), trueVal));
6374 auto notV = pushcse(B.CreateNot(SI->getCondition()));
6375 auto ncmp2 = pushcse(B.CreateAnd(notV, falseVal));
6376 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
6377 auto ext = pushcse(B.CreateUIToFP(ori, SI->getType()));
6378 replaceAndErase(cur, ext);
6379 return "SelectI1Ext";
6383 if (cur->getType()->isIntegerTy(1))
6384 if (
auto SI = dyn_cast<SelectInst>(cur)) {
6385 auto ncmp1 = pushcse(B.CreateAnd(SI->getCondition(), SI->getTrueValue()));
6386 auto notV = pushcse(B.CreateNot(SI->getCondition()));
6387 auto ncmp2 = pushcse(B.CreateAnd(notV, SI->getFalseValue()));
6388 auto ori = pushcse(B.CreateOr(ncmp1, ncmp2));
6389 replaceAndErase(cur, ori);
6393 if (
auto PN = dyn_cast<PHINode>(cur)) {
6394 B.SetInsertPoint(PN->getParent()->getFirstNonPHI());
6395 if (SE.isSCEVable(PN->getType())) {
6396 auto S = SE.getSCEV(PN);
6399 if (
auto SV = dyn_cast<SCEVUnknown>(S)) {
6400 auto val = SV->getValue();
6401 legal |= isa<Constant>(val) || isa<Argument>(val);
6402 if (
auto I = dyn_cast<Instruction>(val)) {
6403 auto L = LI.getLoopFor(I->getParent());
6404 if ((!L || L->getCanonicalInductionVariable() != I) && I != PN)
6408 if (isa<SCEVAddRecExpr>(S)) {
6409 auto L = LI.getLoopFor(PN->getParent());
6411 if (L->getCanonicalInductionVariable() != PN)
6416 for (
auto U : cur->users()) {
6419 auto point = PN->getParent()->getFirstNonPHI();
6420 auto tmp = cast<PHINode>(pushcse(B.CreatePHI(cur->getType(), 1)));
6421 cur->replaceAllUsesWith(tmp);
6422 cur->eraseFromParent();
6424 Value *newIV =
nullptr;
6426#if LLVM_VERSION_MAJOR >= 22
6427 SCEVExpander Exp(SE,
"sparseenzyme");
6429 SCEVExpander Exp(SE, DL,
"sparseenzyme");
6433 newIV = Exp.expandCodeFor(S, tmp->getType(), point);
6435 for (
auto I : Exp.getAllInsertedInstructions())
6439 tmp->replaceAllUsesWith(newIV);
6440 tmp->eraseFromParent();
6441 return "InductVarSCEV";
6447 for (
size_t i = 1; i < PN->getNumIncomingValues(); i++) {
6448 auto v = PN->getIncomingValue(i);
6449 if (v != PN->getIncomingValue(0)) {
6455 auto val = PN->getIncomingValue(0);
6456 replaceAndErase(cur, val);
6461 if (
auto L = LI.getLoopFor(PN->getParent()))
6462 if (L->getHeader() == PN->getParent())
6463 if (
auto idx = L->getCanonicalInductionVariable())
6464 if (
auto PH = L->getLoopPreheader()) {
6465 bool legal = idx != PN;
6466 auto ph_idx = PN->getBasicBlockIndex(PH);
6467 assert(ph_idx >= 0);
6468 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
6469 if ((
int)i == ph_idx)
6471 auto v = PN->getIncomingValue(i);
6472 if (v != PN->getIncomingValue(1 - ph_idx)) {
6477 if (isa<Constant>(v))
6479 if (isa<Argument>(v))
6484 auto I = cast<Instruction>(v);
6485 if (!DT.dominates(I, PN)) {
6491 auto val = PN->getIncomingValue(1 - ph_idx);
6495 B.CreateSub(idx, ConstantInt::get(idx->getType(), 1)));
6498 auto val2 = PN->getIncomingValue(ph_idx);
6501 auto c0 = ConstantInt::get(idx->getType(), 0);
6505 auto eq = pushcse(B.CreateICmpEQ(idx, c0));
6507 B.CreateSelect(eq, val2, val,
"phisel." + cur->getName()));
6510 replaceAndErase(cur, val);
6511 return "PhiLoop0Sel";
6516 SmallVector<Value *, 1> negOps;
6517 SmallVector<Instruction *, 1> prevNegOps;
6519 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
6520 auto v = PN->getIncomingValue(i);
6521 if (
auto C = dyn_cast<ConstantFP>(v)) {
6523 bool isExact =
false;
6524 C->getValue().convertToInteger(Tmp, llvm::RoundingMode::TowardZero,
6526 if (isExact || C->isZero()) {
6527 negOps.push_back(ConstantInt::get(B.getInt64Ty(), Tmp));
6531 if (
auto fneg = dyn_cast<Instruction>(v)) {
6532 if (fneg->getOpcode() == Instruction::SIToFP &&
6533 cast<IntegerType>(fneg->getOperand(0)->getType())
6534 ->getBitWidth() == 64) {
6535 negOps.push_back(fneg->getOperand(0));
6536 prevNegOps.push_back(fneg);
6543 auto PN2 = cast<PHINode>(
6544 pushcse(B.CreatePHI(B.getInt64Ty(), PN->getNumIncomingValues())));
6546 for (
auto val : llvm::enumerate(negOps))
6547 PN2->addIncoming(val.value(), PN->getIncomingBlock(val.index()));
6551 auto fneg = pushcse(B.CreateSIToFP(PN2, PN->getType()));
6553 for (
auto I : prevNegOps)
6555 replaceAndErase(cur, fneg);
6561 SmallVector<Value *, 1> negOps;
6562 SmallVector<Instruction *, 1> prevNegOps;
6564 bool hasNeg =
false;
6565 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
6566 auto v = PN->getIncomingValue(i);
6567 if (
auto C = dyn_cast<ConstantFP>(v)) {
6568 negOps.push_back(C->isZero() ? C : pushcse(B.CreateFNeg(C)));
6571 if (
auto fneg = dyn_cast<Instruction>(v)) {
6572 if (fneg->getOpcode() == Instruction::FNeg) {
6573 negOps.push_back(fneg->getOperand(0));
6574 prevNegOps.push_back(fneg);
6580 if (legal && hasNeg) {
6581 for (
auto val : llvm::enumerate(negOps))
6582 PN->setIncomingValue(val.index(), val.value());
6586 auto fneg = pushcse(B.CreateFNeg(PN));
6588 for (
auto &U : cur->uses()) {
6589 if (U.getUser() == fneg)
6594 for (
auto I : prevNegOps)
6601 SmallVector<Value *, 1> negOps;
6602 SmallVector<Instruction *, 1> prevNegOps;
6604 bool hasNeg =
false;
6605 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
6606 auto v = PN->getIncomingValue(i);
6607 if (
auto C = dyn_cast<ConstantInt>(v)) {
6608 negOps.push_back(pushcse(B.CreateNeg(C)));
6611 if (
auto fneg = dyn_cast<BinaryOperator>(v)) {
6612 if (
auto CI = dyn_cast<ConstantInt>(fneg->getOperand(0)))
6613 if (fneg->getOpcode() == Instruction::Sub && CI->isZero()) {
6614 negOps.push_back(fneg->getOperand(1));
6615 prevNegOps.push_back(fneg);
6622 if (legal && hasNeg) {
6623 for (
auto val : llvm::enumerate(negOps))
6624 PN->setIncomingValue(val.index(), val.value());
6628 auto fneg = pushcse(B.CreateNeg(PN));
6630 for (
auto &U : cur->uses()) {
6631 if (U.getUser() == fneg)
6636 for (
auto I : prevNegOps)
6645 {(unsigned)Instruction::Mul, (
unsigned)Instruction::Sub,
6646 (unsigned)Instruction::Add, (
unsigned)Instruction::ZExt,
6647 (unsigned)Instruction::UIToFP, (
unsigned)Instruction::ICmp,
6648 (unsigned)Instruction::FMul, (
unsigned)Instruction::Or,
6649 (unsigned)Instruction::And}) {
6650 SmallVector<Value *, 1> lhsOps;
6651 SmallVector<Value *, 1> rhsOps;
6652 SmallVector<Instruction *, 1> prevOps;
6658 std::optional<llvm::CmpInst::Predicate> cmpPredicate;
6660 case Instruction::FMul:
6661 case Instruction::FSub:
6662 case Instruction::FAdd:
6666 case Instruction::Mul:
6667 case Instruction::Add:
6671 case Instruction::Sub:
6675 case Instruction::ICmp:
6676 case Instruction::FCmp:
6677 case Instruction::Or:
6678 case Instruction::And:
6681 case Instruction::ZExt:
6682 case Instruction::UIToFP:
6686 llvm_unreachable(
"unknown opcode");
6688 bool changed =
false;
6689 for (
size_t i = 0; i < PN->getNumIncomingValues(); i++) {
6690 auto v = PN->getIncomingValue(i);
6691 if (
auto C = dyn_cast<ConstantInt>(v)) {
6692 if (code == Instruction::ZExt) {
6693 lhsOps.push_back(ConstantInt::getFalse(C->getContext()));
6695 }
else if (C->isZero()) {
6696 rhsOps.push_back(C);
6697 lhsOps.push_back(C);
6701 if (
auto C = dyn_cast<ConstantFP>(v)) {
6702 if (code == Instruction::UIToFP) {
6704 lhsOps.push_back(ConstantInt::getFalse(C->getContext()));
6706 }
else if (code == Instruction::FMul || code == Instruction::FSub ||
6707 code == Instruction::FAdd) {
6709 rhsOps.push_back(C);
6710 lhsOps.push_back(C);
6715 if (
auto fneg = dyn_cast<Instruction>(v)) {
6716 if (fneg->getOpcode() == code) {
6718 case Instruction::FMul:
6719 case Instruction::FSub:
6720 case Instruction::FAdd:
6721 fast &= fneg->isFast();
6722 if (fneg->getOperand(0) == PN)
6724 if (fneg->getOperand(1) == PN)
6726 lhsOps.push_back(fneg->getOperand(0));
6727 rhsOps.push_back(fneg->getOperand(1));
6729 case Instruction::Mul:
6730 case Instruction::Sub:
6731 case Instruction::Add:
6732 NUW &= fneg->hasNoUnsignedWrap();
6733 NSW &= fneg->hasNoSignedWrap();
6734 if (fneg->getOperand(0) == PN)
6736 if (fneg->getOperand(1) == PN)
6738 lhsOps.push_back(fneg->getOperand(0));
6739 rhsOps.push_back(fneg->getOperand(1));
6741 case Instruction::Or:
6742 case Instruction::And:
6743 if (fneg->getOperand(0) == PN)
6745 if (fneg->getOperand(1) == PN)
6747 lhsOps.push_back(fneg->getOperand(0));
6748 rhsOps.push_back(fneg->getOperand(1));
6750 case Instruction::ICmp:
6751 case Instruction::FCmp:
6752 if (fneg->getOperand(0) == PN)
6754 if (fneg->getOperand(1) == PN)
6757 if (*cmpPredicate != cast<CmpInst>(fneg)->getPredicate())
6760 cmpPredicate = cast<CmpInst>(fneg)->getPredicate();
6762 lhsOps.push_back(fneg->getOperand(0));
6763 rhsOps.push_back(fneg->getOperand(1));
6765 case Instruction::ZExt:
6766 case Instruction::UIToFP:
6767 if (cast<IntegerType>(fneg->getOperand(0)->getType())
6768 ->getBitWidth() != 1)
6770 lhsOps.push_back(fneg->getOperand(0));
6773 llvm_unreachable(
"unhandled opcode");
6775 prevOps.push_back(fneg);
6783 int preheader_fix = -1;
6785 if (code == Instruction::ICmp || code == Instruction::FCmp) {
6788 auto L = LI.getLoopFor(PN->getParent());
6789 if (legal && L && L->getLoopPreheader() &&
6790 L->getCanonicalInductionVariable() &&
6791 L->getHeader() == PN->getParent()) {
6792 auto ph_idx = PN->getBasicBlockIndex(L->getLoopPreheader());
6793 if (isa<ConstantInt>(PN->getIncomingValue(ph_idx))) {
6795 Constant::getNullValue(lhsOps[1 - ph_idx]->getType());
6797 Constant::getNullValue(rhsOps[1 - ph_idx]->getType());
6798 preheader_fix = ph_idx;
6801 for (
auto v : lhsOps)
6802 if (v->getType() != lhsOps[0]->getType())
6804 for (
auto v : rhsOps)
6805 if (v->getType() != rhsOps[0]->getType())
6809 if (legal && changed) {
6810 auto lhsPN = cast<PHINode>(pushcse(
6811 B.CreatePHI(lhsOps[0]->getType(), PN->getNumIncomingValues())));
6812 PHINode *rhsPN =
nullptr;
6814 rhsPN = cast<PHINode>(pushcse(
6815 B.CreatePHI(rhsOps[0]->getType(), PN->getNumIncomingValues())));
6817 for (
auto val : llvm::enumerate(lhsOps))
6818 lhsPN->addIncoming(val.value(), PN->getIncomingBlock(val.index()));
6821 for (
auto val : llvm::enumerate(rhsOps))
6822 rhsPN->addIncoming(val.value(),
6823 PN->getIncomingBlock(val.index()));
6826 Value *fneg =
nullptr;
6828 case Instruction::FMul:
6829 fneg = B.CreateFMul(lhsPN, rhsPN);
6830 if (
auto I = dyn_cast<Instruction>(fneg))
6833 case Instruction::FAdd:
6834 fneg = B.CreateFAdd(lhsPN, rhsPN);
6835 if (
auto I = dyn_cast<Instruction>(fneg))
6838 case Instruction::FSub:
6839 fneg = B.CreateFSub(lhsPN, rhsPN);
6840 if (
auto I = dyn_cast<Instruction>(fneg))
6843 case Instruction::Mul:
6844 fneg = B.CreateMul(lhsPN, rhsPN,
"", NUW, NSW);
6846 case Instruction::Add:
6847 fneg = B.CreateAdd(lhsPN, rhsPN,
"", NUW, NSW);
6849 case Instruction::Sub:
6850 fneg = B.CreateSub(lhsPN, rhsPN,
"", NUW, NSW);
6852 case Instruction::ZExt:
6853 fneg = B.CreateZExt(lhsPN, PN->getType());
6855 case Instruction::FCmp:
6856 case Instruction::ICmp:
6857 fneg = B.CreateCmp(*cmpPredicate, lhsPN, rhsPN);
6859 case Instruction::UIToFP:
6860 fneg = B.CreateUIToFP(lhsPN, PN->getType());
6862 case Instruction::Or:
6863 fneg = B.CreateOr(lhsPN, rhsPN);
6865 case Instruction::And:
6866 fneg = B.CreateAnd(lhsPN, rhsPN);
6869 llvm_unreachable(
"unhandled opcode");
6874 if (preheader_fix != -1) {
6875 auto L = LI.getLoopFor(PN->getParent());
6876 auto idx = L->getCanonicalInductionVariable();
6878 B.CreateICmpEQ(idx, ConstantInt::get(idx->getType(), 0)));
6880 pushcse(B.CreateSelect(eq, PN->getIncomingValue(preheader_fix),
6881 fneg,
"phphisel." + cur->getName()));
6884 replaceAndErase(cur, fneg);
6890 if (PN->getNumIncomingValues() == 2) {
6891 for (
int i = 0; i < 2; i++) {
6892 auto prev = PN->getIncomingBlock(i);
6893 if (!DT.dominates(prev, PN->getParent())) {
6896 auto br = dyn_cast<BranchInst>(prev->getTerminator());
6900 if (!br->isConditional()) {
6903 if (br->getSuccessor(0) != PN->getParent()) {
6906 if (br->getSuccessor(1) != PN->getIncomingBlock(1 - i)) {
6910 Value *specVal = PN->getIncomingValue(1 - i);
6911 SetVector<Value *, std::deque<Value *>> todo;
6912 todo.insert(specVal);
6913 SetVector<Instruction *> toMove;
6915 while (!todo.empty()) {
6916 auto cur = *todo.begin();
6917 todo.erase(todo.begin());
6918 auto I = dyn_cast<Instruction>(cur);
6921 if (I->mayReadOrWriteMemory()) {
6925 if (DT.dominates(I, PN))
6927 for (
size_t i = 0; i < I->getNumOperands(); i++)
6928 todo.insert(I->getOperand(i));
6933 for (
auto iter = toMove.rbegin(), end = toMove.rend(); iter != end;
6935 (*iter)->moveBefore(br);
6937 auto sel = pushcse(B.CreateSelect(
6938 br->getCondition(), PN->getIncomingValueForBlock(prev),
6939 PN->getIncomingValueForBlock(br->getSuccessor(1)),
6940 "tphisel." + cur->getName()));
6942 replaceAndErase(cur, sel);
6948 if (
auto SI = dyn_cast<SelectInst>(cur)) {
6949 auto tval = replace(SI->getTrueValue(), SI->getCondition(),
6950 ConstantInt::getTrue(SI->getContext()));
6951 auto fval = replace(SI->getFalseValue(), SI->getCondition(),
6952 ConstantInt::getFalse(SI->getContext()));
6953 if (tval != SI->getTrueValue() || fval != SI->getFalseValue()) {
6954 auto res = pushcse(B.CreateSelect(SI->getCondition(), tval, fval,
6955 "postsel." + SI->getName()));
6956 replaceAndErase(cur, res);
6957 return "SelectReplace";
6962 if (cur->getOpcode() == Instruction::And) {
6963 auto lhs = replace(cur->getOperand(0), cur->getOperand(1),
6964 ConstantInt::getTrue(cur->getContext()));
6965 if (lhs != cur->getOperand(0)) {
6967 B.CreateAnd(lhs, cur->getOperand(1),
"postand." + cur->getName()));
6968 replaceAndErase(cur, res);
6969 return "AndReplaceLHS";
6971 auto rhs = replace(cur->getOperand(1), cur->getOperand(0),
6972 ConstantInt::getTrue(cur->getContext()));
6973 if (rhs != cur->getOperand(1)) {
6975 B.CreateAnd(cur->getOperand(0), rhs,
"postand." + cur->getName()));
6976 replaceAndErase(cur, res);
6977 return "AndReplaceRHS";
6982 if (cur->getOpcode() == Instruction::Or) {
6983 auto lhs = replace(cur->getOperand(0), cur->getOperand(1),
6984 ConstantInt::getFalse(cur->getContext()));
6985 if (lhs != cur->getOperand(0)) {
6987 B.CreateOr(lhs, cur->getOperand(1),
"postor." + cur->getName()));
6988 replaceAndErase(cur, res);
6989 return "OrReplaceLHS";
6991 auto rhs = replace(cur->getOperand(1), cur->getOperand(0),
6992 ConstantInt::getFalse(cur->getContext()));
6993 if (rhs != cur->getOperand(1)) {
6995 B.CreateOr(cur->getOperand(0), rhs,
"postor." + cur->getName()));
6996 replaceAndErase(cur, res);
6997 return "OrReplaceRHS";