https://github.com/quic-asaravan created https://github.com/llvm/llvm-project/pull/79021
This patch inlines float division function calls for hexagon. >From e8beb77010becb9a9c82d875597bdedbfed9be9e Mon Sep 17 00:00:00 2001 From: Awanish Pandey <awanp...@codeaurora.org> Date: Sun, 6 Sep 2020 14:39:57 +0530 Subject: [PATCH] [HEXAGON] Inlining division This patch inlines float division function calls for hexagon. --- .../Target/Hexagon/HexagonISelDAGToDAG.cpp | 94 +++++++++++++++++++ llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h | 3 + .../Target/Hexagon/HexagonISelLowering.cpp | 11 +++ llvm/lib/Target/Hexagon/HexagonISelLowering.h | 1 + .../CodeGen/Hexagon/inline-division-space.ll | 30 ++++++ llvm/test/CodeGen/Hexagon/inline-division.ll | 29 ++++++ 6 files changed, 168 insertions(+) create mode 100644 llvm/test/CodeGen/Hexagon/inline-division-space.ll create mode 100644 llvm/test/CodeGen/Hexagon/inline-division.ll diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index e4127b0b94c625..6fe3fe0d36b9e7 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -904,6 +904,98 @@ void HexagonDAGToDAGISel::SelectQ2V(SDNode *N) { ReplaceNode(N, T); } +void HexagonDAGToDAGISel::FDiv(SDNode *N) { + const SDLoc &dl(N); + ArrayRef<EVT> ResultType(N->value_begin(), N->value_end()); + SmallVector<SDValue, 2> Ops; + Ops = {N->getOperand(0), N->getOperand(1)}; + SDVTList VTs; + VTs = CurDAG->getVTList(MVT::f32, MVT::f32); + SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops); + SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops); + + SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32); + SDNode *constNode = + CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C); + + SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops); + SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, + SDValue(constNode, 0), SDValue(D, 0), + SDValue(ResScale, 0)); + SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, + SDValue(ResScale, 0), SDValue(Err, 0), + SDValue(ResScale, 0)); + SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, + SDValue(constNode, 0), SDValue(D, 0), + SDValue(NewRec, 0)); + SDNode *q = CurDAG->getMachineNode( + Hexagon::A2_andir, dl, MVT::f32, SDValue(n, 0), + CurDAG->getTargetConstant(0x80000000, dl, MVT::i32)); + SDNode *NewQ = + CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(q, 0), + SDValue(n, 0), SDValue(NewRec, 0)); + SDNode *NNewRec = CurDAG->getMachineNode( + Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0), + SDValue(newErr, 0), SDValue(NewRec, 0)); + SDNode *qErr = + CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0), + SDValue(D, 0), SDValue(NewQ, 0)); + SDNode *NNewQ = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, + SDValue(NewQ, 0), SDValue(qErr, 0), + SDValue(NNewRec, 0)); + + SDNode *NqErr = + CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0), + SDValue(NNewQ, 0), SDValue(D, 0)); + std::array<SDValue, 4> temp1 = {SDValue(NNewQ, 0), SDValue(NqErr, 0), + SDValue(NNewRec, 0), SDValue(ResScale, 1)}; + ArrayRef<SDValue> OpValue1(temp1); + SDNode *FinalNewQ = + CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1); + ReplaceNode(N, FinalNewQ); +} + +void HexagonDAGToDAGISel::FastFDiv(SDNode *N) { + const SDLoc &dl(N); + ArrayRef<EVT> ResultType(N->value_begin(), N->value_end()); + SmallVector<SDValue, 2> Ops; + Ops = {N->getOperand(0), N->getOperand(1)}; + SDVTList VTs; + VTs = CurDAG->getVTList(MVT::f32, MVT::f32); + SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops); + SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops); + + SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32); + SDNode *constNode = + CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C); + + SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops); + SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, + SDValue(constNode, 0), SDValue(D, 0), + SDValue(ResScale, 0)); + SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, + SDValue(ResScale, 0), SDValue(Err, 0), + SDValue(ResScale, 0)); + SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, + SDValue(constNode, 0), SDValue(D, 0), + SDValue(NewRec, 0)); + + SDNode *NNewRec = CurDAG->getMachineNode( + Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0), + SDValue(newErr, 0), SDValue(NewRec, 0)); + SDNode *FinalNewQ = CurDAG->getMachineNode( + Hexagon::F2_sfmpy, dl, MVT::f32, SDValue(NNewRec, 0), SDValue(n, 0)); + ReplaceNode(N, FinalNewQ); +} + +void HexagonDAGToDAGISel::SelectFDiv(SDNode *N) { + if (N->getFlags().hasAllowReassociation()) + FastFDiv(N); + else + FDiv(N); + return; +} + void HexagonDAGToDAGISel::Select(SDNode *N) { if (N->isMachineOpcode()) return N->setNodeId(-1); // Already selected. @@ -949,6 +1041,8 @@ void HexagonDAGToDAGISel::Select(SDNode *N) { case HexagonISD::D2P: return SelectD2P(N); case HexagonISD::Q2V: return SelectQ2V(N); case HexagonISD::V2Q: return SelectV2Q(N); + case ISD::FDIV: + return SelectFDiv(N); } SelectCode(N); diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h index 8fb1760936e819..50162b10799643 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h +++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h @@ -110,6 +110,9 @@ class HexagonDAGToDAGISel : public SelectionDAGISel { void SelectD2P(SDNode *N); void SelectQ2V(SDNode *N); void SelectV2Q(SDNode *N); + void SelectFDiv(SDNode *N); + void FDiv(SDNode *N); + void FastFDiv(SDNode *N); // Include the declarations autogenerated from the selection patterns. #define GET_DAGISEL_DECL diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 51138091f4a558..13691053ddd707 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -653,6 +653,13 @@ bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, return Subtarget.getInstrInfo()->isValidAutoIncImm(VT, V); } +SDValue HexagonTargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const { + if (DAG.getMachineFunction().getFunction().hasOptSize()) + return SDValue(); + else + return Op; +} + SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); @@ -1765,6 +1772,7 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, setOperationAction(ISD::FADD, MVT::f64, Expand); setOperationAction(ISD::FSUB, MVT::f64, Expand); setOperationAction(ISD::FMUL, MVT::f64, Expand); + setOperationAction(ISD::FDIV, MVT::f32, Custom); setOperationAction(ISD::FMINNUM, MVT::f32, Legal); setOperationAction(ISD::FMAXNUM, MVT::f32, Legal); @@ -3341,6 +3349,9 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { errs() << "Error: check for a non-legal type in this operation\n"; #endif llvm_unreachable("Should not custom lower this!"); + + case ISD::FDIV: + return LowerFDIV(Op, DAG); case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); case ISD::INSERT_SUBVECTOR: return LowerINSERT_SUBVECTOR(Op, DAG); case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG); diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h index 8c7d0b70f38578..cb09e5b17843e0 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -204,6 +204,7 @@ class HexagonTargetLowering : public TargetLowering { SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFDIV(SDValue Op, SelectionDAG &DAG) const; SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG) const; SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const; SDValue LowerEH_LABEL(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/test/CodeGen/Hexagon/inline-division-space.ll b/llvm/test/CodeGen/Hexagon/inline-division-space.ll new file mode 100644 index 00000000000000..9cf3c5c8b2b84b --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/inline-division-space.ll @@ -0,0 +1,30 @@ +; Test for checking division is inlined or not in case of Os. +; RUN: llc -O2 -march=hexagon < %s | FileCheck %s + +; Function Attrs: optsize +define dso_local i32 @testInt(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: +;CHECK: call __hexagon_divsi3 + %div = sdiv i32 %a, %b + %conv = sitofp i32 %div to float + %conv1 = fptosi float %conv to i32 + ret i32 %conv1 +} + +; Function Attrs: optsize +define dso_local float @testFloat(float %a, float %b) local_unnamed_addr #0 { +entry: +;CHECK: call __hexagon_divsf3 + %div = fdiv float %a, %b + ret float %div +} + +; Function Attrs: optsize +define dso_local double @testDouble(double %a, double %b) local_unnamed_addr #0 { +entry: +;CHECK: call __hexagon_divdf3 + %div = fdiv double %a, %b + ret double %div +} + +attributes #0 = { optsize } diff --git a/llvm/test/CodeGen/Hexagon/inline-division.ll b/llvm/test/CodeGen/Hexagon/inline-division.ll new file mode 100644 index 00000000000000..7249a3f55e8683 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/inline-division.ll @@ -0,0 +1,29 @@ +; Test for checking division is inlined or not in case of Os. +; RUN: llc -O2 -march=hexagon < %s | FileCheck %s + +define dso_local i32 @testInt(i32 %a, i32 %b) local_unnamed_addr { +entry: +;CHECK: call __hexagon_divsi3 + %div = sdiv i32 %a, %b + %conv = sitofp i32 %div to float + %conv1 = fptosi float %conv to i32 + ret i32 %conv1 +} + +define dso_local float @testFloat(float %a, float %b) local_unnamed_addr { +entry: +;CHECK-NOT: call __hexagon_divsf3 +;CHECK: sfrecipa +;CHECK: sffixupn +;CHEKC: and +;CHECK: sfmpy + %div = fdiv float %a, %b + ret float %div +} + +define dso_local double @testDouble(double %a, double %b) local_unnamed_addr { +entry: +;CHECK: call __hexagon_divdf3 + %div = fdiv double %a, %b + ret double %div +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits