[DAG] Add basic mul-with-overflow constant folding support

As noticed on D97160
This commit is contained in:
Simon Pilgrim 2021-02-24 11:08:49 +00:00
parent a4f9c0f562
commit 8082bfe7e5
2 changed files with 22 additions and 12 deletions

View File

@ -4638,6 +4638,21 @@ SDValue DAGCombiner::visitMULO(SDNode *N) {
EVT CarryVT = N->getValueType(1);
SDLoc DL(N);
ConstantSDNode *N0C = isConstOrConstSplat(N0);
ConstantSDNode *N1C = isConstOrConstSplat(N1);
// fold operation with constant operands.
// TODO: Move this to FoldConstantArithmetic when it supports nodes with
// multiple results.
if (N0C && N1C) {
bool Overflow;
APInt Result =
IsSigned ? N0C->getAPIntValue().smul_ov(N1C->getAPIntValue(), Overflow)
: N0C->getAPIntValue().umul_ov(N1C->getAPIntValue(), Overflow);
return CombineTo(N, DAG.getConstant(Result, DL, VT),
DAG.getBoolConstant(Overflow, DL, CarryVT, CarryVT));
}
// canonicalize constant to RHS.
if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
!DAG.isConstantIntBuildVectorOrConstantInt(N1))
@ -4649,10 +4664,9 @@ SDValue DAGCombiner::visitMULO(SDNode *N) {
DAG.getConstant(0, DL, CarryVT));
// (mulo x, 2) -> (addo x, x)
if (ConstantSDNode *C2 = isConstOrConstSplat(N1))
if (C2->getAPIntValue() == 2)
return DAG.getNode(IsSigned ? ISD::SADDO : ISD::UADDO, DL,
N->getVTList(), N0, N0);
if (N1C && N1C->getAPIntValue() == 2)
return DAG.getNode(IsSigned ? ISD::SADDO : ISD::UADDO, DL,
N->getVTList(), N0, N0);
return SDValue();
}

View File

@ -6,10 +6,8 @@
define {i64, i1} @t1() nounwind {
; CHECK-LABEL: t1:
; CHECK: ## %bb.0:
; CHECK-NEXT: movl $8, %ecx
; CHECK-NEXT: movl $9, %eax
; CHECK-NEXT: mulq %rcx
; CHECK-NEXT: seto %dl
; CHECK-NEXT: movl $72, %eax
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: retq
%1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 8)
ret {i64, i1} %1
@ -28,10 +26,8 @@ define {i64, i1} @t2() nounwind {
define {i64, i1} @t3() nounwind {
; CHECK-LABEL: t3:
; CHECK: ## %bb.0:
; CHECK-NEXT: movq $-1, %rcx
; CHECK-NEXT: movl $9, %eax
; CHECK-NEXT: mulq %rcx
; CHECK-NEXT: seto %dl
; CHECK-NEXT: movq $-9, %rax
; CHECK-NEXT: movb $1, %dl
; CHECK-NEXT: retq
%1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 -1)
ret {i64, i1} %1