-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[Xtensa] Implement Xtensa Floating Point Option. #136086
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-mc @llvm/pr-subscribers-backend-xtensa Author: Andrei Safronov (andreisfr) ChangesPatch is 55.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136086.diff 14 Files Affected:
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]
|
41853e4
to
94b8fbe
Compare
@@ -113,6 +113,44 @@ static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo, | |||
return MCDisassembler::Success; | |||
} | |||
|
|||
static const unsigned FPRDecoderTable[] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static const unsigned FPRDecoderTable[] = { | |
static const MCPhysReg FPRDecoderTable[] = { |
if (RegNo >= std::size(FPRDecoderTable)) | ||
return MCDisassembler::Fail; | ||
|
||
unsigned Reg = FPRDecoderTable[RegNo]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unsigned Reg = FPRDecoderTable[RegNo]; | |
MCPhysReg Reg = FPRDecoderTable[RegNo]; |
@@ -175,6 +184,103 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM, | |||
setOperationAction(ISD::VACOPY, MVT::Other, Custom); | |||
setOperationAction(ISD::VAEND, MVT::Other, Expand); | |||
|
|||
// Handle floating-point types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mostly reinventing the default logic based on legal types
bool XtensaTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, | ||
bool ForCodeSize) const { | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is redundant if you make ConstantFP Expand
@@ -815,6 +936,21 @@ SDValue XtensaTargetLowering::LowerImmediate(SDValue Op, | |||
return Op; | |||
} | |||
|
|||
SDValue XtensaTargetLowering::LowerImmediateFP(SDValue Op, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the same as the default expansion?
|
||
declare float @llvm.fabs.f32(float) | ||
|
||
define float @fabs_s(float %a, float %b) nounwind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing fneg and copysign tests
; XTENSA-NEXT: add.s f8, f9, f8 | ||
; XTENSA-NEXT: rfr a2, f8 | ||
; XTENSA-NEXT: ret | ||
%1 = fadd float %a, %b |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use named values in tests
setOperationAction(ISD::ConstantFP, MVT::f32, Custom); | ||
setOperationAction(ISD::ConstantFP, MVT::f64, Expand); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The custom looks the same as default expand
No description provided.