aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td53
-rw-r--r--llvm/lib/Target/AArch64/SVEInstrFormats.td25
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp35
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp32
-rw-r--r--llvm/lib/Target/RISCV/RISCV.td37
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.cpp8
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.h2
-rw-r--r--llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp36
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoD.td209
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoF.td275
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td207
-rw-r--r--llvm/lib/Target/RISCV/RISCVRegisterInfo.td30
-rw-r--r--llvm/lib/Target/RISCV/RISCVSubtarget.h8
-rw-r--r--llvm/lib/Target/X86/X86.td2
-rw-r--r--llvm/lib/Target/X86/X86FrameLowering.cpp5
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp46
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.h3
17 files changed, 711 insertions, 302 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 1d162610de9c..2397a6d320a2 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -1679,60 +1679,61 @@ let Predicates = [HasSVEorStreamingSVE] in {
defm FCVTZS_ZPmZ_DtoD : sve_fp_2op_p_zd< 0b1111110, "fcvtzs", ZPR64, ZPR64, null_frag, AArch64fcvtzs_mt, nxv2i64, nxv2i1, nxv2f64, ElementSizeD>;
defm FCVTZU_ZPmZ_DtoD : sve_fp_2op_p_zd< 0b1111111, "fcvtzu", ZPR64, ZPR64, null_frag, AArch64fcvtzu_mt, nxv2i64, nxv2i1, nxv2f64, ElementSizeD>;
- def : Pat<(nxv2f32 (AArch64fcvte_mt (nxv2i1 PPR:$Pg), (nxv2f16 ZPR:$Zs), (nxv2f32 ZPR:$Zd))),
- (FCVT_ZPmZ_HtoS ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ //These patterns exist to improve the code quality of conversions on unpacked types.
+ def : Pat<(nxv2f32 (AArch64fcvte_mt (nxv2i1 (SVEAllActive):$Pg), (nxv2f16 ZPR:$Zs), (nxv2f32 ZPR:$Zd))),
+ (FCVT_ZPmZ_HtoS_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
// FP_ROUND has an additional 'precise' flag which indicates the type of rounding.
// This is ignored by the pattern below where it is matched by (i64 timm0_1)
- def : Pat<(nxv2f16 (AArch64fcvtr_mt (nxv2i1 PPR:$Pg), (nxv2f32 ZPR:$Zs), (i64 timm0_1), (nxv2f16 ZPR:$Zd))),
- (FCVT_ZPmZ_StoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ def : Pat<(nxv2f16 (AArch64fcvtr_mt (nxv2i1 (SVEAllActive):$Pg), (nxv2f32 ZPR:$Zs), (i64 timm0_1), (nxv2f16 ZPR:$Zd))),
+ (FCVT_ZPmZ_StoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- // Floating-point -> signed integer
- def : Pat<(nxv2f16 (AArch64scvtf_mt (nxv2i1 PPR:$Pg),
+ // Signed integer -> Floating-point
+ def : Pat<(nxv2f16 (AArch64scvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(sext_inreg (nxv2i64 ZPR:$Zs), nxv2i16), (nxv2f16 ZPR:$Zd))),
- (SCVTF_ZPmZ_HtoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (SCVTF_ZPmZ_HtoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv4f16 (AArch64scvtf_mt (nxv4i1 PPR:$Pg),
+ def : Pat<(nxv4f16 (AArch64scvtf_mt (nxv4i1 (SVEAllActive):$Pg),
(sext_inreg (nxv4i32 ZPR:$Zs), nxv4i16), (nxv4f16 ZPR:$Zd))),
- (SCVTF_ZPmZ_HtoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (SCVTF_ZPmZ_HtoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv2f16 (AArch64scvtf_mt (nxv2i1 PPR:$Pg),
+ def : Pat<(nxv2f16 (AArch64scvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(sext_inreg (nxv2i64 ZPR:$Zs), nxv2i32), (nxv2f16 ZPR:$Zd))),
- (SCVTF_ZPmZ_StoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (SCVTF_ZPmZ_StoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv2f32 (AArch64scvtf_mt (nxv2i1 PPR:$Pg),
+ def : Pat<(nxv2f32 (AArch64scvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(sext_inreg (nxv2i64 ZPR:$Zs), nxv2i32), (nxv2f32 ZPR:$Zd))),
- (SCVTF_ZPmZ_StoS ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (SCVTF_ZPmZ_StoS_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv2f64 (AArch64scvtf_mt (nxv2i1 PPR:$Pg),
+ def : Pat<(nxv2f64 (AArch64scvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(sext_inreg (nxv2i64 ZPR:$Zs), nxv2i32), (nxv2f64 ZPR:$Zd))),
- (SCVTF_ZPmZ_StoD ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (SCVTF_ZPmZ_StoD_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- // Floating-point -> unsigned integer
- def : Pat<(nxv2f16 (AArch64ucvtf_mt (nxv2i1 PPR:$Pg),
+ // Unsigned integer -> Floating-point
+ def : Pat<(nxv2f16 (AArch64ucvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(and (nxv2i64 ZPR:$Zs),
(nxv2i64 (AArch64dup (i64 0xFFFF)))), (nxv2f16 ZPR:$Zd))),
- (UCVTF_ZPmZ_HtoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (UCVTF_ZPmZ_HtoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv2f16 (AArch64ucvtf_mt (nxv2i1 PPR:$Pg),
+ def : Pat<(nxv2f16 (AArch64ucvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(and (nxv2i64 ZPR:$Zs),
(nxv2i64 (AArch64dup (i64 0xFFFFFFFF)))), (nxv2f16 ZPR:$Zd))),
- (UCVTF_ZPmZ_StoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (UCVTF_ZPmZ_StoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv4f16 (AArch64ucvtf_mt (nxv4i1 PPR:$Pg),
+ def : Pat<(nxv4f16 (AArch64ucvtf_mt (nxv4i1 (SVEAllActive):$Pg),
(and (nxv4i32 ZPR:$Zs),
(nxv4i32 (AArch64dup (i32 0xFFFF)))), (nxv4f16 ZPR:$Zd))),
- (UCVTF_ZPmZ_HtoH ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (UCVTF_ZPmZ_HtoH_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv2f32 (AArch64ucvtf_mt (nxv2i1 PPR:$Pg),
+ def : Pat<(nxv2f32 (AArch64ucvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(and (nxv2i64 ZPR:$Zs),
(nxv2i64 (AArch64dup (i64 0xFFFFFFFF)))), (nxv2f32 ZPR:$Zd))),
- (UCVTF_ZPmZ_StoS ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (UCVTF_ZPmZ_StoS_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
- def : Pat<(nxv2f64 (AArch64ucvtf_mt (nxv2i1 PPR:$Pg),
+ def : Pat<(nxv2f64 (AArch64ucvtf_mt (nxv2i1 (SVEAllActive):$Pg),
(and (nxv2i64 ZPR:$Zs),
(nxv2i64 (AArch64dup (i64 0xFFFFFFFF)))), (nxv2f64 ZPR:$Zd))),
- (UCVTF_ZPmZ_StoD ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
+ (UCVTF_ZPmZ_StoD_UNDEF ZPR:$Zd, PPR:$Pg, ZPR:$Zs)>;
defm FRINTN_ZPmZ : sve_fp_2op_p_zd_HSD<0b00000, "frintn", AArch64frintn_mt>;
defm FRINTP_ZPmZ : sve_fp_2op_p_zd_HSD<0b00001, "frintp", AArch64frintp_mt>;
diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td
index 9d4bdbe5d053..37b2ac4d8759 100644
--- a/llvm/lib/Target/AArch64/SVEInstrFormats.td
+++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td
@@ -370,6 +370,14 @@ class SVE_1_Op_Passthru_Round_Pat<ValueType vtd, SDPatternOperator op, ValueType
: Pat<(vtd (op pg:$Op1, vts:$Op2, (i64 timm0_1), vtd:$Op3)),
(inst $Op3, $Op1, $Op2)>;
+multiclass SVE_1_Op_PassthruUndef_Round_Pat<ValueType vtd, SDPatternOperator op, ValueType pg,
+ ValueType vts, Instruction inst>{
+ def : Pat<(vtd (op pg:$Op1, vts:$Op2, (i64 timm0_1), (vtd undef))),
+ (inst (IMPLICIT_DEF), $Op1, $Op2)>;
+ def : Pat<(vtd (op (pg (SVEAllActive:$Op1)), vts:$Op2, (i64 timm0_1), vtd:$Op3)),
+ (inst $Op3, $Op1, $Op2)>;
+}
+
class SVE_1_Op_Imm_OptLsl_Reverse_Pat<ValueType vt, SDPatternOperator op, ZPRRegOp zprty,
ValueType it, ComplexPattern cpx, Instruction inst>
: Pat<(vt (op (vt (AArch64dup (it (cpx i32:$imm, i32:$shift)))), (vt zprty:$Op1))),
@@ -2589,8 +2597,8 @@ multiclass sve_fp_2op_p_zd<bits<7> opc, string asm,
SDPatternOperator int_op,
SDPatternOperator ir_op, ValueType vt1,
ValueType vt2, ValueType vt3, ElementSizeEnum Sz> {
- def NAME : sve_fp_2op_p_zd<opc, asm, i_zprtype, o_zprtype, Sz>;
-
+ def NAME : sve_fp_2op_p_zd<opc, asm, i_zprtype, o_zprtype, Sz>,
+ SVEPseudo2Instr<NAME, 1>;
// convert vt1 to a packed type for the intrinsic patterns
defvar packedvt1 = !cond(!eq(!cast<string>(vt1), "nxv2f16"): nxv8f16,
!eq(!cast<string>(vt1), "nxv4f16"): nxv8f16,
@@ -2604,8 +2612,11 @@ multiclass sve_fp_2op_p_zd<bits<7> opc, string asm,
1 : vt3);
def : SVE_3_Op_Pat<packedvt1, int_op, packedvt1, vt2, packedvt3, !cast<Instruction>(NAME)>;
-
def : SVE_1_Op_Passthru_Pat<vt1, ir_op, vt2, vt3, !cast<Instruction>(NAME)>;
+
+ def _UNDEF : PredOneOpPassthruPseudo<NAME, !cast<ZPRRegOp>(i_zprtype)>;
+
+ defm : SVE_1_Op_PassthruUndef_Pat<vt1, ir_op, vt2, vt3, !cast<Instruction>(NAME # _UNDEF)>;
}
multiclass sve_fp_2op_p_zdr<bits<7> opc, string asm,
@@ -2614,7 +2625,8 @@ multiclass sve_fp_2op_p_zdr<bits<7> opc, string asm,
SDPatternOperator int_op,
SDPatternOperator ir_op, ValueType vt1,
ValueType vt2, ValueType vt3, ElementSizeEnum Sz> {
- def NAME : sve_fp_2op_p_zd<opc, asm, i_zprtype, o_zprtype, Sz>;
+ def NAME : sve_fp_2op_p_zd<opc, asm, i_zprtype, o_zprtype, Sz>,
+ SVEPseudo2Instr<NAME, 1>;
// convert vt1 to a packed type for the intrinsic patterns
defvar packedvt1 = !cond(!eq(!cast<string>(vt1), "nxv2f16"): nxv8f16,
@@ -2623,8 +2635,11 @@ multiclass sve_fp_2op_p_zdr<bits<7> opc, string asm,
1 : vt1);
def : SVE_3_Op_Pat<packedvt1, int_op, packedvt1, vt2, vt3, !cast<Instruction>(NAME)>;
-
def : SVE_1_Op_Passthru_Round_Pat<vt1, ir_op, vt2, vt3, !cast<Instruction>(NAME)>;
+
+ def _UNDEF : PredOneOpPassthruPseudo<NAME, !cast<ZPRRegOp>(i_zprtype)>;
+
+ defm : SVE_1_Op_PassthruUndef_Round_Pat<vt1, ir_op, vt2, vt3, !cast<Instruction>(NAME # _UNDEF)>;
}
multiclass sve_fp_2op_p_zd_HSD<bits<5> opc, string asm, SDPatternOperator op> {
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 01f36e6dcdd2..95319d1b0b74 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -170,6 +170,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseVTypeI(OperandVector &Operands);
OperandMatchResultTy parseMaskReg(OperandVector &Operands);
OperandMatchResultTy parseInsnDirectiveOpcode(OperandVector &Operands);
+ OperandMatchResultTy parseGPRAsFPR(OperandVector &Operands);
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
@@ -273,6 +274,8 @@ struct RISCVOperand : public MCParsedAsmOperand {
bool IsRV64;
+ bool IsGPRAsFPR;
+
struct RegOp {
MCRegister RegNum;
};
@@ -343,6 +346,14 @@ public:
RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
}
+ bool isGPRAsFPR() const { return isGPR() && IsGPRAsFPR; }
+
+ bool isGPRF64AsFPR() const { return isGPR() && IsGPRAsFPR && IsRV64; }
+
+ bool isGPRPF64AsFPR() const {
+ return isGPR() && IsGPRAsFPR && !IsRV64 && !((Reg.RegNum - RISCV::X0) & 1);
+ }
+
static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
RISCVMCExpr::VariantKind &VK) {
if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
@@ -831,12 +842,14 @@ public:
}
static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
- SMLoc E, bool IsRV64) {
+ SMLoc E, bool IsRV64,
+ bool IsGPRAsFPR = false) {
auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
Op->Reg.RegNum = RegNo;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsRV64 = IsRV64;
+ Op->IsGPRAsFPR = IsGPRAsFPR;
return Op;
}
@@ -1780,6 +1793,26 @@ OperandMatchResultTy RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
return MatchOperand_Success;
}
+OperandMatchResultTy RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::Identifier:
+ StringRef Name = getLexer().getTok().getIdentifier();
+ MCRegister RegNo;
+ matchRegisterNameHelper(isRV32E(), RegNo, Name);
+
+ if (RegNo == RISCV::NoRegister)
+ return MatchOperand_NoMatch;
+ SMLoc S = getLoc();
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+ getLexer().Lex();
+ Operands.push_back(RISCVOperand::createReg(
+ RegNo, S, E, isRV64(), !getSTI().hasFeature(RISCV::FeatureStdExtF)));
+ }
+ return MatchOperand_Success;
+}
+
OperandMatchResultTy
RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
if (getLexer().isNot(AsmToken::LParen)) {
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index ff96b2b254ca..18947997dc58 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -161,6 +161,17 @@ static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeGPRPF64RegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo >= 32 || RegNo & 1)
+ return MCDisassembler::Fail;
+
+ MCRegister Reg = RISCV::X0 + RegNo;
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeVRRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
@@ -427,6 +438,27 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
return MCDisassembler::Fail;
}
Insn = support::endian::read32le(Bytes.data());
+ if (STI.getFeatureBits()[RISCV::FeatureStdExtZdinx] &&
+ !STI.getFeatureBits()[RISCV::Feature64Bit]) {
+ LLVM_DEBUG(dbgs() << "Trying RV32Zdinx table (Double in Integer and"
+ "rv32)\n");
+ Result = decodeInstruction(DecoderTableRV32Zdinx32, MI, Insn, Address,
+ this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+ }
+
+ if (STI.getFeatureBits()[RISCV::FeatureStdExtZfinx]) {
+ LLVM_DEBUG(dbgs() << "Trying RVZfinx table (Float in Integer):\n");
+ Result = decodeInstruction(DecoderTableRVZfinx32, MI, Insn, Address, this,
+ STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+ }
LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
Size = 4;
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index e32a8fb010de..065e731ff6bc 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -63,6 +63,43 @@ def HasStdExtZfhOrZfhmin
"'Zfh' (Half-Precision Floating-Point) or "
"'Zfhmin' (Half-Precision Floating-Point Minimal)">;
+def FeatureStdExtZfinx
+ : SubtargetFeature<"zfinx", "HasStdExtZfinx", "true",
+ "'Zfinx' (Float in Integer)">;
+def HasStdExtZfinx : Predicate<"Subtarget->hasStdExtZfinx()">,
+ AssemblerPredicate<(all_of FeatureStdExtZfinx),
+ "'Zfinx' (Float in Integer)">;
+
+def FeatureStdExtZdinx
+ : SubtargetFeature<"zdinx", "HasStdExtZdinx", "true",
+ "'Zdinx' (Double in Integer)",
+ [FeatureStdExtZfinx]>;
+def HasStdExtZdinx : Predicate<"Subtarget->hasStdExtZdinx()">,
+ AssemblerPredicate<(all_of FeatureStdExtZdinx),
+ "'Zdinx' (Double in Integer)">;
+
+def FeatureStdExtZhinxmin
+ : SubtargetFeature<"zhinxmin", "HasStdExtZhinxmin", "true",
+ "'Zhinxmin' (Half Float in Integer Minimal)",
+ [FeatureStdExtZfinx]>;
+def HasStdExtZhinxmin : Predicate<"Subtarget->hasStdExtZhinxmin()">,
+ AssemblerPredicate<(all_of FeatureStdExtZhinxmin),
+ "'Zhinxmin' (Half Float in Integer Minimal)">;
+
+def FeatureStdExtZhinx
+ : SubtargetFeature<"zhinx", "HasStdExtZhinx", "true",
+ "'Zhinx' (Half Float in Integer)",
+ [FeatureStdExtZfinx]>;
+def HasStdExtZhinx : Predicate<"Subtarget->hasStdExtZhinx()">,
+ AssemblerPredicate<(all_of FeatureStdExtZhinx),
+ "'Zhinx' (Half Float in Integer)">;
+
+def HasStdExtZhinxOrZhinxmin
+ : Predicate<"Subtarget->hasStdExtZhinx() || Subtarget->hasStdExtZhinxmin()">,
+ AssemblerPredicate<(any_of FeatureStdExtZhinx, FeatureStdExtZhinxmin),
+ "'Zhinx' (Half Float in Integer) or "
+ "'Zhinxmin' (Half Float in Integer Minimal)">;
+
def FeatureStdExtC
: SubtargetFeature<"c", "HasStdExtC", "true",
"'C' (Compressed Instructions)">;
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index ad003404d793..f3cc7d3fb46f 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1116,14 +1116,6 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
return true;
}
-bool RISCVFrameLowering::enableShrinkWrapping(const MachineFunction &MF) const {
- // Keep the conventional code flow when not optimizing.
- if (MF.getFunction().hasOptNone())
- return false;
-
- return true;
-}
-
bool RISCVFrameLowering::canUseAsPrologue(const MachineBasicBlock &MBB) const {
MachineBasicBlock *TmpMBB = const_cast<MachineBasicBlock *>(&MBB);
const MachineFunction *MF = MBB.getParent();
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index 1e94e34acf2f..bc3ace786272 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -65,8 +65,6 @@ public:
bool canUseAsPrologue(const MachineBasicBlock &MBB) const override;
bool canUseAsEpilogue(const MachineBasicBlock &MBB) const override;
- bool enableShrinkWrapping(const MachineFunction &MF) const override;
-
bool isSupportedStackID(TargetStackID::Value ID) const override;
TargetStackID::Value getStackIDForScalableVectors() const override;
diff --git a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
index 649eb57b325b..6c4d2682bcd8 100644
--- a/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp
@@ -334,6 +334,10 @@ public:
return false;
}
+ bool operator!=(const VSETVLIInfo &Other) const {
+ return !(*this == Other);
+ }
+
// Calculate the VSETVLIInfo visible to a block assuming this and Other are
// both predecessors.
VSETVLIInfo intersect(const VSETVLIInfo &Other) const {
@@ -999,12 +1003,6 @@ bool RISCVInsertVSETVLI::needVSETVLIPHI(const VSETVLIInfo &Require,
void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
VSETVLIInfo CurInfo;
- // BBLocalInfo tracks the VL/VTYPE state the same way BBInfo.Change was
- // calculated in computeIncomingVLVTYPE. We need this to apply
- // canSkipVSETVLIForLoadStore the same way computeIncomingVLVTYPE did. We
- // can't include predecessor information in that decision to avoid disagreeing
- // with the global analysis.
- VSETVLIInfo BBLocalInfo;
// Only be set if current VSETVLIInfo is from an explicit VSET(I)VLI.
MachineInstr *PrevVSETVLIMI = nullptr;
@@ -1020,7 +1018,6 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
MI.getOperand(3).setIsDead(false);
MI.getOperand(4).setIsDead(false);
CurInfo = getInfoForVSETVLI(MI);
- BBLocalInfo = getInfoForVSETVLI(MI);
PrevVSETVLIMI = &MI;
continue;
}
@@ -1050,22 +1047,12 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
// use the predecessor information.
assert(BlockInfo[MBB.getNumber()].Pred.isValid() &&
"Expected a valid predecessor state.");
- // Don't use predecessor information if there was an earlier instruction
- // in this block that allowed a vsetvli to be skipped for load/store.
- if (!(BBLocalInfo.isValid() &&
- canSkipVSETVLIForLoadStore(MI, NewInfo, BBLocalInfo)) &&
- needVSETVLI(NewInfo, BlockInfo[MBB.getNumber()].Pred) &&
+ if (needVSETVLI(NewInfo, BlockInfo[MBB.getNumber()].Pred) &&
needVSETVLIPHI(NewInfo, MBB)) {
insertVSETVLI(MBB, MI, NewInfo, BlockInfo[MBB.getNumber()].Pred);
CurInfo = NewInfo;
- BBLocalInfo = NewInfo;
}
-
- // We must update BBLocalInfo for every vector instruction.
- if (!BBLocalInfo.isValid())
- BBLocalInfo = NewInfo;
} else {
- assert(BBLocalInfo.isValid());
// If this instruction isn't compatible with the previous VL/VTYPE
// we need to insert a VSETVLI.
// If this is a unit-stride or strided load/store, we may be able to use
@@ -1101,7 +1088,6 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
if (NeedInsertVSETVLI)
insertVSETVLI(MBB, MI, NewInfo, CurInfo);
CurInfo = NewInfo;
- BBLocalInfo = NewInfo;
}
}
PrevVSETVLIMI = nullptr;
@@ -1112,9 +1098,19 @@ void RISCVInsertVSETVLI::emitVSETVLIs(MachineBasicBlock &MBB) {
if (MI.isCall() || MI.isInlineAsm() || MI.modifiesRegister(RISCV::VL) ||
MI.modifiesRegister(RISCV::VTYPE)) {
CurInfo = VSETVLIInfo::getUnknown();
- BBLocalInfo = VSETVLIInfo::getUnknown();
PrevVSETVLIMI = nullptr;
}
+
+ // If we reach the end of the block and our current info doesn't match the
+ // expected info, insert a vsetvli to correct.
+ if (MI.isTerminator()) {
+ const VSETVLIInfo &ExitInfo = BlockInfo[MBB.getNumber()].Exit;
+ if (CurInfo.isValid() && ExitInfo.isValid() && !ExitInfo.isUnknown() &&
+ CurInfo != ExitInfo) {
+ insertVSETVLI(MBB, MI, ExitInfo, CurInfo);
+ CurInfo = ExitInfo;
+ }
+ }
}
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
index 2837b92da81f..4f5ec6aada61 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
@@ -26,6 +26,69 @@ def RISCVBuildPairF64 : SDNode<"RISCVISD::BuildPairF64", SDT_RISCVBuildPairF64>;
def RISCVSplitF64 : SDNode<"RISCVISD::SplitF64", SDT_RISCVSplitF64>;
//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+
+// Zdinx
+
+def GPRPF64AsFPR : AsmOperandClass {
+ let Name = "GPRPF64AsFPR";
+ let ParserMethod = "parseGPRAsFPR";
+ let RenderMethod = "addRegOperands";
+}
+
+def GPRF64AsFPR : AsmOperandClass {
+ let Name = "GPRF64AsFPR";
+ let ParserMethod = "parseGPRAsFPR";
+ let RenderMethod = "addRegOperands";
+}
+
+def FPR64INX : RegisterOperand<GPRF64> {
+ let ParserMatchClass = GPRF64AsFPR;
+ let DecoderMethod = "DecodeGPRRegisterClass";
+}
+
+def FPR64IN32X : RegisterOperand<GPRPF64> {
+ let ParserMatchClass = GPRPF64AsFPR;
+}
+
+def DExt : ExtInfo<0, [HasStdExtD]>;
+def D64Ext : ExtInfo<0, [HasStdExtD, IsRV64]>;
+def ZdinxExt : ExtInfo<1, [HasStdExtZdinx, IsRV64]>;
+def Zdinx32Ext : ExtInfo<2, [HasStdExtZdinx, IsRV32]>;
+
+def D : ExtInfo_r<DExt, FPR64>;
+def D_INX : ExtInfo_r<ZdinxExt, FPR64INX>;
+def D_IN32X : ExtInfo_r<Zdinx32Ext, FPR64IN32X>;
+
+def DD : ExtInfo_rr<DExt, FPR64, FPR64>;
+def DD_INX : ExtInfo_rr<ZdinxExt, FPR64INX, FPR64INX>;
+def DD_IN32X : ExtInfo_rr<Zdinx32Ext, FPR64IN32X, FPR64IN32X>;
+def DF : ExtInfo_rr<DExt, FPR64, FPR32>;
+def DF_INX : ExtInfo_rr<ZdinxExt, FPR64INX, FPR32INX>;
+def DF_IN32X : ExtInfo_rr<Zdinx32Ext, FPR64IN32X, FPR32INX>;
+def DX : ExtInfo_rr<DExt, FPR64, GPR>;
+def DX_INX : ExtInfo_rr<ZdinxExt, FPR64INX, GPR>;
+def DX_IN32X : ExtInfo_rr<Zdinx32Ext, FPR64IN32X, GPR>;
+def DX_64 : ExtInfo_rr<D64Ext, FPR64, GPR>;
+def FD : ExtInfo_rr<DExt, FPR32, FPR64>;
+def FD_INX : ExtInfo_rr<ZdinxExt, FPR32INX, FPR64INX>;
+def FD_IN32X : ExtInfo_rr<Zdinx32Ext, FPR32INX, FPR64IN32X>;
+def XD : ExtInfo_rr<DExt, GPR, FPR64>;
+def XD_INX : ExtInfo_rr<ZdinxExt, GPR, FPR64INX>;
+def XD_IN32X : ExtInfo_rr<Zdinx32Ext, GPR, FPR64IN32X>;
+def XD_64 : ExtInfo_rr<D64Ext, GPR, FPR64>;
+
+defvar DINX = [D, D_INX, D_IN32X];
+defvar DDINX = [DD, DD_INX, DD_IN32X];
+defvar DXINX = [DX, DX_INX, DX_IN32X];
+defvar DFINX = [DF, DF_INX, DF_IN32X];
+defvar FDINX = [FD, FD_INX, FD_IN32X];
+defvar XDINX = [XD, XD_INX, XD_IN32X];
+defvar DXIN64X = [DX_64, DX_INX];
+defvar XDIN64X = [XD_64, XD_INX];
+
+//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -36,106 +99,104 @@ def FLD : FPLoad_r<0b011, "fld", FPR64, WriteFLD64>;
// reflecting the order these fields are specified in the instruction
// encoding.
def FSD : FPStore_r<0b011, "fsd", FPR64, WriteFST64>;
+} // Predicates = [HasStdExtD]
let SchedRW = [WriteFMA64, ReadFMA64, ReadFMA64, ReadFMA64] in {
-def FMADD_D : FPFMA_rrr_frm<OPC_MADD, 0b01, "fmadd.d", FPR64>;
-def FMSUB_D : FPFMA_rrr_frm<OPC_MSUB, 0b01, "fmsub.d", FPR64>;
-def FNMSUB_D : FPFMA_rrr_frm<OPC_NMSUB, 0b01, "fnmsub.d", FPR64>;
-def FNMADD_D : FPFMA_rrr_frm<OPC_NMADD, 0b01, "fnmadd.d", FPR64>;
+defm FMADD_D : FPFMA_rrr_frm_m<OPC_MADD, 0b01, "fmadd.d", DINX>;
+defm FMSUB_D : FPFMA_rrr_frm_m<OPC_MSUB, 0b01, "fmsub.d", DINX>;
+defm FNMSUB_D : FPFMA_rrr_frm_m<OPC_NMSUB, 0b01, "fnmsub.d", DINX>;
+defm FNMADD_D : FPFMA_rrr_frm_m<OPC_NMADD, 0b01, "fnmadd.d", DINX>;
}
-def : FPFMADynFrmAlias<FMADD_D, "fmadd.d", FPR64>;
-def : FPFMADynFrmAlias<FMSUB_D, "fmsub.d", FPR64>;
-def : FPFMADynFrmAlias<FNMSUB_D, "fnmsub.d", FPR64>;
-def : FPFMADynFrmAlias<FNMADD_D, "fnmadd.d", FPR64>;
+defm : FPFMADynFrmAlias_m<FMADD_D, "fmadd.d", DINX>;
+defm : FPFMADynFrmAlias_m<FMSUB_D, "fmsub.d", DINX>;
+defm : FPFMADynFrmAlias_m<FNMSUB_D, "fnmsub.d", DINX>;
+defm : FPFMADynFrmAlias_m<FNMADD_D, "fnmadd.d", DINX>;
-def FADD_D : FPALU_rr_frm<0b0000001, "fadd.d", FPR64>,
- Sched<[WriteFALU64, ReadFALU64, ReadFALU64]>;
-def FSUB_D : FPALU_rr_frm<0b0000101, "fsub.d", FPR64>,
- Sched<[WriteFALU64, ReadFALU64, ReadFALU64]>;
-def FMUL_D : FPALU_rr_frm<0b0001001, "fmul.d", FPR64>,
- Sched<[WriteFMul64, ReadFMul64, ReadFMul64]>;
-def FDIV_D : FPALU_rr_frm<0b0001101, "fdiv.d", FPR64>,
- Sched<[WriteFDiv64, ReadFDiv64, ReadFDiv64]>;
+let SchedRW = [WriteFALU64, ReadFALU64, ReadFALU64] in {
+defm FADD_D : FPALU_rr_frm_m<0b0000001, "fadd.d", DINX>;
+defm FSUB_D : FPALU_rr_frm_m<0b0000101, "fsub.d", DINX>;
+}
+let SchedRW = [WriteFMul64, ReadFMul64, ReadFMul64] in
+defm FMUL_D : FPALU_rr_frm_m<0b0001001, "fmul.d", DINX>;
+
+let SchedRW = [WriteFDiv64, ReadFDiv64, ReadFDiv64] in
+defm FDIV_D : FPALU_rr_frm_m<0b0001101, "fdiv.d", DINX>;
-def : FPALUDynFrmAlias<FADD_D, "fadd.d", FPR64>;
-def : FPALUDynFrmAlias<FSUB_D, "fsub.d", FPR64>;
-def : FPALUDynFrmAlias<FMUL_D, "fmul.d", FPR64>;
-def : FPALUDynFrmAlias<FDIV_D, "fdiv.d", FPR64>;
+defm : FPALUDynFrmAlias_m<FADD_D, "fadd.d", DINX>;
+defm : FPALUDynFrmAlias_m<FSUB_D, "fsub.d", DINX>;
+defm : FPALUDynFrmAlias_m<FMUL_D, "fmul.d", DINX>;
+defm : FPALUDynFrmAlias_m<FDIV_D, "fdiv.d", DINX>;
-def FSQRT_D : FPUnaryOp_r_frm<0b0101101, 0b00000, FPR64, FPR64, "fsqrt.d">,
- Sched<[WriteFSqrt64, ReadFSqrt64]>;
-def : FPUnaryOpDynFrmAlias<FSQRT_D, "fsqrt.d", FPR64, FPR64>;
+defm FSQRT_D : FPUnaryOp_r_frm_m<0b0101101, 0b00000, DDINX, "fsqrt.d">,
+ Sched<[WriteFSqrt64, ReadFSqrt64]>;
+defm : FPUnaryOpDynFrmAlias_m<FSQRT_D, "fsqrt.d", DDINX>;
let SchedRW = [WriteFSGNJ64, ReadFSGNJ64, ReadFSGNJ64],
mayRaiseFPException = 0 in {
-def FSGNJ_D : FPALU_rr<0b0010001, 0b000, "fsgnj.d", FPR64>;
-def FSGNJN_D : FPALU_rr<0b0010001, 0b001, "fsgnjn.d", FPR64>;
-def FSGNJX_D : FPALU_rr<0b0010001, 0b010, "fsgnjx.d", FPR64>;
+defm FSGNJ_D : FPALU_rr_m<0b0010001, 0b000, "fsgnj.d", DINX>;
+defm FSGNJN_D : FPALU_rr_m<0b0010001, 0b001, "fsgnjn.d", DINX>;
+defm FSGNJX_D : FPALU_rr_m<0b0010001, 0b010, "fsgnjx.d", DINX>;
}
let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in {
-def FMIN_D : FPALU_rr<0b0010101, 0b000, "fmin.d", FPR64>;
-def FMAX_D : FPALU_rr<0b0010101, 0b001, "fmax.d", FPR64>;
+defm FMIN_D : FPALU_rr_m<0b0010101, 0b000, "fmin.d", DINX>;
+defm FMAX_D : FPALU_rr_m<0b0010101, 0b001, "fmax.d", DINX>;
}
-def FCVT_S_D : FPUnaryOp_r_frm<0b0100000, 0b00001, FPR32, FPR64, "fcvt.s.d">,
- Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_S_D, "fcvt.s.d", FPR32, FPR64>;
+defm FCVT_S_D : FPUnaryOp_r_frm_m<0b0100000, 0b00001, FDINX, "fcvt.s.d">,
+ Sched<[WriteFCvtF64ToF32, ReadFCvtF64ToF32]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_S_D, "fcvt.s.d", FDINX>;
-def FCVT_D_S : FPUnaryOp_r<0b0100001, 0b00000, 0b000, FPR64, FPR32, "fcvt.d.s">,
- Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]>;
+defm FCVT_D_S : FPUnaryOp_r_m<0b0100001, 0b00000, 0b000, DFINX, "fcvt.d.s">,
+ Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]>;
let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in {
-def FEQ_D : FPCmp_rr<0b1010001, 0b010, "feq.d", FPR64>;
-def FLT_D : FPCmp_rr<0b1010001, 0b001, "flt.d", FPR64>;
-def FLE_D : FPCmp_rr<0b1010001, 0b000, "fle.d", FPR64>;
+defm FEQ_D : FPCmp_rr_m<0b1010001, 0b010, "feq.d", DINX>;
+defm FLT_D : FPCmp_rr_m<0b1010001, 0b001, "flt.d", DINX>;
+defm FLE_D : FPCmp_rr_m<0b1010001, 0b000, "fle.d", DINX>;
}
-let mayRaiseFPException = 0 in
-def FCLASS_D : FPUnaryOp_r<0b1110001, 0b00000, 0b001, GPR, FPR64, "fclass.d">,
- Sched<[WriteFClass64, ReadFClass64]>;
+defm FCLASS_D : FPUnaryOp_r_m<0b1110001, 0b00000, 0b001, XDINX, "fclass.d">,
+ Sched<[WriteFClass64, ReadFClass64]>;
-def FCVT_W_D : FPUnaryOp_r_frm<0b1100001, 0b00000, GPR, FPR64, "fcvt.w.d">,
+defm FCVT_W_D : FPUnaryOp_r_frm_m<0b1100001, 0b00000, XDINX, "fcvt.w.d">,
Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_W_D, "fcvt.w.d", GPR, FPR64>;
-
-def FCVT_WU_D : FPUnaryOp_r_frm<0b1100001, 0b00001, GPR, FPR64, "fcvt.wu.d">,
- Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_WU_D, "fcvt.wu.d", GPR, FPR64>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_W_D, "fcvt.w.d", XDINX>;
-def FCVT_D_W : FPUnaryOp_r<0b1101001, 0b00000, 0b000, FPR64, GPR, "fcvt.d.w">,
- Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
+defm FCVT_WU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00001, XDINX, "fcvt.wu.d">,
+ Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_WU_D, "fcvt.wu.d", XDINX>;
-def FCVT_D_WU : FPUnaryOp_r<0b1101001, 0b00001, 0b000, FPR64, GPR, "fcvt.d.wu">,
+defm FCVT_D_W : FPUnaryOp_r_m<0b1101001, 0b00000, 0b000, DXINX, "fcvt.d.w">,
Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
-} // Predicates = [HasStdExtD]
-let Predicates = [HasStdExtD, IsRV64] in {
-def FCVT_L_D : FPUnaryOp_r_frm<0b1100001, 0b00010, GPR, FPR64, "fcvt.l.d">,
- Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_L_D, "fcvt.l.d", GPR, FPR64>;
+defm FCVT_D_WU : FPUnaryOp_r_m<0b1101001, 0b00001, 0b000, DXINX, "fcvt.d.wu">,
+ Sched<[WriteFCvtI32ToF64, ReadFCvtI32ToF64]>;
-def FCVT_LU_D : FPUnaryOp_r_frm<0b1100001, 0b00011, GPR, FPR64, "fcvt.lu.d">,
+defm FCVT_L_D : FPUnaryOp_r_frm_m<0b1100001, 0b00010, XDIN64X, "fcvt.l.d">,
Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_LU_D, "fcvt.lu.d", GPR, FPR64>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_L_D, "fcvt.l.d", XDIN64X>;
-let mayRaiseFPException = 0 in
+defm FCVT_LU_D : FPUnaryOp_r_frm_m<0b1100001, 0b00011, XDIN64X, "fcvt.lu.d">,
+ Sched<[WriteFCvtF64ToI64, ReadFCvtF64ToI64]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_LU_D, "fcvt.lu.d", XDIN64X>;
+
+let Predicates = [HasStdExtD, IsRV64], mayRaiseFPException = 0 in
def FMV_X_D : FPUnaryOp_r<0b1110001, 0b00000, 0b000, GPR, FPR64, "fmv.x.d">,
Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>;
-def FCVT_D_L : FPUnaryOp_r_frm<0b1101001, 0b00010, FPR64, GPR, "fcvt.d.l">,
- Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_D_L, "fcvt.d.l", FPR64, GPR>;
-
-def FCVT_D_LU : FPUnaryOp_r_frm<0b1101001, 0b00011, FPR64, GPR, "fcvt.d.lu">,
+defm FCVT_D_L : FPUnaryOp_r_frm_m<0b1101001, 0b00010, DXIN64X, "fcvt.d.l">,
Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_D_LU, "fcvt.d.lu", FPR64, GPR>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_D_L, "fcvt.d.l", DXIN64X>;
-let mayRaiseFPException = 0 in
+defm FCVT_D_LU : FPUnaryOp_r_frm_m<0b1101001, 0b00011, DXIN64X, "fcvt.d.lu">,
+ Sched<[WriteFCvtI64ToF64, ReadFCvtI64ToF64]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_D_LU, "fcvt.d.lu", DXIN64X>;
+
+let Predicates = [HasStdExtD, IsRV64], mayRaiseFPException = 0 in
def FMV_D_X : FPUnaryOp_r<0b1111001, 0b00000, 0b000, FPR64, GPR, "fmv.d.x">,
Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]>;
-} // Predicates = [HasStdExtD, IsRV64]
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
@@ -164,6 +225,26 @@ def PseudoQuietFLT_D : PseudoQuietFCMP<FPR64>;
}
} // Predicates = [HasStdExtD]
+let Predicates = [HasStdExtZdinx, IsRV64] in {
+def : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D_INX FPR64INX:$rd, FPR64INX:$rs, FPR64INX:$rs)>;
+def : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D_INX FPR64INX:$rd, FPR64INX:$rs, FPR64INX:$rs)>;
+
+def : InstAlias<"fgt.d $rd, $rs, $rt",
+ (FLT_D_INX GPR:$rd, FPR64INX:$rt, FPR64INX:$rs), 0>;
+def : InstAlias<"fge.d $rd, $rs, $rt",
+ (FLE_D_INX GPR:$rd, FPR64INX:$rt, FPR64INX:$rs), 0>;
+} // Predicates = [HasStdExtZdinx, IsRV64]
+
+let Predicates = [HasStdExtZdinx, IsRV32] in {
+def : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D_IN32X FPR64IN32X:$rd, FPR64IN32X:$rs, FPR64IN32X:$rs)>;
+def : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D_IN32X FPR64IN32X:$rd, FPR64IN32X:$rs, FPR64IN32X:$rs)>;
+
+def : InstAlias<"fgt.d $rd, $rs, $rt",
+ (FLT_D_IN32X GPR:$rd, FPR64IN32X:$rt, FPR64IN32X:$rs), 0>;
+def : InstAlias<"fge.d $rd, $rs, $rt",
+ (FLE_D_IN32X GPR:$rd, FPR64IN32X:$rt, FPR64IN32X:$rs), 0>;
+} // Predicates = [HasStdExtZdinx, IsRV32]
+
//===----------------------------------------------------------------------===//
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
index a8ac06ba8da3..4b45b47af451 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
@@ -57,6 +57,73 @@ def riscv_any_fcvt_wu_rv64 : PatFrags<(ops node:$src, node:$frm),
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//
+// Zfinx
+
+def GPRAsFPR : AsmOperandClass {
+ let Name = "GPRAsFPR";
+ let ParserMethod = "parseGPRAsFPR";
+ let RenderMethod = "addRegOperands";
+}
+
+def FPR32INX : RegisterOperand<GPRF32> {
+ let ParserMatchClass = GPRAsFPR;
+ let DecoderMethod = "DecodeGPRRegisterClass";
+}
+
+// inx = 0 : f, d, zfh, zfhmin
+// = 1 : zfinx, zdinx, zhinx, zhinxmin
+// = 2 : zdinx_rv32
+class ExtInfo<bits<2> inx, list<Predicate> pres> {
+ string Suffix = !cond(!eq(inx, 0): "",
+ !eq(inx, 1): "_INX",
+ !eq(inx, 2): "_IN32X");
+ list<Predicate> Predicates = pres;
+ string Space = !cond(!eq(inx, 0): "",
+ !eq(inx, 1): "RVZfinx",
+ !eq(inx, 2): "RV32Zdinx");
+}
+
+class ExtInfo_r<ExtInfo ext, DAGOperand reg> {
+ string Suffix = ext.Suffix;
+ list<Predicate> Predicates = ext.Predicates;
+ string Space = ext.Space;
+ DAGOperand Reg = reg;
+}
+
+class ExtInfo_rr<ExtInfo ext, DAGOperand rdty, DAGOperand rs1ty> {
+ string Suffix = ext.Suffix;
+ list<Predicate> Predicates = ext.Predicates;
+ string Space = ext.Space;
+ DAGOperand RdTy = rdty;
+ DAGOperand Rs1Ty = rs1ty;
+}
+
+def FExt : ExtInfo<0, [HasStdExtF]>;
+def F64Ext : ExtInfo<0, [HasStdExtF, IsRV64]>;
+def ZfinxExt : ExtInfo<1, [HasStdExtZfinx]>;
+def Zfinx64Ext : ExtInfo<1, [HasStdExtZfinx, IsRV64]>;
+
+def F : ExtInfo_r<FExt, FPR32>;
+def F_INX : ExtInfo_r<ZfinxExt, FPR32INX>;
+
+def FF : ExtInfo_rr<FExt, FPR32, FPR32>;
+def FF_INX : ExtInfo_rr<ZfinxExt, FPR32INX, FPR32INX>;
+def FX : ExtInfo_rr<FExt, FPR32, GPR>;
+def FX_INX : ExtInfo_rr<ZfinxExt, FPR32INX, GPR>;
+def FX_64 : ExtInfo_rr<F64Ext, FPR32, GPR>;
+def FX_INX_64 : ExtInfo_rr<Zfinx64Ext, FPR32INX, GPR>;
+def XF : ExtInfo_rr<FExt, GPR, FPR32>;
+def XF_64 : ExtInfo_rr<F64Ext, GPR, FPR32>;
+def XF_INX : ExtInfo_rr<ZfinxExt, GPR, FPR32INX>;
+def XF_INX_64 : ExtInfo_rr<Zfinx64Ext, GPR, FPR32INX>;
+
+defvar FINX = [F, F_INX];
+defvar FFINX = [FF, FF_INX];
+defvar FXINX = [FX, FX_INX];
+defvar XFINX = [XF, XF_INX];
+defvar XFIN64X = [XF_64, XF_INX_64];
+defvar FXIN64X = [FX_64, FX_INX_64];
+
// Floating-point rounding mode
def FRMArg : AsmOperandClass {
@@ -94,62 +161,123 @@ class FPStore_r<bits<3> funct3, string opcodestr, RegisterClass rty,
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
UseNamedOperandTable = 1, hasPostISelHook = 1 in
class FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr,
- RegisterClass rty>
+ DAGOperand rty>
: RVInstR4Frm<funct2, opcode, (outs rty:$rd),
(ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm),
opcodestr, "$rd, $rs1, $rs2, $rs3, $frm">;
+multiclass FPFMA_rrr_frm_m<RISCVOpcode opcode, bits<2> funct2,
+ string opcodestr, list<ExtInfo_r> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+ def Ext.Suffix : FPFMA_rrr_frm<opcode, funct2, opcodestr, Ext.Reg>;
+}
+
class FPFMADynFrmAlias<FPFMA_rrr_frm Inst, string OpcodeStr,
- RegisterClass rty>
+ DAGOperand rty>
: InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
(Inst rty:$rd, rty:$rs1, rty:$rs2, rty:$rs3, 0b111)>;
+multiclass FPFMADynFrmAlias_m<FPFMA_rrr_frm Inst, string OpcodeStr,
+ list<ExtInfo_r> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates in
+ def : FPFMADynFrmAlias<!cast<FPFMA_rrr_frm>(Inst#Ext.Suffix), OpcodeStr,
+ Ext.Reg>;
+}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
class FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
- RegisterClass rty>
+ DAGOperand rty>
: RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd),
(ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+multiclass FPALU_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
+ list<ExtInfo_r> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+ def Ext.Suffix : FPALU_rr<funct7, funct3, opcodestr, Ext.Reg>;
+}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
UseNamedOperandTable = 1, hasPostISelHook = 1 in
-class FPALU_rr_frm<bits<7> funct7, string opcodestr, RegisterClass rty>
+class FPALU_rr_frm<bits<7> funct7, string opcodestr, DAGOperand rty>
: RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd),
(ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr,
"$rd, $rs1, $rs2, $frm">;
+multiclass FPALU_rr_frm_m<bits<7> funct7, string opcodestr,
+ list<ExtInfo_r> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+ def Ext.Suffix : FPALU_rr_frm<funct7, opcodestr, Ext.Reg>;
+}
+
class FPALUDynFrmAlias<FPALU_rr_frm Inst, string OpcodeStr,
- RegisterClass rty>
+ DAGOperand rty>
: InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
(Inst rty:$rd, rty:$rs1, rty:$rs2, 0b111)>;
+multiclass FPALUDynFrmAlias_m<FPALU_rr_frm Inst, string OpcodeStr,
+ list<ExtInfo_r> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates in
+ def : FPALUDynFrmAlias<!cast<FPALU_rr_frm>(Inst#Ext.Suffix), OpcodeStr,
+ Ext.Reg>;
+}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
class FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
- RegisterClass rdty, RegisterClass rs1ty, string opcodestr>
+ DAGOperand rdty, DAGOperand rs1ty, string opcodestr>
: RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
opcodestr, "$rd, $rs1"> {
let rs2 = rs2val;
}
+multiclass FPUnaryOp_r_m<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
+ list<ExtInfo_rr> Exts, string opcodestr> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+ def Ext.Suffix : FPUnaryOp_r<funct7, rs2val, funct3, Ext.RdTy, Ext.Rs1Ty,
+ opcodestr>;
+}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
UseNamedOperandTable = 1, hasPostISelHook = 1 in
-class FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, RegisterClass rdty,
- RegisterClass rs1ty, string opcodestr>
+class FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
+ DAGOperand rs1ty, string opcodestr>
: RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
(ins rs1ty:$rs1, frmarg:$frm), opcodestr,
"$rd, $rs1, $frm"> {
let rs2 = rs2val;
}
+multiclass FPUnaryOp_r_frm_m<bits<7> funct7, bits<5> rs2val,
+ list<ExtInfo_rr> Exts, string opcodestr> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+ def Ext.Suffix : FPUnaryOp_r_frm<funct7, rs2val, Ext.RdTy, Ext.Rs1Ty,
+ opcodestr>;
+}
class FPUnaryOpDynFrmAlias<FPUnaryOp_r_frm Inst, string OpcodeStr,
- RegisterClass rdty, RegisterClass rs1ty>
+ DAGOperand rdty, DAGOperand rs1ty>
: InstAlias<OpcodeStr#" $rd, $rs1",
(Inst rdty:$rd, rs1ty:$rs1, 0b111)>;
+multiclass FPUnaryOpDynFrmAlias_m<FPUnaryOp_r_frm Inst, string OpcodeStr,
+ list<ExtInfo_rr> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates in
+ def : FPUnaryOpDynFrmAlias<!cast<FPUnaryOp_r_frm>(Inst#Ext.Suffix),
+ OpcodeStr, Ext.RdTy, Ext.Rs1Ty>;
+}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
class FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
- RegisterClass rty>
+ DAGOperand rty>
: RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd),
(ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+multiclass FPCmp_rr_m<bits<7> funct7, bits<3> funct3, string opcodestr,
+ list<ExtInfo_r> Exts> {
+ foreach Ext = Exts in
+ let Predicates = Ext.Predicates, DecoderNamespace = Ext.Space in
+ def Ext.Suffix : FPCmp_rr<funct7, funct3, opcodestr, Ext.Reg>;
+}
//===----------------------------------------------------------------------===//
// Instructions
@@ -162,101 +290,100 @@ def FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>;
// reflecting the order these fields are specified in the instruction
// encoding.
def FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>;
+} // Predicates = [HasStdExtF]
let SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32] in {
-def FMADD_S : FPFMA_rrr_frm<OPC_MADD, 0b00, "fmadd.s", FPR32>;
-def FMSUB_S : FPFMA_rrr_frm<OPC_MSUB, 0b00, "fmsub.s", FPR32>;
-def FNMSUB_S : FPFMA_rrr_frm<OPC_NMSUB, 0b00, "fnmsub.s", FPR32>;
-def FNMADD_S : FPFMA_rrr_frm<OPC_NMADD, 0b00, "fnmadd.s", FPR32>;
+defm FMADD_S : FPFMA_rrr_frm_m<OPC_MADD, 0b00, "fmadd.s", FINX>;
+defm FMSUB_S : FPFMA_rrr_frm_m<OPC_MSUB, 0b00, "fmsub.s", FINX>;
+defm FNMSUB_S : FPFMA_rrr_frm_m<OPC_NMSUB, 0b00, "fnmsub.s", FINX>;
+defm FNMADD_S : FPFMA_rrr_frm_m<OPC_NMADD, 0b00, "fnmadd.s", FINX>;
}
-def : FPFMADynFrmAlias<FMADD_S, "fmadd.s", FPR32>;
-def : FPFMADynFrmAlias<FMSUB_S, "fmsub.s", FPR32>;
-def : FPFMADynFrmAlias<FNMSUB_S, "fnmsub.s", FPR32>;
-def : FPFMADynFrmAlias<FNMADD_S, "fnmadd.s", FPR32>;
+defm : FPFMADynFrmAlias_m<FMADD_S, "fmadd.s", FINX>;
+defm : FPFMADynFrmAlias_m<FMSUB_S, "fmsub.s", FINX>;
+defm : FPFMADynFrmAlias_m<FNMSUB_S, "fnmsub.s", FINX>;
+defm : FPFMADynFrmAlias_m<FNMADD_S, "fnmadd.s", FINX>;
-def FADD_S : FPALU_rr_frm<0b0000000, "fadd.s", FPR32>,
- Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>;
-def FSUB_S : FPALU_rr_frm<0b0000100, "fsub.s", FPR32>,
- Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>;
-def FMUL_S : FPALU_rr_frm<0b0001000, "fmul.s", FPR32>,
- Sched<[WriteFMul32, ReadFMul32, ReadFMul32]>;
-def FDIV_S : FPALU_rr_frm<0b0001100, "fdiv.s", FPR32>,
- Sched<[WriteFDiv32, ReadFDiv32, ReadFDiv32]>;
+let SchedRW = [WriteFALU32, ReadFALU32, ReadFALU32] in {
+defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", FINX>;
+defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", FINX>;
+}
+let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in
+defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", FINX>;
+
+let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in
+defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", FINX>;
-def : FPALUDynFrmAlias<FADD_S, "fadd.s", FPR32>;
-def : FPALUDynFrmAlias<FSUB_S, "fsub.s", FPR32>;
-def : FPALUDynFrmAlias<FMUL_S, "fmul.s", FPR32>;
-def : FPALUDynFrmAlias<FDIV_S, "fdiv.s", FPR32>;
+defm : FPALUDynFrmAlias_m<FADD_S, "fadd.s", FINX>;
+defm : FPALUDynFrmAlias_m<FSUB_S, "fsub.s", FINX>;
+defm : FPALUDynFrmAlias_m<FMUL_S, "fmul.s", FINX>;
+defm : FPALUDynFrmAlias_m<FDIV_S, "fdiv.s", FINX>;
-def FSQRT_S : FPUnaryOp_r_frm<0b0101100, 0b00000, FPR32, FPR32, "fsqrt.s">,
- Sched<[WriteFSqrt32, ReadFSqrt32]>;
-def : FPUnaryOpDynFrmAlias<FSQRT_S, "fsqrt.s", FPR32, FPR32>;
+defm FSQRT_S : FPUnaryOp_r_frm_m<0b0101100, 0b00000, FFINX, "fsqrt.s">,
+ Sched<[WriteFSqrt32, ReadFSqrt32]>;
+defm : FPUnaryOpDynFrmAlias_m<FSQRT_S, "fsqrt.s", FFINX>;
let SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32],
mayRaiseFPException = 0 in {
-def FSGNJ_S : FPALU_rr<0b0010000, 0b000, "fsgnj.s", FPR32>;
-def FSGNJN_S : FPALU_rr<0b0010000, 0b001, "fsgnjn.s", FPR32>;
-def FSGNJX_S : FPALU_rr<0b0010000, 0b010, "fsgnjx.s", FPR32>;
+defm FSGNJ_S : FPALU_rr_m<0b0010000, 0b000, "fsgnj.s", FINX>;
+defm FSGNJN_S : FPALU_rr_m<0b0010000, 0b001, "fsgnjn.s", FINX>;
+defm FSGNJX_S : FPALU_rr_m<0b0010000, 0b010, "fsgnjx.s", FINX>;
}
let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
-def FMIN_S : FPALU_rr<0b0010100, 0b000, "fmin.s", FPR32>;
-def FMAX_S : FPALU_rr<0b0010100, 0b001, "fmax.s", FPR32>;
+defm FMIN_S : FPALU_rr_m<0b0010100, 0b000, "fmin.s", FINX>;
+defm FMAX_S : FPALU_rr_m<0b0010100, 0b001, "fmax.s", FINX>;
}
-def FCVT_W_S : FPUnaryOp_r_frm<0b1100000, 0b00000, GPR, FPR32, "fcvt.w.s">,
- Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_W_S, "fcvt.w.s", GPR, FPR32>;
-
-def FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, 0b00001, GPR, FPR32, "fcvt.wu.s">,
+defm FCVT_W_S : FPUnaryOp_r_frm_m<0b1100000, 0b00000, XFINX, "fcvt.w.s">,
Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_WU_S, "fcvt.wu.s", GPR, FPR32>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_W_S, "fcvt.w.s", XFINX>;
+
+defm FCVT_WU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00001, XFINX, "fcvt.wu.s">,
+ Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_WU_S, "fcvt.wu.s", XFINX>;
let mayRaiseFPException = 0 in
def FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">,
Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>;
let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
-def FEQ_S : FPCmp_rr<0b1010000, 0b010, "feq.s", FPR32>;
-def FLT_S : FPCmp_rr<0b1010000, 0b001, "flt.s", FPR32>;
-def FLE_S : FPCmp_rr<0b1010000, 0b000, "fle.s", FPR32>;
+defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", FINX>;
+defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", FINX>;
+defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", FINX>;
}
let mayRaiseFPException = 0 in
-def FCLASS_S : FPUnaryOp_r<0b1110000, 0b00000, 0b001, GPR, FPR32, "fclass.s">,
- Sched<[WriteFClass32, ReadFClass32]>;
-
-def FCVT_S_W : FPUnaryOp_r_frm<0b1101000, 0b00000, FPR32, GPR, "fcvt.s.w">,
- Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_S_W, "fcvt.s.w", FPR32, GPR>;
+defm FCLASS_S : FPUnaryOp_r_m<0b1110000, 0b00000, 0b001, XFINX, "fclass.s">,
+ Sched<[WriteFClass32, ReadFClass32]>;
-def FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, 0b00001, FPR32, GPR, "fcvt.s.wu">,
+defm FCVT_S_W : FPUnaryOp_r_frm_m<0b1101000, 0b00000, FXINX, "fcvt.s.w">,
Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_S_WU, "fcvt.s.wu", FPR32, GPR>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_S_W, "fcvt.s.w", FXINX>;
+
+defm FCVT_S_WU : FPUnaryOp_r_frm_m<0b1101000, 0b00001, FXINX, "fcvt.s.wu">,
+ Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_S_WU, "fcvt.s.wu", FXINX>;
let mayRaiseFPException = 0 in
def FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">,
Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>;
-} // Predicates = [HasStdExtF]
-let Predicates = [HasStdExtF, IsRV64] in {
-def FCVT_L_S : FPUnaryOp_r_frm<0b1100000, 0b00010, GPR, FPR32, "fcvt.l.s">,
- Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_L_S, "fcvt.l.s", GPR, FPR32>;
-
-def FCVT_LU_S : FPUnaryOp_r_frm<0b1100000, 0b00011, GPR, FPR32, "fcvt.lu.s">,
+defm FCVT_L_S : FPUnaryOp_r_frm_m<0b1100000, 0b00010, XFIN64X, "fcvt.l.s">,
Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_LU_S, "fcvt.lu.s", GPR, FPR32>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_L_S, "fcvt.l.s", XFIN64X>;
-def FCVT_S_L : FPUnaryOp_r_frm<0b1101000, 0b00010, FPR32, GPR, "fcvt.s.l">,
- Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_S_L, "fcvt.s.l", FPR32, GPR>;
+defm FCVT_LU_S : FPUnaryOp_r_frm_m<0b1100000, 0b00011, XFIN64X, "fcvt.lu.s">,
+ Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_LU_S, "fcvt.lu.s", XFIN64X>;
-def FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, 0b00011, FPR32, GPR, "fcvt.s.lu">,
+defm FCVT_S_L : FPUnaryOp_r_frm_m<0b1101000, 0b00010, FXIN64X, "fcvt.s.l">,
Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_S_LU, "fcvt.s.lu", FPR32, GPR>;
-} // Predicates = [HasStdExtF, IsRV64]
+defm : FPUnaryOpDynFrmAlias_m<FCVT_S_L, "fcvt.s.l", FXIN64X>;
+
+defm FCVT_S_LU : FPUnaryOp_r_frm_m<0b1101000, 0b00011, FXIN64X, "fcvt.s.lu">,
+ Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_S_LU, "fcvt.s.lu", FXIN64X>;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
@@ -315,6 +442,16 @@ def PseudoQuietFLT_S : PseudoQuietFCMP<FPR32>;
}
} // Predicates = [HasStdExtF]
+let Predicates = [HasStdExtZfinx] in {
+def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
+def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S_INX FPR32INX:$rd, FPR32INX:$rs, FPR32INX:$rs)>;
+
+def : InstAlias<"fgt.s $rd, $rs, $rt",
+ (FLT_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
+def : InstAlias<"fge.s $rd, $rs, $rt",
+ (FLE_S_INX GPR:$rd, FPR32INX:$rt, FPR32INX:$rs), 0>;
+} // Predicates = [HasStdExtZfinx]
+
//===----------------------------------------------------------------------===//
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
index a2753c132354..631525484bd9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
@@ -26,6 +26,62 @@ def riscv_fmv_x_anyexth
: SDNode<"RISCVISD::FMV_X_ANYEXTH", SDT_RISCVFMV_X_ANYEXTH>;
//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+
+// Zhinxmin and Zhinx
+
+def FPR16INX : RegisterOperand<GPRF16> {
+ let ParserMatchClass = GPRAsFPR;
+ let DecoderMethod = "DecodeGPRRegisterClass";
+}
+
+def ZfhExt : ExtInfo<0, [HasStdExtZfh]>;
+def Zfh64Ext : ExtInfo<0, [HasStdExtZfh, IsRV64]>;
+def ZfhminExt : ExtInfo<0, [HasStdExtZfhOrZfhmin]>;
+def ZhinxExt : ExtInfo<1, [HasStdExtZhinx]>;
+def ZhinxminExt : ExtInfo<1, [HasStdExtZhinxOrZhinxmin]>;
+def Zhinx64Ext : ExtInfo<1, [HasStdExtZhinx, IsRV64]>;
+
+def ZfhminDExt : ExtInfo<0, [HasStdExtZfhOrZfhmin, HasStdExtD]>;
+def ZhinxminZdinxExt : ExtInfo<1, [HasStdExtZhinxOrZhinxmin, HasStdExtZdinx]>;
+
+def H : ExtInfo_r<ZfhExt, FPR16>;
+def H_INX : ExtInfo_r<ZhinxExt, FPR16INX>;
+
+def HH : ExtInfo_rr<ZfhExt, FPR16, FPR16>;
+def HH_INX : ExtInfo_rr<ZhinxExt, FPR16INX, FPR16INX>;
+def XH : ExtInfo_rr<ZfhExt, GPR, FPR16>;
+def XH_INX : ExtInfo_rr<ZhinxExt, GPR, FPR16INX>;
+def HX : ExtInfo_rr<ZfhExt, FPR16, GPR>;
+def HX_INX : ExtInfo_rr<ZhinxExt, FPR16INX, GPR>;
+def XH_64 : ExtInfo_rr<Zfh64Ext, GPR, FPR16>;
+def HX_64 : ExtInfo_rr<Zfh64Ext, FPR16, GPR>;
+def XH_INX_64 : ExtInfo_rr<Zhinx64Ext, GPR, FPR16INX>;
+def HX_INX_64 : ExtInfo_rr<Zhinx64Ext, FPR16INX, GPR>;
+def HFmin : ExtInfo_rr<ZfhminExt, FPR16, FPR32>;
+def HF_INXmin : ExtInfo_rr<ZhinxminExt, FPR16INX, FPR32INX>;
+def HF_INX : ExtInfo_rr<ZhinxExt, FPR16INX, FPR32INX>;
+def FHmin : ExtInfo_rr<ZfhminExt, FPR32, FPR16>;
+def FH_INXmin : ExtInfo_rr<ZhinxminExt, FPR32INX, FPR16INX>;
+def FH_INX : ExtInfo_rr<ZhinxExt, FPR32INX, FPR16INX>;
+def DHmin : ExtInfo_rr<ZfhminDExt, FPR64, FPR16>;
+def DH_INXmin : ExtInfo_rr<ZhinxminZdinxExt, FPR64INX, FPR16INX>;
+def HDmin : ExtInfo_rr<ZfhminDExt, FPR16, FPR64>;
+def HD_INXmin : ExtInfo_rr<ZhinxminZdinxExt, FPR16INX, FPR64INX>;
+
+defvar HINX = [H, H_INX];
+defvar HHINX = [HH, HH_INX];
+defvar XHINX = [XH, XH_INX];
+defvar HXINX = [HX, HX_INX];
+defvar XHIN64X = [XH_64, XH_INX_64];
+defvar HXIN64X = [HX_64, HX_INX_64];
+defvar HFINXmin = [HFmin, HF_INXmin];
+defvar FHINXmin = [FHmin, FH_INXmin];
+defvar DHINXmin = [DHmin, DH_INXmin];
+defvar HDINXmin = [HDmin, HD_INXmin];
+
+//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -38,74 +94,73 @@ def FLH : FPLoad_r<0b001, "flh", FPR16, WriteFLD16>;
def FSH : FPStore_r<0b001, "fsh", FPR16, WriteFST16>;
} // Predicates = [HasStdExtZfhOrZfhmin]
-let Predicates = [HasStdExtZfh] in {
let SchedRW = [WriteFMA16, ReadFMA16, ReadFMA16, ReadFMA16] in {
-def FMADD_H : FPFMA_rrr_frm<OPC_MADD, 0b10, "fmadd.h", FPR16>;
-def FMSUB_H : FPFMA_rrr_frm<OPC_MSUB, 0b10, "fmsub.h", FPR16>;
-def FNMSUB_H : FPFMA_rrr_frm<OPC_NMSUB, 0b10, "fnmsub.h", FPR16>;
-def FNMADD_H : FPFMA_rrr_frm<OPC_NMADD, 0b10, "fnmadd.h", FPR16>;
+defm FMADD_H : FPFMA_rrr_frm_m<OPC_MADD, 0b10, "fmadd.h", HINX>;
+defm FMSUB_H : FPFMA_rrr_frm_m<OPC_MSUB, 0b10, "fmsub.h", HINX>;
+defm FNMSUB_H : FPFMA_rrr_frm_m<OPC_NMSUB, 0b10, "fnmsub.h", HINX>;
+defm FNMADD_H : FPFMA_rrr_frm_m<OPC_NMADD, 0b10, "fnmadd.h", HINX>;
}
-def : FPFMADynFrmAlias<FMADD_H, "fmadd.h", FPR16>;
-def : FPFMADynFrmAlias<FMSUB_H, "fmsub.h", FPR16>;
-def : FPFMADynFrmAlias<FNMSUB_H, "fnmsub.h", FPR16>;
-def : FPFMADynFrmAlias<FNMADD_H, "fnmadd.h", FPR16>;
+defm : FPFMADynFrmAlias_m<FMADD_H, "fmadd.h", HINX>;
+defm : FPFMADynFrmAlias_m<FMSUB_H, "fmsub.h", HINX>;
+defm : FPFMADynFrmAlias_m<FNMSUB_H, "fnmsub.h", HINX>;
+defm : FPFMADynFrmAlias_m<FNMADD_H, "fnmadd.h", HINX>;
-def FADD_H : FPALU_rr_frm<0b0000010, "fadd.h", FPR16>,
- Sched<[WriteFALU16, ReadFALU16, ReadFALU16]>;
-def FSUB_H : FPALU_rr_frm<0b0000110, "fsub.h", FPR16>,
- Sched<[WriteFALU16, ReadFALU16, ReadFALU16]>;
-def FMUL_H : FPALU_rr_frm<0b0001010, "fmul.h", FPR16>,
- Sched<[WriteFMul16, ReadFMul16, ReadFMul16]>;
-def FDIV_H : FPALU_rr_frm<0b0001110, "fdiv.h", FPR16>,
- Sched<[WriteFDiv16, ReadFDiv16, ReadFDiv16]>;
+let SchedRW = [WriteFALU16, ReadFALU16, ReadFALU16] in {
+defm FADD_H : FPALU_rr_frm_m<0b0000010, "fadd.h", HINX>;
+defm FSUB_H : FPALU_rr_frm_m<0b0000110, "fsub.h", HINX>;
+}
+let SchedRW = [WriteFMul16, ReadFMul16, ReadFMul16] in
+defm FMUL_H : FPALU_rr_frm_m<0b0001010, "fmul.h", HINX>;
+
+let SchedRW = [WriteFDiv16, ReadFDiv16, ReadFDiv16] in
+defm FDIV_H : FPALU_rr_frm_m<0b0001110, "fdiv.h", HINX>;
-def : FPALUDynFrmAlias<FADD_H, "fadd.h", FPR16>;
-def : FPALUDynFrmAlias<FSUB_H, "fsub.h", FPR16>;
-def : FPALUDynFrmAlias<FMUL_H, "fmul.h", FPR16>;
-def : FPALUDynFrmAlias<FDIV_H, "fdiv.h", FPR16>;
+defm : FPALUDynFrmAlias_m<FADD_H, "fadd.h", HINX>;
+defm : FPALUDynFrmAlias_m<FSUB_H, "fsub.h", HINX>;
+defm : FPALUDynFrmAlias_m<FMUL_H, "fmul.h", HINX>;
+defm : FPALUDynFrmAlias_m<FDIV_H, "fdiv.h", HINX>;
-def FSQRT_H : FPUnaryOp_r_frm<0b0101110, 0b00000, FPR16, FPR16, "fsqrt.h">,
- Sched<[WriteFSqrt16, ReadFSqrt16]>;
-def : FPUnaryOpDynFrmAlias<FSQRT_H, "fsqrt.h", FPR16, FPR16>;
+defm FSQRT_H : FPUnaryOp_r_frm_m<0b0101110, 0b00000, HHINX, "fsqrt.h">,
+ Sched<[WriteFSqrt16, ReadFSqrt16]>;
+defm : FPUnaryOpDynFrmAlias_m<FSQRT_H, "fsqrt.h", HHINX>;
let SchedRW = [WriteFSGNJ16, ReadFSGNJ16, ReadFSGNJ16],
mayRaiseFPException = 0 in {
-def FSGNJ_H : FPALU_rr<0b0010010, 0b000, "fsgnj.h", FPR16>;
-def FSGNJN_H : FPALU_rr<0b0010010, 0b001, "fsgnjn.h", FPR16>;
-def FSGNJX_H : FPALU_rr<0b0010010, 0b010, "fsgnjx.h", FPR16>;
+defm FSGNJ_H : FPALU_rr_m<0b0010010, 0b000, "fsgnj.h", HINX>;
+defm FSGNJN_H : FPALU_rr_m<0b0010010, 0b001, "fsgnjn.h", HINX>;
+defm FSGNJX_H : FPALU_rr_m<0b0010010, 0b010, "fsgnjx.h", HINX>;
}
let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in {
-def FMIN_H : FPALU_rr<0b0010110, 0b000, "fmin.h", FPR16>;
-def FMAX_H : FPALU_rr<0b0010110, 0b001, "fmax.h", FPR16>;
+defm FMIN_H : FPALU_rr_m<0b0010110, 0b000, "fmin.h", HINX>;
+defm FMAX_H : FPALU_rr_m<0b0010110, 0b001, "fmax.h", HINX>;
}
-def FCVT_W_H : FPUnaryOp_r_frm<0b1100010, 0b00000, GPR, FPR16, "fcvt.w.h">,
- Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_W_H, "fcvt.w.h", GPR, FPR16>;
-
-def FCVT_WU_H : FPUnaryOp_r_frm<0b1100010, 0b00001, GPR, FPR16, "fcvt.wu.h">,
+defm FCVT_W_H : FPUnaryOp_r_frm_m<0b1100010, 0b00000, XHINX, "fcvt.w.h">,
Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
-def : FPUnaryOpDynFrmAlias<FCVT_WU_H, "fcvt.wu.h", GPR, FPR16>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_W_H, "fcvt.w.h", XHINX>;
-def FCVT_H_W : FPUnaryOp_r_frm<0b1101010, 0b00000, FPR16, GPR, "fcvt.h.w">,
- Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
-def : FPUnaryOpDynFrmAlias<FCVT_H_W, "fcvt.h.w", FPR16, GPR>;
+defm FCVT_WU_H : FPUnaryOp_r_frm_m<0b1100010, 0b00001, XHINX, "fcvt.wu.h">,
+ Sched<[WriteFCvtF16ToI32, ReadFCvtF16ToI32]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_WU_H, "fcvt.wu.h", XHINX>;
-def FCVT_H_WU : FPUnaryOp_r_frm<0b1101010, 0b00001, FPR16, GPR, "fcvt.h.wu">,
+defm FCVT_H_W : FPUnaryOp_r_frm_m<0b1101010, 0b00000, HXINX, "fcvt.h.w">,
Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
-def : FPUnaryOpDynFrmAlias<FCVT_H_WU, "fcvt.h.wu", FPR16, GPR>;
-} // Predicates = [HasStdExtZfh]
+defm : FPUnaryOpDynFrmAlias_m<FCVT_H_W, "fcvt.h.w", HXINX>;
-let Predicates = [HasStdExtZfhOrZfhmin] in {
-def FCVT_H_S : FPUnaryOp_r_frm<0b0100010, 0b00000, FPR16, FPR32, "fcvt.h.s">,
- Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]>;
-def : FPUnaryOpDynFrmAlias<FCVT_H_S, "fcvt.h.s", FPR16, FPR32>;
+defm FCVT_H_WU : FPUnaryOp_r_frm_m<0b1101010, 0b00001, HXINX, "fcvt.h.wu">,
+ Sched<[WriteFCvtI32ToF16, ReadFCvtI32ToF16]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_H_WU, "fcvt.h.wu", HXINX>;
+
+defm FCVT_H_S : FPUnaryOp_r_frm_m<0b0100010, 0b00000, HFINXmin, "fcvt.h.s">,
+ Sched<[WriteFCvtF32ToF16, ReadFCvtF32ToF16]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_H_S, "fcvt.h.s", HFINXmin>;
-def FCVT_S_H : FPUnaryOp_r<0b0100000, 0b00010, 0b000, FPR32, FPR16, "fcvt.s.h">,
+defm FCVT_S_H : FPUnaryOp_r_m<0b0100000, 0b00010, 0b000, FHINXmin, "fcvt.s.h">,
Sched<[WriteFCvtF16ToF32, ReadFCvtF16ToF32]>;
+let Predicates = [HasStdExtZfhOrZfhmin] in {
let mayRaiseFPException = 0 in
def FMV_X_H : FPUnaryOp_r<0b1110010, 0b00000, 0b000, GPR, FPR16, "fmv.x.h">,
Sched<[WriteFMovF16ToI16, ReadFMovF16ToI16]>;
@@ -115,45 +170,38 @@ def FMV_H_X : FPUnaryOp_r<0b1111010, 0b00000, 0b000, FPR16, GPR, "fmv.h.x">,
Sched<[WriteFMovI16ToF16, ReadFMovI16ToF16]>;
} // Predicates = [HasStdExtZfhOrZfhmin]
-let Predicates = [HasStdExtZfh] in {
-
let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in {
-def FEQ_H : FPCmp_rr<0b1010010, 0b010, "feq.h", FPR16>;
-def FLT_H : FPCmp_rr<0b1010010, 0b001, "flt.h", FPR16>;
-def FLE_H : FPCmp_rr<0b1010010, 0b000, "fle.h", FPR16>;
+defm FEQ_H : FPCmp_rr_m<0b1010010, 0b010, "feq.h", HINX>;
+defm FLT_H : FPCmp_rr_m<0b1010010, 0b001, "flt.h", HINX>;
+defm FLE_H : FPCmp_rr_m<0b1010010, 0b000, "fle.h", HINX>;
}
let mayRaiseFPException = 0 in
-def FCLASS_H : FPUnaryOp_r<0b1110010, 0b00000, 0b001, GPR, FPR16, "fclass.h">,
- Sched<[WriteFClass16, ReadFClass16]>;
-} // Predicates = [HasStdExtZfh]
-
-let Predicates = [HasStdExtZfh, IsRV64] in {
-def FCVT_L_H : FPUnaryOp_r_frm<0b1100010, 0b00010, GPR, FPR16, "fcvt.l.h">,
- Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_L_H, "fcvt.l.h", GPR, FPR16>;
+defm FCLASS_H : FPUnaryOp_r_m<0b1110010, 0b00000, 0b001, XHINX, "fclass.h">,
+ Sched<[WriteFClass16, ReadFClass16]>;
-def FCVT_LU_H : FPUnaryOp_r_frm<0b1100010, 0b00011, GPR, FPR16, "fcvt.lu.h">,
+defm FCVT_L_H : FPUnaryOp_r_frm_m<0b1100010, 0b00010, XHIN64X, "fcvt.l.h">,
Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
-def : FPUnaryOpDynFrmAlias<FCVT_LU_H, "fcvt.lu.h", GPR, FPR16>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_L_H, "fcvt.l.h", XHIN64X>;
-def FCVT_H_L : FPUnaryOp_r_frm<0b1101010, 0b00010, FPR16, GPR, "fcvt.h.l">,
- Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
-def : FPUnaryOpDynFrmAlias<FCVT_H_L, "fcvt.h.l", FPR16, GPR>;
+defm FCVT_LU_H : FPUnaryOp_r_frm_m<0b1100010, 0b00011, XHIN64X, "fcvt.lu.h">,
+ Sched<[WriteFCvtF16ToI64, ReadFCvtF16ToI64]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_LU_H, "fcvt.lu.h", XHIN64X>;
-def FCVT_H_LU : FPUnaryOp_r_frm<0b1101010, 0b00011, FPR16, GPR, "fcvt.h.lu">,
+defm FCVT_H_L : FPUnaryOp_r_frm_m<0b1101010, 0b00010, HXIN64X, "fcvt.h.l">,
Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
-def : FPUnaryOpDynFrmAlias<FCVT_H_LU, "fcvt.h.lu", FPR16, GPR>;
-} // Predicates = [HasStdExtZfh, IsRV64]
+defm : FPUnaryOpDynFrmAlias_m<FCVT_H_L, "fcvt.h.l", HXIN64X>;
-let Predicates = [HasStdExtZfhOrZfhmin, HasStdExtD] in {
-def FCVT_H_D : FPUnaryOp_r_frm<0b0100010, 0b00001, FPR16, FPR64, "fcvt.h.d">,
- Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]>;
-def : FPUnaryOpDynFrmAlias<FCVT_H_D, "fcvt.h.d", FPR16, FPR64>;
+defm FCVT_H_LU : FPUnaryOp_r_frm_m<0b1101010, 0b00011, HXIN64X, "fcvt.h.lu">,
+ Sched<[WriteFCvtI64ToF16, ReadFCvtI64ToF16]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_H_LU, "fcvt.h.lu", HXIN64X>;
-def FCVT_D_H : FPUnaryOp_r<0b0100001, 0b00010, 0b000, FPR64, FPR16, "fcvt.d.h">,
- Sched<[WriteFCvtF16ToF64, ReadFCvtF16ToF64]>;
-} // Predicates = [HasStdExtZfhOrZfhmin, HasStdExtD]
+defm FCVT_H_D : FPUnaryOp_r_frm_m<0b0100010, 0b00001, HDINXmin, "fcvt.h.d">,
+ Sched<[WriteFCvtF64ToF16, ReadFCvtF64ToF16]>;
+defm : FPUnaryOpDynFrmAlias_m<FCVT_H_D, "fcvt.h.d", HDINXmin>;
+
+defm FCVT_D_H : FPUnaryOp_r_m<0b0100001, 0b00010, 0b000, DHINXmin, "fcvt.d.h">,
+ Sched<[WriteFCvtF16ToF64, ReadFCvtF16ToF64]>;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
@@ -186,6 +234,17 @@ def PseudoQuietFLT_H : PseudoQuietFCMP<FPR16>;
}
} // Predicates = [HasStdExtZfhOrZfhmin]
+let Predicates = [HasStdExtZhinx] in {
+def : InstAlias<"fmv.h $rd, $rs", (FSGNJ_H_INX FPR16INX:$rd, FPR16INX:$rs, FPR16INX:$rs)>;
+def : InstAlias<"fabs.h $rd, $rs", (FSGNJX_H_INX FPR16INX:$rd, FPR16INX:$rs, FPR16INX:$rs)>;
+def : InstAlias<"fneg.h $rd, $rs", (FSGNJN_H_INX FPR16INX:$rd, FPR16INX:$rs, FPR16INX:$rs)>;
+
+def : InstAlias<"fgt.h $rd, $rs, $rt",
+ (FLT_H_INX GPR:$rd, FPR16INX:$rt, FPR16INX:$rs), 0>;
+def : InstAlias<"fge.h $rd, $rs, $rt",
+ (FLE_H_INX GPR:$rd, FPR16INX:$rt, FPR16INX:$rs), 0>;
+} // Predicates = [HasStdExtZhinx]
+
//===----------------------------------------------------------------------===//
// Pseudo-instructions and codegen patterns
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index 8c1c03b51c24..b06af3787b5d 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -66,6 +66,7 @@ def sub_vrm1_5 : ComposedSubRegIndex<sub_vrm2_2, sub_vrm1_1>;
def sub_vrm1_6 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_0>;
def sub_vrm1_7 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_1>;
+def sub_32_hi : SubRegIndex<32, 32>;
} // Namespace = "RISCV"
// Integer registers
@@ -534,6 +535,35 @@ def VMV0 : RegisterClass<"RISCV", VMaskVTs, 64, (add V0)> {
let Size = 64;
}
+let RegInfos = XLenRI in {
+def GPRF16 : RegisterClass<"RISCV", [f16], 16, (add GPR)>;
+def GPRF32 : RegisterClass<"RISCV", [f32], 32, (add GPR)>;
+def GPRF64 : RegisterClass<"RISCV", [f64], 64, (add GPR)>;
+} // RegInfos = XLenRI
+
+let RegAltNameIndices = [ABIRegAltName] in {
+ foreach Index = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30] in {
+ defvar Reg = !cast<Register>("X"#Index);
+ def X#Index#_PD : RISCVRegWithSubRegs<Index, Reg.AsmName,
+ [!cast<Register>("X"#Index),
+ !cast<Register>("X"#!add(Index, 1))],
+ Reg.AltNames> {
+ let SubRegIndices = [sub_32, sub_32_hi];
+ }
+ }
+}
+
+let RegInfos = RegInfoByHwMode<[RV64], [RegInfo<64, 64, 64>]> in
+def GPRPF64 : RegisterClass<"RISCV", [f64], 64, (add
+ X10_PD, X12_PD, X14_PD, X16_PD,
+ X6_PD,
+ X28_PD, X30_PD,
+ X8_PD,
+ X18_PD, X20_PD, X22_PD, X24_PD, X26_PD,
+ X0_PD, X2_PD, X4_PD
+)>;
+
// The register class is added for inline assembly for vector mask types.
def VM : VReg<VMaskVTs,
(add (sequence "V%u", 8, 31),
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 34c6e8e684ac..c8237e60b4e4 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -83,6 +83,10 @@ private:
bool HasStdExtZve64d = false;
bool HasStdExtZfhmin = false;
bool HasStdExtZfh = false;
+ bool HasStdExtZfinx = false;
+ bool HasStdExtZdinx = false;
+ bool HasStdExtZhinxmin = false;
+ bool HasStdExtZhinx = false;
bool HasStdExtZbkb = false;
bool HasStdExtZbkc = false;
bool HasStdExtZbkx = false;
@@ -170,6 +174,10 @@ public:
bool hasStdExtZvl() const { return ZvlLen != ExtZvl::NotSet; }
bool hasStdExtZfhmin() const { return HasStdExtZfhmin; }
bool hasStdExtZfh() const { return HasStdExtZfh; }
+ bool hasStdExtZfinx() const { return HasStdExtZfinx; }
+ bool hasStdExtZdinx() const { return HasStdExtZdinx; }
+ bool hasStdExtZhinxmin() const { return HasStdExtZhinxmin; }
+ bool hasStdExtZhinx() const { return HasStdExtZhinx; }
bool hasStdExtZbkb() const { return HasStdExtZbkb; }
bool hasStdExtZbkc() const { return HasStdExtZbkc; }
bool hasStdExtZbkx() const { return HasStdExtZbkx; }
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index 380507308c3d..bafba2ee09c3 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -1169,6 +1169,8 @@ def ProcessorFeatures {
TuningFastBEXTR,
TuningFast15ByteNOP,
TuningBranchFusion,
+ TuningFastScalarFSQRT,
+ TuningFastVectorFSQRT,
TuningFastScalarShiftMasks,
TuningFastMOVBE,
TuningSlowSHLD,
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 51f2ced321bb..0971a0e33f98 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -99,7 +99,7 @@ bool X86FrameLowering::hasFP(const MachineFunction &MF) const {
MF.getInfo<X86MachineFunctionInfo>()->hasPreallocatedCall() ||
MF.callsUnwindInit() || MF.hasEHFunclets() || MF.callsEHReturn() ||
MFI.hasStackMap() || MFI.hasPatchPoint() ||
- MFI.hasCopyImplyingStackAdjustment());
+ (isWin64Prologue(MF) && MFI.hasCopyImplyingStackAdjustment()));
}
static unsigned getSUBriOpcode(bool IsLP64, int64_t Imm) {
@@ -1289,6 +1289,9 @@ bool X86FrameLowering::has128ByteRedZone(const MachineFunction& MF) const {
return Is64Bit && !IsWin64CC && !Fn.hasFnAttribute(Attribute::NoRedZone);
}
+/// Return true if we need to use the restricted Windows x64 prologue and
+/// epilogue code patterns that can be described with WinCFI (.seh_*
+/// directives).
bool X86FrameLowering::isWin64Prologue(const MachineFunction &MF) const {
return MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 90753b5b4d33..a1c387574ebb 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -33418,6 +33418,20 @@ bool X86TargetLowering::isNarrowingProfitable(EVT VT1, EVT VT2) const {
return !(VT1 == MVT::i32 && VT2 == MVT::i16);
}
+bool X86TargetLowering::shouldFoldSelectWithIdentityConstant(unsigned Opcode,
+ EVT VT) const {
+ // TODO: This is too general. There are cases where pre-AVX512 codegen would
+ // benefit. The transform may also be profitable for scalar code.
+ if (!Subtarget.hasAVX512())
+ return false;
+ if (!Subtarget.hasVLX() && !VT.is512BitVector())
+ return false;
+ if (!VT.isVector())
+ return false;
+
+ return true;
+}
+
/// Targets can use this to indicate that they only support *some*
/// VECTOR_SHUFFLE operations, those with specific masks.
/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
@@ -43108,38 +43122,6 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG,
}
}
- // If this extract is from a loaded vector value and will be used as an
- // integer, that requires a potentially expensive XMM -> GPR transfer.
- // Additionally, if we can convert to a scalar integer load, that will likely
- // be folded into a subsequent integer op.
- // Note: Unlike the related fold for this in DAGCombiner, this is not limited
- // to a single-use of the loaded vector. For the reasons above, we
- // expect this to be profitable even if it creates an extra load.
- bool LikelyUsedAsVector = any_of(N->uses(), [](SDNode *Use) {
- return Use->getOpcode() == ISD::STORE ||
- Use->getOpcode() == ISD::INSERT_VECTOR_ELT ||
- Use->getOpcode() == ISD::SCALAR_TO_VECTOR;
- });
- auto *LoadVec = dyn_cast<LoadSDNode>(InputVector);
- if (LoadVec && CIdx && ISD::isNormalLoad(LoadVec) && VT.isInteger() &&
- SrcVT.getVectorElementType() == VT && DCI.isAfterLegalizeDAG() &&
- !LikelyUsedAsVector) {
- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- SDValue NewPtr =
- TLI.getVectorElementPointer(DAG, LoadVec->getBasePtr(), SrcVT, EltIdx);
- unsigned PtrOff = VT.getSizeInBits() * CIdx->getZExtValue() / 8;
- MachinePointerInfo MPI = LoadVec->getPointerInfo().getWithOffset(PtrOff);
- Align Alignment = commonAlignment(LoadVec->getAlign(), PtrOff);
- SDValue Load =
- DAG.getLoad(VT, dl, LoadVec->getChain(), NewPtr, MPI, Alignment,
- LoadVec->getMemOperand()->getFlags(), LoadVec->getAAInfo());
- SDValue Chain = Load.getValue(1);
- SDValue From[] = {SDValue(N, 0), SDValue(LoadVec, 1)};
- SDValue To[] = {Load, Chain};
- DAG.ReplaceAllUsesOfValuesWith(From, To, 2);
- return SDValue(N, 0);
- }
-
return SDValue();
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 3f6d567d3f4d..50c7e2c319f6 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -1288,6 +1288,9 @@ namespace llvm {
/// from i32 to i8 but not from i32 to i16.
bool isNarrowingProfitable(EVT VT1, EVT VT2) const override;
+ bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode,
+ EVT VT) const override;
+
/// Given an intrinsic, checks if on the target the intrinsic will need to map
/// to a MemIntrinsicNode (touches memory). If this is the case, it returns
/// true and stores the intrinsic information into the IntrinsicInfo that was