Index: llvm/lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.h +++ llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -185,6 +185,9 @@ bool mayBeEmittedAsTailCall(const CallInst *CI) const override; bool shouldConsiderGEPOffsetSplit() const override { return true; } + bool decomposeMulByConstant(LLVMContext &Context, EVT VT, + SDValue C) const override; + TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; Value *emitMaskedAtomicRMWIntrinsic(IRBuilder<> &Builder, AtomicRMWInst *AI, Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/MathExtras.h" using namespace llvm; @@ -2978,6 +2979,22 @@ return true; } +bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, + SDValue C) const { + // Check integral scalar types. + if (VT.isScalarInteger()) + if (auto *ConstNode = dyn_cast(C.getNode())) { + int64_t Imm = ConstNode->getSExtValue(); + // This also benefits i64 mul on RISCV32, since MUL/MULHS/MULHU + // are all eliminated. + if (isPowerOf2_64(Imm + 1) || isPowerOf2_64(Imm - 1) || + isPowerOf2_64(1 - Imm) || isPowerOf2_64(-1 - Imm)) + return true; + } + + return false; +} + #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" Index: llvm/test/CodeGen/RISCV/mul.ll =================================================================== --- llvm/test/CodeGen/RISCV/mul.ll +++ llvm/test/CodeGen/RISCV/mul.ll @@ -78,36 +78,27 @@ define signext i32 @mul_constant(i32 %a) nounwind { ; RV32I-LABEL: mul_constant: -; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, 5 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: # %bb.0: +; RV32I-NEXT: slli a1, a0, 2 +; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: mul_constant: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a1, zero, 5 -; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: slli a1, a0, 2 +; RV32IM-NEXT: add a0, a1, a0 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: mul_constant: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 5 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: sext.w a0, a0 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 2 +; RV64I-NEXT: addw a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: mul_constant: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 5 -; RV64IM-NEXT: mulw a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 2 +; RV64IM-NEXT: addw a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, 5 ret i32 %1 @@ -177,38 +168,40 @@ define i64 @mul64_constant(i64 %a) nounwind { ; RV32I-LABEL: mul64_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, 5 -; RV32I-NEXT: mv a3, zero -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 -; RV32I-NEXT: ret +; RV32I-NEXT: slli a3, a0, 2 +; RV32I-NEXT: add a2, a3, a0 +; RV32I-NEXT: sltu a3, a2, a3 +; RV32I-NEXT: srli a0, a0, 30 +; RV32I-NEXT: slli a4, a1, 2 +; RV32I-NEXT: or a0, a4, a0 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: add a1, a0, a3 +; RV32I-NEXT: mv a0, a2 +; RV32I-NEXT: ret ; ; RV32IM-LABEL: mul64_constant: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a2, zero, 5 -; RV32IM-NEXT: mul a1, a1, a2 -; RV32IM-NEXT: mulhu a3, a0, a2 -; RV32IM-NEXT: add a1, a3, a1 -; RV32IM-NEXT: mul a0, a0, a2 -; RV32IM-NEXT: ret +; RV32IM-NEXT: slli a3, a0, 2 +; RV32IM-NEXT: add a2, a3, a0 +; RV32IM-NEXT: sltu a3, a2, a3 +; RV32IM-NEXT: srli a0, a0, 30 +; RV32IM-NEXT: slli a4, a1, 2 +; RV32IM-NEXT: or a0, a4, a0 +; RV32IM-NEXT: add a0, a0, a1 +; RV32IM-NEXT: add a1, a0, a3 +; RV32IM-NEXT: mv a0, a2 +; RV32IM-NEXT: ret ; ; RV64I-LABEL: mul64_constant: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 5 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 2 +; RV64I-NEXT: add a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: mul64_constant: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 5 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 2 +; RV64IM-NEXT: add a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, 5 ret i64 %1 @@ -305,34 +298,26 @@ define i32 @muli32_p65(i32 %a) nounwind { ; RV32I-LABEL: muli32_p65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, 65 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_p65: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a1, zero, 65 -; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: slli a1, a0, 6 +; RV32IM-NEXT: add a0, a1, a0 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: muli32_p65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: addw a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_p65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: addw a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, 65 ret i32 %1 @@ -341,34 +326,26 @@ define i32 @muli32_p63(i32 %a) nounwind { ; RV32I-LABEL: muli32_p63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, 63 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: sub a0, a1, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_p63: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a1, zero, 63 -; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: slli a1, a0, 6 +; RV32IM-NEXT: sub a0, a1, a0 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: muli32_p63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: subw a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_p63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: subw a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, 63 ret i32 %1 @@ -377,38 +354,38 @@ define i64 @muli64_p65(i64 %a) nounwind { ; RV32I-LABEL: muli64_p65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, 65 -; RV32I-NEXT: mv a3, zero -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 -; RV32I-NEXT: ret +; RV32I-NEXT: slli a3, a0, 6 +; RV32I-NEXT: add a2, a3, a0 +; RV32I-NEXT: sltu a3, a2, a3 +; RV32I-NEXT: srli a0, a0, 26 +; RV32I-NEXT: slli a4, a1, 6 +; RV32I-NEXT: or a0, a4, a0 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: add a1, a0, a3 +; RV32I-NEXT: mv a0, a2 ; ; RV32IM-LABEL: muli64_p65: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a2, zero, 65 -; RV32IM-NEXT: mul a1, a1, a2 -; RV32IM-NEXT: mulhu a3, a0, a2 -; RV32IM-NEXT: add a1, a3, a1 -; RV32IM-NEXT: mul a0, a0, a2 -; RV32IM-NEXT: ret +; RV32IM-NEXT: slli a3, a0, 6 +; RV32IM-NEXT: add a2, a3, a0 +; RV32IM-NEXT: sltu a3, a2, a3 +; RV32IM-NEXT: srli a0, a0, 26 +; RV32IM-NEXT: slli a4, a1, 6 +; RV32IM-NEXT: or a0, a4, a0 +; RV32IM-NEXT: add a0, a0, a1 +; RV32IM-NEXT: add a1, a0, a3 +; RV32IM-NEXT: mv a0, a2 ; ; RV64I-LABEL: muli64_p65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: add a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_p65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: add a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, 65 ret i64 %1 @@ -417,38 +394,36 @@ define i64 @muli64_p63(i64 %a) nounwind { ; RV32I-LABEL: muli64_p63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, 63 -; RV32I-NEXT: mv a3, zero -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 -; RV32I-NEXT: ret +; RV32I-NEXT: slli a2, a0, 6 +; RV32I-NEXT: sltu a3, a2, a0 +; RV32I-NEXT: srli a4, a0, 26 +; RV32I-NEXT: slli a5, a1, 6 +; RV32I-NEXT: or a4, a5, a4 +; RV32I-NEXT: sub a1, a4, a1 +; RV32I-NEXT: sub a1, a1, a3 +; RV32I-NEXT: sub a0, a2, a0 ; ; RV32IM-LABEL: muli64_p63: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a2, zero, 63 -; RV32IM-NEXT: mul a1, a1, a2 -; RV32IM-NEXT: mulhu a3, a0, a2 -; RV32IM-NEXT: add a1, a3, a1 -; RV32IM-NEXT: mul a0, a0, a2 -; RV32IM-NEXT: ret +; RV32IM-NEXT: slli a2, a0, 6 +; RV32IM-NEXT: sltu a3, a2, a0 +; RV32IM-NEXT: srli a4, a0, 26 +; RV32IM-NEXT: slli a5, a1, 6 +; RV32IM-NEXT: or a4, a5, a4 +; RV32IM-NEXT: sub a1, a4, a1 +; RV32IM-NEXT: sub a1, a1, a3 +; RV32IM-NEXT: sub a0, a2, a0 ; ; RV64I-LABEL: muli64_p63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: sub a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_p63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: sub a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, 63 ret i64 %1 @@ -457,34 +432,26 @@ define i32 @muli32_m63(i32 %a) nounwind { ; RV32I-LABEL: muli32_m63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, -63 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: sub a0, a0, a1 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_m63: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a1, zero, -63 -; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: slli a1, a0, 6 +; RV32IM-NEXT: sub a0, a0, a1 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: muli32_m63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: subw a0, a0, a1 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_m63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: subw a0, a0, a1 ; RV64IM-NEXT: ret %1 = mul i32 %a, -63 ret i32 %1 @@ -493,34 +460,30 @@ define i32 @muli32_m65(i32 %a) nounwind { ; RV32I-LABEL: muli32_m65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, -65 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: neg a0, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_m65: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a1, zero, -65 -; RV32IM-NEXT: mul a0, a0, a1 +; RV32IM-NEXT: slli a1, a0, 6 +; RV32IM-NEXT: add a0, a1, a0 +; RV32IM-NEXT: neg a0, a0 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: muli32_m65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: negw a0, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_m65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: add a0, a1, a0 +; RV64IM-NEXT: negw a0, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, -65 ret i32 %1 @@ -529,39 +492,38 @@ define i64 @muli64_m63(i64 %a) nounwind { ; RV32I-LABEL: muli64_m63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, -63 -; RV32I-NEXT: addi a3, zero, -1 -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a2, a0, 6 +; RV32I-NEXT: sltu a3, a0, a2 +; RV32I-NEXT: srli a4, a0, 26 +; RV32I-NEXT: slli a5, a1, 6 +; RV32I-NEXT: or a4, a5, a4 +; RV32I-NEXT: sub a1, a1, a4 +; RV32I-NEXT: sub a1, a1, a3 +; RV32I-NEXT: sub a0, a0, a2 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli64_m63: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a2, zero, -63 -; RV32IM-NEXT: mul a1, a1, a2 -; RV32IM-NEXT: mulhu a3, a0, a2 -; RV32IM-NEXT: sub a3, a3, a0 -; RV32IM-NEXT: add a1, a3, a1 -; RV32IM-NEXT: mul a0, a0, a2 +; RV32IM-NEXT: slli a2, a0, 6 +; RV32IM-NEXT: sltu a3, a0, a2 +; RV32IM-NEXT: srli a4, a0, 26 +; RV32IM-NEXT: slli a5, a1, 6 +; RV32IM-NEXT: or a4, a5, a4 +; RV32IM-NEXT: sub a1, a1, a4 +; RV32IM-NEXT: sub a1, a1, a3 +; RV32IM-NEXT: sub a0, a0, a2 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: muli64_m63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: sub a0, a0, a1 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_m63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: sub a0, a0, a1 ; RV64IM-NEXT: ret %1 = mul i64 %a, -63 ret i64 %1 @@ -570,39 +532,48 @@ define i64 @muli64_m65(i64 %a) nounwind { ; RV32I-LABEL: muli64_m65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, -65 -; RV32I-NEXT: addi a3, zero, -1 -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a2, a0, 6 +; RV32I-NEXT: add a3, a2, a0 +; RV32I-NEXT: sltu a2, a3, a2 +; RV32I-NEXT: srli a0, a0, 26 +; RV32I-NEXT: slli a4, a1, 6 +; RV32I-NEXT: or a0, a4, a0 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: snez a1, a3 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: neg a1, a0 +; RV32I-NEXT: neg a0, a3 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli64_m65: ; RV32IM: # %bb.0: -; RV32IM-NEXT: addi a2, zero, -65 -; RV32IM-NEXT: mul a1, a1, a2 -; RV32IM-NEXT: mulhu a3, a0, a2 -; RV32IM-NEXT: sub a3, a3, a0 -; RV32IM-NEXT: add a1, a3, a1 -; RV32IM-NEXT: mul a0, a0, a2 +; RV32IM-NEXT: slli a2, a0, 6 +; RV32IM-NEXT: add a3, a2, a0 +; RV32IM-NEXT: sltu a2, a3, a2 +; RV32IM-NEXT: srli a0, a0, 26 +; RV32IM-NEXT: slli a4, a1, 6 +; RV32IM-NEXT: or a0, a4, a0 +; RV32IM-NEXT: add a0, a0, a1 +; RV32IM-NEXT: add a0, a0, a2 +; RV32IM-NEXT: snez a1, a3 +; RV32IM-NEXT: add a0, a0, a1 +; RV32IM-NEXT: neg a1, a0 +; RV32IM-NEXT: neg a0, a3 ; RV32IM-NEXT: ret ; ; RV64I-LABEL: muli64_m65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: neg a0, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_m65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: add a0, a1, a0 +; RV64IM-NEXT: neg a0, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, -65 ret i64 %1