xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- InstCombineMulDivRem.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the visit functions for mul, fmul, sdiv, udiv, fdiv,
100b57cec5SDimitry Andric // srem, urem, frem.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "InstCombineInternal.h"
150b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h"
18bdd1243dSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
190b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
200b57cec5SDimitry Andric #include "llvm/IR/Constant.h"
210b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
220b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
230b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
240b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
250b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
260b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h"
270b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
280b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
290b57cec5SDimitry Andric #include "llvm/IR/Type.h"
300b57cec5SDimitry Andric #include "llvm/IR/Value.h"
310b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
320b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
33e8d8bef9SDimitry Andric #include "llvm/Transforms/InstCombine/InstCombiner.h"
340b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BuildLibCalls.h"
350b57cec5SDimitry Andric #include <cassert>
360b57cec5SDimitry Andric 
37349cc55cSDimitry Andric #define DEBUG_TYPE "instcombine"
38349cc55cSDimitry Andric #include "llvm/Transforms/Utils/InstructionWorklist.h"
39349cc55cSDimitry Andric 
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric using namespace PatternMatch;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// The specific integer value is used in a context where it is known to be
440b57cec5SDimitry Andric /// non-zero.  If this allows us to simplify the computation, do so and return
450b57cec5SDimitry Andric /// the new operand, otherwise return null.
simplifyValueKnownNonZero(Value * V,InstCombinerImpl & IC,Instruction & CxtI)46e8d8bef9SDimitry Andric static Value *simplifyValueKnownNonZero(Value *V, InstCombinerImpl &IC,
470b57cec5SDimitry Andric                                         Instruction &CxtI) {
480b57cec5SDimitry Andric   // If V has multiple uses, then we would have to do more analysis to determine
490b57cec5SDimitry Andric   // if this is safe.  For example, the use could be in dynamically unreached
500b57cec5SDimitry Andric   // code.
510b57cec5SDimitry Andric   if (!V->hasOneUse()) return nullptr;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   bool MadeChange = false;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   // ((1 << A) >>u B) --> (1 << (A-B))
560b57cec5SDimitry Andric   // Because V cannot be zero, we know that B is less than A.
570b57cec5SDimitry Andric   Value *A = nullptr, *B = nullptr, *One = nullptr;
580b57cec5SDimitry Andric   if (match(V, m_LShr(m_OneUse(m_Shl(m_Value(One), m_Value(A))), m_Value(B))) &&
590b57cec5SDimitry Andric       match(One, m_One())) {
600b57cec5SDimitry Andric     A = IC.Builder.CreateSub(A, B);
610b57cec5SDimitry Andric     return IC.Builder.CreateShl(One, A);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   // (PowerOfTwo >>u B) --> isExact since shifting out the result would make it
650b57cec5SDimitry Andric   // inexact.  Similarly for <<.
660b57cec5SDimitry Andric   BinaryOperator *I = dyn_cast<BinaryOperator>(V);
670b57cec5SDimitry Andric   if (I && I->isLogicalShift() &&
680b57cec5SDimitry Andric       IC.isKnownToBeAPowerOfTwo(I->getOperand(0), false, 0, &CxtI)) {
690b57cec5SDimitry Andric     // We know that this is an exact/nuw shift and that the input is a
700b57cec5SDimitry Andric     // non-zero context as well.
710b57cec5SDimitry Andric     if (Value *V2 = simplifyValueKnownNonZero(I->getOperand(0), IC, CxtI)) {
725ffd83dbSDimitry Andric       IC.replaceOperand(*I, 0, V2);
730b57cec5SDimitry Andric       MadeChange = true;
740b57cec5SDimitry Andric     }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric     if (I->getOpcode() == Instruction::LShr && !I->isExact()) {
770b57cec5SDimitry Andric       I->setIsExact();
780b57cec5SDimitry Andric       MadeChange = true;
790b57cec5SDimitry Andric     }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric     if (I->getOpcode() == Instruction::Shl && !I->hasNoUnsignedWrap()) {
820b57cec5SDimitry Andric       I->setHasNoUnsignedWrap();
830b57cec5SDimitry Andric       MadeChange = true;
840b57cec5SDimitry Andric     }
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   // TODO: Lots more we could do here:
880b57cec5SDimitry Andric   //    If V is a phi node, we can call this on each of its operands.
890b57cec5SDimitry Andric   //    "select cond, X, 0" can simplify to "X".
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   return MadeChange ? V : nullptr;
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
948bcb0991SDimitry Andric // TODO: This is a specific form of a much more general pattern.
958bcb0991SDimitry Andric //       We could detect a select with any binop identity constant, or we
968bcb0991SDimitry Andric //       could use SimplifyBinOp to see if either arm of the select reduces.
978bcb0991SDimitry Andric //       But that needs to be done carefully and/or while removing potential
988bcb0991SDimitry Andric //       reverse canonicalizations as in InstCombiner::foldSelectIntoOp().
foldMulSelectToNegate(BinaryOperator & I,InstCombiner::BuilderTy & Builder)998bcb0991SDimitry Andric static Value *foldMulSelectToNegate(BinaryOperator &I,
1008bcb0991SDimitry Andric                                     InstCombiner::BuilderTy &Builder) {
1018bcb0991SDimitry Andric   Value *Cond, *OtherOp;
1028bcb0991SDimitry Andric 
1038bcb0991SDimitry Andric   // mul (select Cond, 1, -1), OtherOp --> select Cond, OtherOp, -OtherOp
1048bcb0991SDimitry Andric   // mul OtherOp, (select Cond, 1, -1) --> select Cond, OtherOp, -OtherOp
1058bcb0991SDimitry Andric   if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes())),
106349cc55cSDimitry Andric                         m_Value(OtherOp)))) {
107349cc55cSDimitry Andric     bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap();
108*0fca6ea1SDimitry Andric     Value *Neg = Builder.CreateNeg(OtherOp, "", HasAnyNoWrap);
109349cc55cSDimitry Andric     return Builder.CreateSelect(Cond, OtherOp, Neg);
110349cc55cSDimitry Andric   }
1118bcb0991SDimitry Andric   // mul (select Cond, -1, 1), OtherOp --> select Cond, -OtherOp, OtherOp
1128bcb0991SDimitry Andric   // mul OtherOp, (select Cond, -1, 1) --> select Cond, -OtherOp, OtherOp
1138bcb0991SDimitry Andric   if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One())),
114349cc55cSDimitry Andric                         m_Value(OtherOp)))) {
115349cc55cSDimitry Andric     bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap();
116*0fca6ea1SDimitry Andric     Value *Neg = Builder.CreateNeg(OtherOp, "", HasAnyNoWrap);
117349cc55cSDimitry Andric     return Builder.CreateSelect(Cond, Neg, OtherOp);
118349cc55cSDimitry Andric   }
1198bcb0991SDimitry Andric 
1208bcb0991SDimitry Andric   // fmul (select Cond, 1.0, -1.0), OtherOp --> select Cond, OtherOp, -OtherOp
1218bcb0991SDimitry Andric   // fmul OtherOp, (select Cond, 1.0, -1.0) --> select Cond, OtherOp, -OtherOp
1228bcb0991SDimitry Andric   if (match(&I, m_c_FMul(m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(1.0),
1238bcb0991SDimitry Andric                                            m_SpecificFP(-1.0))),
1248bcb0991SDimitry Andric                          m_Value(OtherOp)))) {
1258bcb0991SDimitry Andric     IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
1268bcb0991SDimitry Andric     Builder.setFastMathFlags(I.getFastMathFlags());
1278bcb0991SDimitry Andric     return Builder.CreateSelect(Cond, OtherOp, Builder.CreateFNeg(OtherOp));
1288bcb0991SDimitry Andric   }
1298bcb0991SDimitry Andric 
1308bcb0991SDimitry Andric   // fmul (select Cond, -1.0, 1.0), OtherOp --> select Cond, -OtherOp, OtherOp
1318bcb0991SDimitry Andric   // fmul OtherOp, (select Cond, -1.0, 1.0) --> select Cond, -OtherOp, OtherOp
1328bcb0991SDimitry Andric   if (match(&I, m_c_FMul(m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(-1.0),
1338bcb0991SDimitry Andric                                            m_SpecificFP(1.0))),
1348bcb0991SDimitry Andric                          m_Value(OtherOp)))) {
1358bcb0991SDimitry Andric     IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
1368bcb0991SDimitry Andric     Builder.setFastMathFlags(I.getFastMathFlags());
1378bcb0991SDimitry Andric     return Builder.CreateSelect(Cond, Builder.CreateFNeg(OtherOp), OtherOp);
1388bcb0991SDimitry Andric   }
1398bcb0991SDimitry Andric 
1408bcb0991SDimitry Andric   return nullptr;
1418bcb0991SDimitry Andric }
1428bcb0991SDimitry Andric 
143bdd1243dSDimitry Andric /// Reduce integer multiplication patterns that contain a (+/-1 << Z) factor.
144bdd1243dSDimitry Andric /// Callers are expected to call this twice to handle commuted patterns.
foldMulShl1(BinaryOperator & Mul,bool CommuteOperands,InstCombiner::BuilderTy & Builder)145bdd1243dSDimitry Andric static Value *foldMulShl1(BinaryOperator &Mul, bool CommuteOperands,
146bdd1243dSDimitry Andric                           InstCombiner::BuilderTy &Builder) {
147bdd1243dSDimitry Andric   Value *X = Mul.getOperand(0), *Y = Mul.getOperand(1);
148bdd1243dSDimitry Andric   if (CommuteOperands)
149bdd1243dSDimitry Andric     std::swap(X, Y);
150bdd1243dSDimitry Andric 
151bdd1243dSDimitry Andric   const bool HasNSW = Mul.hasNoSignedWrap();
152bdd1243dSDimitry Andric   const bool HasNUW = Mul.hasNoUnsignedWrap();
153bdd1243dSDimitry Andric 
154bdd1243dSDimitry Andric   // X * (1 << Z) --> X << Z
155bdd1243dSDimitry Andric   Value *Z;
156bdd1243dSDimitry Andric   if (match(Y, m_Shl(m_One(), m_Value(Z)))) {
157bdd1243dSDimitry Andric     bool PropagateNSW = HasNSW && cast<ShlOperator>(Y)->hasNoSignedWrap();
158bdd1243dSDimitry Andric     return Builder.CreateShl(X, Z, Mul.getName(), HasNUW, PropagateNSW);
159bdd1243dSDimitry Andric   }
160bdd1243dSDimitry Andric 
161bdd1243dSDimitry Andric   // Similar to above, but an increment of the shifted value becomes an add:
162bdd1243dSDimitry Andric   // X * ((1 << Z) + 1) --> (X * (1 << Z)) + X --> (X << Z) + X
163bdd1243dSDimitry Andric   // This increases uses of X, so it may require a freeze, but that is still
164bdd1243dSDimitry Andric   // expected to be an improvement because it removes the multiply.
165bdd1243dSDimitry Andric   BinaryOperator *Shift;
166bdd1243dSDimitry Andric   if (match(Y, m_OneUse(m_Add(m_BinOp(Shift), m_One()))) &&
167bdd1243dSDimitry Andric       match(Shift, m_OneUse(m_Shl(m_One(), m_Value(Z))))) {
168bdd1243dSDimitry Andric     bool PropagateNSW = HasNSW && Shift->hasNoSignedWrap();
169*0fca6ea1SDimitry Andric     Value *FrX = X;
170*0fca6ea1SDimitry Andric     if (!isGuaranteedNotToBeUndef(X))
171*0fca6ea1SDimitry Andric       FrX = Builder.CreateFreeze(X, X->getName() + ".fr");
172bdd1243dSDimitry Andric     Value *Shl = Builder.CreateShl(FrX, Z, "mulshl", HasNUW, PropagateNSW);
173bdd1243dSDimitry Andric     return Builder.CreateAdd(Shl, FrX, Mul.getName(), HasNUW, PropagateNSW);
174bdd1243dSDimitry Andric   }
175bdd1243dSDimitry Andric 
176bdd1243dSDimitry Andric   // Similar to above, but a decrement of the shifted value is disguised as
177bdd1243dSDimitry Andric   // 'not' and becomes a sub:
178bdd1243dSDimitry Andric   // X * (~(-1 << Z)) --> X * ((1 << Z) - 1) --> (X << Z) - X
179bdd1243dSDimitry Andric   // This increases uses of X, so it may require a freeze, but that is still
180bdd1243dSDimitry Andric   // expected to be an improvement because it removes the multiply.
181bdd1243dSDimitry Andric   if (match(Y, m_OneUse(m_Not(m_OneUse(m_Shl(m_AllOnes(), m_Value(Z))))))) {
182*0fca6ea1SDimitry Andric     Value *FrX = X;
183*0fca6ea1SDimitry Andric     if (!isGuaranteedNotToBeUndef(X))
184*0fca6ea1SDimitry Andric       FrX = Builder.CreateFreeze(X, X->getName() + ".fr");
185bdd1243dSDimitry Andric     Value *Shl = Builder.CreateShl(FrX, Z, "mulshl");
186bdd1243dSDimitry Andric     return Builder.CreateSub(Shl, FrX, Mul.getName());
187bdd1243dSDimitry Andric   }
188bdd1243dSDimitry Andric 
189bdd1243dSDimitry Andric   return nullptr;
190bdd1243dSDimitry Andric }
191bdd1243dSDimitry Andric 
19206c3fb27SDimitry Andric static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
19306c3fb27SDimitry Andric                        bool AssumeNonZero, bool DoFold);
19406c3fb27SDimitry Andric 
visitMul(BinaryOperator & I)195e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
196bdd1243dSDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
197bdd1243dSDimitry Andric   if (Value *V =
198bdd1243dSDimitry Andric           simplifyMulInst(Op0, Op1, I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
1990b57cec5SDimitry Andric                           SQ.getWithInstruction(&I)))
2000b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   if (SimplifyAssociativeOrCommutative(I))
2030b57cec5SDimitry Andric     return &I;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
2060b57cec5SDimitry Andric     return X;
2070b57cec5SDimitry Andric 
20804eeddc0SDimitry Andric   if (Instruction *Phi = foldBinopWithPhiOperands(I))
20904eeddc0SDimitry Andric     return Phi;
21004eeddc0SDimitry Andric 
211bdd1243dSDimitry Andric   if (Value *V = foldUsingDistributiveLaws(I))
2120b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
2130b57cec5SDimitry Andric 
214bdd1243dSDimitry Andric   Type *Ty = I.getType();
215bdd1243dSDimitry Andric   const unsigned BitWidth = Ty->getScalarSizeInBits();
216bdd1243dSDimitry Andric   const bool HasNSW = I.hasNoSignedWrap();
217bdd1243dSDimitry Andric   const bool HasNUW = I.hasNoUnsignedWrap();
218e8d8bef9SDimitry Andric 
219bdd1243dSDimitry Andric   // X * -1 --> 0 - X
2200b57cec5SDimitry Andric   if (match(Op1, m_AllOnes())) {
221bdd1243dSDimitry Andric     return HasNSW ? BinaryOperator::CreateNSWNeg(Op0)
222bdd1243dSDimitry Andric                   : BinaryOperator::CreateNeg(Op0);
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   // Also allow combining multiply instructions on vectors.
2260b57cec5SDimitry Andric   {
2270b57cec5SDimitry Andric     Value *NewOp;
2280b57cec5SDimitry Andric     Constant *C1, *C2;
2290b57cec5SDimitry Andric     const APInt *IVal;
230*0fca6ea1SDimitry Andric     if (match(&I, m_Mul(m_Shl(m_Value(NewOp), m_ImmConstant(C2)),
231*0fca6ea1SDimitry Andric                         m_ImmConstant(C1))) &&
2320b57cec5SDimitry Andric         match(C1, m_APInt(IVal))) {
2330b57cec5SDimitry Andric       // ((X << C2)*C1) == (X * (C1 << C2))
234*0fca6ea1SDimitry Andric       Constant *Shl =
235*0fca6ea1SDimitry Andric           ConstantFoldBinaryOpOperands(Instruction::Shl, C1, C2, DL);
236*0fca6ea1SDimitry Andric       assert(Shl && "Constant folding of immediate constants failed");
2370b57cec5SDimitry Andric       BinaryOperator *Mul = cast<BinaryOperator>(I.getOperand(0));
2380b57cec5SDimitry Andric       BinaryOperator *BO = BinaryOperator::CreateMul(NewOp, Shl);
239bdd1243dSDimitry Andric       if (HasNUW && Mul->hasNoUnsignedWrap())
2400b57cec5SDimitry Andric         BO->setHasNoUnsignedWrap();
241bdd1243dSDimitry Andric       if (HasNSW && Mul->hasNoSignedWrap() && Shl->isNotMinSignedValue())
2420b57cec5SDimitry Andric         BO->setHasNoSignedWrap();
2430b57cec5SDimitry Andric       return BO;
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric     if (match(&I, m_Mul(m_Value(NewOp), m_Constant(C1)))) {
2470b57cec5SDimitry Andric       // Replace X*(2^C) with X << C, where C is either a scalar or a vector.
248e8d8bef9SDimitry Andric       if (Constant *NewCst = ConstantExpr::getExactLogBase2(C1)) {
2490b57cec5SDimitry Andric         BinaryOperator *Shl = BinaryOperator::CreateShl(NewOp, NewCst);
2500b57cec5SDimitry Andric 
251bdd1243dSDimitry Andric         if (HasNUW)
2520b57cec5SDimitry Andric           Shl->setHasNoUnsignedWrap();
253bdd1243dSDimitry Andric         if (HasNSW) {
2540b57cec5SDimitry Andric           const APInt *V;
2550b57cec5SDimitry Andric           if (match(NewCst, m_APInt(V)) && *V != V->getBitWidth() - 1)
2560b57cec5SDimitry Andric             Shl->setHasNoSignedWrap();
2570b57cec5SDimitry Andric         }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric         return Shl;
2600b57cec5SDimitry Andric       }
2610b57cec5SDimitry Andric     }
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
264e8d8bef9SDimitry Andric   if (Op0->hasOneUse() && match(Op1, m_NegatedPower2())) {
265e8d8bef9SDimitry Andric     // Interpret  X * (-1<<C)  as  (-X) * (1<<C)  and try to sink the negation.
266e8d8bef9SDimitry Andric     // The "* (1<<C)" thus becomes a potential shifting opportunity.
2675f757f3fSDimitry Andric     if (Value *NegOp0 =
2685f757f3fSDimitry Andric             Negator::Negate(/*IsNegation*/ true, HasNSW, Op0, *this)) {
2695f757f3fSDimitry Andric       auto *Op1C = cast<Constant>(Op1);
2705f757f3fSDimitry Andric       return replaceInstUsesWith(
2715f757f3fSDimitry Andric           I, Builder.CreateMul(NegOp0, ConstantExpr::getNeg(Op1C), "",
2725f757f3fSDimitry Andric                                /* HasNUW */ false,
2735f757f3fSDimitry Andric                                HasNSW && Op1C->isNotMinSignedValue()));
2745f757f3fSDimitry Andric     }
275bdd1243dSDimitry Andric 
276bdd1243dSDimitry Andric     // Try to convert multiply of extended operand to narrow negate and shift
277bdd1243dSDimitry Andric     // for better analysis.
278bdd1243dSDimitry Andric     // This is valid if the shift amount (trailing zeros in the multiplier
279bdd1243dSDimitry Andric     // constant) clears more high bits than the bitwidth difference between
280bdd1243dSDimitry Andric     // source and destination types:
281bdd1243dSDimitry Andric     // ({z/s}ext X) * (-1<<C) --> (zext (-X)) << C
282bdd1243dSDimitry Andric     const APInt *NegPow2C;
283bdd1243dSDimitry Andric     Value *X;
284bdd1243dSDimitry Andric     if (match(Op0, m_ZExtOrSExt(m_Value(X))) &&
285*0fca6ea1SDimitry Andric         match(Op1, m_APIntAllowPoison(NegPow2C))) {
286bdd1243dSDimitry Andric       unsigned SrcWidth = X->getType()->getScalarSizeInBits();
28706c3fb27SDimitry Andric       unsigned ShiftAmt = NegPow2C->countr_zero();
288bdd1243dSDimitry Andric       if (ShiftAmt >= BitWidth - SrcWidth) {
289bdd1243dSDimitry Andric         Value *N = Builder.CreateNeg(X, X->getName() + ".neg");
290bdd1243dSDimitry Andric         Value *Z = Builder.CreateZExt(N, Ty, N->getName() + ".z");
291bdd1243dSDimitry Andric         return BinaryOperator::CreateShl(Z, ConstantInt::get(Ty, ShiftAmt));
292bdd1243dSDimitry Andric       }
293bdd1243dSDimitry Andric     }
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   if (Instruction *FoldedMul = foldBinOpIntoSelectOrPhi(I))
2970b57cec5SDimitry Andric     return FoldedMul;
2980b57cec5SDimitry Andric 
2998bcb0991SDimitry Andric   if (Value *FoldedMul = foldMulSelectToNegate(I, Builder))
3008bcb0991SDimitry Andric     return replaceInstUsesWith(I, FoldedMul);
3018bcb0991SDimitry Andric 
3020b57cec5SDimitry Andric   // Simplify mul instructions with a constant RHS.
303bdd1243dSDimitry Andric   Constant *MulC;
304bdd1243dSDimitry Andric   if (match(Op1, m_ImmConstant(MulC))) {
305bdd1243dSDimitry Andric     // Canonicalize (X+C1)*MulC -> X*MulC+C1*MulC.
306bdd1243dSDimitry Andric     // Canonicalize (X|C1)*MulC -> X*MulC+C1*MulC.
3070b57cec5SDimitry Andric     Value *X;
3080b57cec5SDimitry Andric     Constant *C1;
3095f757f3fSDimitry Andric     if (match(Op0, m_OneUse(m_AddLike(m_Value(X), m_ImmConstant(C1))))) {
310bdd1243dSDimitry Andric       // C1*MulC simplifies to a tidier constant.
311bdd1243dSDimitry Andric       Value *NewC = Builder.CreateMul(C1, MulC);
312bdd1243dSDimitry Andric       auto *BOp0 = cast<BinaryOperator>(Op0);
313bdd1243dSDimitry Andric       bool Op0NUW =
314bdd1243dSDimitry Andric           (BOp0->getOpcode() == Instruction::Or || BOp0->hasNoUnsignedWrap());
315bdd1243dSDimitry Andric       Value *NewMul = Builder.CreateMul(X, MulC);
316bdd1243dSDimitry Andric       auto *BO = BinaryOperator::CreateAdd(NewMul, NewC);
317bdd1243dSDimitry Andric       if (HasNUW && Op0NUW) {
318bdd1243dSDimitry Andric         // If NewMulBO is constant we also can set BO to nuw.
319bdd1243dSDimitry Andric         if (auto *NewMulBO = dyn_cast<BinaryOperator>(NewMul))
320bdd1243dSDimitry Andric           NewMulBO->setHasNoUnsignedWrap();
321bdd1243dSDimitry Andric         BO->setHasNoUnsignedWrap();
322bdd1243dSDimitry Andric       }
323bdd1243dSDimitry Andric       return BO;
3240b57cec5SDimitry Andric     }
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric 
3275ffd83dbSDimitry Andric   // abs(X) * abs(X) -> X * X
328*0fca6ea1SDimitry Andric   Value *X;
329*0fca6ea1SDimitry Andric   if (Op0 == Op1 && match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
3305ffd83dbSDimitry Andric     return BinaryOperator::CreateMul(X, X);
331e8d8bef9SDimitry Andric 
3327a6dacacSDimitry Andric   {
333*0fca6ea1SDimitry Andric     Value *Y;
3347a6dacacSDimitry Andric     // abs(X) * abs(Y) -> abs(X * Y)
3357a6dacacSDimitry Andric     if (I.hasNoSignedWrap() &&
3367a6dacacSDimitry Andric         match(Op0,
3377a6dacacSDimitry Andric               m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(X), m_One()))) &&
3387a6dacacSDimitry Andric         match(Op1, m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(Y), m_One()))))
3397a6dacacSDimitry Andric       return replaceInstUsesWith(
3407a6dacacSDimitry Andric           I, Builder.CreateBinaryIntrinsic(Intrinsic::abs,
3417a6dacacSDimitry Andric                                            Builder.CreateNSWMul(X, Y),
3427a6dacacSDimitry Andric                                            Builder.getTrue()));
3437a6dacacSDimitry Andric   }
3447a6dacacSDimitry Andric 
3450b57cec5SDimitry Andric   // -X * C --> X * -C
346*0fca6ea1SDimitry Andric   Value *Y;
3470b57cec5SDimitry Andric   Constant *Op1C;
3480b57cec5SDimitry Andric   if (match(Op0, m_Neg(m_Value(X))) && match(Op1, m_Constant(Op1C)))
3490b57cec5SDimitry Andric     return BinaryOperator::CreateMul(X, ConstantExpr::getNeg(Op1C));
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric   // -X * -Y --> X * Y
3520b57cec5SDimitry Andric   if (match(Op0, m_Neg(m_Value(X))) && match(Op1, m_Neg(m_Value(Y)))) {
3530b57cec5SDimitry Andric     auto *NewMul = BinaryOperator::CreateMul(X, Y);
354bdd1243dSDimitry Andric     if (HasNSW && cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap() &&
3550b57cec5SDimitry Andric         cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap())
3560b57cec5SDimitry Andric       NewMul->setHasNoSignedWrap();
3570b57cec5SDimitry Andric     return NewMul;
3580b57cec5SDimitry Andric   }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   // -X * Y --> -(X * Y)
3610b57cec5SDimitry Andric   // X * -Y --> -(X * Y)
3620b57cec5SDimitry Andric   if (match(&I, m_c_Mul(m_OneUse(m_Neg(m_Value(X))), m_Value(Y))))
3630b57cec5SDimitry Andric     return BinaryOperator::CreateNeg(Builder.CreateMul(X, Y));
3640b57cec5SDimitry Andric 
365cb14a3feSDimitry Andric   // (-X * Y) * -X --> (X * Y) * X
366cb14a3feSDimitry Andric   // (-X << Y) * -X --> (X << Y) * X
367cb14a3feSDimitry Andric   if (match(Op1, m_Neg(m_Value(X)))) {
368cb14a3feSDimitry Andric     if (Value *NegOp0 = Negator::Negate(false, /*IsNSW*/ false, Op0, *this))
369cb14a3feSDimitry Andric       return BinaryOperator::CreateMul(NegOp0, X);
370cb14a3feSDimitry Andric   }
371cb14a3feSDimitry Andric 
372*0fca6ea1SDimitry Andric   if (Op0->hasOneUse()) {
373*0fca6ea1SDimitry Andric     // (mul (div exact X, C0), C1)
374*0fca6ea1SDimitry Andric     //    -> (div exact X, C0 / C1)
375*0fca6ea1SDimitry Andric     // iff C0 % C1 == 0 and X / (C0 / C1) doesn't create UB.
376*0fca6ea1SDimitry Andric     const APInt *C1;
377*0fca6ea1SDimitry Andric     auto UDivCheck = [&C1](const APInt &C) { return C.urem(*C1).isZero(); };
378*0fca6ea1SDimitry Andric     auto SDivCheck = [&C1](const APInt &C) {
379*0fca6ea1SDimitry Andric       APInt Quot, Rem;
380*0fca6ea1SDimitry Andric       APInt::sdivrem(C, *C1, Quot, Rem);
381*0fca6ea1SDimitry Andric       return Rem.isZero() && !Quot.isAllOnes();
382*0fca6ea1SDimitry Andric     };
383*0fca6ea1SDimitry Andric     if (match(Op1, m_APInt(C1)) &&
384*0fca6ea1SDimitry Andric         (match(Op0, m_Exact(m_UDiv(m_Value(X), m_CheckedInt(UDivCheck)))) ||
385*0fca6ea1SDimitry Andric          match(Op0, m_Exact(m_SDiv(m_Value(X), m_CheckedInt(SDivCheck)))))) {
386*0fca6ea1SDimitry Andric       auto BOpc = cast<BinaryOperator>(Op0)->getOpcode();
387*0fca6ea1SDimitry Andric       return BinaryOperator::CreateExact(
388*0fca6ea1SDimitry Andric           BOpc, X,
389*0fca6ea1SDimitry Andric           Builder.CreateBinOp(BOpc, cast<BinaryOperator>(Op0)->getOperand(1),
390*0fca6ea1SDimitry Andric                               Op1));
391*0fca6ea1SDimitry Andric     }
392*0fca6ea1SDimitry Andric   }
393*0fca6ea1SDimitry Andric 
3940b57cec5SDimitry Andric   // (X / Y) *  Y = X - (X % Y)
3950b57cec5SDimitry Andric   // (X / Y) * -Y = (X % Y) - X
3960b57cec5SDimitry Andric   {
3970b57cec5SDimitry Andric     Value *Y = Op1;
3980b57cec5SDimitry Andric     BinaryOperator *Div = dyn_cast<BinaryOperator>(Op0);
3990b57cec5SDimitry Andric     if (!Div || (Div->getOpcode() != Instruction::UDiv &&
4000b57cec5SDimitry Andric                  Div->getOpcode() != Instruction::SDiv)) {
4010b57cec5SDimitry Andric       Y = Op0;
4020b57cec5SDimitry Andric       Div = dyn_cast<BinaryOperator>(Op1);
4030b57cec5SDimitry Andric     }
4040b57cec5SDimitry Andric     Value *Neg = dyn_castNegVal(Y);
4050b57cec5SDimitry Andric     if (Div && Div->hasOneUse() &&
4060b57cec5SDimitry Andric         (Div->getOperand(1) == Y || Div->getOperand(1) == Neg) &&
4070b57cec5SDimitry Andric         (Div->getOpcode() == Instruction::UDiv ||
4080b57cec5SDimitry Andric          Div->getOpcode() == Instruction::SDiv)) {
4090b57cec5SDimitry Andric       Value *X = Div->getOperand(0), *DivOp1 = Div->getOperand(1);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric       // If the division is exact, X % Y is zero, so we end up with X or -X.
4120b57cec5SDimitry Andric       if (Div->isExact()) {
4130b57cec5SDimitry Andric         if (DivOp1 == Y)
4140b57cec5SDimitry Andric           return replaceInstUsesWith(I, X);
4150b57cec5SDimitry Andric         return BinaryOperator::CreateNeg(X);
4160b57cec5SDimitry Andric       }
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric       auto RemOpc = Div->getOpcode() == Instruction::UDiv ? Instruction::URem
4190b57cec5SDimitry Andric                                                           : Instruction::SRem;
42081ad6265SDimitry Andric       // X must be frozen because we are increasing its number of uses.
421*0fca6ea1SDimitry Andric       Value *XFreeze = X;
422*0fca6ea1SDimitry Andric       if (!isGuaranteedNotToBeUndef(X))
423*0fca6ea1SDimitry Andric         XFreeze = Builder.CreateFreeze(X, X->getName() + ".fr");
42481ad6265SDimitry Andric       Value *Rem = Builder.CreateBinOp(RemOpc, XFreeze, DivOp1);
4250b57cec5SDimitry Andric       if (DivOp1 == Y)
42681ad6265SDimitry Andric         return BinaryOperator::CreateSub(XFreeze, Rem);
42781ad6265SDimitry Andric       return BinaryOperator::CreateSub(Rem, XFreeze);
4280b57cec5SDimitry Andric     }
4290b57cec5SDimitry Andric   }
4300b57cec5SDimitry Andric 
43181ad6265SDimitry Andric   // Fold the following two scenarios:
43281ad6265SDimitry Andric   //   1) i1 mul -> i1 and.
43381ad6265SDimitry Andric   //   2) X * Y --> X & Y, iff X, Y can be only {0,1}.
43481ad6265SDimitry Andric   // Note: We could use known bits to generalize this and related patterns with
43581ad6265SDimitry Andric   // shifts/truncs
43681ad6265SDimitry Andric   if (Ty->isIntOrIntVectorTy(1) ||
43781ad6265SDimitry Andric       (match(Op0, m_And(m_Value(), m_One())) &&
43881ad6265SDimitry Andric        match(Op1, m_And(m_Value(), m_One()))))
4390b57cec5SDimitry Andric     return BinaryOperator::CreateAnd(Op0, Op1);
4400b57cec5SDimitry Andric 
441bdd1243dSDimitry Andric   if (Value *R = foldMulShl1(I, /* CommuteOperands */ false, Builder))
442bdd1243dSDimitry Andric     return replaceInstUsesWith(I, R);
443bdd1243dSDimitry Andric   if (Value *R = foldMulShl1(I, /* CommuteOperands */ true, Builder))
444bdd1243dSDimitry Andric     return replaceInstUsesWith(I, R);
4450b57cec5SDimitry Andric 
4465ffd83dbSDimitry Andric   // (zext bool X) * (zext bool Y) --> zext (and X, Y)
4475ffd83dbSDimitry Andric   // (sext bool X) * (sext bool Y) --> zext (and X, Y)
4485ffd83dbSDimitry Andric   // Note: -1 * -1 == 1 * 1 == 1 (if the extends match, the result is the same)
4495ffd83dbSDimitry Andric   if (((match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) ||
4505ffd83dbSDimitry Andric        (match(Op0, m_SExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) &&
4515ffd83dbSDimitry Andric       X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() &&
452fe6060f1SDimitry Andric       (Op0->hasOneUse() || Op1->hasOneUse() || X == Y)) {
4535ffd83dbSDimitry Andric     Value *And = Builder.CreateAnd(X, Y, "mulbool");
45481ad6265SDimitry Andric     return CastInst::Create(Instruction::ZExt, And, Ty);
4555ffd83dbSDimitry Andric   }
4565ffd83dbSDimitry Andric   // (sext bool X) * (zext bool Y) --> sext (and X, Y)
4575ffd83dbSDimitry Andric   // (zext bool X) * (sext bool Y) --> sext (and X, Y)
4585ffd83dbSDimitry Andric   // Note: -1 * 1 == 1 * -1  == -1
4595ffd83dbSDimitry Andric   if (((match(Op0, m_SExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) ||
4605ffd83dbSDimitry Andric        (match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) &&
4615ffd83dbSDimitry Andric       X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() &&
4625ffd83dbSDimitry Andric       (Op0->hasOneUse() || Op1->hasOneUse())) {
4635ffd83dbSDimitry Andric     Value *And = Builder.CreateAnd(X, Y, "mulbool");
46481ad6265SDimitry Andric     return CastInst::Create(Instruction::SExt, And, Ty);
4655ffd83dbSDimitry Andric   }
4665ffd83dbSDimitry Andric 
46704eeddc0SDimitry Andric   // (zext bool X) * Y --> X ? Y : 0
46804eeddc0SDimitry Andric   // Y * (zext bool X) --> X ? Y : 0
4690b57cec5SDimitry Andric   if (match(Op0, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
47081ad6265SDimitry Andric     return SelectInst::Create(X, Op1, ConstantInt::getNullValue(Ty));
4710b57cec5SDimitry Andric   if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
47281ad6265SDimitry Andric     return SelectInst::Create(X, Op0, ConstantInt::getNullValue(Ty));
4730b57cec5SDimitry Andric 
474*0fca6ea1SDimitry Andric   // mul (sext X), Y -> select X, -Y, 0
475*0fca6ea1SDimitry Andric   // mul Y, (sext X) -> select X, -Y, 0
476*0fca6ea1SDimitry Andric   if (match(&I, m_c_Mul(m_OneUse(m_SExt(m_Value(X))), m_Value(Y))) &&
477*0fca6ea1SDimitry Andric       X->getType()->isIntOrIntVectorTy(1))
478*0fca6ea1SDimitry Andric     return SelectInst::Create(X, Builder.CreateNeg(Y, "", I.hasNoSignedWrap()),
479*0fca6ea1SDimitry Andric                               ConstantInt::getNullValue(Op0->getType()));
480*0fca6ea1SDimitry Andric 
48104eeddc0SDimitry Andric   Constant *ImmC;
48281ad6265SDimitry Andric   if (match(Op1, m_ImmConstant(ImmC))) {
48381ad6265SDimitry Andric     // (sext bool X) * C --> X ? -C : 0
48481ad6265SDimitry Andric     if (match(Op0, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
48504eeddc0SDimitry Andric       Constant *NegC = ConstantExpr::getNeg(ImmC);
48681ad6265SDimitry Andric       return SelectInst::Create(X, NegC, ConstantInt::getNullValue(Ty));
48704eeddc0SDimitry Andric     }
48804eeddc0SDimitry Andric 
48981ad6265SDimitry Andric     // (ashr i32 X, 31) * C --> (X < 0) ? -C : 0
49081ad6265SDimitry Andric     const APInt *C;
49181ad6265SDimitry Andric     if (match(Op0, m_OneUse(m_AShr(m_Value(X), m_APInt(C)))) &&
49281ad6265SDimitry Andric         *C == C->getBitWidth() - 1) {
49381ad6265SDimitry Andric       Constant *NegC = ConstantExpr::getNeg(ImmC);
49481ad6265SDimitry Andric       Value *IsNeg = Builder.CreateIsNeg(X, "isneg");
49581ad6265SDimitry Andric       return SelectInst::Create(IsNeg, NegC, ConstantInt::getNullValue(Ty));
49681ad6265SDimitry Andric     }
49781ad6265SDimitry Andric   }
49881ad6265SDimitry Andric 
49981ad6265SDimitry Andric   // (lshr X, 31) * Y --> (X < 0) ? Y : 0
5000b57cec5SDimitry Andric   // TODO: We are not checking one-use because the elimination of the multiply
5010b57cec5SDimitry Andric   //       is better for analysis?
5020b57cec5SDimitry Andric   const APInt *C;
50381ad6265SDimitry Andric   if (match(&I, m_c_BinOp(m_LShr(m_Value(X), m_APInt(C)), m_Value(Y))) &&
50481ad6265SDimitry Andric       *C == C->getBitWidth() - 1) {
50581ad6265SDimitry Andric     Value *IsNeg = Builder.CreateIsNeg(X, "isneg");
50681ad6265SDimitry Andric     return SelectInst::Create(IsNeg, Y, ConstantInt::getNullValue(Ty));
50781ad6265SDimitry Andric   }
50881ad6265SDimitry Andric 
50981ad6265SDimitry Andric   // (and X, 1) * Y --> (trunc X) ? Y : 0
51081ad6265SDimitry Andric   if (match(&I, m_c_BinOp(m_OneUse(m_And(m_Value(X), m_One())), m_Value(Y)))) {
51181ad6265SDimitry Andric     Value *Tr = Builder.CreateTrunc(X, CmpInst::makeCmpResultType(Ty));
51281ad6265SDimitry Andric     return SelectInst::Create(Tr, Y, ConstantInt::getNullValue(Ty));
51381ad6265SDimitry Andric   }
5140b57cec5SDimitry Andric 
515e8d8bef9SDimitry Andric   // ((ashr X, 31) | 1) * X --> abs(X)
516e8d8bef9SDimitry Andric   // X * ((ashr X, 31) | 1) --> abs(X)
517e8d8bef9SDimitry Andric   if (match(&I, m_c_BinOp(m_Or(m_AShr(m_Value(X),
518*0fca6ea1SDimitry Andric                                       m_SpecificIntAllowPoison(BitWidth - 1)),
519e8d8bef9SDimitry Andric                                m_One()),
520e8d8bef9SDimitry Andric                           m_Deferred(X)))) {
521e8d8bef9SDimitry Andric     Value *Abs = Builder.CreateBinaryIntrinsic(
522bdd1243dSDimitry Andric         Intrinsic::abs, X, ConstantInt::getBool(I.getContext(), HasNSW));
523e8d8bef9SDimitry Andric     Abs->takeName(&I);
524e8d8bef9SDimitry Andric     return replaceInstUsesWith(I, Abs);
525e8d8bef9SDimitry Andric   }
526e8d8bef9SDimitry Andric 
5270b57cec5SDimitry Andric   if (Instruction *Ext = narrowMathIfNoOverflow(I))
5280b57cec5SDimitry Andric     return Ext;
5290b57cec5SDimitry Andric 
53006c3fb27SDimitry Andric   if (Instruction *Res = foldBinOpOfSelectAndCastOfSelectCondition(I))
53106c3fb27SDimitry Andric     return Res;
53206c3fb27SDimitry Andric 
53306c3fb27SDimitry Andric   // (mul Op0 Op1):
53406c3fb27SDimitry Andric   //    if Log2(Op0) folds away ->
53506c3fb27SDimitry Andric   //        (shl Op1, Log2(Op0))
53606c3fb27SDimitry Andric   //    if Log2(Op1) folds away ->
53706c3fb27SDimitry Andric   //        (shl Op0, Log2(Op1))
53806c3fb27SDimitry Andric   if (takeLog2(Builder, Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
53906c3fb27SDimitry Andric                /*DoFold*/ false)) {
54006c3fb27SDimitry Andric     Value *Res = takeLog2(Builder, Op0, /*Depth*/ 0, /*AssumeNonZero*/ false,
54106c3fb27SDimitry Andric                           /*DoFold*/ true);
54206c3fb27SDimitry Andric     BinaryOperator *Shl = BinaryOperator::CreateShl(Op1, Res);
54306c3fb27SDimitry Andric     // We can only propegate nuw flag.
54406c3fb27SDimitry Andric     Shl->setHasNoUnsignedWrap(HasNUW);
54506c3fb27SDimitry Andric     return Shl;
54606c3fb27SDimitry Andric   }
54706c3fb27SDimitry Andric   if (takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
54806c3fb27SDimitry Andric                /*DoFold*/ false)) {
54906c3fb27SDimitry Andric     Value *Res = takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ false,
55006c3fb27SDimitry Andric                           /*DoFold*/ true);
55106c3fb27SDimitry Andric     BinaryOperator *Shl = BinaryOperator::CreateShl(Op0, Res);
55206c3fb27SDimitry Andric     // We can only propegate nuw flag.
55306c3fb27SDimitry Andric     Shl->setHasNoUnsignedWrap(HasNUW);
55406c3fb27SDimitry Andric     return Shl;
55506c3fb27SDimitry Andric   }
55606c3fb27SDimitry Andric 
5570b57cec5SDimitry Andric   bool Changed = false;
558bdd1243dSDimitry Andric   if (!HasNSW && willNotOverflowSignedMul(Op0, Op1, I)) {
5590b57cec5SDimitry Andric     Changed = true;
5600b57cec5SDimitry Andric     I.setHasNoSignedWrap(true);
5610b57cec5SDimitry Andric   }
5620b57cec5SDimitry Andric 
563*0fca6ea1SDimitry Andric   if (!HasNUW && willNotOverflowUnsignedMul(Op0, Op1, I, I.hasNoSignedWrap())) {
5640b57cec5SDimitry Andric     Changed = true;
5650b57cec5SDimitry Andric     I.setHasNoUnsignedWrap(true);
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   return Changed ? &I : nullptr;
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
foldFPSignBitOps(BinaryOperator & I)571e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) {
5725ffd83dbSDimitry Andric   BinaryOperator::BinaryOps Opcode = I.getOpcode();
5735ffd83dbSDimitry Andric   assert((Opcode == Instruction::FMul || Opcode == Instruction::FDiv) &&
5745ffd83dbSDimitry Andric          "Expected fmul or fdiv");
5755ffd83dbSDimitry Andric 
5765ffd83dbSDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
5775ffd83dbSDimitry Andric   Value *X, *Y;
5785ffd83dbSDimitry Andric 
5795ffd83dbSDimitry Andric   // -X * -Y --> X * Y
5805ffd83dbSDimitry Andric   // -X / -Y --> X / Y
5815ffd83dbSDimitry Andric   if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_FNeg(m_Value(Y))))
5825ffd83dbSDimitry Andric     return BinaryOperator::CreateWithCopiedFlags(Opcode, X, Y, &I);
5835ffd83dbSDimitry Andric 
5845ffd83dbSDimitry Andric   // fabs(X) * fabs(X) -> X * X
5855ffd83dbSDimitry Andric   // fabs(X) / fabs(X) -> X / X
586e8d8bef9SDimitry Andric   if (Op0 == Op1 && match(Op0, m_FAbs(m_Value(X))))
5875ffd83dbSDimitry Andric     return BinaryOperator::CreateWithCopiedFlags(Opcode, X, X, &I);
5885ffd83dbSDimitry Andric 
5895ffd83dbSDimitry Andric   // fabs(X) * fabs(Y) --> fabs(X * Y)
5905ffd83dbSDimitry Andric   // fabs(X) / fabs(Y) --> fabs(X / Y)
591e8d8bef9SDimitry Andric   if (match(Op0, m_FAbs(m_Value(X))) && match(Op1, m_FAbs(m_Value(Y))) &&
5925ffd83dbSDimitry Andric       (Op0->hasOneUse() || Op1->hasOneUse())) {
5935ffd83dbSDimitry Andric     IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
5945ffd83dbSDimitry Andric     Builder.setFastMathFlags(I.getFastMathFlags());
5955ffd83dbSDimitry Andric     Value *XY = Builder.CreateBinOp(Opcode, X, Y);
5965ffd83dbSDimitry Andric     Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, XY);
5975ffd83dbSDimitry Andric     Fabs->takeName(&I);
5985ffd83dbSDimitry Andric     return replaceInstUsesWith(I, Fabs);
5995ffd83dbSDimitry Andric   }
6005ffd83dbSDimitry Andric 
6015ffd83dbSDimitry Andric   return nullptr;
6025ffd83dbSDimitry Andric }
6035ffd83dbSDimitry Andric 
foldPowiReassoc(BinaryOperator & I)604*0fca6ea1SDimitry Andric Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) {
605*0fca6ea1SDimitry Andric   auto createPowiExpr = [](BinaryOperator &I, InstCombinerImpl &IC, Value *X,
606*0fca6ea1SDimitry Andric                            Value *Y, Value *Z) {
607*0fca6ea1SDimitry Andric     InstCombiner::BuilderTy &Builder = IC.Builder;
608*0fca6ea1SDimitry Andric     Value *YZ = Builder.CreateAdd(Y, Z);
609*0fca6ea1SDimitry Andric     Instruction *NewPow = Builder.CreateIntrinsic(
610*0fca6ea1SDimitry Andric         Intrinsic::powi, {X->getType(), YZ->getType()}, {X, YZ}, &I);
611*0fca6ea1SDimitry Andric 
612*0fca6ea1SDimitry Andric     return NewPow;
613*0fca6ea1SDimitry Andric   };
614*0fca6ea1SDimitry Andric 
615*0fca6ea1SDimitry Andric   Value *X, *Y, *Z;
616*0fca6ea1SDimitry Andric   unsigned Opcode = I.getOpcode();
617*0fca6ea1SDimitry Andric   assert((Opcode == Instruction::FMul || Opcode == Instruction::FDiv) &&
618*0fca6ea1SDimitry Andric          "Unexpected opcode");
619*0fca6ea1SDimitry Andric 
620*0fca6ea1SDimitry Andric   // powi(X, Y) * X --> powi(X, Y+1)
621*0fca6ea1SDimitry Andric   // X * powi(X, Y) --> powi(X, Y+1)
622*0fca6ea1SDimitry Andric   if (match(&I, m_c_FMul(m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(
623*0fca6ea1SDimitry Andric                              m_Value(X), m_Value(Y)))),
624*0fca6ea1SDimitry Andric                          m_Deferred(X)))) {
625*0fca6ea1SDimitry Andric     Constant *One = ConstantInt::get(Y->getType(), 1);
626*0fca6ea1SDimitry Andric     if (willNotOverflowSignedAdd(Y, One, I)) {
627*0fca6ea1SDimitry Andric       Instruction *NewPow = createPowiExpr(I, *this, X, Y, One);
628*0fca6ea1SDimitry Andric       return replaceInstUsesWith(I, NewPow);
629*0fca6ea1SDimitry Andric     }
630*0fca6ea1SDimitry Andric   }
631*0fca6ea1SDimitry Andric 
632*0fca6ea1SDimitry Andric   // powi(x, y) * powi(x, z) -> powi(x, y + z)
633*0fca6ea1SDimitry Andric   Value *Op0 = I.getOperand(0);
634*0fca6ea1SDimitry Andric   Value *Op1 = I.getOperand(1);
635*0fca6ea1SDimitry Andric   if (Opcode == Instruction::FMul && I.isOnlyUserOfAnyOperand() &&
636*0fca6ea1SDimitry Andric       match(Op0, m_AllowReassoc(
637*0fca6ea1SDimitry Andric                      m_Intrinsic<Intrinsic::powi>(m_Value(X), m_Value(Y)))) &&
638*0fca6ea1SDimitry Andric       match(Op1, m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(m_Specific(X),
639*0fca6ea1SDimitry Andric                                                              m_Value(Z)))) &&
640*0fca6ea1SDimitry Andric       Y->getType() == Z->getType()) {
641*0fca6ea1SDimitry Andric     Instruction *NewPow = createPowiExpr(I, *this, X, Y, Z);
642*0fca6ea1SDimitry Andric     return replaceInstUsesWith(I, NewPow);
643*0fca6ea1SDimitry Andric   }
644*0fca6ea1SDimitry Andric 
645*0fca6ea1SDimitry Andric   if (Opcode == Instruction::FDiv && I.hasAllowReassoc() && I.hasNoNaNs()) {
646*0fca6ea1SDimitry Andric     // powi(X, Y) / X --> powi(X, Y-1)
647*0fca6ea1SDimitry Andric     // This is legal when (Y - 1) can't wraparound, in which case reassoc and
648*0fca6ea1SDimitry Andric     // nnan are required.
649*0fca6ea1SDimitry Andric     // TODO: Multi-use may be also better off creating Powi(x,y-1)
650*0fca6ea1SDimitry Andric     if (match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(
651*0fca6ea1SDimitry Andric                        m_Specific(Op1), m_Value(Y))))) &&
652*0fca6ea1SDimitry Andric         willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) {
653*0fca6ea1SDimitry Andric       Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType());
654*0fca6ea1SDimitry Andric       Instruction *NewPow = createPowiExpr(I, *this, Op1, Y, NegOne);
655*0fca6ea1SDimitry Andric       return replaceInstUsesWith(I, NewPow);
656*0fca6ea1SDimitry Andric     }
657*0fca6ea1SDimitry Andric 
658*0fca6ea1SDimitry Andric     // powi(X, Y) / (X * Z) --> powi(X, Y-1) / Z
659*0fca6ea1SDimitry Andric     // This is legal when (Y - 1) can't wraparound, in which case reassoc and
660*0fca6ea1SDimitry Andric     // nnan are required.
661*0fca6ea1SDimitry Andric     // TODO: Multi-use may be also better off creating Powi(x,y-1)
662*0fca6ea1SDimitry Andric     if (match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(
663*0fca6ea1SDimitry Andric                        m_Value(X), m_Value(Y))))) &&
664*0fca6ea1SDimitry Andric         match(Op1, m_AllowReassoc(m_c_FMul(m_Specific(X), m_Value(Z)))) &&
665*0fca6ea1SDimitry Andric         willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) {
666*0fca6ea1SDimitry Andric       Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType());
667*0fca6ea1SDimitry Andric       auto *NewPow = createPowiExpr(I, *this, X, Y, NegOne);
668*0fca6ea1SDimitry Andric       return BinaryOperator::CreateFDivFMF(NewPow, Z, &I);
669*0fca6ea1SDimitry Andric     }
670*0fca6ea1SDimitry Andric   }
671*0fca6ea1SDimitry Andric 
672*0fca6ea1SDimitry Andric   return nullptr;
673*0fca6ea1SDimitry Andric }
674*0fca6ea1SDimitry Andric 
foldFMulReassoc(BinaryOperator & I)6755f757f3fSDimitry Andric Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) {
6765f757f3fSDimitry Andric   Value *Op0 = I.getOperand(0);
6775f757f3fSDimitry Andric   Value *Op1 = I.getOperand(1);
6785ffd83dbSDimitry Andric   Value *X, *Y;
6790b57cec5SDimitry Andric   Constant *C;
680*0fca6ea1SDimitry Andric   BinaryOperator *Op0BinOp;
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // Reassociate constant RHS with another constant to form constant
6830b57cec5SDimitry Andric   // expression.
684*0fca6ea1SDimitry Andric   if (match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP() &&
685*0fca6ea1SDimitry Andric       match(Op0, m_AllowReassoc(m_BinOp(Op0BinOp)))) {
686*0fca6ea1SDimitry Andric     // Everything in this scope folds I with Op0, intersecting their FMF.
687*0fca6ea1SDimitry Andric     FastMathFlags FMF = I.getFastMathFlags() & Op0BinOp->getFastMathFlags();
688*0fca6ea1SDimitry Andric     IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
689*0fca6ea1SDimitry Andric     Builder.setFastMathFlags(FMF);
6900b57cec5SDimitry Andric     Constant *C1;
6910b57cec5SDimitry Andric     if (match(Op0, m_OneUse(m_FDiv(m_Constant(C1), m_Value(X))))) {
6920b57cec5SDimitry Andric       // (C1 / X) * C --> (C * C1) / X
693753f127fSDimitry Andric       Constant *CC1 =
694753f127fSDimitry Andric           ConstantFoldBinaryOpOperands(Instruction::FMul, C, C1, DL);
695753f127fSDimitry Andric       if (CC1 && CC1->isNormalFP())
696*0fca6ea1SDimitry Andric         return BinaryOperator::CreateFDivFMF(CC1, X, FMF);
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric     if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
699*0fca6ea1SDimitry Andric       // FIXME: This seems like it should also be checking for arcp
7000b57cec5SDimitry Andric       // (X / C1) * C --> X * (C / C1)
701753f127fSDimitry Andric       Constant *CDivC1 =
702753f127fSDimitry Andric           ConstantFoldBinaryOpOperands(Instruction::FDiv, C, C1, DL);
703753f127fSDimitry Andric       if (CDivC1 && CDivC1->isNormalFP())
704*0fca6ea1SDimitry Andric         return BinaryOperator::CreateFMulFMF(X, CDivC1, FMF);
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric       // If the constant was a denormal, try reassociating differently.
7070b57cec5SDimitry Andric       // (X / C1) * C --> X / (C1 / C)
708753f127fSDimitry Andric       Constant *C1DivC =
709753f127fSDimitry Andric           ConstantFoldBinaryOpOperands(Instruction::FDiv, C1, C, DL);
710753f127fSDimitry Andric       if (C1DivC && Op0->hasOneUse() && C1DivC->isNormalFP())
711*0fca6ea1SDimitry Andric         return BinaryOperator::CreateFDivFMF(X, C1DivC, FMF);
7120b57cec5SDimitry Andric     }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric     // We do not need to match 'fadd C, X' and 'fsub X, C' because they are
7150b57cec5SDimitry Andric     // canonicalized to 'fadd X, C'. Distributing the multiply may allow
7160b57cec5SDimitry Andric     // further folds and (X * C) + C2 is 'fma'.
7170b57cec5SDimitry Andric     if (match(Op0, m_OneUse(m_FAdd(m_Value(X), m_Constant(C1))))) {
7180b57cec5SDimitry Andric       // (X + C1) * C --> (X * C) + (C * C1)
7195f757f3fSDimitry Andric       if (Constant *CC1 =
7205f757f3fSDimitry Andric               ConstantFoldBinaryOpOperands(Instruction::FMul, C, C1, DL)) {
721*0fca6ea1SDimitry Andric         Value *XC = Builder.CreateFMul(X, C);
722*0fca6ea1SDimitry Andric         return BinaryOperator::CreateFAddFMF(XC, CC1, FMF);
7230b57cec5SDimitry Andric       }
724753f127fSDimitry Andric     }
7250b57cec5SDimitry Andric     if (match(Op0, m_OneUse(m_FSub(m_Constant(C1), m_Value(X))))) {
7260b57cec5SDimitry Andric       // (C1 - X) * C --> (C * C1) - (X * C)
7275f757f3fSDimitry Andric       if (Constant *CC1 =
7285f757f3fSDimitry Andric               ConstantFoldBinaryOpOperands(Instruction::FMul, C, C1, DL)) {
729*0fca6ea1SDimitry Andric         Value *XC = Builder.CreateFMul(X, C);
730*0fca6ea1SDimitry Andric         return BinaryOperator::CreateFSubFMF(CC1, XC, FMF);
7310b57cec5SDimitry Andric       }
7320b57cec5SDimitry Andric     }
733753f127fSDimitry Andric   }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   Value *Z;
7365f757f3fSDimitry Andric   if (match(&I,
737*0fca6ea1SDimitry Andric             m_c_FMul(m_AllowReassoc(m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))),
738*0fca6ea1SDimitry Andric                      m_Value(Z)))) {
739*0fca6ea1SDimitry Andric     BinaryOperator *DivOp = cast<BinaryOperator>(((Z == Op0) ? Op1 : Op0));
740*0fca6ea1SDimitry Andric     FastMathFlags FMF = I.getFastMathFlags() & DivOp->getFastMathFlags();
741*0fca6ea1SDimitry Andric     if (FMF.allowReassoc()) {
7420b57cec5SDimitry Andric       // Sink division: (X / Y) * Z --> (X * Z) / Y
743*0fca6ea1SDimitry Andric       IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
744*0fca6ea1SDimitry Andric       Builder.setFastMathFlags(FMF);
745*0fca6ea1SDimitry Andric       auto *NewFMul = Builder.CreateFMul(X, Z);
746*0fca6ea1SDimitry Andric       return BinaryOperator::CreateFDivFMF(NewFMul, Y, FMF);
747*0fca6ea1SDimitry Andric     }
7480b57cec5SDimitry Andric   }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   // sqrt(X) * sqrt(Y) -> sqrt(X * Y)
7510b57cec5SDimitry Andric   // nnan disallows the possibility of returning a number if both operands are
7520b57cec5SDimitry Andric   // negative (in that case, we should return NaN).
75381ad6265SDimitry Andric   if (I.hasNoNaNs() && match(Op0, m_OneUse(m_Sqrt(m_Value(X)))) &&
75481ad6265SDimitry Andric       match(Op1, m_OneUse(m_Sqrt(m_Value(Y))))) {
7550b57cec5SDimitry Andric     Value *XY = Builder.CreateFMulFMF(X, Y, &I);
7560b57cec5SDimitry Andric     Value *Sqrt = Builder.CreateUnaryIntrinsic(Intrinsic::sqrt, XY, &I);
7570b57cec5SDimitry Andric     return replaceInstUsesWith(I, Sqrt);
7580b57cec5SDimitry Andric   }
7590b57cec5SDimitry Andric 
760e8d8bef9SDimitry Andric   // The following transforms are done irrespective of the number of uses
761e8d8bef9SDimitry Andric   // for the expression "1.0/sqrt(X)".
762e8d8bef9SDimitry Andric   //  1) 1.0/sqrt(X) * X -> X/sqrt(X)
763e8d8bef9SDimitry Andric   //  2) X * 1.0/sqrt(X) -> X/sqrt(X)
764e8d8bef9SDimitry Andric   // We always expect the backend to reduce X/sqrt(X) to sqrt(X), if it
765e8d8bef9SDimitry Andric   // has the necessary (reassoc) fast-math-flags.
766e8d8bef9SDimitry Andric   if (I.hasNoSignedZeros() &&
767e8d8bef9SDimitry Andric       match(Op0, (m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) &&
76881ad6265SDimitry Andric       match(Y, m_Sqrt(m_Value(X))) && Op1 == X)
769e8d8bef9SDimitry Andric     return BinaryOperator::CreateFDivFMF(X, Y, &I);
770e8d8bef9SDimitry Andric   if (I.hasNoSignedZeros() &&
771e8d8bef9SDimitry Andric       match(Op1, (m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) &&
77281ad6265SDimitry Andric       match(Y, m_Sqrt(m_Value(X))) && Op0 == X)
773e8d8bef9SDimitry Andric     return BinaryOperator::CreateFDivFMF(X, Y, &I);
774e8d8bef9SDimitry Andric 
7750b57cec5SDimitry Andric   // Like the similar transform in instsimplify, this requires 'nsz' because
7760b57cec5SDimitry Andric   // sqrt(-0.0) = -0.0, and -0.0 * -0.0 does not simplify to -0.0.
7775f757f3fSDimitry Andric   if (I.hasNoNaNs() && I.hasNoSignedZeros() && Op0 == Op1 && Op0->hasNUses(2)) {
7780b57cec5SDimitry Andric     // Peek through fdiv to find squaring of square root:
7790b57cec5SDimitry Andric     // (X / sqrt(Y)) * (X / sqrt(Y)) --> (X * X) / Y
78081ad6265SDimitry Andric     if (match(Op0, m_FDiv(m_Value(X), m_Sqrt(m_Value(Y))))) {
7810b57cec5SDimitry Andric       Value *XX = Builder.CreateFMulFMF(X, X, &I);
7820b57cec5SDimitry Andric       return BinaryOperator::CreateFDivFMF(XX, Y, &I);
7830b57cec5SDimitry Andric     }
7840b57cec5SDimitry Andric     // (sqrt(Y) / X) * (sqrt(Y) / X) --> Y / (X * X)
78581ad6265SDimitry Andric     if (match(Op0, m_FDiv(m_Sqrt(m_Value(Y)), m_Value(X)))) {
7860b57cec5SDimitry Andric       Value *XX = Builder.CreateFMulFMF(X, X, &I);
7870b57cec5SDimitry Andric       return BinaryOperator::CreateFDivFMF(Y, XX, &I);
7880b57cec5SDimitry Andric     }
7890b57cec5SDimitry Andric   }
7900b57cec5SDimitry Andric 
791bdd1243dSDimitry Andric   // pow(X, Y) * X --> pow(X, Y+1)
792bdd1243dSDimitry Andric   // X * pow(X, Y) --> pow(X, Y+1)
793bdd1243dSDimitry Andric   if (match(&I, m_c_FMul(m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Value(X),
794bdd1243dSDimitry Andric                                                               m_Value(Y))),
795bdd1243dSDimitry Andric                          m_Deferred(X)))) {
7965f757f3fSDimitry Andric     Value *Y1 = Builder.CreateFAddFMF(Y, ConstantFP::get(I.getType(), 1.0), &I);
797bdd1243dSDimitry Andric     Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, Y1, &I);
798bdd1243dSDimitry Andric     return replaceInstUsesWith(I, Pow);
799bdd1243dSDimitry Andric   }
800bdd1243dSDimitry Andric 
801*0fca6ea1SDimitry Andric   if (Instruction *FoldedPowi = foldPowiReassoc(I))
802*0fca6ea1SDimitry Andric     return FoldedPowi;
803*0fca6ea1SDimitry Andric 
804fe6060f1SDimitry Andric   if (I.isOnlyUserOfAnyOperand()) {
805bdd1243dSDimitry Andric     // pow(X, Y) * pow(X, Z) -> pow(X, Y + Z)
806fe6060f1SDimitry Andric     if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
807fe6060f1SDimitry Andric         match(Op1, m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z)))) {
808fe6060f1SDimitry Andric       auto *YZ = Builder.CreateFAddFMF(Y, Z, &I);
809fe6060f1SDimitry Andric       auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, YZ, &I);
810fe6060f1SDimitry Andric       return replaceInstUsesWith(I, NewPow);
811fe6060f1SDimitry Andric     }
812bdd1243dSDimitry Andric     // pow(X, Y) * pow(Z, Y) -> pow(X * Z, Y)
813bdd1243dSDimitry Andric     if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
814bdd1243dSDimitry Andric         match(Op1, m_Intrinsic<Intrinsic::pow>(m_Value(Z), m_Specific(Y)))) {
815bdd1243dSDimitry Andric       auto *XZ = Builder.CreateFMulFMF(X, Z, &I);
816bdd1243dSDimitry Andric       auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, XZ, Y, &I);
817bdd1243dSDimitry Andric       return replaceInstUsesWith(I, NewPow);
818bdd1243dSDimitry Andric     }
819fe6060f1SDimitry Andric 
8200b57cec5SDimitry Andric     // exp(X) * exp(Y) -> exp(X + Y)
8210b57cec5SDimitry Andric     if (match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X))) &&
822fe6060f1SDimitry Andric         match(Op1, m_Intrinsic<Intrinsic::exp>(m_Value(Y)))) {
8230b57cec5SDimitry Andric       Value *XY = Builder.CreateFAddFMF(X, Y, &I);
8240b57cec5SDimitry Andric       Value *Exp = Builder.CreateUnaryIntrinsic(Intrinsic::exp, XY, &I);
8250b57cec5SDimitry Andric       return replaceInstUsesWith(I, Exp);
8260b57cec5SDimitry Andric     }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric     // exp2(X) * exp2(Y) -> exp2(X + Y)
8290b57cec5SDimitry Andric     if (match(Op0, m_Intrinsic<Intrinsic::exp2>(m_Value(X))) &&
830fe6060f1SDimitry Andric         match(Op1, m_Intrinsic<Intrinsic::exp2>(m_Value(Y)))) {
8310b57cec5SDimitry Andric       Value *XY = Builder.CreateFAddFMF(X, Y, &I);
8320b57cec5SDimitry Andric       Value *Exp2 = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, XY, &I);
8330b57cec5SDimitry Andric       return replaceInstUsesWith(I, Exp2);
8340b57cec5SDimitry Andric     }
835fe6060f1SDimitry Andric   }
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   // (X*Y) * X => (X*X) * Y where Y != X
8380b57cec5SDimitry Andric   //  The purpose is two-fold:
8390b57cec5SDimitry Andric   //   1) to form a power expression (of X).
8400b57cec5SDimitry Andric   //   2) potentially shorten the critical path: After transformation, the
8410b57cec5SDimitry Andric   //  latency of the instruction Y is amortized by the expression of X*X,
8420b57cec5SDimitry Andric   //  and therefore Y is in a "less critical" position compared to what it
8430b57cec5SDimitry Andric   //  was before the transformation.
8445f757f3fSDimitry Andric   if (match(Op0, m_OneUse(m_c_FMul(m_Specific(Op1), m_Value(Y)))) && Op1 != Y) {
8450b57cec5SDimitry Andric     Value *XX = Builder.CreateFMulFMF(Op1, Op1, &I);
8460b57cec5SDimitry Andric     return BinaryOperator::CreateFMulFMF(XX, Y, &I);
8470b57cec5SDimitry Andric   }
8485f757f3fSDimitry Andric   if (match(Op1, m_OneUse(m_c_FMul(m_Specific(Op0), m_Value(Y)))) && Op0 != Y) {
8490b57cec5SDimitry Andric     Value *XX = Builder.CreateFMulFMF(Op0, Op0, &I);
8500b57cec5SDimitry Andric     return BinaryOperator::CreateFMulFMF(XX, Y, &I);
8510b57cec5SDimitry Andric   }
8525f757f3fSDimitry Andric 
8535f757f3fSDimitry Andric   return nullptr;
8540b57cec5SDimitry Andric }
8550b57cec5SDimitry Andric 
visitFMul(BinaryOperator & I)8565f757f3fSDimitry Andric Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
8575f757f3fSDimitry Andric   if (Value *V = simplifyFMulInst(I.getOperand(0), I.getOperand(1),
8585f757f3fSDimitry Andric                                   I.getFastMathFlags(),
8595f757f3fSDimitry Andric                                   SQ.getWithInstruction(&I)))
8605f757f3fSDimitry Andric     return replaceInstUsesWith(I, V);
8615f757f3fSDimitry Andric 
8625f757f3fSDimitry Andric   if (SimplifyAssociativeOrCommutative(I))
8635f757f3fSDimitry Andric     return &I;
8645f757f3fSDimitry Andric 
8655f757f3fSDimitry Andric   if (Instruction *X = foldVectorBinop(I))
8665f757f3fSDimitry Andric     return X;
8675f757f3fSDimitry Andric 
8685f757f3fSDimitry Andric   if (Instruction *Phi = foldBinopWithPhiOperands(I))
8695f757f3fSDimitry Andric     return Phi;
8705f757f3fSDimitry Andric 
8715f757f3fSDimitry Andric   if (Instruction *FoldedMul = foldBinOpIntoSelectOrPhi(I))
8725f757f3fSDimitry Andric     return FoldedMul;
8735f757f3fSDimitry Andric 
8745f757f3fSDimitry Andric   if (Value *FoldedMul = foldMulSelectToNegate(I, Builder))
8755f757f3fSDimitry Andric     return replaceInstUsesWith(I, FoldedMul);
8765f757f3fSDimitry Andric 
8775f757f3fSDimitry Andric   if (Instruction *R = foldFPSignBitOps(I))
8785f757f3fSDimitry Andric     return R;
8795f757f3fSDimitry Andric 
880*0fca6ea1SDimitry Andric   if (Instruction *R = foldFBinOpOfIntCasts(I))
881*0fca6ea1SDimitry Andric     return R;
882*0fca6ea1SDimitry Andric 
8835f757f3fSDimitry Andric   // X * -1.0 --> -X
8845f757f3fSDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
8855f757f3fSDimitry Andric   if (match(Op1, m_SpecificFP(-1.0)))
8865f757f3fSDimitry Andric     return UnaryOperator::CreateFNegFMF(Op0, &I);
8875f757f3fSDimitry Andric 
888*0fca6ea1SDimitry Andric   // With no-nans/no-infs:
889*0fca6ea1SDimitry Andric   // X * 0.0 --> copysign(0.0, X)
890*0fca6ea1SDimitry Andric   // X * -0.0 --> copysign(0.0, -X)
891*0fca6ea1SDimitry Andric   const APFloat *FPC;
892*0fca6ea1SDimitry Andric   if (match(Op1, m_APFloatAllowPoison(FPC)) && FPC->isZero() &&
893*0fca6ea1SDimitry Andric       ((I.hasNoInfs() &&
894*0fca6ea1SDimitry Andric         isKnownNeverNaN(Op0, /*Depth=*/0, SQ.getWithInstruction(&I))) ||
895*0fca6ea1SDimitry Andric        isKnownNeverNaN(&I, /*Depth=*/0, SQ.getWithInstruction(&I)))) {
896*0fca6ea1SDimitry Andric     if (FPC->isNegative())
897*0fca6ea1SDimitry Andric       Op0 = Builder.CreateFNegFMF(Op0, &I);
8985f757f3fSDimitry Andric     CallInst *CopySign = Builder.CreateIntrinsic(Intrinsic::copysign,
8995f757f3fSDimitry Andric                                                  {I.getType()}, {Op1, Op0}, &I);
9005f757f3fSDimitry Andric     return replaceInstUsesWith(I, CopySign);
9015f757f3fSDimitry Andric   }
9025f757f3fSDimitry Andric 
9035f757f3fSDimitry Andric   // -X * C --> X * -C
9045f757f3fSDimitry Andric   Value *X, *Y;
9055f757f3fSDimitry Andric   Constant *C;
9065f757f3fSDimitry Andric   if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_Constant(C)))
9075f757f3fSDimitry Andric     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
9085f757f3fSDimitry Andric       return BinaryOperator::CreateFMulFMF(X, NegC, &I);
9095f757f3fSDimitry Andric 
910*0fca6ea1SDimitry Andric   if (I.hasNoNaNs() && I.hasNoSignedZeros()) {
911*0fca6ea1SDimitry Andric     // (uitofp bool X) * Y --> X ? Y : 0
912*0fca6ea1SDimitry Andric     // Y * (uitofp bool X) --> X ? Y : 0
913*0fca6ea1SDimitry Andric     // Note INF * 0 is NaN.
914*0fca6ea1SDimitry Andric     if (match(Op0, m_UIToFP(m_Value(X))) &&
915*0fca6ea1SDimitry Andric         X->getType()->isIntOrIntVectorTy(1)) {
916*0fca6ea1SDimitry Andric       auto *SI = SelectInst::Create(X, Op1, ConstantFP::get(I.getType(), 0.0));
917*0fca6ea1SDimitry Andric       SI->copyFastMathFlags(I.getFastMathFlags());
918*0fca6ea1SDimitry Andric       return SI;
919*0fca6ea1SDimitry Andric     }
920*0fca6ea1SDimitry Andric     if (match(Op1, m_UIToFP(m_Value(X))) &&
921*0fca6ea1SDimitry Andric         X->getType()->isIntOrIntVectorTy(1)) {
922*0fca6ea1SDimitry Andric       auto *SI = SelectInst::Create(X, Op0, ConstantFP::get(I.getType(), 0.0));
923*0fca6ea1SDimitry Andric       SI->copyFastMathFlags(I.getFastMathFlags());
924*0fca6ea1SDimitry Andric       return SI;
925*0fca6ea1SDimitry Andric     }
926*0fca6ea1SDimitry Andric   }
927*0fca6ea1SDimitry Andric 
9285f757f3fSDimitry Andric   // (select A, B, C) * (select A, D, E) --> select A, (B*D), (C*E)
9295f757f3fSDimitry Andric   if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
9305f757f3fSDimitry Andric     return replaceInstUsesWith(I, V);
9315f757f3fSDimitry Andric 
9325f757f3fSDimitry Andric   if (I.hasAllowReassoc())
9335f757f3fSDimitry Andric     if (Instruction *FoldedMul = foldFMulReassoc(I))
9345f757f3fSDimitry Andric       return FoldedMul;
9355f757f3fSDimitry Andric 
9360b57cec5SDimitry Andric   // log2(X * 0.5) * Y = log2(X) * Y - Y
9370b57cec5SDimitry Andric   if (I.isFast()) {
9380b57cec5SDimitry Andric     IntrinsicInst *Log2 = nullptr;
9390b57cec5SDimitry Andric     if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::log2>(
9400b57cec5SDimitry Andric             m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
9410b57cec5SDimitry Andric       Log2 = cast<IntrinsicInst>(Op0);
9420b57cec5SDimitry Andric       Y = Op1;
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric     if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::log2>(
9450b57cec5SDimitry Andric             m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
9460b57cec5SDimitry Andric       Log2 = cast<IntrinsicInst>(Op1);
9470b57cec5SDimitry Andric       Y = Op0;
9480b57cec5SDimitry Andric     }
9490b57cec5SDimitry Andric     if (Log2) {
9505ffd83dbSDimitry Andric       Value *Log2 = Builder.CreateUnaryIntrinsic(Intrinsic::log2, X, &I);
9510b57cec5SDimitry Andric       Value *LogXTimesY = Builder.CreateFMulFMF(Log2, Y, &I);
9520b57cec5SDimitry Andric       return BinaryOperator::CreateFSubFMF(LogXTimesY, Y, &I);
9530b57cec5SDimitry Andric     }
9540b57cec5SDimitry Andric   }
9550b57cec5SDimitry Andric 
956bdd1243dSDimitry Andric   // Simplify FMUL recurrences starting with 0.0 to 0.0 if nnan and nsz are set.
957bdd1243dSDimitry Andric   // Given a phi node with entry value as 0 and it used in fmul operation,
958bdd1243dSDimitry Andric   // we can replace fmul with 0 safely and eleminate loop operation.
959bdd1243dSDimitry Andric   PHINode *PN = nullptr;
960bdd1243dSDimitry Andric   Value *Start = nullptr, *Step = nullptr;
961bdd1243dSDimitry Andric   if (matchSimpleRecurrence(&I, PN, Start, Step) && I.hasNoNaNs() &&
962bdd1243dSDimitry Andric       I.hasNoSignedZeros() && match(Start, m_Zero()))
963bdd1243dSDimitry Andric     return replaceInstUsesWith(I, Start);
964bdd1243dSDimitry Andric 
9655f757f3fSDimitry Andric   // minimum(X, Y) * maximum(X, Y) => X * Y.
96606c3fb27SDimitry Andric   if (match(&I,
96706c3fb27SDimitry Andric             m_c_FMul(m_Intrinsic<Intrinsic::maximum>(m_Value(X), m_Value(Y)),
96806c3fb27SDimitry Andric                      m_c_Intrinsic<Intrinsic::minimum>(m_Deferred(X),
96906c3fb27SDimitry Andric                                                        m_Deferred(Y))))) {
97006c3fb27SDimitry Andric     BinaryOperator *Result = BinaryOperator::CreateFMulFMF(X, Y, &I);
97106c3fb27SDimitry Andric     // We cannot preserve ninf if nnan flag is not set.
97206c3fb27SDimitry Andric     // If X is NaN and Y is Inf then in original program we had NaN * NaN,
97306c3fb27SDimitry Andric     // while in optimized version NaN * Inf and this is a poison with ninf flag.
97406c3fb27SDimitry Andric     if (!Result->hasNoNaNs())
97506c3fb27SDimitry Andric       Result->setHasNoInfs(false);
97606c3fb27SDimitry Andric     return Result;
97706c3fb27SDimitry Andric   }
97806c3fb27SDimitry Andric 
9790b57cec5SDimitry Andric   return nullptr;
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric /// Fold a divide or remainder with a select instruction divisor when one of the
9830b57cec5SDimitry Andric /// select operands is zero. In that case, we can use the other select operand
9840b57cec5SDimitry Andric /// because div/rem by zero is undefined.
simplifyDivRemOfSelectWithZeroOp(BinaryOperator & I)985e8d8bef9SDimitry Andric bool InstCombinerImpl::simplifyDivRemOfSelectWithZeroOp(BinaryOperator &I) {
9860b57cec5SDimitry Andric   SelectInst *SI = dyn_cast<SelectInst>(I.getOperand(1));
9870b57cec5SDimitry Andric   if (!SI)
9880b57cec5SDimitry Andric     return false;
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric   int NonNullOperand;
9910b57cec5SDimitry Andric   if (match(SI->getTrueValue(), m_Zero()))
9920b57cec5SDimitry Andric     // div/rem X, (Cond ? 0 : Y) -> div/rem X, Y
9930b57cec5SDimitry Andric     NonNullOperand = 2;
9940b57cec5SDimitry Andric   else if (match(SI->getFalseValue(), m_Zero()))
9950b57cec5SDimitry Andric     // div/rem X, (Cond ? Y : 0) -> div/rem X, Y
9960b57cec5SDimitry Andric     NonNullOperand = 1;
9970b57cec5SDimitry Andric   else
9980b57cec5SDimitry Andric     return false;
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric   // Change the div/rem to use 'Y' instead of the select.
10015ffd83dbSDimitry Andric   replaceOperand(I, 1, SI->getOperand(NonNullOperand));
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   // Okay, we know we replace the operand of the div/rem with 'Y' with no
10040b57cec5SDimitry Andric   // problem.  However, the select, or the condition of the select may have
10050b57cec5SDimitry Andric   // multiple uses.  Based on our knowledge that the operand must be non-zero,
10060b57cec5SDimitry Andric   // propagate the known value for the select into other uses of it, and
10070b57cec5SDimitry Andric   // propagate a known value of the condition into its other users.
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   // If the select and condition only have a single use, don't bother with this,
10100b57cec5SDimitry Andric   // early exit.
10110b57cec5SDimitry Andric   Value *SelectCond = SI->getCondition();
10120b57cec5SDimitry Andric   if (SI->use_empty() && SelectCond->hasOneUse())
10130b57cec5SDimitry Andric     return true;
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   // Scan the current block backward, looking for other uses of SI.
10160b57cec5SDimitry Andric   BasicBlock::iterator BBI = I.getIterator(), BBFront = I.getParent()->begin();
10170b57cec5SDimitry Andric   Type *CondTy = SelectCond->getType();
10180b57cec5SDimitry Andric   while (BBI != BBFront) {
10190b57cec5SDimitry Andric     --BBI;
10200b57cec5SDimitry Andric     // If we found an instruction that we can't assume will return, so
10210b57cec5SDimitry Andric     // information from below it cannot be propagated above it.
10220b57cec5SDimitry Andric     if (!isGuaranteedToTransferExecutionToSuccessor(&*BBI))
10230b57cec5SDimitry Andric       break;
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric     // Replace uses of the select or its condition with the known values.
1026fe6060f1SDimitry Andric     for (Use &Op : BBI->operands()) {
1027fe6060f1SDimitry Andric       if (Op == SI) {
1028fe6060f1SDimitry Andric         replaceUse(Op, SI->getOperand(NonNullOperand));
10295ffd83dbSDimitry Andric         Worklist.push(&*BBI);
1030fe6060f1SDimitry Andric       } else if (Op == SelectCond) {
1031fe6060f1SDimitry Andric         replaceUse(Op, NonNullOperand == 1 ? ConstantInt::getTrue(CondTy)
10325ffd83dbSDimitry Andric                                            : ConstantInt::getFalse(CondTy));
10335ffd83dbSDimitry Andric         Worklist.push(&*BBI);
10340b57cec5SDimitry Andric       }
10350b57cec5SDimitry Andric     }
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric     // If we past the instruction, quit looking for it.
10380b57cec5SDimitry Andric     if (&*BBI == SI)
10390b57cec5SDimitry Andric       SI = nullptr;
10400b57cec5SDimitry Andric     if (&*BBI == SelectCond)
10410b57cec5SDimitry Andric       SelectCond = nullptr;
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric     // If we ran out of things to eliminate, break out of the loop.
10440b57cec5SDimitry Andric     if (!SelectCond && !SI)
10450b57cec5SDimitry Andric       break;
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   }
10480b57cec5SDimitry Andric   return true;
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric /// True if the multiply can not be expressed in an int this size.
multiplyOverflows(const APInt & C1,const APInt & C2,APInt & Product,bool IsSigned)10520b57cec5SDimitry Andric static bool multiplyOverflows(const APInt &C1, const APInt &C2, APInt &Product,
10530b57cec5SDimitry Andric                               bool IsSigned) {
10540b57cec5SDimitry Andric   bool Overflow;
10550b57cec5SDimitry Andric   Product = IsSigned ? C1.smul_ov(C2, Overflow) : C1.umul_ov(C2, Overflow);
10560b57cec5SDimitry Andric   return Overflow;
10570b57cec5SDimitry Andric }
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric /// True if C1 is a multiple of C2. Quotient contains C1/C2.
isMultiple(const APInt & C1,const APInt & C2,APInt & Quotient,bool IsSigned)10600b57cec5SDimitry Andric static bool isMultiple(const APInt &C1, const APInt &C2, APInt &Quotient,
10610b57cec5SDimitry Andric                        bool IsSigned) {
10620b57cec5SDimitry Andric   assert(C1.getBitWidth() == C2.getBitWidth() && "Constant widths not equal");
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   // Bail if we will divide by zero.
1065349cc55cSDimitry Andric   if (C2.isZero())
10660b57cec5SDimitry Andric     return false;
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   // Bail if we would divide INT_MIN by -1.
1069349cc55cSDimitry Andric   if (IsSigned && C1.isMinSignedValue() && C2.isAllOnes())
10700b57cec5SDimitry Andric     return false;
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric   APInt Remainder(C1.getBitWidth(), /*val=*/0ULL, IsSigned);
10730b57cec5SDimitry Andric   if (IsSigned)
10740b57cec5SDimitry Andric     APInt::sdivrem(C1, C2, Quotient, Remainder);
10750b57cec5SDimitry Andric   else
10760b57cec5SDimitry Andric     APInt::udivrem(C1, C2, Quotient, Remainder);
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   return Remainder.isMinValue();
10790b57cec5SDimitry Andric }
10800b57cec5SDimitry Andric 
foldIDivShl(BinaryOperator & I,InstCombiner::BuilderTy & Builder)10815f757f3fSDimitry Andric static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
1082bdd1243dSDimitry Andric   assert((I.getOpcode() == Instruction::SDiv ||
1083bdd1243dSDimitry Andric           I.getOpcode() == Instruction::UDiv) &&
1084bdd1243dSDimitry Andric          "Expected integer divide");
1085bdd1243dSDimitry Andric 
1086bdd1243dSDimitry Andric   bool IsSigned = I.getOpcode() == Instruction::SDiv;
1087bdd1243dSDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1088bdd1243dSDimitry Andric   Type *Ty = I.getType();
1089bdd1243dSDimitry Andric 
1090bdd1243dSDimitry Andric   Value *X, *Y, *Z;
1091bdd1243dSDimitry Andric 
1092bdd1243dSDimitry Andric   // With appropriate no-wrap constraints, remove a common factor in the
1093bdd1243dSDimitry Andric   // dividend and divisor that is disguised as a left-shifted value.
1094bdd1243dSDimitry Andric   if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
1095bdd1243dSDimitry Andric       match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
1096bdd1243dSDimitry Andric     // Both operands must have the matching no-wrap for this kind of division.
1097bdd1243dSDimitry Andric     auto *Mul = cast<OverflowingBinaryOperator>(Op0);
1098bdd1243dSDimitry Andric     auto *Shl = cast<OverflowingBinaryOperator>(Op1);
1099bdd1243dSDimitry Andric     bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
1100bdd1243dSDimitry Andric     bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
1101bdd1243dSDimitry Andric 
1102bdd1243dSDimitry Andric     // (X * Y) u/ (X << Z) --> Y u>> Z
1103bdd1243dSDimitry Andric     if (!IsSigned && HasNUW)
11045f757f3fSDimitry Andric       return Builder.CreateLShr(Y, Z, "", I.isExact());
1105bdd1243dSDimitry Andric 
1106bdd1243dSDimitry Andric     // (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
1107bdd1243dSDimitry Andric     if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
1108bdd1243dSDimitry Andric       Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
11095f757f3fSDimitry Andric       return Builder.CreateSDiv(Y, Shl, "", I.isExact());
1110bdd1243dSDimitry Andric     }
1111bdd1243dSDimitry Andric   }
1112bdd1243dSDimitry Andric 
1113bdd1243dSDimitry Andric   // With appropriate no-wrap constraints, remove a common factor in the
1114bdd1243dSDimitry Andric   // dividend and divisor that is disguised as a left-shift amount.
1115bdd1243dSDimitry Andric   if (match(Op0, m_Shl(m_Value(X), m_Value(Z))) &&
1116bdd1243dSDimitry Andric       match(Op1, m_Shl(m_Value(Y), m_Specific(Z)))) {
1117bdd1243dSDimitry Andric     auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
1118bdd1243dSDimitry Andric     auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
1119bdd1243dSDimitry Andric 
1120bdd1243dSDimitry Andric     // For unsigned div, we need 'nuw' on both shifts or
1121bdd1243dSDimitry Andric     // 'nsw' on both shifts + 'nuw' on the dividend.
1122bdd1243dSDimitry Andric     // (X << Z) / (Y << Z) --> X / Y
1123bdd1243dSDimitry Andric     if (!IsSigned &&
1124bdd1243dSDimitry Andric         ((Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap()) ||
1125bdd1243dSDimitry Andric          (Shl0->hasNoUnsignedWrap() && Shl0->hasNoSignedWrap() &&
1126bdd1243dSDimitry Andric           Shl1->hasNoSignedWrap())))
11275f757f3fSDimitry Andric       return Builder.CreateUDiv(X, Y, "", I.isExact());
1128bdd1243dSDimitry Andric 
1129bdd1243dSDimitry Andric     // For signed div, we need 'nsw' on both shifts + 'nuw' on the divisor.
1130bdd1243dSDimitry Andric     // (X << Z) / (Y << Z) --> X / Y
1131bdd1243dSDimitry Andric     if (IsSigned && Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap() &&
1132bdd1243dSDimitry Andric         Shl1->hasNoUnsignedWrap())
11335f757f3fSDimitry Andric       return Builder.CreateSDiv(X, Y, "", I.isExact());
1134bdd1243dSDimitry Andric   }
1135bdd1243dSDimitry Andric 
11365f757f3fSDimitry Andric   // If X << Y and X << Z does not overflow, then:
11375f757f3fSDimitry Andric   // (X << Y) / (X << Z) -> (1 << Y) / (1 << Z) -> 1 << Y >> Z
11385f757f3fSDimitry Andric   if (match(Op0, m_Shl(m_Value(X), m_Value(Y))) &&
11395f757f3fSDimitry Andric       match(Op1, m_Shl(m_Specific(X), m_Value(Z)))) {
11405f757f3fSDimitry Andric     auto *Shl0 = cast<OverflowingBinaryOperator>(Op0);
11415f757f3fSDimitry Andric     auto *Shl1 = cast<OverflowingBinaryOperator>(Op1);
1142bdd1243dSDimitry Andric 
11435f757f3fSDimitry Andric     if (IsSigned ? (Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap())
11445f757f3fSDimitry Andric                  : (Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap())) {
11455f757f3fSDimitry Andric       Constant *One = ConstantInt::get(X->getType(), 1);
11465f757f3fSDimitry Andric       // Only preserve the nsw flag if dividend has nsw
11475f757f3fSDimitry Andric       // or divisor has nsw and operator is sdiv.
11485f757f3fSDimitry Andric       Value *Dividend = Builder.CreateShl(
11495f757f3fSDimitry Andric           One, Y, "shl.dividend",
11505f757f3fSDimitry Andric           /*HasNUW*/ true,
11515f757f3fSDimitry Andric           /*HasNSW*/
11525f757f3fSDimitry Andric           IsSigned ? (Shl0->hasNoUnsignedWrap() || Shl1->hasNoUnsignedWrap())
11535f757f3fSDimitry Andric                    : Shl0->hasNoSignedWrap());
11545f757f3fSDimitry Andric       return Builder.CreateLShr(Dividend, Z, "", I.isExact());
11555f757f3fSDimitry Andric     }
11565f757f3fSDimitry Andric   }
11575f757f3fSDimitry Andric 
11585f757f3fSDimitry Andric   return nullptr;
1159bdd1243dSDimitry Andric }
1160bdd1243dSDimitry Andric 
11610b57cec5SDimitry Andric /// This function implements the transforms common to both integer division
11620b57cec5SDimitry Andric /// instructions (udiv and sdiv). It is called by the visitors to those integer
11630b57cec5SDimitry Andric /// division instructions.
11640b57cec5SDimitry Andric /// Common integer divide transforms
commonIDivTransforms(BinaryOperator & I)1165e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
116604eeddc0SDimitry Andric   if (Instruction *Phi = foldBinopWithPhiOperands(I))
116704eeddc0SDimitry Andric     return Phi;
116804eeddc0SDimitry Andric 
11690b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
11700b57cec5SDimitry Andric   bool IsSigned = I.getOpcode() == Instruction::SDiv;
11710b57cec5SDimitry Andric   Type *Ty = I.getType();
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric   // The RHS is known non-zero.
11745ffd83dbSDimitry Andric   if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this, I))
11755ffd83dbSDimitry Andric     return replaceOperand(I, 1, V);
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   // Handle cases involving: [su]div X, (select Cond, Y, Z)
11780b57cec5SDimitry Andric   // This does not apply for fdiv.
11790b57cec5SDimitry Andric   if (simplifyDivRemOfSelectWithZeroOp(I))
11800b57cec5SDimitry Andric     return &I;
11810b57cec5SDimitry Andric 
11820eae32dcSDimitry Andric   // If the divisor is a select-of-constants, try to constant fold all div ops:
11830eae32dcSDimitry Andric   // C / (select Cond, TrueC, FalseC) --> select Cond, (C / TrueC), (C / FalseC)
11840eae32dcSDimitry Andric   // TODO: Adapt simplifyDivRemOfSelectWithZeroOp to allow this and other folds.
11850eae32dcSDimitry Andric   if (match(Op0, m_ImmConstant()) &&
11860eae32dcSDimitry Andric       match(Op1, m_Select(m_Value(), m_ImmConstant(), m_ImmConstant()))) {
118781ad6265SDimitry Andric     if (Instruction *R = FoldOpIntoSelect(I, cast<SelectInst>(Op1),
118881ad6265SDimitry Andric                                           /*FoldWithMultiUse*/ true))
11890eae32dcSDimitry Andric       return R;
11900eae32dcSDimitry Andric   }
11910eae32dcSDimitry Andric 
11920b57cec5SDimitry Andric   const APInt *C2;
11930b57cec5SDimitry Andric   if (match(Op1, m_APInt(C2))) {
11940b57cec5SDimitry Andric     Value *X;
11950b57cec5SDimitry Andric     const APInt *C1;
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric     // (X / C1) / C2  -> X / (C1*C2)
11980b57cec5SDimitry Andric     if ((IsSigned && match(Op0, m_SDiv(m_Value(X), m_APInt(C1)))) ||
11990b57cec5SDimitry Andric         (!IsSigned && match(Op0, m_UDiv(m_Value(X), m_APInt(C1))))) {
12000b57cec5SDimitry Andric       APInt Product(C1->getBitWidth(), /*val=*/0ULL, IsSigned);
12010b57cec5SDimitry Andric       if (!multiplyOverflows(*C1, *C2, Product, IsSigned))
12020b57cec5SDimitry Andric         return BinaryOperator::Create(I.getOpcode(), X,
12030b57cec5SDimitry Andric                                       ConstantInt::get(Ty, Product));
12040b57cec5SDimitry Andric     }
12050b57cec5SDimitry Andric 
120606c3fb27SDimitry Andric     APInt Quotient(C2->getBitWidth(), /*val=*/0ULL, IsSigned);
12070b57cec5SDimitry Andric     if ((IsSigned && match(Op0, m_NSWMul(m_Value(X), m_APInt(C1)))) ||
12080b57cec5SDimitry Andric         (!IsSigned && match(Op0, m_NUWMul(m_Value(X), m_APInt(C1))))) {
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric       // (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1.
12110b57cec5SDimitry Andric       if (isMultiple(*C2, *C1, Quotient, IsSigned)) {
12120b57cec5SDimitry Andric         auto *NewDiv = BinaryOperator::Create(I.getOpcode(), X,
12130b57cec5SDimitry Andric                                               ConstantInt::get(Ty, Quotient));
12140b57cec5SDimitry Andric         NewDiv->setIsExact(I.isExact());
12150b57cec5SDimitry Andric         return NewDiv;
12160b57cec5SDimitry Andric       }
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric       // (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2.
12190b57cec5SDimitry Andric       if (isMultiple(*C1, *C2, Quotient, IsSigned)) {
12200b57cec5SDimitry Andric         auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
12210b57cec5SDimitry Andric                                            ConstantInt::get(Ty, Quotient));
12220b57cec5SDimitry Andric         auto *OBO = cast<OverflowingBinaryOperator>(Op0);
12230b57cec5SDimitry Andric         Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
12240b57cec5SDimitry Andric         Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
12250b57cec5SDimitry Andric         return Mul;
12260b57cec5SDimitry Andric       }
12270b57cec5SDimitry Andric     }
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric     if ((IsSigned && match(Op0, m_NSWShl(m_Value(X), m_APInt(C1))) &&
1230349cc55cSDimitry Andric          C1->ult(C1->getBitWidth() - 1)) ||
1231349cc55cSDimitry Andric         (!IsSigned && match(Op0, m_NUWShl(m_Value(X), m_APInt(C1))) &&
1232349cc55cSDimitry Andric          C1->ult(C1->getBitWidth()))) {
12330b57cec5SDimitry Andric       APInt C1Shifted = APInt::getOneBitSet(
1234349cc55cSDimitry Andric           C1->getBitWidth(), static_cast<unsigned>(C1->getZExtValue()));
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric       // (X << C1) / C2 -> X / (C2 >> C1) if C2 is a multiple of 1 << C1.
12370b57cec5SDimitry Andric       if (isMultiple(*C2, C1Shifted, Quotient, IsSigned)) {
12380b57cec5SDimitry Andric         auto *BO = BinaryOperator::Create(I.getOpcode(), X,
12390b57cec5SDimitry Andric                                           ConstantInt::get(Ty, Quotient));
12400b57cec5SDimitry Andric         BO->setIsExact(I.isExact());
12410b57cec5SDimitry Andric         return BO;
12420b57cec5SDimitry Andric       }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric       // (X << C1) / C2 -> X * ((1 << C1) / C2) if 1 << C1 is a multiple of C2.
12450b57cec5SDimitry Andric       if (isMultiple(C1Shifted, *C2, Quotient, IsSigned)) {
12460b57cec5SDimitry Andric         auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
12470b57cec5SDimitry Andric                                            ConstantInt::get(Ty, Quotient));
12480b57cec5SDimitry Andric         auto *OBO = cast<OverflowingBinaryOperator>(Op0);
12490b57cec5SDimitry Andric         Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
12500b57cec5SDimitry Andric         Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
12510b57cec5SDimitry Andric         return Mul;
12520b57cec5SDimitry Andric       }
12530b57cec5SDimitry Andric     }
12540b57cec5SDimitry Andric 
125506c3fb27SDimitry Andric     // Distribute div over add to eliminate a matching div/mul pair:
125606c3fb27SDimitry Andric     // ((X * C2) + C1) / C2 --> X + C1/C2
125706c3fb27SDimitry Andric     // We need a multiple of the divisor for a signed add constant, but
125806c3fb27SDimitry Andric     // unsigned is fine with any constant pair.
125906c3fb27SDimitry Andric     if (IsSigned &&
1260*0fca6ea1SDimitry Andric         match(Op0, m_NSWAddLike(m_NSWMul(m_Value(X), m_SpecificInt(*C2)),
126106c3fb27SDimitry Andric                                 m_APInt(C1))) &&
126206c3fb27SDimitry Andric         isMultiple(*C1, *C2, Quotient, IsSigned)) {
126306c3fb27SDimitry Andric       return BinaryOperator::CreateNSWAdd(X, ConstantInt::get(Ty, Quotient));
126406c3fb27SDimitry Andric     }
126506c3fb27SDimitry Andric     if (!IsSigned &&
1266*0fca6ea1SDimitry Andric         match(Op0, m_NUWAddLike(m_NUWMul(m_Value(X), m_SpecificInt(*C2)),
126706c3fb27SDimitry Andric                                 m_APInt(C1)))) {
126806c3fb27SDimitry Andric       return BinaryOperator::CreateNUWAdd(X,
126906c3fb27SDimitry Andric                                           ConstantInt::get(Ty, C1->udiv(*C2)));
127006c3fb27SDimitry Andric     }
127106c3fb27SDimitry Andric 
1272349cc55cSDimitry Andric     if (!C2->isZero()) // avoid X udiv 0
12730b57cec5SDimitry Andric       if (Instruction *FoldedDiv = foldBinOpIntoSelectOrPhi(I))
12740b57cec5SDimitry Andric         return FoldedDiv;
12750b57cec5SDimitry Andric   }
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric   if (match(Op0, m_One())) {
12780b57cec5SDimitry Andric     assert(!Ty->isIntOrIntVectorTy(1) && "i1 divide not removed?");
12790b57cec5SDimitry Andric     if (IsSigned) {
128081ad6265SDimitry Andric       // 1 / 0 --> undef ; 1 / 1 --> 1 ; 1 / -1 --> -1 ; 1 / anything else --> 0
128181ad6265SDimitry Andric       // (Op1 + 1) u< 3 ? Op1 : 0
128281ad6265SDimitry Andric       // Op1 must be frozen because we are increasing its number of uses.
1283*0fca6ea1SDimitry Andric       Value *F1 = Op1;
1284*0fca6ea1SDimitry Andric       if (!isGuaranteedNotToBeUndef(Op1))
1285*0fca6ea1SDimitry Andric         F1 = Builder.CreateFreeze(Op1, Op1->getName() + ".fr");
128681ad6265SDimitry Andric       Value *Inc = Builder.CreateAdd(F1, Op0);
12870b57cec5SDimitry Andric       Value *Cmp = Builder.CreateICmpULT(Inc, ConstantInt::get(Ty, 3));
128881ad6265SDimitry Andric       return SelectInst::Create(Cmp, F1, ConstantInt::get(Ty, 0));
12890b57cec5SDimitry Andric     } else {
12900b57cec5SDimitry Andric       // If Op1 is 0 then it's undefined behaviour. If Op1 is 1 then the
12910b57cec5SDimitry Andric       // result is one, otherwise it's zero.
12920b57cec5SDimitry Andric       return new ZExtInst(Builder.CreateICmpEQ(Op1, Op0), Ty);
12930b57cec5SDimitry Andric     }
12940b57cec5SDimitry Andric   }
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric   // See if we can fold away this div instruction.
12970b57cec5SDimitry Andric   if (SimplifyDemandedInstructionBits(I))
12980b57cec5SDimitry Andric     return &I;
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric   // (X - (X rem Y)) / Y -> X / Y; usually originates as ((X / Y) * Y) / Y
13010b57cec5SDimitry Andric   Value *X, *Z;
13020b57cec5SDimitry Andric   if (match(Op0, m_Sub(m_Value(X), m_Value(Z)))) // (X - Z) / Y; Y = Op1
13030b57cec5SDimitry Andric     if ((IsSigned && match(Z, m_SRem(m_Specific(X), m_Specific(Op1)))) ||
13040b57cec5SDimitry Andric         (!IsSigned && match(Z, m_URem(m_Specific(X), m_Specific(Op1)))))
13050b57cec5SDimitry Andric       return BinaryOperator::Create(I.getOpcode(), X, Op1);
13060b57cec5SDimitry Andric 
13070b57cec5SDimitry Andric   // (X << Y) / X -> 1 << Y
13080b57cec5SDimitry Andric   Value *Y;
13090b57cec5SDimitry Andric   if (IsSigned && match(Op0, m_NSWShl(m_Specific(Op1), m_Value(Y))))
13100b57cec5SDimitry Andric     return BinaryOperator::CreateNSWShl(ConstantInt::get(Ty, 1), Y);
13110b57cec5SDimitry Andric   if (!IsSigned && match(Op0, m_NUWShl(m_Specific(Op1), m_Value(Y))))
13120b57cec5SDimitry Andric     return BinaryOperator::CreateNUWShl(ConstantInt::get(Ty, 1), Y);
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   // X / (X * Y) -> 1 / Y if the multiplication does not overflow.
13150b57cec5SDimitry Andric   if (match(Op1, m_c_Mul(m_Specific(Op0), m_Value(Y)))) {
13160b57cec5SDimitry Andric     bool HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
13170b57cec5SDimitry Andric     bool HasNUW = cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
13180b57cec5SDimitry Andric     if ((IsSigned && HasNSW) || (!IsSigned && HasNUW)) {
13195ffd83dbSDimitry Andric       replaceOperand(I, 0, ConstantInt::get(Ty, 1));
13205ffd83dbSDimitry Andric       replaceOperand(I, 1, Y);
13210b57cec5SDimitry Andric       return &I;
13220b57cec5SDimitry Andric     }
13230b57cec5SDimitry Andric   }
13240b57cec5SDimitry Andric 
1325bdd1243dSDimitry Andric   // (X << Z) / (X * Y) -> (1 << Z) / Y
1326bdd1243dSDimitry Andric   // TODO: Handle sdiv.
1327bdd1243dSDimitry Andric   if (!IsSigned && Op1->hasOneUse() &&
1328bdd1243dSDimitry Andric       match(Op0, m_NUWShl(m_Value(X), m_Value(Z))) &&
1329bdd1243dSDimitry Andric       match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
1330bdd1243dSDimitry Andric     if (cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap()) {
1331bdd1243dSDimitry Andric       Instruction *NewDiv = BinaryOperator::CreateUDiv(
1332bdd1243dSDimitry Andric           Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", /*NUW*/ true), Y);
1333bdd1243dSDimitry Andric       NewDiv->setIsExact(I.isExact());
1334bdd1243dSDimitry Andric       return NewDiv;
1335bdd1243dSDimitry Andric     }
1336bdd1243dSDimitry Andric 
13375f757f3fSDimitry Andric   if (Value *R = foldIDivShl(I, Builder))
13385f757f3fSDimitry Andric     return replaceInstUsesWith(I, R);
1339bdd1243dSDimitry Andric 
1340bdd1243dSDimitry Andric   // With the appropriate no-wrap constraint, remove a multiply by the divisor
1341bdd1243dSDimitry Andric   // after peeking through another divide:
1342bdd1243dSDimitry Andric   // ((Op1 * X) / Y) / Op1 --> X / Y
1343bdd1243dSDimitry Andric   if (match(Op0, m_BinOp(I.getOpcode(), m_c_Mul(m_Specific(Op1), m_Value(X)),
1344bdd1243dSDimitry Andric                          m_Value(Y)))) {
1345bdd1243dSDimitry Andric     auto *InnerDiv = cast<PossiblyExactOperator>(Op0);
1346bdd1243dSDimitry Andric     auto *Mul = cast<OverflowingBinaryOperator>(InnerDiv->getOperand(0));
1347bdd1243dSDimitry Andric     Instruction *NewDiv = nullptr;
1348bdd1243dSDimitry Andric     if (!IsSigned && Mul->hasNoUnsignedWrap())
1349bdd1243dSDimitry Andric       NewDiv = BinaryOperator::CreateUDiv(X, Y);
1350bdd1243dSDimitry Andric     else if (IsSigned && Mul->hasNoSignedWrap())
1351bdd1243dSDimitry Andric       NewDiv = BinaryOperator::CreateSDiv(X, Y);
1352bdd1243dSDimitry Andric 
1353bdd1243dSDimitry Andric     // Exact propagates only if both of the original divides are exact.
1354bdd1243dSDimitry Andric     if (NewDiv) {
1355bdd1243dSDimitry Andric       NewDiv->setIsExact(I.isExact() && InnerDiv->isExact());
1356bdd1243dSDimitry Andric       return NewDiv;
1357bdd1243dSDimitry Andric     }
1358bdd1243dSDimitry Andric   }
1359bdd1243dSDimitry Andric 
13605f757f3fSDimitry Andric   // (X * Y) / (X * Z) --> Y / Z (and commuted variants)
13615f757f3fSDimitry Andric   if (match(Op0, m_Mul(m_Value(X), m_Value(Y)))) {
13625f757f3fSDimitry Andric     auto OB0HasNSW = cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap();
13635f757f3fSDimitry Andric     auto OB0HasNUW = cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap();
13645f757f3fSDimitry Andric 
13655f757f3fSDimitry Andric     auto CreateDivOrNull = [&](Value *A, Value *B) -> Instruction * {
13665f757f3fSDimitry Andric       auto OB1HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
13675f757f3fSDimitry Andric       auto OB1HasNUW =
13685f757f3fSDimitry Andric           cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
13695f757f3fSDimitry Andric       const APInt *C1, *C2;
13705f757f3fSDimitry Andric       if (IsSigned && OB0HasNSW) {
13715f757f3fSDimitry Andric         if (OB1HasNSW && match(B, m_APInt(C1)) && !C1->isAllOnes())
13725f757f3fSDimitry Andric           return BinaryOperator::CreateSDiv(A, B);
13735f757f3fSDimitry Andric       }
13745f757f3fSDimitry Andric       if (!IsSigned && OB0HasNUW) {
13755f757f3fSDimitry Andric         if (OB1HasNUW)
13765f757f3fSDimitry Andric           return BinaryOperator::CreateUDiv(A, B);
13775f757f3fSDimitry Andric         if (match(A, m_APInt(C1)) && match(B, m_APInt(C2)) && C2->ule(*C1))
13785f757f3fSDimitry Andric           return BinaryOperator::CreateUDiv(A, B);
13795f757f3fSDimitry Andric       }
13805f757f3fSDimitry Andric       return nullptr;
13815f757f3fSDimitry Andric     };
13825f757f3fSDimitry Andric 
13835f757f3fSDimitry Andric     if (match(Op1, m_c_Mul(m_Specific(X), m_Value(Z)))) {
13845f757f3fSDimitry Andric       if (auto *Val = CreateDivOrNull(Y, Z))
13855f757f3fSDimitry Andric         return Val;
13865f757f3fSDimitry Andric     }
13875f757f3fSDimitry Andric     if (match(Op1, m_c_Mul(m_Specific(Y), m_Value(Z)))) {
13885f757f3fSDimitry Andric       if (auto *Val = CreateDivOrNull(X, Z))
13895f757f3fSDimitry Andric         return Val;
13905f757f3fSDimitry Andric     }
13915f757f3fSDimitry Andric   }
13920b57cec5SDimitry Andric   return nullptr;
13930b57cec5SDimitry Andric }
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric static const unsigned MaxDepth = 6;
13960b57cec5SDimitry Andric 
139781ad6265SDimitry Andric // Take the exact integer log2 of the value. If DoFold is true, create the
139881ad6265SDimitry Andric // actual instructions, otherwise return a non-null dummy value. Return nullptr
139981ad6265SDimitry Andric // on failure.
takeLog2(IRBuilderBase & Builder,Value * Op,unsigned Depth,bool AssumeNonZero,bool DoFold)140081ad6265SDimitry Andric static Value *takeLog2(IRBuilderBase &Builder, Value *Op, unsigned Depth,
1401cbe9438cSDimitry Andric                        bool AssumeNonZero, bool DoFold) {
140281ad6265SDimitry Andric   auto IfFold = [DoFold](function_ref<Value *()> Fn) {
140381ad6265SDimitry Andric     if (!DoFold)
140481ad6265SDimitry Andric       return reinterpret_cast<Value *>(-1);
140581ad6265SDimitry Andric     return Fn();
14060b57cec5SDimitry Andric   };
14070b57cec5SDimitry Andric 
1408e8d8bef9SDimitry Andric   // FIXME: assert that Op1 isn't/doesn't contain undef.
1409e8d8bef9SDimitry Andric 
141081ad6265SDimitry Andric   // log2(2^C) -> C
141181ad6265SDimitry Andric   if (match(Op, m_Power2()))
141281ad6265SDimitry Andric     return IfFold([&]() {
141381ad6265SDimitry Andric       Constant *C = ConstantExpr::getExactLogBase2(cast<Constant>(Op));
141481ad6265SDimitry Andric       if (!C)
141581ad6265SDimitry Andric         llvm_unreachable("Failed to constant fold udiv -> logbase2");
141681ad6265SDimitry Andric       return C;
141781ad6265SDimitry Andric     });
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric   // The remaining tests are all recursive, so bail out if we hit the limit.
14200b57cec5SDimitry Andric   if (Depth++ == MaxDepth)
142181ad6265SDimitry Andric     return nullptr;
14220b57cec5SDimitry Andric 
142381ad6265SDimitry Andric   // log2(zext X) -> zext log2(X)
142481ad6265SDimitry Andric   // FIXME: Require one use?
142581ad6265SDimitry Andric   Value *X, *Y;
142681ad6265SDimitry Andric   if (match(Op, m_ZExt(m_Value(X))))
1427cbe9438cSDimitry Andric     if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
142881ad6265SDimitry Andric       return IfFold([&]() { return Builder.CreateZExt(LogX, Op->getType()); });
142981ad6265SDimitry Andric 
143081ad6265SDimitry Andric   // log2(X << Y) -> log2(X) + Y
143181ad6265SDimitry Andric   // FIXME: Require one use unless X is 1?
1432cbe9438cSDimitry Andric   if (match(Op, m_Shl(m_Value(X), m_Value(Y)))) {
1433cbe9438cSDimitry Andric     auto *BO = cast<OverflowingBinaryOperator>(Op);
1434cbe9438cSDimitry Andric     // nuw will be set if the `shl` is trivially non-zero.
1435cbe9438cSDimitry Andric     if (AssumeNonZero || BO->hasNoUnsignedWrap() || BO->hasNoSignedWrap())
1436cbe9438cSDimitry Andric       if (Value *LogX = takeLog2(Builder, X, Depth, AssumeNonZero, DoFold))
143781ad6265SDimitry Andric         return IfFold([&]() { return Builder.CreateAdd(LogX, Y); });
1438cbe9438cSDimitry Andric   }
143981ad6265SDimitry Andric 
144081ad6265SDimitry Andric   // log2(Cond ? X : Y) -> Cond ? log2(X) : log2(Y)
144181ad6265SDimitry Andric   // FIXME: Require one use?
144281ad6265SDimitry Andric   if (SelectInst *SI = dyn_cast<SelectInst>(Op))
1443cbe9438cSDimitry Andric     if (Value *LogX = takeLog2(Builder, SI->getOperand(1), Depth,
1444cbe9438cSDimitry Andric                                AssumeNonZero, DoFold))
1445cbe9438cSDimitry Andric       if (Value *LogY = takeLog2(Builder, SI->getOperand(2), Depth,
1446cbe9438cSDimitry Andric                                  AssumeNonZero, DoFold))
144781ad6265SDimitry Andric         return IfFold([&]() {
144881ad6265SDimitry Andric           return Builder.CreateSelect(SI->getOperand(0), LogX, LogY);
144981ad6265SDimitry Andric         });
14500b57cec5SDimitry Andric 
145181ad6265SDimitry Andric   // log2(umin(X, Y)) -> umin(log2(X), log2(Y))
145281ad6265SDimitry Andric   // log2(umax(X, Y)) -> umax(log2(X), log2(Y))
145381ad6265SDimitry Andric   auto *MinMax = dyn_cast<MinMaxIntrinsic>(Op);
1454cbe9438cSDimitry Andric   if (MinMax && MinMax->hasOneUse() && !MinMax->isSigned()) {
1455cbe9438cSDimitry Andric     // Use AssumeNonZero as false here. Otherwise we can hit case where
1456cbe9438cSDimitry Andric     // log2(umax(X, Y)) != umax(log2(X), log2(Y)) (because overflow).
1457cbe9438cSDimitry Andric     if (Value *LogX = takeLog2(Builder, MinMax->getLHS(), Depth,
1458cbe9438cSDimitry Andric                                /*AssumeNonZero*/ false, DoFold))
1459cbe9438cSDimitry Andric       if (Value *LogY = takeLog2(Builder, MinMax->getRHS(), Depth,
1460cbe9438cSDimitry Andric                                  /*AssumeNonZero*/ false, DoFold))
146181ad6265SDimitry Andric         return IfFold([&]() {
1462cbe9438cSDimitry Andric           return Builder.CreateBinaryIntrinsic(MinMax->getIntrinsicID(), LogX,
1463cbe9438cSDimitry Andric                                                LogY);
146481ad6265SDimitry Andric         });
1465cbe9438cSDimitry Andric   }
146681ad6265SDimitry Andric 
146781ad6265SDimitry Andric   return nullptr;
14680b57cec5SDimitry Andric }
14690b57cec5SDimitry Andric 
14700b57cec5SDimitry Andric /// If we have zero-extended operands of an unsigned div or rem, we may be able
14710b57cec5SDimitry Andric /// to narrow the operation (sink the zext below the math).
narrowUDivURem(BinaryOperator & I,InstCombinerImpl & IC)14720b57cec5SDimitry Andric static Instruction *narrowUDivURem(BinaryOperator &I,
14735f757f3fSDimitry Andric                                    InstCombinerImpl &IC) {
14740b57cec5SDimitry Andric   Instruction::BinaryOps Opcode = I.getOpcode();
14750b57cec5SDimitry Andric   Value *N = I.getOperand(0);
14760b57cec5SDimitry Andric   Value *D = I.getOperand(1);
14770b57cec5SDimitry Andric   Type *Ty = I.getType();
14780b57cec5SDimitry Andric   Value *X, *Y;
14790b57cec5SDimitry Andric   if (match(N, m_ZExt(m_Value(X))) && match(D, m_ZExt(m_Value(Y))) &&
14800b57cec5SDimitry Andric       X->getType() == Y->getType() && (N->hasOneUse() || D->hasOneUse())) {
14810b57cec5SDimitry Andric     // udiv (zext X), (zext Y) --> zext (udiv X, Y)
14820b57cec5SDimitry Andric     // urem (zext X), (zext Y) --> zext (urem X, Y)
14835f757f3fSDimitry Andric     Value *NarrowOp = IC.Builder.CreateBinOp(Opcode, X, Y);
14840b57cec5SDimitry Andric     return new ZExtInst(NarrowOp, Ty);
14850b57cec5SDimitry Andric   }
14860b57cec5SDimitry Andric 
14870b57cec5SDimitry Andric   Constant *C;
1488bdd1243dSDimitry Andric   if (isa<Instruction>(N) && match(N, m_OneUse(m_ZExt(m_Value(X)))) &&
1489bdd1243dSDimitry Andric       match(D, m_Constant(C))) {
14900b57cec5SDimitry Andric     // If the constant is the same in the smaller type, use the narrow version.
14915f757f3fSDimitry Andric     Constant *TruncC = IC.getLosslessUnsignedTrunc(C, X->getType());
14925f757f3fSDimitry Andric     if (!TruncC)
14930b57cec5SDimitry Andric       return nullptr;
14940b57cec5SDimitry Andric 
14950b57cec5SDimitry Andric     // udiv (zext X), C --> zext (udiv X, C')
14960b57cec5SDimitry Andric     // urem (zext X), C --> zext (urem X, C')
14975f757f3fSDimitry Andric     return new ZExtInst(IC.Builder.CreateBinOp(Opcode, X, TruncC), Ty);
1498bdd1243dSDimitry Andric   }
1499bdd1243dSDimitry Andric   if (isa<Instruction>(D) && match(D, m_OneUse(m_ZExt(m_Value(X)))) &&
1500bdd1243dSDimitry Andric       match(N, m_Constant(C))) {
1501bdd1243dSDimitry Andric     // If the constant is the same in the smaller type, use the narrow version.
15025f757f3fSDimitry Andric     Constant *TruncC = IC.getLosslessUnsignedTrunc(C, X->getType());
15035f757f3fSDimitry Andric     if (!TruncC)
1504bdd1243dSDimitry Andric       return nullptr;
1505bdd1243dSDimitry Andric 
15060b57cec5SDimitry Andric     // udiv C, (zext X) --> zext (udiv C', X)
15070b57cec5SDimitry Andric     // urem C, (zext X) --> zext (urem C', X)
15085f757f3fSDimitry Andric     return new ZExtInst(IC.Builder.CreateBinOp(Opcode, TruncC, X), Ty);
15090b57cec5SDimitry Andric   }
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric   return nullptr;
15120b57cec5SDimitry Andric }
15130b57cec5SDimitry Andric 
visitUDiv(BinaryOperator & I)1514e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) {
1515bdd1243dSDimitry Andric   if (Value *V = simplifyUDivInst(I.getOperand(0), I.getOperand(1), I.isExact(),
15160b57cec5SDimitry Andric                                   SQ.getWithInstruction(&I)))
15170b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
15200b57cec5SDimitry Andric     return X;
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric   // Handle the integer div common cases
15230b57cec5SDimitry Andric   if (Instruction *Common = commonIDivTransforms(I))
15240b57cec5SDimitry Andric     return Common;
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
15270b57cec5SDimitry Andric   Value *X;
15280b57cec5SDimitry Andric   const APInt *C1, *C2;
15290b57cec5SDimitry Andric   if (match(Op0, m_LShr(m_Value(X), m_APInt(C1))) && match(Op1, m_APInt(C2))) {
15300b57cec5SDimitry Andric     // (X lshr C1) udiv C2 --> X udiv (C2 << C1)
15310b57cec5SDimitry Andric     bool Overflow;
15320b57cec5SDimitry Andric     APInt C2ShlC1 = C2->ushl_ov(*C1, Overflow);
15330b57cec5SDimitry Andric     if (!Overflow) {
15340b57cec5SDimitry Andric       bool IsExact = I.isExact() && match(Op0, m_Exact(m_Value()));
15350b57cec5SDimitry Andric       BinaryOperator *BO = BinaryOperator::CreateUDiv(
15360b57cec5SDimitry Andric           X, ConstantInt::get(X->getType(), C2ShlC1));
15370b57cec5SDimitry Andric       if (IsExact)
15380b57cec5SDimitry Andric         BO->setIsExact();
15390b57cec5SDimitry Andric       return BO;
15400b57cec5SDimitry Andric     }
15410b57cec5SDimitry Andric   }
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric   // Op0 / C where C is large (negative) --> zext (Op0 >= C)
15440b57cec5SDimitry Andric   // TODO: Could use isKnownNegative() to handle non-constant values.
15450b57cec5SDimitry Andric   Type *Ty = I.getType();
15460b57cec5SDimitry Andric   if (match(Op1, m_Negative())) {
15470b57cec5SDimitry Andric     Value *Cmp = Builder.CreateICmpUGE(Op0, Op1);
15480b57cec5SDimitry Andric     return CastInst::CreateZExtOrBitCast(Cmp, Ty);
15490b57cec5SDimitry Andric   }
15500b57cec5SDimitry Andric   // Op0 / (sext i1 X) --> zext (Op0 == -1) (if X is 0, the div is undefined)
15510b57cec5SDimitry Andric   if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
15520b57cec5SDimitry Andric     Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::getAllOnesValue(Ty));
15530b57cec5SDimitry Andric     return CastInst::CreateZExtOrBitCast(Cmp, Ty);
15540b57cec5SDimitry Andric   }
15550b57cec5SDimitry Andric 
15565f757f3fSDimitry Andric   if (Instruction *NarrowDiv = narrowUDivURem(I, *this))
15570b57cec5SDimitry Andric     return NarrowDiv;
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   Value *A, *B;
15600b57cec5SDimitry Andric 
1561bdd1243dSDimitry Andric   // Look through a right-shift to find the common factor:
1562bdd1243dSDimitry Andric   // ((Op1 *nuw A) >> B) / Op1 --> A >> B
1563bdd1243dSDimitry Andric   if (match(Op0, m_LShr(m_NUWMul(m_Specific(Op1), m_Value(A)), m_Value(B))) ||
1564bdd1243dSDimitry Andric       match(Op0, m_LShr(m_NUWMul(m_Value(A), m_Specific(Op1)), m_Value(B)))) {
1565bdd1243dSDimitry Andric     Instruction *Lshr = BinaryOperator::CreateLShr(A, B);
1566bdd1243dSDimitry Andric     if (I.isExact() && cast<PossiblyExactOperator>(Op0)->isExact())
1567bdd1243dSDimitry Andric       Lshr->setIsExact();
1568bdd1243dSDimitry Andric     return Lshr;
1569bdd1243dSDimitry Andric   }
1570bdd1243dSDimitry Andric 
157181ad6265SDimitry Andric   // Op1 udiv Op2 -> Op1 lshr log2(Op2), if log2() folds away.
1572cbe9438cSDimitry Andric   if (takeLog2(Builder, Op1, /*Depth*/ 0, /*AssumeNonZero*/ true,
1573cbe9438cSDimitry Andric                /*DoFold*/ false)) {
1574cbe9438cSDimitry Andric     Value *Res = takeLog2(Builder, Op1, /*Depth*/ 0,
1575cbe9438cSDimitry Andric                           /*AssumeNonZero*/ true, /*DoFold*/ true);
157681ad6265SDimitry Andric     return replaceInstUsesWith(
157781ad6265SDimitry Andric         I, Builder.CreateLShr(Op0, Res, I.getName(), I.isExact()));
15780b57cec5SDimitry Andric   }
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric   return nullptr;
15810b57cec5SDimitry Andric }
15820b57cec5SDimitry Andric 
visitSDiv(BinaryOperator & I)1583e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) {
1584bdd1243dSDimitry Andric   if (Value *V = simplifySDivInst(I.getOperand(0), I.getOperand(1), I.isExact(),
15850b57cec5SDimitry Andric                                   SQ.getWithInstruction(&I)))
15860b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
15890b57cec5SDimitry Andric     return X;
15900b57cec5SDimitry Andric 
15910b57cec5SDimitry Andric   // Handle the integer div common cases
15920b57cec5SDimitry Andric   if (Instruction *Common = commonIDivTransforms(I))
15930b57cec5SDimitry Andric     return Common;
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1596e8d8bef9SDimitry Andric   Type *Ty = I.getType();
15970b57cec5SDimitry Andric   Value *X;
15980b57cec5SDimitry Andric   // sdiv Op0, -1 --> -Op0
15990b57cec5SDimitry Andric   // sdiv Op0, (sext i1 X) --> -Op0 (because if X is 0, the op is undefined)
16000b57cec5SDimitry Andric   if (match(Op1, m_AllOnes()) ||
16010b57cec5SDimitry Andric       (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)))
16025f757f3fSDimitry Andric     return BinaryOperator::CreateNSWNeg(Op0);
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric   // X / INT_MIN --> X == INT_MIN
16050b57cec5SDimitry Andric   if (match(Op1, m_SignMask()))
1606e8d8bef9SDimitry Andric     return new ZExtInst(Builder.CreateICmpEQ(Op0, Op1), Ty);
1607e8d8bef9SDimitry Andric 
1608bdd1243dSDimitry Andric   if (I.isExact()) {
1609e8d8bef9SDimitry Andric     // sdiv exact X, 1<<C --> ashr exact X, C   iff  1<<C  is non-negative
1610bdd1243dSDimitry Andric     if (match(Op1, m_Power2()) && match(Op1, m_NonNegative())) {
1611bdd1243dSDimitry Andric       Constant *C = ConstantExpr::getExactLogBase2(cast<Constant>(Op1));
1612bdd1243dSDimitry Andric       return BinaryOperator::CreateExactAShr(Op0, C);
1613bdd1243dSDimitry Andric     }
1614bdd1243dSDimitry Andric 
1615bdd1243dSDimitry Andric     // sdiv exact X, (1<<ShAmt) --> ashr exact X, ShAmt (if shl is non-negative)
1616bdd1243dSDimitry Andric     Value *ShAmt;
1617bdd1243dSDimitry Andric     if (match(Op1, m_NSWShl(m_One(), m_Value(ShAmt))))
1618bdd1243dSDimitry Andric       return BinaryOperator::CreateExactAShr(Op0, ShAmt);
1619bdd1243dSDimitry Andric 
1620e8d8bef9SDimitry Andric     // sdiv exact X, -1<<C --> -(ashr exact X, C)
1621bdd1243dSDimitry Andric     if (match(Op1, m_NegatedPower2())) {
1622bdd1243dSDimitry Andric       Constant *NegPow2C = ConstantExpr::getNeg(cast<Constant>(Op1));
1623bdd1243dSDimitry Andric       Constant *C = ConstantExpr::getExactLogBase2(NegPow2C);
1624bdd1243dSDimitry Andric       Value *Ashr = Builder.CreateAShr(Op0, C, I.getName() + ".neg", true);
16255f757f3fSDimitry Andric       return BinaryOperator::CreateNSWNeg(Ashr);
1626bdd1243dSDimitry Andric     }
1627e8d8bef9SDimitry Andric   }
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric   const APInt *Op1C;
16300b57cec5SDimitry Andric   if (match(Op1, m_APInt(Op1C))) {
16310b57cec5SDimitry Andric     // If the dividend is sign-extended and the constant divisor is small enough
16320b57cec5SDimitry Andric     // to fit in the source type, shrink the division to the narrower type:
16330b57cec5SDimitry Andric     // (sext X) sdiv C --> sext (X sdiv C)
16340b57cec5SDimitry Andric     Value *Op0Src;
16350b57cec5SDimitry Andric     if (match(Op0, m_OneUse(m_SExt(m_Value(Op0Src)))) &&
163606c3fb27SDimitry Andric         Op0Src->getType()->getScalarSizeInBits() >=
163706c3fb27SDimitry Andric             Op1C->getSignificantBits()) {
16380b57cec5SDimitry Andric 
16390b57cec5SDimitry Andric       // In the general case, we need to make sure that the dividend is not the
16400b57cec5SDimitry Andric       // minimum signed value because dividing that by -1 is UB. But here, we
16410b57cec5SDimitry Andric       // know that the -1 divisor case is already handled above.
16420b57cec5SDimitry Andric 
16430b57cec5SDimitry Andric       Constant *NarrowDivisor =
16440b57cec5SDimitry Andric           ConstantExpr::getTrunc(cast<Constant>(Op1), Op0Src->getType());
16450b57cec5SDimitry Andric       Value *NarrowOp = Builder.CreateSDiv(Op0Src, NarrowDivisor);
1646e8d8bef9SDimitry Andric       return new SExtInst(NarrowOp, Ty);
16470b57cec5SDimitry Andric     }
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric     // -X / C --> X / -C (if the negation doesn't overflow).
16500b57cec5SDimitry Andric     // TODO: This could be enhanced to handle arbitrary vector constants by
16510b57cec5SDimitry Andric     //       checking if all elements are not the min-signed-val.
1652*0fca6ea1SDimitry Andric     if (!Op1C->isMinSignedValue() && match(Op0, m_NSWNeg(m_Value(X)))) {
1653e8d8bef9SDimitry Andric       Constant *NegC = ConstantInt::get(Ty, -(*Op1C));
16540b57cec5SDimitry Andric       Instruction *BO = BinaryOperator::CreateSDiv(X, NegC);
16550b57cec5SDimitry Andric       BO->setIsExact(I.isExact());
16560b57cec5SDimitry Andric       return BO;
16570b57cec5SDimitry Andric     }
16580b57cec5SDimitry Andric   }
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric   // -X / Y --> -(X / Y)
16610b57cec5SDimitry Andric   Value *Y;
1662*0fca6ea1SDimitry Andric   if (match(&I, m_SDiv(m_OneUse(m_NSWNeg(m_Value(X))), m_Value(Y))))
16630b57cec5SDimitry Andric     return BinaryOperator::CreateNSWNeg(
16640b57cec5SDimitry Andric         Builder.CreateSDiv(X, Y, I.getName(), I.isExact()));
16650b57cec5SDimitry Andric 
1666e8d8bef9SDimitry Andric   // abs(X) / X --> X > -1 ? 1 : -1
1667e8d8bef9SDimitry Andric   // X / abs(X) --> X > -1 ? 1 : -1
1668e8d8bef9SDimitry Andric   if (match(&I, m_c_BinOp(
1669e8d8bef9SDimitry Andric                     m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(X), m_One())),
1670e8d8bef9SDimitry Andric                     m_Deferred(X)))) {
167181ad6265SDimitry Andric     Value *Cond = Builder.CreateIsNotNeg(X);
167281ad6265SDimitry Andric     return SelectInst::Create(Cond, ConstantInt::get(Ty, 1),
167381ad6265SDimitry Andric                               ConstantInt::getAllOnesValue(Ty));
1674e8d8bef9SDimitry Andric   }
1675e8d8bef9SDimitry Andric 
1676bdd1243dSDimitry Andric   KnownBits KnownDividend = computeKnownBits(Op0, 0, &I);
1677bdd1243dSDimitry Andric   if (!I.isExact() &&
1678bdd1243dSDimitry Andric       (match(Op1, m_Power2(Op1C)) || match(Op1, m_NegatedPower2(Op1C))) &&
167906c3fb27SDimitry Andric       KnownDividend.countMinTrailingZeros() >= Op1C->countr_zero()) {
1680bdd1243dSDimitry Andric     I.setIsExact();
1681bdd1243dSDimitry Andric     return &I;
1682bdd1243dSDimitry Andric   }
1683bdd1243dSDimitry Andric 
1684bdd1243dSDimitry Andric   if (KnownDividend.isNonNegative()) {
1685bdd1243dSDimitry Andric     // If both operands are unsigned, turn this into a udiv.
16865f757f3fSDimitry Andric     if (isKnownNonNegative(Op1, SQ.getWithInstruction(&I))) {
16870b57cec5SDimitry Andric       auto *BO = BinaryOperator::CreateUDiv(Op0, Op1, I.getName());
16880b57cec5SDimitry Andric       BO->setIsExact(I.isExact());
16890b57cec5SDimitry Andric       return BO;
16900b57cec5SDimitry Andric     }
16910b57cec5SDimitry Andric 
1692e8d8bef9SDimitry Andric     if (match(Op1, m_NegatedPower2())) {
1693e8d8bef9SDimitry Andric       // X sdiv (-(1 << C)) -> -(X sdiv (1 << C)) ->
1694e8d8bef9SDimitry Andric       //                    -> -(X udiv (1 << C)) -> -(X u>> C)
169581ad6265SDimitry Andric       Constant *CNegLog2 = ConstantExpr::getExactLogBase2(
169681ad6265SDimitry Andric           ConstantExpr::getNeg(cast<Constant>(Op1)));
169781ad6265SDimitry Andric       Value *Shr = Builder.CreateLShr(Op0, CNegLog2, I.getName(), I.isExact());
169881ad6265SDimitry Andric       return BinaryOperator::CreateNeg(Shr);
1699e8d8bef9SDimitry Andric     }
1700e8d8bef9SDimitry Andric 
17010b57cec5SDimitry Andric     if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
17020b57cec5SDimitry Andric       // X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y)
17030b57cec5SDimitry Andric       // Safe because the only negative value (1 << Y) can take on is
17040b57cec5SDimitry Andric       // INT_MIN, and X sdiv INT_MIN == X udiv INT_MIN == 0 if X doesn't have
17050b57cec5SDimitry Andric       // the sign bit set.
17060b57cec5SDimitry Andric       auto *BO = BinaryOperator::CreateUDiv(Op0, Op1, I.getName());
17070b57cec5SDimitry Andric       BO->setIsExact(I.isExact());
17080b57cec5SDimitry Andric       return BO;
17090b57cec5SDimitry Andric     }
17100b57cec5SDimitry Andric   }
17110b57cec5SDimitry Andric 
17125f757f3fSDimitry Andric   // -X / X --> X == INT_MIN ? 1 : -1
17135f757f3fSDimitry Andric   if (isKnownNegation(Op0, Op1)) {
17145f757f3fSDimitry Andric     APInt MinVal = APInt::getSignedMinValue(Ty->getScalarSizeInBits());
17155f757f3fSDimitry Andric     Value *Cond = Builder.CreateICmpEQ(Op0, ConstantInt::get(Ty, MinVal));
17165f757f3fSDimitry Andric     return SelectInst::Create(Cond, ConstantInt::get(Ty, 1),
17175f757f3fSDimitry Andric                               ConstantInt::getAllOnesValue(Ty));
17185f757f3fSDimitry Andric   }
17190b57cec5SDimitry Andric   return nullptr;
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric 
17220b57cec5SDimitry Andric /// Remove negation and try to convert division into multiplication.
foldFDivConstantDivisor(BinaryOperator & I)1723bdd1243dSDimitry Andric Instruction *InstCombinerImpl::foldFDivConstantDivisor(BinaryOperator &I) {
17240b57cec5SDimitry Andric   Constant *C;
17250b57cec5SDimitry Andric   if (!match(I.getOperand(1), m_Constant(C)))
17260b57cec5SDimitry Andric     return nullptr;
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric   // -X / C --> X / -C
17290b57cec5SDimitry Andric   Value *X;
1730*0fca6ea1SDimitry Andric   const DataLayout &DL = I.getDataLayout();
17310b57cec5SDimitry Andric   if (match(I.getOperand(0), m_FNeg(m_Value(X))))
1732bdd1243dSDimitry Andric     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
1733bdd1243dSDimitry Andric       return BinaryOperator::CreateFDivFMF(X, NegC, &I);
1734bdd1243dSDimitry Andric 
1735bdd1243dSDimitry Andric   // nnan X / +0.0 -> copysign(inf, X)
1736*0fca6ea1SDimitry Andric   // nnan nsz X / -0.0 -> copysign(inf, X)
1737*0fca6ea1SDimitry Andric   if (I.hasNoNaNs() &&
1738*0fca6ea1SDimitry Andric       (match(I.getOperand(1), m_PosZeroFP()) ||
1739*0fca6ea1SDimitry Andric        (I.hasNoSignedZeros() && match(I.getOperand(1), m_AnyZeroFP())))) {
1740bdd1243dSDimitry Andric     IRBuilder<> B(&I);
1741bdd1243dSDimitry Andric     CallInst *CopySign = B.CreateIntrinsic(
1742bdd1243dSDimitry Andric         Intrinsic::copysign, {C->getType()},
1743bdd1243dSDimitry Andric         {ConstantFP::getInfinity(I.getType()), I.getOperand(0)}, &I);
1744bdd1243dSDimitry Andric     CopySign->takeName(&I);
1745bdd1243dSDimitry Andric     return replaceInstUsesWith(I, CopySign);
1746bdd1243dSDimitry Andric   }
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric   // If the constant divisor has an exact inverse, this is always safe. If not,
17490b57cec5SDimitry Andric   // then we can still create a reciprocal if fast-math-flags allow it and the
17500b57cec5SDimitry Andric   // constant is a regular number (not zero, infinite, or denormal).
17510b57cec5SDimitry Andric   if (!(C->hasExactInverseFP() || (I.hasAllowReciprocal() && C->isNormalFP())))
17520b57cec5SDimitry Andric     return nullptr;
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric   // Disallow denormal constants because we don't know what would happen
17550b57cec5SDimitry Andric   // on all targets.
17560b57cec5SDimitry Andric   // TODO: Use Intrinsic::canonicalize or let function attributes tell us that
17570b57cec5SDimitry Andric   // denorms are flushed?
1758753f127fSDimitry Andric   auto *RecipC = ConstantFoldBinaryOpOperands(
1759753f127fSDimitry Andric       Instruction::FDiv, ConstantFP::get(I.getType(), 1.0), C, DL);
1760753f127fSDimitry Andric   if (!RecipC || !RecipC->isNormalFP())
17610b57cec5SDimitry Andric     return nullptr;
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric   // X / C --> X * (1 / C)
17640b57cec5SDimitry Andric   return BinaryOperator::CreateFMulFMF(I.getOperand(0), RecipC, &I);
17650b57cec5SDimitry Andric }
17660b57cec5SDimitry Andric 
17670b57cec5SDimitry Andric /// Remove negation and try to reassociate constant math.
foldFDivConstantDividend(BinaryOperator & I)17680b57cec5SDimitry Andric static Instruction *foldFDivConstantDividend(BinaryOperator &I) {
17690b57cec5SDimitry Andric   Constant *C;
17700b57cec5SDimitry Andric   if (!match(I.getOperand(0), m_Constant(C)))
17710b57cec5SDimitry Andric     return nullptr;
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric   // C / -X --> -C / X
17740b57cec5SDimitry Andric   Value *X;
1775*0fca6ea1SDimitry Andric   const DataLayout &DL = I.getDataLayout();
17760b57cec5SDimitry Andric   if (match(I.getOperand(1), m_FNeg(m_Value(X))))
1777bdd1243dSDimitry Andric     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
1778bdd1243dSDimitry Andric       return BinaryOperator::CreateFDivFMF(NegC, X, &I);
17790b57cec5SDimitry Andric 
17800b57cec5SDimitry Andric   if (!I.hasAllowReassoc() || !I.hasAllowReciprocal())
17810b57cec5SDimitry Andric     return nullptr;
17820b57cec5SDimitry Andric 
17830b57cec5SDimitry Andric   // Try to reassociate C / X expressions where X includes another constant.
17840b57cec5SDimitry Andric   Constant *C2, *NewC = nullptr;
17850b57cec5SDimitry Andric   if (match(I.getOperand(1), m_FMul(m_Value(X), m_Constant(C2)))) {
17860b57cec5SDimitry Andric     // C / (X * C2) --> (C / C2) / X
1787753f127fSDimitry Andric     NewC = ConstantFoldBinaryOpOperands(Instruction::FDiv, C, C2, DL);
17880b57cec5SDimitry Andric   } else if (match(I.getOperand(1), m_FDiv(m_Value(X), m_Constant(C2)))) {
17890b57cec5SDimitry Andric     // C / (X / C2) --> (C * C2) / X
1790753f127fSDimitry Andric     NewC = ConstantFoldBinaryOpOperands(Instruction::FMul, C, C2, DL);
17910b57cec5SDimitry Andric   }
17920b57cec5SDimitry Andric   // Disallow denormal constants because we don't know what would happen
17930b57cec5SDimitry Andric   // on all targets.
17940b57cec5SDimitry Andric   // TODO: Use Intrinsic::canonicalize or let function attributes tell us that
17950b57cec5SDimitry Andric   // denorms are flushed?
17960b57cec5SDimitry Andric   if (!NewC || !NewC->isNormalFP())
17970b57cec5SDimitry Andric     return nullptr;
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric   return BinaryOperator::CreateFDivFMF(NewC, X, &I);
18000b57cec5SDimitry Andric }
18010b57cec5SDimitry Andric 
1802fe6060f1SDimitry Andric /// Negate the exponent of pow/exp to fold division-by-pow() into multiply.
foldFDivPowDivisor(BinaryOperator & I,InstCombiner::BuilderTy & Builder)1803fe6060f1SDimitry Andric static Instruction *foldFDivPowDivisor(BinaryOperator &I,
1804fe6060f1SDimitry Andric                                        InstCombiner::BuilderTy &Builder) {
1805fe6060f1SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1806fe6060f1SDimitry Andric   auto *II = dyn_cast<IntrinsicInst>(Op1);
1807fe6060f1SDimitry Andric   if (!II || !II->hasOneUse() || !I.hasAllowReassoc() ||
1808fe6060f1SDimitry Andric       !I.hasAllowReciprocal())
1809fe6060f1SDimitry Andric     return nullptr;
1810fe6060f1SDimitry Andric 
1811fe6060f1SDimitry Andric   // Z / pow(X, Y) --> Z * pow(X, -Y)
1812fe6060f1SDimitry Andric   // Z / exp{2}(Y) --> Z * exp{2}(-Y)
1813fe6060f1SDimitry Andric   // In the general case, this creates an extra instruction, but fmul allows
1814fe6060f1SDimitry Andric   // for better canonicalization and optimization than fdiv.
1815fe6060f1SDimitry Andric   Intrinsic::ID IID = II->getIntrinsicID();
1816fe6060f1SDimitry Andric   SmallVector<Value *> Args;
1817fe6060f1SDimitry Andric   switch (IID) {
1818fe6060f1SDimitry Andric   case Intrinsic::pow:
1819fe6060f1SDimitry Andric     Args.push_back(II->getArgOperand(0));
1820fe6060f1SDimitry Andric     Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(1), &I));
1821fe6060f1SDimitry Andric     break;
1822fe6060f1SDimitry Andric   case Intrinsic::powi: {
1823fe6060f1SDimitry Andric     // Require 'ninf' assuming that makes powi(X, -INT_MIN) acceptable.
1824fe6060f1SDimitry Andric     // That is, X ** (huge negative number) is 0.0, ~1.0, or INF and so
1825fe6060f1SDimitry Andric     // dividing by that is INF, ~1.0, or 0.0. Code that uses powi allows
1826fe6060f1SDimitry Andric     // non-standard results, so this corner case should be acceptable if the
1827fe6060f1SDimitry Andric     // code rules out INF values.
1828fe6060f1SDimitry Andric     if (!I.hasNoInfs())
1829fe6060f1SDimitry Andric       return nullptr;
1830fe6060f1SDimitry Andric     Args.push_back(II->getArgOperand(0));
1831fe6060f1SDimitry Andric     Args.push_back(Builder.CreateNeg(II->getArgOperand(1)));
1832fe6060f1SDimitry Andric     Type *Tys[] = {I.getType(), II->getArgOperand(1)->getType()};
1833fe6060f1SDimitry Andric     Value *Pow = Builder.CreateIntrinsic(IID, Tys, Args, &I);
1834fe6060f1SDimitry Andric     return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
1835fe6060f1SDimitry Andric   }
1836fe6060f1SDimitry Andric   case Intrinsic::exp:
1837fe6060f1SDimitry Andric   case Intrinsic::exp2:
1838fe6060f1SDimitry Andric     Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(0), &I));
1839fe6060f1SDimitry Andric     break;
1840fe6060f1SDimitry Andric   default:
1841fe6060f1SDimitry Andric     return nullptr;
1842fe6060f1SDimitry Andric   }
1843fe6060f1SDimitry Andric   Value *Pow = Builder.CreateIntrinsic(IID, I.getType(), Args, &I);
1844fe6060f1SDimitry Andric   return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
1845fe6060f1SDimitry Andric }
1846fe6060f1SDimitry Andric 
1847*0fca6ea1SDimitry Andric /// Convert div to mul if we have an sqrt divisor iff sqrt's operand is a fdiv
1848*0fca6ea1SDimitry Andric /// instruction.
foldFDivSqrtDivisor(BinaryOperator & I,InstCombiner::BuilderTy & Builder)1849*0fca6ea1SDimitry Andric static Instruction *foldFDivSqrtDivisor(BinaryOperator &I,
1850*0fca6ea1SDimitry Andric                                         InstCombiner::BuilderTy &Builder) {
1851*0fca6ea1SDimitry Andric   // X / sqrt(Y / Z) -->  X * sqrt(Z / Y)
1852*0fca6ea1SDimitry Andric   if (!I.hasAllowReassoc() || !I.hasAllowReciprocal())
1853*0fca6ea1SDimitry Andric     return nullptr;
1854*0fca6ea1SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
1855*0fca6ea1SDimitry Andric   auto *II = dyn_cast<IntrinsicInst>(Op1);
1856*0fca6ea1SDimitry Andric   if (!II || II->getIntrinsicID() != Intrinsic::sqrt || !II->hasOneUse() ||
1857*0fca6ea1SDimitry Andric       !II->hasAllowReassoc() || !II->hasAllowReciprocal())
1858*0fca6ea1SDimitry Andric     return nullptr;
1859*0fca6ea1SDimitry Andric 
1860*0fca6ea1SDimitry Andric   Value *Y, *Z;
1861*0fca6ea1SDimitry Andric   auto *DivOp = dyn_cast<Instruction>(II->getOperand(0));
1862*0fca6ea1SDimitry Andric   if (!DivOp)
1863*0fca6ea1SDimitry Andric     return nullptr;
1864*0fca6ea1SDimitry Andric   if (!match(DivOp, m_FDiv(m_Value(Y), m_Value(Z))))
1865*0fca6ea1SDimitry Andric     return nullptr;
1866*0fca6ea1SDimitry Andric   if (!DivOp->hasAllowReassoc() || !I.hasAllowReciprocal() ||
1867*0fca6ea1SDimitry Andric       !DivOp->hasOneUse())
1868*0fca6ea1SDimitry Andric     return nullptr;
1869*0fca6ea1SDimitry Andric   Value *SwapDiv = Builder.CreateFDivFMF(Z, Y, DivOp);
1870*0fca6ea1SDimitry Andric   Value *NewSqrt =
1871*0fca6ea1SDimitry Andric       Builder.CreateUnaryIntrinsic(II->getIntrinsicID(), SwapDiv, II);
1872*0fca6ea1SDimitry Andric   return BinaryOperator::CreateFMulFMF(Op0, NewSqrt, &I);
1873*0fca6ea1SDimitry Andric }
1874*0fca6ea1SDimitry Andric 
visitFDiv(BinaryOperator & I)1875e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
187681ad6265SDimitry Andric   Module *M = I.getModule();
187781ad6265SDimitry Andric 
187881ad6265SDimitry Andric   if (Value *V = simplifyFDivInst(I.getOperand(0), I.getOperand(1),
18790b57cec5SDimitry Andric                                   I.getFastMathFlags(),
18800b57cec5SDimitry Andric                                   SQ.getWithInstruction(&I)))
18810b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
18840b57cec5SDimitry Andric     return X;
18850b57cec5SDimitry Andric 
188604eeddc0SDimitry Andric   if (Instruction *Phi = foldBinopWithPhiOperands(I))
188704eeddc0SDimitry Andric     return Phi;
188804eeddc0SDimitry Andric 
18890b57cec5SDimitry Andric   if (Instruction *R = foldFDivConstantDivisor(I))
18900b57cec5SDimitry Andric     return R;
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric   if (Instruction *R = foldFDivConstantDividend(I))
18930b57cec5SDimitry Andric     return R;
18940b57cec5SDimitry Andric 
18955ffd83dbSDimitry Andric   if (Instruction *R = foldFPSignBitOps(I))
18965ffd83dbSDimitry Andric     return R;
18975ffd83dbSDimitry Andric 
18980b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
18990b57cec5SDimitry Andric   if (isa<Constant>(Op0))
19000b57cec5SDimitry Andric     if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
19010b57cec5SDimitry Andric       if (Instruction *R = FoldOpIntoSelect(I, SI))
19020b57cec5SDimitry Andric         return R;
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   if (isa<Constant>(Op1))
19050b57cec5SDimitry Andric     if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
19060b57cec5SDimitry Andric       if (Instruction *R = FoldOpIntoSelect(I, SI))
19070b57cec5SDimitry Andric         return R;
19080b57cec5SDimitry Andric 
19090b57cec5SDimitry Andric   if (I.hasAllowReassoc() && I.hasAllowReciprocal()) {
19100b57cec5SDimitry Andric     Value *X, *Y;
19110b57cec5SDimitry Andric     if (match(Op0, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) &&
19120b57cec5SDimitry Andric         (!isa<Constant>(Y) || !isa<Constant>(Op1))) {
19130b57cec5SDimitry Andric       // (X / Y) / Z => X / (Y * Z)
19140b57cec5SDimitry Andric       Value *YZ = Builder.CreateFMulFMF(Y, Op1, &I);
19150b57cec5SDimitry Andric       return BinaryOperator::CreateFDivFMF(X, YZ, &I);
19160b57cec5SDimitry Andric     }
19170b57cec5SDimitry Andric     if (match(Op1, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) &&
19180b57cec5SDimitry Andric         (!isa<Constant>(Y) || !isa<Constant>(Op0))) {
19190b57cec5SDimitry Andric       // Z / (X / Y) => (Y * Z) / X
19200b57cec5SDimitry Andric       Value *YZ = Builder.CreateFMulFMF(Y, Op0, &I);
19210b57cec5SDimitry Andric       return BinaryOperator::CreateFDivFMF(YZ, X, &I);
19220b57cec5SDimitry Andric     }
1923480093f4SDimitry Andric     // Z / (1.0 / Y) => (Y * Z)
1924480093f4SDimitry Andric     //
1925480093f4SDimitry Andric     // This is a special case of Z / (X / Y) => (Y * Z) / X, with X = 1.0. The
1926480093f4SDimitry Andric     // m_OneUse check is avoided because even in the case of the multiple uses
1927480093f4SDimitry Andric     // for 1.0/Y, the number of instructions remain the same and a division is
1928480093f4SDimitry Andric     // replaced by a multiplication.
1929480093f4SDimitry Andric     if (match(Op1, m_FDiv(m_SpecificFP(1.0), m_Value(Y))))
1930480093f4SDimitry Andric       return BinaryOperator::CreateFMulFMF(Y, Op0, &I);
19310b57cec5SDimitry Andric   }
19320b57cec5SDimitry Andric 
19330b57cec5SDimitry Andric   if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) {
19340b57cec5SDimitry Andric     // sin(X) / cos(X) -> tan(X)
19350b57cec5SDimitry Andric     // cos(X) / sin(X) -> 1/tan(X) (cotangent)
19360b57cec5SDimitry Andric     Value *X;
19370b57cec5SDimitry Andric     bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) &&
19380b57cec5SDimitry Andric                  match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X)));
19390b57cec5SDimitry Andric     bool IsCot =
19400b57cec5SDimitry Andric         !IsTan && match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
19410b57cec5SDimitry Andric                   match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
19420b57cec5SDimitry Andric 
194381ad6265SDimitry Andric     if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
194481ad6265SDimitry Andric                                        LibFunc_tanf, LibFunc_tanl)) {
19450b57cec5SDimitry Andric       IRBuilder<> B(&I);
19460b57cec5SDimitry Andric       IRBuilder<>::FastMathFlagGuard FMFGuard(B);
19470b57cec5SDimitry Andric       B.setFastMathFlags(I.getFastMathFlags());
19480b57cec5SDimitry Andric       AttributeList Attrs =
19490b57cec5SDimitry Andric           cast<CallBase>(Op0)->getCalledFunction()->getAttributes();
19500b57cec5SDimitry Andric       Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
19510b57cec5SDimitry Andric                                         LibFunc_tanl, B, Attrs);
19520b57cec5SDimitry Andric       if (IsCot)
19530b57cec5SDimitry Andric         Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
19540b57cec5SDimitry Andric       return replaceInstUsesWith(I, Res);
19550b57cec5SDimitry Andric     }
19560b57cec5SDimitry Andric   }
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   // X / (X * Y) --> 1.0 / Y
19590b57cec5SDimitry Andric   // Reassociate to (X / X -> 1.0) is legal when NaNs are not allowed.
19600b57cec5SDimitry Andric   // We can ignore the possibility that X is infinity because INF/INF is NaN.
19615ffd83dbSDimitry Andric   Value *X, *Y;
19620b57cec5SDimitry Andric   if (I.hasNoNaNs() && I.hasAllowReassoc() &&
19630b57cec5SDimitry Andric       match(Op1, m_c_FMul(m_Specific(Op0), m_Value(Y)))) {
19645ffd83dbSDimitry Andric     replaceOperand(I, 0, ConstantFP::get(I.getType(), 1.0));
19655ffd83dbSDimitry Andric     replaceOperand(I, 1, Y);
19660b57cec5SDimitry Andric     return &I;
19670b57cec5SDimitry Andric   }
19680b57cec5SDimitry Andric 
19698bcb0991SDimitry Andric   // X / fabs(X) -> copysign(1.0, X)
19708bcb0991SDimitry Andric   // fabs(X) / X -> copysign(1.0, X)
19718bcb0991SDimitry Andric   if (I.hasNoNaNs() && I.hasNoInfs() &&
1972e8d8bef9SDimitry Andric       (match(&I, m_FDiv(m_Value(X), m_FAbs(m_Deferred(X)))) ||
1973e8d8bef9SDimitry Andric        match(&I, m_FDiv(m_FAbs(m_Value(X)), m_Deferred(X))))) {
19748bcb0991SDimitry Andric     Value *V = Builder.CreateBinaryIntrinsic(
19758bcb0991SDimitry Andric         Intrinsic::copysign, ConstantFP::get(I.getType(), 1.0), X, &I);
19768bcb0991SDimitry Andric     return replaceInstUsesWith(I, V);
19778bcb0991SDimitry Andric   }
1978fe6060f1SDimitry Andric 
1979fe6060f1SDimitry Andric   if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
1980fe6060f1SDimitry Andric     return Mul;
1981fe6060f1SDimitry Andric 
1982*0fca6ea1SDimitry Andric   if (Instruction *Mul = foldFDivSqrtDivisor(I, Builder))
1983*0fca6ea1SDimitry Andric     return Mul;
1984*0fca6ea1SDimitry Andric 
1985bdd1243dSDimitry Andric   // pow(X, Y) / X --> pow(X, Y-1)
1986bdd1243dSDimitry Andric   if (I.hasAllowReassoc() &&
1987bdd1243dSDimitry Andric       match(Op0, m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Specific(Op1),
1988bdd1243dSDimitry Andric                                                       m_Value(Y))))) {
1989bdd1243dSDimitry Andric     Value *Y1 =
1990bdd1243dSDimitry Andric         Builder.CreateFAddFMF(Y, ConstantFP::get(I.getType(), -1.0), &I);
1991bdd1243dSDimitry Andric     Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, Op1, Y1, &I);
1992bdd1243dSDimitry Andric     return replaceInstUsesWith(I, Pow);
1993bdd1243dSDimitry Andric   }
1994bdd1243dSDimitry Andric 
1995*0fca6ea1SDimitry Andric   if (Instruction *FoldedPowi = foldPowiReassoc(I))
1996*0fca6ea1SDimitry Andric     return FoldedPowi;
19975f757f3fSDimitry Andric 
19980b57cec5SDimitry Andric   return nullptr;
19990b57cec5SDimitry Andric }
20000b57cec5SDimitry Andric 
200106c3fb27SDimitry Andric // Variety of transform for:
200206c3fb27SDimitry Andric //  (urem/srem (mul X, Y), (mul X, Z))
200306c3fb27SDimitry Andric //  (urem/srem (shl X, Y), (shl X, Z))
200406c3fb27SDimitry Andric //  (urem/srem (shl Y, X), (shl Z, X))
200506c3fb27SDimitry Andric // NB: The shift cases are really just extensions of the mul case. We treat
200606c3fb27SDimitry Andric // shift as Val * (1 << Amt).
simplifyIRemMulShl(BinaryOperator & I,InstCombinerImpl & IC)200706c3fb27SDimitry Andric static Instruction *simplifyIRemMulShl(BinaryOperator &I,
200806c3fb27SDimitry Andric                                        InstCombinerImpl &IC) {
200906c3fb27SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *X = nullptr;
201006c3fb27SDimitry Andric   APInt Y, Z;
201106c3fb27SDimitry Andric   bool ShiftByX = false;
201206c3fb27SDimitry Andric 
201306c3fb27SDimitry Andric   // If V is not nullptr, it will be matched using m_Specific.
201406c3fb27SDimitry Andric   auto MatchShiftOrMulXC = [](Value *Op, Value *&V, APInt &C) -> bool {
201506c3fb27SDimitry Andric     const APInt *Tmp = nullptr;
201606c3fb27SDimitry Andric     if ((!V && match(Op, m_Mul(m_Value(V), m_APInt(Tmp)))) ||
201706c3fb27SDimitry Andric         (V && match(Op, m_Mul(m_Specific(V), m_APInt(Tmp)))))
201806c3fb27SDimitry Andric       C = *Tmp;
201906c3fb27SDimitry Andric     else if ((!V && match(Op, m_Shl(m_Value(V), m_APInt(Tmp)))) ||
202006c3fb27SDimitry Andric              (V && match(Op, m_Shl(m_Specific(V), m_APInt(Tmp)))))
202106c3fb27SDimitry Andric       C = APInt(Tmp->getBitWidth(), 1) << *Tmp;
202206c3fb27SDimitry Andric     if (Tmp != nullptr)
202306c3fb27SDimitry Andric       return true;
202406c3fb27SDimitry Andric 
202506c3fb27SDimitry Andric     // Reset `V` so we don't start with specific value on next match attempt.
202606c3fb27SDimitry Andric     V = nullptr;
202706c3fb27SDimitry Andric     return false;
202806c3fb27SDimitry Andric   };
202906c3fb27SDimitry Andric 
203006c3fb27SDimitry Andric   auto MatchShiftCX = [](Value *Op, APInt &C, Value *&V) -> bool {
203106c3fb27SDimitry Andric     const APInt *Tmp = nullptr;
203206c3fb27SDimitry Andric     if ((!V && match(Op, m_Shl(m_APInt(Tmp), m_Value(V)))) ||
203306c3fb27SDimitry Andric         (V && match(Op, m_Shl(m_APInt(Tmp), m_Specific(V))))) {
203406c3fb27SDimitry Andric       C = *Tmp;
203506c3fb27SDimitry Andric       return true;
203606c3fb27SDimitry Andric     }
203706c3fb27SDimitry Andric 
203806c3fb27SDimitry Andric     // Reset `V` so we don't start with specific value on next match attempt.
203906c3fb27SDimitry Andric     V = nullptr;
204006c3fb27SDimitry Andric     return false;
204106c3fb27SDimitry Andric   };
204206c3fb27SDimitry Andric 
204306c3fb27SDimitry Andric   if (MatchShiftOrMulXC(Op0, X, Y) && MatchShiftOrMulXC(Op1, X, Z)) {
204406c3fb27SDimitry Andric     // pass
204506c3fb27SDimitry Andric   } else if (MatchShiftCX(Op0, Y, X) && MatchShiftCX(Op1, Z, X)) {
204606c3fb27SDimitry Andric     ShiftByX = true;
204706c3fb27SDimitry Andric   } else {
204806c3fb27SDimitry Andric     return nullptr;
204906c3fb27SDimitry Andric   }
205006c3fb27SDimitry Andric 
205106c3fb27SDimitry Andric   bool IsSRem = I.getOpcode() == Instruction::SRem;
205206c3fb27SDimitry Andric 
205306c3fb27SDimitry Andric   OverflowingBinaryOperator *BO0 = cast<OverflowingBinaryOperator>(Op0);
205406c3fb27SDimitry Andric   // TODO: We may be able to deduce more about nsw/nuw of BO0/BO1 based on Y >=
205506c3fb27SDimitry Andric   // Z or Z >= Y.
205606c3fb27SDimitry Andric   bool BO0HasNSW = BO0->hasNoSignedWrap();
205706c3fb27SDimitry Andric   bool BO0HasNUW = BO0->hasNoUnsignedWrap();
205806c3fb27SDimitry Andric   bool BO0NoWrap = IsSRem ? BO0HasNSW : BO0HasNUW;
205906c3fb27SDimitry Andric 
206006c3fb27SDimitry Andric   APInt RemYZ = IsSRem ? Y.srem(Z) : Y.urem(Z);
206106c3fb27SDimitry Andric   // (rem (mul nuw/nsw X, Y), (mul X, Z))
206206c3fb27SDimitry Andric   //      if (rem Y, Z) == 0
206306c3fb27SDimitry Andric   //          -> 0
206406c3fb27SDimitry Andric   if (RemYZ.isZero() && BO0NoWrap)
206506c3fb27SDimitry Andric     return IC.replaceInstUsesWith(I, ConstantInt::getNullValue(I.getType()));
206606c3fb27SDimitry Andric 
206706c3fb27SDimitry Andric   // Helper function to emit either (RemSimplificationC << X) or
206806c3fb27SDimitry Andric   // (RemSimplificationC * X) depending on whether we matched Op0/Op1 as
206906c3fb27SDimitry Andric   // (shl V, X) or (mul V, X) respectively.
207006c3fb27SDimitry Andric   auto CreateMulOrShift =
207106c3fb27SDimitry Andric       [&](const APInt &RemSimplificationC) -> BinaryOperator * {
207206c3fb27SDimitry Andric     Value *RemSimplification =
207306c3fb27SDimitry Andric         ConstantInt::get(I.getType(), RemSimplificationC);
207406c3fb27SDimitry Andric     return ShiftByX ? BinaryOperator::CreateShl(RemSimplification, X)
207506c3fb27SDimitry Andric                     : BinaryOperator::CreateMul(X, RemSimplification);
207606c3fb27SDimitry Andric   };
207706c3fb27SDimitry Andric 
207806c3fb27SDimitry Andric   OverflowingBinaryOperator *BO1 = cast<OverflowingBinaryOperator>(Op1);
207906c3fb27SDimitry Andric   bool BO1HasNSW = BO1->hasNoSignedWrap();
208006c3fb27SDimitry Andric   bool BO1HasNUW = BO1->hasNoUnsignedWrap();
208106c3fb27SDimitry Andric   bool BO1NoWrap = IsSRem ? BO1HasNSW : BO1HasNUW;
208206c3fb27SDimitry Andric   // (rem (mul X, Y), (mul nuw/nsw X, Z))
208306c3fb27SDimitry Andric   //      if (rem Y, Z) == Y
208406c3fb27SDimitry Andric   //          -> (mul nuw/nsw X, Y)
208506c3fb27SDimitry Andric   if (RemYZ == Y && BO1NoWrap) {
208606c3fb27SDimitry Andric     BinaryOperator *BO = CreateMulOrShift(Y);
208706c3fb27SDimitry Andric     // Copy any overflow flags from Op0.
208806c3fb27SDimitry Andric     BO->setHasNoSignedWrap(IsSRem || BO0HasNSW);
208906c3fb27SDimitry Andric     BO->setHasNoUnsignedWrap(!IsSRem || BO0HasNUW);
209006c3fb27SDimitry Andric     return BO;
209106c3fb27SDimitry Andric   }
209206c3fb27SDimitry Andric 
209306c3fb27SDimitry Andric   // (rem (mul nuw/nsw X, Y), (mul {nsw} X, Z))
209406c3fb27SDimitry Andric   //      if Y >= Z
209506c3fb27SDimitry Andric   //          -> (mul {nuw} nsw X, (rem Y, Z))
209606c3fb27SDimitry Andric   if (Y.uge(Z) && (IsSRem ? (BO0HasNSW && BO1HasNSW) : BO0HasNUW)) {
209706c3fb27SDimitry Andric     BinaryOperator *BO = CreateMulOrShift(RemYZ);
209806c3fb27SDimitry Andric     BO->setHasNoSignedWrap();
209906c3fb27SDimitry Andric     BO->setHasNoUnsignedWrap(BO0HasNUW);
210006c3fb27SDimitry Andric     return BO;
210106c3fb27SDimitry Andric   }
210206c3fb27SDimitry Andric 
210306c3fb27SDimitry Andric   return nullptr;
210406c3fb27SDimitry Andric }
210506c3fb27SDimitry Andric 
21060b57cec5SDimitry Andric /// This function implements the transforms common to both integer remainder
21070b57cec5SDimitry Andric /// instructions (urem and srem). It is called by the visitors to those integer
21080b57cec5SDimitry Andric /// remainder instructions.
21090b57cec5SDimitry Andric /// Common integer remainder transforms
commonIRemTransforms(BinaryOperator & I)2110e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::commonIRemTransforms(BinaryOperator &I) {
211104eeddc0SDimitry Andric   if (Instruction *Phi = foldBinopWithPhiOperands(I))
211204eeddc0SDimitry Andric     return Phi;
211304eeddc0SDimitry Andric 
21140b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric   // The RHS is known non-zero.
21175ffd83dbSDimitry Andric   if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this, I))
21185ffd83dbSDimitry Andric     return replaceOperand(I, 1, V);
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric   // Handle cases involving: rem X, (select Cond, Y, Z)
21210b57cec5SDimitry Andric   if (simplifyDivRemOfSelectWithZeroOp(I))
21220b57cec5SDimitry Andric     return &I;
21230b57cec5SDimitry Andric 
21240eae32dcSDimitry Andric   // If the divisor is a select-of-constants, try to constant fold all rem ops:
21250eae32dcSDimitry Andric   // C % (select Cond, TrueC, FalseC) --> select Cond, (C % TrueC), (C % FalseC)
21260eae32dcSDimitry Andric   // TODO: Adapt simplifyDivRemOfSelectWithZeroOp to allow this and other folds.
21270eae32dcSDimitry Andric   if (match(Op0, m_ImmConstant()) &&
21280eae32dcSDimitry Andric       match(Op1, m_Select(m_Value(), m_ImmConstant(), m_ImmConstant()))) {
212981ad6265SDimitry Andric     if (Instruction *R = FoldOpIntoSelect(I, cast<SelectInst>(Op1),
213081ad6265SDimitry Andric                                           /*FoldWithMultiUse*/ true))
21310eae32dcSDimitry Andric       return R;
21320eae32dcSDimitry Andric   }
21330eae32dcSDimitry Andric 
21340b57cec5SDimitry Andric   if (isa<Constant>(Op1)) {
21350b57cec5SDimitry Andric     if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
21360b57cec5SDimitry Andric       if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
21370b57cec5SDimitry Andric         if (Instruction *R = FoldOpIntoSelect(I, SI))
21380b57cec5SDimitry Andric           return R;
21390b57cec5SDimitry Andric       } else if (auto *PN = dyn_cast<PHINode>(Op0I)) {
21400b57cec5SDimitry Andric         const APInt *Op1Int;
21410b57cec5SDimitry Andric         if (match(Op1, m_APInt(Op1Int)) && !Op1Int->isMinValue() &&
21420b57cec5SDimitry Andric             (I.getOpcode() == Instruction::URem ||
21430b57cec5SDimitry Andric              !Op1Int->isMinSignedValue())) {
21440b57cec5SDimitry Andric           // foldOpIntoPhi will speculate instructions to the end of the PHI's
21450b57cec5SDimitry Andric           // predecessor blocks, so do this only if we know the srem or urem
21460b57cec5SDimitry Andric           // will not fault.
21470b57cec5SDimitry Andric           if (Instruction *NV = foldOpIntoPhi(I, PN))
21480b57cec5SDimitry Andric             return NV;
21490b57cec5SDimitry Andric         }
21500b57cec5SDimitry Andric       }
21510b57cec5SDimitry Andric 
21520b57cec5SDimitry Andric       // See if we can fold away this rem instruction.
21530b57cec5SDimitry Andric       if (SimplifyDemandedInstructionBits(I))
21540b57cec5SDimitry Andric         return &I;
21550b57cec5SDimitry Andric     }
21560b57cec5SDimitry Andric   }
21570b57cec5SDimitry Andric 
215806c3fb27SDimitry Andric   if (Instruction *R = simplifyIRemMulShl(I, *this))
215906c3fb27SDimitry Andric     return R;
216006c3fb27SDimitry Andric 
21610b57cec5SDimitry Andric   return nullptr;
21620b57cec5SDimitry Andric }
21630b57cec5SDimitry Andric 
visitURem(BinaryOperator & I)2164e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitURem(BinaryOperator &I) {
216581ad6265SDimitry Andric   if (Value *V = simplifyURemInst(I.getOperand(0), I.getOperand(1),
21660b57cec5SDimitry Andric                                   SQ.getWithInstruction(&I)))
21670b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
21680b57cec5SDimitry Andric 
21690b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
21700b57cec5SDimitry Andric     return X;
21710b57cec5SDimitry Andric 
21720b57cec5SDimitry Andric   if (Instruction *common = commonIRemTransforms(I))
21730b57cec5SDimitry Andric     return common;
21740b57cec5SDimitry Andric 
21755f757f3fSDimitry Andric   if (Instruction *NarrowRem = narrowUDivURem(I, *this))
21760b57cec5SDimitry Andric     return NarrowRem;
21770b57cec5SDimitry Andric 
21780b57cec5SDimitry Andric   // X urem Y -> X and Y-1, where Y is a power of 2,
21790b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
21800b57cec5SDimitry Andric   Type *Ty = I.getType();
21810b57cec5SDimitry Andric   if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
21828bcb0991SDimitry Andric     // This may increase instruction count, we don't enforce that Y is a
21838bcb0991SDimitry Andric     // constant.
21840b57cec5SDimitry Andric     Constant *N1 = Constant::getAllOnesValue(Ty);
21850b57cec5SDimitry Andric     Value *Add = Builder.CreateAdd(Op1, N1);
21860b57cec5SDimitry Andric     return BinaryOperator::CreateAnd(Op0, Add);
21870b57cec5SDimitry Andric   }
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric   // 1 urem X -> zext(X != 1)
2190480093f4SDimitry Andric   if (match(Op0, m_One())) {
2191480093f4SDimitry Andric     Value *Cmp = Builder.CreateICmpNE(Op1, ConstantInt::get(Ty, 1));
2192480093f4SDimitry Andric     return CastInst::CreateZExtOrBitCast(Cmp, Ty);
2193480093f4SDimitry Andric   }
21940b57cec5SDimitry Andric 
219581ad6265SDimitry Andric   // Op0 urem C -> Op0 < C ? Op0 : Op0 - C, where C >= signbit.
219681ad6265SDimitry Andric   // Op0 must be frozen because we are increasing its number of uses.
21970b57cec5SDimitry Andric   if (match(Op1, m_Negative())) {
2198*0fca6ea1SDimitry Andric     Value *F0 = Op0;
2199*0fca6ea1SDimitry Andric     if (!isGuaranteedNotToBeUndef(Op0))
2200*0fca6ea1SDimitry Andric       F0 = Builder.CreateFreeze(Op0, Op0->getName() + ".fr");
220181ad6265SDimitry Andric     Value *Cmp = Builder.CreateICmpULT(F0, Op1);
220281ad6265SDimitry Andric     Value *Sub = Builder.CreateSub(F0, Op1);
220381ad6265SDimitry Andric     return SelectInst::Create(Cmp, F0, Sub);
22040b57cec5SDimitry Andric   }
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric   // If the divisor is a sext of a boolean, then the divisor must be max
22070b57cec5SDimitry Andric   // unsigned value (-1). Therefore, the remainder is Op0 unless Op0 is also
22080b57cec5SDimitry Andric   // max unsigned value. In that case, the remainder is 0:
22090b57cec5SDimitry Andric   // urem Op0, (sext i1 X) --> (Op0 == -1) ? 0 : Op0
22100b57cec5SDimitry Andric   Value *X;
22110b57cec5SDimitry Andric   if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
2212*0fca6ea1SDimitry Andric     Value *FrozenOp0 = Op0;
2213*0fca6ea1SDimitry Andric     if (!isGuaranteedNotToBeUndef(Op0))
2214*0fca6ea1SDimitry Andric       FrozenOp0 = Builder.CreateFreeze(Op0, Op0->getName() + ".frozen");
221506c3fb27SDimitry Andric     Value *Cmp =
221606c3fb27SDimitry Andric         Builder.CreateICmpEQ(FrozenOp0, ConstantInt::getAllOnesValue(Ty));
221706c3fb27SDimitry Andric     return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), FrozenOp0);
221806c3fb27SDimitry Andric   }
221906c3fb27SDimitry Andric 
222006c3fb27SDimitry Andric   // For "(X + 1) % Op1" and if (X u< Op1) => (X + 1) == Op1 ? 0 : X + 1 .
222106c3fb27SDimitry Andric   if (match(Op0, m_Add(m_Value(X), m_One()))) {
222206c3fb27SDimitry Andric     Value *Val =
222306c3fb27SDimitry Andric         simplifyICmpInst(ICmpInst::ICMP_ULT, X, Op1, SQ.getWithInstruction(&I));
222406c3fb27SDimitry Andric     if (Val && match(Val, m_One())) {
2225*0fca6ea1SDimitry Andric       Value *FrozenOp0 = Op0;
2226*0fca6ea1SDimitry Andric       if (!isGuaranteedNotToBeUndef(Op0))
2227*0fca6ea1SDimitry Andric         FrozenOp0 = Builder.CreateFreeze(Op0, Op0->getName() + ".frozen");
222806c3fb27SDimitry Andric       Value *Cmp = Builder.CreateICmpEQ(FrozenOp0, Op1);
222906c3fb27SDimitry Andric       return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), FrozenOp0);
223006c3fb27SDimitry Andric     }
22310b57cec5SDimitry Andric   }
22320b57cec5SDimitry Andric 
22330b57cec5SDimitry Andric   return nullptr;
22340b57cec5SDimitry Andric }
22350b57cec5SDimitry Andric 
visitSRem(BinaryOperator & I)2236e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitSRem(BinaryOperator &I) {
223781ad6265SDimitry Andric   if (Value *V = simplifySRemInst(I.getOperand(0), I.getOperand(1),
22380b57cec5SDimitry Andric                                   SQ.getWithInstruction(&I)))
22390b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
22420b57cec5SDimitry Andric     return X;
22430b57cec5SDimitry Andric 
22440b57cec5SDimitry Andric   // Handle the integer rem common cases
22450b57cec5SDimitry Andric   if (Instruction *Common = commonIRemTransforms(I))
22460b57cec5SDimitry Andric     return Common;
22470b57cec5SDimitry Andric 
22480b57cec5SDimitry Andric   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
22490b57cec5SDimitry Andric   {
22500b57cec5SDimitry Andric     const APInt *Y;
22510b57cec5SDimitry Andric     // X % -Y -> X % Y
22525ffd83dbSDimitry Andric     if (match(Op1, m_Negative(Y)) && !Y->isMinSignedValue())
22535ffd83dbSDimitry Andric       return replaceOperand(I, 1, ConstantInt::get(I.getType(), -*Y));
22540b57cec5SDimitry Andric   }
22550b57cec5SDimitry Andric 
22560b57cec5SDimitry Andric   // -X srem Y --> -(X srem Y)
22570b57cec5SDimitry Andric   Value *X, *Y;
2258*0fca6ea1SDimitry Andric   if (match(&I, m_SRem(m_OneUse(m_NSWNeg(m_Value(X))), m_Value(Y))))
22590b57cec5SDimitry Andric     return BinaryOperator::CreateNSWNeg(Builder.CreateSRem(X, Y));
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric   // If the sign bits of both operands are zero (i.e. we can prove they are
22620b57cec5SDimitry Andric   // unsigned inputs), turn this into a urem.
22630b57cec5SDimitry Andric   APInt Mask(APInt::getSignMask(I.getType()->getScalarSizeInBits()));
22640b57cec5SDimitry Andric   if (MaskedValueIsZero(Op1, Mask, 0, &I) &&
22650b57cec5SDimitry Andric       MaskedValueIsZero(Op0, Mask, 0, &I)) {
22660b57cec5SDimitry Andric     // X srem Y -> X urem Y, iff X and Y don't have sign bit set
22670b57cec5SDimitry Andric     return BinaryOperator::CreateURem(Op0, Op1, I.getName());
22680b57cec5SDimitry Andric   }
22690b57cec5SDimitry Andric 
22700b57cec5SDimitry Andric   // If it's a constant vector, flip any negative values positive.
22710b57cec5SDimitry Andric   if (isa<ConstantVector>(Op1) || isa<ConstantDataVector>(Op1)) {
22720b57cec5SDimitry Andric     Constant *C = cast<Constant>(Op1);
2273e8d8bef9SDimitry Andric     unsigned VWidth = cast<FixedVectorType>(C->getType())->getNumElements();
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric     bool hasNegative = false;
22760b57cec5SDimitry Andric     bool hasMissing = false;
22770b57cec5SDimitry Andric     for (unsigned i = 0; i != VWidth; ++i) {
22780b57cec5SDimitry Andric       Constant *Elt = C->getAggregateElement(i);
22790b57cec5SDimitry Andric       if (!Elt) {
22800b57cec5SDimitry Andric         hasMissing = true;
22810b57cec5SDimitry Andric         break;
22820b57cec5SDimitry Andric       }
22830b57cec5SDimitry Andric 
22840b57cec5SDimitry Andric       if (ConstantInt *RHS = dyn_cast<ConstantInt>(Elt))
22850b57cec5SDimitry Andric         if (RHS->isNegative())
22860b57cec5SDimitry Andric           hasNegative = true;
22870b57cec5SDimitry Andric     }
22880b57cec5SDimitry Andric 
22890b57cec5SDimitry Andric     if (hasNegative && !hasMissing) {
22900b57cec5SDimitry Andric       SmallVector<Constant *, 16> Elts(VWidth);
22910b57cec5SDimitry Andric       for (unsigned i = 0; i != VWidth; ++i) {
22920b57cec5SDimitry Andric         Elts[i] = C->getAggregateElement(i);  // Handle undef, etc.
22930b57cec5SDimitry Andric         if (ConstantInt *RHS = dyn_cast<ConstantInt>(Elts[i])) {
22940b57cec5SDimitry Andric           if (RHS->isNegative())
22950b57cec5SDimitry Andric             Elts[i] = cast<ConstantInt>(ConstantExpr::getNeg(RHS));
22960b57cec5SDimitry Andric         }
22970b57cec5SDimitry Andric       }
22980b57cec5SDimitry Andric 
22990b57cec5SDimitry Andric       Constant *NewRHSV = ConstantVector::get(Elts);
23005ffd83dbSDimitry Andric       if (NewRHSV != C)  // Don't loop on -MININT
23015ffd83dbSDimitry Andric         return replaceOperand(I, 1, NewRHSV);
23020b57cec5SDimitry Andric     }
23030b57cec5SDimitry Andric   }
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric   return nullptr;
23060b57cec5SDimitry Andric }
23070b57cec5SDimitry Andric 
visitFRem(BinaryOperator & I)2308e8d8bef9SDimitry Andric Instruction *InstCombinerImpl::visitFRem(BinaryOperator &I) {
230981ad6265SDimitry Andric   if (Value *V = simplifyFRemInst(I.getOperand(0), I.getOperand(1),
23100b57cec5SDimitry Andric                                   I.getFastMathFlags(),
23110b57cec5SDimitry Andric                                   SQ.getWithInstruction(&I)))
23120b57cec5SDimitry Andric     return replaceInstUsesWith(I, V);
23130b57cec5SDimitry Andric 
23140b57cec5SDimitry Andric   if (Instruction *X = foldVectorBinop(I))
23150b57cec5SDimitry Andric     return X;
23160b57cec5SDimitry Andric 
231704eeddc0SDimitry Andric   if (Instruction *Phi = foldBinopWithPhiOperands(I))
231804eeddc0SDimitry Andric     return Phi;
231904eeddc0SDimitry Andric 
23200b57cec5SDimitry Andric   return nullptr;
23210b57cec5SDimitry Andric }
2322