diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 53 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/SVEInstrFormats.td | 25 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 35 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp | 32 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCV.td | 37 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVFrameLowering.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp | 36 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoD.td | 209 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoF.td | 275 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td | 207 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 30 | ||||
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVSubtarget.h | 8 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86.td | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 46 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.h | 3 |
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 |
