[llvm] [Xtensa] Implement Xtensa Floating Point Option. (PR #136086)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 16 23:30:10 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-xtensa
Author: Andrei Safronov (andreisfr)
<details>
<summary>Changes</summary>
---
Patch is 55.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136086.diff
14 Files Affected:
- (modified) llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp (+38)
- (modified) llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp (+5)
- (modified) llvm/lib/Target/Xtensa/XtensaCallingConv.td (+1)
- (modified) llvm/lib/Target/Xtensa/XtensaFeatures.td (+5)
- (modified) llvm/lib/Target/Xtensa/XtensaISelLowering.cpp (+167-1)
- (modified) llvm/lib/Target/Xtensa/XtensaISelLowering.h (+23)
- (modified) llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp (+9-5)
- (modified) llvm/lib/Target/Xtensa/XtensaInstrInfo.td (+291)
- (modified) llvm/lib/Target/Xtensa/XtensaOperators.td (+17)
- (modified) llvm/lib/Target/Xtensa/XtensaRegisterInfo.td (+44)
- (modified) llvm/lib/Target/Xtensa/XtensaSubtarget.h (+1)
- (added) llvm/test/CodeGen/Xtensa/float-arith.ll (+569)
- (added) llvm/test/MC/Xtensa/float-err.s (+37)
- (added) llvm/test/MC/Xtensa/float.s (+177)
``````````diff
diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
index 6b355e6363b22..237aed3cc71ea 100644
--- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
+++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp
@@ -113,6 +113,44 @@ static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}
+static const unsigned FPRDecoderTable[] = {
+ Xtensa::F0, Xtensa::F1, Xtensa::F2, Xtensa::F3, Xtensa::F4, Xtensa::F5,
+ Xtensa::F6, Xtensa::F7, Xtensa::F8, Xtensa::F9, Xtensa::F10, Xtensa::F11,
+ Xtensa::F12, Xtensa::F13, Xtensa::F14, Xtensa::F15};
+
+static DecodeStatus DecodeFPRRegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo >= std::size(FPRDecoderTable))
+ return MCDisassembler::Fail;
+
+ unsigned Reg = FPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static const unsigned URDecoderTable[] = {Xtensa::FCR, 232, Xtensa::FSR, 233};
+
+static DecodeStatus DecodeURRegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ const llvm::MCSubtargetInfo STI =
+ ((const MCDisassembler *)Decoder)->getSubtargetInfo();
+
+ if (RegNo > 255)
+ return MCDisassembler::Fail;
+
+ for (unsigned i = 0; i < std::size(URDecoderTable); i += 2) {
+ if (URDecoderTable[i + 1] == RegNo) {
+ unsigned Reg = URDecoderTable[i];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+ }
+ }
+
+ return MCDisassembler::Fail;
+}
+
const MCPhysReg SRDecoderTable[] = {
Xtensa::SAR, 3, Xtensa::ACCLO, 16, Xtensa::ACCHI, 17,
Xtensa::M0, 32, Xtensa::M1, 33, Xtensa::M2, 34,
diff --git a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
index 8231a8a9a44d4..03b3ed0c121be 100644
--- a/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp
@@ -307,6 +307,11 @@ XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
case Xtensa::L32I:
case Xtensa::S32I_N:
case Xtensa::L32I_N:
+ case Xtensa::SSI:
+ case Xtensa::SSIP:
+ case Xtensa::LSI:
+ case Xtensa::LSIP:
+
if (Res & 0x3) {
report_fatal_error("Unexpected operand value!");
}
diff --git a/llvm/lib/Target/Xtensa/XtensaCallingConv.td b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
index 2c48f8f86cafb..96528ed283a30 100644
--- a/llvm/lib/Target/Xtensa/XtensaCallingConv.td
+++ b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
@@ -15,6 +15,7 @@
def RetCC_Xtensa : CallingConv<[
// First two return values go in a2, a3, a4, a5
CCIfType<[i32], CCAssignToReg<[A2, A3, A4, A5]>>,
+ CCIfType<[f32], CCAssignToReg<[A2, A3, A4, A5]>>,
CCIfType<[i64], CCAssignToRegWithShadow<[A2, A4], [A3, A5]>>
]>;
diff --git a/llvm/lib/Target/Xtensa/XtensaFeatures.td b/llvm/lib/Target/Xtensa/XtensaFeatures.td
index 8b2d351dae386..9515bbc8830b4 100644
--- a/llvm/lib/Target/Xtensa/XtensaFeatures.td
+++ b/llvm/lib/Target/Xtensa/XtensaFeatures.td
@@ -8,6 +8,11 @@ def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
def HasDensity : Predicate<"Subtarget->hasDensity()">,
AssemblerPredicate<(all_of FeatureDensity)>;
+def FeatureSingleFloat : SubtargetFeature<"fp", "HasSingleFloat", "true",
+ "Enable Xtensa Single FP instructions">;
+def HasSingleFloat : Predicate<"Subtarget->hasSingleFloat()">,
+ AssemblerPredicate<(all_of FeatureSingleFloat)>;
+
def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
"Enable Xtensa Windowed Register option">;
def HasWindowed : Predicate<"Subtarget->hasWindowed()">,
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 9ba87cf6d5878..8224b5e140f9f 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -58,6 +58,10 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
// Set up the register classes.
addRegisterClass(MVT::i32, &Xtensa::ARRegClass);
+ if (Subtarget.hasSingleFloat()) {
+ addRegisterClass(MVT::f32, &Xtensa::FPRRegClass);
+ }
+
if (Subtarget.hasBoolean()) {
addRegisterClass(MVT::v1i1, &Xtensa::BRRegClass);
}
@@ -71,6 +75,8 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::Constant, MVT::i32, Custom);
setOperationAction(ISD::Constant, MVT::i64, Expand);
+ setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
+ setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
setBooleanContents(ZeroOrOneBooleanContent);
@@ -108,7 +114,10 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SELECT, MVT::i32, Expand);
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+ setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
+
setOperationAction(ISD::SETCC, MVT::i32, Expand);
+ setOperationAction(ISD::SETCC, MVT::f32, Expand);
setCondCodeAction(ISD::SETGT, MVT::i32, Expand);
setCondCodeAction(ISD::SETLE, MVT::i32, Expand);
@@ -157,6 +166,103 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::VACOPY, MVT::Other, Custom);
setOperationAction(ISD::VAEND, MVT::Other, Expand);
+ // Handle floating-point types.
+ for (unsigned I = MVT::FIRST_FP_VALUETYPE; I <= MVT::LAST_FP_VALUETYPE; ++I) {
+ MVT VT = MVT::SimpleValueType(I);
+ if (isTypeLegal(VT)) {
+ // We can use FI for FRINT.
+ // setOperationAction(ISD::FRINT, VT, Legal);
+ if (VT.getSizeInBits() == 32 && Subtarget.hasSingleFloat()) {
+ setOperationAction(ISD::FABS, VT, Legal);
+ setOperationAction(ISD::FADD, VT, Legal);
+ setOperationAction(ISD::FSUB, VT, Legal);
+ setOperationAction(ISD::FMA, VT, Legal);
+ setOperationAction(ISD::FMUL, VT, Legal);
+ setOperationAction(ISD::FNEG, VT, Legal);
+ } else {
+ setOperationAction(ISD::FABS, VT, Expand);
+ setOperationAction(ISD::FADD, VT, Expand);
+ setOperationAction(ISD::FSUB, VT, Expand);
+ setOperationAction(ISD::FMA, VT, Expand);
+ setOperationAction(ISD::FMUL, VT, Expand);
+ setOperationAction(ISD::FNEG, VT, Expand);
+ }
+
+ // TODO: once implemented in InstrInfo uncomment
+ setOperationAction(ISD::FSQRT, VT, Expand);
+
+ // No special instructions for these.
+ setOperationAction(ISD::FCBRT, VT, Expand);
+ setOperationAction(ISD::FCEIL, VT, Expand);
+ setOperationAction(ISD::FSIN, VT, Expand);
+ setOperationAction(ISD::FCOS, VT, Expand);
+ setOperationAction(ISD::FREM, VT, Expand);
+ setOperationAction(ISD::FDIV, VT, Expand);
+ setOperationAction(ISD::FEXP, VT, Expand);
+ setOperationAction(ISD::FEXP2, VT, Expand);
+ setOperationAction(ISD::FFLOOR, VT, Expand);
+ setOperationAction(ISD::FLOG, VT, Expand);
+ setOperationAction(ISD::FLOG2, VT, Expand);
+ setOperationAction(ISD::FLOG10, VT, Expand);
+ setOperationAction(ISD::FMAXIMUM, VT, Expand);
+ setOperationAction(ISD::FMINIMUM, VT, Expand);
+ setOperationAction(ISD::FMAXNUM, VT, Expand);
+ setOperationAction(ISD::FMINNUM, VT, Expand);
+ setOperationAction(ISD::FNEARBYINT, VT, Expand);
+ setOperationAction(ISD::FPOW, VT, Expand);
+ setOperationAction(ISD::FPOWI, VT, Expand);
+ setOperationAction(ISD::FRINT, VT, Expand);
+ setOperationAction(ISD::FROUND, VT, Expand);
+ setOperationAction(ISD::FSINCOS, VT, Expand);
+ setOperationAction(ISD::FSQRT, VT, Expand);
+ setOperationAction(ISD::FTRUNC, VT, Expand);
+ setOperationAction(ISD::LLRINT, VT, Expand);
+ setOperationAction(ISD::LLROUND, VT, Expand);
+ setOperationAction(ISD::LRINT, VT, Expand);
+ setOperationAction(ISD::LROUND, VT, Expand);
+ }
+ }
+
+ // Handle floating-point types.
+ if (Subtarget.hasSingleFloat()) {
+ setOperationAction(ISD::BITCAST, MVT::i32, Legal);
+ setOperationAction(ISD::BITCAST, MVT::f32, Legal);
+ setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
+ setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
+ setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
+ setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
+
+ setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
+ setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
+ setCondCodeAction(ISD::SETONE, MVT::f32, Expand);
+ setCondCodeAction(ISD::SETUGE, MVT::f32, Expand);
+ setCondCodeAction(ISD::SETUGT, MVT::f32, Expand);
+ } else {
+ setOperationAction(ISD::BITCAST, MVT::i32, Expand);
+ setOperationAction(ISD::BITCAST, MVT::f32, Expand);
+ setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
+ setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
+ setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
+ setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand);
+ }
+ setOperationAction(ISD::FMA, MVT::f64, Expand);
+ setOperationAction(ISD::SETCC, MVT::f64, Expand);
+ setOperationAction(ISD::BITCAST, MVT::i64, Expand);
+ setOperationAction(ISD::BITCAST, MVT::f64, Expand);
+ setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
+ setOperationAction(ISD::SINT_TO_FP, MVT::i64, Expand);
+ setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
+ setOperationAction(ISD::FP_TO_SINT, MVT::i64, Expand);
+
+ // Needed so that we don't try to implement f128 constant loads using
+ // a load-and-extend of a f80 constant (in cases where the constant
+ // would fit in an f80).
+ for (MVT VT : MVT::fp_valuetypes())
+ setLoadExtAction(ISD::EXTLOAD, VT, MVT::f80, Expand);
+
+ // Floating-point truncation and stores need to be done separately.
+ setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+
// Compute derived properties from the register classes
computeRegisterProperties(STI.getRegisterInfo());
}
@@ -167,6 +273,11 @@ bool XtensaTargetLowering::isOffsetFoldingLegal(
return false;
}
+bool XtensaTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const {
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Inline asm support
//===----------------------------------------------------------------------===//
@@ -317,6 +428,16 @@ static bool CC_Xtensa_Custom(unsigned ValNo, MVT ValVT, MVT LocVT,
return false;
}
+/// Return the register type for a given MVT
+MVT XtensaTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
+ CallingConv::ID CC,
+ EVT VT) const {
+ if (VT.isFloatingPoint())
+ return MVT::i32;
+
+ return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
+}
+
CCAssignFn *XtensaTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
bool IsVarArg) const {
return CC_Xtensa_Custom;
@@ -797,6 +918,21 @@ SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
return Op;
}
+SDValue XtensaTargetLowering::LowerImmediateFP(SDValue Op,
+ SelectionDAG &DAG) const {
+ const ConstantFPSDNode *CN = cast<ConstantFPSDNode>(Op);
+ SDLoc DL(CN);
+ APFloat apval = CN->getValueAPF();
+ int64_t value = llvm::bit_cast<uint32_t>(CN->getValueAPF().convertToFloat());
+ if (Op.getValueType() == MVT::f32) {
+ Type *Ty = Type::getInt32Ty(*DAG.getContext());
+ Constant *CV = ConstantInt::get(Ty, value);
+ SDValue CP = DAG.getConstantPool(CV, MVT::i32);
+ return DAG.getNode(ISD::BITCAST, DL, MVT::f32, CP);
+ }
+ return Op;
+}
+
SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
@@ -1230,6 +1366,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
return LowerBR_JT(Op, DAG);
case ISD::Constant:
return LowerImmediate(Op, DAG);
+ case ISD::ConstantFP:
+ return LowerImmediateFP(Op, DAG);
case ISD::RETURNADDR:
return LowerRETURNADDR(Op, DAG);
case ISD::GlobalAddress:
@@ -1293,6 +1431,26 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "XtensaISD::SRCL";
case XtensaISD::SRCR:
return "XtensaISD::SRCR";
+ case XtensaISD::CMPUO:
+ return "XtensaISD::CMPUO";
+ case XtensaISD::CMPUEQ:
+ return "XtensaISD::CMPUEQ";
+ case XtensaISD::CMPULE:
+ return "XtensaISD::CMPULE";
+ case XtensaISD::CMPULT:
+ return "XtensaISD::CMPULT";
+ case XtensaISD::CMPOEQ:
+ return "XtensaISD::CMPOEQ";
+ case XtensaISD::CMPOLE:
+ return "XtensaISD::CMPOLE";
+ case XtensaISD::CMPOLT:
+ return "XtensaISD::CMPOLT";
+ case XtensaISD::MADD:
+ return "XtensaISD::MADD";
+ case XtensaISD::MSUB:
+ return "XtensaISD::MSUB";
+ case XtensaISD::MOVS:
+ return "XtensaISD::MOVS";
}
return nullptr;
}
@@ -1377,11 +1535,19 @@ MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
case Xtensa::S16I:
case Xtensa::S32I:
case Xtensa::S32I_N:
+ case Xtensa::SSI:
+ case Xtensa::SSIP:
+ case Xtensa::SSX:
+ case Xtensa::SSXP:
case Xtensa::L8UI:
case Xtensa::L16SI:
case Xtensa::L16UI:
case Xtensa::L32I:
- case Xtensa::L32I_N: {
+ case Xtensa::L32I_N:
+ case Xtensa::LSI:
+ case Xtensa::LSIP:
+ case Xtensa::LSX:
+ case Xtensa::LSXP: {
// Insert memory wait instruction "memw" before volatile load/store as it is
// implemented in gcc. If memoperands is empty then assume that it aslo
// maybe volatile load/store and insert "memw".
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index c7d4f41b1f08e..850ec6f3b023a 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -56,6 +56,21 @@ enum {
SRCL,
// Shift Right Combined
SRCR,
+
+ // Floating point unordered compare conditions
+ CMPUEQ,
+ CMPULE,
+ CMPULT,
+ CMPUO,
+ // Floating point compare conditions
+ CMPOEQ,
+ CMPOLE,
+ CMPOLT,
+ // FP multipy-add/sub
+ MADD,
+ MSUB,
+ // FP move
+ MOVS,
};
}
@@ -70,6 +85,9 @@ class XtensaTargetLowering : public TargetLowering {
return LHSTy.getSizeInBits() <= 32 ? MVT::i32 : MVT::i64;
}
+ MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
+ EVT VT) const override;
+
EVT getSetCCResultType(const DataLayout &, LLVMContext &,
EVT VT) const override {
if (!VT.isVector())
@@ -81,6 +99,9 @@ class XtensaTargetLowering : public TargetLowering {
const char *getTargetNodeName(unsigned Opcode) const override;
+ bool isFPImmLegal(const APFloat &Imm, EVT VT,
+ bool ForCodeSize) const override;
+
std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
StringRef Constraint, MVT VT) const override;
@@ -133,6 +154,8 @@ class XtensaTargetLowering : public TargetLowering {
SDValue LowerImmediate(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerImmediateFP(SDValue Op, SelectionDAG &DAG) const;
+
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 005532b864c41..5b1bc73267157 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -151,11 +151,15 @@ void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
unsigned &LoadOpcode,
unsigned &StoreOpcode,
int64_t offset) const {
- assert((RC == &Xtensa::ARRegClass) &&
- "Unsupported regclass to load or store");
-
- LoadOpcode = Xtensa::L32I;
- StoreOpcode = Xtensa::S32I;
+ if (RC == &Xtensa::ARRegClass) {
+ LoadOpcode = Xtensa::L32I;
+ StoreOpcode = Xtensa::S32I;
+ } else if (RC == &Xtensa::FPRRegClass) {
+ LoadOpcode = Xtensa::LSI;
+ StoreOpcode = Xtensa::SSI;
+ } else {
+ llvm_unreachable("Unsupported regclass to load or store");
+ }
}
void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 9734e914db335..b0b0cb1bb61de 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -956,6 +956,297 @@ def LOOPNEZ : RRI8_Inst<0x06, (outs), (ins AR:$s, ltarget:$target),
def : InstAlias<"_loopnez\t$s, $target", (LOOPNEZ AR:$s, ltarget:$target)>;
+//===----------------------------------------------------------------------===//
+// Floating-Point Instructions
+//===----------------------------------------------------------------------===//
+
+class FPArith_RRR<bits<4> oper2, bits<4> oper1, string instrAsm,
+ SDPatternOperator opNode, bit isComm = 0>
+ : RRR_Inst<0x00, oper1, oper2, (outs FPR:$r), (ins FPR:$s, FPR:$t),
+ instrAsm#"\t$r, $s, $t",
+ [(set FPR:$r, (opNode FPR:$s, FPR:$t))]> {
+ let isCommutable = isComm;
+ let isReMaterializable = 0;
+ let Predicates = [HasSingleFloat];
+}
+
+def ADD_S : FPArith_RRR<0x00, 0x0A, "add.s", fadd, 1>;
+def SUB_S : FPArith_RRR<0x01, 0x0A, "sub.s", fsub>;
+def MUL_S : FPArith_RRR<0x02, 0x0A, "mul.s", fmul, 1>;
+
+// FP load instructions
+let mayLoad = 1, usesCustomInserter = 1, Predicates = [HasSingleFloat] in {
+ def LSI : RRI8_Inst<0x03, (outs FPR:$t), (ins mem32:$addr),
+ "lsi\t$t, $addr", []> {
+ bits<12> addr;
+
+ let r = 0x00;
+ let imm8{7-0} = addr{11-4};
+ let s{3-0} = addr{3-0};
+ }
+
+ def LSIP : RRI8_Inst<0x03, (outs FPR:$t), (ins mem32:$addr),
+ "lsip\t$t, $addr", []> {
+ bits<12> addr;
+
+ let r = 0x08;
+ let imm8{7-0} = addr{11-4};
+ let s{3-0} = addr{3-0};
+ }
+
+ def LSX : RRR_Inst<0x00, 0x08, 0x00, (outs), (ins FPR:$r, AR:$s, AR:$t),
+ "lsx\t$r, $s, $t", []>;
+
+ def LSXP : RRR_Inst<0x00, 0x08, 0x01, (outs), (ins FPR:$r, AR:$s, AR:$t),
+ "lsxp\t$r, $s, $t", []>;
+}
+
+def : Pat<(f32 (load addr_ish4:$addr)), (f32 (LSI mem32:$addr))>;
+
+// FP store instructions
+let mayStore = 1, usesCustomInserter = 1, Predicates = [HasSingleFloat] in {
+ def SSI : RRI8_Inst<0x03, (outs), (ins FPR:$t, mem32:$addr),
+ "ssi\t$t, $addr", []> {
+ bits<12> addr;
+
+ let r = 0x04;
+ let imm8{7-0} = addr{11-4};
+ let s{3-0} = addr{3-0};
+ }
+
+ def SSIP : RRI8_Inst<0x03, (outs), (ins FPR:$t, mem32:$addr),
+ "ssip\t$t, $addr", []> {
+ bits<12> addr;
+
+ let r = 0x0C;
+ let imm8{7-0} = addr{11-4};
+ let s{3-0} = addr{3-0};
+ }
+
+ def SSX: RRR_Inst<0x00, 0x08, 0x04, (outs), (ins FPR:$r, AR:$s, AR:$t),
+ "ssx\t$r, $s, $t", []>;
+
+ def SSXP: RRR_Inst<0x00, 0x08, 0x05, (outs), (ins FPR:$r, AR:$s, AR:$t),
+ "ssxp\t$r, $s, $t", []>;
+}
+
+def : Pat<(store FPR:$t, addr_ish4:$addr), (SSI FPR:$t, mem32:$addr)>;
+
+// FP compare instructions
+let isCompare = 1, Predicates = [HasSingleFloat] in {
+ class FCompare <bits<4> oper2, bits<4> oper1, string instrAsm,
+ SDPatternOperator opNode, bit isComm = 0>
+ : RRR_Inst<0x00, oper1, oper2, (outs BR:$r), (ins FPR:$s, FPR:$t),
+ instrAsm#"\t$r, $s, $t",
+ [(set BR:$r, (opNode FPR:$s, FPR:$t))]> {
+ let isCommutable = isComm;
+ let isReMaterializable = 0;
+ let Predicates = [Has...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/136086
More information about the llvm-commits
mailing list