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 = [HasStdExtM] in { 28def MUL : ALU_rr<0b0000001, 0b000, "mul">, 29 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 30def MULH : ALU_rr<0b0000001, 0b001, "mulh">, 31 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 32def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, 33 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 34def MULHU : ALU_rr<0b0000001, 0b011, "mulhu">, 35 Sched<[WriteIMul, ReadIMul, ReadIMul]>; 36def DIV : ALU_rr<0b0000001, 0b100, "div">, 37 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 38def DIVU : ALU_rr<0b0000001, 0b101, "divu">, 39 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 40def REM : ALU_rr<0b0000001, 0b110, "rem">, 41 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 42def REMU : ALU_rr<0b0000001, 0b111, "remu">, 43 Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 44} // Predicates = [HasStdExtM] 45 46let Predicates = [HasStdExtM, IsRV64] in { 47def MULW : ALUW_rr<0b0000001, 0b000, "mulw">, 48 Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; 49def DIVW : ALUW_rr<0b0000001, 0b100, "divw">, 50 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 51def DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">, 52 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 53def REMW : ALUW_rr<0b0000001, 0b110, "remw">, 54 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 55def REMUW : ALUW_rr<0b0000001, 0b111, "remuw">, 56 Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 57} // Predicates = [HasStdExtM, IsRV64] 58 59//===----------------------------------------------------------------------===// 60// Pseudo-instructions and codegen patterns 61//===----------------------------------------------------------------------===// 62 63let Predicates = [HasStdExtM] in { 64def : PatGprGpr<mul, MUL>; 65def : PatGprGpr<mulhs, MULH>; 66def : PatGprGpr<mulhu, MULHU>; 67def : PatGprGpr<riscv_mulhsu, MULHSU>; 68def : PatGprGpr<sdiv, DIV>; 69def : PatGprGpr<udiv, DIVU>; 70def : PatGprGpr<srem, REM>; 71def : PatGprGpr<urem, REMU>; 72} // Predicates = [HasStdExtM] 73 74let Predicates = [HasStdExtM, IsRV64] in { 75def : Pat<(sext_inreg (mul GPR:$rs1, GPR:$rs2), i32), 76 (MULW GPR:$rs1, GPR:$rs2)>; 77 78def : PatGprGpr<riscv_divw, DIVW>; 79def : PatGprGpr<riscv_divuw, DIVUW>; 80def : PatGprGpr<riscv_remuw, REMUW>; 81 82// Handle the specific cases where using DIVU/REMU would be correct and result 83// in fewer instructions than emitting DIVUW/REMUW then zero-extending the 84// result. 85def : Pat<(and (riscv_divuw (assertzexti32 GPR:$rs1), 86 (assertzexti32 GPR:$rs2)), 0xffffffff), 87 (DIVU GPR:$rs1, GPR:$rs2)>; 88def : Pat<(and (riscv_remuw (assertzexti32 GPR:$rs1), 89 (assertzexti32 GPR:$rs2)), 0xffffffff), 90 (REMU GPR:$rs1, GPR:$rs2)>; 91 92// Although the sexti32 operands may not have originated from an i32 srem, 93// this pattern is safe as it is impossible for two sign extended inputs to 94// produce a result where res[63:32]=0 and res[31]=1. 95def : Pat<(srem (sexti32 (i64 GPR:$rs1)), (sexti32 (i64 GPR:$rs2))), 96 (REMW GPR:$rs1, GPR:$rs2)>; 97} // Predicates = [HasStdExtM, IsRV64] 98 99let Predicates = [HasStdExtM, IsRV64, NotHasStdExtZba] in { 100// Special case for calculating the full 64-bit product of a 32x32 unsigned 101// multiply where the inputs aren't known to be zero extended. We can shift the 102// inputs left by 32 and use a MULHU. This saves two SRLIs needed to finish 103// zeroing the upper 32 bits. 104// TODO: If one of the operands is zero extended and the other isn't, we might 105// still be better off shifting both left by 32. 106def : Pat<(i64 (mul (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff))), 107 (MULHU (SLLI GPR:$rs1, 32), (SLLI GPR:$rs2, 32))>; 108// Prevent matching the first part of this pattern to mulw. The mul here has 109// additionals users or the ANDs would have been removed. The above pattern 110// will be used for the other users. If we form a mulw we'll keep the ANDs alive 111// and they'll still become SLLI+SRLI. 112def : Pat<(sext_inreg (mul (and GPR:$rs1, 0xffffffff), 113 (and GPR:$rs2, 0xffffffff)), i32), 114 (ADDIW (MULHU (SLLI GPR:$rs1, 32), (SLLI GPR:$rs2, 32)), 0)>; 115} // Predicates = [HasStdExtM, IsRV64, NotHasStdExtZba] 116