achieveartificialintelligence created this revision. achieveartificialintelligence added reviewers: craig.topper, jrtc27, kito-cheng, asb, luismarques. Herald added subscribers: vkmr, frasercrmck, evandro, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, shiva0217, niosHD, sabuasal, simoncook, johnrusso, rbar, hiraditya. achieveartificialintelligence requested review of this revision. Herald added subscribers: llvm-commits, cfe-commits, MaskRay. Herald added projects: clang, LLVM.
According to RISC-V Unprivileged ISA 15.6. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D111866 Files: clang/lib/Basic/Targets/RISCV.cpp clang/lib/Basic/Targets/RISCV.h clang/lib/Driver/ToolChains/Arch/RISCV.cpp clang/test/Driver/riscv-arch.c llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp llvm/lib/Target/RISCV/RISCV.td llvm/lib/Target/RISCV/RISCVISelLowering.cpp llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td llvm/lib/Target/RISCV/RISCVSubtarget.h llvm/test/MC/RISCV/attribute-arch.s
Index: llvm/test/MC/RISCV/attribute-arch.s =================================================================== --- llvm/test/MC/RISCV/attribute-arch.s +++ llvm/test/MC/RISCV/attribute-arch.s @@ -69,8 +69,11 @@ .attribute arch, "rv32izbt" # CHECK: attribute 5, "rv32i2p0_zbt0p93" +.attribute arch, "rv32ifzfhmin" +# CHECK: attribute 5, "rv32i2p0_f2p0_zfhmin0p1" + .attribute arch, "rv32ifzfh" -# CHECK: attribute 5, "rv32i2p0_f2p0_zfh0p1" +# CHECK: attribute 5, "rv32i2p0_f2p0_zfh0p1_zfhmin0p1" .attribute arch, "rv32ivzvamo_zvlsseg" # CHECK: attribute 5, "rv32i2p0_v0p10_zvamo0p10_zvlsseg0p10" Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -53,6 +53,7 @@ bool HasStdExtZvlsseg = false; bool HasStdExtZvamo = false; bool HasStdExtZfh = false; + bool HasStdExtZfhmin = false; bool HasRV64 = false; bool IsRV32E = false; bool EnableLinkerRelax = false; @@ -119,6 +120,7 @@ bool hasStdExtZvlsseg() const { return HasStdExtZvlsseg; } bool hasStdExtZvamo() const { return HasStdExtZvamo; } bool hasStdExtZfh() const { return HasStdExtZfh; } + bool hasStdExtZfhmin() const { return HasStdExtZfhmin; } bool is64Bit() const { return HasRV64; } bool isRV32E() const { return IsRV32E; } bool enableLinkerRelax() const { return EnableLinkerRelax; } Index: llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td +++ llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td @@ -66,7 +66,7 @@ // Instructions //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtZfh] in { +let Predicates = [HasStdExtZfhmin] in { let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def FLH : RVInstI<0b001, OPC_LOAD_FP, (outs FPR16:$rd), (ins GPR:$rs1, simm12:$imm12), @@ -81,7 +81,9 @@ (ins FPR16:$rs2, GPR:$rs1, simm12:$imm12), "fsh", "$rs2, ${imm12}(${rs1})">, Sched<[WriteFST16, ReadStoreData, ReadFMemBase]>; +} // Predicates = [HasStdExtZfhmin] +let Predicates = [HasStdExtZfh] in { def FMADD_H : FPFMAH_rrr_frm<OPC_MADD, "fmadd.h">, Sched<[WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16]>; def : FPFMAHDynFrmAlias<FMADD_H, "fmadd.h">; @@ -148,7 +150,9 @@ let rs2 = 0b00001; } def : FPUnaryOpDynFrmAlias<FCVT_H_WU, "fcvt.h.wu", FPR16, GPR>; +} // Predicates = [HasStdExtZfh] +let Predicates = [HasStdExtZfhmin] in { def FCVT_H_S : FPUnaryOp_r_frm<0b0100010, FPR16, FPR32, "fcvt.h.s">, Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]> { let rs2 = 0b00000; @@ -169,7 +173,9 @@ Sched<[WriteFMovI16ToF16, ReadFMovI16ToF16]> { let rs2 = 0b00000; } +} // Predicates = [HasStdExtZfhmin] +let Predicates = [HasStdExtZfh] in { def FEQ_H : FPCmpH_rr<0b010, "feq.h">; def FLT_H : FPCmpH_rr<0b001, "flt.h">; def FLE_H : FPCmpH_rr<0b000, "fle.h">; @@ -178,7 +184,7 @@ 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">, @@ -206,7 +212,7 @@ def : FPUnaryOpDynFrmAlias<FCVT_H_LU, "fcvt.h.lu", FPR16, GPR>; } // Predicates = [HasStdExtZfh, IsRV64] -let Predicates = [HasStdExtZfh, HasStdExtD] in { +let Predicates = [HasStdExtZfhmin, HasStdExtD] in { def FCVT_H_D : FPUnaryOp_r_frm<0b0100010, FPR16, FPR64, "fcvt.h.d">, Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]> { let rs2 = 0b00001; @@ -223,10 +229,12 @@ // Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) //===----------------------------------------------------------------------===// -let Predicates = [HasStdExtZfh] in { +let Predicates = [HasStdExtZfhmin] in { def : InstAlias<"flh $rd, (${rs1})", (FLH FPR16:$rd, GPR:$rs1, 0), 0>; def : InstAlias<"fsh $rs2, (${rs1})", (FSH FPR16:$rs2, GPR:$rs1, 0), 0>; +} // Predicates = [HasStdExtZfhmin] +let Predicates = [HasStdExtZfh] in { def : InstAlias<"fmv.h $rd, $rs", (FSGNJ_H FPR16:$rd, FPR16:$rs, FPR16:$rs)>; def : InstAlias<"fabs.h $rd, $rs", (FSGNJX_H FPR16:$rd, FPR16:$rs, FPR16:$rs)>; def : InstAlias<"fneg.h $rd, $rs", (FSGNJN_H FPR16:$rd, FPR16:$rs, FPR16:$rs)>; @@ -237,7 +245,9 @@ (FLT_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>; def : InstAlias<"fge.h $rd, $rs, $rt", (FLE_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>; +} // Predicates = [HasStdExtZfh] +let Predicates = [HasStdExtZfhmin] in { def PseudoFLH : PseudoFloatLoad<"flh", FPR16>; def PseudoFSH : PseudoStore<"fsh", FPR16>; } // Predicates = [HasStdExtZfh] @@ -313,7 +323,9 @@ def : PatFpr16Fpr16<setole, FLE_H>; def Select_FPR16_Using_CC_GPR : SelectCC_rrirr<FPR16, GPR>; +} // Predicates = [HasStdExtZfh] +let Predicates = [HasStdExtZfhmin] in { /// Loads defm : LdPat<load, FLH, f16>; @@ -331,7 +343,7 @@ // Moves (no conversion) def : Pat<(riscv_fmv_h_x GPR:$src), (FMV_H_X GPR:$src)>; def : Pat<(riscv_fmv_x_anyexth FPR16:$src), (FMV_X_H FPR16:$src)>; -} // Predicates = [HasStdExtZfh] +} // Predicates = [HasStdExtZfhmin] let Predicates = [HasStdExtZfh, IsRV32] in { // half->[u]int. Round-to-zero must be used. @@ -383,7 +395,7 @@ def : Pat<(uint_to_fp (i64 GPR:$rs1)), (FCVT_H_LU $rs1, 0b111)>; } // Predicates = [HasStdExtZfh, IsRV64] -let Predicates = [HasStdExtZfh, HasStdExtD] in { +let Predicates = [HasStdExtZfhmin, HasStdExtD] in { /// Float conversion operations // f64 -> f16, f16 -> f64 def : Pat<(fpround FPR64:$rs1), (FCVT_H_D FPR64:$rs1, 0b111)>; Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -85,7 +85,7 @@ // Set up the register classes. addRegisterClass(XLenVT, &RISCV::GPRRegClass); - if (Subtarget.hasStdExtZfh()) + if (Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh()) addRegisterClass(MVT::f16, &RISCV::FPR16RegClass); if (Subtarget.hasStdExtF()) addRegisterClass(MVT::f32, &RISCV::FPR32RegClass); @@ -131,7 +131,7 @@ for (MVT VT : IntVecVTs) addRegClassForRVV(VT); - if (Subtarget.hasStdExtZfh()) + if (Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh()) for (MVT VT : F16VecVTs) addRegClassForRVV(VT); @@ -316,7 +316,7 @@ ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FP16_TO_FP, ISD::FP_TO_FP16}; - if (Subtarget.hasStdExtZfh()) + if (Subtarget.hasStdExtZfhmin()||Subtarget.hasStdExtZfh()) setOperationAction(ISD::BITCAST, MVT::i16, Custom); if (Subtarget.hasStdExtZfh()) { @@ -1150,7 +1150,8 @@ bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const { - if (VT == MVT::f16 && !Subtarget.hasStdExtZfh()) + if (VT == MVT::f16 && !Subtarget.hasStdExtZfhmin() && + !Subtarget.hasStdExtZfh()) return false; if (VT == MVT::f32 && !Subtarget.hasStdExtF()) return false; @@ -1162,7 +1163,8 @@ } bool RISCVTargetLowering::hasBitPreservingFPLogic(EVT VT) const { - return (VT == MVT::f16 && Subtarget.hasStdExtZfh()) || + return (VT == MVT::f16 && + (Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh())) || (VT == MVT::f32 && Subtarget.hasStdExtF()) || (VT == MVT::f64 && Subtarget.hasStdExtD()); } @@ -1170,9 +1172,10 @@ MVT RISCVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const { - // Use f32 to pass f16 if it is legal and Zfh is not enabled. We might still - // end up using a GPR but that will be decided based on ABI. - if (VT == MVT::f16 && Subtarget.hasStdExtF() && !Subtarget.hasStdExtZfh()) + // Use f32 to pass f16 if it is legal and Zfhmin/Zfh is not enabled. + // We might still end up using a GPR but that will be decided based on ABI. + if (VT == MVT::f16 && Subtarget.hasStdExtF() && + !Subtarget.hasStdExtZfhmin() && !Subtarget.hasStdExtZfh()) return MVT::f32; return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT); @@ -1181,9 +1184,10 @@ unsigned RISCVTargetLowering::getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const { - // Use f32 to pass f16 if it is legal and Zfh is not enabled. We might still - // end up using a GPR but that will be decided based on ABI. - if (VT == MVT::f16 && Subtarget.hasStdExtF() && !Subtarget.hasStdExtZfh()) + // Use f32 to pass f16 if it is legal and Zfhmin/Zfh is not enabled. + // We might still end up using a GPR but that will be decided based on ABI. + if (VT == MVT::f16 && Subtarget.hasStdExtF() && + !Subtarget.hasStdExtZfhmin() && !Subtarget.hasStdExtZfh()) return 1; return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT); @@ -1347,7 +1351,7 @@ return true; if (ScalarTy->isHalfTy()) - return Subtarget.hasStdExtZfh(); + return Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh(); if (ScalarTy->isFloatTy()) return Subtarget.hasStdExtF(); if (ScalarTy->isDoubleTy()) @@ -1390,7 +1394,7 @@ case MVT::i64: break; case MVT::f16: - if (!Subtarget.hasStdExtZfh()) + if (!Subtarget.hasStdExtZfh() && !Subtarget.hasStdExtZfh()) return false; break; case MVT::f32: @@ -2400,7 +2404,8 @@ return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, BVec, DAG.getConstant(0, DL, XLenVT)); } - if (VT == MVT::f16 && Op0VT == MVT::i16 && Subtarget.hasStdExtZfh()) { + if (VT == MVT::f16 && Op0VT == MVT::i16 && + (Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZfh())) { SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, Op0); SDValue FPConv = DAG.getNode(RISCVISD::FMV_H_X, DL, MVT::f16, NewOp0); return FPConv; @@ -5668,7 +5673,8 @@ SDValue Op0 = N->getOperand(0); EVT Op0VT = Op0.getValueType(); MVT XLenVT = Subtarget.getXLenVT(); - if (VT == MVT::i16 && Op0VT == MVT::f16 && Subtarget.hasStdExtZfh()) { + if (VT == MVT::i16 && Op0VT == MVT::f16 && + (Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh())) { SDValue FPConv = DAG.getNode(RISCVISD::FMV_X_ANYEXTH, DL, XLenVT, Op0); Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, FPConv)); } else if (VT == MVT::i32 && Op0VT == MVT::f32 && Subtarget.is64Bit() && @@ -9286,7 +9292,8 @@ case 'r': return std::make_pair(0U, &RISCV::GPRRegClass); case 'f': - if (Subtarget.hasStdExtZfh() && VT == MVT::f16) + if ((Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh()) && + VT == MVT::f16) return std::make_pair(0U, &RISCV::FPR16RegClass); if (Subtarget.hasStdExtF() && VT == MVT::f32) return std::make_pair(0U, &RISCV::FPR32RegClass); @@ -9688,7 +9695,7 @@ switch (VT.getSimpleVT().SimpleTy) { case MVT::f16: - return Subtarget.hasStdExtZfh(); + return Subtarget.hasStdExtZfhmin() || Subtarget.hasStdExtZfh(); case MVT::f32: return Subtarget.hasStdExtF(); case MVT::f64: Index: llvm/lib/Target/RISCV/RISCV.td =================================================================== --- llvm/lib/Target/RISCV/RISCV.td +++ llvm/lib/Target/RISCV/RISCV.td @@ -41,10 +41,18 @@ AssemblerPredicate<(all_of FeatureStdExtD), "'D' (Double-Precision Floating-Point)">; +def FeatureStdExtZfhmin + : SubtargetFeature<"experimental-zfhmin", "HasStdExtZfhmin", "true", + "'Zfhmin' (Half-Precision Floating-Point Minimal)", + [FeatureStdExtF]>; +def HasStdExtZfhmin : Predicate<"Subtarget->hasStdExtZfhmin()">, + AssemblerPredicate<(all_of FeatureStdExtZfhmin), + "'Zfhmin' (Half-Precision Floating-Point Minimal)">; + def FeatureStdExtZfh : SubtargetFeature<"experimental-zfh", "HasStdExtZfh", "true", "'Zfh' (Half-Precision Floating-Point)", - [FeatureStdExtF]>; + [FeatureStdExtZfhmin, FeatureStdExtF]>; def HasStdExtZfh : Predicate<"Subtarget->hasStdExtZfh()">, AssemblerPredicate<(all_of FeatureStdExtZfh), "'Zfh' (Half-Precision Floating-Point)">; Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -2070,6 +2070,7 @@ clearFeatureBits(RISCV::FeatureStdExtC, "c"); clearFeatureBits(RISCV::FeatureStdExtV, "experimental-v"); clearFeatureBits(RISCV::FeatureStdExtZfh, "experimental-zfh"); + clearFeatureBits(RISCV::FeatureStdExtZfhmin, "experimental-zfhmin"); clearFeatureBits(RISCV::FeatureStdExtZba, "experimental-zba"); clearFeatureBits(RISCV::FeatureStdExtZbb, "experimental-zbb"); clearFeatureBits(RISCV::FeatureStdExtZbc, "experimental-zbc"); @@ -2133,6 +2134,8 @@ setFeatureBits(RISCV::FeatureStdExtZbt, "experimental-zbt"); else if (Ext == "zfh") setFeatureBits(RISCV::FeatureStdExtZfh, "experimental-zfh"); + else if (Ext == "zfhmin") + setFeatureBits(RISCV::FeatureStdExtZfhmin, "experimental-zfhmin"); else if (Ext == "zvamo") setFeatureBits(RISCV::FeatureStdExtZvamo, "experimental-zvamo"); else if (Ext == "zvlsseg") @@ -2183,6 +2186,8 @@ formalArchStr = (Twine(formalArchStr) + "_v0p10").str(); if (getFeatureBits(RISCV::FeatureStdExtZfh)) formalArchStr = (Twine(formalArchStr) + "_zfh0p1").str(); + if (getFeatureBits(RISCV::FeatureStdExtZfhmin)) + formalArchStr = (Twine(formalArchStr) + "_zfhmin0p1").str(); if (getFeatureBits(RISCV::FeatureStdExtZba)) formalArchStr = (Twine(formalArchStr) + "_zba1p0").str(); if (getFeatureBits(RISCV::FeatureStdExtZbb)) Index: clang/test/Driver/riscv-arch.c =================================================================== --- clang/test/Driver/riscv-arch.c +++ clang/test/Driver/riscv-arch.c @@ -432,6 +432,15 @@ // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFH %s // RV32-EXPERIMENTAL-ZFH: "-target-feature" "+experimental-zfh" +// RUN: %clang -target riscv32-unknown-elf -march=rv32izfhmin -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFHMIN-NOFLAG %s +// RV32-EXPERIMENTAL-ZFHMIN-NOFLAG: error: invalid arch name 'rv32izfhmin' +// RV32-EXPERIMENTAL-ZFHMIN-NOFLAG: requires '-menable-experimental-extensions' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32izfhmin0p1 -menable-experimental-extensions -### %s \ +// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-ZFHMIN %s +// RV32-EXPERIMENTAL-ZFHMIN: "-target-feature" "+experimental-zfhmin" + // RUN: %clang -target riscv32-unknown-elf -march=rv32izvamo -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVAMO-NOFLAG %s // RV32-EXPERIMENTAL-ZVAMO-NOFLAG: error: invalid arch name 'rv32izvamo' Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp =================================================================== --- clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -65,7 +65,7 @@ return RISCVExtensionVersion{"0", "93"}; if (Ext == "v" || Ext == "zvamo" || Ext == "zvlsseg") return RISCVExtensionVersion{"0", "10"}; - if (Ext == "zfh") + if (Ext == "zfh" || Ext == "zfhmin") return RISCVExtensionVersion{"0", "1"}; return None; } Index: clang/lib/Basic/Targets/RISCV.h =================================================================== --- clang/lib/Basic/Targets/RISCV.h +++ clang/lib/Basic/Targets/RISCV.h @@ -42,6 +42,7 @@ bool HasZbs = false; bool HasZbt = false; bool HasZfh = false; + bool HasZfhmin = false; bool HasZvamo = false; bool HasZvlsseg = false; Index: clang/lib/Basic/Targets/RISCV.cpp =================================================================== --- clang/lib/Basic/Targets/RISCV.cpp +++ clang/lib/Basic/Targets/RISCV.cpp @@ -211,7 +211,7 @@ if (HasZbt) Builder.defineMacro("__riscv_zbt", "93000"); - if (HasZfh) + if (HasZfh || HasZfhmin) Builder.defineMacro("__riscv_zfh", "1000"); if (HasZvamo) @@ -269,6 +269,7 @@ .Case("experimental-zbs", HasZbs) .Case("experimental-zbt", HasZbt) .Case("experimental-zfh", HasZfh) + .Case("experimental-zfhmin", HasZfhmin) .Case("experimental-zvamo", HasZvamo) .Case("experimental-zvlsseg", HasZvlsseg) .Default(false); @@ -312,6 +313,8 @@ HasZbt = true; else if (Feature == "+experimental-zfh") HasZfh = true; + else if (Feature == "+experimental-zfhmin") + HasZfhmin = true; else if (Feature == "+experimental-zvamo") HasZvamo = true; else if (Feature == "+experimental-zvlsseg")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits