Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -15743,9 +15743,24 @@ SDValue &ConstNode) { APInt Val; - // If the add only has one use, this would be OK to do. - if (AddNode.getNode()->hasOneUse()) + // If the add only has one use, do further check of c1 and c1*c2. + if (AddNode.getNode()->hasOneUse()) { + if (auto *C1Node = dyn_cast(AddNode.getOperand(1))) + if (auto *C2Node = dyn_cast(ConstNode)) { + int64_t C1 = C1Node->getSExtValue(); + int64_t C2 = C2Node->getSExtValue(); + // Do sign extension for c1*c2 according to c2's type. + int ShiftBits = 64 - ConstNode.getScalarValueSizeInBits(); + int64_t C1C2 = ((C1 * C2) << ShiftBits) >> ShiftBits; + // This transform will introduce regression, if c1 is legal add + // immediate while c1*c2 isn't. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (TLI.isLegalAddImmediate(C1) && !TLI.isLegalAddImmediate(C1C2)) + return false; + } + // It is OK to do the transform. return true; + } // Walk all the users of the constant with which we're multiplying. for (SDNode *Use : ConstNode->uses()) { Index: llvm/test/CodeGen/AArch64/addimm-mulimm.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/addimm-mulimm.ll @@ -0,0 +1,37 @@ +; RUN: llc < %s -mtriple=aarch64-eabi | FileCheck %s + +define i32 @add_mul_trans_1(i32 %x) { +; CHECK-LABEL: add_mul_trans_1 +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, #11 +; CHECK-NEXT: mul w8, w0, w8 +; CHECK-NEXT: add w0, w8, #407 // =407 + %tmp0 = add i32 %x, 37 + %tmp1 = mul i32 %tmp0, 11 + ret i32 %tmp1 +} + +define i32 @add_mul_trans_2(i32 %x) { +; CHECK-LABEL: add_mul_trans_2 +; CHECK: // %bb.0: +; CHECK-NEXT: mov w9, #50853 +; CHECK-NEXT: mov w8, #13 +; CHECK-NEXT: movk w9, #1, lsl #16 +; CHECK-NEXT: madd w0, w0, w8, w9 +; CHECK-NEXT: ret + %tmp0 = add i32 %x, 8953 + %tmp1 = mul i32 %tmp0, 13 + ret i32 %tmp1 +} + +define i32 @add_mul_not_trans(i32 %x) { +; CHECK-LABEL: add_mul_not_trans +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #1971 // =1971 +; CHECK-NEXT: mov w9, #19 +; CHECK-NEXT: mul w0, w8, w9 +; CHECK-NEXT: ret + %tmp0 = add i32 %x, 1971 + %tmp1 = mul i32 %tmp0, 19 + ret i32 %tmp1 +} Index: llvm/test/CodeGen/AArch64/urem-seteq-nonzero.ll =================================================================== --- llvm/test/CodeGen/AArch64/urem-seteq-nonzero.ll +++ llvm/test/CodeGen/AArch64/urem-seteq-nonzero.ll @@ -4,10 +4,11 @@ define i1 @t32_3_1(i32 %X) nounwind { ; CHECK-LABEL: t32_3_1: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #43691 -; CHECK-NEXT: movk w8, #43690, lsl #16 +; CHECK-NEXT: mov w9, #43691 +; CHECK-NEXT: sub w8, w0, #1 // =1 +; CHECK-NEXT: movk w9, #43690, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #1431655765 -; CHECK-NEXT: madd w8, w0, w8, w9 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo ; CHECK-NEXT: ret @@ -19,10 +20,10 @@ define i1 @t32_3_2(i32 %X) nounwind { ; CHECK-LABEL: t32_3_2: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #43691 -; CHECK-NEXT: movk w8, #43690, lsl #16 -; CHECK-NEXT: mov w9, #-1431655766 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #43691 +; CHECK-NEXT: sub w8, w0, #2 // =2 +; CHECK-NEXT: movk w9, #43690, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #1431655765 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo @@ -36,10 +37,11 @@ define i1 @t32_5_1(i32 %X) nounwind { ; CHECK-LABEL: t32_5_1: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #52429 -; CHECK-NEXT: movk w8, #52428, lsl #16 +; CHECK-NEXT: mov w9, #52429 +; CHECK-NEXT: sub w8, w0, #1 // =1 +; CHECK-NEXT: movk w9, #52428, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #858993459 -; CHECK-NEXT: madd w8, w0, w8, w9 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo ; CHECK-NEXT: ret @@ -51,10 +53,10 @@ define i1 @t32_5_2(i32 %X) nounwind { ; CHECK-LABEL: t32_5_2: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #52429 -; CHECK-NEXT: movk w8, #52428, lsl #16 -; CHECK-NEXT: mov w9, #1717986918 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #52429 +; CHECK-NEXT: sub w8, w0, #2 // =2 +; CHECK-NEXT: movk w9, #52428, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #858993459 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo @@ -67,10 +69,10 @@ define i1 @t32_5_3(i32 %X) nounwind { ; CHECK-LABEL: t32_5_3: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #52429 -; CHECK-NEXT: movk w8, #52428, lsl #16 -; CHECK-NEXT: mov w9, #-1717986919 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #52429 +; CHECK-NEXT: sub w8, w0, #3 // =3 +; CHECK-NEXT: movk w9, #52428, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #858993459 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo @@ -83,10 +85,10 @@ define i1 @t32_5_4(i32 %X) nounwind { ; CHECK-LABEL: t32_5_4: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #52429 -; CHECK-NEXT: movk w8, #52428, lsl #16 -; CHECK-NEXT: mov w9, #-858993460 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #52429 +; CHECK-NEXT: sub w8, w0, #4 // =4 +; CHECK-NEXT: movk w9, #52428, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #858993459 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo @@ -100,10 +102,10 @@ define i1 @t32_6_1(i32 %X) nounwind { ; CHECK-LABEL: t32_6_1: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #43691 -; CHECK-NEXT: movk w8, #43690, lsl #16 -; CHECK-NEXT: mov w9, #1431655765 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #43691 +; CHECK-NEXT: sub w8, w0, #1 // =1 +; CHECK-NEXT: movk w9, #43690, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #43691 ; CHECK-NEXT: ror w8, w8, #1 ; CHECK-NEXT: movk w9, #10922, lsl #16 @@ -118,10 +120,10 @@ define i1 @t32_6_2(i32 %X) nounwind { ; CHECK-LABEL: t32_6_2: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #43691 -; CHECK-NEXT: movk w8, #43690, lsl #16 -; CHECK-NEXT: mov w9, #-1431655766 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #43691 +; CHECK-NEXT: sub w8, w0, #2 // =2 +; CHECK-NEXT: movk w9, #43690, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #43691 ; CHECK-NEXT: ror w8, w8, #1 ; CHECK-NEXT: movk w9, #10922, lsl #16 @@ -154,11 +156,10 @@ define i1 @t32_6_4(i32 %X) nounwind { ; CHECK-LABEL: t32_6_4: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #43691 -; CHECK-NEXT: mov w9, #21844 -; CHECK-NEXT: movk w8, #43690, lsl #16 -; CHECK-NEXT: movk w9, #21845, lsl #16 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mov w9, #43691 +; CHECK-NEXT: sub w8, w0, #4 // =4 +; CHECK-NEXT: movk w9, #43690, lsl #16 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #43690 ; CHECK-NEXT: ror w8, w8, #1 ; CHECK-NEXT: movk w9, #10922, lsl #16 @@ -173,11 +174,10 @@ define i1 @t32_6_5(i32 %X) nounwind { ; CHECK-LABEL: t32_6_5: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #43691 -; CHECK-NEXT: mov w9, #43689 -; CHECK-NEXT: movk w8, #43690, lsl #16 +; CHECK-NEXT: mov w9, #43691 +; CHECK-NEXT: sub w8, w0, #5 // =5 ; CHECK-NEXT: movk w9, #43690, lsl #16 -; CHECK-NEXT: madd w8, w0, w8, w9 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #43690 ; CHECK-NEXT: ror w8, w8, #1 ; CHECK-NEXT: movk w9, #10922, lsl #16 @@ -195,11 +195,11 @@ define i1 @t16_3_2(i16 %X) nounwind { ; CHECK-LABEL: t16_3_2: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w9, #43691 ; CHECK-NEXT: and w8, w0, #0xffff +; CHECK-NEXT: mov w9, #43691 ; CHECK-NEXT: movk w9, #43690, lsl #16 -; CHECK-NEXT: mov w10, #-1431655766 -; CHECK-NEXT: madd w8, w8, w9, w10 +; CHECK-NEXT: sub w8, w8, #2 // =2 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #1431655765 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo @@ -212,11 +212,11 @@ define i1 @t8_3_2(i8 %X) nounwind { ; CHECK-LABEL: t8_3_2: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w9, #43691 ; CHECK-NEXT: and w8, w0, #0xff +; CHECK-NEXT: mov w9, #43691 ; CHECK-NEXT: movk w9, #43690, lsl #16 -; CHECK-NEXT: mov w10, #-1431655766 -; CHECK-NEXT: madd w8, w8, w9, w10 +; CHECK-NEXT: sub w8, w8, #2 // =2 +; CHECK-NEXT: mul w8, w8, w9 ; CHECK-NEXT: mov w9, #1431655765 ; CHECK-NEXT: cmp w8, w9 ; CHECK-NEXT: cset w0, lo @@ -229,10 +229,10 @@ define i1 @t64_3_2(i64 %X) nounwind { ; CHECK-LABEL: t64_3_2: ; CHECK: // %bb.0: -; CHECK-NEXT: mov x8, #-6148914691236517206 -; CHECK-NEXT: movk x8, #43691 ; CHECK-NEXT: mov x9, #-6148914691236517206 -; CHECK-NEXT: madd x8, x0, x8, x9 +; CHECK-NEXT: sub x8, x0, #2 // =2 +; CHECK-NEXT: movk x9, #43691 +; CHECK-NEXT: mul x8, x8, x9 ; CHECK-NEXT: mov x9, #6148914691236517205 ; CHECK-NEXT: cmp x8, x9 ; CHECK-NEXT: cset w0, lo Index: llvm/test/CodeGen/RISCV/addimm-mulimm.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/addimm-mulimm.ll @@ -0,0 +1,65 @@ +; RUN: llc -mtriple=riscv32 -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32IM %s +; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64IM %s + +define signext i32 @add_mul_trans_1(i32 %x) { +; RV32IM-LABEL: add_mul_trans_1 +; RV32IM: # %bb.0: +; RV32IM-NEXT: addi a1, zero, 11 +; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: addi a0, a0, 407 +; RV32IM-NEXT: ret +; +; RV64IM-LABEL: add_mul_trans_1 +; RV64IM: # %bb.0: +; RV64IM-NEXT: addi a1, zero, 11 +; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: addiw a0, a0, 407 +; RV64IM-NEXT: ret + %tmp0 = add i32 %x, 37 + %tmp1 = mul i32 %tmp0, 11 + ret i32 %tmp1 +} + +define signext i32 @add_mul_trans_2(i32 %x) { +; RV32IM-LABEL: add_mul_trans_2 +; RV32IM: # %bb.0: +; RV32IM-NEXT: addi a1, zero, 13 +; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: lui a1, 28 +; RV32IM-NEXT: addi a1, a1, 1701 +; RV32IM-NEXT: add a0, a0, a1 +; RV32IM-NEXT: ret +; +; RV64IM-LABEL: add_mul_trans_2 +; RV64IM: # %bb.0: +; RV64IM-NEXT: addi a1, zero, 13 +; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: lui a1, 28 +; RV64IM-NEXT: addiw a1, a1, 1701 +; RV64IM-NEXT: addw a0, a0, a1 +; RV64IM-NEXT: ret + %tmp0 = add i32 %x, 8953 + %tmp1 = mul i32 %tmp0, 13 + ret i32 %tmp1 +} + +define signext i32 @add_mul_not_trans(i32 %x) { +; RV32IM-LABEL: add_mul_not_trans +; RV32IM: # %bb.0: +; RV32IM-NEXT: addi a0, a0, 1971 +; RV32IM-NEXT: addi a1, zero, 19 +; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: ret +; +; RV64IM-LABEL: add_mul_not_trans +; RV64IM: # %bb.0: +; RV64IM-NEXT: addi a0, a0, 1971 +; RV64IM-NEXT: addi a1, zero, 19 +; RV64IM-NEXT: mulw a0, a0, a1 +; RV64IM-NEXT: ret + %tmp0 = add i32 %x, 1971 + %tmp1 = mul i32 %tmp0, 19 + ret i32 %tmp1 +} Index: llvm/test/CodeGen/X86/urem-seteq-nonzero.ll =================================================================== --- llvm/test/CodeGen/X86/urem-seteq-nonzero.ll +++ llvm/test/CodeGen/X86/urem-seteq-nonzero.ll @@ -310,12 +310,11 @@ ; ; X64-LABEL: t64_3_2: ; X64: # %bb.0: +; X64-NEXT: addq $-2, %rdi ; X64-NEXT: movabsq $-6148914691236517205, %rax # imm = 0xAAAAAAAAAAAAAAAB ; X64-NEXT: imulq %rdi, %rax -; X64-NEXT: movabsq $-6148914691236517206, %rcx # imm = 0xAAAAAAAAAAAAAAAA -; X64-NEXT: addq %rax, %rcx -; X64-NEXT: movabsq $6148914691236517205, %rax # imm = 0x5555555555555555 -; X64-NEXT: cmpq %rax, %rcx +; X64-NEXT: movabsq $6148914691236517205, %rcx # imm = 0x5555555555555555 +; X64-NEXT: cmpq %rcx, %rax ; X64-NEXT: setb %al ; X64-NEXT: retq %urem = urem i64 %X, 3