From aeaca854d123d8a263722b7c80f55333f856d026 Mon Sep 17 00:00:00 2001 From: gonglingqin Date: Wed, 6 Jul 2022 18:02:45 +0800 Subject: [PATCH] [LoongArch] Add codegen support for handling floating point immediates Differential Revision: https://reviews.llvm.org/D128898 --- .../Target/LoongArch/LoongArchFloat32InstrInfo.td | 5 ++ .../Target/LoongArch/LoongArchFloat64InstrInfo.td | 20 ++++- .../lib/Target/LoongArch/LoongArchISelLowering.cpp | 38 ++++++++- llvm/lib/Target/LoongArch/LoongArchISelLowering.h | 4 + llvm/lib/Target/LoongArch/LoongArchInstrInfo.td | 5 ++ llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp | 4 +- llvm/test/CodeGen/LoongArch/double-imm.ll | 89 ++++++++++++++++++++++ llvm/test/CodeGen/LoongArch/float-imm.ll | 85 +++++++++++++++++++++ 8 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/LoongArch/double-imm.ll create mode 100644 llvm/test/CodeGen/LoongArch/float-imm.ll diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td index b1df8db7d480..9a13b8607dca 100644 --- a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td @@ -182,4 +182,9 @@ defm : LdPat; defm : StPat; +/// Floating point constants + +def : Pat<(f32 fpimm0), (MOVGR2FR_W R0)>; +def : Pat<(f32 fpimm0neg), (FNEG_S (MOVGR2FR_W R0))>; +def : Pat<(f32 fpimm1), (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1)))>; } // Predicates = [HasBasicF] diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td index c3569ae84e9d..f6402606d9bf 100644 --- a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td @@ -131,6 +131,11 @@ def MOVGR2FR_D : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>; def MOVFR2GR_D : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>; } // Predicates = [HasBasicD, IsLA64] +// Instructions only available on LA32 +let Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 in { +def MOVGR2FR_W_64 : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR64, GPR>; +} // Predicates = [HasBasicD, IsLA32], isCodeGenOnly = 1 + //===----------------------------------------------------------------------===// // Pseudo-instructions and codegen patterns //===----------------------------------------------------------------------===// @@ -192,5 +197,18 @@ defm : LdPat; /// Stores defm : StPat; - } // Predicates = [HasBasicD] + +/// Floating point constants + +let Predicates = [HasBasicD, IsLA64] in { +def : Pat<(f64 fpimm0), (MOVGR2FR_D R0)>; +def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FR_D R0))>; +def : Pat<(f64 fpimm1), (FFINT_D_L (MOVGR2FR_D (ADDI_D R0, 1)))>; +} // Predicates = [HasBasicD, IsLA64] + +let Predicates = [HasBasicD, IsLA32] in { +def : Pat<(f64 fpimm0), (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0)>; +def : Pat<(f64 fpimm0neg), (FNEG_D (MOVGR2FRH_W (MOVGR2FR_W_64 R0), R0))>; +def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>; +} // Predicates = [HasBasicD, IsLA32] diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 25823b777cbe..a8f95a0e62db 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -51,7 +51,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); - setOperationAction(ISD::GlobalAddress, GRLenVT, Custom); + setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom); if (Subtarget.is64Bit()) { setOperationAction(ISD::SHL, MVT::i32, Custom); @@ -69,6 +69,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, if (Subtarget.hasBasicD()) { setCondCodeAction(FPCCToExpand, MVT::f64, Expand); setOperationAction(ISD::SELECT_CC, MVT::f64, Expand); + setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand); } setOperationAction(ISD::BR_CC, GRLenVT, Expand); @@ -110,9 +111,33 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && "Unexpected custom legalisation"); return SDValue(); + case ISD::ConstantPool: + return lowerConstantPool(Op, DAG); } } +SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + EVT Ty = Op.getValueType(); + ConstantPoolSDNode *N = cast(Op); + + // FIXME: Only support PC-relative addressing to access the symbol. + // Target flags will be added later. + if (!isPositionIndependent()) { + SDValue ConstantN = DAG.getTargetConstantPool( + N->getConstVal(), Ty, N->getAlign(), N->getOffset()); + SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN), + 0); + SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D + : LoongArch::ADDI_W, + DL, Ty, AddrHi, ConstantN), + 0); + return Addr; + } + report_fatal_error("Unable to lower ConstantPool"); +} + SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); @@ -736,3 +761,14 @@ SDValue LoongArchTargetLowering::LowerReturn( return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps); } + +bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, + bool ForCodeSize) const { + assert((VT == MVT::f32 || VT == MVT::f64) && "Unexpected VT"); + + if (VT == MVT::f32 && !Subtarget.hasBasicF()) + return false; + if (VT == MVT::f64 && !Subtarget.hasBasicD()) + return false; + return (Imm.isZero() || Imm.isExactlyValue(+1.0)); +} diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h index 80845d2d627d..6e4747a5f940 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -96,6 +96,10 @@ private: MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override; + SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; + + bool isFPImmLegal(const APFloat &Imm, EVT VT, + bool ForCodeSize) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index 98c3bffb0c40..57130f169b8f 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -164,6 +164,11 @@ def NegImm : SDNodeXFormgetValueType(0)); }]>; +// FP immediate patterns. +def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>; +def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>; +def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>; + def CallSymbol: AsmOperandClass { let Name = "CallSymbol"; let RenderMethod = "addImmOperands"; diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp index 6c77a79369ad..488c66f47863 100644 --- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp @@ -57,6 +57,9 @@ bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, case MachineOperand::MO_Immediate: MCOp = MCOperand::createImm(MO.getImm()); break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = lowerSymbolOperand(MO, AP.GetCPISymbol(MO.getIndex()), AP); + break; case MachineOperand::MO_GlobalAddress: MCOp = lowerSymbolOperand(MO, AP.getSymbolPreferLocal(*MO.getGlobal()), AP); break; @@ -69,7 +72,6 @@ bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO, break; // TODO: lower special operands case MachineOperand::MO_BlockAddress: - case MachineOperand::MO_ConstantPoolIndex: case MachineOperand::MO_JumpTableIndex: break; } diff --git a/llvm/test/CodeGen/LoongArch/double-imm.ll b/llvm/test/CodeGen/LoongArch/double-imm.ll new file mode 100644 index 000000000000..a7782cf85954 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/double-imm.ll @@ -0,0 +1,89 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch32 --mattr=+d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 --mattr=+d < %s | FileCheck %s --check-prefix=LA64 + +define double @f64_positive_zero() nounwind { +; LA32-LABEL: f64_positive_zero: +; LA32: # %bb.0: +; LA32-NEXT: movgr2fr.w $fa0, $zero +; LA32-NEXT: movgr2frh.w $fa0, $zero +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f64_positive_zero: +; LA64: # %bb.0: +; LA64-NEXT: movgr2fr.d $fa0, $zero +; LA64-NEXT: jirl $zero, $ra, 0 + ret double 0.0 +} + +define double @f64_negative_zero() nounwind { +; LA32-LABEL: f64_negative_zero: +; LA32: # %bb.0: +; LA32-NEXT: movgr2fr.w $fa0, $zero +; LA32-NEXT: movgr2frh.w $fa0, $zero +; LA32-NEXT: fneg.d $fa0, $fa0 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f64_negative_zero: +; LA64: # %bb.0: +; LA64-NEXT: movgr2fr.d $fa0, $zero +; LA64-NEXT: fneg.d $fa0, $fa0 +; LA64-NEXT: jirl $zero, $ra, 0 + ret double -0.0 +} + +define double @f64_constant_pi() nounwind { +; LA32-LABEL: f64_constant_pi: +; LA32: # %bb.0: +; LA32-NEXT: pcalau12i $a0, .LCPI2_0 +; LA32-NEXT: addi.w $a0, $a0, .LCPI2_0 +; LA32-NEXT: fld.d $fa0, $a0, 0 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f64_constant_pi: +; LA64: # %bb.0: +; LA64-NEXT: pcalau12i $a0, .LCPI2_0 +; LA64-NEXT: addi.d $a0, $a0, .LCPI2_0 +; LA64-NEXT: fld.d $fa0, $a0, 0 +; LA64-NEXT: jirl $zero, $ra, 0 + ret double 3.1415926535897931159979634685441851615905761718750 +} + +define double @f64_add_fimm1(double %a) nounwind { +; LA32-LABEL: f64_add_fimm1: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $a0, $zero, 1 +; LA32-NEXT: movgr2fr.w $fa1, $a0 +; LA32-NEXT: ffint.s.w $fa1, $fa1 +; LA32-NEXT: fcvt.d.s $fa1, $fa1 +; LA32-NEXT: fadd.d $fa0, $fa0, $fa1 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f64_add_fimm1: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $a0, $zero, 1 +; LA64-NEXT: movgr2fr.d $fa1, $a0 +; LA64-NEXT: ffint.d.l $fa1, $fa1 +; LA64-NEXT: fadd.d $fa0, $fa0, $fa1 +; LA64-NEXT: jirl $zero, $ra, 0 + %1 = fadd double %a, 1.0 + ret double %1 +} + +define double @f64_positive_fimm1() nounwind { +; LA32-LABEL: f64_positive_fimm1: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $a0, $zero, 1 +; LA32-NEXT: movgr2fr.w $fa0, $a0 +; LA32-NEXT: ffint.s.w $fa0, $fa0 +; LA32-NEXT: fcvt.d.s $fa0, $fa0 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f64_positive_fimm1: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $a0, $zero, 1 +; LA64-NEXT: movgr2fr.d $fa0, $a0 +; LA64-NEXT: ffint.d.l $fa0, $fa0 +; LA64-NEXT: jirl $zero, $ra, 0 + ret double 1.0 +} diff --git a/llvm/test/CodeGen/LoongArch/float-imm.ll b/llvm/test/CodeGen/LoongArch/float-imm.ll new file mode 100644 index 000000000000..a6b542c29ed7 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/float-imm.ll @@ -0,0 +1,85 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch32 --mattr=+f,-d < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 --mattr=+f,-d < %s | FileCheck %s --check-prefix=LA64 + +define float @f32_positive_zero() nounwind { +; LA32-LABEL: f32_positive_zero: +; LA32: # %bb.0: +; LA32-NEXT: movgr2fr.w $fa0, $zero +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f32_positive_zero: +; LA64: # %bb.0: +; LA64-NEXT: movgr2fr.w $fa0, $zero +; LA64-NEXT: jirl $zero, $ra, 0 + ret float 0.0 +} + +define float @f32_negative_zero() nounwind { +; LA32-LABEL: f32_negative_zero: +; LA32: # %bb.0: +; LA32-NEXT: movgr2fr.w $fa0, $zero +; LA32-NEXT: fneg.s $fa0, $fa0 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f32_negative_zero: +; LA64: # %bb.0: +; LA64-NEXT: movgr2fr.w $fa0, $zero +; LA64-NEXT: fneg.s $fa0, $fa0 +; LA64-NEXT: jirl $zero, $ra, 0 + ret float -0.0 +} + +define float @f32_constant_pi() nounwind { +; LA32-LABEL: f32_constant_pi: +; LA32: # %bb.0: +; LA32-NEXT: pcalau12i $a0, .LCPI2_0 +; LA32-NEXT: addi.w $a0, $a0, .LCPI2_0 +; LA32-NEXT: fld.s $fa0, $a0, 0 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f32_constant_pi: +; LA64: # %bb.0: +; LA64-NEXT: pcalau12i $a0, .LCPI2_0 +; LA64-NEXT: addi.d $a0, $a0, .LCPI2_0 +; LA64-NEXT: fld.s $fa0, $a0, 0 +; LA64-NEXT: jirl $zero, $ra, 0 + ret float 3.14159274101257324218750 +} + +define float @f32_add_fimm1(float %a) nounwind { +; LA32-LABEL: f32_add_fimm1: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $a0, $zero, 1 +; LA32-NEXT: movgr2fr.w $fa1, $a0 +; LA32-NEXT: ffint.s.w $fa1, $fa1 +; LA32-NEXT: fadd.s $fa0, $fa0, $fa1 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f32_add_fimm1: +; LA64: # %bb.0: +; LA64-NEXT: addi.w $a0, $zero, 1 +; LA64-NEXT: movgr2fr.w $fa1, $a0 +; LA64-NEXT: ffint.s.w $fa1, $fa1 +; LA64-NEXT: fadd.s $fa0, $fa0, $fa1 +; LA64-NEXT: jirl $zero, $ra, 0 + %1 = fadd float %a, 1.0 + ret float %1 +} + +define float @f32_positive_fimm1() nounwind { +; LA32-LABEL: f32_positive_fimm1: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $a0, $zero, 1 +; LA32-NEXT: movgr2fr.w $fa0, $a0 +; LA32-NEXT: ffint.s.w $fa0, $fa0 +; LA32-NEXT: jirl $zero, $ra, 0 +; +; LA64-LABEL: f32_positive_fimm1: +; LA64: # %bb.0: +; LA64-NEXT: addi.w $a0, $zero, 1 +; LA64-NEXT: movgr2fr.w $fa0, $a0 +; LA64-NEXT: ffint.s.w $fa0, $fa0 +; LA64-NEXT: jirl $zero, $ra, 0 + ret float 1.0 +} -- 2.11.4.GIT