diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3058,6 +3058,15 @@ } } + // add (mul x, C), x -> mul x, C+1 + if (N0.getOpcode() == ISD::MUL && N0.getOperand(0) == N1 && + isConstantOrConstantVector(N0.getOperand(1), /*NoOpaques=*/true) && + N0.hasOneUse()) { + SDValue NewC = DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(1), + DAG.getConstant(1, DL, VT)); + return DAG.getNode(ISD::MUL, DL, VT, N0.getOperand(0), NewC); + } + // If the target's bool is represented as 0/1, prefer to make this 'sub 0/1' // rather than 'add 0/-1' (the zext should get folded). // add (sext i1 Y), X --> sub X, (zext i1 Y) diff --git a/llvm/test/CodeGen/AArch64/arm64-promote-const.ll b/llvm/test/CodeGen/AArch64/arm64-promote-const.ll --- a/llvm/test/CodeGen/AArch64/arm64-promote-const.ll +++ b/llvm/test/CodeGen/AArch64/arm64-promote-const.ll @@ -44,7 +44,7 @@ ; PROMOTED: ldr q[[REGNUM:[0-9]+]], [[[PAGEADDR]], [[CSTV1]]@PAGEOFF] ; Destination register is defined by ABI ; PROMOTED-NEXT: add.16b v0, v0, v[[REGNUM]] -; PROMOTED-NEXT: mla.16b v0, v0, v[[REGNUM]] +; PROMOTED-NEXT: mls.16b v0, v0, v[[REGNUM]] ; PROMOTED-NEXT: ret ; REGULAR-LABEL: test2: @@ -55,12 +55,12 @@ ; REGULAR: ldr q[[REGNUM:[0-9]+]], [[[PAGEADDR]], [[CSTLABEL]]@PAGEOFF] ; Destination register is defined by ABI ; REGULAR-NEXT: add.16b v0, v0, v[[REGNUM]] -; REGULAR-NEXT: mla.16b v0, v0, v[[REGNUM]] +; REGULAR-NEXT: mls.16b v0, v0, v[[REGNUM]] ; REGULAR-NEXT: ret %add.i = add <16 x i8> %arg, %mul.i = mul <16 x i8> %add.i, - %add.i9 = add <16 x i8> %add.i, %mul.i - ret <16 x i8> %add.i9 + %sub.i9 = sub <16 x i8> %add.i, %mul.i + ret <16 x i8> %sub.i9 } ; Two different uses of the same constant in two different basic blocks, diff --git a/llvm/test/CodeGen/X86/add-of-mul.ll b/llvm/test/CodeGen/X86/add-of-mul.ll --- a/llvm/test/CodeGen/X86/add-of-mul.ll +++ b/llvm/test/CodeGen/X86/add-of-mul.ll @@ -5,8 +5,7 @@ ; CHECK-LABEL: test_scalar: ; CHECK: # %bb.0: ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi -; CHECK-NEXT: leal (%rdi,%rdi,2), %eax -; CHECK-NEXT: addl %edi, %eax +; CHECK-NEXT: leal (,%rdi,4), %eax ; CHECK-NEXT: retq %mul = mul i32 %x, 3 %add = add i32 %mul, %x @@ -17,8 +16,7 @@ ; CHECK-LABEL: test_scalar_commuted: ; CHECK: # %bb.0: ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi -; CHECK-NEXT: leal (%rdi,%rdi,2), %eax -; CHECK-NEXT: addl %edi, %eax +; CHECK-NEXT: leal (,%rdi,4), %eax ; CHECK-NEXT: retq %mul = mul i32 %x, 3 %add = add i32 %x, %mul @@ -28,8 +26,7 @@ define <4 x i32> @test_vector(<4 x i32> %x) { ; CHECK-LABEL: test_vector: ; CHECK: # %bb.0: -; CHECK-NEXT: paddd %xmm0, %xmm0 -; CHECK-NEXT: paddd %xmm0, %xmm0 +; CHECK-NEXT: pslld $2, %xmm0 ; CHECK-NEXT: retq %mul = mul <4 x i32> %x, %add = add <4 x i32> %mul, %x @@ -39,8 +36,7 @@ define ptr @test_ptr(ptr %p) { ; CHECK-LABEL: test_ptr: ; CHECK: # %bb.0: -; CHECK-NEXT: leaq (%rdi,%rdi,2), %rax -; CHECK-NEXT: addq %rdi, %rax +; CHECK-NEXT: leaq (,%rdi,4), %rax ; CHECK-NEXT: retq %addr = ptrtoint ptr %p to i64 %mul = mul i64 %addr, 3