@@ -1554,7 +1554,11 @@ static bool leftDistributesOverRight(Instruction::BinaryOps LOp, bool HasNUW,
1554
1554
switch (ROp) {
1555
1555
case Intrinsic::umax:
1556
1556
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 ;
1558
1562
case Intrinsic::smax:
1559
1563
case Intrinsic::smin:
1560
1564
return HasNSW && LOp == Instruction::Add;
@@ -1592,29 +1596,37 @@ foldIntrinsicUsingDistributiveLaws(IntrinsicInst *II,
1592
1596
if (!leftDistributesOverRight (InnerOpcode, HasNUW, HasNSW, TopLevelOpcode))
1593
1597
return nullptr ;
1594
1598
1595
- assert (II->isCommutative () && Op0->isCommutative () &&
1596
- " Only inner and outer commutative op codes are supported." );
1597
-
1598
1599
Value *A = Op0->getOperand (0 );
1599
1600
Value *B = Op0->getOperand (1 );
1600
1601
Value *C = Op1->getOperand (0 );
1601
1602
Value *D = Op1->getOperand (1 );
1602
1603
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)
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) {
1607
+ if (A == D || B == C)
1608
1608
std::swap (C, D);
1609
+ else
1610
+ return nullptr ;
1611
+ }
1612
+
1613
+ BinaryOperator *NewBinop;
1614
+ if (A == C) {
1609
1615
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;
1616
+ NewBinop =
1617
+ cast<BinaryOperator>(Builder.CreateBinOp (InnerOpcode, A, NewIntrinsic));
1618
+ } else if (B == D) {
1619
+ Value *NewIntrinsic = Builder.CreateBinaryIntrinsic (TopLevelOpcode, A, C);
1620
+ NewBinop =
1621
+ cast<BinaryOperator>(Builder.CreateBinOp (InnerOpcode, NewIntrinsic, B));
1622
+ } else {
1623
+ return nullptr ;
1615
1624
}
1616
1625
1617
- return nullptr ;
1626
+ NewBinop->setHasNoUnsignedWrap (HasNUW);
1627
+ NewBinop->setHasNoSignedWrap (HasNSW);
1628
+
1629
+ return NewBinop;
1618
1630
}
1619
1631
1620
1632
// / CallInst simplification. This mostly only handles folding of intrinsic
@@ -1887,6 +1899,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
1887
1899
if (Instruction *I = foldMaxMulShift (I1, I0))
1888
1900
return I;
1889
1901
}
1902
+
1890
1903
// If both operands of unsigned min/max are sign-extended, it is still ok
1891
1904
// to narrow the operation.
1892
1905
[[fallthrough]];
0 commit comments