1//===-- RISCVInstrInfoZfa.td - RISC-V 'Zfa' 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 'Zfa' 10// additional floating-point extension, version 1.0. 11// 12//===----------------------------------------------------------------------===// 13 14//===----------------------------------------------------------------------===// 15// RISC-V specific DAG Nodes. 16//===----------------------------------------------------------------------===// 17 18def SDT_RISCVFLI 19 : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVT<1, XLenVT>]>; 20 21def riscv_fli : SDNode<"RISCVISD::FLI", SDT_RISCVFLI>; 22 23//===----------------------------------------------------------------------===// 24// Operand and SDNode transformation definitions. 25//===----------------------------------------------------------------------===// 26 27// 5-bit floating-point immediate encodings. 28def LoadFPImmOperand : AsmOperandClass { 29 let Name = "LoadFPImm"; 30 let ParserMethod = "parseFPImm"; 31 let RenderMethod = "addFPImmOperands"; 32 let DiagnosticType = "InvalidLoadFPImm"; 33} 34 35def loadfpimm : Operand<XLenVT> { 36 let ParserMatchClass = LoadFPImmOperand; 37 let PrintMethod = "printFPImmOperand"; 38 let OperandType = "OPERAND_UIMM5"; 39 let OperandNamespace = "RISCVOp"; 40} 41 42def RTZArg : AsmOperandClass { 43 let Name = "RTZArg"; 44 let RenderMethod = "addFRMArgOperands"; 45 let DiagnosticType = "InvalidRTZArg"; 46 let ParserMethod = "parseFRMArg"; 47} 48 49def rtzarg : Operand<XLenVT> { 50 let ParserMatchClass = RTZArg; 51 let PrintMethod = "printFRMArg"; 52 let DecoderMethod = "decodeRTZArg"; 53 let OperandType = "OPERAND_RTZARG"; 54 let OperandNamespace = "RISCVOp"; 55} 56 57//===----------------------------------------------------------------------===// 58// Instruction class templates 59//===----------------------------------------------------------------------===// 60 61let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 62class FPBinaryOp_rr<bits<7> funct7, bits<3> funct3, DAGOperand rdty, 63 DAGOperand rsty, string opcodestr> 64 : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), 65 (ins rsty:$rs1, rsty:$rs2), opcodestr, "$rd, $rs1, $rs2">; 66 67let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 68class FPFLI_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3, 69 DAGOperand rdty, string opcodestr> 70 : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), 71 (ins loadfpimm:$imm), opcodestr, "$rd, $imm"> { 72 bits<5> imm; 73 74 let rs2 = rs2val; 75 let rs1 = imm; 76} 77 78let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 79 UseNamedOperandTable = 1, hasPostISelHook = 1 in 80class FPUnaryOp_r_rtz<bits<7> funct7, bits<5> rs2val, DAGOperand rdty, 81 DAGOperand rs1ty, string opcodestr> 82 : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd), 83 (ins rs1ty:$rs1, rtzarg:$frm), opcodestr, 84 "$rd, $rs1$frm"> { 85 let rs2 = rs2val; 86} 87 88//===----------------------------------------------------------------------===// 89// Instructions 90//===----------------------------------------------------------------------===// 91 92let Predicates = [HasStdExtZfa] in { 93let isReMaterializable = 1, isAsCheapAsAMove = 1 in 94def FLI_S : FPFLI_r<0b1111000, 0b00001, 0b000, FPR32, "fli.s">, 95 Sched<[WriteFLI32]>; 96 97let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in { 98def FMINM_S: FPALU_rr<0b0010100, 0b010, "fminm.s", FPR32, Commutable=1>; 99def FMAXM_S: FPALU_rr<0b0010100, 0b011, "fmaxm.s", FPR32, Commutable=1>; 100} 101 102def FROUND_S : FPUnaryOp_r_frm<0b0100000, 0b00100, FPR32, FPR32, "fround.s">, 103 Sched<[WriteFRoundF32, ReadFRoundF32]>; 104def FROUNDNX_S : FPUnaryOp_r_frm<0b0100000, 0b00101, FPR32, FPR32, "froundnx.s">, 105 Sched<[WriteFRoundF32, ReadFRoundF32]>; 106 107let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in { 108def FLTQ_S : FPCmp_rr<0b1010000, 0b101, "fltq.s", FPR32>; 109def FLEQ_S : FPCmp_rr<0b1010000, 0b100, "fleq.s", FPR32>; 110} 111} // Predicates = [HasStdExtZfa] 112 113let Predicates = [HasStdExtZfa, HasStdExtD] in { 114let isReMaterializable = 1, isAsCheapAsAMove = 1 in 115def FLI_D : FPFLI_r<0b1111001, 0b00001, 0b000, FPR64, "fli.d">, 116 Sched<[WriteFLI64]>; 117 118let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in { 119def FMINM_D: FPALU_rr<0b0010101, 0b010, "fminm.d", FPR64, Commutable=1>; 120def FMAXM_D: FPALU_rr<0b0010101, 0b011, "fmaxm.d", FPR64, Commutable=1>; 121} 122 123def FROUND_D : FPUnaryOp_r_frm<0b0100001, 0b00100, FPR64, FPR64, "fround.d">, 124 Sched<[WriteFRoundF64, ReadFRoundF64]>; 125def FROUNDNX_D : FPUnaryOp_r_frm<0b0100001, 0b00101, FPR64, FPR64, "froundnx.d">, 126 Sched<[WriteFRoundF64, ReadFRoundF64]>; 127 128let IsSignExtendingOpW = 1 in 129def FCVTMOD_W_D 130 : FPUnaryOp_r_rtz<0b1100001, 0b01000, GPR, FPR64, "fcvtmod.w.d">, 131 Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>; 132 133let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in { 134def FLTQ_D : FPCmp_rr<0b1010001, 0b101, "fltq.d", FPR64>; 135def FLEQ_D : FPCmp_rr<0b1010001, 0b100, "fleq.d", FPR64>; 136} 137} // Predicates = [HasStdExtZfa, HasStdExtD] 138 139let Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] in { 140let mayRaiseFPException = 0 in { 141def FMVH_X_D : FPUnaryOp_r<0b1110001, 0b00001, 0b000, GPR, FPR64, "fmvh.x.d">, 142 Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>; 143def FMVP_D_X : FPBinaryOp_rr<0b1011001, 0b000, FPR64, GPR, "fmvp.d.x">, 144 Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]>; 145} 146 147let isCodeGenOnly = 1, mayRaiseFPException = 0 in 148def FMV_X_W_FPR64 : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR64, 149 "fmv.x.w">, 150 Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>; 151} // Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] 152 153let Predicates = [HasStdExtZfa, HasStdExtZfhOrZvfh] in 154let isReMaterializable = 1, isAsCheapAsAMove = 1 in 155def FLI_H : FPFLI_r<0b1111010, 0b00001, 0b000, FPR16, "fli.h">, 156 Sched<[WriteFLI16]>; 157 158let Predicates = [HasStdExtZfa, HasStdExtZfh] in { 159let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in { 160def FMINM_H: FPALU_rr<0b0010110, 0b010, "fminm.h", FPR16, Commutable=1>; 161def FMAXM_H: FPALU_rr<0b0010110, 0b011, "fmaxm.h", FPR16, Commutable=1>; 162} 163 164def FROUND_H : FPUnaryOp_r_frm<0b0100010, 0b00100, FPR16, FPR16, "fround.h">, 165 Sched<[WriteFRoundF16, ReadFRoundF16]>; 166def FROUNDNX_H : FPUnaryOp_r_frm<0b0100010, 0b00101, FPR16, FPR16, "froundnx.h">, 167 Sched<[WriteFRoundF16, ReadFRoundF16]>; 168 169let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in { 170def FLTQ_H : FPCmp_rr<0b1010010, 0b101, "fltq.h", FPR16>; 171def FLEQ_H : FPCmp_rr<0b1010010, 0b100, "fleq.h", FPR16>; 172} 173} // Predicates = [HasStdExtZfa, HasStdExtZfh] 174 175//===----------------------------------------------------------------------===// 176// Pseudo-instructions and codegen patterns 177//===----------------------------------------------------------------------===// 178 179let Predicates = [HasStdExtZfa] in { 180def : InstAlias<"fgtq.s $rd, $rs, $rt", 181 (FLTQ_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 182def : InstAlias<"fgeq.s $rd, $rs, $rt", 183 (FLEQ_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 184} 185 186let Predicates = [HasStdExtZfa, HasStdExtD] in { 187def : InstAlias<"fgtq.d $rd, $rs, $rt", 188 (FLTQ_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; 189def : InstAlias<"fgeq.d $rd, $rs, $rt", 190 (FLEQ_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; 191} 192 193let Predicates = [HasStdExtZfa, HasStdExtZfh] in { 194def : InstAlias<"fgtq.h $rd, $rs, $rt", 195 (FLTQ_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>; 196def : InstAlias<"fgeq.h $rd, $rs, $rt", 197 (FLEQ_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>; 198} 199 200//===----------------------------------------------------------------------===// 201// Codegen patterns 202//===----------------------------------------------------------------------===// 203 204let Predicates = [HasStdExtZfa] in { 205def: Pat<(f32 (riscv_fli timm:$imm)), (FLI_S timm:$imm)>; 206 207def: PatFprFpr<fminimum, FMINM_S, FPR32, f32>; 208def: PatFprFpr<fmaximum, FMAXM_S, FPR32, f32>; 209 210// frint rounds according to the current rounding mode and detects 211// inexact conditions. 212def: Pat<(any_frint FPR32:$rs1), (FROUNDNX_S FPR32:$rs1, FRM_DYN)>; 213 214// fnearbyint is like frint but does not detect inexact conditions. 215def: Pat<(any_fnearbyint FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_DYN)>; 216 217def: Pat<(any_fround FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RMM)>; 218def: Pat<(any_froundeven FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RNE)>; 219def: Pat<(any_ffloor FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RDN)>; 220def: Pat<(any_fceil FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RUP)>; 221def: Pat<(any_ftrunc FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RTZ)>; 222 223def: PatSetCC<FPR32, strict_fsetcc, SETLT, FLTQ_S, f32>; 224def: PatSetCC<FPR32, strict_fsetcc, SETOLT, FLTQ_S, f32>; 225def: PatSetCC<FPR32, strict_fsetcc, SETLE, FLEQ_S, f32>; 226def: PatSetCC<FPR32, strict_fsetcc, SETOLE, FLEQ_S, f32>; 227} // Predicates = [HasStdExtZfa] 228 229let Predicates = [HasStdExtZfa, HasStdExtD] in { 230def: Pat<(f64 (riscv_fli timm:$imm)), (FLI_D timm:$imm)>; 231 232def: PatFprFpr<fminimum, FMINM_D, FPR64, f64>; 233def: PatFprFpr<fmaximum, FMAXM_D, FPR64, f64>; 234 235// frint rounds according to the current rounding mode and detects 236// inexact conditions. 237def: Pat<(any_frint FPR64:$rs1), (FROUNDNX_D FPR64:$rs1, FRM_DYN)>; 238 239// fnearbyint is like frint but does not detect inexact conditions. 240def: Pat<(any_fnearbyint FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_DYN)>; 241 242def: Pat<(any_fround FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RMM)>; 243def: Pat<(any_froundeven FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RNE)>; 244def: Pat<(any_ffloor FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RDN)>; 245def: Pat<(any_fceil FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RUP)>; 246def: Pat<(any_ftrunc FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RTZ)>; 247 248def: PatSetCC<FPR64, strict_fsetcc, SETLT, FLTQ_D, f64>; 249def: PatSetCC<FPR64, strict_fsetcc, SETOLT, FLTQ_D, f64>; 250def: PatSetCC<FPR64, strict_fsetcc, SETLE, FLEQ_D, f64>; 251def: PatSetCC<FPR64, strict_fsetcc, SETOLE, FLEQ_D, f64>; 252} // Predicates = [HasStdExtZfa, HasStdExtD] 253 254let Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] in { 255def : Pat<(RISCVBuildPairF64 GPR:$rs1, GPR:$rs2), 256 (FMVP_D_X GPR:$rs1, GPR:$rs2)>; 257} 258 259let Predicates = [HasStdExtZfa, HasStdExtZfh] in { 260def: Pat<(f16 (riscv_fli timm:$imm)), (FLI_H timm:$imm)>; 261 262def: PatFprFpr<fminimum, FMINM_H, FPR16, f16>; 263def: PatFprFpr<fmaximum, FMAXM_H, FPR16, f16>; 264 265// frint rounds according to the current rounding mode and detects 266// inexact conditions. 267def: Pat<(f16 (any_frint FPR16:$rs1)), (FROUNDNX_H FPR16:$rs1, FRM_DYN)>; 268 269// fnearbyint is like frint but does not detect inexact conditions. 270def: Pat<(f16 (any_fnearbyint FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_DYN)>; 271 272def: Pat<(f16 (any_fround FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RMM)>; 273def: Pat<(f16 (any_froundeven FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RNE)>; 274def: Pat<(f16 (any_ffloor FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RDN)>; 275def: Pat<(f16 (any_fceil FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RUP)>; 276def: Pat<(f16 (any_ftrunc FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RTZ)>; 277 278def: PatSetCC<FPR16, strict_fsetcc, SETLT, FLTQ_H, f16>; 279def: PatSetCC<FPR16, strict_fsetcc, SETOLT, FLTQ_H, f16>; 280def: PatSetCC<FPR16, strict_fsetcc, SETLE, FLEQ_H, f16>; 281def: PatSetCC<FPR16, strict_fsetcc, SETOLE, FLEQ_H, f16>; 282} // Predicates = [HasStdExtZfa, HasStdExtZfh] 283