aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/LoongArch
diff options
context:
space:
mode:
authorwanglei <wanglei@loongson.cn>2022-11-03 11:10:41 +0800
committerWeining Lu <luweining@loongson.cn>2022-11-03 11:40:50 +0800
commit5adb090795914a4122492117f3af8dacaf69301f (patch)
tree1ad2eafeaae1340980f4728f2532fd2cbe7fc3b6 /llvm/lib/Target/LoongArch
parent1024497fffd18bba92485852cfedebb829499953 (diff)
downloadllvm-5adb090795914a4122492117f3af8dacaf69301f.zip
llvm-5adb090795914a4122492117f3af8dacaf69301f.tar.gz
llvm-5adb090795914a4122492117f3af8dacaf69301f.tar.bz2
[LoongArch] Fix codegen for [su]itofp instructions
This patch fixes codegen for `[su]itofp` instructions. In LoongArch, a legal int-to-float conversion is done in two steps: 1. Move the data from `GPR` to `FPR`. (FRLen >= GRLen) 2. Conversion in `FPR`. (the data in `FPR` is treated as a signed value) Based on the above features, when the type's BitWidth meets the requirements, all `SINT_TO_FP` are legal, all `UINT_TO_FP` are expand and lowered to libcall when appropriate. The only special case is, LoongArch64 with `+f,-d` features. At this point, custom processing is required for `[SU]INT_TO_FP`. Of course, we can also ignore it and use libcall directly. Differential Revision: https://reviews.llvm.org/D136916
Diffstat (limited to 'llvm/lib/Target/LoongArch')
-rw-r--r--llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td6
-rw-r--r--llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td4
-rw-r--r--llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp6
-rw-r--r--llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp72
-rw-r--r--llvm/lib/Target/LoongArch/LoongArchISelLowering.h1
5 files changed, 74 insertions, 15 deletions
diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
index 0e2f575..3767fc1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
@@ -284,7 +284,11 @@ def : Pat<(loongarch_movgr2fr_w_la64 GPR:$src), (MOVGR2FR_W GPR:$src)>;
def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src),
(MOVFR2GR_S FPR32:$src)>;
// int -> f32
-def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
+def : Pat<(f32 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
+ (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
+// uint -> f32
+def : Pat<(f32 (uint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
+ (FFINT_S_W (MOVGR2FR_W GPR:$src))>;
} // Predicates = [HasBasicF, IsLA64]
// FP Rounding
diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
index d061b64..44a8005 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
@@ -288,13 +288,11 @@ def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>;
/// Convert int to FP
let Predicates = [HasBasicD, IsLA64] in {
+def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_L (MOVGR2FR_D GPR:$src))>;
def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))),
(FFINT_D_W (MOVGR2FR_W GPR:$src))>;
def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>;
-def : Pat<(f64 (uint_to_fp (i64 (zexti32 (i64 GPR:$src))))),
- (FFINT_D_W (MOVGR2FR_W GPR:$src))>;
-
def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>;
} // Predicates = [HasBasicD, IsLA64]
let Predicates = [HasBasicD, IsLA32] in {
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
index 415ca4d..8ba1f9c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
@@ -213,6 +213,12 @@ bool LoongArchDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) {
Val = N.getOperand(0);
return true;
}
+ if (N.getOpcode() == LoongArchISD::BSTRPICK &&
+ N.getConstantOperandVal(1) < UINT64_C(0X1F) &&
+ N.getConstantOperandVal(2) == UINT64_C(0)) {
+ Val = N;
+ return true;
+ }
MVT VT = N.getSimpleValueType();
if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) {
Val = N;
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 6f47741..49e8ce0 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -21,6 +21,7 @@
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicsLoongArch.h"
#include "llvm/Support/Debug.h"
@@ -160,7 +161,12 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setLibcallName(RTLIB::MUL_I128, nullptr);
setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom);
- setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom);
+ setOperationAction(ISD::UINT_TO_FP, GRLenVT, Expand);
+ if ((Subtarget.is64Bit() && Subtarget.hasBasicF() &&
+ !Subtarget.hasBasicD())) {
+ setOperationAction(ISD::SINT_TO_FP, GRLenVT, Custom);
+ setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom);
+ }
// Compute derived properties from the register classes.
computeRegisterProperties(STI.getRegisterInfo());
@@ -220,6 +226,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
return lowerBITCAST(Op, DAG);
case ISD::UINT_TO_FP:
return lowerUINT_TO_FP(Op, DAG);
+ case ISD::SINT_TO_FP:
+ return lowerSINT_TO_FP(Op, DAG);
case ISD::VASTART:
return lowerVASTART(Op, DAG);
case ISD::FRAMEADDR:
@@ -302,19 +310,61 @@ SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op,
SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op,
SelectionDAG &DAG) const {
+ assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
+ !Subtarget.hasBasicD() && "unexpected target features");
+
+ SDLoc DL(Op);
+ SDValue Op0 = Op.getOperand(0);
+ if (Op0->getOpcode() == ISD::AND) {
+ auto *C = dyn_cast<ConstantSDNode>(Op0.getOperand(1));
+ if (C && C->getZExtValue() < UINT64_C(0xFFFFFFFF))
+ return Op;
+ }
+
+ if (Op0->getOpcode() == LoongArchISD::BSTRPICK &&
+ Op0.getConstantOperandVal(1) < UINT64_C(0X1F) &&
+ Op0.getConstantOperandVal(2) == UINT64_C(0))
+ return Op;
+
+ if (Op0.getOpcode() == ISD::AssertZext &&
+ dyn_cast<VTSDNode>(Op0.getOperand(1))->getVT().bitsLT(MVT::i32))
+ return Op;
+
+ EVT OpVT = Op0.getValueType();
+ EVT RetVT = Op.getValueType();
+ RTLIB::Libcall LC = RTLIB::getUINTTOFP(OpVT, RetVT);
+ MakeLibCallOptions CallOptions;
+ CallOptions.setTypeListBeforeSoften(OpVT, RetVT, true);
+ SDValue Chain = SDValue();
+ SDValue Result;
+ std::tie(Result, Chain) =
+ makeLibCall(DAG, LC, Op.getValueType(), Op0, CallOptions, DL, Chain);
+ return Result;
+}
+
+SDValue LoongArchTargetLowering::lowerSINT_TO_FP(SDValue Op,
+ SelectionDAG &DAG) const {
+ assert(Subtarget.is64Bit() && Subtarget.hasBasicF() &&
+ !Subtarget.hasBasicD() && "unexpected target features");
SDLoc DL(Op);
- auto &TLI = DAG.getTargetLoweringInfo();
- SDValue Tmp1, Tmp2;
- SDValue Op1 = Op.getOperand(0);
- if (Op1->getOpcode() == ISD::AssertZext ||
- Op1->getOpcode() == ISD::AssertSext)
+ SDValue Op0 = Op.getOperand(0);
+
+ if ((Op0.getOpcode() == ISD::AssertSext ||
+ Op0.getOpcode() == ISD::SIGN_EXTEND_INREG) &&
+ dyn_cast<VTSDNode>(Op0.getOperand(1))->getVT().bitsLE(MVT::i32))
return Op;
- SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op.getOperand(0));
- SDValue Res = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f64, Trunc);
- SDNode *N = Res.getNode();
- TLI.expandUINT_TO_FP(N, Tmp1, Tmp2, DAG);
- return Tmp1;
+
+ EVT OpVT = Op0.getValueType();
+ EVT RetVT = Op.getValueType();
+ RTLIB::Libcall LC = RTLIB::getSINTTOFP(OpVT, RetVT);
+ MakeLibCallOptions CallOptions;
+ CallOptions.setTypeListBeforeSoften(OpVT, RetVT, true);
+ SDValue Chain = SDValue();
+ SDValue Result;
+ std::tie(Result, Chain) =
+ makeLibCall(DAG, LC, Op.getValueType(), Op0, CallOptions, DL, Chain);
+ return Result;
}
SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op,
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 1e411fb..358da7f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -171,6 +171,7 @@ private:
SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;