Skip to content

Commit 94b8fbe

Browse files
committed
[Xtensa] Implement Xtensa Floating Point Option.
1 parent 886f119 commit 94b8fbe

14 files changed

+1384
-6
lines changed

llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,44 @@ static DecodeStatus DecodeMR23RegisterClass(MCInst &Inst, uint64_t RegNo,
113113
return MCDisassembler::Success;
114114
}
115115

116+
static const unsigned FPRDecoderTable[] = {
117+
Xtensa::F0, Xtensa::F1, Xtensa::F2, Xtensa::F3, Xtensa::F4, Xtensa::F5,
118+
Xtensa::F6, Xtensa::F7, Xtensa::F8, Xtensa::F9, Xtensa::F10, Xtensa::F11,
119+
Xtensa::F12, Xtensa::F13, Xtensa::F14, Xtensa::F15};
120+
121+
static DecodeStatus DecodeFPRRegisterClass(MCInst &Inst, uint64_t RegNo,
122+
uint64_t Address,
123+
const void *Decoder) {
124+
if (RegNo >= std::size(FPRDecoderTable))
125+
return MCDisassembler::Fail;
126+
127+
unsigned Reg = FPRDecoderTable[RegNo];
128+
Inst.addOperand(MCOperand::createReg(Reg));
129+
return MCDisassembler::Success;
130+
}
131+
132+
static const unsigned URDecoderTable[] = {Xtensa::FCR, 232, Xtensa::FSR, 233};
133+
134+
static DecodeStatus DecodeURRegisterClass(MCInst &Inst, uint64_t RegNo,
135+
uint64_t Address,
136+
const void *Decoder) {
137+
const llvm::MCSubtargetInfo STI =
138+
((const MCDisassembler *)Decoder)->getSubtargetInfo();
139+
140+
if (RegNo > 255)
141+
return MCDisassembler::Fail;
142+
143+
for (unsigned i = 0; i < std::size(URDecoderTable); i += 2) {
144+
if (URDecoderTable[i + 1] == RegNo) {
145+
unsigned Reg = URDecoderTable[i];
146+
Inst.addOperand(MCOperand::createReg(Reg));
147+
return MCDisassembler::Success;
148+
}
149+
}
150+
151+
return MCDisassembler::Fail;
152+
}
153+
116154
const MCPhysReg SRDecoderTable[] = {
117155
Xtensa::SAR, 3, Xtensa::ACCLO, 16, Xtensa::ACCHI, 17,
118156
Xtensa::M0, 32, Xtensa::M1, 33, Xtensa::M2, 34,

llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCCodeEmitter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,11 @@ XtensaMCCodeEmitter::getMemRegEncoding(const MCInst &MI, unsigned OpNo,
307307
case Xtensa::L32I:
308308
case Xtensa::S32I_N:
309309
case Xtensa::L32I_N:
310+
case Xtensa::SSI:
311+
case Xtensa::SSIP:
312+
case Xtensa::LSI:
313+
case Xtensa::LSIP:
314+
310315
if (Res & 0x3) {
311316
report_fatal_error("Unexpected operand value!");
312317
}

llvm/lib/Target/Xtensa/XtensaCallingConv.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
def RetCC_Xtensa : CallingConv<[
1616
// First two return values go in a2, a3, a4, a5
1717
CCIfType<[i32], CCAssignToReg<[A2, A3, A4, A5]>>,
18+
CCIfType<[f32], CCAssignToReg<[A2, A3, A4, A5]>>,
1819
CCIfType<[i64], CCAssignToRegWithShadow<[A2, A4], [A3, A5]>>
1920
]>;
2021

llvm/lib/Target/Xtensa/XtensaFeatures.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ def FeatureDensity : SubtargetFeature<"density", "HasDensity", "true",
88
def HasDensity : Predicate<"Subtarget->hasDensity()">,
99
AssemblerPredicate<(all_of FeatureDensity)>;
1010

11+
def FeatureSingleFloat : SubtargetFeature<"fp", "HasSingleFloat", "true",
12+
"Enable Xtensa Single FP instructions">;
13+
def HasSingleFloat : Predicate<"Subtarget->hasSingleFloat()">,
14+
AssemblerPredicate<(all_of FeatureSingleFloat)>;
15+
1116
def FeatureWindowed : SubtargetFeature<"windowed", "HasWindowed", "true",
1217
"Enable Xtensa Windowed Register option">;
1318
def HasWindowed : Predicate<"Subtarget->hasWindowed()">,

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
5858
// Set up the register classes.
5959
addRegisterClass(MVT::i32, &Xtensa::ARRegClass);
6060

61+
if (Subtarget.hasSingleFloat()) {
62+
addRegisterClass(MVT::f32, &Xtensa::FPRRegClass);
63+
}
64+
6165
if (Subtarget.hasBoolean()) {
6266
addRegisterClass(MVT::v1i1, &Xtensa::BRRegClass);
6367
}
@@ -71,6 +75,8 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
7175

7276
setOperationAction(ISD::Constant, MVT::i32, Custom);
7377
setOperationAction(ISD::Constant, MVT::i64, Expand);
78+
setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
79+
setOperationAction(ISD::ConstantFP, MVT::f64, Expand);
7480

7581
setBooleanContents(ZeroOrOneBooleanContent);
7682

@@ -108,7 +114,10 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
108114

109115
setOperationAction(ISD::SELECT, MVT::i32, Expand);
110116
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
117+
setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
118+
111119
setOperationAction(ISD::SETCC, MVT::i32, Expand);
120+
setOperationAction(ISD::SETCC, MVT::f32, Expand);
112121

113122
setCondCodeAction(ISD::SETGT, MVT::i32, Expand);
114123
setCondCodeAction(ISD::SETLE, MVT::i32, Expand);
@@ -175,6 +184,103 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
175184
setOperationAction(ISD::VACOPY, MVT::Other, Custom);
176185
setOperationAction(ISD::VAEND, MVT::Other, Expand);
177186

187+
// Handle floating-point types.
188+
for (unsigned I = MVT::FIRST_FP_VALUETYPE; I <= MVT::LAST_FP_VALUETYPE; ++I) {
189+
MVT VT = MVT::SimpleValueType(I);
190+
if (isTypeLegal(VT)) {
191+
// We can use FI for FRINT.
192+
// setOperationAction(ISD::FRINT, VT, Legal);
193+
if (VT.getSizeInBits() == 32 && Subtarget.hasSingleFloat()) {
194+
setOperationAction(ISD::FABS, VT, Legal);
195+
setOperationAction(ISD::FADD, VT, Legal);
196+
setOperationAction(ISD::FSUB, VT, Legal);
197+
setOperationAction(ISD::FMA, VT, Legal);
198+
setOperationAction(ISD::FMUL, VT, Legal);
199+
setOperationAction(ISD::FNEG, VT, Legal);
200+
} else {
201+
setOperationAction(ISD::FABS, VT, Expand);
202+
setOperationAction(ISD::FADD, VT, Expand);
203+
setOperationAction(ISD::FSUB, VT, Expand);
204+
setOperationAction(ISD::FMA, VT, Expand);
205+
setOperationAction(ISD::FMUL, VT, Expand);
206+
setOperationAction(ISD::FNEG, VT, Expand);
207+
}
208+
209+
// TODO: once implemented in InstrInfo uncomment
210+
setOperationAction(ISD::FSQRT, VT, Expand);
211+
212+
// No special instructions for these.
213+
setOperationAction(ISD::FCBRT, VT, Expand);
214+
setOperationAction(ISD::FCEIL, VT, Expand);
215+
setOperationAction(ISD::FSIN, VT, Expand);
216+
setOperationAction(ISD::FCOS, VT, Expand);
217+
setOperationAction(ISD::FREM, VT, Expand);
218+
setOperationAction(ISD::FDIV, VT, Expand);
219+
setOperationAction(ISD::FEXP, VT, Expand);
220+
setOperationAction(ISD::FEXP2, VT, Expand);
221+
setOperationAction(ISD::FFLOOR, VT, Expand);
222+
setOperationAction(ISD::FLOG, VT, Expand);
223+
setOperationAction(ISD::FLOG2, VT, Expand);
224+
setOperationAction(ISD::FLOG10, VT, Expand);
225+
setOperationAction(ISD::FMAXIMUM, VT, Expand);
226+
setOperationAction(ISD::FMINIMUM, VT, Expand);
227+
setOperationAction(ISD::FMAXNUM, VT, Expand);
228+
setOperationAction(ISD::FMINNUM, VT, Expand);
229+
setOperationAction(ISD::FNEARBYINT, VT, Expand);
230+
setOperationAction(ISD::FPOW, VT, Expand);
231+
setOperationAction(ISD::FPOWI, VT, Expand);
232+
setOperationAction(ISD::FRINT, VT, Expand);
233+
setOperationAction(ISD::FROUND, VT, Expand);
234+
setOperationAction(ISD::FSINCOS, VT, Expand);
235+
setOperationAction(ISD::FSQRT, VT, Expand);
236+
setOperationAction(ISD::FTRUNC, VT, Expand);
237+
setOperationAction(ISD::LLRINT, VT, Expand);
238+
setOperationAction(ISD::LLROUND, VT, Expand);
239+
setOperationAction(ISD::LRINT, VT, Expand);
240+
setOperationAction(ISD::LROUND, VT, Expand);
241+
}
242+
}
243+
244+
// Handle floating-point types.
245+
if (Subtarget.hasSingleFloat()) {
246+
setOperationAction(ISD::BITCAST, MVT::i32, Legal);
247+
setOperationAction(ISD::BITCAST, MVT::f32, Legal);
248+
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
249+
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
250+
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
251+
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
252+
253+
setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
254+
setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
255+
setCondCodeAction(ISD::SETONE, MVT::f32, Expand);
256+
setCondCodeAction(ISD::SETUGE, MVT::f32, Expand);
257+
setCondCodeAction(ISD::SETUGT, MVT::f32, Expand);
258+
} else {
259+
setOperationAction(ISD::BITCAST, MVT::i32, Expand);
260+
setOperationAction(ISD::BITCAST, MVT::f32, Expand);
261+
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
262+
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
263+
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
264+
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand);
265+
}
266+
setOperationAction(ISD::FMA, MVT::f64, Expand);
267+
setOperationAction(ISD::SETCC, MVT::f64, Expand);
268+
setOperationAction(ISD::BITCAST, MVT::i64, Expand);
269+
setOperationAction(ISD::BITCAST, MVT::f64, Expand);
270+
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
271+
setOperationAction(ISD::SINT_TO_FP, MVT::i64, Expand);
272+
setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
273+
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Expand);
274+
275+
// Needed so that we don't try to implement f128 constant loads using
276+
// a load-and-extend of a f80 constant (in cases where the constant
277+
// would fit in an f80).
278+
for (MVT VT : MVT::fp_valuetypes())
279+
setLoadExtAction(ISD::EXTLOAD, VT, MVT::f80, Expand);
280+
281+
// Floating-point truncation and stores need to be done separately.
282+
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
283+
178284
// Compute derived properties from the register classes
179285
computeRegisterProperties(STI.getRegisterInfo());
180286
}
@@ -185,6 +291,11 @@ bool XtensaTargetLowering::isOffsetFoldingLegal(
185291
return false;
186292
}
187293

294+
bool XtensaTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
295+
bool ForCodeSize) const {
296+
return false;
297+
}
298+
188299
//===----------------------------------------------------------------------===//
189300
// Inline asm support
190301
//===----------------------------------------------------------------------===//
@@ -335,6 +446,16 @@ static bool CC_Xtensa_Custom(unsigned ValNo, MVT ValVT, MVT LocVT,
335446
return false;
336447
}
337448

449+
/// Return the register type for a given MVT
450+
MVT XtensaTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
451+
CallingConv::ID CC,
452+
EVT VT) const {
453+
if (VT.isFloatingPoint())
454+
return MVT::i32;
455+
456+
return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
457+
}
458+
338459
CCAssignFn *XtensaTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
339460
bool IsVarArg) const {
340461
return CC_Xtensa_Custom;
@@ -815,6 +936,21 @@ SDValue XtensaTargetLowering::LowerImmediate(SDValue Op,
815936
return Op;
816937
}
817938

939+
SDValue XtensaTargetLowering::LowerImmediateFP(SDValue Op,
940+
SelectionDAG &DAG) const {
941+
const ConstantFPSDNode *CN = cast<ConstantFPSDNode>(Op);
942+
SDLoc DL(CN);
943+
APFloat apval = CN->getValueAPF();
944+
int64_t value = llvm::bit_cast<uint32_t>(CN->getValueAPF().convertToFloat());
945+
if (Op.getValueType() == MVT::f32) {
946+
Type *Ty = Type::getInt32Ty(*DAG.getContext());
947+
Constant *CV = ConstantInt::get(Ty, value);
948+
SDValue CP = DAG.getConstantPool(CV, MVT::i32);
949+
return DAG.getNode(ISD::BITCAST, DL, MVT::f32, CP);
950+
}
951+
return Op;
952+
}
953+
818954
SDValue XtensaTargetLowering::LowerGlobalAddress(SDValue Op,
819955
SelectionDAG &DAG) const {
820956
const GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
@@ -1248,6 +1384,8 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
12481384
return LowerBR_JT(Op, DAG);
12491385
case ISD::Constant:
12501386
return LowerImmediate(Op, DAG);
1387+
case ISD::ConstantFP:
1388+
return LowerImmediateFP(Op, DAG);
12511389
case ISD::RETURNADDR:
12521390
return LowerRETURNADDR(Op, DAG);
12531391
case ISD::GlobalAddress:
@@ -1311,6 +1449,26 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
13111449
return "XtensaISD::SRCL";
13121450
case XtensaISD::SRCR:
13131451
return "XtensaISD::SRCR";
1452+
case XtensaISD::CMPUO:
1453+
return "XtensaISD::CMPUO";
1454+
case XtensaISD::CMPUEQ:
1455+
return "XtensaISD::CMPUEQ";
1456+
case XtensaISD::CMPULE:
1457+
return "XtensaISD::CMPULE";
1458+
case XtensaISD::CMPULT:
1459+
return "XtensaISD::CMPULT";
1460+
case XtensaISD::CMPOEQ:
1461+
return "XtensaISD::CMPOEQ";
1462+
case XtensaISD::CMPOLE:
1463+
return "XtensaISD::CMPOLE";
1464+
case XtensaISD::CMPOLT:
1465+
return "XtensaISD::CMPOLT";
1466+
case XtensaISD::MADD:
1467+
return "XtensaISD::MADD";
1468+
case XtensaISD::MSUB:
1469+
return "XtensaISD::MSUB";
1470+
case XtensaISD::MOVS:
1471+
return "XtensaISD::MOVS";
13141472
}
13151473
return nullptr;
13161474
}
@@ -1395,11 +1553,19 @@ MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
13951553
case Xtensa::S16I:
13961554
case Xtensa::S32I:
13971555
case Xtensa::S32I_N:
1556+
case Xtensa::SSI:
1557+
case Xtensa::SSIP:
1558+
case Xtensa::SSX:
1559+
case Xtensa::SSXP:
13981560
case Xtensa::L8UI:
13991561
case Xtensa::L16SI:
14001562
case Xtensa::L16UI:
14011563
case Xtensa::L32I:
1402-
case Xtensa::L32I_N: {
1564+
case Xtensa::L32I_N:
1565+
case Xtensa::LSI:
1566+
case Xtensa::LSIP:
1567+
case Xtensa::LSX:
1568+
case Xtensa::LSXP: {
14031569
// Insert memory wait instruction "memw" before volatile load/store as it is
14041570
// implemented in gcc. If memoperands is empty then assume that it aslo
14051571
// maybe volatile load/store and insert "memw".

llvm/lib/Target/Xtensa/XtensaISelLowering.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,21 @@ enum {
5656
SRCL,
5757
// Shift Right Combined
5858
SRCR,
59+
60+
// Floating point unordered compare conditions
61+
CMPUEQ,
62+
CMPULE,
63+
CMPULT,
64+
CMPUO,
65+
// Floating point compare conditions
66+
CMPOEQ,
67+
CMPOLE,
68+
CMPOLT,
69+
// FP multipy-add/sub
70+
MADD,
71+
MSUB,
72+
// FP move
73+
MOVS,
5974
};
6075
}
6176

@@ -70,6 +85,9 @@ class XtensaTargetLowering : public TargetLowering {
7085
return LHSTy.getSizeInBits() <= 32 ? MVT::i32 : MVT::i64;
7186
}
7287

88+
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
89+
EVT VT) const override;
90+
7391
EVT getSetCCResultType(const DataLayout &, LLVMContext &,
7492
EVT VT) const override {
7593
if (!VT.isVector())
@@ -81,6 +99,9 @@ class XtensaTargetLowering : public TargetLowering {
8199

82100
const char *getTargetNodeName(unsigned Opcode) const override;
83101

102+
bool isFPImmLegal(const APFloat &Imm, EVT VT,
103+
bool ForCodeSize) const override;
104+
84105
std::pair<unsigned, const TargetRegisterClass *>
85106
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
86107
StringRef Constraint, MVT VT) const override;
@@ -133,6 +154,8 @@ class XtensaTargetLowering : public TargetLowering {
133154

134155
SDValue LowerImmediate(SDValue Op, SelectionDAG &DAG) const;
135156

157+
SDValue LowerImmediateFP(SDValue Op, SelectionDAG &DAG) const;
158+
136159
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
137160

138161
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;

llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,15 @@ void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
151151
unsigned &LoadOpcode,
152152
unsigned &StoreOpcode,
153153
int64_t offset) const {
154-
assert((RC == &Xtensa::ARRegClass) &&
155-
"Unsupported regclass to load or store");
156-
157-
LoadOpcode = Xtensa::L32I;
158-
StoreOpcode = Xtensa::S32I;
154+
if (RC == &Xtensa::ARRegClass) {
155+
LoadOpcode = Xtensa::L32I;
156+
StoreOpcode = Xtensa::S32I;
157+
} else if (RC == &Xtensa::FPRRegClass) {
158+
LoadOpcode = Xtensa::LSI;
159+
StoreOpcode = Xtensa::SSI;
160+
} else {
161+
llvm_unreachable("Unsupported regclass to load or store");
162+
}
159163
}
160164

161165
void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,

0 commit comments

Comments
 (0)