mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[DAGCombiner][X86][ARM] Teach visitMULO to fold multiplies with 0 to 0 and no carry.
I modified the ARM test to use two inputs instead of 0 so the test hopefully still tests what was intended. llvm-svn: 371344
This commit is contained in:
parent
09af94b030
commit
9078ffc0a4
@ -4404,13 +4404,29 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDValue DAGCombiner::visitMULO(SDNode *N) {
|
SDValue DAGCombiner::visitMULO(SDNode *N) {
|
||||||
|
SDValue N0 = N->getOperand(0);
|
||||||
|
SDValue N1 = N->getOperand(1);
|
||||||
|
EVT VT = N0.getValueType();
|
||||||
bool IsSigned = (ISD::SMULO == N->getOpcode());
|
bool IsSigned = (ISD::SMULO == N->getOpcode());
|
||||||
|
|
||||||
|
EVT CarryVT = N->getValueType(1);
|
||||||
|
SDLoc DL(N);
|
||||||
|
|
||||||
|
// canonicalize constant to RHS.
|
||||||
|
if (DAG.isConstantIntBuildVectorOrConstantInt(N0) &&
|
||||||
|
!DAG.isConstantIntBuildVectorOrConstantInt(N1))
|
||||||
|
return DAG.getNode(N->getOpcode(), DL, N->getVTList(), N1, N0);
|
||||||
|
|
||||||
|
// fold (mulo x, 0) -> 0 + no carry out
|
||||||
|
if (isNullOrNullSplat(N1))
|
||||||
|
return CombineTo(N, DAG.getConstant(0, DL, VT),
|
||||||
|
DAG.getConstant(0, DL, CarryVT));
|
||||||
|
|
||||||
// (mulo x, 2) -> (addo x, x)
|
// (mulo x, 2) -> (addo x, x)
|
||||||
if (ConstantSDNode *C2 = isConstOrConstSplat(N->getOperand(1)))
|
if (ConstantSDNode *C2 = isConstOrConstSplat(N1))
|
||||||
if (C2->getAPIntValue() == 2)
|
if (C2->getAPIntValue() == 2)
|
||||||
return DAG.getNode(IsSigned ? ISD::SADDO : ISD::UADDO, SDLoc(N),
|
return DAG.getNode(IsSigned ? ISD::SADDO : ISD::UADDO, DL,
|
||||||
N->getVTList(), N->getOperand(0), N->getOperand(0));
|
N->getVTList(), N0, N0);
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
@ -143,11 +143,11 @@ define float @f12(i32 %a, i32 %b) nounwind uwtable readnone ssp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
; CHECK-LABEL: test_overflow_recombine:
|
; CHECK-LABEL: test_overflow_recombine:
|
||||||
define i1 @test_overflow_recombine(i32 %in) {
|
define i1 @test_overflow_recombine(i32 %in1, i32 %in2) {
|
||||||
; CHECK: smull [[LO:r[0-9]+]], [[HI:r[0-9]+]]
|
; CHECK: smull [[LO:r[0-9]+]], [[HI:r[0-9]+]]
|
||||||
; CHECK: subs [[ZERO:r[0-9]+]], [[HI]], [[LO]], asr #31
|
; CHECK: subs [[ZERO:r[0-9]+]], [[HI]], [[LO]], asr #31
|
||||||
; CHECK: movne [[ZERO]], #1
|
; CHECK: movne [[ZERO]], #1
|
||||||
%prod = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 0, i32 %in)
|
%prod = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %in1, i32 %in2)
|
||||||
%overflow = extractvalue { i32, i1 } %prod, 1
|
%overflow = extractvalue { i32, i1 } %prod, 1
|
||||||
ret i1 %overflow
|
ret i1 %overflow
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,14 @@ define {i64, i1} @t1() nounwind {
|
|||||||
define {i64, i1} @t2() nounwind {
|
define {i64, i1} @t2() nounwind {
|
||||||
; SDAG-LABEL: t2:
|
; SDAG-LABEL: t2:
|
||||||
; SDAG: ## %bb.0:
|
; SDAG: ## %bb.0:
|
||||||
; SDAG-NEXT: xorl %ecx, %ecx
|
; SDAG-NEXT: xorl %eax, %eax
|
||||||
; SDAG-NEXT: movl $9, %eax
|
; SDAG-NEXT: xorl %edx, %edx
|
||||||
; SDAG-NEXT: mulq %rcx
|
|
||||||
; SDAG-NEXT: seto %dl
|
|
||||||
; SDAG-NEXT: retq
|
; SDAG-NEXT: retq
|
||||||
;
|
;
|
||||||
; FAST-LABEL: t2:
|
; FAST-LABEL: t2:
|
||||||
; FAST: ## %bb.0:
|
; FAST: ## %bb.0:
|
||||||
; FAST-NEXT: xorl %ecx, %ecx
|
; FAST-NEXT: xorl %eax, %eax
|
||||||
; FAST-NEXT: movl $9, %eax
|
; FAST-NEXT: xorl %edx, %edx
|
||||||
; FAST-NEXT: mulq %rcx
|
|
||||||
; FAST-NEXT: seto %dl
|
|
||||||
; FAST-NEXT: retq
|
; FAST-NEXT: retq
|
||||||
%1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 0)
|
%1 = call {i64, i1} @llvm.umul.with.overflow.i64(i64 9, i64 0)
|
||||||
ret {i64, i1} %1
|
ret {i64, i1} %1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user