Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ 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) Index: llvm/test/CodeGen/AArch64/arm64-promote-const.ll =================================================================== --- llvm/test/CodeGen/AArch64/arm64-promote-const.ll +++ 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, Index: llvm/test/CodeGen/X86/add-of-mul.ll =================================================================== --- llvm/test/CodeGen/X86/add-of-mul.ll +++ llvm/test/CodeGen/X86/add-of-mul.ll @@ -5,19 +5,28 @@ ; 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 ret i32 %add } +define i32 @test_scalar_commuted(i32 %x) { +; CHECK-LABEL: test_scalar_commuted: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $edi killed $edi def $rdi +; CHECK-NEXT: leal (,%rdi,4), %eax +; CHECK-NEXT: retq + %mul = mul i32 %x, 3 + %add = add i32 %x, %mul + ret i32 %add +} + 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 @@ -27,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