diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -202,6 +202,27 @@ return !isInt<13>(C) && isInt<15>(C) && (C & 7) == 0; }]>; +def CPow2Plus2 : PatLeaf<(imm), [{ + if (!N->hasOneUse()) + return false; + int64_t C = N->getSExtValue(); + return !isPowerOf2_64(C) && C > 2 && isPowerOf2_64(C - 2); +}]>; + +def CPow2Plus4 : PatLeaf<(imm), [{ + if (!N->hasOneUse()) + return false; + int64_t C = N->getSExtValue(); + return !isPowerOf2_64(C) && C > 4 && isPowerOf2_64(C - 4); +}]>; + +def CPow2Plus8 : PatLeaf<(imm), [{ + if (!N->hasOneUse()) + return false; + int64_t C = N->getSExtValue(); + return !isPowerOf2_64(C) && C > 8 && isPowerOf2_64(C - 8); +}]>; + def SimmShiftRightBy2XForm : SDNodeXFormgetTargetConstant(N->getSExtValue() >> 2, SDLoc(N), N->getValueType(0)); @@ -212,6 +233,24 @@ N->getValueType(0)); }]>; +def SimmMinus2Lg2XForm : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(countTrailingZeros(I - 2), SDLoc(N), + N->getValueType(0)); +}]>; + +def SimmMinus4Lg2XForm : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(countTrailingZeros(I - 4), SDLoc(N), + N->getValueType(0)); +}]>; + +def SimmMinus8Lg2XForm : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(countTrailingZeros(I - 8), SDLoc(N), + N->getValueType(0)); +}]>; + //===----------------------------------------------------------------------===// // Instruction class templates //===----------------------------------------------------------------------===// @@ -1037,6 +1076,16 @@ def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 72)), GPR:$rs2), (SH3ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; +def : Pat<(mul GPR:$rs1, CPow2Plus2:$i), + (SH1ADD GPR:$rs1, (SLLI GPR:$rs1, + (SimmMinus2Lg2XForm CPow2Plus2:$i)))>; +def : Pat<(mul GPR:$rs1, CPow2Plus4:$i), + (SH2ADD GPR:$rs1, (SLLI GPR:$rs1, + (SimmMinus4Lg2XForm CPow2Plus4:$i)))>; +def : Pat<(mul GPR:$rs1, CPow2Plus8:$i), + (SH3ADD GPR:$rs1, (SLLI GPR:$rs1, + (SimmMinus8Lg2XForm CPow2Plus8:$i)))>; + def : Pat<(add GPR:$r, CSImm12MulBy4:$i), (SH2ADD (ADDI X0, (SimmShiftRightBy2XForm CSImm12MulBy4:$i)), GPR:$r)>; diff --git a/llvm/test/CodeGen/RISCV/rv32zba.ll b/llvm/test/CodeGen/RISCV/rv32zba.ll --- a/llvm/test/CodeGen/RISCV/rv32zba.ll +++ b/llvm/test/CodeGen/RISCV/rv32zba.ll @@ -372,14 +372,14 @@ ; ; RV32B-LABEL: mul258: ; RV32B: # %bb.0: -; RV32B-NEXT: addi a1, zero, 258 -; RV32B-NEXT: mul a0, a0, a1 +; RV32B-NEXT: slli a1, a0, 8 +; RV32B-NEXT: sh1add a0, a0, a1 ; RV32B-NEXT: ret ; ; RV32ZBA-LABEL: mul258: ; RV32ZBA: # %bb.0: -; RV32ZBA-NEXT: addi a1, zero, 258 -; RV32ZBA-NEXT: mul a0, a0, a1 +; RV32ZBA-NEXT: slli a1, a0, 8 +; RV32ZBA-NEXT: sh1add a0, a0, a1 ; RV32ZBA-NEXT: ret %c = mul i32 %a, 258 ret i32 %c @@ -394,14 +394,14 @@ ; ; RV32B-LABEL: mul260: ; RV32B: # %bb.0: -; RV32B-NEXT: addi a1, zero, 260 -; RV32B-NEXT: mul a0, a0, a1 +; RV32B-NEXT: slli a1, a0, 8 +; RV32B-NEXT: sh2add a0, a0, a1 ; RV32B-NEXT: ret ; ; RV32ZBA-LABEL: mul260: ; RV32ZBA: # %bb.0: -; RV32ZBA-NEXT: addi a1, zero, 260 -; RV32ZBA-NEXT: mul a0, a0, a1 +; RV32ZBA-NEXT: slli a1, a0, 8 +; RV32ZBA-NEXT: sh2add a0, a0, a1 ; RV32ZBA-NEXT: ret %c = mul i32 %a, 260 ret i32 %c @@ -416,19 +416,151 @@ ; ; RV32B-LABEL: mul264: ; RV32B: # %bb.0: -; RV32B-NEXT: addi a1, zero, 264 -; RV32B-NEXT: mul a0, a0, a1 +; RV32B-NEXT: slli a1, a0, 8 +; RV32B-NEXT: sh3add a0, a0, a1 ; RV32B-NEXT: ret ; ; RV32ZBA-LABEL: mul264: ; RV32ZBA: # %bb.0: -; RV32ZBA-NEXT: addi a1, zero, 264 -; RV32ZBA-NEXT: mul a0, a0, a1 +; RV32ZBA-NEXT: slli a1, a0, 8 +; RV32ZBA-NEXT: sh3add a0, a0, a1 ; RV32ZBA-NEXT: ret %c = mul i32 %a, 264 ret i32 %c } +define i32 @mul514(i32 %a) { +; RV32I-LABEL: mul514: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, 514 +; RV32I-NEXT: mul a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32B-LABEL: mul514: +; RV32B: # %bb.0: +; RV32B-NEXT: slli a1, a0, 9 +; RV32B-NEXT: sh1add a0, a0, a1 +; RV32B-NEXT: ret +; +; RV32ZBA-LABEL: mul514: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: slli a1, a0, 9 +; RV32ZBA-NEXT: sh1add a0, a0, a1 +; RV32ZBA-NEXT: ret + %c = mul i32 %a, 514 + ret i32 %c +} + +define i32 @mul516(i32 %a) { +; RV32I-LABEL: mul516: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, 516 +; RV32I-NEXT: mul a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32B-LABEL: mul516: +; RV32B: # %bb.0: +; RV32B-NEXT: slli a1, a0, 9 +; RV32B-NEXT: sh2add a0, a0, a1 +; RV32B-NEXT: ret +; +; RV32ZBA-LABEL: mul516: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: slli a1, a0, 9 +; RV32ZBA-NEXT: sh2add a0, a0, a1 +; RV32ZBA-NEXT: ret + %c = mul i32 %a, 516 + ret i32 %c +} + +define i32 @mul520(i32 %a) { +; RV32I-LABEL: mul520: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, 520 +; RV32I-NEXT: mul a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32B-LABEL: mul520: +; RV32B: # %bb.0: +; RV32B-NEXT: slli a1, a0, 9 +; RV32B-NEXT: sh3add a0, a0, a1 +; RV32B-NEXT: ret +; +; RV32ZBA-LABEL: mul520: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: slli a1, a0, 9 +; RV32ZBA-NEXT: sh3add a0, a0, a1 +; RV32ZBA-NEXT: ret + %c = mul i32 %a, 520 + ret i32 %c +} + +define i32 @mul1026(i32 %a) { +; RV32I-LABEL: mul1026: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, 1026 +; RV32I-NEXT: mul a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32B-LABEL: mul1026: +; RV32B: # %bb.0: +; RV32B-NEXT: slli a1, a0, 10 +; RV32B-NEXT: sh1add a0, a0, a1 +; RV32B-NEXT: ret +; +; RV32ZBA-LABEL: mul1026: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: slli a1, a0, 10 +; RV32ZBA-NEXT: sh1add a0, a0, a1 +; RV32ZBA-NEXT: ret + %c = mul i32 %a, 1026 + ret i32 %c +} + +define i32 @mul1028(i32 %a) { +; RV32I-LABEL: mul1028: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, 1028 +; RV32I-NEXT: mul a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32B-LABEL: mul1028: +; RV32B: # %bb.0: +; RV32B-NEXT: slli a1, a0, 10 +; RV32B-NEXT: sh2add a0, a0, a1 +; RV32B-NEXT: ret +; +; RV32ZBA-LABEL: mul1028: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: slli a1, a0, 10 +; RV32ZBA-NEXT: sh2add a0, a0, a1 +; RV32ZBA-NEXT: ret + %c = mul i32 %a, 1028 + ret i32 %c +} + +define i32 @mul1032(i32 %a) { +; RV32I-LABEL: mul1032: +; RV32I: # %bb.0: +; RV32I-NEXT: addi a1, zero, 1032 +; RV32I-NEXT: mul a0, a0, a1 +; RV32I-NEXT: ret +; +; RV32B-LABEL: mul1032: +; RV32B: # %bb.0: +; RV32B-NEXT: slli a1, a0, 10 +; RV32B-NEXT: sh3add a0, a0, a1 +; RV32B-NEXT: ret +; +; RV32ZBA-LABEL: mul1032: +; RV32ZBA: # %bb.0: +; RV32ZBA-NEXT: slli a1, a0, 10 +; RV32ZBA-NEXT: sh3add a0, a0, a1 +; RV32ZBA-NEXT: ret + %c = mul i32 %a, 1032 + ret i32 %c +} + define i32 @mul11(i32 %a) { ; RV32I-LABEL: mul11: ; RV32I: # %bb.0: diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -830,14 +830,14 @@ ; ; RV64B-LABEL: mul258: ; RV64B: # %bb.0: -; RV64B-NEXT: addi a1, zero, 258 -; RV64B-NEXT: mul a0, a0, a1 +; RV64B-NEXT: slli a1, a0, 8 +; RV64B-NEXT: sh1add a0, a0, a1 ; RV64B-NEXT: ret ; ; RV64ZBA-LABEL: mul258: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: addi a1, zero, 258 -; RV64ZBA-NEXT: mul a0, a0, a1 +; RV64ZBA-NEXT: slli a1, a0, 8 +; RV64ZBA-NEXT: sh1add a0, a0, a1 ; RV64ZBA-NEXT: ret %c = mul i64 %a, 258 ret i64 %c @@ -852,14 +852,14 @@ ; ; RV64B-LABEL: mul260: ; RV64B: # %bb.0: -; RV64B-NEXT: addi a1, zero, 260 -; RV64B-NEXT: mul a0, a0, a1 +; RV64B-NEXT: slli a1, a0, 8 +; RV64B-NEXT: sh2add a0, a0, a1 ; RV64B-NEXT: ret ; ; RV64ZBA-LABEL: mul260: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: addi a1, zero, 260 -; RV64ZBA-NEXT: mul a0, a0, a1 +; RV64ZBA-NEXT: slli a1, a0, 8 +; RV64ZBA-NEXT: sh2add a0, a0, a1 ; RV64ZBA-NEXT: ret %c = mul i64 %a, 260 ret i64 %c @@ -874,19 +874,151 @@ ; ; RV64B-LABEL: mul264: ; RV64B: # %bb.0: -; RV64B-NEXT: addi a1, zero, 264 -; RV64B-NEXT: mul a0, a0, a1 +; RV64B-NEXT: slli a1, a0, 8 +; RV64B-NEXT: sh3add a0, a0, a1 ; RV64B-NEXT: ret ; ; RV64ZBA-LABEL: mul264: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: addi a1, zero, 264 -; RV64ZBA-NEXT: mul a0, a0, a1 +; RV64ZBA-NEXT: slli a1, a0, 8 +; RV64ZBA-NEXT: sh3add a0, a0, a1 ; RV64ZBA-NEXT: ret %c = mul i64 %a, 264 ret i64 %c } +define i64 @mul514(i64 %a) { +; RV64I-LABEL: mul514: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a1, zero, 514 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64B-LABEL: mul514: +; RV64B: # %bb.0: +; RV64B-NEXT: slli a1, a0, 9 +; RV64B-NEXT: sh1add a0, a0, a1 +; RV64B-NEXT: ret +; +; RV64ZBA-LABEL: mul514: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 9 +; RV64ZBA-NEXT: sh1add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 514 + ret i64 %c +} + +define i64 @mul516(i64 %a) { +; RV64I-LABEL: mul516: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a1, zero, 516 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64B-LABEL: mul516: +; RV64B: # %bb.0: +; RV64B-NEXT: slli a1, a0, 9 +; RV64B-NEXT: sh2add a0, a0, a1 +; RV64B-NEXT: ret +; +; RV64ZBA-LABEL: mul516: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 9 +; RV64ZBA-NEXT: sh2add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 516 + ret i64 %c +} + +define i64 @mul520(i64 %a) { +; RV64I-LABEL: mul520: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a1, zero, 520 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64B-LABEL: mul520: +; RV64B: # %bb.0: +; RV64B-NEXT: slli a1, a0, 9 +; RV64B-NEXT: sh3add a0, a0, a1 +; RV64B-NEXT: ret +; +; RV64ZBA-LABEL: mul520: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 9 +; RV64ZBA-NEXT: sh3add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 520 + ret i64 %c +} + +define i64 @mul1026(i64 %a) { +; RV64I-LABEL: mul1026: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a1, zero, 1026 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64B-LABEL: mul1026: +; RV64B: # %bb.0: +; RV64B-NEXT: slli a1, a0, 10 +; RV64B-NEXT: sh1add a0, a0, a1 +; RV64B-NEXT: ret +; +; RV64ZBA-LABEL: mul1026: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 10 +; RV64ZBA-NEXT: sh1add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 1026 + ret i64 %c +} + +define i64 @mul1028(i64 %a) { +; RV64I-LABEL: mul1028: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a1, zero, 1028 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64B-LABEL: mul1028: +; RV64B: # %bb.0: +; RV64B-NEXT: slli a1, a0, 10 +; RV64B-NEXT: sh2add a0, a0, a1 +; RV64B-NEXT: ret +; +; RV64ZBA-LABEL: mul1028: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 10 +; RV64ZBA-NEXT: sh2add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 1028 + ret i64 %c +} + +define i64 @mul1032(i64 %a) { +; RV64I-LABEL: mul1032: +; RV64I: # %bb.0: +; RV64I-NEXT: addi a1, zero, 1032 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64B-LABEL: mul1032: +; RV64B: # %bb.0: +; RV64B-NEXT: slli a1, a0, 10 +; RV64B-NEXT: sh3add a0, a0, a1 +; RV64B-NEXT: ret +; +; RV64ZBA-LABEL: mul1032: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli a1, a0, 10 +; RV64ZBA-NEXT: sh3add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 1032 + ret i64 %c +} + define i64 @imm_zextw() nounwind { ; RV64I-LABEL: imm_zextw: ; RV64I: # %bb.0: