This patch fixes issue with lowering below mentioned pattern :-

_foo:
        smull	 r0, r1, r1, r0
	smull	 r2, r3, r3, r2
	adds	r0, r2, r0
	adc	r1, r3, r1
	bx	lr

to

_foo:
        smull	 r0, r1, r1, r0
	smlal	 r0, r1, r3, r2
	bx	lr

llvm-svn: 226904
This commit is contained in:
Jyoti Allur 2015-01-23 09:10:03 +00:00
parent 494acc597f
commit f1d7050a25
2 changed files with 51 additions and 7 deletions

View File

@ -8058,29 +8058,35 @@ static SDValue AddCombineTo64bitMLAL(SDNode *AddcNode,
else
IsLeftOperandMUL = true;
if (MULOp == SDValue())
return SDValue();
return SDValue();
// Figure out the right opcode.
unsigned Opc = MULOp->getOpcode();
unsigned FinalOpc = (Opc == ISD::SMUL_LOHI) ? ARMISD::SMLAL : ARMISD::UMLAL;
// Figure out the high and low input values to the MLAL node.
SDValue* HiMul = &MULOp;
SDValue* HiAdd = nullptr;
SDValue* LoMul = nullptr;
SDValue* LowAdd = nullptr;
// Ensure that ADDE is from high result of ISD::SMUL_LOHI.
if ((AddeOp0 != MULOp.getValue(1)) && (AddeOp1 != MULOp.getValue(1)))
return SDValue();
if (IsLeftOperandMUL)
HiAdd = &AddeOp1;
else
HiAdd = &AddeOp0;
if (AddcOp0->getOpcode() == Opc) {
// Ensure that LoMul and LowAdd are taken from correct ISD::SMUL_LOHI node
// whose low result is fed to the ADDC we are checking.
if (AddcOp0 == MULOp.getValue(0)) {
LoMul = &AddcOp0;
LowAdd = &AddcOp1;
}
if (AddcOp1->getOpcode() == Opc) {
if (AddcOp1 == MULOp.getValue(0)) {
LoMul = &AddcOp1;
LowAdd = &AddcOp0;
}
@ -8088,9 +8094,6 @@ static SDValue AddCombineTo64bitMLAL(SDNode *AddcNode,
if (!LoMul)
return SDValue();
if (LoMul->getNode() != HiMul->getNode())
return SDValue();
// Create the merged node.
SelectionDAG &DAG = DCI.DAG;

View File

@ -75,3 +75,44 @@ define i64 @MACLongTest5(i64 %c, i32 %a, i32 %b) {
%add = add i64 %mul, %c
ret i64 %add
}
define i64 @MACLongTest6(i32 %a, i32 %b, i32 %c, i32 %d) {
;CHECK-LABEL: MACLongTest6:
;CHECK: smull r12, lr, r1, r0
;CHECK: smlal r12, lr, r3, r2
%conv = sext i32 %a to i64
%conv1 = sext i32 %b to i64
%mul = mul nsw i64 %conv1, %conv
%conv2 = sext i32 %c to i64
%conv3 = sext i32 %d to i64
%mul4 = mul nsw i64 %conv3, %conv2
%add = add nsw i64 %mul4, %mul
ret i64 %add
}
define i64 @MACLongTest7(i64 %acc, i32 %lhs, i32 %rhs) {
;CHECK-LABEL: MACLongTest7:
;CHECK-NOT: smlal
%conv = sext i32 %lhs to i64
%conv1 = sext i32 %rhs to i64
%mul = mul nsw i64 %conv1, %conv
%shl = shl i64 %mul, 32
%shr = lshr i64 %mul, 32
%or = or i64 %shl, %shr
%add = add i64 %or, %acc
ret i64 %add
}
define i64 @MACLongTest8(i64 %acc, i32 %lhs, i32 %rhs) {
;CHECK-LABEL: MACLongTest8:
;CHECK-NOT: smlal
%conv = zext i32 %lhs to i64
%conv1 = zext i32 %rhs to i64
%mul = mul nuw i64 %conv1, %conv
%and = and i64 %mul, 4294967295
%shl = shl i64 %mul, 32
%or = or i64 %and, %shl
%add = add i64 %or, %acc
ret i64 %add
}