Skip to content

Commit 2dc0fa0

Browse files
author
Shao-Ce SUN
committed
[RISCV][CodeGen] Support Zdinx on RV64 codegen
This patch was split from D122918 . Co-Author: @liaolucy @realqhc Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D149665
1 parent 20b12fa commit 2dc0fa0

25 files changed

+2573
-18
lines changed

llvm/docs/RISCVUsage.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ on support follow.
100100
``Zbkc`` Supported
101101
``Zbkx`` Supported (`See note <#riscv-scalar-crypto-note1>`__)
102102
``Zbs`` Supported
103-
``Zdinx`` Assembly Support
103+
``Zdinx`` Assembly Support for RV32. Full support for RV64.
104104
``Zfh`` Supported
105105
``Zfhmin`` Supported
106106
``Zfinx`` Supported

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,11 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
890890
// For RV32, we can't move from a GPR, we need to convert instead. This
891891
// should only happen for +0.0 and -0.0.
892892
assert((Subtarget->is64Bit() || APF.isZero()) && "Unexpected constant");
893-
Opc = Subtarget->is64Bit() ? RISCV::FMV_D_X : RISCV::FCVT_D_W;
893+
bool HasZdinx = Subtarget->hasStdExtZdinx();
894+
if (Subtarget->is64Bit())
895+
Opc = HasZdinx ? RISCV::COPY : RISCV::FMV_D_X;
896+
else
897+
Opc = RISCV::FCVT_D_W;
894898
break;
895899
}
896900

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
122122
addRegisterClass(MVT::f64, &RISCV::FPR64RegClass);
123123
if (Subtarget.hasStdExtZfinx())
124124
addRegisterClass(MVT::f32, &RISCV::GPRF32RegClass);
125+
if (Subtarget.hasStdExtZdinx()) {
126+
if (Subtarget.is64Bit())
127+
addRegisterClass(MVT::f64, &RISCV::GPRF64RegClass);
128+
}
125129

126130
static const MVT::SimpleValueType BoolVecVTs[] = {
127131
MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
@@ -429,7 +433,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
429433
if (Subtarget.hasStdExtFOrZfinx() && Subtarget.is64Bit())
430434
setOperationAction(ISD::BITCAST, MVT::i32, Custom);
431435

432-
if (Subtarget.hasStdExtD()) {
436+
if (Subtarget.hasStdExtDOrZdinx()) {
433437
setOperationAction(FPLegalNodeTypes, MVT::f64, Legal);
434438

435439
if (Subtarget.hasStdExtZfa()) {
@@ -1075,7 +1079,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
10751079
setOperationAction(ISD::BITCAST, MVT::f16, Custom);
10761080
if (Subtarget.hasStdExtFOrZfinx())
10771081
setOperationAction(ISD::BITCAST, MVT::f32, Custom);
1078-
if (Subtarget.hasStdExtD())
1082+
if (Subtarget.hasStdExtDOrZdinx())
10791083
setOperationAction(ISD::BITCAST, MVT::f64, Custom);
10801084
}
10811085
}
@@ -1799,7 +1803,7 @@ bool RISCVTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
17991803
else if (VT == MVT::f32)
18001804
IsLegalVT = Subtarget.hasStdExtFOrZfinx();
18011805
else if (VT == MVT::f64)
1802-
IsLegalVT = Subtarget.hasStdExtD();
1806+
IsLegalVT = Subtarget.hasStdExtDOrZdinx();
18031807

18041808
if (!IsLegalVT)
18051809
return false;
@@ -12670,6 +12674,7 @@ static bool isSelectPseudo(MachineInstr &MI) {
1267012674
case RISCV::Select_FPR32_Using_CC_GPR:
1267112675
case RISCV::Select_FPR32INX_Using_CC_GPR:
1267212676
case RISCV::Select_FPR64_Using_CC_GPR:
12677+
case RISCV::Select_FPR64INX_Using_CC_GPR:
1267312678
return true;
1267412679
}
1267512680
}
@@ -13071,6 +13076,15 @@ static MachineBasicBlock *emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB,
1307113076
FSGNJXOpc = RISCV::FSGNJX_D;
1307213077
RC = &RISCV::FPR64RegClass;
1307313078
break;
13079+
case RISCV::PseudoFROUND_D_INX:
13080+
assert(Subtarget.is64Bit() && "Expected 64-bit GPR.");
13081+
CmpOpc = RISCV::FLT_D_INX;
13082+
F2IOpc = RISCV::FCVT_L_D_INX;
13083+
I2FOpc = RISCV::FCVT_D_L_INX;
13084+
FSGNJOpc = RISCV::FSGNJ_D_INX;
13085+
FSGNJXOpc = RISCV::FSGNJX_D_INX;
13086+
RC = &RISCV::GPRF64RegClass;
13087+
break;
1307413088
}
1307513089

1307613090
const BasicBlock *BB = MBB->getBasicBlock();
@@ -13161,6 +13175,7 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1316113175
case RISCV::Select_FPR32_Using_CC_GPR:
1316213176
case RISCV::Select_FPR32INX_Using_CC_GPR:
1316313177
case RISCV::Select_FPR64_Using_CC_GPR:
13178+
case RISCV::Select_FPR64INX_Using_CC_GPR:
1316413179
return emitSelectPseudo(MI, BB, Subtarget);
1316513180
case RISCV::BuildPairF64Pseudo:
1316613181
return emitBuildPairF64Pseudo(MI, BB, Subtarget);
@@ -13180,8 +13195,12 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1318013195
return emitQuietFCMP(MI, BB, RISCV::FLT_S_INX, RISCV::FEQ_S_INX, Subtarget);
1318113196
case RISCV::PseudoQuietFLE_D:
1318213197
return emitQuietFCMP(MI, BB, RISCV::FLE_D, RISCV::FEQ_D, Subtarget);
13198+
case RISCV::PseudoQuietFLE_D_INX:
13199+
return emitQuietFCMP(MI, BB, RISCV::FLE_D_INX, RISCV::FEQ_D_INX, Subtarget);
1318313200
case RISCV::PseudoQuietFLT_D:
1318413201
return emitQuietFCMP(MI, BB, RISCV::FLT_D, RISCV::FEQ_D, Subtarget);
13202+
case RISCV::PseudoQuietFLT_D_INX:
13203+
return emitQuietFCMP(MI, BB, RISCV::FLT_D_INX, RISCV::FEQ_D_INX, Subtarget);
1318513204

1318613205
// =========================================================================
1318713206
// VFCVT
@@ -13365,6 +13384,7 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1336513384
case RISCV::PseudoFROUND_S:
1336613385
case RISCV::PseudoFROUND_S_INX:
1336713386
case RISCV::PseudoFROUND_D:
13387+
case RISCV::PseudoFROUND_D_INX:
1336813388
return emitFROUND(MI, BB, Subtarget);
1336913389
}
1337013390
}
@@ -15616,7 +15636,7 @@ bool RISCVTargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
1561615636
case MVT::f32:
1561715637
return Subtarget.hasStdExtFOrZfinx();
1561815638
case MVT::f64:
15619-
return Subtarget.hasStdExtD();
15639+
return Subtarget.hasStdExtDOrZdinx();
1562015640
default:
1562115641
break;
1562215642
}

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,6 +1271,7 @@ bool RISCVInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
12711271
case RISCV::FSGNJ_D:
12721272
case RISCV::FSGNJ_S:
12731273
case RISCV::FSGNJ_H:
1274+
case RISCV::FSGNJ_D_INX:
12741275
case RISCV::FSGNJ_S_INX:
12751276
// The canonical floating-point move is fsgnj rd, rs, rs.
12761277
return MI.getOperand(1).isReg() && MI.getOperand(2).isReg() &&
@@ -1301,6 +1302,7 @@ RISCVInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
13011302
case RISCV::FSGNJ_D:
13021303
case RISCV::FSGNJ_S:
13031304
case RISCV::FSGNJ_H:
1305+
case RISCV::FSGNJ_D_INX:
13041306
case RISCV::FSGNJ_S_INX:
13051307
// The canonical floating-point move is fsgnj rd, rs, rs.
13061308
if (MI.getOperand(1).isReg() && MI.getOperand(2).isReg() &&

llvm/lib/Target/RISCV/RISCVInstrInfoD.td

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def XD_IN32X : ExtInfo_rr<Zdinx32Ext, GPR, FPR64IN32X>;
8080
def XD_64 : ExtInfo_rr<D64Ext, GPR, FPR64>;
8181

8282
defvar DINX = [D, D_INX, D_IN32X];
83+
// TODO: Remove DIN64X when Zdinx for RV32 supported
84+
defvar DIN64X = [D, D_INX];
8385
defvar DDINX = [DD, DD_INX, DD_IN32X];
8486
defvar DXINX = [DX, DX_INX, DX_IN32X];
8587
defvar DFINX = [DF, DF_INX, DF_IN32X];
@@ -218,6 +220,10 @@ def : InstAlias<"fgt.d $rd, $rs, $rt",
218220
(FLT_D_INX GPR:$rd, FPR64INX:$rt, FPR64INX:$rs), 0>;
219221
def : InstAlias<"fge.d $rd, $rs, $rt",
220222
(FLE_D_INX GPR:$rd, FPR64INX:$rt, FPR64INX:$rs), 0>;
223+
let usesCustomInserter = 1 in {
224+
def PseudoQuietFLE_D_INX : PseudoQuietFCMP<FPR64INX>;
225+
def PseudoQuietFLT_D_INX : PseudoQuietFCMP<FPR64INX>;
226+
}
221227
} // Predicates = [HasStdExtZdinx, IsRV64]
222228

223229
let Predicates = [HasStdExtZdinx, IsRV32] in {
@@ -241,17 +247,27 @@ let Predicates = [HasStdExtD] in {
241247
// f64 -> f32, f32 -> f64
242248
def : Pat<(any_fpround FPR64:$rs1), (FCVT_S_D FPR64:$rs1, FRM_DYN)>;
243249
def : Pat<(any_fpextend FPR32:$rs1), (FCVT_D_S FPR32:$rs1)>;
250+
} // Predicates = [HasStdExtD]
251+
252+
let Predicates = [HasStdExtZdinx, IsRV64] in {
253+
/// Float conversion operations
254+
255+
// f64 -> f32, f32 -> f64
256+
def : Pat<(any_fpround FPR64INX:$rs1), (FCVT_S_D_INX FPR64INX:$rs1, FRM_DYN)>;
257+
def : Pat<(any_fpextend FPR32INX:$rs1), (FCVT_D_S_INX FPR32INX:$rs1)>;
258+
} // Predicates = [HasStdExtZdinx, IsRV64]
244259

245260
// [u]int<->double conversion patterns must be gated on IsRV32 or IsRV64, so
246261
// are defined later.
247262

248263
/// Float arithmetic operations
249264

250-
def : PatFprFprDynFrm<any_fadd, FADD_D, FPR64>;
251-
def : PatFprFprDynFrm<any_fsub, FSUB_D, FPR64>;
252-
def : PatFprFprDynFrm<any_fmul, FMUL_D, FPR64>;
253-
def : PatFprFprDynFrm<any_fdiv, FDIV_D, FPR64>;
265+
defm : PatFprFprDynFrm_m<any_fadd, FADD_D, DINX>;
266+
defm : PatFprFprDynFrm_m<any_fsub, FSUB_D, DINX>;
267+
defm : PatFprFprDynFrm_m<any_fmul, FMUL_D, DINX>;
268+
defm : PatFprFprDynFrm_m<any_fdiv, FDIV_D, DINX>;
254269

270+
let Predicates = [HasStdExtD] in {
255271
def : Pat<(any_fsqrt FPR64:$rs1), (FSQRT_D FPR64:$rs1, FRM_DYN)>;
256272

257273
def : Pat<(fneg FPR64:$rs1), (FSGNJN_D $rs1, $rs1)>;
@@ -284,25 +300,64 @@ def : Pat<(any_fma (fneg FPR64:$rs1), FPR64:$rs2, (fneg FPR64:$rs3)),
284300
// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
285301
def : Pat<(fneg (any_fma_nsz FPR64:$rs1, FPR64:$rs2, FPR64:$rs3)),
286302
(FNMADD_D FPR64:$rs1, FPR64:$rs2, FPR64:$rs3, FRM_DYN)>;
303+
} // Predicates = [HasStdExtD]
304+
305+
let Predicates = [HasStdExtZdinx, IsRV64] in {
306+
def : Pat<(any_fsqrt FPR64INX:$rs1), (FSQRT_D_INX FPR64INX:$rs1, FRM_DYN)>;
307+
308+
def : Pat<(fneg FPR64INX:$rs1), (FSGNJN_D_INX $rs1, $rs1)>;
309+
def : Pat<(fabs FPR64INX:$rs1), (FSGNJX_D_INX $rs1, $rs1)>;
310+
311+
def : Pat<(riscv_fpclass FPR64INX:$rs1), (FCLASS_D_INX $rs1)>;
312+
313+
def : PatFprFpr<fcopysign, FSGNJ_D_INX, FPR64INX>;
314+
def : Pat<(fcopysign FPR64INX:$rs1, (fneg FPR64INX:$rs2)),
315+
(FSGNJN_D_INX $rs1, $rs2)>;
316+
def : Pat<(fcopysign FPR64INX:$rs1, FPR32INX:$rs2),
317+
(FSGNJ_D_INX $rs1, (FCVT_D_S_INX $rs2))>;
318+
def : Pat<(fcopysign FPR32INX:$rs1, FPR64INX:$rs2),
319+
(FSGNJ_S_INX $rs1, (FCVT_S_D_INX $rs2, FRM_DYN))>;
320+
321+
// fmadd: rs1 * rs2 + rs3
322+
def : Pat<(any_fma FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3),
323+
(FMADD_D_INX $rs1, $rs2, $rs3, FRM_DYN)>;
324+
325+
// fmsub: rs1 * rs2 - rs3
326+
def : Pat<(any_fma FPR64INX:$rs1, FPR64INX:$rs2, (fneg FPR64INX:$rs3)),
327+
(FMSUB_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>;
328+
329+
// fnmsub: -rs1 * rs2 + rs3
330+
def : Pat<(any_fma (fneg FPR64INX:$rs1), FPR64INX:$rs2, FPR64INX:$rs3),
331+
(FNMSUB_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>;
332+
333+
// fnmadd: -rs1 * rs2 - rs3
334+
def : Pat<(any_fma (fneg FPR64INX:$rs1), FPR64INX:$rs2, (fneg FPR64INX:$rs3)),
335+
(FNMADD_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>;
336+
337+
// fnmadd: -(rs1 * rs2 + rs3) (the nsz flag on the FMA)
338+
def : Pat<(fneg (any_fma_nsz FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3)),
339+
(FNMADD_D_INX FPR64INX:$rs1, FPR64INX:$rs2, FPR64INX:$rs3, FRM_DYN)>;
340+
} // Predicates = [HasStdExtZdinx, IsRV64]
287341

288342
// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches
289343
// LLVM's fminnum and fmaxnum.
290344
// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
291-
def : PatFprFpr<fminnum, FMIN_D, FPR64>;
292-
def : PatFprFpr<fmaxnum, FMAX_D, FPR64>;
345+
defm : PatFprFpr_m<fminnum, FMIN_D, DINX>;
346+
defm : PatFprFpr_m<fmaxnum, FMAX_D, DINX>;
293347

294348
/// Setcc
295349
// FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for
296350
// strict versions of those.
297351

298352
// Match non-signaling FEQ_D
299-
def : PatSetCC<FPR64, any_fsetcc, SETEQ, FEQ_D>;
300-
def : PatSetCC<FPR64, any_fsetcc, SETOEQ, FEQ_D>;
301-
def : PatSetCC<FPR64, strict_fsetcc, SETLT, PseudoQuietFLT_D>;
302-
def : PatSetCC<FPR64, strict_fsetcc, SETOLT, PseudoQuietFLT_D>;
303-
def : PatSetCC<FPR64, strict_fsetcc, SETLE, PseudoQuietFLE_D>;
304-
def : PatSetCC<FPR64, strict_fsetcc, SETOLE, PseudoQuietFLE_D>;
353+
defm : PatSetCC_m<any_fsetcc, SETEQ, FEQ_D, DINX>;
354+
defm : PatSetCC_m<any_fsetcc, SETOEQ, FEQ_D, DINX>;
355+
defm : PatSetCC_m<strict_fsetcc, SETLT, PseudoQuietFLT_D, DIN64X>;
356+
defm : PatSetCC_m<strict_fsetcc, SETOLT, PseudoQuietFLT_D, DIN64X>;
357+
defm : PatSetCC_m<strict_fsetcc, SETLE, PseudoQuietFLE_D, DIN64X>;
358+
defm : PatSetCC_m<strict_fsetcc, SETOLE, PseudoQuietFLE_D, DIN64X>;
305359

360+
let Predicates = [HasStdExtD] in {
306361
// Match signaling FEQ_D
307362
def : Pat<(strict_fsetccs FPR64:$rs1, FPR64:$rs2, SETEQ),
308363
(AND (FLE_D $rs1, $rs2),
@@ -320,7 +375,29 @@ def : PatSetCC<FPR64, any_fsetccs, SETLT, FLT_D>;
320375
def : PatSetCC<FPR64, any_fsetccs, SETOLT, FLT_D>;
321376
def : PatSetCC<FPR64, any_fsetccs, SETLE, FLE_D>;
322377
def : PatSetCC<FPR64, any_fsetccs, SETOLE, FLE_D>;
378+
} // Predicates = [HasStdExtD]
379+
380+
let Predicates = [HasStdExtZdinx, IsRV64] in {
381+
// Match signaling FEQ_D
382+
def : Pat<(strict_fsetccs FPR64INX:$rs1, FPR64INX:$rs2, SETEQ),
383+
(AND (FLE_D_INX $rs1, $rs2),
384+
(FLE_D_INX $rs2, $rs1))>;
385+
def : Pat<(strict_fsetccs FPR64INX:$rs1, FPR64INX:$rs2, SETOEQ),
386+
(AND (FLE_D_INX $rs1, $rs2),
387+
(FLE_D_INX $rs2, $rs1))>;
388+
// If both operands are the same, use a single FLE.
389+
def : Pat<(strict_fsetccs FPR64INX:$rs1, FPR64INX:$rs1, SETEQ),
390+
(FLE_D_INX $rs1, $rs1)>;
391+
def : Pat<(strict_fsetccs FPR64INX:$rs1, FPR64INX:$rs1, SETOEQ),
392+
(FLE_D_INX $rs1, $rs1)>;
393+
394+
def : PatSetCC<FPR64INX, any_fsetccs, SETLT, FLT_D_INX>;
395+
def : PatSetCC<FPR64INX, any_fsetccs, SETOLT, FLT_D_INX>;
396+
def : PatSetCC<FPR64INX, any_fsetccs, SETLE, FLE_D_INX>;
397+
def : PatSetCC<FPR64INX, any_fsetccs, SETOLE, FLE_D_INX>;
398+
} // Predicates = [HasStdExtZdinx, IsRV64]
323399

400+
let Predicates = [HasStdExtD] in {
324401
defm Select_FPR64 : SelectCC_GPR_rrirr<FPR64>;
325402

326403
def PseudoFROUND_D : PseudoFROUND<FPR64>;
@@ -349,6 +426,20 @@ def SplitF64Pseudo
349426

350427
} // Predicates = [HasStdExtD]
351428

429+
let Predicates = [HasStdExtZdinx, IsRV64] in {
430+
defm Select_FPR64INX : SelectCC_GPR_rrirr<FPR64INX>;
431+
432+
def PseudoFROUND_D_INX : PseudoFROUND<FPR64INX>;
433+
434+
/// Loads
435+
def : Pat<(f64 (load (AddrRegImm GPR:$rs1, simm12:$imm12))),
436+
(COPY_TO_REGCLASS (LD GPR:$rs1, simm12:$imm12), GPRF64)>;
437+
438+
/// Stores
439+
def : Pat<(store (f64 FPR64INX:$rs2), (AddrRegImm GPR:$rs1, simm12:$imm12)),
440+
(SD (COPY_TO_REGCLASS FPR64INX:$rs2, GPR), GPR:$rs1, simm12:$imm12)>;
441+
} // Predicates = [HasStdExtZdinx, IsRV64]
442+
352443
let Predicates = [HasStdExtD, IsRV32] in {
353444

354445
// double->[u]int. Round-to-zero must be used.
@@ -406,3 +497,40 @@ def : Pat<(i64 (any_llround FPR64:$rs1)), (FCVT_L_D $rs1, FRM_RMM)>;
406497
def : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_D_L GPR:$rs1, FRM_DYN)>;
407498
def : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_D_LU GPR:$rs1, FRM_DYN)>;
408499
} // Predicates = [HasStdExtD, IsRV64]
500+
501+
let Predicates = [HasStdExtZdinx, IsRV64] in {
502+
503+
// Moves (no conversion)
504+
def : Pat<(f64 (bitconvert (i64 GPR:$rs1))), (COPY_TO_REGCLASS GPR:$rs1, GPRF64)>;
505+
def : Pat<(i64 (bitconvert FPR64INX:$rs1)), (COPY_TO_REGCLASS FPR64INX:$rs1, GPR)>;
506+
507+
// Use target specific isd nodes to help us remember the result is sign
508+
// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
509+
// duplicated if it has another user that didn't need the sign_extend.
510+
def : Pat<(riscv_any_fcvt_w_rv64 FPR64INX:$rs1, timm:$frm), (FCVT_W_D_INX $rs1, timm:$frm)>;
511+
def : Pat<(riscv_any_fcvt_wu_rv64 FPR64INX:$rs1, timm:$frm), (FCVT_WU_D_INX $rs1, timm:$frm)>;
512+
513+
// [u]int32->fp
514+
def : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_D_W_INX $rs1)>;
515+
def : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_D_WU_INX $rs1)>;
516+
517+
// Saturating double->[u]int64.
518+
def : Pat<(i64 (riscv_fcvt_x FPR64INX:$rs1, timm:$frm)), (FCVT_L_D_INX $rs1, timm:$frm)>;
519+
def : Pat<(i64 (riscv_fcvt_xu FPR64INX:$rs1, timm:$frm)), (FCVT_LU_D_INX $rs1, timm:$frm)>;
520+
521+
// double->[u]int64. Round-to-zero must be used.
522+
def : Pat<(i64 (any_fp_to_sint FPR64INX:$rs1)), (FCVT_L_D_INX FPR64INX:$rs1, FRM_RTZ)>;
523+
def : Pat<(i64 (any_fp_to_uint FPR64INX:$rs1)), (FCVT_LU_D_INX FPR64INX:$rs1, FRM_RTZ)>;
524+
525+
// double->int64 with current rounding mode.
526+
def : Pat<(i64 (any_lrint FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_DYN)>;
527+
def : Pat<(i64 (any_llrint FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_DYN)>;
528+
529+
// double->int64 rounded to nearest with ties rounded away from zero.
530+
def : Pat<(i64 (any_lround FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_RMM)>;
531+
def : Pat<(i64 (any_llround FPR64INX:$rs1)), (FCVT_L_D_INX $rs1, FRM_RMM)>;
532+
533+
// [u]int64->fp. Match GCC and default to using dynamic rounding mode.
534+
def : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_D_L_INX GPR:$rs1, FRM_DYN)>;
535+
def : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_D_LU_INX GPR:$rs1, FRM_DYN)>;
536+
} // Predicates = [HasStdExtZdinx, IsRV64]

llvm/lib/Target/RISCV/RISCVSubtarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
114114
bool hasStdExtCOrZca() const { return HasStdExtC || HasStdExtZca; }
115115
bool hasStdExtZvl() const { return ZvlLen != 0; }
116116
bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
117+
bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
117118
bool hasStdExtZfhOrZfhmin() const { return HasStdExtZfh || HasStdExtZfhmin; }
118119
bool is64Bit() const { return IsRV64; }
119120
MVT getXLenVT() const { return XLenVT; }

0 commit comments

Comments
 (0)