@@ -1554,7 +1554,11 @@ static bool leftDistributesOverRight(Instruction::BinaryOps LOp, bool HasNUW,
15541554 switch (ROp) {
15551555 case Intrinsic::umax:
15561556 case Intrinsic::umin:
1557- return HasNUW && LOp == Instruction::Add;
1557+ if (HasNUW && LOp == Instruction::Add)
1558+ return true ;
1559+ if (HasNUW && LOp == Instruction::Shl)
1560+ return true ;
1561+ return false ;
15581562 case Intrinsic::smax:
15591563 case Intrinsic::smin:
15601564 return HasNSW && LOp == Instruction::Add;
@@ -1592,29 +1596,34 @@ foldIntrinsicUsingDistributiveLaws(IntrinsicInst *II,
15921596 if (!leftDistributesOverRight (InnerOpcode, HasNUW, HasNSW, TopLevelOpcode))
15931597 return nullptr ;
15941598
1595- assert (II->isCommutative () && Op0->isCommutative () &&
1596- " Only inner and outer commutative op codes are supported." );
1597-
15981599 Value *A = Op0->getOperand (0 );
15991600 Value *B = Op0->getOperand (1 );
16001601 Value *C = Op1->getOperand (0 );
16011602 Value *D = Op1->getOperand (1 );
16021603
1603- // Attempts to swap variables such that A always equals C
1604- if (A != C && A != D)
1605- std::swap (A, B);
1606- if (A == C || A == D) {
1607- if (A != C)
1608- std::swap (C, D);
1604+ // Attempts to swap variables such that A equals C or B equals D,
1605+ // if the inner operation is commutative.
1606+ if (Op0->isCommutative () && A != C && B != D && A == D)
1607+ std::swap (C, D);
1608+
1609+ if (A != C && B != D)
1610+ return nullptr ;
1611+
1612+ BinaryOperator *NewBinop;
1613+ if (A == C) {
16091614 Value *NewIntrinsic = Builder.CreateBinaryIntrinsic (TopLevelOpcode, B, D);
1610- BinaryOperator *NewBinop =
1611- cast<BinaryOperator>(Builder.CreateBinOp (InnerOpcode, NewIntrinsic, A));
1612- NewBinop->setHasNoSignedWrap (HasNSW);
1613- NewBinop->setHasNoUnsignedWrap (HasNUW);
1614- return NewBinop;
1615+ NewBinop =
1616+ cast<BinaryOperator>(Builder.CreateBinOp (InnerOpcode, A, NewIntrinsic));
1617+ } else { // B == D
1618+ Value *NewIntrinsic = Builder.CreateBinaryIntrinsic (TopLevelOpcode, A, C);
1619+ NewBinop =
1620+ cast<BinaryOperator>(Builder.CreateBinOp (InnerOpcode, NewIntrinsic, B));
16151621 }
16161622
1617- return nullptr ;
1623+ NewBinop->setHasNoUnsignedWrap (HasNUW);
1624+ NewBinop->setHasNoSignedWrap (HasNSW);
1625+
1626+ return NewBinop;
16181627}
16191628
16201629// / CallInst simplification. This mostly only handles folding of intrinsic
@@ -1888,29 +1897,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
18881897 return I;
18891898 }
18901899
1891- Value *CommonShlOperand;
1892- BinaryOperator *NewShl = nullptr ;
1893- // umax(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umax(x, y))
1894- // umin(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umin(x, y))
1895- if (match (I0, m_OneUse (m_NUWShl (m_Value (CommonShlOperand), m_Value (X)))) &&
1896- match (I1,
1897- m_OneUse (m_NUWShl (m_Deferred (CommonShlOperand), m_Value (Y))))) {
1898- Value *MaxMin = Builder.CreateBinaryIntrinsic (IID, X, Y);
1899- NewShl = BinaryOperator::CreateNUWShl (CommonShlOperand, MaxMin);
1900- } else if (match (I0, m_OneUse (m_NUWShl (m_Value (X),
1901- m_Value (CommonShlOperand)))) &&
1902- match (I1, m_OneUse (m_NUWShl (m_Value (Y),
1903- m_Deferred (CommonShlOperand))))) {
1904- Value *MaxMin = Builder.CreateBinaryIntrinsic (IID, X, Y);
1905- NewShl = BinaryOperator::CreateNUWShl (MaxMin, CommonShlOperand);
1906- }
1907- if (NewShl) {
1908- if (cast<BinaryOperator>(I0)->hasNoSignedWrap () &&
1909- cast<BinaryOperator>(I1)->hasNoSignedWrap ())
1910- NewShl->setHasNoSignedWrap ();
1911- return NewShl;
1912- }
1913-
19141900 // If both operands of unsigned min/max are sign-extended, it is still ok
19151901 // to narrow the operation.
19161902 [[fallthrough]];
0 commit comments