From 8e1ea8af3898361c3320662661a6939c3d1985ed Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 6 Apr 2026 15:37:51 -0700 Subject: [PATCH] [RISCV][P-ext] Add isel patterns for mhacc/mhaccu/mhaccsu. (#190670) --- llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 7 ++ llvm/test/CodeGen/RISCV/rv32p.ll | 130 +++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index 651c8e8608f5..02c1be2883e1 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1959,6 +1959,13 @@ let Predicates = [HasStdExtP, IsRV32] in { def : Pat<(i32 (add GPR:$rd, (mul_oneuse sexti16:$rs1, zexti16:$rs2))), (MACCSU_H00 GPR:$rd, sexti16:$rs1, zexti16:$rs2)>; + def : Pat<(i32 (add GPR:$rd, (binop_oneuse GPR:$rs1, GPR:$rs2))), + (MHACC GPR:$rd, GPR:$rs1, GPR:$rs2)>; + def : Pat<(i32 (add GPR:$rd, (binop_oneuse GPR:$rs1, GPR:$rs2))), + (MHACCU GPR:$rd, GPR:$rs1, GPR:$rs2)>; + def : Pat<(i32 (add GPR:$rd, (binop_oneuse GPR:$rs1, GPR:$rs2))), + (MHACCSU GPR:$rd, GPR:$rs1, GPR:$rs2)>; + // Narrowing shift patterns (NSRL/NSRA) // Immediate shift amount patterns def : Pat<(riscv_nsrl GPR:$lo, GPR:$hi, uimm6:$shamt), diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll index a4c39e08f746..99bd1f7fd31e 100644 --- a/llvm/test/CodeGen/RISCV/rv32p.ll +++ b/llvm/test/CodeGen/RISCV/rv32p.ll @@ -1189,6 +1189,136 @@ define i32 @macc_h00_multiple_uses(i16 %a, i16 %b, i32 %c, ptr %out) nounwind { ret i32 %result } +define i32 @mhacc(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhacc: +; CHECK: # %bb.0: +; CHECK-NEXT: mhacc a0, a1, a2 +; CHECK-NEXT: ret + %aext = sext i32 %a to i64 + %bext = sext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %rd, %trunc + ret i32 %result +} + +define i32 @mhacc_commute(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhacc_commute: +; CHECK: # %bb.0: +; CHECK-NEXT: mhacc a0, a1, a2 +; CHECK-NEXT: ret + %aext = sext i32 %a to i64 + %bext = sext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %trunc, %rd + ret i32 %result +} + +define i32 @mhaccu(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhaccu: +; CHECK: # %bb.0: +; CHECK-NEXT: mhaccu a0, a1, a2 +; CHECK-NEXT: ret + %aext = zext i32 %a to i64 + %bext = zext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %rd, %trunc + ret i32 %result +} + +define i32 @mhaccu_commute(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhaccu_commute: +; CHECK: # %bb.0: +; CHECK-NEXT: mhaccu a0, a1, a2 +; CHECK-NEXT: ret + %aext = zext i32 %a to i64 + %bext = zext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %trunc, %rd + ret i32 %result +} + +define i32 @mhaccsu(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhaccsu: +; CHECK: # %bb.0: +; CHECK-NEXT: mhaccsu a0, a1, a2 +; CHECK-NEXT: ret + %aext = sext i32 %a to i64 + %bext = zext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %rd, %trunc + ret i32 %result +} + +define i32 @mhaccsu_commute(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhaccsu_commute: +; CHECK: # %bb.0: +; CHECK-NEXT: mhaccsu a0, a1, a2 +; CHECK-NEXT: ret + %aext = sext i32 %a to i64 + %bext = zext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %trunc, %rd + ret i32 %result +} + +define i32 @mhaccsu_swap_operands(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhaccsu_swap_operands: +; CHECK: # %bb.0: +; CHECK-NEXT: mhaccsu a0, a2, a1 +; CHECK-NEXT: ret + %aext = zext i32 %a to i64 + %bext = sext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %rd, %trunc + ret i32 %result +} + +define i32 @mhaccsu_swap_operands_commute(i32 %rd, i32 %a, i32 %b) nounwind { +; CHECK-LABEL: mhaccsu_swap_operands_commute: +; CHECK: # %bb.0: +; CHECK-NEXT: mhaccsu a0, a2, a1 +; CHECK-NEXT: ret + %aext = zext i32 %a to i64 + %bext = sext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %trunc, %rd + ret i32 %result +} + +; Negative test: multiply result has multiple uses, should not combine to mhacc +define i32 @mhacc_multiple_uses(i32 %a, i32 %b, i32 %c, ptr %out) nounwind { +; CHECK-LABEL: mhacc_multiple_uses: +; CHECK: # %bb.0: +; CHECK-NEXT: mulh a1, a0, a1 +; CHECK-NEXT: add a0, a2, a1 +; CHECK-NEXT: sw a1, 0(a3) +; CHECK-NEXT: ret + %aext = sext i32 %a to i64 + %bext = sext i32 %b to i64 + %mul = mul i64 %aext, %bext + %shift = lshr i64 %mul, 32 + %trunc = trunc i64 %shift to i32 + %result = add i32 %c, %trunc + store i32 %trunc, ptr %out + ret i32 %result +} + ; Negative test: multiply result has multiple uses, should not combine define void @wmaccu_multiple_uses(i32 %a, i32 %b, i64 %c, ptr %out1, ptr %out2) nounwind { ; CHECK-LABEL: wmaccu_multiple_uses: