xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceSwitchLowering.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceSwitchLowering.h - Switch lowering --------*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Helpers for switch lowering.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICESWITCHLOWERING_H
16*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICESWITCHLOWERING_H
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h"
20*03ce13f7SAndroid Build Coastguard Worker 
21*03ce13f7SAndroid Build Coastguard Worker #include <string>
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker class CaseCluster;
26*03ce13f7SAndroid Build Coastguard Worker 
27*03ce13f7SAndroid Build Coastguard Worker using CaseClusterArray = CfgVector<CaseCluster>;
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker /// A cluster of cases can be tested by a common method during switch lowering.
30*03ce13f7SAndroid Build Coastguard Worker class CaseCluster {
31*03ce13f7SAndroid Build Coastguard Worker   CaseCluster() = delete;
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker public:
34*03ce13f7SAndroid Build Coastguard Worker   enum CaseClusterKind {
35*03ce13f7SAndroid Build Coastguard Worker     Range,     /// Numerically adjacent case values with same target.
36*03ce13f7SAndroid Build Coastguard Worker     JumpTable, /// Different targets and possibly sparse.
37*03ce13f7SAndroid Build Coastguard Worker   };
38*03ce13f7SAndroid Build Coastguard Worker 
39*03ce13f7SAndroid Build Coastguard Worker   CaseCluster(const CaseCluster &) = default;
40*03ce13f7SAndroid Build Coastguard Worker   CaseCluster &operator=(const CaseCluster &) = default;
41*03ce13f7SAndroid Build Coastguard Worker 
42*03ce13f7SAndroid Build Coastguard Worker   /// Create a cluster of a single case represented by a unitary range.
CaseCluster(uint64_t Value,CfgNode * Target)43*03ce13f7SAndroid Build Coastguard Worker   CaseCluster(uint64_t Value, CfgNode *Target)
44*03ce13f7SAndroid Build Coastguard Worker       : Kind(Range), Low(Value), High(Value), Target(Target) {}
45*03ce13f7SAndroid Build Coastguard Worker   /// Create a case consisting of a jump table.
CaseCluster(uint64_t Low,uint64_t High,InstJumpTable * JT)46*03ce13f7SAndroid Build Coastguard Worker   CaseCluster(uint64_t Low, uint64_t High, InstJumpTable *JT)
47*03ce13f7SAndroid Build Coastguard Worker       : Kind(JumpTable), Low(Low), High(High), JT(JT) {}
48*03ce13f7SAndroid Build Coastguard Worker 
getKind()49*03ce13f7SAndroid Build Coastguard Worker   CaseClusterKind getKind() const { return Kind; }
getLow()50*03ce13f7SAndroid Build Coastguard Worker   uint64_t getLow() const { return Low; }
getHigh()51*03ce13f7SAndroid Build Coastguard Worker   uint64_t getHigh() const { return High; }
getTarget()52*03ce13f7SAndroid Build Coastguard Worker   CfgNode *getTarget() const {
53*03ce13f7SAndroid Build Coastguard Worker     assert(Kind == Range);
54*03ce13f7SAndroid Build Coastguard Worker     return Target;
55*03ce13f7SAndroid Build Coastguard Worker   }
getJumpTable()56*03ce13f7SAndroid Build Coastguard Worker   InstJumpTable *getJumpTable() const {
57*03ce13f7SAndroid Build Coastguard Worker     assert(Kind == JumpTable);
58*03ce13f7SAndroid Build Coastguard Worker     return JT;
59*03ce13f7SAndroid Build Coastguard Worker   }
60*03ce13f7SAndroid Build Coastguard Worker 
isUnitRange()61*03ce13f7SAndroid Build Coastguard Worker   bool isUnitRange() const { return Low == High; }
isPairRange()62*03ce13f7SAndroid Build Coastguard Worker   bool isPairRange() const { return Low == High - 1; }
63*03ce13f7SAndroid Build Coastguard Worker 
64*03ce13f7SAndroid Build Coastguard Worker   /// Discover cases which can be clustered together and return the clusters
65*03ce13f7SAndroid Build Coastguard Worker   /// ordered by case value.
66*03ce13f7SAndroid Build Coastguard Worker   static CaseClusterArray clusterizeSwitch(Cfg *Func, const InstSwitch *Instr);
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker private:
69*03ce13f7SAndroid Build Coastguard Worker   CaseClusterKind Kind;
70*03ce13f7SAndroid Build Coastguard Worker   uint64_t Low;
71*03ce13f7SAndroid Build Coastguard Worker   uint64_t High;
72*03ce13f7SAndroid Build Coastguard Worker   union {
73*03ce13f7SAndroid Build Coastguard Worker     CfgNode *Target;   /// Target for a range.
74*03ce13f7SAndroid Build Coastguard Worker     InstJumpTable *JT; /// Jump table targets.
75*03ce13f7SAndroid Build Coastguard Worker   };
76*03ce13f7SAndroid Build Coastguard Worker 
77*03ce13f7SAndroid Build Coastguard Worker   /// Try and append a cluster returning whether or not it was successful.
78*03ce13f7SAndroid Build Coastguard Worker   bool tryAppend(const CaseCluster &New);
79*03ce13f7SAndroid Build Coastguard Worker };
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker /// Store the jump table data so that it can be emitted later in the correct ELF
82*03ce13f7SAndroid Build Coastguard Worker /// section once the offsets from the start of the function are known.
83*03ce13f7SAndroid Build Coastguard Worker class JumpTableData {
84*03ce13f7SAndroid Build Coastguard Worker   JumpTableData() = delete;
85*03ce13f7SAndroid Build Coastguard Worker   JumpTableData &operator=(const JumpTableData &) = delete;
86*03ce13f7SAndroid Build Coastguard Worker 
87*03ce13f7SAndroid Build Coastguard Worker public:
88*03ce13f7SAndroid Build Coastguard Worker   using TargetList = std::vector<intptr_t>;
89*03ce13f7SAndroid Build Coastguard Worker 
JumpTableData(GlobalString Name,GlobalString FuncName,SizeT Id,const TargetList & TargetOffsets)90*03ce13f7SAndroid Build Coastguard Worker   JumpTableData(GlobalString Name, GlobalString FuncName, SizeT Id,
91*03ce13f7SAndroid Build Coastguard Worker                 const TargetList &TargetOffsets)
92*03ce13f7SAndroid Build Coastguard Worker       : Name(Name), FuncName(FuncName), Id(Id), TargetOffsets(TargetOffsets) {}
93*03ce13f7SAndroid Build Coastguard Worker   JumpTableData(const JumpTableData &) = default;
94*03ce13f7SAndroid Build Coastguard Worker   JumpTableData(JumpTableData &&) = default;
95*03ce13f7SAndroid Build Coastguard Worker   JumpTableData &operator=(JumpTableData &&) = default;
96*03ce13f7SAndroid Build Coastguard Worker 
getName()97*03ce13f7SAndroid Build Coastguard Worker   GlobalString getName() const { return Name; }
getFunctionName()98*03ce13f7SAndroid Build Coastguard Worker   GlobalString getFunctionName() const { return FuncName; }
getId()99*03ce13f7SAndroid Build Coastguard Worker   SizeT getId() const { return Id; }
getTargetOffsets()100*03ce13f7SAndroid Build Coastguard Worker   const TargetList &getTargetOffsets() const { return TargetOffsets; }
createSectionName(const GlobalString Name)101*03ce13f7SAndroid Build Coastguard Worker   static std::string createSectionName(const GlobalString Name) {
102*03ce13f7SAndroid Build Coastguard Worker     if (Name.hasStdString()) {
103*03ce13f7SAndroid Build Coastguard Worker       return Name.toString() + "$jumptable";
104*03ce13f7SAndroid Build Coastguard Worker     }
105*03ce13f7SAndroid Build Coastguard Worker     return std::to_string(Name.getID()) + "$jumptable";
106*03ce13f7SAndroid Build Coastguard Worker   }
getSectionName()107*03ce13f7SAndroid Build Coastguard Worker   std::string getSectionName() const { return createSectionName(FuncName); }
108*03ce13f7SAndroid Build Coastguard Worker 
109*03ce13f7SAndroid Build Coastguard Worker private:
110*03ce13f7SAndroid Build Coastguard Worker   GlobalString Name;
111*03ce13f7SAndroid Build Coastguard Worker   GlobalString FuncName;
112*03ce13f7SAndroid Build Coastguard Worker   SizeT Id;
113*03ce13f7SAndroid Build Coastguard Worker   TargetList TargetOffsets;
114*03ce13f7SAndroid Build Coastguard Worker };
115*03ce13f7SAndroid Build Coastguard Worker 
116*03ce13f7SAndroid Build Coastguard Worker using JumpTableDataList = std::vector<JumpTableData>;
117*03ce13f7SAndroid Build Coastguard Worker 
118*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
119*03ce13f7SAndroid Build Coastguard Worker 
120*03ce13f7SAndroid Build Coastguard Worker #endif //  SUBZERO_SRC_ICESWITCHLOWERING_H
121