187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//===- subzero/src/IceSwitchLowering.h - Switch lowering --------*- C++ -*-===//
287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//
387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//                     The LLVM Compiler Infrastructure
487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//
587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull// This file is distributed under the University of Illinois Open Source
687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull// License. See LICENSE.TXT for details.
787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//
887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//===----------------------------------------------------------------------===//
987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull///
1087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Helpers for switch lowering.
1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth///
1387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull//===----------------------------------------------------------------------===//
1487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
1587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull#ifndef SUBZERO_SRC_ICESWITCHLOWERING_H
1687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull#define SUBZERO_SRC_ICESWITCHLOWERING_H
1787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
1886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull#include "IceDefs.h"
19467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth#include "IceStringPool.h"
2087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
21030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto#include <string>
22030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto
2387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullnamespace Ice {
2487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
2587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass CaseCluster;
2687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
2700741a005cf242d2e9108f7cc7c454246e13741cAndrew Scullusing CaseClusterArray = CfgVector<CaseCluster>;
2887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
2987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull/// A cluster of cases can be tested by a common method during switch lowering.
3087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullclass CaseCluster {
3187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CaseCluster() = delete;
3287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
3387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullpublic:
3487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  enum CaseClusterKind {
3587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    Range,     /// Numerically adjacent case values with same target.
3687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    JumpTable, /// Different targets and possibly sparse.
3787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  };
3887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
3987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CaseCluster(const CaseCluster &) = default;
4087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CaseCluster &operator=(const CaseCluster &) = default;
4187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
4287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// Create a cluster of a single case represented by a unitary range.
4386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CaseCluster(uint64_t Value, CfgNode *Target)
4486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull      : Kind(Range), Low(Value), High(Value), Target(Target) {}
4587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// Create a case consisting of a jump table.
4687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CaseCluster(uint64_t Low, uint64_t High, InstJumpTable *JT)
4787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull      : Kind(JumpTable), Low(Low), High(High), JT(JT) {}
4887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
4987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CaseClusterKind getKind() const { return Kind; }
5087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  uint64_t getLow() const { return Low; }
5187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  uint64_t getHigh() const { return High; }
5286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  CfgNode *getTarget() const {
5387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(Kind == Range);
5486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    return Target;
5587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
5687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  InstJumpTable *getJumpTable() const {
5787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    assert(Kind == JumpTable);
5887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    return JT;
5987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  }
6087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
6186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  bool isUnitRange() const { return Low == High; }
6286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  bool isPairRange() const { return Low == High - 1; }
6386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
6487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// Discover cases which can be clustered together and return the clusters
6587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// ordered by case value.
668cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth  static CaseClusterArray clusterizeSwitch(Cfg *Func, const InstSwitch *Instr);
6787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
6887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scullprivate:
6987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  CaseClusterKind Kind;
7087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  uint64_t Low;
7187f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  uint64_t High;
7287f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  union {
7386df4e9e6d183f07638440afd2c225b485c03917Andrew Scull    CfgNode *Target;   /// Target for a range.
7487f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull    InstJumpTable *JT; /// Jump table targets.
7587f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  };
7687f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
7787f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  /// Try and append a cluster returning whether or not it was successful.
7887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull  bool tryAppend(const CaseCluster &New);
7987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull};
8087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
8157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// Store the jump table data so that it can be emitted later in the correct ELF
8257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull/// section once the offsets from the start of the function are known.
8386df4e9e6d183f07638440afd2c225b485c03917Andrew Scullclass JumpTableData {
8486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  JumpTableData() = delete;
8586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  JumpTableData &operator=(const JumpTableData &) = delete;
8686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
8786df4e9e6d183f07638440afd2c225b485c03917Andrew Scullpublic:
880fe6b5448002000c97eccc62e02a4a73e15a9e9aDavid Sehr  using TargetList = std::vector<intptr_t>;
890fe6b5448002000c97eccc62e02a4a73e15a9e9aDavid Sehr
90030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  JumpTableData(GlobalString Name, GlobalString FuncName, SizeT Id,
910fe6b5448002000c97eccc62e02a4a73e15a9e9aDavid Sehr                const TargetList &TargetOffsets)
92030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto      : Name(Name), FuncName(FuncName), Id(Id), TargetOffsets(TargetOffsets) {}
931eda90a112993eb171b8f60e5470b554e59542afAndrew Scull  JumpTableData(const JumpTableData &) = default;
9486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  JumpTableData(JumpTableData &&) = default;
951eda90a112993eb171b8f60e5470b554e59542afAndrew Scull  JumpTableData &operator=(JumpTableData &&) = default;
9686df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
97030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString getName() const { return Name; }
98030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString getFunctionName() const { return FuncName; }
9986df4e9e6d183f07638440afd2c225b485c03917Andrew Scull  SizeT getId() const { return Id; }
1000fe6b5448002000c97eccc62e02a4a73e15a9e9aDavid Sehr  const TargetList &getTargetOffsets() const { return TargetOffsets; }
101030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  static std::string createSectionName(const GlobalString Name) {
102030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    if (Name.hasStdString()) {
103030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto      return Name.toString() + "$jumptable";
104030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    }
105030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto    return std::to_string(Name.getID()) + "$jumptable";
106030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  }
107030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  std::string getSectionName() const { return createSectionName(FuncName); }
10886df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
10986df4e9e6d183f07638440afd2c225b485c03917Andrew Scullprivate:
110030772114216c1a57c749050bb58d07de8ceaa7cJohn Porto  GlobalString Name;
111467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  GlobalString FuncName;
1121eda90a112993eb171b8f60e5470b554e59542afAndrew Scull  SizeT Id;
1130fe6b5448002000c97eccc62e02a4a73e15a9e9aDavid Sehr  TargetList TargetOffsets;
11486df4e9e6d183f07638440afd2c225b485c03917Andrew Scull};
11586df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
11686df4e9e6d183f07638440afd2c225b485c03917Andrew Scullusing JumpTableDataList = std::vector<JumpTableData>;
11786df4e9e6d183f07638440afd2c225b485c03917Andrew Scull
11887f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull} // end of namespace Ice
11987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull
12087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull#endif //  SUBZERO_SRC_ICESWITCHLOWERING_H
121