Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def NotBoolXor : PatFrags<(ops node:$val),
// LoongArch specific DAG Nodes.
//===----------------------------------------------------------------------===//

def SDT_LoongArchMOVGR2FR_W
: SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i32>]>;
def SDT_LoongArchMOVGR2FR_W_LA64
: SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
def SDT_LoongArchMOVFR2GR_S_LA64
Expand All @@ -28,6 +30,8 @@ def SDT_LoongArchFRSQRTE : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisFP<1>]>;
// ISD::BRCOND is custom-lowered to LoongArchISD::BRCOND for floating-point
// comparisons to prevent recursive lowering.
def loongarch_brcond : SDNode<"LoongArchISD::BRCOND", SDTBrcond, [SDNPHasChain]>;
def loongarch_movgr2fr_w
: SDNode<"LoongArchISD::MOVGR2FR_W", SDT_LoongArchMOVGR2FR_W>;
def loongarch_movgr2fr_w_la64
: SDNode<"LoongArchISD::MOVGR2FR_W_LA64", SDT_LoongArchMOVGR2FR_W_LA64>;
def loongarch_movfr2gr_s_la64
Expand Down Expand Up @@ -185,6 +189,14 @@ def : PatFpr<fneg, FNEG_S, FPR32>;
def : PatFpr<fabs, FABS_S, FPR32>;
def : PatFpr<fsqrt, FSQRT_S, FPR32>;
def : Pat<(fdiv fpimm1, (fsqrt FPR32:$fj)), (FRSQRT_S FPR32:$fj)>;
let Predicates = [HasBasicF, IsLA64] in {
def : Pat<(fdiv (loongarch_movgr2fr_w_la64 (i64 1065353216)), (fsqrt FPR32:$fj)),
(FRSQRT_S FPR32:$fj)>;
} // Predicates = [HasBasicF, IsLA64]
let Predicates = [HasBasicF, IsLA32] in {
def : Pat<(fdiv (loongarch_movgr2fr_w (i32 1065353216)), (fsqrt FPR32:$fj)),
(FRSQRT_S FPR32:$fj)>;
} // Predicates = [HasBasicF, IsLA32]
def : Pat<(fcanonicalize FPR32:$fj), (FMAX_S $fj, $fj)>;
def : Pat<(is_fpclass FPR32:$fj, (i32 timm:$mask)),
(SLTU R0, (ANDI (MOVFR2GR_S (FCLASS_S FPR32:$fj)),
Expand Down Expand Up @@ -295,6 +307,14 @@ def : Pat<(loongarch_ftint FPR32:$src), (FTINTRZ_W_S FPR32:$src)>;

// FP reciprocal operation
def : Pat<(fdiv fpimm1, FPR32:$src), (FRECIP_S $src)>;
let Predicates = [HasBasicF, IsLA64] in {
def : Pat<(fdiv (loongarch_movgr2fr_w_la64 (i64 1065353216)), FPR32:$src),
(FRECIP_S $src)>;
} // Predicates = [HasBasicF, IsLA64]
let Predicates = [HasBasicF, IsLA32] in {
def : Pat<(fdiv (loongarch_movgr2fr_w (i32 1065353216)), FPR32:$src),
(FRECIP_S $src)>;
} // Predicates = [HasBasicF, IsLA32]

let Predicates = [HasFrecipe] in {
// FP approximate reciprocal operation
Expand Down Expand Up @@ -350,6 +370,7 @@ def : PatFpr<frint, FRINT_S, FPR32>;
let Predicates = [HasBasicF, IsLA32] in {
// GPR -> FPR
def : Pat<(bitconvert (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
def : Pat<(loongarch_movgr2fr_w (i32 GPR:$src)), (MOVGR2FR_W GPR:$src)>;
// FPR -> GPR
def : Pat<(i32 (bitconvert FPR32:$src)), (MOVFR2GR_S FPR32:$src)>;
// int -> f32
Expand Down
28 changes: 28 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// LoongArch specific DAG Nodes.
//===----------------------------------------------------------------------===//

def SDT_LoongArchMOVGR2FR_D
: SDTypeProfile<1, 1, [SDTCisVT<0, f64>, SDTCisVT<1, i64>]>;
def SDT_LoongArchMOVGR2FR_D_LO_HI
: SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisVT<1, i32>,
SDTCisSameAs<1, 2>]>;

def loongarch_movgr2fr_d
: SDNode<"LoongArchISD::MOVGR2FR_D", SDT_LoongArchMOVGR2FR_D>;
def loongarch_movgr2fr_d_lo_hi
: SDNode<"LoongArchISD::MOVGR2FR_D_LO_HI", SDT_LoongArchMOVGR2FR_D_LO_HI>;

//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -147,6 +162,11 @@ def : PatFpr<fneg, FNEG_D, FPR64>;
def : PatFpr<fabs, FABS_D, FPR64>;
def : PatFpr<fsqrt, FSQRT_D, FPR64>;
def : Pat<(fdiv fpimm1, (fsqrt FPR64:$fj)), (FRSQRT_D FPR64:$fj)>;
let Predicates = [IsLA32] in {
def : Pat<(fdiv (loongarch_movgr2fr_d_lo_hi (i32 0), (i32 1072693248)),
(fsqrt FPR64:$fj)),
(FRSQRT_D FPR64:$fj)>;
} // Predicates = [IsLA32]
def : Pat<(fcopysign FPR64:$fj, FPR32:$fk),
(FCOPYSIGN_D FPR64:$fj, (FCVT_D_S FPR32:$fk))>;
def : Pat<(fcopysign FPR32:$fj, FPR64:$fk),
Expand Down Expand Up @@ -252,6 +272,10 @@ def : Pat<(f64 (fpextend FPR32:$src)), (FCVT_D_S FPR32:$src)>;

// FP reciprocal operation
def : Pat<(fdiv fpimm1, FPR64:$src), (FRECIP_D $src)>;
let Predicates = [IsLA32] in {
def : Pat<(fdiv (loongarch_movgr2fr_d_lo_hi (i32 0), (i32 1072693248)), FPR64:$src),
(FRECIP_D FPR64:$src)>;
} // Predicates = [IsLA32]

let Predicates = [HasFrecipe] in {
// FP approximate reciprocal operation
Expand Down Expand Up @@ -307,9 +331,13 @@ def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>;

def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>;
def : Pat<(loongarch_movgr2fr_d GPR:$src), (MOVGR2FR_D GPR:$src)>;
} // Predicates = [HasBasicD, IsLA64]
let Predicates = [HasBasicD, IsLA32] in {
def : Pat<(f64 (sint_to_fp (i32 GPR:$src))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>;

def : Pat<(f64 (loongarch_movgr2fr_d_lo_hi (i32 GPR:$lo), (i32 GPR:$hi))),
(MOVGR2FRH_W (MOVGR2FR_W_64 GPR:$lo), GPR:$hi)>;
} // Predicates = [HasBasicD, IsLA32]

// Convert FP to int
Expand Down
91 changes: 91 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "LoongArchSubtarget.h"
#include "MCTargetDesc/LoongArchBaseInfo.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "MCTargetDesc/LoongArchMatInt.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
Expand All @@ -41,6 +42,34 @@ using namespace llvm;

STATISTIC(NumTailCalls, "Number of tail calls");

enum MaterializeFPImm {
NoMaterializeFPImm = 0,
MaterializeFPImm2Ins = 2,
MaterializeFPImm3Ins = 3,
MaterializeFPImm4Ins = 4,
MaterializeFPImm5Ins = 5,
MaterializeFPImm6Ins = 6
};

static cl::opt<MaterializeFPImm> MaterializeFPImmInsNum(
"loongarch-materialize-float-imm", cl::Hidden,
cl::desc("Maximum number of instructions used (including code sequence "
"to generate the value and moving the value to FPR) when "
"materializing floating-point immediates (default = 3)"),
cl::init(MaterializeFPImm3Ins),
cl::values(clEnumValN(NoMaterializeFPImm, "0", "Use constant pool"),
clEnumValN(MaterializeFPImm2Ins, "2",
"Materialize FP immediate within 2 instructions"),
clEnumValN(MaterializeFPImm3Ins, "3",
"Materialize FP immediate within 3 instructions"),
clEnumValN(MaterializeFPImm4Ins, "4",
"Materialize FP immediate within 4 instructions"),
clEnumValN(MaterializeFPImm5Ins, "5",
"Materialize FP immediate within 5 instructions"),
clEnumValN(MaterializeFPImm6Ins, "6",
"Materialize FP immediate within 6 instructions "
"(behaves same as 5 on loongarch64)")));

static cl::opt<bool> ZeroDivCheck("loongarch-check-zero-division", cl::Hidden,
cl::desc("Trap on integer division by zero."),
cl::init(false));
Expand Down Expand Up @@ -190,6 +219,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
setCondCodeAction(FPCCToExpand, MVT::f32, Expand);

setOperationAction(ISD::ConstantFP, MVT::f32, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
setOperationAction(ISD::FMA, MVT::f32, Legal);
Expand Down Expand Up @@ -237,6 +267,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
setCondCodeAction(FPCCToExpand, MVT::f64, Expand);

setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
setOperationAction(ISD::BR_CC, MVT::f64, Expand);
setOperationAction(ISD::STRICT_FSETCCS, MVT::f64, Legal);
Expand Down Expand Up @@ -557,10 +588,67 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
case ISD::VECREDUCE_UMAX:
case ISD::VECREDUCE_UMIN:
return lowerVECREDUCE(Op, DAG);
case ISD::ConstantFP:
return lowerConstantFP(Op, DAG);
}
return SDValue();
}

SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op,
SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
const APFloat &FPVal = CFP->getValueAPF();
SDLoc DL(CFP);

assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
(VT == MVT::f64 && Subtarget.hasBasicD()));

// If value is 0.0 or -0.0, just ignore it.
if (FPVal.isZero())
return SDValue();

// If lsx enabled, use cheaper 'vldi' instruction if possible.
if (isFPImmVLDILegal(FPVal, VT))
return SDValue();

// Construct as integer, and move to float register.
APInt INTVal = FPVal.bitcastToAPInt();

// If more than MaterializeFPImmInsNum instructions will be used to
// generate the INTVal and move it to float register, fallback to
// use floating point load from the constant pool.
auto Seq = LoongArchMatInt::generateInstSeq(INTVal.getSExtValue());
int InsNum = Seq.size() + ((VT == MVT::f64 && !Subtarget.is64Bit()) ? 2 : 1);
if (InsNum > MaterializeFPImmInsNum && !FPVal.isExactlyValue(+1.0))
return SDValue();

switch (VT.getSimpleVT().SimpleTy) {
default:
llvm_unreachable("Unexpected floating point type!");
break;
case MVT::f32: {
SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i32);
if (Subtarget.is64Bit())
NewVal = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, NewVal);
return DAG.getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
: LoongArchISD::MOVGR2FR_W,
DL, VT, NewVal);
}
case MVT::f64: {
if (Subtarget.is64Bit()) {
SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i64);
return DAG.getNode(LoongArchISD::MOVGR2FR_D, DL, VT, NewVal);
}
SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32);
SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32);
return DAG.getNode(LoongArchISD::MOVGR2FR_D_LO_HI, DL, VT, Lo, Hi);
}
}

return SDValue();
}

// Lower vecreduce_add using vhaddw instructions.
// For Example:
// call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
Expand Down Expand Up @@ -7152,7 +7240,10 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(SRL_W)
NODE_NAME_CASE(BSTRINS)
NODE_NAME_CASE(BSTRPICK)
NODE_NAME_CASE(MOVGR2FR_W)
NODE_NAME_CASE(MOVGR2FR_W_LA64)
NODE_NAME_CASE(MOVGR2FR_D)
NODE_NAME_CASE(MOVGR2FR_D_LO_HI)
NODE_NAME_CASE(MOVFR2GR_S_LA64)
NODE_NAME_CASE(FTINT)
NODE_NAME_CASE(BUILD_PAIR_F64)
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ enum NodeType : unsigned {
MOD_WU,

// FPR<->GPR transfer operations
MOVGR2FR_W,
MOVGR2FR_W_LA64,
MOVGR2FR_D,
MOVGR2FR_D_LO_HI,
MOVFR2GR_S_LA64,
MOVFCSR2GR,
MOVGR2FCSR,
Expand Down Expand Up @@ -399,6 +402,7 @@ class LoongArchTargetLowering : public TargetLowering {
SDValue lowerBF16_TO_FP(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVECREDUCE_ADD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVECREDUCE(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;

bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
Expand Down
Loading