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