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. 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(). 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. 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 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 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 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 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 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. 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. 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. 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 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 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. 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). 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 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 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. 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. 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. 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. 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 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). 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 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 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 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 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