Index: llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp =================================================================== --- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -3165,6 +3165,22 @@ ((Imm - 2).isPowerOf2() || (Imm - 4).isPowerOf2() || (Imm - 8).isPowerOf2() || (Imm - 16).isPowerOf2())) return true; + // Break (MUL x, imm) into (ADD (SLLI x, s0), (SLLI x, s1)), + // in which the immediate has two set bits. Or Break (MUL x, imm) + // into (SUB (SLLI x, s0), (SLLI x, s1)), in which the immediate + // equals to (1 << s0) - (1 << s1). + if (ConstNode->hasOneUse() && !(Imm.sge(-2048) && Imm.sle(4095))) { + unsigned Shifts = Imm.countr_zero(); + // Reject immediates which can be composed via a single LUI. + if (Shifts >= 12) + return false; + APInt ImmSmall = APInt(Imm.getBitWidth(), 1 << Shifts, true); + // We do not consider the case `(-Imm - ImmSmall).isPowerOf2()`, + // since it needs one more instruction than other 3 cases. + if ((Imm - ImmSmall).isPowerOf2() || (Imm + ImmSmall).isPowerOf2() || + (ImmSmall - Imm).isPowerOf2()) + return true; + } } return false; Index: llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll =================================================================== --- llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll +++ llvm/test/CodeGen/LoongArch/ir-instruction/mul.ll @@ -1218,17 +1218,16 @@ define signext i32 @mul_i32_4352(i32 %a) { ; LA32-LABEL: mul_i32_4352: ; LA32: # %bb.0: -; LA32-NEXT: lu12i.w $a1, 1 -; LA32-NEXT: ori $a1, $a1, 256 -; LA32-NEXT: mul.w $a0, $a0, $a1 +; LA32-NEXT: slli.w $a1, $a0, 8 +; LA32-NEXT: slli.w $a0, $a0, 12 +; LA32-NEXT: add.w $a0, $a0, $a1 ; LA32-NEXT: ret ; ; LA64-LABEL: mul_i32_4352: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 1 -; LA64-NEXT: ori $a1, $a1, 256 -; LA64-NEXT: mul.d $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: slli.d $a1, $a0, 8 +; LA64-NEXT: slli.d $a0, $a0, 12 +; LA64-NEXT: add.w $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i32 %a, 4352 ret i32 %b @@ -1304,9 +1303,9 @@ ; ; LA64-LABEL: mul_i64_4352: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 1 -; LA64-NEXT: ori $a1, $a1, 256 -; LA64-NEXT: mul.d $a0, $a0, $a1 +; LA64-NEXT: slli.d $a1, $a0, 8 +; LA64-NEXT: slli.d $a0, $a0, 12 +; LA64-NEXT: add.d $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i64 %a, 4352 ret i64 %b @@ -1315,17 +1314,16 @@ define signext i32 @mul_i32_65792(i32 %a) { ; LA32-LABEL: mul_i32_65792: ; LA32: # %bb.0: -; LA32-NEXT: lu12i.w $a1, 16 -; LA32-NEXT: ori $a1, $a1, 256 -; LA32-NEXT: mul.w $a0, $a0, $a1 +; LA32-NEXT: slli.w $a1, $a0, 8 +; LA32-NEXT: slli.w $a0, $a0, 16 +; LA32-NEXT: add.w $a0, $a0, $a1 ; LA32-NEXT: ret ; ; LA64-LABEL: mul_i32_65792: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 16 -; LA64-NEXT: ori $a1, $a1, 256 -; LA64-NEXT: mul.d $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: slli.d $a1, $a0, 8 +; LA64-NEXT: slli.d $a0, $a0, 16 +; LA64-NEXT: add.w $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i32 %a, 65792 ret i32 %b @@ -1334,17 +1332,16 @@ define signext i32 @mul_i32_65280(i32 %a) { ; LA32-LABEL: mul_i32_65280: ; LA32: # %bb.0: -; LA32-NEXT: lu12i.w $a1, 15 -; LA32-NEXT: ori $a1, $a1, 3840 -; LA32-NEXT: mul.w $a0, $a0, $a1 +; LA32-NEXT: slli.w $a1, $a0, 8 +; LA32-NEXT: slli.w $a0, $a0, 16 +; LA32-NEXT: sub.w $a0, $a0, $a1 ; LA32-NEXT: ret ; ; LA64-LABEL: mul_i32_65280: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 15 -; LA64-NEXT: ori $a1, $a1, 3840 -; LA64-NEXT: mul.d $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: slli.d $a1, $a0, 8 +; LA64-NEXT: slli.d $a0, $a0, 16 +; LA64-NEXT: sub.w $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i32 %a, 65280 ret i32 %b @@ -1353,17 +1350,16 @@ define signext i32 @mul_i32_minus_65280(i32 %a) { ; LA32-LABEL: mul_i32_minus_65280: ; LA32: # %bb.0: -; LA32-NEXT: lu12i.w $a1, -16 -; LA32-NEXT: ori $a1, $a1, 256 -; LA32-NEXT: mul.w $a0, $a0, $a1 +; LA32-NEXT: slli.w $a1, $a0, 16 +; LA32-NEXT: slli.w $a0, $a0, 8 +; LA32-NEXT: sub.w $a0, $a0, $a1 ; LA32-NEXT: ret ; ; LA64-LABEL: mul_i32_minus_65280: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, -16 -; LA64-NEXT: ori $a1, $a1, 256 -; LA64-NEXT: mul.d $a0, $a0, $a1 -; LA64-NEXT: addi.w $a0, $a0, 0 +; LA64-NEXT: slli.d $a1, $a0, 16 +; LA64-NEXT: slli.d $a0, $a0, 8 +; LA64-NEXT: sub.w $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i32 %a, -65280 ret i32 %b @@ -1382,9 +1378,9 @@ ; ; LA64-LABEL: mul_i64_65792: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 16 -; LA64-NEXT: ori $a1, $a1, 256 -; LA64-NEXT: mul.d $a0, $a0, $a1 +; LA64-NEXT: slli.d $a1, $a0, 8 +; LA64-NEXT: slli.d $a0, $a0, 16 +; LA64-NEXT: add.d $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i64 %a, 65792 ret i64 %b @@ -1403,9 +1399,9 @@ ; ; LA64-LABEL: mul_i64_65280: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 15 -; LA64-NEXT: ori $a1, $a1, 3840 -; LA64-NEXT: mul.d $a0, $a0, $a1 +; LA64-NEXT: slli.d $a1, $a0, 8 +; LA64-NEXT: slli.d $a0, $a0, 16 +; LA64-NEXT: sub.d $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i64 %a, 65280 ret i64 %b @@ -1425,9 +1421,9 @@ ; ; LA64-LABEL: mul_i64_minus_65280: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, -16 -; LA64-NEXT: ori $a1, $a1, 256 -; LA64-NEXT: mul.d $a0, $a0, $a1 +; LA64-NEXT: slli.d $a1, $a0, 16 +; LA64-NEXT: slli.d $a0, $a0, 8 +; LA64-NEXT: sub.d $a0, $a0, $a1 ; LA64-NEXT: ret %b = mul i64 %a, -65280 ret i64 %b