Skip to content

Commit dc5b4da

Browse files
quic-asaravanAwanish Pandey
andauthored
[HEXAGON] Inlining Division (#79021)
This patch inlines float division function calls for hexagon. Co-authored-by: Awanish Pandey <[email protected]>
1 parent 0065d06 commit dc5b4da

File tree

6 files changed

+168
-0
lines changed

6 files changed

+168
-0
lines changed

llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,98 @@ void HexagonDAGToDAGISel::SelectQ2V(SDNode *N) {
904904
ReplaceNode(N, T);
905905
}
906906

907+
void HexagonDAGToDAGISel::FDiv(SDNode *N) {
908+
const SDLoc &dl(N);
909+
ArrayRef<EVT> ResultType(N->value_begin(), N->value_end());
910+
SmallVector<SDValue, 2> Ops;
911+
Ops = {N->getOperand(0), N->getOperand(1)};
912+
SDVTList VTs;
913+
VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
914+
SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
915+
SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
916+
917+
SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
918+
SDNode *constNode =
919+
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
920+
921+
SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
922+
SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
923+
SDValue(constNode, 0), SDValue(D, 0),
924+
SDValue(ResScale, 0));
925+
SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
926+
SDValue(ResScale, 0), SDValue(Err, 0),
927+
SDValue(ResScale, 0));
928+
SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
929+
SDValue(constNode, 0), SDValue(D, 0),
930+
SDValue(NewRec, 0));
931+
SDNode *q = CurDAG->getMachineNode(
932+
Hexagon::A2_andir, dl, MVT::f32, SDValue(n, 0),
933+
CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
934+
SDNode *NewQ =
935+
CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(q, 0),
936+
SDValue(n, 0), SDValue(NewRec, 0));
937+
SDNode *NNewRec = CurDAG->getMachineNode(
938+
Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
939+
SDValue(newErr, 0), SDValue(NewRec, 0));
940+
SDNode *qErr =
941+
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
942+
SDValue(D, 0), SDValue(NewQ, 0));
943+
SDNode *NNewQ = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
944+
SDValue(NewQ, 0), SDValue(qErr, 0),
945+
SDValue(NNewRec, 0));
946+
947+
SDNode *NqErr =
948+
CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
949+
SDValue(NNewQ, 0), SDValue(D, 0));
950+
std::array<SDValue, 4> temp1 = {SDValue(NNewQ, 0), SDValue(NqErr, 0),
951+
SDValue(NNewRec, 0), SDValue(ResScale, 1)};
952+
ArrayRef<SDValue> OpValue1(temp1);
953+
SDNode *FinalNewQ =
954+
CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
955+
ReplaceNode(N, FinalNewQ);
956+
}
957+
958+
void HexagonDAGToDAGISel::FastFDiv(SDNode *N) {
959+
const SDLoc &dl(N);
960+
ArrayRef<EVT> ResultType(N->value_begin(), N->value_end());
961+
SmallVector<SDValue, 2> Ops;
962+
Ops = {N->getOperand(0), N->getOperand(1)};
963+
SDVTList VTs;
964+
VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
965+
SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
966+
SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
967+
968+
SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
969+
SDNode *constNode =
970+
CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
971+
972+
SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
973+
SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
974+
SDValue(constNode, 0), SDValue(D, 0),
975+
SDValue(ResScale, 0));
976+
SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
977+
SDValue(ResScale, 0), SDValue(Err, 0),
978+
SDValue(ResScale, 0));
979+
SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
980+
SDValue(constNode, 0), SDValue(D, 0),
981+
SDValue(NewRec, 0));
982+
983+
SDNode *NNewRec = CurDAG->getMachineNode(
984+
Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
985+
SDValue(newErr, 0), SDValue(NewRec, 0));
986+
SDNode *FinalNewQ = CurDAG->getMachineNode(
987+
Hexagon::F2_sfmpy, dl, MVT::f32, SDValue(NNewRec, 0), SDValue(n, 0));
988+
ReplaceNode(N, FinalNewQ);
989+
}
990+
991+
void HexagonDAGToDAGISel::SelectFDiv(SDNode *N) {
992+
if (N->getFlags().hasAllowReassociation())
993+
FastFDiv(N);
994+
else
995+
FDiv(N);
996+
return;
997+
}
998+
907999
void HexagonDAGToDAGISel::Select(SDNode *N) {
9081000
if (N->isMachineOpcode())
9091001
return N->setNodeId(-1); // Already selected.
@@ -949,6 +1041,8 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
9491041
case HexagonISD::D2P: return SelectD2P(N);
9501042
case HexagonISD::Q2V: return SelectQ2V(N);
9511043
case HexagonISD::V2Q: return SelectV2Q(N);
1044+
case ISD::FDIV:
1045+
return SelectFDiv(N);
9521046
}
9531047

9541048
SelectCode(N);

llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class HexagonDAGToDAGISel : public SelectionDAGISel {
110110
void SelectD2P(SDNode *N);
111111
void SelectQ2V(SDNode *N);
112112
void SelectV2Q(SDNode *N);
113+
void SelectFDiv(SDNode *N);
114+
void FDiv(SDNode *N);
115+
void FastFDiv(SDNode *N);
113116

114117
// Include the declarations autogenerated from the selection patterns.
115118
#define GET_DAGISEL_DECL

llvm/lib/Target/Hexagon/HexagonISelLowering.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,13 @@ bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
653653
return Subtarget.getInstrInfo()->isValidAutoIncImm(VT, V);
654654
}
655655

656+
SDValue HexagonTargetLowering::LowerFDIV(SDValue Op, SelectionDAG &DAG) const {
657+
if (DAG.getMachineFunction().getFunction().hasOptSize())
658+
return SDValue();
659+
else
660+
return Op;
661+
}
662+
656663
SDValue
657664
HexagonTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
658665
MachineFunction &MF = DAG.getMachineFunction();
@@ -1765,6 +1772,7 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
17651772
setOperationAction(ISD::FADD, MVT::f64, Expand);
17661773
setOperationAction(ISD::FSUB, MVT::f64, Expand);
17671774
setOperationAction(ISD::FMUL, MVT::f64, Expand);
1775+
setOperationAction(ISD::FDIV, MVT::f32, Custom);
17681776

17691777
setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
17701778
setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
@@ -3341,6 +3349,9 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
33413349
errs() << "Error: check for a non-legal type in this operation\n";
33423350
#endif
33433351
llvm_unreachable("Should not custom lower this!");
3352+
3353+
case ISD::FDIV:
3354+
return LowerFDIV(Op, DAG);
33443355
case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
33453356
case ISD::INSERT_SUBVECTOR: return LowerINSERT_SUBVECTOR(Op, DAG);
33463357
case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG);

llvm/lib/Target/Hexagon/HexagonISelLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class HexagonTargetLowering : public TargetLowering {
204204

205205
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
206206
SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
207+
SDValue LowerFDIV(SDValue Op, SelectionDAG &DAG) const;
207208
SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG) const;
208209
SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
209210
SDValue LowerEH_LABEL(SDValue Op, SelectionDAG &DAG) const;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; Test for checking division is inlined or not in case of Os.
2+
; RUN: llc -O2 -march=hexagon < %s | FileCheck %s
3+
4+
; Function Attrs: optsize
5+
define dso_local i32 @testInt(i32 %a, i32 %b) local_unnamed_addr #0 {
6+
entry:
7+
;CHECK: call __hexagon_divsi3
8+
%div = sdiv i32 %a, %b
9+
%conv = sitofp i32 %div to float
10+
%conv1 = fptosi float %conv to i32
11+
ret i32 %conv1
12+
}
13+
14+
; Function Attrs: optsize
15+
define dso_local float @testFloat(float %a, float %b) local_unnamed_addr #0 {
16+
entry:
17+
;CHECK: call __hexagon_divsf3
18+
%div = fdiv float %a, %b
19+
ret float %div
20+
}
21+
22+
; Function Attrs: optsize
23+
define dso_local double @testDouble(double %a, double %b) local_unnamed_addr #0 {
24+
entry:
25+
;CHECK: call __hexagon_divdf3
26+
%div = fdiv double %a, %b
27+
ret double %div
28+
}
29+
30+
attributes #0 = { optsize }
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
; Test for checking division is inlined or not in case of Os.
2+
; RUN: llc -O2 -march=hexagon < %s | FileCheck %s
3+
4+
define dso_local i32 @testInt(i32 %a, i32 %b) local_unnamed_addr {
5+
entry:
6+
;CHECK: call __hexagon_divsi3
7+
%div = sdiv i32 %a, %b
8+
%conv = sitofp i32 %div to float
9+
%conv1 = fptosi float %conv to i32
10+
ret i32 %conv1
11+
}
12+
13+
define dso_local float @testFloat(float %a, float %b) local_unnamed_addr {
14+
entry:
15+
;CHECK-NOT: call __hexagon_divsf3
16+
;CHECK: sfrecipa
17+
;CHECK: sffixupn
18+
;CHEKC: and
19+
;CHECK: sfmpy
20+
%div = fdiv float %a, %b
21+
ret float %div
22+
}
23+
24+
define dso_local double @testDouble(double %a, double %b) local_unnamed_addr {
25+
entry:
26+
;CHECK: call __hexagon_divdf3
27+
%div = fdiv double %a, %b
28+
ret double %div
29+
}

0 commit comments

Comments
 (0)