10b57cec5SDimitry Andric//===-- RISCVInstrInfoM.td - RISC-V 'M' instructions -------*- tablegen -*-===// 20b57cec5SDimitry Andric// 30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric// 70b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric// 90b57cec5SDimitry Andric// This file describes the RISC-V instructions from the standard 'M', Integer 100b57cec5SDimitry Andric// Multiplication and Division instruction set extension. 110b57cec5SDimitry Andric// 120b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric// RISC-V specific DAG Nodes. 160b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 18fe6060f1SDimitry Andricdef riscv_mulhsu : SDNode<"RISCVISD::MULHSU", SDTIntBinOp>; 19fe6060f1SDimitry Andricdef riscv_divw : SDNode<"RISCVISD::DIVW", SDT_RISCVIntBinOpW>; 20fe6060f1SDimitry Andricdef riscv_divuw : SDNode<"RISCVISD::DIVUW", SDT_RISCVIntBinOpW>; 21fe6060f1SDimitry Andricdef riscv_remuw : SDNode<"RISCVISD::REMUW", SDT_RISCVIntBinOpW>; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 240b57cec5SDimitry Andric// Instructions 250b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 260b57cec5SDimitry Andric 27*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul] in { 2806c3fb27SDimitry Andricdef MUL : ALU_rr<0b0000001, 0b000, "mul", Commutable=1>, 2913138422SDimitry Andric Sched<[WriteIMul, ReadIMul, ReadIMul]>; 3006c3fb27SDimitry Andricdef MULH : ALU_rr<0b0000001, 0b001, "mulh", Commutable=1>, 3113138422SDimitry Andric Sched<[WriteIMul, ReadIMul, ReadIMul]>; 3213138422SDimitry Andricdef MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, 3313138422SDimitry Andric Sched<[WriteIMul, ReadIMul, ReadIMul]>; 3406c3fb27SDimitry Andricdef MULHU : ALU_rr<0b0000001, 0b011, "mulhu", Commutable=1>, 3513138422SDimitry Andric Sched<[WriteIMul, ReadIMul, ReadIMul]>; 36*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul] 37fcaf7f86SDimitry Andric 38fcaf7f86SDimitry Andriclet Predicates = [HasStdExtM] in { 3913138422SDimitry Andricdef DIV : ALU_rr<0b0000001, 0b100, "div">, 4013138422SDimitry Andric Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 4113138422SDimitry Andricdef DIVU : ALU_rr<0b0000001, 0b101, "divu">, 4213138422SDimitry Andric Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; 4313138422SDimitry Andricdef REM : ALU_rr<0b0000001, 0b110, "rem">, 44*0fca6ea1SDimitry Andric Sched<[WriteIRem, ReadIRem, ReadIRem]>; 4513138422SDimitry Andricdef REMU : ALU_rr<0b0000001, 0b111, "remu">, 46*0fca6ea1SDimitry Andric Sched<[WriteIRem, ReadIRem, ReadIRem]>; 470b57cec5SDimitry Andric} // Predicates = [HasStdExtM] 480b57cec5SDimitry Andric 49*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64], IsSignExtendingOpW = 1 in { 5006c3fb27SDimitry Andricdef MULW : ALUW_rr<0b0000001, 0b000, "mulw", Commutable=1>, 5113138422SDimitry Andric Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; 52*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul, IsRV64] 53fcaf7f86SDimitry Andric 54bdd1243dSDimitry Andriclet Predicates = [HasStdExtM, IsRV64], IsSignExtendingOpW = 1 in { 5513138422SDimitry Andricdef DIVW : ALUW_rr<0b0000001, 0b100, "divw">, 5613138422SDimitry Andric Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 5713138422SDimitry Andricdef DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">, 5813138422SDimitry Andric Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; 5913138422SDimitry Andricdef REMW : ALUW_rr<0b0000001, 0b110, "remw">, 60*0fca6ea1SDimitry Andric Sched<[WriteIRem32, ReadIRem32, ReadIRem32]>; 6113138422SDimitry Andricdef REMUW : ALUW_rr<0b0000001, 0b111, "remuw">, 62*0fca6ea1SDimitry Andric Sched<[WriteIRem32, ReadIRem32, ReadIRem32]>; 630b57cec5SDimitry Andric} // Predicates = [HasStdExtM, IsRV64] 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 660b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 670b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 680b57cec5SDimitry Andric 69*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul] in { 700b57cec5SDimitry Andricdef : PatGprGpr<mul, MUL>; 710b57cec5SDimitry Andricdef : PatGprGpr<mulhs, MULH>; 720b57cec5SDimitry Andricdef : PatGprGpr<mulhu, MULHU>; 73fe6060f1SDimitry Andricdef : PatGprGpr<riscv_mulhsu, MULHSU>; 74*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul] 75fcaf7f86SDimitry Andric 76fcaf7f86SDimitry Andriclet Predicates = [HasStdExtM] in { 770b57cec5SDimitry Andricdef : PatGprGpr<sdiv, DIV>; 780b57cec5SDimitry Andricdef : PatGprGpr<udiv, DIVU>; 790b57cec5SDimitry Andricdef : PatGprGpr<srem, REM>; 800b57cec5SDimitry Andricdef : PatGprGpr<urem, REMU>; 810b57cec5SDimitry Andric} // Predicates = [HasStdExtM] 820b57cec5SDimitry Andric 83349cc55cSDimitry Andric// Select W instructions if only the lower 32-bits of the result are used. 84*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64] in 85349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<mul>, MULW>; 860b57cec5SDimitry Andric 87fcaf7f86SDimitry Andriclet Predicates = [HasStdExtM, IsRV64] in { 880b57cec5SDimitry Andricdef : PatGprGpr<riscv_divw, DIVW>; 890b57cec5SDimitry Andricdef : PatGprGpr<riscv_divuw, DIVUW>; 900b57cec5SDimitry Andricdef : PatGprGpr<riscv_remuw, REMUW>; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric// Handle the specific cases where using DIVU/REMU would be correct and result 930b57cec5SDimitry Andric// in fewer instructions than emitting DIVUW/REMUW then zero-extending the 940b57cec5SDimitry Andric// result. 95e8d8bef9SDimitry Andricdef : Pat<(and (riscv_divuw (assertzexti32 GPR:$rs1), 96e8d8bef9SDimitry Andric (assertzexti32 GPR:$rs2)), 0xffffffff), 970b57cec5SDimitry Andric (DIVU GPR:$rs1, GPR:$rs2)>; 98e8d8bef9SDimitry Andricdef : Pat<(and (riscv_remuw (assertzexti32 GPR:$rs1), 99e8d8bef9SDimitry Andric (assertzexti32 GPR:$rs2)), 0xffffffff), 1000b57cec5SDimitry Andric (REMU GPR:$rs1, GPR:$rs2)>; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric// Although the sexti32 operands may not have originated from an i32 srem, 1030b57cec5SDimitry Andric// this pattern is safe as it is impossible for two sign extended inputs to 1040b57cec5SDimitry Andric// produce a result where res[63:32]=0 and res[31]=1. 105fe6060f1SDimitry Andricdef : Pat<(srem (sexti32 (i64 GPR:$rs1)), (sexti32 (i64 GPR:$rs2))), 1060b57cec5SDimitry Andric (REMW GPR:$rs1, GPR:$rs2)>; 1070b57cec5SDimitry Andric} // Predicates = [HasStdExtM, IsRV64] 108fe6060f1SDimitry Andric 109*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64, NotHasStdExtZba] in { 110fe6060f1SDimitry Andric// Special case for calculating the full 64-bit product of a 32x32 unsigned 111fe6060f1SDimitry Andric// multiply where the inputs aren't known to be zero extended. We can shift the 112fe6060f1SDimitry Andric// inputs left by 32 and use a MULHU. This saves two SRLIs needed to finish 113fe6060f1SDimitry Andric// zeroing the upper 32 bits. 114fe6060f1SDimitry Andricdef : Pat<(i64 (mul (and GPR:$rs1, 0xffffffff), (and GPR:$rs2, 0xffffffff))), 115*0fca6ea1SDimitry Andric (MULHU (i64 (SLLI GPR:$rs1, 32)), (i64 (SLLI GPR:$rs2, 32)))>; 116*0fca6ea1SDimitry Andric} // Predicates = [HasStdExtZmmul, IsRV64, NotHasStdExtZba] 1175f757f3fSDimitry Andric 1185f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 1195f757f3fSDimitry Andric// Experimental RV64 i32 legalization patterns. 1205f757f3fSDimitry Andric//===----------------------------------------------------------------------===// 1215f757f3fSDimitry Andric 122*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZmmul, IsRV64] in { 1235f757f3fSDimitry Andricdef : PatGprGpr<mul, MULW, i32, i32>; 1245f757f3fSDimitry Andric} 1255f757f3fSDimitry Andric 1265f757f3fSDimitry Andriclet Predicates = [HasStdExtM, IsRV64] in { 1275f757f3fSDimitry Andricdef : PatGprGpr<sdiv, DIVW, i32, i32>; 1285f757f3fSDimitry Andricdef : PatGprGpr<udiv, DIVUW, i32, i32>; 1295f757f3fSDimitry Andricdef : PatGprGpr<srem, REMW, i32, i32>; 1305f757f3fSDimitry Andricdef : PatGprGpr<urem, REMUW, i32, i32>; 1315f757f3fSDimitry Andric} 132