/// foldFMulConst() is a helper routine of InstCombiner::visitFMul(). /// The input \p FMulOrDiv is a FMul/FDiv with one and only one operand /// being a constant (i.e. isFMulOrFDivWithConstant(FMulOrDiv) == true). /// This function is to simplify "FMulOrDiv * C" and returns the /// resulting expression. Note that this function could return NULL in /// case the constants cannot be folded into a normal floating-point. /// Value *InstCombiner::foldFMulConst(Instruction *FMulOrDiv, Constant *C, Instruction *InsertBefore) { assert(isFMulOrFDivWithConstant(FMulOrDiv) && "V is invalid"); Value *Opnd0 = FMulOrDiv->getOperand(0); Value *Opnd1 = FMulOrDiv->getOperand(1); Constant *C0 = dyn_cast<Constant>(Opnd0); Constant *C1 = dyn_cast<Constant>(Opnd1); BinaryOperator *R = nullptr; // (X * C0) * C => X * (C0*C) if (FMulOrDiv->getOpcode() == Instruction::FMul) { Constant *F = ConstantExpr::getFMul(C1 ? C1 : C0, C); if (isNormalFp(F)) R = BinaryOperator::CreateFMul(C1 ? Opnd0 : Opnd1, F); } else { if (C0) { // (C0 / X) * C => (C0 * C) / X if (FMulOrDiv->hasOneUse()) { // It would otherwise introduce another div. Constant *F = ConstantExpr::getFMul(C0, C); if (isNormalFp(F)) R = BinaryOperator::CreateFDiv(F, Opnd1); } } else { // (X / C1) * C => X * (C/C1) if C/C1 is not a denormal Constant *F = ConstantExpr::getFDiv(C, C1); if (isNormalFp(F)) { R = BinaryOperator::CreateFMul(Opnd0, F); } else { // (X / C1) * C => X / (C1/C) Constant *F = ConstantExpr::getFDiv(C1, C); if (isNormalFp(F)) R = BinaryOperator::CreateFDiv(Opnd0, F); } } } if (R) { R->setHasUnsafeAlgebra(true); InsertNewInstWith(R, *InsertBefore); } return R; }