aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td')
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td137
1 files changed, 77 insertions, 60 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
index 85ebe054499e..7316b7ad7674 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
@@ -33,9 +33,9 @@ def riscv_fmv_x_anyexth
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class FPFMAH_rrr_frm<RISCVOpcode opcode, string opcodestr>
- : RVInstR4<0b10, opcode, (outs FPR16:$rd),
- (ins FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, frmarg:$funct3),
- opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
+ : RVInstR4Frm<0b10, opcode, (outs FPR16:$rd),
+ (ins FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, frmarg:$funct3),
+ opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
class FPFMAHDynFrmAlias<FPFMAH_rrr_frm Inst, string OpcodeStr>
: InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
@@ -60,7 +60,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class FPCmpH_rr<bits<3> funct3, string opcodestr>
: RVInstR<0b1010010, funct3, OPC_OP_FP, (outs GPR:$rd),
(ins FPR16:$rs1, FPR16:$rs2), opcodestr, "$rd, $rs1, $rs2">,
- Sched<[]>;
+ Sched<[WriteFCmp16, ReadFCmp16, ReadFCmp16]>;
//===----------------------------------------------------------------------===//
// Instructions
@@ -71,7 +71,7 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
def FLH : RVInstI<0b001, OPC_LOAD_FP, (outs FPR16:$rd),
(ins GPR:$rs1, simm12:$imm12),
"flh", "$rd, ${imm12}(${rs1})">,
- Sched<[]>;
+ Sched<[WriteFLD16, ReadFMemBase]>;
// Operands for stores are in the order srcreg, base, offset rather than
// reflecting the order these fields are specified in the instruction
@@ -80,94 +80,93 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
def FSH : RVInstS<0b001, OPC_STORE_FP, (outs),
(ins FPR16:$rs2, GPR:$rs1, simm12:$imm12),
"fsh", "$rs2, ${imm12}(${rs1})">,
- Sched<[]>;
+ Sched<[WriteFST16, ReadStoreData, ReadFMemBase]>;
def FMADD_H : FPFMAH_rrr_frm<OPC_MADD, "fmadd.h">,
- Sched<[]>;
+ Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
def : FPFMAHDynFrmAlias<FMADD_H, "fmadd.h">;
def FMSUB_H : FPFMAH_rrr_frm<OPC_MSUB, "fmsub.h">,
- Sched<[]>;
+ Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
def : FPFMAHDynFrmAlias<FMSUB_H, "fmsub.h">;
def FNMSUB_H : FPFMAH_rrr_frm<OPC_NMSUB, "fnmsub.h">,
- Sched<[]>;
+ Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
def : FPFMAHDynFrmAlias<FNMSUB_H, "fnmsub.h">;
def FNMADD_H : FPFMAH_rrr_frm<OPC_NMADD, "fnmadd.h">,
- Sched<[]>;
+ Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>;
def : FPFMAHDynFrmAlias<FNMADD_H, "fnmadd.h">;
def FADD_H : FPALUH_rr_frm<0b0000010, "fadd.h">,
- Sched<[]>;
+ Sched<[WriteFALU16, ReadFALU16, ReadFALU16]>;
def : FPALUHDynFrmAlias<FADD_H, "fadd.h">;
def FSUB_H : FPALUH_rr_frm<0b0000110, "fsub.h">,
- Sched<[]>;
+ Sched<[WriteFALU16, ReadFALU16, ReadFALU16]>;
def : FPALUHDynFrmAlias<FSUB_H, "fsub.h">;
def FMUL_H : FPALUH_rr_frm<0b0001010, "fmul.h">,
- Sched<[]>;
+ Sched<[WriteFMul16, ReadFMul16, ReadFMul16]>;
def : FPALUHDynFrmAlias<FMUL_H, "fmul.h">;
def FDIV_H : FPALUH_rr_frm<0b0001110, "fdiv.h">,
- Sched<[]>;
+ Sched<[WriteFDiv16, ReadFDiv16, ReadFDiv16]>;
def : FPALUHDynFrmAlias<FDIV_H, "fdiv.h">;
def FSQRT_H : FPUnaryOp_r_frm<0b0101110, FPR16, FPR16, "fsqrt.h">,
- Sched<[]> {
+ Sched<[WriteFSqrt16, ReadFSqrt16]> {
let rs2 = 0b00000;
}
def : FPUnaryOpDynFrmAlias<FSQRT_H, "fsqrt.h", FPR16, FPR16>;
def FSGNJ_H : FPALUH_rr<0b0010010, 0b000, "fsgnj.h">,
- Sched<[]>;
+ Sched<[WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16]>;
def FSGNJN_H : FPALUH_rr<0b0010010, 0b001, "fsgnjn.h">,
- Sched<[]>;
+ Sched<[WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16]>;
def FSGNJX_H : FPALUH_rr<0b0010010, 0b010, "fsgnjx.h">,
- Sched<[]>;
-
+ Sched<[WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16]>;
def FMIN_H : FPALUH_rr<0b0010110, 0b000, "fmin.h">,
- Sched<[]>;
+ Sched<[WriteFMinMax16, ReadFMinMax16, ReadFMinMax16]>;
def FMAX_H : FPALUH_rr<0b0010110, 0b001, "fmax.h">,
- Sched<[]>;
+ Sched<[WriteFMinMax16, ReadFMinMax16, ReadFMinMax16]>;
def FCVT_W_H : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.w.h">,
- Sched<[]> {
+ Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]> {
let rs2 = 0b00000;
}
def : FPUnaryOpDynFrmAlias<FCVT_W_H, "fcvt.w.h", GPR, FPR16>;
def FCVT_WU_H : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.wu.h">,
- Sched<[]> {
+ Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]> {
let rs2 = 0b00001;
}
def : FPUnaryOpDynFrmAlias<FCVT_WU_H, "fcvt.wu.h", GPR, FPR16>;
def FCVT_H_W : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.w">,
- Sched<[]> {
+ Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]> {
let rs2 = 0b00000;
}
def : FPUnaryOpDynFrmAlias<FCVT_H_W, "fcvt.h.w", FPR16, GPR>;
def FCVT_H_WU : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.wu">,
- Sched<[]> {
+ Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]> {
let rs2 = 0b00001;
}
def : FPUnaryOpDynFrmAlias<FCVT_H_WU, "fcvt.h.wu", FPR16, GPR>;
def FCVT_H_S : FPUnaryOp_r_frm<0b0100010, FPR16, FPR32, "fcvt.h.s">,
- Sched<[]> {
+ Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]> {
let rs2 = 0b00000;
}
def : FPUnaryOpDynFrmAlias<FCVT_H_S, "fcvt.h.s", FPR16, FPR32>;
def FCVT_S_H : FPUnaryOp_r<0b0100000, 0b000, FPR32, FPR16, "fcvt.s.h">,
- Sched<[]> {
+ Sched<[WriteFCvtF16ToF32, ReadFCvtF16ToF32]> {
let rs2 = 0b00010;
}
def FMV_X_H : FPUnaryOp_r<0b1110010, 0b000, GPR, FPR16, "fmv.x.h">,
- Sched<[]> {
+ Sched<[WriteFMovF16ToI16, ReadFMovF16ToI16]> {
let rs2 = 0b00000;
}
def FMV_H_X : FPUnaryOp_r<0b1111010, 0b000, FPR16, GPR, "fmv.h.x">,
- Sched<[]> {
+ Sched<[WriteFMovI16ToF16, ReadFMovI16ToF16]> {
let rs2 = 0b00000;
}
@@ -176,32 +175,32 @@ def FLT_H : FPCmpH_rr<0b001, "flt.h">;
def FLE_H : FPCmpH_rr<0b000, "fle.h">;
def FCLASS_H : FPUnaryOp_r<0b1110010, 0b001, GPR, FPR16, "fclass.h">,
- Sched<[]> {
+ Sched<[WriteFClass16, ReadFClass16]> {
let rs2 = 0b00000;
}
} // Predicates = [HasStdExtZfh]
let Predicates = [HasStdExtZfh, IsRV64] in {
def FCVT_L_H : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.l.h">,
- Sched<[]> {
+ Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]> {
let rs2 = 0b00010;
}
def : FPUnaryOpDynFrmAlias<FCVT_L_H, "fcvt.l.h", GPR, FPR16>;
def FCVT_LU_H : FPUnaryOp_r_frm<0b1100010, GPR, FPR16, "fcvt.lu.h">,
- Sched<[]> {
+ Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]> {
let rs2 = 0b00011;
}
def : FPUnaryOpDynFrmAlias<FCVT_LU_H, "fcvt.lu.h", GPR, FPR16>;
def FCVT_H_L : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.l">,
- Sched<[]> {
+ Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]> {
let rs2 = 0b00010;
}
def : FPUnaryOpDynFrmAlias<FCVT_H_L, "fcvt.h.l", FPR16, GPR>;
def FCVT_H_LU : FPUnaryOp_r_frm<0b1101010, FPR16, GPR, "fcvt.h.lu">,
- Sched<[]> {
+ Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]> {
let rs2 = 0b00011;
}
def : FPUnaryOpDynFrmAlias<FCVT_H_LU, "fcvt.h.lu", FPR16, GPR>;
@@ -209,13 +208,13 @@ def : FPUnaryOpDynFrmAlias<FCVT_H_LU, "fcvt.h.lu", FPR16, GPR>;
let Predicates = [HasStdExtZfh, HasStdExtD] in {
def FCVT_H_D : FPUnaryOp_r_frm<0b0100010, FPR16, FPR64, "fcvt.h.d">,
- Sched<[]> {
+ Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]> {
let rs2 = 0b00001;
}
def : FPUnaryOpDynFrmAlias<FCVT_H_D, "fcvt.h.d", FPR16, FPR64>;
def FCVT_D_H : FPUnaryOp_r<0b0100001, 0b000, FPR64, FPR16, "fcvt.d.h">,
- Sched<[]> {
+ Sched<[WriteFCvtF16ToF64, ReadFCvtF16ToF64]> {
let rs2 = 0b00010;
}
} // Predicates = [HasStdExtZfh, HasStdExtD]
@@ -280,10 +279,7 @@ def : PatFpr16Fpr16<fcopysign, FSGNJ_H>;
def : Pat<(fcopysign FPR16:$rs1, (fneg FPR16:$rs2)), (FSGNJN_H $rs1, $rs2)>;
def : Pat<(fcopysign FPR16:$rs1, FPR32:$rs2),
(FSGNJ_H $rs1, (FCVT_H_S $rs2, 0b111))>;
-def : Pat<(fcopysign FPR16:$rs1, FPR64:$rs2),
- (FSGNJ_H $rs1, (FCVT_H_D $rs2, 0b111))>;
def : Pat<(fcopysign FPR32:$rs1, FPR16:$rs2), (FSGNJ_S $rs1, (FCVT_S_H $rs2))>;
-def : Pat<(fcopysign FPR64:$rs1, FPR16:$rs2), (FSGNJ_D $rs1, (FCVT_D_H $rs2))>;
// fmadd: rs1 * rs2 + rs3
def : Pat<(fma FPR16:$rs1, FPR16:$rs2, FPR16:$rs3),
@@ -301,6 +297,9 @@ def : Pat<(fma (fneg FPR16:$rs1), FPR16:$rs2, FPR16:$rs3),
def : Pat<(fma (fneg FPR16:$rs1), FPR16:$rs2, (fneg FPR16:$rs3)),
(FNMADD_H FPR16:$rs1, FPR16:$rs2, FPR16:$rs3, 0b111)>;
+// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
+// LLVM's fminnum and fmaxnum
+// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
def : PatFpr16Fpr16<fminnum, FMIN_H>;
def : PatFpr16Fpr16<fmaxnum, FMAX_H>;
@@ -317,11 +316,11 @@ def Select_FPR16_Using_CC_GPR : SelectCC_rrirr<FPR16, GPR>;
/// Loads
-defm : LdPat<load, FLH>;
+defm : LdPat<load, FLH, f16>;
/// Stores
-defm : StPat<store, FSH, FPR16>;
+defm : StPat<store, FSH, FPR16, f16>;
/// Float conversion operations
@@ -335,32 +334,45 @@ def : Pat<(riscv_fmv_x_anyexth FPR16:$src), (FMV_X_H FPR16:$src)>;
} // Predicates = [HasStdExtZfh]
let Predicates = [HasStdExtZfh, IsRV32] in {
-// float->[u]int. Round-to-zero must be used.
-def : Pat<(fp_to_sint FPR16:$rs1), (FCVT_W_H $rs1, 0b001)>;
-def : Pat<(fp_to_uint FPR16:$rs1), (FCVT_WU_H $rs1, 0b001)>;
+// half->[u]int. Round-to-zero must be used.
+def : Pat<(i32 (fp_to_sint FPR16:$rs1)), (FCVT_W_H $rs1, 0b001)>;
+def : Pat<(i32 (fp_to_uint FPR16:$rs1)), (FCVT_WU_H $rs1, 0b001)>;
-// [u]int->float. Match GCC and default to using dynamic rounding mode.
-def : Pat<(sint_to_fp GPR:$rs1), (FCVT_H_W $rs1, 0b111)>;
-def : Pat<(uint_to_fp GPR:$rs1), (FCVT_H_WU $rs1, 0b111)>;
+// half->int32 with current rounding mode.
+def : Pat<(i32 (lrint FPR16:$rs1)), (FCVT_W_H $rs1, 0b111)>;
+
+// half->int32 rounded to nearest with ties rounded away from zero.
+def : Pat<(i32 (lround FPR16:$rs1)), (FCVT_W_H $rs1, 0b100)>;
+
+// [u]int->half. Match GCC and default to using dynamic rounding mode.
+def : Pat<(sint_to_fp (i32 GPR:$rs1)), (FCVT_H_W $rs1, 0b111)>;
+def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_H_WU $rs1, 0b111)>;
} // Predicates = [HasStdExtZfh, IsRV32]
let Predicates = [HasStdExtZfh, IsRV64] in {
-// FP->[u]int32 is mostly handled by the FP->[u]int64 patterns. This is safe
-// because fpto[u|s]i produces poison if the value can't fit into the target.
-// We match the single case below because fcvt.wu.s sign-extends its result so
-// is cheaper than fcvt.lu.h+sext.w.
-def : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR16:$rs1)), i32),
- (FCVT_WU_H $rs1, 0b001)>;
+// Use target specific isd nodes to help us remember the result is sign
+// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
+// duplicated if it has another user that didn't need the sign_extend.
+def : Pat<(riscv_fcvt_w_rv64 FPR16:$rs1), (FCVT_W_H $rs1, 0b001)>;
+def : Pat<(riscv_fcvt_wu_rv64 FPR16:$rs1), (FCVT_WU_H $rs1, 0b001)>;
+
+// half->[u]int64. Round-to-zero must be used.
+def : Pat<(i64 (fp_to_sint FPR16:$rs1)), (FCVT_L_H $rs1, 0b001)>;
+def : Pat<(i64 (fp_to_uint FPR16:$rs1)), (FCVT_LU_H $rs1, 0b001)>;
-// FP->[u]int64
-def : Pat<(fp_to_sint FPR16:$rs1), (FCVT_L_H $rs1, 0b001)>;
-def : Pat<(fp_to_uint FPR16:$rs1), (FCVT_LU_H $rs1, 0b001)>;
+// half->int64 with current rounding mode.
+def : Pat<(i64 (lrint FPR16:$rs1)), (FCVT_L_H $rs1, 0b111)>;
+def : Pat<(i64 (llrint FPR16:$rs1)), (FCVT_L_H $rs1, 0b111)>;
+
+// half->int64 rounded to nearest with ties rounded away from zero.
+def : Pat<(i64 (lround FPR16:$rs1)), (FCVT_L_H $rs1, 0b100)>;
+def : Pat<(i64 (llround FPR16:$rs1)), (FCVT_L_H $rs1, 0b100)>;
// [u]int->fp. Match GCC and default to using dynamic rounding mode.
-def : Pat<(sint_to_fp (sexti32 GPR:$rs1)), (FCVT_H_W $rs1, 0b111)>;
-def : Pat<(uint_to_fp (zexti32 GPR:$rs1)), (FCVT_H_WU $rs1, 0b111)>;
-def : Pat<(sint_to_fp GPR:$rs1), (FCVT_H_L $rs1, 0b111)>;
-def : Pat<(uint_to_fp GPR:$rs1), (FCVT_H_LU $rs1, 0b111)>;
+def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_H_W $rs1, 0b111)>;
+def : Pat<(uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_H_WU $rs1, 0b111)>;
+def : Pat<(sint_to_fp (i64 GPR:$rs1)), (FCVT_H_L $rs1, 0b111)>;
+def : Pat<(uint_to_fp (i64 GPR:$rs1)), (FCVT_H_LU $rs1, 0b111)>;
} // Predicates = [HasStdExtZfh, IsRV64]
let Predicates = [HasStdExtZfh, HasStdExtD] in {
@@ -368,4 +380,9 @@ let Predicates = [HasStdExtZfh, HasStdExtD] in {
// f64 -> f16, f16 -> f64
def : Pat<(fpround FPR64:$rs1), (FCVT_H_D FPR64:$rs1, 0b111)>;
def : Pat<(fpextend FPR16:$rs1), (FCVT_D_H FPR16:$rs1)>;
+
+/// Float arithmetic operations
+def : Pat<(fcopysign FPR16:$rs1, FPR64:$rs2),
+ (FSGNJ_H $rs1, (FCVT_H_D $rs2, 0b111))>;
+def : Pat<(fcopysign FPR64:$rs1, FPR16:$rs2), (FSGNJ_D $rs1, (FCVT_D_H $rs2))>;
}