1//===-- RISCVInstrInfoM.td - RISC-V 'M' instructions -------*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file describes the RISC-V instructions from the standard 'M', Integer 10// Multiplication and Division instruction set extension. 11// 12//===----------------------------------------------------------------------===// 13 14//===----------------------------------------------------------------------===// 15// RISC-V specific DAG Nodes. 16//===----------------------------------------------------------------------===// 17 18def riscv_mulhsu : SDNode<"RISCVISD::MULHSU", SDTIntBinOp>; 19def riscv_divw : SDNode<"RISCVISD::DIVW", SDT_RISCVIntBinOpW>; 20def riscv_divuw : SDNode<"RISCVISD::DIVUW", SDT_RISCVIntBinOpW>; 21def riscv_remuw : SDNode<"RISCVISD::REMUW", SDT_RISCVIntBinOpW>; 22 23//===----------------------------------------------------------------------===// 24// Instructions 25//===----------------------------------------------------------------------===// 26 27let Predicates = [HasStdExtMOrZmmul] in { 28def MUL : ALU_rr<0b0000001, 0b000, "mul", /*Commutable*/1>, 29 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 30def MULH : ALU_rr<0b0000001, 0b001, "mulh", /*Commutable*/1>, 31 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 32def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, 33 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 34def MULHU : ALU_rr<0b0000001, 0b011, "mulhu", /*Commutable*/1>, 35 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 36} // Predicates = [HasStdExtMOrZmmul] 37 38let Predicates = [HasStdExtM] in { 39def DIV : ALU_rr<0b0000001, 0b100, "div">, 40 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 41def DIVU : ALU_rr<0b0000001, 0b101, "divu">, 42 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 43def REM : ALU_rr<0b0000001, 0b110, "rem">, 44 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 45def REMU : ALU_rr<0b0000001, 0b111, "remu">, 46 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 47} // Predicates = [HasStdExtM] 48 49let Predicates = [HasStdExtMOrZmmul, IsRV64], IsSignExtendingOpW = 1 in { 50def MULW : ALUW_rr<0b0000001, 0b000, "mulw", /*Commutable*/1>, 51 Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; 52} // Predicates = [HasStdExtMOrZmmul, IsRV64] 53 54let Predicates = [HasStdExtM, IsRV64], IsSignExtendingOpW = 1 in { 55def DIVW : ALUW_rr<0b0000001, 0b100, "divw">, 56 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 57def DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">, 58 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 59def REMW : ALUW_rr<0b0000001, 0b110, "remw">, 60 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 61def REMUW : ALUW_rr<0b0000001, 0b111, "remuw">, 62 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 63} // Predicates = [HasStdExtM, IsRV64] 64 65//===----------------------------------------------------------------------===// 66// Pseudo-instructions and codegen patterns 67//===----------------------------------------------------------------------===// 68 69let Predicates = [HasStdExtMOrZmmul] in { 70def : PatGprGpr<mul, MUL>; 71def : PatGprGpr<mulhs, MULH>; 72def : PatGprGpr<mulhu, MULHU>; 73def : PatGprGpr<riscv_mulhsu, MULHSU>; 74} // Predicates = [HasStdExtMOrZmmul] 75 76let Predicates = [HasStdExtM] in { 77def : PatGprGpr<sdiv, DIV>; 78def : PatGprGpr<udiv, DIVU>; 79def : PatGprGpr<srem, REM>; 80def : PatGprGpr<urem, REMU>; 81} // Predicates = [HasStdExtM] 82 83// Select W instructions if only the lower 32-bits of the result are used. 84let Predicates = [HasStdExtMOrZmmul, IsRV64] in 85def : PatGprGpr<binop_allwusers<mul>, MULW>; 86 87let Predicates = [HasStdExtM, IsRV64] in { 88def : PatGprGpr<riscv_divw, DIVW>; 89def : PatGprGpr<riscv_divuw, DIVUW>; 90def : PatGprGpr<riscv_remuw, REMUW>; 91 92// Handle the specific cases where using DIVU/REMU would be correct and result 93// in fewer instructions than emitting DIVUW/REMUW then zero-extending the 94// result. 95def : Pat<(and (riscv_divuw (assertzexti32 GPR:$rs1), 96 (assertzexti32 GPR:$rs2)), 0xffffffff), 97 (DIVU GPR:$rs1, GPR:$rs2)>; 98def : Pat<(and (riscv_remuw (assertzexti32 GPR:$rs1), 99 (assertzexti32 GPR:$rs2)), 0xffffffff), 100 (REMU GPR:$rs1, GPR:$rs2)>; 101 102// Although the sexti32 operands may not have originated from an i32 srem, 103// this pattern is safe as it is impossible for two sign extended inputs to 104// produce a result where res[63:32]=0 and res[31]=1. 105def : Pat<(srem (sexti32 (i64 GPR:$rs1)), (sexti32 (i64 GPR:$rs2))), 106 (REMW GPR:$rs1, GPR:$rs2)>; 107} // Predicates = [HasStdExtM, IsRV64] 108 109let Predicates = [HasStdExtMOrZmmul, IsRV64, NotHasStdExtZba] in { 110// Special case for calculating the full 64-bit product of a 32x32 unsigned 111// multiply where the inputs aren't known to be zero extended. We can shift the 112// inputs left by 32 and use a MULHU. This saves two SRLIs needed to finish 113// zeroing the upper 32 bits. 114def : Pat<(i64 (mul (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff))), 115 (MULHU (SLLI GPR:$rs1, 32), (SLLI GPR:$rs2, 32))>; 116} // Predicates = [HasStdExtMOrZmmul, IsRV64, NotHasStdExtZba] 117