Skip to content

Commit 7c370cd

Browse files
committed
[LoongArch] Custom legalizing ConstantFP to avoid float loads
TODO: `frecip` and `frsqrt` cannot match.
1 parent 4621e17 commit 7c370cd

17 files changed

+1298
-1134
lines changed

llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ def NotBoolXor : PatFrags<(ops node:$val),
1717
// LoongArch specific DAG Nodes.
1818
//===----------------------------------------------------------------------===//
1919

20+
def SDT_LoongArchMOVGR2FR_W
21+
: SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i32>]>;
2022
def SDT_LoongArchMOVGR2FR_W_LA64
2123
: SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
2224
def SDT_LoongArchMOVFR2GR_S_LA64
@@ -28,6 +30,8 @@ def SDT_LoongArchFRSQRTE : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>;
2830
// ISD::BRCOND is custom-lowered to LoongArchISD::BRCOND for floating-point
2931
// comparisons to prevent recursive lowering.
3032
def loongarch_brcond : SDNode<"LoongArchISD::BRCOND", SDTBrcond, [SDNPHasChain]>;
33+
def loongarch_movgr2fr_w
34+
: SDNode<"LoongArchISD::MOVGR2FR_W", SDT_LoongArchMOVGR2FR_W>;
3135
def loongarch_movgr2fr_w_la64
3236
: SDNode<"LoongArchISD::MOVGR2FR_W_LA64", SDT_LoongArchMOVGR2FR_W_LA64>;
3337
def loongarch_movfr2gr_s_la64
@@ -350,6 +354,7 @@ def : PatFpr<frint, FRINT_S, FPR32>;
350354
let Predicates = [HasBasicF, IsLA32] in {
351355
// GPR -> FPR
352356
def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
357+
def : Pat<(loongarch_movgr2fr_w (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
353358
// FPR -> GPR
354359
def : Pat<(i32 (bitconvert FPR32:$src)), (MOVFR2GR_S FPR32:$src)>;
355360
// int -> f32

llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
//===----------------------------------------------------------------------===//
14+
// LoongArch specific DAG Nodes.
15+
//===----------------------------------------------------------------------===//
16+
17+
def SDT_LoongArchMOVGR2FR_D
18+
: SDTypeProfile<1, 1, [SDTCisVT<0, f64>, SDTCisVT<1, i64>]>;
19+
def SDT_LoongArchMOVGR2FR_D_LO_HI
20+
: SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisVT<1, i32>,
21+
SDTCisSameAs<1, 2>]>;
22+
23+
def loongarch_movgr2fr_d
24+
: SDNode<"LoongArchISD::MOVGR2FR_D", SDT_LoongArchMOVGR2FR_D>;
25+
def loongarch_movgr2fr_d_lo_hi
26+
: SDNode<"LoongArchISD::MOVGR2FR_D_LO_HI", SDT_LoongArchMOVGR2FR_D_LO_HI>;
27+
1328
//===----------------------------------------------------------------------===//
1429
// Instructions
1530
//===----------------------------------------------------------------------===//
@@ -307,9 +322,13 @@ def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
307322
def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>;
308323

309324
def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>;
325+
def : Pat<(loongarch_movgr2fr_d GPR:$src), (MOVGR2FR_D GPR:$src)>;
310326
} // Predicates = [HasBasicD, IsLA64]
311327
let Predicates = [HasBasicD, IsLA32] in {
312328
def : Pat<(f64 (sint_to_fp (i32 GPR:$src))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>;
329+
330+
def : Pat<(f64 (loongarch_movgr2fr_d_lo_hi (i32 GPR:$lo), (i32 GPR:$hi))),
331+
(MOVGR2FRH_W (MOVGR2FR_W_64 GPR:$lo), GPR:$hi)>;
313332
} // Predicates = [HasBasicD, IsLA32]
314333

315334
// Convert FP to int

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
190190
setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
191191
setCondCodeAction(FPCCToExpand, MVT::f32, Expand);
192192

193+
setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
193194
setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
194195
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
195196
setOperationAction(ISD::FMA, MVT::f32, Legal);
@@ -237,6 +238,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
237238
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
238239
setCondCodeAction(FPCCToExpand, MVT::f64, Expand);
239240

241+
setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
240242
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
241243
setOperationAction(ISD::BR_CC, MVT::f64, Expand);
242244
setOperationAction(ISD::STRICT_FSETCCS, MVT::f64, Legal);
@@ -549,10 +551,58 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
549551
case ISD::VECREDUCE_UMAX:
550552
case ISD::VECREDUCE_UMIN:
551553
return lowerVECREDUCE(Op, DAG);
554+
case ISD::ConstantFP:
555+
return lowerConstantFP(Op, DAG);
552556
}
553557
return SDValue();
554558
}
555559

560+
SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op,
561+
SelectionDAG &DAG) const {
562+
EVT VT = Op.getValueType();
563+
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
564+
const APFloat &FPVal = CFP->getValueAPF();
565+
SDLoc DL(CFP);
566+
567+
assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
568+
(VT == MVT::f64 && Subtarget.hasBasicD()));
569+
570+
// If value is 0.0 or -0.0, just ignore it.
571+
if (FPVal.isZero())
572+
return SDValue();
573+
574+
// If lsx enabled, use cheaper 'vldi' instruction if possible.
575+
if (Subtarget.hasExtLSX() && isFPImmVLDILegal(FPVal, VT))
576+
return SDValue();
577+
578+
// Construct as integer, and move to float register.
579+
APInt INTVal = FPVal.bitcastToAPInt();
580+
switch (VT.getSimpleVT().SimpleTy) {
581+
default:
582+
llvm_unreachable("Unexpected floating point type!");
583+
break;
584+
case MVT::f32: {
585+
SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i32);
586+
if (Subtarget.is64Bit())
587+
NewVal = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, NewVal);
588+
return DAG.getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
589+
: LoongArchISD::MOVGR2FR_W,
590+
DL, VT, NewVal);
591+
}
592+
case MVT::f64: {
593+
if (Subtarget.is64Bit()) {
594+
SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i64);
595+
return DAG.getNode(LoongArchISD::MOVGR2FR_D, DL, VT, NewVal);
596+
}
597+
SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32);
598+
SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32);
599+
return DAG.getNode(LoongArchISD::MOVGR2FR_D_LO_HI, DL, VT, Lo, Hi);
600+
}
601+
}
602+
603+
return SDValue();
604+
}
605+
556606
// Lower vecreduce_add using vhaddw instructions.
557607
// For Example:
558608
// call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
@@ -7041,7 +7091,10 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
70417091
NODE_NAME_CASE(SRL_W)
70427092
NODE_NAME_CASE(BSTRINS)
70437093
NODE_NAME_CASE(BSTRPICK)
7094+
NODE_NAME_CASE(MOVGR2FR_W)
70447095
NODE_NAME_CASE(MOVGR2FR_W_LA64)
7096+
NODE_NAME_CASE(MOVGR2FR_D)
7097+
NODE_NAME_CASE(MOVGR2FR_D_LO_HI)
70457098
NODE_NAME_CASE(MOVFR2GR_S_LA64)
70467099
NODE_NAME_CASE(FTINT)
70477100
NODE_NAME_CASE(BUILD_PAIR_F64)

llvm/lib/Target/LoongArch/LoongArchISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ enum NodeType : unsigned {
5757
MOD_WU,
5858

5959
// FPR<->GPR transfer operations
60+
MOVGR2FR_W,
6061
MOVGR2FR_W_LA64,
62+
MOVGR2FR_D,
63+
MOVGR2FR_D_LO_HI,
6164
MOVFR2GR_S_LA64,
6265
MOVFCSR2GR,
6366
MOVGR2FCSR,
@@ -397,6 +400,7 @@ class LoongArchTargetLowering : public TargetLowering {
397400
SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
398401
SDValue lowerVECREDUCE_ADD(SDValue Op, SelectionDAG &DAG) const;
399402
SDValue lowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
403+
SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
400404

401405
bool isFPImmLegal(const APFloat &Imm, EVT VT,
402406
bool ForCodeSize) const override;

0 commit comments

Comments
 (0)