@@ -816,6 +816,41 @@ static bool isMultiple(const APInt &C1, const APInt &C2, APInt &Quotient,
816
816
return Remainder.isMinValue ();
817
817
}
818
818
819
+ static Instruction *foldIDivShl (BinaryOperator &I,
820
+ InstCombiner::BuilderTy &Builder) {
821
+ assert ((I.getOpcode () == Instruction::SDiv ||
822
+ I.getOpcode () == Instruction::UDiv) &&
823
+ " Expected integer divide" );
824
+
825
+ bool IsSigned = I.getOpcode () == Instruction::SDiv;
826
+ Value *Op0 = I.getOperand (0 ), *Op1 = I.getOperand (1 );
827
+ Type *Ty = I.getType ();
828
+
829
+ // With appropriate no-wrap constraints, remove a common factor in the
830
+ // dividend and divisor that is disguised as a left-shift.
831
+ Value *X, *Y, *Z;
832
+ if (match (Op1, m_Shl (m_Value (X), m_Value (Z))) &&
833
+ match (Op0, m_c_Mul (m_Specific (X), m_Value (Y)))) {
834
+ // Both operands must have the matching no-wrap for this kind of division.
835
+ auto *Mul = cast<OverflowingBinaryOperator>(Op0);
836
+ auto *Shl = cast<OverflowingBinaryOperator>(Op1);
837
+ bool HasNUW = Mul->hasNoUnsignedWrap () && Shl->hasNoUnsignedWrap ();
838
+ bool HasNSW = Mul->hasNoSignedWrap () && Shl->hasNoSignedWrap ();
839
+
840
+ // (X * Y) u/ (X << Z) --> Y u>> Z
841
+ if (!IsSigned && HasNUW)
842
+ return BinaryOperator::CreateLShr (Y, Z);
843
+
844
+ // (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
845
+ if (IsSigned && HasNSW && (Op0->hasOneUse () || Op1->hasOneUse ())) {
846
+ Value *Shl = Builder.CreateShl (ConstantInt::get (Ty, 1 ), Z);
847
+ return BinaryOperator::CreateSDiv (Y, Shl);
848
+ }
849
+ }
850
+
851
+ return nullptr ;
852
+ }
853
+
819
854
// / This function implements the transforms common to both integer division
820
855
// / instructions (udiv and sdiv). It is called by the visitors to those integer
821
856
// / division instructions.
@@ -962,26 +997,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
962
997
}
963
998
}
964
999
965
- // With appropriate no-wrap constraints, remove a common factor in the
966
- // dividend and divisor that is disguised as a left-shift.
967
- if (match (Op1, m_Shl (m_Value (X), m_Value (Z))) &&
968
- match (Op0, m_c_Mul (m_Specific (X), m_Value (Y)))) {
969
- // Both operands must have the matching no-wrap for this kind of division.
970
- auto *OBO0 = cast<OverflowingBinaryOperator>(Op0);
971
- auto *OBO1 = cast<OverflowingBinaryOperator>(Op1);
972
- bool HasNUW = OBO0->hasNoUnsignedWrap () && OBO1->hasNoUnsignedWrap ();
973
- bool HasNSW = OBO0->hasNoSignedWrap () && OBO1->hasNoSignedWrap ();
974
-
975
- // (X * Y) u/ (X << Z) --> Y u>> Z
976
- if (!IsSigned && HasNUW)
977
- return BinaryOperator::CreateLShr (Y, Z);
978
-
979
- // (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
980
- if (IsSigned && HasNSW && (Op0->hasOneUse () || Op1->hasOneUse ())) {
981
- Value *Shl = Builder.CreateShl (ConstantInt::get (Ty, 1 ), Z);
982
- return BinaryOperator::CreateSDiv (Y, Shl);
983
- }
984
- }
1000
+ if (Instruction *R = foldIDivShl (I, Builder))
1001
+ return R;
985
1002
986
1003
// With the appropriate no-wrap constraint, remove a multiply by the divisor
987
1004
// after peeking through another divide:
0 commit comments