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