mirror of
https://github.com/intel/llvm.git
synced 2026-01-14 03:50:17 +08:00
[InstCombine] Extend 0 - (X sdiv C) -> (X sdiv -C) fold to non-splat vectors
Split off from https://reviews.llvm.org/D68408
This commit is contained in:
@@ -53,6 +53,10 @@ public:
|
||||
/// Returns true if the value is one.
|
||||
bool isOneValue() const;
|
||||
|
||||
/// Return true if the value is not the one value, or,
|
||||
/// for vectors, does not contain one value elements.
|
||||
bool isNotOneValue() const;
|
||||
|
||||
/// Return true if this is the value that would be returned by
|
||||
/// getAllOnesValue.
|
||||
bool isAllOnesValue() const;
|
||||
@@ -64,7 +68,8 @@ public:
|
||||
/// Return true if the value is negative zero or null value.
|
||||
bool isZeroValue() const;
|
||||
|
||||
/// Return true if the value is not the smallest signed value.
|
||||
/// Return true if the value is not the smallest signed value, or,
|
||||
/// for vectors, does not contain smallest signed value elements.
|
||||
bool isNotMinSignedValue() const;
|
||||
|
||||
/// Return true if the value is the smallest signed value.
|
||||
|
||||
@@ -150,6 +150,30 @@ bool Constant::isOneValue() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Constant::isNotOneValue() const {
|
||||
// Check for 1 integers
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
return !CI->isOneValue();
|
||||
|
||||
// Check for FP which are bitcasted from 1 integers
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
|
||||
return !CFP->getValueAPF().bitcastToAPInt().isOneValue();
|
||||
|
||||
// Check that vectors don't contain 1
|
||||
if (this->getType()->isVectorTy()) {
|
||||
unsigned NumElts = this->getType()->getVectorNumElements();
|
||||
for (unsigned i = 0; i != NumElts; ++i) {
|
||||
Constant *Elt = this->getAggregateElement(i);
|
||||
if (!Elt || !Elt->isNotOneValue())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// It *may* contain 1, we can't tell.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Constant::isMinSignedValue() const {
|
||||
// Check for INT_MIN integers
|
||||
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
|
||||
|
||||
@@ -1896,14 +1896,16 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
Builder.CreateNot(Y, Y->getName() + ".not"));
|
||||
|
||||
// 0 - (X sdiv C) -> (X sdiv -C) provided the negation doesn't overflow.
|
||||
// TODO: This could be extended to match arbitrary vector constants.
|
||||
const APInt *DivC;
|
||||
if (match(Op0, m_Zero()) && match(Op1, m_SDiv(m_Value(X), m_APInt(DivC))) &&
|
||||
!DivC->isMinSignedValue() && *DivC != 1) {
|
||||
Constant *NegDivC = ConstantInt::get(I.getType(), -(*DivC));
|
||||
Instruction *BO = BinaryOperator::CreateSDiv(X, NegDivC);
|
||||
BO->setIsExact(cast<BinaryOperator>(Op1)->isExact());
|
||||
return BO;
|
||||
if (match(Op0, m_Zero())) {
|
||||
Constant *Op11C;
|
||||
if (match(Op1, m_SDiv(m_Value(X), m_Constant(Op11C))) &&
|
||||
!Op11C->containsUndefElement() && Op11C->isNotMinSignedValue() &&
|
||||
Op11C->isNotOneValue()) {
|
||||
Instruction *BO =
|
||||
BinaryOperator::CreateSDiv(X, ConstantExpr::getNeg(Op11C));
|
||||
BO->setIsExact(cast<BinaryOperator>(Op1)->isExact());
|
||||
return BO;
|
||||
}
|
||||
}
|
||||
|
||||
// 0 - (X << Y) -> (-X << Y) when X is freely negatable.
|
||||
|
||||
@@ -522,8 +522,7 @@ define <2 x i8> @sdiv_negated_dividend_constant_divisor_vec_undef(<2 x i8> %x) {
|
||||
|
||||
define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) {
|
||||
; CHECK-LABEL: @sdiv_negated_dividend_constant_divisor_vec(
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = sdiv <2 x i64> [[X:%.*]], <i64 3, i64 4>
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV1]]
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
|
||||
; CHECK-NEXT: ret <2 x i64> [[DIV]]
|
||||
;
|
||||
%neg = sub nsw <2 x i64> zeroinitializer, %x
|
||||
@@ -533,8 +532,7 @@ define <2 x i64> @sdiv_negated_dividend_constant_divisor_vec(<2 x i64> %x) {
|
||||
|
||||
define <2 x i64> @sdiv_exact_negated_dividend_constant_divisor_vec(<2 x i64> %x) {
|
||||
; CHECK-LABEL: @sdiv_exact_negated_dividend_constant_divisor_vec(
|
||||
; CHECK-NEXT: [[DIV1:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 3, i64 4>
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV1]]
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
|
||||
; CHECK-NEXT: ret <2 x i64> [[DIV]]
|
||||
;
|
||||
%neg = sub nsw <2 x i64> zeroinitializer, %x
|
||||
@@ -860,8 +858,7 @@ define i32 @test_exact_nsw_exact(i32 %x) {
|
||||
|
||||
define <2 x i64> @test_exact_vec(<2 x i64> %x) {
|
||||
; CHECK-LABEL: @test_exact_vec(
|
||||
; CHECK-NEXT: [[DIV:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 3, i64 4>
|
||||
; CHECK-NEXT: [[NEG:%.*]] = sub nsw <2 x i64> zeroinitializer, [[DIV]]
|
||||
; CHECK-NEXT: [[NEG:%.*]] = sdiv exact <2 x i64> [[X:%.*]], <i64 -3, i64 -4>
|
||||
; CHECK-NEXT: ret <2 x i64> [[NEG]]
|
||||
;
|
||||
%div = sdiv exact <2 x i64> %x, <i64 3, i64 4>
|
||||
|
||||
Reference in New Issue
Block a user