2010-01-05 14:09:35 +08:00
|
|
|
//===- InstCombineMulDivRem.cpp -------------------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-01-05 14:09:35 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the visit functions for mul, fmul, sdiv, udiv, fdiv,
|
|
|
|
// srem, urem, frem.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-01-22 13:25:13 +08:00
|
|
|
#include "InstCombineInternal.h"
|
2017-10-25 05:24:53 +08:00
|
|
|
#include "llvm/ADT/APFloat.h"
|
|
|
|
#include "llvm/ADT/APInt.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2010-12-21 22:00:22 +08:00
|
|
|
#include "llvm/Analysis/InstructionSimplify.h"
|
2017-10-25 05:24:53 +08:00
|
|
|
#include "llvm/IR/BasicBlock.h"
|
|
|
|
#include "llvm/IR/Constant.h"
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
2017-10-25 05:24:53 +08:00
|
|
|
#include "llvm/IR/Intrinsics.h"
|
|
|
|
#include "llvm/IR/Operator.h"
|
2014-03-04 19:08:18 +08:00
|
|
|
#include "llvm/IR/PatternMatch.h"
|
2017-10-25 05:24:53 +08:00
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/KnownBits.h"
|
2020-06-03 21:56:40 +08:00
|
|
|
#include "llvm/Transforms/InstCombine/InstCombiner.h"
|
2018-01-11 14:33:00 +08:00
|
|
|
#include "llvm/Transforms/Utils/BuildLibCalls.h"
|
2017-10-25 05:24:53 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <utility>
|
|
|
|
|
2021-09-22 15:19:01 +08:00
|
|
|
#define DEBUG_TYPE "instcombine"
|
|
|
|
#include "llvm/Transforms/Utils/InstructionWorklist.h"
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
using namespace llvm;
|
|
|
|
using namespace PatternMatch;
|
|
|
|
|
2015-09-09 23:24:36 +08:00
|
|
|
/// The specific integer value is used in a context where it is known to be
|
|
|
|
/// non-zero. If this allows us to simplify the computation, do so and return
|
|
|
|
/// the new operand, otherwise return null.
|
2020-06-03 21:56:40 +08:00
|
|
|
static Value *simplifyValueKnownNonZero(Value *V, InstCombinerImpl &IC,
|
2015-03-10 10:37:25 +08:00
|
|
|
Instruction &CxtI) {
|
Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to
transform:
A / ((1 << B) >>u 2)
into:
A >>u (B-2)
which we compile into:
_divu3: ## @divu3
leal -2(%rsi), %ecx
shrl %cl, %edi
movl %edi, %eax
ret
instead of:
_divu3: ## @divu3
movb %sil, %cl
movl $1, %esi
shll %cl, %esi
shrl $2, %esi
movl %edi, %eax
xorl %edx, %edx
divl %esi, %eax
ret
llvm-svn: 131860
2011-05-23 02:18:41 +08:00
|
|
|
// If V has multiple uses, then we would have to do more analysis to determine
|
|
|
|
// if this is safe. For example, the use could be in dynamically unreached
|
|
|
|
// code.
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!V->hasOneUse()) return nullptr;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2011-05-23 08:32:19 +08:00
|
|
|
bool MadeChange = false;
|
|
|
|
|
|
|
|
// ((1 << A) >>u B) --> (1 << (A-B))
|
|
|
|
// Because V cannot be zero, we know that B is less than A.
|
2014-10-15 04:28:40 +08:00
|
|
|
Value *A = nullptr, *B = nullptr, *One = nullptr;
|
|
|
|
if (match(V, m_LShr(m_OneUse(m_Shl(m_Value(One), m_Value(A))), m_Value(B))) &&
|
|
|
|
match(One, m_One())) {
|
2017-07-08 07:16:26 +08:00
|
|
|
A = IC.Builder.CreateSub(A, B);
|
|
|
|
return IC.Builder.CreateShl(One, A);
|
2011-05-23 08:32:19 +08:00
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2011-05-23 08:21:50 +08:00
|
|
|
// (PowerOfTwo >>u B) --> isExact since shifting out the result would make it
|
|
|
|
// inexact. Similarly for <<.
|
2016-05-23 01:08:52 +08:00
|
|
|
BinaryOperator *I = dyn_cast<BinaryOperator>(V);
|
|
|
|
if (I && I->isLogicalShift() &&
|
2017-05-26 05:51:12 +08:00
|
|
|
IC.isKnownToBeAPowerOfTwo(I->getOperand(0), false, 0, &CxtI)) {
|
2016-05-23 01:08:52 +08:00
|
|
|
// We know that this is an exact/nuw shift and that the input is a
|
|
|
|
// non-zero context as well.
|
|
|
|
if (Value *V2 = simplifyValueKnownNonZero(I->getOperand(0), IC, CxtI)) {
|
2020-03-31 04:00:16 +08:00
|
|
|
IC.replaceOperand(*I, 0, V2);
|
2016-05-23 01:08:52 +08:00
|
|
|
MadeChange = true;
|
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2016-05-23 01:08:52 +08:00
|
|
|
if (I->getOpcode() == Instruction::LShr && !I->isExact()) {
|
|
|
|
I->setIsExact();
|
|
|
|
MadeChange = true;
|
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2016-05-23 01:08:52 +08:00
|
|
|
if (I->getOpcode() == Instruction::Shl && !I->hasNoUnsignedWrap()) {
|
|
|
|
I->setHasNoUnsignedWrap();
|
|
|
|
MadeChange = true;
|
2011-05-23 08:21:50 +08:00
|
|
|
}
|
2016-05-23 01:08:52 +08:00
|
|
|
}
|
2011-05-23 08:32:19 +08:00
|
|
|
|
2011-05-23 02:26:48 +08:00
|
|
|
// TODO: Lots more we could do here:
|
|
|
|
// If V is a phi node, we can call this on each of its operands.
|
|
|
|
// "select cond, X, 0" can simplify to "X".
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return MadeChange ? V : nullptr;
|
Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to
transform:
A / ((1 << B) >>u 2)
into:
A >>u (B-2)
which we compile into:
_divu3: ## @divu3
leal -2(%rsi), %ecx
shrl %cl, %edi
movl %edi, %eax
ret
instead of:
_divu3: ## @divu3
movb %sil, %cl
movl $1, %esi
shll %cl, %esi
shrl $2, %esi
movl %edi, %eax
xorl %edx, %edx
divl %esi, %eax
ret
llvm-svn: 131860
2011-05-23 02:18:41 +08:00
|
|
|
}
|
|
|
|
|
2019-10-06 22:15:48 +08:00
|
|
|
// TODO: This is a specific form of a much more general pattern.
|
|
|
|
// We could detect a select with any binop identity constant, or we
|
|
|
|
// could use SimplifyBinOp to see if either arm of the select reduces.
|
|
|
|
// But that needs to be done carefully and/or while removing potential
|
|
|
|
// reverse canonicalizations as in InstCombiner::foldSelectIntoOp().
|
|
|
|
static Value *foldMulSelectToNegate(BinaryOperator &I,
|
|
|
|
InstCombiner::BuilderTy &Builder) {
|
|
|
|
Value *Cond, *OtherOp;
|
|
|
|
|
|
|
|
// mul (select Cond, 1, -1), OtherOp --> select Cond, OtherOp, -OtherOp
|
|
|
|
// mul OtherOp, (select Cond, 1, -1) --> select Cond, OtherOp, -OtherOp
|
|
|
|
if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes())),
|
2021-10-13 00:18:29 +08:00
|
|
|
m_Value(OtherOp)))) {
|
|
|
|
bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap();
|
|
|
|
Value *Neg = Builder.CreateNeg(OtherOp, "", false, HasAnyNoWrap);
|
|
|
|
return Builder.CreateSelect(Cond, OtherOp, Neg);
|
|
|
|
}
|
2019-10-06 22:15:48 +08:00
|
|
|
// mul (select Cond, -1, 1), OtherOp --> select Cond, -OtherOp, OtherOp
|
|
|
|
// mul OtherOp, (select Cond, -1, 1) --> select Cond, -OtherOp, OtherOp
|
|
|
|
if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One())),
|
2021-10-13 00:18:29 +08:00
|
|
|
m_Value(OtherOp)))) {
|
|
|
|
bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap();
|
|
|
|
Value *Neg = Builder.CreateNeg(OtherOp, "", false, HasAnyNoWrap);
|
|
|
|
return Builder.CreateSelect(Cond, Neg, OtherOp);
|
|
|
|
}
|
2019-10-06 22:15:48 +08:00
|
|
|
|
|
|
|
// fmul (select Cond, 1.0, -1.0), OtherOp --> select Cond, OtherOp, -OtherOp
|
|
|
|
// fmul OtherOp, (select Cond, 1.0, -1.0) --> select Cond, OtherOp, -OtherOp
|
|
|
|
if (match(&I, m_c_FMul(m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(1.0),
|
|
|
|
m_SpecificFP(-1.0))),
|
|
|
|
m_Value(OtherOp)))) {
|
|
|
|
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
|
|
|
|
Builder.setFastMathFlags(I.getFastMathFlags());
|
|
|
|
return Builder.CreateSelect(Cond, OtherOp, Builder.CreateFNeg(OtherOp));
|
|
|
|
}
|
|
|
|
|
|
|
|
// fmul (select Cond, -1.0, 1.0), OtherOp --> select Cond, -OtherOp, OtherOp
|
|
|
|
// fmul OtherOp, (select Cond, -1.0, 1.0) --> select Cond, -OtherOp, OtherOp
|
|
|
|
if (match(&I, m_c_FMul(m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(-1.0),
|
|
|
|
m_SpecificFP(1.0))),
|
|
|
|
m_Value(OtherOp)))) {
|
|
|
|
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
|
|
|
|
Builder.setFastMathFlags(I.getFastMathFlags());
|
|
|
|
return Builder.CreateSelect(Cond, Builder.CreateFNeg(OtherOp), OtherOp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifyMulInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2018-07-13 09:18:07 +08:00
|
|
|
if (SimplifyAssociativeOrCommutative(I))
|
|
|
|
return &I;
|
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2010-12-22 21:36:08 +08:00
|
|
|
if (Value *V = SimplifyUsingDistributiveLaws(I))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2010-12-22 21:36:08 +08:00
|
|
|
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
[InstCombine] Transform abs pattern using multiplication to abs intrinsic (PR45691)
```
unsigned r(int v)
{
return (1 | -(v < 0)) * v;
}
`r` is equivalent to `abs(v)`.
```
```
define <4 x i8> @src(<4 x i8> %0) {
%1:
%2 = ashr <4 x i8> %0, { 31, undef, 31, 31 }
%3 = or <4 x i8> %2, { 1, 1, 1, undef }
%4 = mul nsw <4 x i8> %3, %0
ret <4 x i8> %4
}
=>
define <4 x i8> @tgt(<4 x i8> %0) {
%1:
%2 = icmp slt <4 x i8> %0, { 0, 0, 0, 0 }
%3 = sub nsw <4 x i8> { 0, 0, 0, 0 }, %0
%4 = select <4 x i1> %2, <4 x i8> %3, <4 x i8> %0
ret <4 x i8> %4
}
Transformation seems to be correct!
```
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D94874
2021-01-18 00:06:06 +08:00
|
|
|
unsigned BitWidth = I.getType()->getScalarSizeInBits();
|
|
|
|
|
|
|
|
// X * -1 == 0 - X
|
2014-11-22 12:52:38 +08:00
|
|
|
if (match(Op1, m_AllOnes())) {
|
|
|
|
BinaryOperator *BO = BinaryOperator::CreateNeg(Op0, I.getName());
|
|
|
|
if (I.hasNoSignedWrap())
|
|
|
|
BO->setHasNoSignedWrap();
|
|
|
|
return BO;
|
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2013-05-31 22:27:15 +08:00
|
|
|
// Also allow combining multiply instructions on vectors.
|
|
|
|
{
|
|
|
|
Value *NewOp;
|
|
|
|
Constant *C1, *C2;
|
|
|
|
const APInt *IVal;
|
|
|
|
if (match(&I, m_Mul(m_Shl(m_Value(NewOp), m_Constant(C2)),
|
|
|
|
m_Constant(C1))) &&
|
2014-11-22 12:52:52 +08:00
|
|
|
match(C1, m_APInt(IVal))) {
|
|
|
|
// ((X << C2)*C1) == (X * (C1 << C2))
|
|
|
|
Constant *Shl = ConstantExpr::getShl(C1, C2);
|
|
|
|
BinaryOperator *Mul = cast<BinaryOperator>(I.getOperand(0));
|
|
|
|
BinaryOperator *BO = BinaryOperator::CreateMul(NewOp, Shl);
|
|
|
|
if (I.hasNoUnsignedWrap() && Mul->hasNoUnsignedWrap())
|
|
|
|
BO->setHasNoUnsignedWrap();
|
|
|
|
if (I.hasNoSignedWrap() && Mul->hasNoSignedWrap() &&
|
|
|
|
Shl->isNotMinSignedValue())
|
|
|
|
BO->setHasNoSignedWrap();
|
|
|
|
return BO;
|
|
|
|
}
|
2013-05-31 22:27:15 +08:00
|
|
|
|
|
|
|
if (match(&I, m_Mul(m_Value(NewOp), m_Constant(C1)))) {
|
2018-02-08 22:10:01 +08:00
|
|
|
// Replace X*(2^C) with X << C, where C is either a scalar or a vector.
|
2020-10-11 17:31:17 +08:00
|
|
|
if (Constant *NewCst = ConstantExpr::getExactLogBase2(C1)) {
|
2013-05-31 22:27:15 +08:00
|
|
|
BinaryOperator *Shl = BinaryOperator::CreateShl(NewOp, NewCst);
|
2014-10-07 18:19:34 +08:00
|
|
|
|
|
|
|
if (I.hasNoUnsignedWrap())
|
|
|
|
Shl->setHasNoUnsignedWrap();
|
2015-04-18 12:41:30 +08:00
|
|
|
if (I.hasNoSignedWrap()) {
|
2017-06-28 03:57:53 +08:00
|
|
|
const APInt *V;
|
2018-09-12 01:57:20 +08:00
|
|
|
if (match(NewCst, m_APInt(V)) && *V != V->getBitWidth() - 1)
|
2015-04-18 12:41:30 +08:00
|
|
|
Shl->setHasNoSignedWrap();
|
|
|
|
}
|
2014-10-07 18:19:34 +08:00
|
|
|
|
2013-05-31 22:27:15 +08:00
|
|
|
return Shl;
|
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
2013-05-31 22:27:15 +08:00
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2020-08-07 02:10:43 +08:00
|
|
|
if (Op0->hasOneUse() && match(Op1, m_NegatedPower2())) {
|
|
|
|
// Interpret X * (-1<<C) as (-X) * (1<<C) and try to sink the negation.
|
|
|
|
// The "* (1<<C)" thus becomes a potential shifting opportunity.
|
2020-08-07 04:04:05 +08:00
|
|
|
if (Value *NegOp0 = Negator::Negate(/*IsNegation*/ true, Op0, *this))
|
2020-08-07 02:10:43 +08:00
|
|
|
return BinaryOperator::CreateMul(
|
|
|
|
NegOp0, ConstantExpr::getNeg(cast<Constant>(Op1)), I.getName());
|
2011-02-10 13:36:31 +08:00
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2018-03-01 00:36:24 +08:00
|
|
|
if (Instruction *FoldedMul = foldBinOpIntoSelectOrPhi(I))
|
|
|
|
return FoldedMul;
|
|
|
|
|
2019-10-06 22:15:48 +08:00
|
|
|
if (Value *FoldedMul = foldMulSelectToNegate(I, Builder))
|
|
|
|
return replaceInstUsesWith(I, FoldedMul);
|
[InstCombine] fold negate disguised as select+mul
Name: negate if true
%sel = select i1 %cond, i32 -1, i32 1
%r = mul i32 %sel, %x
=>
%m = sub i32 0, %x
%r = select i1 %cond, i32 %m, i32 %x
Name: negate if false
%sel = select i1 %cond, i32 1, i32 -1
%r = mul i32 %sel, %x
=>
%m = sub i32 0, %x
%r = select i1 %cond, i32 %x, i32 %m
https://rise4fun.com/Alive/Nlh
llvm-svn: 373230
2019-10-01 01:02:26 +08:00
|
|
|
|
2011-02-10 13:36:31 +08:00
|
|
|
// Simplify mul instructions with a constant RHS.
|
2013-04-06 05:20:12 +08:00
|
|
|
if (isa<Constant>(Op1)) {
|
2014-01-19 23:24:22 +08:00
|
|
|
// Canonicalize (X+C1)*CI -> X*CI+C1*CI.
|
2018-03-01 00:36:24 +08:00
|
|
|
Value *X;
|
|
|
|
Constant *C1;
|
|
|
|
if (match(Op0, m_OneUse(m_Add(m_Value(X), m_Constant(C1))))) {
|
|
|
|
Value *Mul = Builder.CreateMul(C1, Op1);
|
|
|
|
// Only go forward with the transform if C1*CI simplifies to a tidier
|
|
|
|
// constant.
|
|
|
|
if (!match(Mul, m_Mul(m_Value(), m_Value())))
|
|
|
|
return BinaryOperator::CreateAdd(Builder.CreateMul(X, Op1), Mul);
|
2014-01-19 23:24:22 +08:00
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2020-05-04 22:21:52 +08:00
|
|
|
// abs(X) * abs(X) -> X * X
|
|
|
|
// nabs(X) * nabs(X) -> X * X
|
|
|
|
if (Op0 == Op1) {
|
|
|
|
Value *X, *Y;
|
|
|
|
SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor;
|
|
|
|
if (SPF == SPF_ABS || SPF == SPF_NABS)
|
|
|
|
return BinaryOperator::CreateMul(X, X);
|
2020-09-05 18:37:45 +08:00
|
|
|
|
|
|
|
if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
|
|
|
|
return BinaryOperator::CreateMul(X, X);
|
2020-05-04 22:21:52 +08:00
|
|
|
}
|
|
|
|
|
2018-02-15 00:50:55 +08:00
|
|
|
// -X * C --> X * -C
|
|
|
|
Value *X, *Y;
|
|
|
|
Constant *Op1C;
|
|
|
|
if (match(Op0, m_Neg(m_Value(X))) && match(Op1, m_Constant(Op1C)))
|
|
|
|
return BinaryOperator::CreateMul(X, ConstantExpr::getNeg(Op1C));
|
|
|
|
|
|
|
|
// -X * -Y --> X * Y
|
|
|
|
if (match(Op0, m_Neg(m_Value(X))) && match(Op1, m_Neg(m_Value(Y)))) {
|
|
|
|
auto *NewMul = BinaryOperator::CreateMul(X, Y);
|
|
|
|
if (I.hasNoSignedWrap() &&
|
|
|
|
cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap() &&
|
|
|
|
cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap())
|
|
|
|
NewMul->setHasNoSignedWrap();
|
|
|
|
return NewMul;
|
2014-11-22 15:25:19 +08:00
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2019-01-01 09:09:20 +08:00
|
|
|
// -X * Y --> -(X * Y)
|
|
|
|
// X * -Y --> -(X * Y)
|
|
|
|
if (match(&I, m_c_Mul(m_OneUse(m_Neg(m_Value(X))), m_Value(Y))))
|
|
|
|
return BinaryOperator::CreateNeg(Builder.CreateMul(X, Y));
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// (X / Y) * Y = X - (X % Y)
|
|
|
|
// (X / Y) * -Y = (X % Y) - X
|
|
|
|
{
|
2017-03-15 01:27:27 +08:00
|
|
|
Value *Y = Op1;
|
|
|
|
BinaryOperator *Div = dyn_cast<BinaryOperator>(Op0);
|
|
|
|
if (!Div || (Div->getOpcode() != Instruction::UDiv &&
|
|
|
|
Div->getOpcode() != Instruction::SDiv)) {
|
|
|
|
Y = Op0;
|
|
|
|
Div = dyn_cast<BinaryOperator>(Op1);
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
2017-03-15 01:27:27 +08:00
|
|
|
Value *Neg = dyn_castNegVal(Y);
|
|
|
|
if (Div && Div->hasOneUse() &&
|
|
|
|
(Div->getOperand(1) == Y || Div->getOperand(1) == Neg) &&
|
|
|
|
(Div->getOpcode() == Instruction::UDiv ||
|
|
|
|
Div->getOpcode() == Instruction::SDiv)) {
|
|
|
|
Value *X = Div->getOperand(0), *DivOp1 = Div->getOperand(1);
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2011-02-07 05:44:57 +08:00
|
|
|
// If the division is exact, X % Y is zero, so we end up with X or -X.
|
2017-03-15 01:27:27 +08:00
|
|
|
if (Div->isExact()) {
|
|
|
|
if (DivOp1 == Y)
|
|
|
|
return replaceInstUsesWith(I, X);
|
|
|
|
return BinaryOperator::CreateNeg(X);
|
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2017-03-15 01:27:27 +08:00
|
|
|
auto RemOpc = Div->getOpcode() == Instruction::UDiv ? Instruction::URem
|
|
|
|
: Instruction::SRem;
|
2017-07-08 07:16:26 +08:00
|
|
|
Value *Rem = Builder.CreateBinOp(RemOpc, X, DivOp1);
|
2017-03-15 01:27:27 +08:00
|
|
|
if (DivOp1 == Y)
|
|
|
|
return BinaryOperator::CreateSub(X, Rem);
|
|
|
|
return BinaryOperator::CreateSub(Rem, X);
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// i1 mul -> i1 and.
|
2017-07-09 15:04:03 +08:00
|
|
|
if (I.getType()->isIntOrIntVectorTy(1))
|
2010-01-05 14:09:35 +08:00
|
|
|
return BinaryOperator::CreateAnd(Op0, Op1);
|
|
|
|
|
|
|
|
// X*(1 << Y) --> X << Y
|
|
|
|
// (1 << Y)*X --> X << Y
|
|
|
|
{
|
|
|
|
Value *Y;
|
2014-11-22 16:57:02 +08:00
|
|
|
BinaryOperator *BO = nullptr;
|
|
|
|
bool ShlNSW = false;
|
|
|
|
if (match(Op0, m_Shl(m_One(), m_Value(Y)))) {
|
|
|
|
BO = BinaryOperator::CreateShl(Op1, Y);
|
2015-01-04 15:36:02 +08:00
|
|
|
ShlNSW = cast<ShlOperator>(Op0)->hasNoSignedWrap();
|
2014-11-25 00:41:13 +08:00
|
|
|
} else if (match(Op1, m_Shl(m_One(), m_Value(Y)))) {
|
2014-11-22 16:57:02 +08:00
|
|
|
BO = BinaryOperator::CreateShl(Op0, Y);
|
2015-01-04 15:36:02 +08:00
|
|
|
ShlNSW = cast<ShlOperator>(Op1)->hasNoSignedWrap();
|
2014-11-22 16:57:02 +08:00
|
|
|
}
|
|
|
|
if (BO) {
|
|
|
|
if (I.hasNoUnsignedWrap())
|
|
|
|
BO->setHasNoUnsignedWrap();
|
|
|
|
if (I.hasNoSignedWrap() && ShlNSW)
|
|
|
|
BO->setHasNoSignedWrap();
|
|
|
|
return BO;
|
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2020-07-04 01:08:59 +08:00
|
|
|
// (zext bool X) * (zext bool Y) --> zext (and X, Y)
|
2020-07-04 03:34:55 +08:00
|
|
|
// (sext bool X) * (sext bool Y) --> zext (and X, Y)
|
|
|
|
// Note: -1 * -1 == 1 * 1 == 1 (if the extends match, the result is the same)
|
|
|
|
if (((match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) ||
|
|
|
|
(match(Op0, m_SExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) &&
|
|
|
|
X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() &&
|
2021-06-02 12:55:38 +08:00
|
|
|
(Op0->hasOneUse() || Op1->hasOneUse() || X == Y)) {
|
2020-07-04 01:08:59 +08:00
|
|
|
Value *And = Builder.CreateAnd(X, Y, "mulbool");
|
|
|
|
return CastInst::Create(Instruction::ZExt, And, I.getType());
|
|
|
|
}
|
2020-07-13 03:56:26 +08:00
|
|
|
// (sext bool X) * (zext bool Y) --> sext (and X, Y)
|
|
|
|
// (zext bool X) * (sext bool Y) --> sext (and X, Y)
|
|
|
|
// Note: -1 * 1 == 1 * -1 == -1
|
|
|
|
if (((match(Op0, m_SExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) ||
|
|
|
|
(match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) &&
|
|
|
|
X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() &&
|
|
|
|
(Op0->hasOneUse() || Op1->hasOneUse())) {
|
|
|
|
Value *And = Builder.CreateAnd(X, Y, "mulbool");
|
|
|
|
return CastInst::Create(Instruction::SExt, And, I.getType());
|
|
|
|
}
|
2020-07-04 01:08:59 +08:00
|
|
|
|
2018-02-14 04:41:22 +08:00
|
|
|
// (bool X) * Y --> X ? Y : 0
|
2018-02-14 06:24:37 +08:00
|
|
|
// Y * (bool X) --> X ? Y : 0
|
2018-02-14 04:41:22 +08:00
|
|
|
if (match(Op0, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
|
|
|
|
return SelectInst::Create(X, Op1, ConstantInt::get(I.getType(), 0));
|
|
|
|
if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1))
|
|
|
|
return SelectInst::Create(X, Op0, ConstantInt::get(I.getType(), 0));
|
|
|
|
|
2018-02-14 06:24:37 +08:00
|
|
|
// (lshr X, 31) * Y --> (ashr X, 31) & Y
|
|
|
|
// Y * (lshr X, 31) --> (ashr X, 31) & Y
|
|
|
|
// TODO: We are not checking one-use because the elimination of the multiply
|
|
|
|
// is better for analysis?
|
|
|
|
// TODO: Should we canonicalize to '(X < 0) ? Y : 0' instead? That would be
|
|
|
|
// more similar to what we're doing above.
|
|
|
|
const APInt *C;
|
|
|
|
if (match(Op0, m_LShr(m_Value(X), m_APInt(C))) && *C == C->getBitWidth() - 1)
|
|
|
|
return BinaryOperator::CreateAnd(Builder.CreateAShr(X, *C), Op1);
|
|
|
|
if (match(Op1, m_LShr(m_Value(X), m_APInt(C))) && *C == C->getBitWidth() - 1)
|
|
|
|
return BinaryOperator::CreateAnd(Builder.CreateAShr(X, *C), Op0);
|
2010-01-05 14:09:35 +08:00
|
|
|
|
[InstCombine] Transform abs pattern using multiplication to abs intrinsic (PR45691)
```
unsigned r(int v)
{
return (1 | -(v < 0)) * v;
}
`r` is equivalent to `abs(v)`.
```
```
define <4 x i8> @src(<4 x i8> %0) {
%1:
%2 = ashr <4 x i8> %0, { 31, undef, 31, 31 }
%3 = or <4 x i8> %2, { 1, 1, 1, undef }
%4 = mul nsw <4 x i8> %3, %0
ret <4 x i8> %4
}
=>
define <4 x i8> @tgt(<4 x i8> %0) {
%1:
%2 = icmp slt <4 x i8> %0, { 0, 0, 0, 0 }
%3 = sub nsw <4 x i8> { 0, 0, 0, 0 }, %0
%4 = select <4 x i1> %2, <4 x i8> %3, <4 x i8> %0
ret <4 x i8> %4
}
Transformation seems to be correct!
```
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D94874
2021-01-18 00:06:06 +08:00
|
|
|
// ((ashr X, 31) | 1) * X --> abs(X)
|
|
|
|
// X * ((ashr X, 31) | 1) --> abs(X)
|
|
|
|
if (match(&I, m_c_BinOp(m_Or(m_AShr(m_Value(X),
|
|
|
|
m_SpecificIntAllowUndef(BitWidth - 1)),
|
|
|
|
m_One()),
|
|
|
|
m_Deferred(X)))) {
|
|
|
|
Value *Abs = Builder.CreateBinaryIntrinsic(
|
|
|
|
Intrinsic::abs, X,
|
|
|
|
ConstantInt::getBool(I.getContext(), I.hasNoSignedWrap()));
|
|
|
|
Abs->takeName(&I);
|
|
|
|
return replaceInstUsesWith(I, Abs);
|
|
|
|
}
|
|
|
|
|
2018-09-15 06:23:35 +08:00
|
|
|
if (Instruction *Ext = narrowMathIfNoOverflow(I))
|
|
|
|
return Ext;
|
2016-12-30 08:28:58 +08:00
|
|
|
|
2018-07-13 09:18:07 +08:00
|
|
|
bool Changed = false;
|
2017-05-22 14:25:31 +08:00
|
|
|
if (!I.hasNoSignedWrap() && willNotOverflowSignedMul(Op0, Op1, I)) {
|
2014-12-26 17:10:14 +08:00
|
|
|
Changed = true;
|
|
|
|
I.setHasNoSignedWrap(true);
|
|
|
|
}
|
|
|
|
|
2017-05-15 10:44:08 +08:00
|
|
|
if (!I.hasNoUnsignedWrap() && willNotOverflowUnsignedMul(Op0, Op1, I)) {
|
2014-12-26 17:50:35 +08:00
|
|
|
Changed = true;
|
|
|
|
I.setHasNoUnsignedWrap(true);
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return Changed ? &I : nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) {
|
2020-06-20 22:20:21 +08:00
|
|
|
BinaryOperator::BinaryOps Opcode = I.getOpcode();
|
2020-06-20 23:47:00 +08:00
|
|
|
assert((Opcode == Instruction::FMul || Opcode == Instruction::FDiv) &&
|
|
|
|
"Expected fmul or fdiv");
|
|
|
|
|
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2020-06-20 22:20:21 +08:00
|
|
|
Value *X, *Y;
|
|
|
|
|
|
|
|
// -X * -Y --> X * Y
|
|
|
|
// -X / -Y --> X / Y
|
|
|
|
if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_FNeg(m_Value(Y))))
|
|
|
|
return BinaryOperator::CreateWithCopiedFlags(Opcode, X, Y, &I);
|
|
|
|
|
|
|
|
// fabs(X) * fabs(X) -> X * X
|
|
|
|
// fabs(X) / fabs(X) -> X / X
|
2020-10-01 21:42:16 +08:00
|
|
|
if (Op0 == Op1 && match(Op0, m_FAbs(m_Value(X))))
|
2020-06-20 22:20:21 +08:00
|
|
|
return BinaryOperator::CreateWithCopiedFlags(Opcode, X, X, &I);
|
|
|
|
|
2020-06-25 23:28:04 +08:00
|
|
|
// fabs(X) * fabs(Y) --> fabs(X * Y)
|
|
|
|
// fabs(X) / fabs(Y) --> fabs(X / Y)
|
2020-10-01 21:42:16 +08:00
|
|
|
if (match(Op0, m_FAbs(m_Value(X))) && match(Op1, m_FAbs(m_Value(Y))) &&
|
2020-06-25 23:28:04 +08:00
|
|
|
(Op0->hasOneUse() || Op1->hasOneUse())) {
|
|
|
|
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
|
|
|
|
Builder.setFastMathFlags(I.getFastMathFlags());
|
|
|
|
Value *XY = Builder.CreateBinOp(Opcode, X, Y);
|
|
|
|
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, XY);
|
|
|
|
Fabs->takeName(&I);
|
|
|
|
return replaceInstUsesWith(I, Fabs);
|
|
|
|
}
|
|
|
|
|
2020-06-20 22:20:21 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifyFMulInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
I.getFastMathFlags(),
|
2017-06-09 11:21:29 +08:00
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2018-07-13 09:18:07 +08:00
|
|
|
if (SimplifyAssociativeOrCommutative(I))
|
|
|
|
return &I;
|
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2018-03-01 00:36:24 +08:00
|
|
|
if (Instruction *FoldedMul = foldBinOpIntoSelectOrPhi(I))
|
|
|
|
return FoldedMul;
|
|
|
|
|
2019-10-06 22:15:48 +08:00
|
|
|
if (Value *FoldedMul = foldMulSelectToNegate(I, Builder))
|
|
|
|
return replaceInstUsesWith(I, FoldedMul);
|
|
|
|
|
2020-06-20 23:47:00 +08:00
|
|
|
if (Instruction *R = foldFPSignBitOps(I))
|
2020-06-20 22:20:21 +08:00
|
|
|
return R;
|
|
|
|
|
2018-03-03 07:06:45 +08:00
|
|
|
// X * -1.0 --> -X
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2018-03-03 07:06:45 +08:00
|
|
|
if (match(Op1, m_SpecificFP(-1.0)))
|
2020-02-28 01:05:54 +08:00
|
|
|
return UnaryOperator::CreateFNegFMF(Op0, &I);
|
2013-01-08 05:39:23 +08:00
|
|
|
|
2018-03-03 07:06:45 +08:00
|
|
|
// -X * C --> X * -C
|
2020-06-20 22:20:21 +08:00
|
|
|
Value *X, *Y;
|
2018-03-03 07:06:45 +08:00
|
|
|
Constant *C;
|
|
|
|
if (match(Op0, m_FNeg(m_Value(X))) && match(Op1, m_Constant(C)))
|
|
|
|
return BinaryOperator::CreateFMulFMF(X, ConstantExpr::getFNeg(C), &I);
|
|
|
|
|
|
|
|
// (select A, B, C) * (select A, D, E) --> select A, (B*D), (C*E)
|
|
|
|
if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1))
|
|
|
|
return replaceInstUsesWith(I, V);
|
|
|
|
|
2018-04-04 06:19:19 +08:00
|
|
|
if (I.hasAllowReassoc()) {
|
|
|
|
// Reassociate constant RHS with another constant to form constant
|
|
|
|
// expression.
|
|
|
|
if (match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP()) {
|
|
|
|
Constant *C1;
|
|
|
|
if (match(Op0, m_OneUse(m_FDiv(m_Constant(C1), m_Value(X))))) {
|
|
|
|
// (C1 / X) * C --> (C * C1) / X
|
|
|
|
Constant *CC1 = ConstantExpr::getFMul(C, C1);
|
|
|
|
if (CC1->isNormalFP())
|
|
|
|
return BinaryOperator::CreateFDivFMF(CC1, X, &I);
|
|
|
|
}
|
|
|
|
if (match(Op0, m_FDiv(m_Value(X), m_Constant(C1)))) {
|
|
|
|
// (X / C1) * C --> X * (C / C1)
|
|
|
|
Constant *CDivC1 = ConstantExpr::getFDiv(C, C1);
|
|
|
|
if (CDivC1->isNormalFP())
|
|
|
|
return BinaryOperator::CreateFMulFMF(X, CDivC1, &I);
|
|
|
|
|
|
|
|
// If the constant was a denormal, try reassociating differently.
|
|
|
|
// (X / C1) * C --> X / (C1 / C)
|
|
|
|
Constant *C1DivC = ConstantExpr::getFDiv(C1, C);
|
|
|
|
if (Op0->hasOneUse() && C1DivC->isNormalFP())
|
|
|
|
return BinaryOperator::CreateFDivFMF(X, C1DivC, &I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We do not need to match 'fadd C, X' and 'fsub X, C' because they are
|
|
|
|
// canonicalized to 'fadd X, C'. Distributing the multiply may allow
|
|
|
|
// further folds and (X * C) + C2 is 'fma'.
|
|
|
|
if (match(Op0, m_OneUse(m_FAdd(m_Value(X), m_Constant(C1))))) {
|
|
|
|
// (X + C1) * C --> (X * C) + (C * C1)
|
|
|
|
Constant *CC1 = ConstantExpr::getFMul(C, C1);
|
|
|
|
Value *XC = Builder.CreateFMulFMF(X, C, &I);
|
|
|
|
return BinaryOperator::CreateFAddFMF(XC, CC1, &I);
|
|
|
|
}
|
|
|
|
if (match(Op0, m_OneUse(m_FSub(m_Constant(C1), m_Value(X))))) {
|
|
|
|
// (C1 - X) * C --> (C * C1) - (X * C)
|
|
|
|
Constant *CC1 = ConstantExpr::getFMul(C, C1);
|
|
|
|
Value *XC = Builder.CreateFMulFMF(X, C, &I);
|
|
|
|
return BinaryOperator::CreateFSubFMF(CC1, XC, &I);
|
|
|
|
}
|
2018-03-13 22:46:32 +08:00
|
|
|
}
|
2018-04-04 06:19:19 +08:00
|
|
|
|
2019-04-15 21:23:38 +08:00
|
|
|
Value *Z;
|
|
|
|
if (match(&I, m_c_FMul(m_OneUse(m_FDiv(m_Value(X), m_Value(Y))),
|
|
|
|
m_Value(Z)))) {
|
|
|
|
// Sink division: (X / Y) * Z --> (X * Z) / Y
|
|
|
|
Value *NewFMul = Builder.CreateFMulFMF(X, Z, &I);
|
|
|
|
return BinaryOperator::CreateFDivFMF(NewFMul, Y, &I);
|
|
|
|
}
|
|
|
|
|
2018-04-04 06:19:19 +08:00
|
|
|
// sqrt(X) * sqrt(Y) -> sqrt(X * Y)
|
|
|
|
// nnan disallows the possibility of returning a number if both operands are
|
|
|
|
// negative (in that case, we should return NaN).
|
|
|
|
if (I.hasNoNaNs() &&
|
|
|
|
match(Op0, m_OneUse(m_Intrinsic<Intrinsic::sqrt>(m_Value(X)))) &&
|
|
|
|
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::sqrt>(m_Value(Y))))) {
|
|
|
|
Value *XY = Builder.CreateFMulFMF(X, Y, &I);
|
2018-10-08 18:32:33 +08:00
|
|
|
Value *Sqrt = Builder.CreateUnaryIntrinsic(Intrinsic::sqrt, XY, &I);
|
2018-04-04 06:19:19 +08:00
|
|
|
return replaceInstUsesWith(I, Sqrt);
|
2018-03-13 22:46:32 +08:00
|
|
|
}
|
|
|
|
|
2020-09-02 20:23:48 +08:00
|
|
|
// The following transforms are done irrespective of the number of uses
|
|
|
|
// for the expression "1.0/sqrt(X)".
|
|
|
|
// 1) 1.0/sqrt(X) * X -> X/sqrt(X)
|
|
|
|
// 2) X * 1.0/sqrt(X) -> X/sqrt(X)
|
|
|
|
// We always expect the backend to reduce X/sqrt(X) to sqrt(X), if it
|
|
|
|
// has the necessary (reassoc) fast-math-flags.
|
|
|
|
if (I.hasNoSignedZeros() &&
|
|
|
|
match(Op0, (m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) &&
|
|
|
|
match(Y, m_Intrinsic<Intrinsic::sqrt>(m_Value(X))) && Op1 == X)
|
|
|
|
return BinaryOperator::CreateFDivFMF(X, Y, &I);
|
|
|
|
if (I.hasNoSignedZeros() &&
|
|
|
|
match(Op1, (m_FDiv(m_SpecificFP(1.0), m_Value(Y)))) &&
|
|
|
|
match(Y, m_Intrinsic<Intrinsic::sqrt>(m_Value(X))) && Op0 == X)
|
|
|
|
return BinaryOperator::CreateFDivFMF(X, Y, &I);
|
|
|
|
|
2019-04-09 05:23:50 +08:00
|
|
|
// Like the similar transform in instsimplify, this requires 'nsz' because
|
|
|
|
// sqrt(-0.0) = -0.0, and -0.0 * -0.0 does not simplify to -0.0.
|
|
|
|
if (I.hasNoNaNs() && I.hasNoSignedZeros() && Op0 == Op1 &&
|
|
|
|
Op0->hasNUses(2)) {
|
|
|
|
// Peek through fdiv to find squaring of square root:
|
|
|
|
// (X / sqrt(Y)) * (X / sqrt(Y)) --> (X * X) / Y
|
|
|
|
if (match(Op0, m_FDiv(m_Value(X),
|
|
|
|
m_Intrinsic<Intrinsic::sqrt>(m_Value(Y))))) {
|
|
|
|
Value *XX = Builder.CreateFMulFMF(X, X, &I);
|
|
|
|
return BinaryOperator::CreateFDivFMF(XX, Y, &I);
|
|
|
|
}
|
|
|
|
// (sqrt(Y) / X) * (sqrt(Y) / X) --> Y / (X * X)
|
|
|
|
if (match(Op0, m_FDiv(m_Intrinsic<Intrinsic::sqrt>(m_Value(Y)),
|
|
|
|
m_Value(X)))) {
|
|
|
|
Value *XX = Builder.CreateFMulFMF(X, X, &I);
|
|
|
|
return BinaryOperator::CreateFDivFMF(Y, XX, &I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[InstCombine] Missed optimization for pow(x, y) * pow(x, z) with fast-math
If FP reassociation (fast-math) is allowed, then LLVM is free to do the
following transformation pow(x, y) * pow(x, z) -> pow(x, y + z).
This patch adds this transformation and tests for it.
See more https://bugs.llvm.org/show_bug.cgi?id=47205
It handles two cases
1. When operands of fmul are different instructions
%4 = call reassoc float @llvm.pow.f32(float %0, float %1)
%5 = call reassoc float @llvm.pow.f32(float %0, float %2)
%6 = fmul reassoc float %5, %4
-->
%3 = fadd reassoc float %1, %2
%4 = call reassoc float @llvm.pow.f32(float %0, float %3)
2. When operands of fmul are the same instruction
%4 = call reassoc float @llvm.pow.f32(float %0, float %1)
%5 = fmul reassoc float %4, %4
-->
%3 = fadd reassoc float %1, %1
%4 = call reassoc float @llvm.pow.f32(float %0, float %3)
Differential Revision: https://reviews.llvm.org/D102574
2021-06-07 19:01:29 +08:00
|
|
|
if (I.isOnlyUserOfAnyOperand()) {
|
|
|
|
// pow(x, y) * pow(x, z) -> pow(x, y + z)
|
|
|
|
if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) &&
|
|
|
|
match(Op1, m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z)))) {
|
|
|
|
auto *YZ = Builder.CreateFAddFMF(Y, Z, &I);
|
|
|
|
auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, YZ, &I);
|
|
|
|
return replaceInstUsesWith(I, NewPow);
|
|
|
|
}
|
2019-01-31 14:28:10 +08:00
|
|
|
|
2021-09-22 00:14:04 +08:00
|
|
|
// powi(x, y) * powi(x, z) -> powi(x, y + z)
|
|
|
|
if (match(Op0, m_Intrinsic<Intrinsic::powi>(m_Value(X), m_Value(Y))) &&
|
|
|
|
match(Op1, m_Intrinsic<Intrinsic::powi>(m_Specific(X), m_Value(Z))) &&
|
|
|
|
Y->getType() == Z->getType()) {
|
|
|
|
auto *YZ = Builder.CreateAdd(Y, Z);
|
|
|
|
auto *NewPow = Builder.CreateIntrinsic(
|
|
|
|
Intrinsic::powi, {X->getType(), YZ->getType()}, {X, YZ}, &I);
|
|
|
|
return replaceInstUsesWith(I, NewPow);
|
|
|
|
}
|
|
|
|
|
[InstCombine] Missed optimization for pow(x, y) * pow(x, z) with fast-math
If FP reassociation (fast-math) is allowed, then LLVM is free to do the
following transformation pow(x, y) * pow(x, z) -> pow(x, y + z).
This patch adds this transformation and tests for it.
See more https://bugs.llvm.org/show_bug.cgi?id=47205
It handles two cases
1. When operands of fmul are different instructions
%4 = call reassoc float @llvm.pow.f32(float %0, float %1)
%5 = call reassoc float @llvm.pow.f32(float %0, float %2)
%6 = fmul reassoc float %5, %4
-->
%3 = fadd reassoc float %1, %2
%4 = call reassoc float @llvm.pow.f32(float %0, float %3)
2. When operands of fmul are the same instruction
%4 = call reassoc float @llvm.pow.f32(float %0, float %1)
%5 = fmul reassoc float %4, %4
-->
%3 = fadd reassoc float %1, %1
%4 = call reassoc float @llvm.pow.f32(float %0, float %3)
Differential Revision: https://reviews.llvm.org/D102574
2021-06-07 19:01:29 +08:00
|
|
|
// exp(X) * exp(Y) -> exp(X + Y)
|
|
|
|
if (match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X))) &&
|
|
|
|
match(Op1, m_Intrinsic<Intrinsic::exp>(m_Value(Y)))) {
|
|
|
|
Value *XY = Builder.CreateFAddFMF(X, Y, &I);
|
|
|
|
Value *Exp = Builder.CreateUnaryIntrinsic(Intrinsic::exp, XY, &I);
|
|
|
|
return replaceInstUsesWith(I, Exp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// exp2(X) * exp2(Y) -> exp2(X + Y)
|
|
|
|
if (match(Op0, m_Intrinsic<Intrinsic::exp2>(m_Value(X))) &&
|
|
|
|
match(Op1, m_Intrinsic<Intrinsic::exp2>(m_Value(Y)))) {
|
|
|
|
Value *XY = Builder.CreateFAddFMF(X, Y, &I);
|
|
|
|
Value *Exp2 = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, XY, &I);
|
|
|
|
return replaceInstUsesWith(I, Exp2);
|
|
|
|
}
|
2019-01-31 14:28:10 +08:00
|
|
|
}
|
|
|
|
|
2018-04-04 06:19:19 +08:00
|
|
|
// (X*Y) * X => (X*X) * Y where Y != X
|
|
|
|
// The purpose is two-fold:
|
|
|
|
// 1) to form a power expression (of X).
|
|
|
|
// 2) potentially shorten the critical path: After transformation, the
|
|
|
|
// latency of the instruction Y is amortized by the expression of X*X,
|
|
|
|
// and therefore Y is in a "less critical" position compared to what it
|
|
|
|
// was before the transformation.
|
|
|
|
if (match(Op0, m_OneUse(m_c_FMul(m_Specific(Op1), m_Value(Y)))) &&
|
|
|
|
Op1 != Y) {
|
|
|
|
Value *XX = Builder.CreateFMulFMF(Op1, Op1, &I);
|
|
|
|
return BinaryOperator::CreateFMulFMF(XX, Y, &I);
|
2018-03-26 23:03:57 +08:00
|
|
|
}
|
2018-04-04 06:19:19 +08:00
|
|
|
if (match(Op1, m_OneUse(m_c_FMul(m_Specific(Op0), m_Value(Y)))) &&
|
|
|
|
Op0 != Y) {
|
|
|
|
Value *XX = Builder.CreateFMulFMF(Op0, Op0, &I);
|
|
|
|
return BinaryOperator::CreateFMulFMF(XX, Y, &I);
|
2018-03-03 07:06:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-03 04:32:46 +08:00
|
|
|
// log2(X * 0.5) * Y = log2(X) * Y - Y
|
|
|
|
if (I.isFast()) {
|
|
|
|
IntrinsicInst *Log2 = nullptr;
|
|
|
|
if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::log2>(
|
|
|
|
m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
|
|
|
|
Log2 = cast<IntrinsicInst>(Op0);
|
|
|
|
Y = Op1;
|
|
|
|
}
|
|
|
|
if (match(Op1, m_OneUse(m_Intrinsic<Intrinsic::log2>(
|
|
|
|
m_OneUse(m_FMul(m_Value(X), m_SpecificFP(0.5))))))) {
|
|
|
|
Log2 = cast<IntrinsicInst>(Op1);
|
|
|
|
Y = Op0;
|
2012-12-01 03:09:41 +08:00
|
|
|
}
|
2018-03-03 04:32:46 +08:00
|
|
|
if (Log2) {
|
2020-02-16 17:15:53 +08:00
|
|
|
Value *Log2 = Builder.CreateUnaryIntrinsic(Intrinsic::log2, X, &I);
|
2018-03-03 04:32:46 +08:00
|
|
|
Value *LogXTimesY = Builder.CreateFMulFMF(Log2, Y, &I);
|
|
|
|
return BinaryOperator::CreateFSubFMF(LogXTimesY, Y, &I);
|
2012-12-01 03:09:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-13 09:18:07 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2017-10-07 07:20:16 +08:00
|
|
|
/// Fold a divide or remainder with a select instruction divisor when one of the
|
|
|
|
/// select operands is zero. In that case, we can use the other select operand
|
|
|
|
/// because div/rem by zero is undefined.
|
2020-06-03 21:56:40 +08:00
|
|
|
bool InstCombinerImpl::simplifyDivRemOfSelectWithZeroOp(BinaryOperator &I) {
|
2017-10-07 07:20:16 +08:00
|
|
|
SelectInst *SI = dyn_cast<SelectInst>(I.getOperand(1));
|
|
|
|
if (!SI)
|
2010-01-05 14:09:35 +08:00
|
|
|
return false;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2017-10-07 07:20:16 +08:00
|
|
|
int NonNullOperand;
|
|
|
|
if (match(SI->getTrueValue(), m_Zero()))
|
|
|
|
// div/rem X, (Cond ? 0 : Y) -> div/rem X, Y
|
|
|
|
NonNullOperand = 2;
|
|
|
|
else if (match(SI->getFalseValue(), m_Zero()))
|
|
|
|
// div/rem X, (Cond ? Y : 0) -> div/rem X, Y
|
|
|
|
NonNullOperand = 1;
|
|
|
|
else
|
|
|
|
return false;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Change the div/rem to use 'Y' instead of the select.
|
2020-03-31 04:00:16 +08:00
|
|
|
replaceOperand(I, 1, SI->getOperand(NonNullOperand));
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Okay, we know we replace the operand of the div/rem with 'Y' with no
|
|
|
|
// problem. However, the select, or the condition of the select may have
|
|
|
|
// multiple uses. Based on our knowledge that the operand must be non-zero,
|
|
|
|
// propagate the known value for the select into other uses of it, and
|
|
|
|
// propagate a known value of the condition into its other users.
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// If the select and condition only have a single use, don't bother with this,
|
|
|
|
// early exit.
|
2017-10-07 07:20:16 +08:00
|
|
|
Value *SelectCond = SI->getCondition();
|
2010-01-05 14:09:35 +08:00
|
|
|
if (SI->use_empty() && SelectCond->hasOneUse())
|
|
|
|
return true;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Scan the current block backward, looking for other uses of SI.
|
2015-10-14 00:59:33 +08:00
|
|
|
BasicBlock::iterator BBI = I.getIterator(), BBFront = I.getParent()->begin();
|
2017-10-07 07:43:06 +08:00
|
|
|
Type *CondTy = SelectCond->getType();
|
2010-01-05 14:09:35 +08:00
|
|
|
while (BBI != BBFront) {
|
|
|
|
--BBI;
|
2018-06-04 10:52:36 +08:00
|
|
|
// If we found an instruction that we can't assume will return, so
|
2010-01-05 14:09:35 +08:00
|
|
|
// information from below it cannot be propagated above it.
|
2018-06-04 10:52:36 +08:00
|
|
|
if (!isGuaranteedToTransferExecutionToSuccessor(&*BBI))
|
2010-01-05 14:09:35 +08:00
|
|
|
break;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Replace uses of the select or its condition with the known values.
|
2021-02-09 14:33:53 +08:00
|
|
|
for (Use &Op : BBI->operands()) {
|
|
|
|
if (Op == SI) {
|
|
|
|
replaceUse(Op, SI->getOperand(NonNullOperand));
|
2020-01-31 05:32:46 +08:00
|
|
|
Worklist.push(&*BBI);
|
2021-02-09 14:33:53 +08:00
|
|
|
} else if (Op == SelectCond) {
|
|
|
|
replaceUse(Op, NonNullOperand == 1 ? ConstantInt::getTrue(CondTy)
|
2020-03-31 04:00:16 +08:00
|
|
|
: ConstantInt::getFalse(CondTy));
|
2020-01-31 05:32:46 +08:00
|
|
|
Worklist.push(&*BBI);
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// If we past the instruction, quit looking for it.
|
|
|
|
if (&*BBI == SI)
|
2014-04-25 13:29:35 +08:00
|
|
|
SI = nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
if (&*BBI == SelectCond)
|
2014-04-25 13:29:35 +08:00
|
|
|
SelectCond = nullptr;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// If we ran out of things to eliminate, break out of the loop.
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!SelectCond && !SI)
|
2010-01-05 14:09:35 +08:00
|
|
|
break;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-13 02:38:35 +08:00
|
|
|
/// True if the multiply can not be expressed in an int this size.
|
|
|
|
static bool multiplyOverflows(const APInt &C1, const APInt &C2, APInt &Product,
|
|
|
|
bool IsSigned) {
|
|
|
|
bool Overflow;
|
|
|
|
Product = IsSigned ? C1.smul_ov(C2, Overflow) : C1.umul_ov(C2, Overflow);
|
|
|
|
return Overflow;
|
|
|
|
}
|
|
|
|
|
2018-07-16 01:06:59 +08:00
|
|
|
/// True if C1 is a multiple of C2. Quotient contains C1/C2.
|
2018-02-13 02:38:35 +08:00
|
|
|
static bool isMultiple(const APInt &C1, const APInt &C2, APInt &Quotient,
|
|
|
|
bool IsSigned) {
|
|
|
|
assert(C1.getBitWidth() == C2.getBitWidth() && "Constant widths not equal");
|
|
|
|
|
|
|
|
// Bail if we will divide by zero.
|
2021-09-30 16:54:57 +08:00
|
|
|
if (C2.isZero())
|
2018-02-13 02:38:35 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Bail if we would divide INT_MIN by -1.
|
2021-09-30 16:54:57 +08:00
|
|
|
if (IsSigned && C1.isMinSignedValue() && C2.isAllOnes())
|
2018-02-13 02:38:35 +08:00
|
|
|
return false;
|
|
|
|
|
2019-07-16 12:46:31 +08:00
|
|
|
APInt Remainder(C1.getBitWidth(), /*val=*/0ULL, IsSigned);
|
2018-02-13 02:38:35 +08:00
|
|
|
if (IsSigned)
|
|
|
|
APInt::sdivrem(C1, C2, Quotient, Remainder);
|
|
|
|
else
|
|
|
|
APInt::udivrem(C1, C2, Quotient, Remainder);
|
|
|
|
|
|
|
|
return Remainder.isMinValue();
|
|
|
|
}
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
/// This function implements the transforms common to both integer division
|
|
|
|
/// instructions (udiv and sdiv). It is called by the visitors to those integer
|
|
|
|
/// division instructions.
|
2018-05-02 00:10:38 +08:00
|
|
|
/// Common integer divide transforms
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
|
2010-01-05 14:09:35 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2018-01-22 00:14:51 +08:00
|
|
|
bool IsSigned = I.getOpcode() == Instruction::SDiv;
|
2018-02-12 22:14:56 +08:00
|
|
|
Type *Ty = I.getType();
|
2010-01-05 14:09:35 +08:00
|
|
|
|
Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to
transform:
A / ((1 << B) >>u 2)
into:
A >>u (B-2)
which we compile into:
_divu3: ## @divu3
leal -2(%rsi), %ecx
shrl %cl, %edi
movl %edi, %eax
ret
instead of:
_divu3: ## @divu3
movb %sil, %cl
movl $1, %esi
shll %cl, %esi
shrl $2, %esi
movl %edi, %eax
xorl %edx, %edx
divl %esi, %eax
ret
llvm-svn: 131860
2011-05-23 02:18:41 +08:00
|
|
|
// The RHS is known non-zero.
|
2020-03-29 23:08:04 +08:00
|
|
|
if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this, I))
|
|
|
|
return replaceOperand(I, 1, V);
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Handle cases involving: [su]div X, (select Cond, Y, Z)
|
|
|
|
// This does not apply for fdiv.
|
2017-10-07 07:20:16 +08:00
|
|
|
if (simplifyDivRemOfSelectWithZeroOp(I))
|
2010-01-05 14:09:35 +08:00
|
|
|
return &I;
|
|
|
|
|
2018-02-13 02:38:35 +08:00
|
|
|
const APInt *C2;
|
|
|
|
if (match(Op1, m_APInt(C2))) {
|
|
|
|
Value *X;
|
|
|
|
const APInt *C1;
|
|
|
|
|
|
|
|
// (X / C1) / C2 -> X / (C1*C2)
|
|
|
|
if ((IsSigned && match(Op0, m_SDiv(m_Value(X), m_APInt(C1)))) ||
|
|
|
|
(!IsSigned && match(Op0, m_UDiv(m_Value(X), m_APInt(C1))))) {
|
2019-07-16 12:46:31 +08:00
|
|
|
APInt Product(C1->getBitWidth(), /*val=*/0ULL, IsSigned);
|
2018-02-13 02:38:35 +08:00
|
|
|
if (!multiplyOverflows(*C1, *C2, Product, IsSigned))
|
|
|
|
return BinaryOperator::Create(I.getOpcode(), X,
|
|
|
|
ConstantInt::get(Ty, Product));
|
|
|
|
}
|
InstCombine: Combine mul with div.
We can combne a mul with a div if one of the operands is a multiple of
the other:
%mul = mul nsw nuw %a, C1
%ret = udiv %mul, C2
=>
%ret = mul nsw %a, (C1 / C2)
This can expose further optimization opportunities if we end up
multiplying or dividing by a power of 2.
Consider this small example:
define i32 @f(i32 %a) {
%mul = mul nuw i32 %a, 14
%div = udiv exact i32 %mul, 7
ret i32 %div
}
which gets CodeGen'd to:
imull $14, %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $2, %eax
retq
We can now transform this into:
define i32 @f(i32 %a) {
%shl = shl nuw i32 %a, 1
ret i32 %shl
}
which gets CodeGen'd to:
leal (%rdi,%rdi), %eax
retq
This fixes PR20681.
llvm-svn: 215815
2014-08-16 16:55:06 +08:00
|
|
|
|
2018-02-13 02:38:35 +08:00
|
|
|
if ((IsSigned && match(Op0, m_NSWMul(m_Value(X), m_APInt(C1)))) ||
|
|
|
|
(!IsSigned && match(Op0, m_NUWMul(m_Value(X), m_APInt(C1))))) {
|
2019-07-16 12:46:31 +08:00
|
|
|
APInt Quotient(C1->getBitWidth(), /*val=*/0ULL, IsSigned);
|
InstCombine: Combine mul with div.
We can combne a mul with a div if one of the operands is a multiple of
the other:
%mul = mul nsw nuw %a, C1
%ret = udiv %mul, C2
=>
%ret = mul nsw %a, (C1 / C2)
This can expose further optimization opportunities if we end up
multiplying or dividing by a power of 2.
Consider this small example:
define i32 @f(i32 %a) {
%mul = mul nuw i32 %a, 14
%div = udiv exact i32 %mul, 7
ret i32 %div
}
which gets CodeGen'd to:
imull $14, %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $2, %eax
retq
We can now transform this into:
define i32 @f(i32 %a) {
%shl = shl nuw i32 %a, 1
ret i32 %shl
}
which gets CodeGen'd to:
leal (%rdi,%rdi), %eax
retq
This fixes PR20681.
llvm-svn: 215815
2014-08-16 16:55:06 +08:00
|
|
|
|
2018-02-13 02:38:35 +08:00
|
|
|
// (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1.
|
|
|
|
if (isMultiple(*C2, *C1, Quotient, IsSigned)) {
|
|
|
|
auto *NewDiv = BinaryOperator::Create(I.getOpcode(), X,
|
|
|
|
ConstantInt::get(Ty, Quotient));
|
|
|
|
NewDiv->setIsExact(I.isExact());
|
|
|
|
return NewDiv;
|
2014-10-12 16:34:24 +08:00
|
|
|
}
|
InstCombine: Combine mul with div.
We can combne a mul with a div if one of the operands is a multiple of
the other:
%mul = mul nsw nuw %a, C1
%ret = udiv %mul, C2
=>
%ret = mul nsw %a, (C1 / C2)
This can expose further optimization opportunities if we end up
multiplying or dividing by a power of 2.
Consider this small example:
define i32 @f(i32 %a) {
%mul = mul nuw i32 %a, 14
%div = udiv exact i32 %mul, 7
ret i32 %div
}
which gets CodeGen'd to:
imull $14, %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $2, %eax
retq
We can now transform this into:
define i32 @f(i32 %a) {
%shl = shl nuw i32 %a, 1
ret i32 %shl
}
which gets CodeGen'd to:
leal (%rdi,%rdi), %eax
retq
This fixes PR20681.
llvm-svn: 215815
2014-08-16 16:55:06 +08:00
|
|
|
|
2018-02-13 02:38:35 +08:00
|
|
|
// (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2.
|
|
|
|
if (isMultiple(*C1, *C2, Quotient, IsSigned)) {
|
|
|
|
auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
|
|
|
|
ConstantInt::get(Ty, Quotient));
|
|
|
|
auto *OBO = cast<OverflowingBinaryOperator>(Op0);
|
|
|
|
Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
|
|
|
|
Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
|
|
|
|
return Mul;
|
|
|
|
}
|
|
|
|
}
|
2014-10-12 16:34:24 +08:00
|
|
|
|
2018-02-13 02:38:35 +08:00
|
|
|
if ((IsSigned && match(Op0, m_NSWShl(m_Value(X), m_APInt(C1))) &&
|
2021-09-25 19:57:33 +08:00
|
|
|
C1->ult(C1->getBitWidth() - 1)) ||
|
|
|
|
(!IsSigned && match(Op0, m_NUWShl(m_Value(X), m_APInt(C1))) &&
|
|
|
|
C1->ult(C1->getBitWidth()))) {
|
2019-07-16 12:46:31 +08:00
|
|
|
APInt Quotient(C1->getBitWidth(), /*val=*/0ULL, IsSigned);
|
2018-02-13 02:38:35 +08:00
|
|
|
APInt C1Shifted = APInt::getOneBitSet(
|
2021-09-25 19:57:33 +08:00
|
|
|
C1->getBitWidth(), static_cast<unsigned>(C1->getZExtValue()));
|
2018-02-13 02:38:35 +08:00
|
|
|
|
2018-07-16 01:06:59 +08:00
|
|
|
// (X << C1) / C2 -> X / (C2 >> C1) if C2 is a multiple of 1 << C1.
|
2018-02-13 02:38:35 +08:00
|
|
|
if (isMultiple(*C2, C1Shifted, Quotient, IsSigned)) {
|
|
|
|
auto *BO = BinaryOperator::Create(I.getOpcode(), X,
|
|
|
|
ConstantInt::get(Ty, Quotient));
|
|
|
|
BO->setIsExact(I.isExact());
|
|
|
|
return BO;
|
InstCombine: Combine mul with div.
We can combne a mul with a div if one of the operands is a multiple of
the other:
%mul = mul nsw nuw %a, C1
%ret = udiv %mul, C2
=>
%ret = mul nsw %a, (C1 / C2)
This can expose further optimization opportunities if we end up
multiplying or dividing by a power of 2.
Consider this small example:
define i32 @f(i32 %a) {
%mul = mul nuw i32 %a, 14
%div = udiv exact i32 %mul, 7
ret i32 %div
}
which gets CodeGen'd to:
imull $14, %edi, %eax
imulq $613566757, %rax, %rcx
shrq $32, %rcx
subl %ecx, %eax
shrl %eax
addl %ecx, %eax
shrl $2, %eax
retq
We can now transform this into:
define i32 @f(i32 %a) {
%shl = shl nuw i32 %a, 1
ret i32 %shl
}
which gets CodeGen'd to:
leal (%rdi,%rdi), %eax
retq
This fixes PR20681.
llvm-svn: 215815
2014-08-16 16:55:06 +08:00
|
|
|
}
|
|
|
|
|
2018-07-16 01:06:59 +08:00
|
|
|
// (X << C1) / C2 -> X * ((1 << C1) / C2) if 1 << C1 is a multiple of C2.
|
2018-02-13 02:38:35 +08:00
|
|
|
if (isMultiple(C1Shifted, *C2, Quotient, IsSigned)) {
|
|
|
|
auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
|
|
|
|
ConstantInt::get(Ty, Quotient));
|
|
|
|
auto *OBO = cast<OverflowingBinaryOperator>(Op0);
|
|
|
|
Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
|
|
|
|
Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
|
|
|
|
return Mul;
|
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
2018-02-13 02:38:35 +08:00
|
|
|
|
2021-09-30 16:54:57 +08:00
|
|
|
if (!C2->isZero()) // avoid X udiv 0
|
2018-03-01 00:36:24 +08:00
|
|
|
if (Instruction *FoldedDiv = foldBinOpIntoSelectOrPhi(I))
|
2018-02-13 02:38:35 +08:00
|
|
|
return FoldedDiv;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2017-04-17 11:41:47 +08:00
|
|
|
if (match(Op0, m_One())) {
|
2018-02-12 22:14:56 +08:00
|
|
|
assert(!Ty->isIntOrIntVectorTy(1) && "i1 divide not removed?");
|
|
|
|
if (IsSigned) {
|
2017-04-17 11:41:47 +08:00
|
|
|
// If Op1 is 0 then it's undefined behaviour, if Op1 is 1 then the
|
|
|
|
// result is one, if Op1 is -1 then the result is minus one, otherwise
|
|
|
|
// it's zero.
|
2017-07-08 07:16:26 +08:00
|
|
|
Value *Inc = Builder.CreateAdd(Op1, Op0);
|
2018-02-12 22:14:56 +08:00
|
|
|
Value *Cmp = Builder.CreateICmpULT(Inc, ConstantInt::get(Ty, 3));
|
|
|
|
return SelectInst::Create(Cmp, Op1, ConstantInt::get(Ty, 0));
|
2017-04-17 11:41:47 +08:00
|
|
|
} else {
|
|
|
|
// If Op1 is 0 then it's undefined behaviour. If Op1 is 1 then the
|
|
|
|
// result is one, otherwise it's zero.
|
2018-02-12 22:14:56 +08:00
|
|
|
return new ZExtInst(Builder.CreateICmpEQ(Op1, Op0), Ty);
|
2014-05-14 11:03:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-01 02:16:00 +08:00
|
|
|
// See if we can fold away this div instruction.
|
|
|
|
if (SimplifyDemandedInstructionBits(I))
|
|
|
|
return &I;
|
|
|
|
|
2011-01-29 00:51:11 +08:00
|
|
|
// (X - (X rem Y)) / Y -> X / Y; usually originates as ((X / Y) * Y) / Y
|
2018-01-22 00:14:51 +08:00
|
|
|
Value *X, *Z;
|
|
|
|
if (match(Op0, m_Sub(m_Value(X), m_Value(Z)))) // (X - Z) / Y; Y = Op1
|
|
|
|
if ((IsSigned && match(Z, m_SRem(m_Specific(X), m_Specific(Op1)))) ||
|
|
|
|
(!IsSigned && match(Z, m_URem(m_Specific(X), m_Specific(Op1)))))
|
2011-01-29 00:51:11 +08:00
|
|
|
return BinaryOperator::Create(I.getOpcode(), X, Op1);
|
2018-01-22 00:14:51 +08:00
|
|
|
|
|
|
|
// (X << Y) / X -> 1 << Y
|
|
|
|
Value *Y;
|
|
|
|
if (IsSigned && match(Op0, m_NSWShl(m_Specific(Op1), m_Value(Y))))
|
2018-02-12 22:14:56 +08:00
|
|
|
return BinaryOperator::CreateNSWShl(ConstantInt::get(Ty, 1), Y);
|
2018-01-22 00:14:51 +08:00
|
|
|
if (!IsSigned && match(Op0, m_NUWShl(m_Specific(Op1), m_Value(Y))))
|
2018-02-12 22:14:56 +08:00
|
|
|
return BinaryOperator::CreateNUWShl(ConstantInt::get(Ty, 1), Y);
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2018-02-12 01:20:32 +08:00
|
|
|
// X / (X * Y) -> 1 / Y if the multiplication does not overflow.
|
|
|
|
if (match(Op1, m_c_Mul(m_Specific(Op0), m_Value(Y)))) {
|
|
|
|
bool HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
|
|
|
|
bool HasNUW = cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
|
|
|
|
if ((IsSigned && HasNSW) || (!IsSigned && HasNUW)) {
|
2020-03-29 23:08:04 +08:00
|
|
|
replaceOperand(I, 0, ConstantInt::get(Ty, 1));
|
|
|
|
replaceOperand(I, 1, Y);
|
2018-02-12 01:20:32 +08:00
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2017-10-25 05:24:53 +08:00
|
|
|
static const unsigned MaxDepth = 6;
|
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
namespace {
|
2017-10-25 05:24:53 +08:00
|
|
|
|
|
|
|
using FoldUDivOperandCb = Instruction *(*)(Value *Op0, Value *Op1,
|
|
|
|
const BinaryOperator &I,
|
2020-06-03 21:56:40 +08:00
|
|
|
InstCombinerImpl &IC);
|
2013-07-05 05:17:49 +08:00
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Used to maintain state for visitUDivOperand().
|
2013-07-05 05:17:49 +08:00
|
|
|
struct UDivFoldAction {
|
2017-10-25 05:24:53 +08:00
|
|
|
/// Informs visitUDiv() how to fold this operand. This can be zero if this
|
|
|
|
/// action joins two actions together.
|
|
|
|
FoldUDivOperandCb FoldAction;
|
|
|
|
|
|
|
|
/// Which operand to fold.
|
|
|
|
Value *OperandToFold;
|
2013-07-05 05:17:49 +08:00
|
|
|
|
|
|
|
union {
|
2017-10-25 05:24:53 +08:00
|
|
|
/// The instruction returned when FoldAction is invoked.
|
|
|
|
Instruction *FoldResult;
|
2013-07-05 05:17:49 +08:00
|
|
|
|
2017-10-25 05:24:53 +08:00
|
|
|
/// Stores the LHS action index if this action joins two actions together.
|
|
|
|
size_t SelectLHSIdx;
|
2013-07-05 05:17:49 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
UDivFoldAction(FoldUDivOperandCb FA, Value *InputOperand)
|
2014-04-25 13:29:35 +08:00
|
|
|
: FoldAction(FA), OperandToFold(InputOperand), FoldResult(nullptr) {}
|
2013-07-05 05:17:49 +08:00
|
|
|
UDivFoldAction(FoldUDivOperandCb FA, Value *InputOperand, size_t SLHS)
|
|
|
|
: FoldAction(FA), OperandToFold(InputOperand), SelectLHSIdx(SLHS) {}
|
|
|
|
};
|
2017-10-25 05:24:53 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
Revert r185257 (InstCombine: Be more agressive optimizing 'udiv' instrs with 'select' denoms)
I'm reverting this commit because:
1. As discussed during review, it needs to be rewritten (to avoid creating and
then deleting instructions).
2. This is causing optimizer crashes. Specifically, I'm seeing things like
this:
While deleting: i1 %
Use still stuck around after Def is destroyed: <badref> = select i1 <badref>, i32 0, i32 1
opt: /src/llvm-trunk/lib/IR/Value.cpp:79: virtual llvm::Value::~Value(): Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed.
I'd guess that these will go away once we're no longer creating/deleting
instructions here, but just in case, I'm adding a regression test.
Because the code is bring rewritten, I've just XFAIL'd the original regression test. Original commit message:
InstCombine: Be more agressive optimizing 'udiv' instrs with 'select' denoms
Real world code sometimes has the denominator of a 'udiv' be a
'select'. LLVM can handle such cases but only when the 'select'
operands are symmetric in structure (both select operands are a constant
power of two or a left shift, etc.). This falls apart if we are dealt a
'udiv' where the code is not symetric or if the select operands lead us
to more select instructions.
Instead, we should treat the LHS and each select operand as a distinct
divide operation and try to optimize them independently. If we can
to simplify each operation, then we can replace the 'udiv' with, say, a
'lshr' that has a new select with a bunch of new operands for the
select.
llvm-svn: 185415
2013-07-02 13:21:11 +08:00
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// X udiv 2^C -> X >> C
|
|
|
|
static Instruction *foldUDivPow2Cst(Value *Op0, Value *Op1,
|
2020-06-03 21:56:40 +08:00
|
|
|
const BinaryOperator &I,
|
|
|
|
InstCombinerImpl &IC) {
|
2020-10-11 17:31:17 +08:00
|
|
|
Constant *C1 = ConstantExpr::getExactLogBase2(cast<Constant>(Op1));
|
2018-02-08 22:46:10 +08:00
|
|
|
if (!C1)
|
|
|
|
llvm_unreachable("Failed to constant fold udiv -> logbase2");
|
|
|
|
BinaryOperator *LShr = BinaryOperator::CreateLShr(Op0, C1);
|
2014-10-07 20:04:07 +08:00
|
|
|
if (I.isExact())
|
|
|
|
LShr->setIsExact();
|
2013-07-05 05:17:49 +08:00
|
|
|
return LShr;
|
|
|
|
}
|
Revert r185257 (InstCombine: Be more agressive optimizing 'udiv' instrs with 'select' denoms)
I'm reverting this commit because:
1. As discussed during review, it needs to be rewritten (to avoid creating and
then deleting instructions).
2. This is causing optimizer crashes. Specifically, I'm seeing things like
this:
While deleting: i1 %
Use still stuck around after Def is destroyed: <badref> = select i1 <badref>, i32 0, i32 1
opt: /src/llvm-trunk/lib/IR/Value.cpp:79: virtual llvm::Value::~Value(): Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed.
I'd guess that these will go away once we're no longer creating/deleting
instructions here, but just in case, I'm adding a regression test.
Because the code is bring rewritten, I've just XFAIL'd the original regression test. Original commit message:
InstCombine: Be more agressive optimizing 'udiv' instrs with 'select' denoms
Real world code sometimes has the denominator of a 'udiv' be a
'select'. LLVM can handle such cases but only when the 'select'
operands are symmetric in structure (both select operands are a constant
power of two or a left shift, etc.). This falls apart if we are dealt a
'udiv' where the code is not symetric or if the select operands lead us
to more select instructions.
Instead, we should treat the LHS and each select operand as a distinct
divide operation and try to optimize them independently. If we can
to simplify each operation, then we can replace the 'udiv' with, say, a
'lshr' that has a new select with a bunch of new operands for the
select.
llvm-svn: 185415
2013-07-02 13:21:11 +08:00
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
|
2016-09-26 20:07:23 +08:00
|
|
|
// X udiv (zext (C1 << N)), where C1 is "1<<C2" --> X >> (N+C2)
|
2013-07-05 05:17:49 +08:00
|
|
|
static Instruction *foldUDivShl(Value *Op0, Value *Op1, const BinaryOperator &I,
|
2020-06-03 21:56:40 +08:00
|
|
|
InstCombinerImpl &IC) {
|
2016-09-26 20:07:23 +08:00
|
|
|
Value *ShiftLeft;
|
|
|
|
if (!match(Op1, m_ZExt(m_Value(ShiftLeft))))
|
|
|
|
ShiftLeft = Op1;
|
|
|
|
|
2018-02-08 23:19:38 +08:00
|
|
|
Constant *CI;
|
2016-09-26 20:07:23 +08:00
|
|
|
Value *N;
|
2018-02-08 23:19:38 +08:00
|
|
|
if (!match(ShiftLeft, m_Shl(m_Constant(CI), m_Value(N))))
|
2016-09-26 20:07:23 +08:00
|
|
|
llvm_unreachable("match should never fail here!");
|
2020-10-11 17:31:17 +08:00
|
|
|
Constant *Log2Base = ConstantExpr::getExactLogBase2(CI);
|
2018-02-08 23:19:38 +08:00
|
|
|
if (!Log2Base)
|
|
|
|
llvm_unreachable("getLogBase2 should never fail here!");
|
|
|
|
N = IC.Builder.CreateAdd(N, Log2Base);
|
2016-09-26 20:07:23 +08:00
|
|
|
if (Op1 != ShiftLeft)
|
2017-07-08 07:16:26 +08:00
|
|
|
N = IC.Builder.CreateZExt(N, Op1->getType());
|
2013-07-05 05:17:49 +08:00
|
|
|
BinaryOperator *LShr = BinaryOperator::CreateLShr(Op0, N);
|
2014-10-07 20:04:07 +08:00
|
|
|
if (I.isExact())
|
|
|
|
LShr->setIsExact();
|
2013-07-05 05:17:49 +08:00
|
|
|
return LShr;
|
|
|
|
}
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
// Recursively visits the possible right hand operands of a udiv
|
2013-07-05 05:17:49 +08:00
|
|
|
// instruction, seeing through select instructions, to determine if we can
|
|
|
|
// replace the udiv with something simpler. If we find that an operand is not
|
|
|
|
// able to simplify the udiv, we abort the entire transformation.
|
|
|
|
static size_t visitUDivOperand(Value *Op0, Value *Op1, const BinaryOperator &I,
|
|
|
|
SmallVectorImpl<UDivFoldAction> &Actions,
|
|
|
|
unsigned Depth = 0) {
|
2020-08-13 02:59:57 +08:00
|
|
|
// FIXME: assert that Op1 isn't/doesn't contain undef.
|
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// Check to see if this is an unsigned division with an exact power of 2,
|
|
|
|
// if so, convert to a right shift.
|
|
|
|
if (match(Op1, m_Power2())) {
|
|
|
|
Actions.push_back(UDivFoldAction(foldUDivPow2Cst, Op1));
|
|
|
|
return Actions.size();
|
2011-11-08 07:04:49 +08:00
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// X udiv (C1 << N), where C1 is "1<<C2" --> X >> (N+C2)
|
|
|
|
if (match(Op1, m_Shl(m_Power2(), m_Value())) ||
|
|
|
|
match(Op1, m_ZExt(m_Shl(m_Power2(), m_Value())))) {
|
|
|
|
Actions.push_back(UDivFoldAction(foldUDivShl, Op1));
|
|
|
|
return Actions.size();
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// The remaining tests are all recursive, so bail out if we hit the limit.
|
|
|
|
if (Depth++ == MaxDepth)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
2020-08-13 02:59:57 +08:00
|
|
|
// FIXME: missed optimization: if one of the hands of select is/contains
|
|
|
|
// undef, just directly pick the other one.
|
|
|
|
// FIXME: can both hands contain undef?
|
2014-08-30 17:19:05 +08:00
|
|
|
if (size_t LHSIdx =
|
|
|
|
visitUDivOperand(Op0, SI->getOperand(1), I, Actions, Depth))
|
|
|
|
if (visitUDivOperand(Op0, SI->getOperand(2), I, Actions, Depth)) {
|
|
|
|
Actions.push_back(UDivFoldAction(nullptr, Op1, LHSIdx - 1));
|
2013-07-05 05:17:49 +08:00
|
|
|
return Actions.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-25 06:54:01 +08:00
|
|
|
/// If we have zero-extended operands of an unsigned div or rem, we may be able
|
|
|
|
/// to narrow the operation (sink the zext below the math).
|
|
|
|
static Instruction *narrowUDivURem(BinaryOperator &I,
|
|
|
|
InstCombiner::BuilderTy &Builder) {
|
|
|
|
Instruction::BinaryOps Opcode = I.getOpcode();
|
|
|
|
Value *N = I.getOperand(0);
|
|
|
|
Value *D = I.getOperand(1);
|
|
|
|
Type *Ty = I.getType();
|
|
|
|
Value *X, *Y;
|
|
|
|
if (match(N, m_ZExt(m_Value(X))) && match(D, m_ZExt(m_Value(Y))) &&
|
|
|
|
X->getType() == Y->getType() && (N->hasOneUse() || D->hasOneUse())) {
|
|
|
|
// udiv (zext X), (zext Y) --> zext (udiv X, Y)
|
|
|
|
// urem (zext X), (zext Y) --> zext (urem X, Y)
|
|
|
|
Value *NarrowOp = Builder.CreateBinOp(Opcode, X, Y);
|
|
|
|
return new ZExtInst(NarrowOp, Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
Constant *C;
|
|
|
|
if ((match(N, m_OneUse(m_ZExt(m_Value(X)))) && match(D, m_Constant(C))) ||
|
|
|
|
(match(D, m_OneUse(m_ZExt(m_Value(X)))) && match(N, m_Constant(C)))) {
|
|
|
|
// If the constant is the same in the smaller type, use the narrow version.
|
|
|
|
Constant *TruncC = ConstantExpr::getTrunc(C, X->getType());
|
|
|
|
if (ConstantExpr::getZExt(TruncC, Ty) != C)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// udiv (zext X), C --> zext (udiv X, C')
|
|
|
|
// urem (zext X), C --> zext (urem X, C')
|
|
|
|
// udiv C, (zext X) --> zext (udiv C', X)
|
|
|
|
// urem C, (zext X) --> zext (urem C', X)
|
|
|
|
Value *NarrowOp = isa<Constant>(D) ? Builder.CreateBinOp(Opcode, X, TruncC)
|
|
|
|
: Builder.CreateBinOp(Opcode, TruncC, X);
|
|
|
|
return new ZExtInst(NarrowOp, Ty);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifyUDivInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2013-07-05 05:17:49 +08:00
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// Handle the integer div common cases
|
|
|
|
if (Instruction *Common = commonIDivTransforms(I))
|
|
|
|
return Common;
|
|
|
|
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2018-06-26 06:50:26 +08:00
|
|
|
Value *X;
|
|
|
|
const APInt *C1, *C2;
|
|
|
|
if (match(Op0, m_LShr(m_Value(X), m_APInt(C1))) && match(Op1, m_APInt(C2))) {
|
|
|
|
// (X lshr C1) udiv C2 --> X udiv (C2 << C1)
|
|
|
|
bool Overflow;
|
|
|
|
APInt C2ShlC1 = C2->ushl_ov(*C1, Overflow);
|
|
|
|
if (!Overflow) {
|
|
|
|
bool IsExact = I.isExact() && match(Op0, m_Exact(m_Value()));
|
|
|
|
BinaryOperator *BO = BinaryOperator::CreateUDiv(
|
|
|
|
X, ConstantInt::get(X->getType(), C2ShlC1));
|
|
|
|
if (IsExact)
|
|
|
|
BO->setIsExact();
|
|
|
|
return BO;
|
2014-10-14 05:48:30 +08:00
|
|
|
}
|
Revert r185257 (InstCombine: Be more agressive optimizing 'udiv' instrs with 'select' denoms)
I'm reverting this commit because:
1. As discussed during review, it needs to be rewritten (to avoid creating and
then deleting instructions).
2. This is causing optimizer crashes. Specifically, I'm seeing things like
this:
While deleting: i1 %
Use still stuck around after Def is destroyed: <badref> = select i1 <badref>, i32 0, i32 1
opt: /src/llvm-trunk/lib/IR/Value.cpp:79: virtual llvm::Value::~Value(): Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed.
I'd guess that these will go away once we're no longer creating/deleting
instructions here, but just in case, I'm adding a regression test.
Because the code is bring rewritten, I've just XFAIL'd the original regression test. Original commit message:
InstCombine: Be more agressive optimizing 'udiv' instrs with 'select' denoms
Real world code sometimes has the denominator of a 'udiv' be a
'select'. LLVM can handle such cases but only when the 'select'
operands are symmetric in structure (both select operands are a constant
power of two or a left shift, etc.). This falls apart if we are dealt a
'udiv' where the code is not symetric or if the select operands lead us
to more select instructions.
Instead, we should treat the LHS and each select operand as a distinct
divide operation and try to optimize them independently. If we can
to simplify each operation, then we can replace the 'udiv' with, say, a
'lshr' that has a new select with a bunch of new operands for the
select.
llvm-svn: 185415
2013-07-02 13:21:11 +08:00
|
|
|
}
|
|
|
|
|
2018-06-26 06:50:26 +08:00
|
|
|
// Op0 / C where C is large (negative) --> zext (Op0 >= C)
|
|
|
|
// TODO: Could use isKnownNegative() to handle non-constant values.
|
2018-06-26 20:41:15 +08:00
|
|
|
Type *Ty = I.getType();
|
2018-06-26 06:50:26 +08:00
|
|
|
if (match(Op1, m_Negative())) {
|
|
|
|
Value *Cmp = Builder.CreateICmpUGE(Op0, Op1);
|
2018-06-26 20:41:15 +08:00
|
|
|
return CastInst::CreateZExtOrBitCast(Cmp, Ty);
|
|
|
|
}
|
|
|
|
// Op0 / (sext i1 X) --> zext (Op0 == -1) (if X is 0, the div is undefined)
|
|
|
|
if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
|
|
|
|
Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::getAllOnesValue(Ty));
|
|
|
|
return CastInst::CreateZExtOrBitCast(Cmp, Ty);
|
2018-06-26 06:50:26 +08:00
|
|
|
}
|
|
|
|
|
2017-08-25 06:54:01 +08:00
|
|
|
if (Instruction *NarrowDiv = narrowUDivURem(I, Builder))
|
|
|
|
return NarrowDiv;
|
2011-05-01 02:16:07 +08:00
|
|
|
|
2018-07-27 03:22:41 +08:00
|
|
|
// If the udiv operands are non-overflowing multiplies with a common operand,
|
|
|
|
// then eliminate the common factor:
|
|
|
|
// (A * B) / (A * X) --> B / X (and commuted variants)
|
|
|
|
// TODO: The code would be reduced if we had m_c_NUWMul pattern matching.
|
|
|
|
// TODO: If -reassociation handled this generally, we could remove this.
|
|
|
|
Value *A, *B;
|
|
|
|
if (match(Op0, m_NUWMul(m_Value(A), m_Value(B)))) {
|
|
|
|
if (match(Op1, m_NUWMul(m_Specific(A), m_Value(X))) ||
|
|
|
|
match(Op1, m_NUWMul(m_Value(X), m_Specific(A))))
|
|
|
|
return BinaryOperator::CreateUDiv(B, X);
|
|
|
|
if (match(Op1, m_NUWMul(m_Specific(B), m_Value(X))) ||
|
|
|
|
match(Op1, m_NUWMul(m_Value(X), m_Specific(B))))
|
|
|
|
return BinaryOperator::CreateUDiv(A, X);
|
|
|
|
}
|
|
|
|
|
2013-07-05 05:17:49 +08:00
|
|
|
// (LHS udiv (select (select (...)))) -> (LHS >> (select (select (...))))
|
|
|
|
SmallVector<UDivFoldAction, 6> UDivActions;
|
|
|
|
if (visitUDivOperand(Op0, Op1, I, UDivActions))
|
|
|
|
for (unsigned i = 0, e = UDivActions.size(); i != e; ++i) {
|
|
|
|
FoldUDivOperandCb Action = UDivActions[i].FoldAction;
|
|
|
|
Value *ActionOp1 = UDivActions[i].OperandToFold;
|
|
|
|
Instruction *Inst;
|
|
|
|
if (Action)
|
|
|
|
Inst = Action(Op0, ActionOp1, I, *this);
|
|
|
|
else {
|
|
|
|
// This action joins two actions together. The RHS of this action is
|
|
|
|
// simply the last action we processed, we saved the LHS action index in
|
|
|
|
// the joining action.
|
|
|
|
size_t SelectRHSIdx = i - 1;
|
|
|
|
Value *SelectRHS = UDivActions[SelectRHSIdx].FoldResult;
|
|
|
|
size_t SelectLHSIdx = UDivActions[i].SelectLHSIdx;
|
|
|
|
Value *SelectLHS = UDivActions[SelectLHSIdx].FoldResult;
|
|
|
|
Inst = SelectInst::Create(cast<SelectInst>(ActionOp1)->getCondition(),
|
|
|
|
SelectLHS, SelectRHS);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is the last action to process, return it to the InstCombiner.
|
|
|
|
// Otherwise, we insert it before the UDiv and record it so that we may
|
|
|
|
// use it as part of a joining action (i.e., a SelectInst).
|
|
|
|
if (e - i != 1) {
|
|
|
|
Inst->insertBefore(&I);
|
|
|
|
UDivActions[i].FoldResult = Inst;
|
|
|
|
} else
|
|
|
|
return Inst;
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifySDivInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2011-01-29 00:51:11 +08:00
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Handle the integer div common cases
|
|
|
|
if (Instruction *Common = commonIDivTransforms(I))
|
|
|
|
return Common;
|
|
|
|
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2020-08-17 03:00:03 +08:00
|
|
|
Type *Ty = I.getType();
|
2018-06-26 05:39:41 +08:00
|
|
|
Value *X;
|
|
|
|
// sdiv Op0, -1 --> -Op0
|
|
|
|
// sdiv Op0, (sext i1 X) --> -Op0 (because if X is 0, the op is undefined)
|
|
|
|
if (match(Op1, m_AllOnes()) ||
|
|
|
|
(match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)))
|
|
|
|
return BinaryOperator::CreateNeg(Op0);
|
|
|
|
|
2019-04-09 23:13:03 +08:00
|
|
|
// X / INT_MIN --> X == INT_MIN
|
|
|
|
if (match(Op1, m_SignMask()))
|
2020-08-17 03:00:03 +08:00
|
|
|
return new ZExtInst(Builder.CreateICmpEQ(Op0, Op1), Ty);
|
2019-04-09 23:13:03 +08:00
|
|
|
|
2020-08-07 01:18:55 +08:00
|
|
|
// sdiv exact X, 1<<C --> ashr exact X, C iff 1<<C is non-negative
|
[InstCombine] Fold sdiv exact X, -1<<C --> -(ashr exact X, C)
While that does increases instruction count,
shift is obviously better than a division.
Name: base
Pre: (1<<C1) >= 0
%o0 = shl i8 1, C1
%r = sdiv exact i8 C0, %o0
=>
%r = ashr exact i8 C0, C1
Name: neg
%o0 = shl i8 -1, C1
%r = sdiv exact i8 C0, %o0
=>
%t0 = ashr exact i8 C0, C1
%r = sub i8 0, %t0
Name: reverse
Pre: C1 != 0 && C1 u< 8
%t0 = ashr exact i8 C0, C1
%r = sub i8 0, %t0
=>
%o0 = shl i8 -1, C1
%r = sdiv exact i8 C0, %o0
https://rise4fun.com/Alive/MRplf
2020-08-07 02:08:30 +08:00
|
|
|
// sdiv exact X, -1<<C --> -(ashr exact X, C)
|
|
|
|
if (I.isExact() && ((match(Op1, m_Power2()) && match(Op1, m_NonNegative())) ||
|
|
|
|
match(Op1, m_NegatedPower2()))) {
|
|
|
|
bool DivisorWasNegative = match(Op1, m_NegatedPower2());
|
|
|
|
if (DivisorWasNegative)
|
|
|
|
Op1 = ConstantExpr::getNeg(cast<Constant>(Op1));
|
|
|
|
auto *AShr = BinaryOperator::CreateExactAShr(
|
2020-10-11 17:31:17 +08:00
|
|
|
Op0, ConstantExpr::getExactLogBase2(cast<Constant>(Op1)), I.getName());
|
[InstCombine] Fold sdiv exact X, -1<<C --> -(ashr exact X, C)
While that does increases instruction count,
shift is obviously better than a division.
Name: base
Pre: (1<<C1) >= 0
%o0 = shl i8 1, C1
%r = sdiv exact i8 C0, %o0
=>
%r = ashr exact i8 C0, C1
Name: neg
%o0 = shl i8 -1, C1
%r = sdiv exact i8 C0, %o0
=>
%t0 = ashr exact i8 C0, C1
%r = sub i8 0, %t0
Name: reverse
Pre: C1 != 0 && C1 u< 8
%t0 = ashr exact i8 C0, C1
%r = sub i8 0, %t0
=>
%o0 = shl i8 -1, C1
%r = sdiv exact i8 C0, %o0
https://rise4fun.com/Alive/MRplf
2020-08-07 02:08:30 +08:00
|
|
|
if (!DivisorWasNegative)
|
|
|
|
return AShr;
|
|
|
|
Builder.Insert(AShr);
|
|
|
|
AShr->setName(I.getName() + ".neg");
|
|
|
|
return BinaryOperator::CreateNeg(AShr, I.getName());
|
|
|
|
}
|
2020-08-07 01:18:55 +08:00
|
|
|
|
2016-06-28 01:25:57 +08:00
|
|
|
const APInt *Op1C;
|
2016-06-28 02:38:40 +08:00
|
|
|
if (match(Op1, m_APInt(Op1C))) {
|
2016-06-28 06:27:11 +08:00
|
|
|
// If the dividend is sign-extended and the constant divisor is small enough
|
|
|
|
// to fit in the source type, shrink the division to the narrower type:
|
|
|
|
// (sext X) sdiv C --> sext (X sdiv C)
|
|
|
|
Value *Op0Src;
|
|
|
|
if (match(Op0, m_OneUse(m_SExt(m_Value(Op0Src)))) &&
|
|
|
|
Op0Src->getType()->getScalarSizeInBits() >= Op1C->getMinSignedBits()) {
|
|
|
|
|
|
|
|
// In the general case, we need to make sure that the dividend is not the
|
|
|
|
// minimum signed value because dividing that by -1 is UB. But here, we
|
|
|
|
// know that the -1 divisor case is already handled above.
|
|
|
|
|
|
|
|
Constant *NarrowDivisor =
|
|
|
|
ConstantExpr::getTrunc(cast<Constant>(Op1), Op0Src->getType());
|
2017-07-08 07:16:26 +08:00
|
|
|
Value *NarrowOp = Builder.CreateSDiv(Op0Src, NarrowDivisor);
|
2020-08-17 03:00:03 +08:00
|
|
|
return new SExtInst(NarrowOp, Ty);
|
2016-06-28 06:27:11 +08:00
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2019-04-09 23:13:03 +08:00
|
|
|
// -X / C --> X / -C (if the negation doesn't overflow).
|
|
|
|
// TODO: This could be enhanced to handle arbitrary vector constants by
|
|
|
|
// checking if all elements are not the min-signed-val.
|
|
|
|
if (!Op1C->isMinSignedValue() &&
|
|
|
|
match(Op0, m_NSWSub(m_Zero(), m_Value(X)))) {
|
2020-08-17 03:00:03 +08:00
|
|
|
Constant *NegC = ConstantInt::get(Ty, -(*Op1C));
|
2019-04-09 23:13:03 +08:00
|
|
|
Instruction *BO = BinaryOperator::CreateSDiv(X, NegC);
|
2014-11-23 04:00:34 +08:00
|
|
|
BO->setIsExact(I.isExact());
|
|
|
|
return BO;
|
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2019-04-10 14:52:09 +08:00
|
|
|
// -X / Y --> -(X / Y)
|
|
|
|
Value *Y;
|
|
|
|
if (match(&I, m_SDiv(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y))))
|
|
|
|
return BinaryOperator::CreateNSWNeg(
|
|
|
|
Builder.CreateSDiv(X, Y, I.getName(), I.isExact()));
|
|
|
|
|
2020-08-17 03:42:06 +08:00
|
|
|
// abs(X) / X --> X > -1 ? 1 : -1
|
|
|
|
// X / abs(X) --> X > -1 ? 1 : -1
|
|
|
|
if (match(&I, m_c_BinOp(
|
|
|
|
m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(X), m_One())),
|
|
|
|
m_Deferred(X)))) {
|
|
|
|
Constant *NegOne = ConstantInt::getAllOnesValue(Ty);
|
|
|
|
Value *Cond = Builder.CreateICmpSGT(X, NegOne);
|
|
|
|
return SelectInst::Create(Cond, ConstantInt::get(Ty, 1), NegOne);
|
|
|
|
}
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// If the sign bits of both operands are zero (i.e. we can prove they are
|
|
|
|
// unsigned inputs), turn this into a udiv.
|
2020-08-17 03:00:03 +08:00
|
|
|
APInt Mask(APInt::getSignMask(Ty->getScalarSizeInBits()));
|
2017-04-17 09:51:19 +08:00
|
|
|
if (MaskedValueIsZero(Op0, Mask, 0, &I)) {
|
|
|
|
if (MaskedValueIsZero(Op1, Mask, 0, &I)) {
|
|
|
|
// X sdiv Y -> X udiv Y, iff X and Y don't have sign bit set
|
|
|
|
auto *BO = BinaryOperator::CreateUDiv(Op0, Op1, I.getName());
|
|
|
|
BO->setIsExact(I.isExact());
|
|
|
|
return BO;
|
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
[InstCombine] Fold X sdiv (-1 << C) -> -(X u>> Y) iff X is non-negative
This is the one i'm seeing as missed optimization,
although there are likely other possibilities, as usual.
There are 4 variants of a general sdiv->udiv fold:
https://rise4fun.com/Alive/VS6
Name: v0
Pre: C0 >= 0 && C1 >= 0
%r = sdiv i8 C0, C1
=>
%r = udiv i8 C0, C1
Name: v1
Pre: C0 <= 0 && C1 >= 0
%r = sdiv i8 C0, C1
=>
%t0 = udiv i8 -C0, C1
%r = sub i8 0, %t0
Name: v2
Pre: C0 >= 0 && C1 <= 0
%r = sdiv i8 C0, C1
=>
%t0 = udiv i8 C0, -C1
%r = sub i8 0, %t0
Name: v3
Pre: C0 <= 0 && C1 <= 0
%r = sdiv i8 C0, C1
=>
%r = udiv i8 -C0, -C1
If we really don't like sdiv (more than udiv that is),
and are okay with increasing instruction count (2 new negations),
and we ensure that we don't undo the fold,
then we could just implement these..
2020-07-18 03:35:21 +08:00
|
|
|
if (match(Op1, m_NegatedPower2())) {
|
|
|
|
// X sdiv (-(1 << C)) -> -(X sdiv (1 << C)) ->
|
|
|
|
// -> -(X udiv (1 << C)) -> -(X u>> C)
|
|
|
|
return BinaryOperator::CreateNeg(Builder.Insert(foldUDivPow2Cst(
|
|
|
|
Op0, ConstantExpr::getNeg(cast<Constant>(Op1)), I, *this)));
|
|
|
|
}
|
|
|
|
|
2017-05-26 05:51:12 +08:00
|
|
|
if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
|
2017-04-17 09:51:19 +08:00
|
|
|
// X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y)
|
|
|
|
// Safe because the only negative value (1 << Y) can take on is
|
|
|
|
// INT_MIN, and X sdiv INT_MIN == X udiv INT_MIN == 0 if X doesn't have
|
|
|
|
// the sign bit set.
|
|
|
|
auto *BO = BinaryOperator::CreateUDiv(Op0, Op1, I.getName());
|
|
|
|
BO->setIsExact(I.isExact());
|
|
|
|
return BO;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2018-02-21 07:51:16 +08:00
|
|
|
/// Remove negation and try to convert division into multiplication.
|
2018-02-21 00:08:15 +08:00
|
|
|
static Instruction *foldFDivConstantDivisor(BinaryOperator &I) {
|
|
|
|
Constant *C;
|
|
|
|
if (!match(I.getOperand(1), m_Constant(C)))
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2014-01-19 21:36:27 +08:00
|
|
|
|
2018-02-21 07:51:16 +08:00
|
|
|
// -X / C --> X / -C
|
|
|
|
Value *X;
|
|
|
|
if (match(I.getOperand(0), m_FNeg(m_Value(X))))
|
2018-02-22 06:18:55 +08:00
|
|
|
return BinaryOperator::CreateFDivFMF(X, ConstantExpr::getFNeg(C), &I);
|
2018-02-21 07:51:16 +08:00
|
|
|
|
2018-02-21 00:08:15 +08:00
|
|
|
// If the constant divisor has an exact inverse, this is always safe. If not,
|
|
|
|
// then we can still create a reciprocal if fast-math-flags allow it and the
|
|
|
|
// constant is a regular number (not zero, infinite, or denormal).
|
|
|
|
if (!(C->hasExactInverseFP() || (I.hasAllowReciprocal() && C->isNormalFP())))
|
|
|
|
return nullptr;
|
2013-01-15 06:48:41 +08:00
|
|
|
|
2018-02-21 00:08:15 +08:00
|
|
|
// Disallow denormal constants because we don't know what would happen
|
|
|
|
// on all targets.
|
|
|
|
// TODO: Use Intrinsic::canonicalize or let function attributes tell us that
|
|
|
|
// denorms are flushed?
|
|
|
|
auto *RecipC = ConstantExpr::getFDiv(ConstantFP::get(I.getType(), 1.0), C);
|
|
|
|
if (!RecipC->isNormalFP())
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2013-01-15 06:48:41 +08:00
|
|
|
|
2018-02-21 07:51:16 +08:00
|
|
|
// X / C --> X * (1 / C)
|
2018-02-22 06:18:55 +08:00
|
|
|
return BinaryOperator::CreateFMulFMF(I.getOperand(0), RecipC, &I);
|
2013-01-15 06:48:41 +08:00
|
|
|
}
|
|
|
|
|
2018-02-21 08:01:45 +08:00
|
|
|
/// Remove negation and try to reassociate constant math.
|
2018-02-20 05:17:58 +08:00
|
|
|
static Instruction *foldFDivConstantDividend(BinaryOperator &I) {
|
2018-02-21 08:01:45 +08:00
|
|
|
Constant *C;
|
|
|
|
if (!match(I.getOperand(0), m_Constant(C)))
|
2018-02-20 05:17:58 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2018-02-21 08:01:45 +08:00
|
|
|
// C / -X --> -C / X
|
2018-02-20 05:17:58 +08:00
|
|
|
Value *X;
|
2018-02-22 06:18:55 +08:00
|
|
|
if (match(I.getOperand(1), m_FNeg(m_Value(X))))
|
|
|
|
return BinaryOperator::CreateFDivFMF(ConstantExpr::getFNeg(C), X, &I);
|
2018-02-21 08:01:45 +08:00
|
|
|
|
|
|
|
if (!I.hasAllowReassoc() || !I.hasAllowReciprocal())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Try to reassociate C / X expressions where X includes another constant.
|
2018-02-20 05:17:58 +08:00
|
|
|
Constant *C2, *NewC = nullptr;
|
|
|
|
if (match(I.getOperand(1), m_FMul(m_Value(X), m_Constant(C2)))) {
|
2018-02-21 08:01:45 +08:00
|
|
|
// C / (X * C2) --> (C / C2) / X
|
|
|
|
NewC = ConstantExpr::getFDiv(C, C2);
|
2018-02-20 05:17:58 +08:00
|
|
|
} else if (match(I.getOperand(1), m_FDiv(m_Value(X), m_Constant(C2)))) {
|
2018-02-21 08:01:45 +08:00
|
|
|
// C / (X / C2) --> (C * C2) / X
|
|
|
|
NewC = ConstantExpr::getFMul(C, C2);
|
2018-02-20 05:17:58 +08:00
|
|
|
}
|
|
|
|
// Disallow denormal constants because we don't know what would happen
|
|
|
|
// on all targets.
|
|
|
|
// TODO: Use Intrinsic::canonicalize or let function attributes tell us that
|
|
|
|
// denorms are flushed?
|
|
|
|
if (!NewC || !NewC->isNormalFP())
|
|
|
|
return nullptr;
|
|
|
|
|
2018-02-22 06:18:55 +08:00
|
|
|
return BinaryOperator::CreateFDivFMF(NewC, X, &I);
|
2018-02-20 05:17:58 +08:00
|
|
|
}
|
|
|
|
|
2021-02-25 04:31:59 +08:00
|
|
|
/// Negate the exponent of pow/exp to fold division-by-pow() into multiply.
|
|
|
|
static Instruction *foldFDivPowDivisor(BinaryOperator &I,
|
|
|
|
InstCombiner::BuilderTy &Builder) {
|
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
|
|
|
auto *II = dyn_cast<IntrinsicInst>(Op1);
|
|
|
|
if (!II || !II->hasOneUse() || !I.hasAllowReassoc() ||
|
|
|
|
!I.hasAllowReciprocal())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Z / pow(X, Y) --> Z * pow(X, -Y)
|
|
|
|
// Z / exp{2}(Y) --> Z * exp{2}(-Y)
|
|
|
|
// In the general case, this creates an extra instruction, but fmul allows
|
|
|
|
// for better canonicalization and optimization than fdiv.
|
|
|
|
Intrinsic::ID IID = II->getIntrinsicID();
|
|
|
|
SmallVector<Value *> Args;
|
|
|
|
switch (IID) {
|
|
|
|
case Intrinsic::pow:
|
|
|
|
Args.push_back(II->getArgOperand(0));
|
|
|
|
Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(1), &I));
|
|
|
|
break;
|
2021-03-27 04:02:26 +08:00
|
|
|
case Intrinsic::powi: {
|
2021-02-25 05:12:48 +08:00
|
|
|
// Require 'ninf' assuming that makes powi(X, -INT_MIN) acceptable.
|
|
|
|
// That is, X ** (huge negative number) is 0.0, ~1.0, or INF and so
|
|
|
|
// dividing by that is INF, ~1.0, or 0.0. Code that uses powi allows
|
|
|
|
// non-standard results, so this corner case should be acceptable if the
|
|
|
|
// code rules out INF values.
|
|
|
|
if (!I.hasNoInfs())
|
|
|
|
return nullptr;
|
|
|
|
Args.push_back(II->getArgOperand(0));
|
|
|
|
Args.push_back(Builder.CreateNeg(II->getArgOperand(1)));
|
2021-03-27 04:02:26 +08:00
|
|
|
Type *Tys[] = {I.getType(), II->getArgOperand(1)->getType()};
|
|
|
|
Value *Pow = Builder.CreateIntrinsic(IID, Tys, Args, &I);
|
|
|
|
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
|
|
|
|
}
|
2021-02-25 04:31:59 +08:00
|
|
|
case Intrinsic::exp:
|
|
|
|
case Intrinsic::exp2:
|
|
|
|
Args.push_back(Builder.CreateFNegFMF(II->getArgOperand(0), &I));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
Value *Pow = Builder.CreateIntrinsic(IID, I.getType(), Args, &I);
|
|
|
|
return BinaryOperator::CreateFMulFMF(Op0, Pow, &I);
|
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifyFDivInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
I.getFastMathFlags(),
|
2017-06-09 11:21:29 +08:00
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2011-01-30 01:50:27 +08:00
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2018-02-21 07:51:16 +08:00
|
|
|
if (Instruction *R = foldFDivConstantDivisor(I))
|
|
|
|
return R;
|
2018-02-20 07:09:03 +08:00
|
|
|
|
2018-02-21 07:51:16 +08:00
|
|
|
if (Instruction *R = foldFDivConstantDividend(I))
|
|
|
|
return R;
|
2018-02-15 07:04:17 +08:00
|
|
|
|
2020-06-20 23:47:00 +08:00
|
|
|
if (Instruction *R = foldFPSignBitOps(I))
|
2020-06-20 22:20:21 +08:00
|
|
|
return R;
|
|
|
|
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2013-07-20 15:13:13 +08:00
|
|
|
if (isa<Constant>(Op0))
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op1))
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
|
|
|
return R;
|
|
|
|
|
2018-02-21 01:14:53 +08:00
|
|
|
if (isa<Constant>(Op1))
|
2013-07-20 15:13:13 +08:00
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
|
|
|
return R;
|
2013-01-15 06:48:41 +08:00
|
|
|
|
2018-02-27 00:02:45 +08:00
|
|
|
if (I.hasAllowReassoc() && I.hasAllowReciprocal()) {
|
2013-01-15 06:48:41 +08:00
|
|
|
Value *X, *Y;
|
2018-02-17 01:52:32 +08:00
|
|
|
if (match(Op0, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) &&
|
|
|
|
(!isa<Constant>(Y) || !isa<Constant>(Op1))) {
|
|
|
|
// (X / Y) / Z => X / (Y * Z)
|
2018-02-27 00:02:45 +08:00
|
|
|
Value *YZ = Builder.CreateFMulFMF(Y, Op1, &I);
|
2018-02-22 06:18:55 +08:00
|
|
|
return BinaryOperator::CreateFDivFMF(X, YZ, &I);
|
2013-01-15 06:48:41 +08:00
|
|
|
}
|
2018-02-17 01:52:32 +08:00
|
|
|
if (match(Op1, m_OneUse(m_FDiv(m_Value(X), m_Value(Y)))) &&
|
|
|
|
(!isa<Constant>(Y) || !isa<Constant>(Op0))) {
|
|
|
|
// Z / (X / Y) => (Y * Z) / X
|
2018-02-27 00:02:45 +08:00
|
|
|
Value *YZ = Builder.CreateFMulFMF(Y, Op0, &I);
|
2018-02-22 06:18:55 +08:00
|
|
|
return BinaryOperator::CreateFDivFMF(YZ, X, &I);
|
2011-03-30 23:42:35 +08:00
|
|
|
}
|
2020-01-09 23:52:39 +08:00
|
|
|
// Z / (1.0 / Y) => (Y * Z)
|
|
|
|
//
|
|
|
|
// This is a special case of Z / (X / Y) => (Y * Z) / X, with X = 1.0. The
|
|
|
|
// m_OneUse check is avoided because even in the case of the multiple uses
|
|
|
|
// for 1.0/Y, the number of instructions remain the same and a division is
|
|
|
|
// replaced by a multiplication.
|
|
|
|
if (match(Op1, m_FDiv(m_SpecificFP(1.0), m_Value(Y))))
|
|
|
|
return BinaryOperator::CreateFMulFMF(Y, Op0, &I);
|
2011-03-30 23:42:35 +08:00
|
|
|
}
|
|
|
|
|
2018-02-15 23:07:12 +08:00
|
|
|
if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) {
|
2018-02-17 00:13:20 +08:00
|
|
|
// sin(X) / cos(X) -> tan(X)
|
|
|
|
// cos(X) / sin(X) -> 1/tan(X) (cotangent)
|
|
|
|
Value *X;
|
|
|
|
bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) &&
|
|
|
|
match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X)));
|
|
|
|
bool IsCot =
|
|
|
|
!IsTan && match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
|
|
|
|
match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
|
|
|
|
|
2019-08-10 00:04:18 +08:00
|
|
|
if ((IsTan || IsCot) &&
|
|
|
|
hasFloatFn(&TLI, I.getType(), LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) {
|
2018-02-17 00:13:20 +08:00
|
|
|
IRBuilder<> B(&I);
|
|
|
|
IRBuilder<>::FastMathFlagGuard FMFGuard(B);
|
|
|
|
B.setFastMathFlags(I.getFastMathFlags());
|
2019-02-01 01:23:29 +08:00
|
|
|
AttributeList Attrs =
|
|
|
|
cast<CallBase>(Op0)->getCalledFunction()->getAttributes();
|
Add a emitUnaryFloatFnCall version that fetches the function name from TLI
Summary:
In several places in the code we use the following pattern:
if (hasUnaryFloatFn(&TLI, Ty, LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) {
[...]
Value *Res = emitUnaryFloatFnCall(X, TLI.getName(LibFunc_tan), B, Attrs);
[...]
}
In short, we check if there is a lib-function for a certain type, and then
we _always_ fetch the name of the "double" version of the lib function and
construct a call to the appropriate function, that we just checked exists,
using that "double" name as a basis.
This is of course a problem in cases where the target doesn't support the
"double" version, but e.g. only the "float" version.
In that case TLI.getName(LibFunc_tan) returns "", and
emitUnaryFloatFnCall happily appends an "f" to "", and we erroneously end
up with a call to a function called "f".
To solve this, the above pattern is changed to
if (hasUnaryFloatFn(&TLI, Ty, LibFunc_tan, LibFunc_tanf, LibFunc_tanl)) {
[...]
Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
LibFunc_tanl, B, Attrs);
[...]
}
I.e instead of first fetching the name of the "double" version and then
letting emitUnaryFloatFnCall() add the final "f" or "l", we let
emitUnaryFloatFnCall() fetch the right name from TLI.
Reviewers: eli.friedman, efriedma
Reviewed By: efriedma
Subscribers: efriedma, bjope, llvm-commits
Differential Revision: https://reviews.llvm.org/D53370
llvm-svn: 344725
2018-10-18 14:27:53 +08:00
|
|
|
Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
|
|
|
|
LibFunc_tanl, B, Attrs);
|
2018-02-17 00:13:20 +08:00
|
|
|
if (IsCot)
|
|
|
|
Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
|
|
|
|
return replaceInstUsesWith(I, Res);
|
2018-01-11 14:33:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-13 03:39:21 +08:00
|
|
|
// X / (X * Y) --> 1.0 / Y
|
|
|
|
// Reassociate to (X / X -> 1.0) is legal when NaNs are not allowed.
|
|
|
|
// We can ignore the possibility that X is infinity because INF/INF is NaN.
|
2020-06-20 22:20:21 +08:00
|
|
|
Value *X, *Y;
|
2018-02-13 03:39:21 +08:00
|
|
|
if (I.hasNoNaNs() && I.hasAllowReassoc() &&
|
|
|
|
match(Op1, m_c_FMul(m_Specific(Op0), m_Value(Y)))) {
|
2020-03-29 23:08:04 +08:00
|
|
|
replaceOperand(I, 0, ConstantFP::get(I.getType(), 1.0));
|
|
|
|
replaceOperand(I, 1, Y);
|
2018-02-13 03:39:21 +08:00
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
|
2019-08-12 21:43:35 +08:00
|
|
|
// X / fabs(X) -> copysign(1.0, X)
|
|
|
|
// fabs(X) / X -> copysign(1.0, X)
|
|
|
|
if (I.hasNoNaNs() && I.hasNoInfs() &&
|
2020-10-01 21:42:16 +08:00
|
|
|
(match(&I, m_FDiv(m_Value(X), m_FAbs(m_Deferred(X)))) ||
|
|
|
|
match(&I, m_FDiv(m_FAbs(m_Value(X)), m_Deferred(X))))) {
|
2019-08-12 21:43:35 +08:00
|
|
|
Value *V = Builder.CreateBinaryIntrinsic(
|
|
|
|
Intrinsic::copysign, ConstantFP::get(I.getType(), 1.0), X, &I);
|
|
|
|
return replaceInstUsesWith(I, V);
|
|
|
|
}
|
2021-02-25 04:31:59 +08:00
|
|
|
|
|
|
|
if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
|
|
|
|
return Mul;
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2011-01-30 01:50:27 +08:00
|
|
|
}
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
/// This function implements the transforms common to both integer remainder
|
|
|
|
/// instructions (urem and srem). It is called by the visitors to those integer
|
|
|
|
/// remainder instructions.
|
2018-05-02 00:10:38 +08:00
|
|
|
/// Common integer remainder transforms
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::commonIRemTransforms(BinaryOperator &I) {
|
2010-01-05 14:09:35 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
|
|
|
|
Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to
transform:
A / ((1 << B) >>u 2)
into:
A >>u (B-2)
which we compile into:
_divu3: ## @divu3
leal -2(%rsi), %ecx
shrl %cl, %edi
movl %edi, %eax
ret
instead of:
_divu3: ## @divu3
movb %sil, %cl
movl $1, %esi
shll %cl, %esi
shrl $2, %esi
movl %edi, %eax
xorl %edx, %edx
divl %esi, %eax
ret
llvm-svn: 131860
2011-05-23 02:18:41 +08:00
|
|
|
// The RHS is known non-zero.
|
2020-03-29 23:08:04 +08:00
|
|
|
if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this, I))
|
|
|
|
return replaceOperand(I, 1, V);
|
Carve out a place in instcombine to put transformations which work knowing that their
result is non-zero. Implement an example optimization (PR9814), which allows us to
transform:
A / ((1 << B) >>u 2)
into:
A >>u (B-2)
which we compile into:
_divu3: ## @divu3
leal -2(%rsi), %ecx
shrl %cl, %edi
movl %edi, %eax
ret
instead of:
_divu3: ## @divu3
movb %sil, %cl
movl $1, %esi
shll %cl, %esi
shrl $2, %esi
movl %edi, %eax
xorl %edx, %edx
divl %esi, %eax
ret
llvm-svn: 131860
2011-05-23 02:18:41 +08:00
|
|
|
|
2011-05-03 00:27:02 +08:00
|
|
|
// Handle cases involving: rem X, (select Cond, Y, Z)
|
2017-10-07 07:20:16 +08:00
|
|
|
if (simplifyDivRemOfSelectWithZeroOp(I))
|
2011-05-03 00:27:02 +08:00
|
|
|
return &I;
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2014-01-19 23:24:22 +08:00
|
|
|
if (isa<Constant>(Op1)) {
|
2010-01-05 14:09:35 +08:00
|
|
|
if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
|
|
|
|
if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
|
|
|
|
if (Instruction *R = FoldOpIntoSelect(I, SI))
|
|
|
|
return R;
|
2017-04-15 03:20:12 +08:00
|
|
|
} else if (auto *PN = dyn_cast<PHINode>(Op0I)) {
|
2016-06-06 05:17:04 +08:00
|
|
|
const APInt *Op1Int;
|
|
|
|
if (match(Op1, m_APInt(Op1Int)) && !Op1Int->isMinValue() &&
|
|
|
|
(I.getOpcode() == Instruction::URem ||
|
|
|
|
!Op1Int->isMinSignedValue())) {
|
2017-04-15 03:20:12 +08:00
|
|
|
// foldOpIntoPhi will speculate instructions to the end of the PHI's
|
2016-06-06 05:17:04 +08:00
|
|
|
// predecessor blocks, so do this only if we know the srem or urem
|
|
|
|
// will not fault.
|
2017-04-15 03:20:12 +08:00
|
|
|
if (Instruction *NV = foldOpIntoPhi(I, PN))
|
2016-06-06 05:17:04 +08:00
|
|
|
return NV;
|
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// See if we can fold away this rem instruction.
|
|
|
|
if (SimplifyDemandedInstructionBits(I))
|
|
|
|
return &I;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitURem(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifyURemInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2011-05-03 00:27:02 +08:00
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
if (Instruction *common = commonIRemTransforms(I))
|
|
|
|
return common;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2017-08-25 06:54:01 +08:00
|
|
|
if (Instruction *NarrowRem = narrowUDivURem(I, Builder))
|
|
|
|
return NarrowRem;
|
2013-05-12 08:07:05 +08:00
|
|
|
|
2013-05-11 17:01:28 +08:00
|
|
|
// X urem Y -> X and Y-1, where Y is a power of 2,
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2018-06-27 00:30:00 +08:00
|
|
|
Type *Ty = I.getType();
|
2017-05-26 05:51:12 +08:00
|
|
|
if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) {
|
[InstCombine] Fold "x ?% y ==/!= 0" to "x & (y-1) ==/!= 0" iff y is power-of-two
Summary:
I have stumbled into this by accident while preparing to extend backend `x s% C ==/!= 0` handling.
While we did happen to handle this fold in most of the cases,
the folding is indirect - we fold `x u% y` to `x & (y-1)` (iff `y` is power-of-two),
or first turn `x s% -y` to `x u% y`; that does handle most of the cases.
But we can't turn `x s% INT_MIN` to `x u% -INT_MIN`,
and thus we end up being stuck with `(x s% INT_MIN) == 0`.
There is no such restriction for the more general fold:
https://rise4fun.com/Alive/IIeS
To be noted, the fold does not enforce that `y` is a constant,
so it may indeed increase instruction count.
This is consistent with what `x u% y`->`x & (y-1)` already does.
I think it makes sense, it's at most one (simple) extra instruction,
while `rem`ainder is really much more un-simple (and likely **very** costly).
Reviewers: spatel, RKSimon, nikic, xbolva00, craig.topper
Reviewed By: RKSimon
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65046
llvm-svn: 367322
2019-07-30 23:28:22 +08:00
|
|
|
// This may increase instruction count, we don't enforce that Y is a
|
|
|
|
// constant.
|
2018-06-27 00:30:00 +08:00
|
|
|
Constant *N1 = Constant::getAllOnesValue(Ty);
|
2017-07-08 07:16:26 +08:00
|
|
|
Value *Add = Builder.CreateAdd(Op1, N1);
|
2011-02-10 13:36:31 +08:00
|
|
|
return BinaryOperator::CreateAnd(Op0, Add);
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2013-07-13 09:16:47 +08:00
|
|
|
// 1 urem X -> zext(X != 1)
|
2019-12-03 01:10:05 +08:00
|
|
|
if (match(Op0, m_One())) {
|
|
|
|
Value *Cmp = Builder.CreateICmpNE(Op1, ConstantInt::get(Ty, 1));
|
|
|
|
return CastInst::CreateZExtOrBitCast(Cmp, Ty);
|
|
|
|
}
|
2013-07-13 09:16:47 +08:00
|
|
|
|
2016-09-23 06:36:26 +08:00
|
|
|
// X urem C -> X < C ? X : X - C, where C >= signbit.
|
2018-02-09 02:36:01 +08:00
|
|
|
if (match(Op1, m_Negative())) {
|
2017-07-08 07:16:26 +08:00
|
|
|
Value *Cmp = Builder.CreateICmpULT(Op0, Op1);
|
|
|
|
Value *Sub = Builder.CreateSub(Op0, Op1);
|
2016-09-23 06:36:26 +08:00
|
|
|
return SelectInst::Create(Cmp, Op0, Sub);
|
|
|
|
}
|
|
|
|
|
2018-06-27 00:30:00 +08:00
|
|
|
// If the divisor is a sext of a boolean, then the divisor must be max
|
|
|
|
// unsigned value (-1). Therefore, the remainder is Op0 unless Op0 is also
|
|
|
|
// max unsigned value. In that case, the remainder is 0:
|
|
|
|
// urem Op0, (sext i1 X) --> (Op0 == -1) ? 0 : Op0
|
|
|
|
Value *X;
|
|
|
|
if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
|
|
|
|
Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::getAllOnesValue(Ty));
|
|
|
|
return SelectInst::Create(Cmp, ConstantInt::getNullValue(Ty), Op0);
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitSRem(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifySRemInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2011-05-03 00:27:02 +08:00
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// Handle the integer rem common cases
|
|
|
|
if (Instruction *Common = commonIRemTransforms(I))
|
|
|
|
return Common;
|
2013-04-06 05:20:12 +08:00
|
|
|
|
2018-06-22 01:06:36 +08:00
|
|
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
2014-10-14 06:37:51 +08:00
|
|
|
{
|
|
|
|
const APInt *Y;
|
|
|
|
// X % -Y -> X % Y
|
2020-02-01 05:23:33 +08:00
|
|
|
if (match(Op1, m_Negative(Y)) && !Y->isMinSignedValue())
|
|
|
|
return replaceOperand(I, 1, ConstantInt::get(I.getType(), -*Y));
|
2014-10-14 06:37:51 +08:00
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2019-04-13 17:21:22 +08:00
|
|
|
// -X srem Y --> -(X srem Y)
|
|
|
|
Value *X, *Y;
|
|
|
|
if (match(&I, m_SRem(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y))))
|
2020-06-03 21:56:40 +08:00
|
|
|
return BinaryOperator::CreateNSWNeg(Builder.CreateSRem(X, Y));
|
2019-04-13 17:21:22 +08:00
|
|
|
|
2010-01-05 14:09:35 +08:00
|
|
|
// If the sign bits of both operands are zero (i.e. we can prove they are
|
|
|
|
// unsigned inputs), turn this into a urem.
|
2017-04-21 00:56:25 +08:00
|
|
|
APInt Mask(APInt::getSignMask(I.getType()->getScalarSizeInBits()));
|
2017-04-17 09:51:24 +08:00
|
|
|
if (MaskedValueIsZero(Op1, Mask, 0, &I) &&
|
|
|
|
MaskedValueIsZero(Op0, Mask, 0, &I)) {
|
|
|
|
// X srem Y -> X urem Y, iff X and Y don't have sign bit set
|
|
|
|
return BinaryOperator::CreateURem(Op0, Op1, I.getName());
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If it's a constant vector, flip any negative values positive.
|
2012-01-27 11:08:05 +08:00
|
|
|
if (isa<ConstantVector>(Op1) || isa<ConstantDataVector>(Op1)) {
|
|
|
|
Constant *C = cast<Constant>(Op1);
|
2020-09-01 03:17:51 +08:00
|
|
|
unsigned VWidth = cast<FixedVectorType>(C->getType())->getNumElements();
|
2010-01-05 14:09:35 +08:00
|
|
|
|
|
|
|
bool hasNegative = false;
|
2012-01-27 11:08:05 +08:00
|
|
|
bool hasMissing = false;
|
|
|
|
for (unsigned i = 0; i != VWidth; ++i) {
|
|
|
|
Constant *Elt = C->getAggregateElement(i);
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!Elt) {
|
2012-01-27 11:08:05 +08:00
|
|
|
hasMissing = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Elt))
|
2011-07-15 14:08:15 +08:00
|
|
|
if (RHS->isNegative())
|
2010-01-05 14:09:35 +08:00
|
|
|
hasNegative = true;
|
2012-01-27 11:08:05 +08:00
|
|
|
}
|
2010-01-05 14:09:35 +08:00
|
|
|
|
2012-01-27 11:08:05 +08:00
|
|
|
if (hasNegative && !hasMissing) {
|
2012-01-25 14:02:56 +08:00
|
|
|
SmallVector<Constant *, 16> Elts(VWidth);
|
2010-01-05 14:09:35 +08:00
|
|
|
for (unsigned i = 0; i != VWidth; ++i) {
|
2012-02-07 05:56:39 +08:00
|
|
|
Elts[i] = C->getAggregateElement(i); // Handle undef, etc.
|
2012-01-27 11:08:05 +08:00
|
|
|
if (ConstantInt *RHS = dyn_cast<ConstantInt>(Elts[i])) {
|
2011-07-15 14:08:15 +08:00
|
|
|
if (RHS->isNegative())
|
2010-01-05 14:09:35 +08:00
|
|
|
Elts[i] = cast<ConstantInt>(ConstantExpr::getNeg(RHS));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Constant *NewRHSV = ConstantVector::get(Elts);
|
2020-02-01 05:23:33 +08:00
|
|
|
if (NewRHSV != C) // Don't loop on -MININT
|
|
|
|
return replaceOperand(I, 1, NewRHSV);
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2010-01-05 14:09:35 +08:00
|
|
|
}
|
|
|
|
|
2020-06-03 21:56:40 +08:00
|
|
|
Instruction *InstCombinerImpl::visitFRem(BinaryOperator &I) {
|
2018-06-22 01:06:36 +08:00
|
|
|
if (Value *V = SimplifyFRemInst(I.getOperand(0), I.getOperand(1),
|
|
|
|
I.getFastMathFlags(),
|
2017-06-09 11:21:29 +08:00
|
|
|
SQ.getWithInstruction(&I)))
|
2016-02-02 06:23:39 +08:00
|
|
|
return replaceInstUsesWith(I, V);
|
2011-05-03 00:27:02 +08:00
|
|
|
|
2018-10-03 23:20:58 +08:00
|
|
|
if (Instruction *X = foldVectorBinop(I))
|
2018-06-03 00:27:44 +08:00
|
|
|
return X;
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2011-05-03 00:27:02 +08:00
|
|
|
}
|