diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index c83f7b194ae8..773b710ab051 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -8342,6 +8342,13 @@ static SDValue PerformSUBCombine(SDNode *N, /// is faster than /// vadd d3, d0, d1 /// vmul d3, d3, d2 +// However, for (A + B) * (A + B), +// vadd d2, d0, d1 +// vmul d3, d0, d2 +// vmla d3, d1, d2 +// is slower than +// vadd d2, d0, d1 +// vmul d3, d2, d2 static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget) { @@ -8361,6 +8368,9 @@ static SDValue PerformVMULCombine(SDNode *N, std::swap(N0, N1); } + if (N0 == N1) + return SDValue(); + EVT VT = N->getValueType(0); SDLoc DL(N); SDValue N00 = N0->getOperand(0); diff --git a/llvm/test/CodeGen/ARM/vmul.ll b/llvm/test/CodeGen/ARM/vmul.ll index 5e5e99bc2f96..de329acdf3c7 100644 --- a/llvm/test/CodeGen/ARM/vmul.ll +++ b/llvm/test/CodeGen/ARM/vmul.ll @@ -515,6 +515,17 @@ entry: ret void } +define <8 x i8> @no_distribute(<8 x i8> %a, <8 x i8> %b) nounwind { +entry: +; CHECK: no_distribute +; CHECK: vadd.i8 +; CHECK: vmul.i8 +; CHECK-NOT: vmla.i8 + %0 = add <8 x i8> %a, %b + %1 = mul <8x i8> %0, %0 + ret <8 x i8> %1 +} + ; If one operand has a zero-extend and the other a sign-extend, vmull ; cannot be used. define i16 @vmullWithInconsistentExtensions(<8 x i8> %vec) {