blob: 57dd8288079b9e173095b2ebcb073d927b7ea52a [file] [log] [blame]
Andrew Scull87f80c12015-07-20 10:19:16 -07001//===- 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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Helpers for switch lowering.
12///
Andrew Scull87f80c12015-07-20 10:19:16 -070013//===----------------------------------------------------------------------===//
14
15#ifndef SUBZERO_SRC_ICESWITCHLOWERING_H
16#define SUBZERO_SRC_ICESWITCHLOWERING_H
17
Andrew Scull86df4e92015-07-30 13:54:44 -070018#include "IceDefs.h"
Jim Stichnoth467ffe52016-03-29 15:01:06 -070019#include "IceStringPool.h"
Andrew Scull87f80c12015-07-20 10:19:16 -070020
John Porto03077212016-04-05 06:30:21 -070021#include <string>
22
Andrew Scull87f80c12015-07-20 10:19:16 -070023namespace Ice {
24
25class CaseCluster;
26
Andrew Scull00741a02015-09-16 19:04:09 -070027using CaseClusterArray = CfgVector<CaseCluster>;
Andrew Scull87f80c12015-07-20 10:19:16 -070028
29/// A cluster of cases can be tested by a common method during switch lowering.
30class CaseCluster {
31 CaseCluster() = delete;
32
33public:
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.
Andrew Scull86df4e92015-07-30 13:54:44 -070043 CaseCluster(uint64_t Value, CfgNode *Target)
44 : Kind(Range), Low(Value), High(Value), Target(Target) {}
Andrew Scull87f80c12015-07-20 10:19:16 -070045 /// Create a case consisting of a jump table.
46 CaseCluster(uint64_t Low, uint64_t High, InstJumpTable *JT)
47 : Kind(JumpTable), Low(Low), High(High), JT(JT) {}
48
49 CaseClusterKind getKind() const { return Kind; }
50 uint64_t getLow() const { return Low; }
51 uint64_t getHigh() const { return High; }
Andrew Scull86df4e92015-07-30 13:54:44 -070052 CfgNode *getTarget() const {
Andrew Scull87f80c12015-07-20 10:19:16 -070053 assert(Kind == Range);
Andrew Scull86df4e92015-07-30 13:54:44 -070054 return Target;
Andrew Scull87f80c12015-07-20 10:19:16 -070055 }
56 InstJumpTable *getJumpTable() const {
57 assert(Kind == JumpTable);
58 return JT;
59 }
60
Andrew Scull86df4e92015-07-30 13:54:44 -070061 bool isUnitRange() const { return Low == High; }
62 bool isPairRange() const { return Low == High - 1; }
63
Andrew Scull87f80c12015-07-20 10:19:16 -070064 /// Discover cases which can be clustered together and return the clusters
65 /// ordered by case value.
Jim Stichnoth8cfeb692016-02-05 09:50:02 -080066 static CaseClusterArray clusterizeSwitch(Cfg *Func, const InstSwitch *Instr);
Andrew Scull87f80c12015-07-20 10:19:16 -070067
68private:
69 CaseClusterKind Kind;
70 uint64_t Low;
71 uint64_t High;
72 union {
Andrew Scull86df4e92015-07-30 13:54:44 -070073 CfgNode *Target; /// Target for a range.
Andrew Scull87f80c12015-07-20 10:19:16 -070074 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
Andrew Scull57e12682015-09-16 11:30:19 -070081/// 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.
Andrew Scull86df4e92015-07-30 13:54:44 -070083class JumpTableData {
84 JumpTableData() = delete;
Andrew Scull86df4e92015-07-30 13:54:44 -070085 JumpTableData &operator=(const JumpTableData &) = delete;
86
87public:
David Sehr0fe6b542015-11-19 21:47:15 -080088 using TargetList = std::vector<intptr_t>;
89
John Porto03077212016-04-05 06:30:21 -070090 JumpTableData(GlobalString Name, GlobalString FuncName, SizeT Id,
David Sehr0fe6b542015-11-19 21:47:15 -080091 const TargetList &TargetOffsets)
John Porto03077212016-04-05 06:30:21 -070092 : Name(Name), FuncName(FuncName), Id(Id), TargetOffsets(TargetOffsets) {}
Andrew Scull1eda90a2015-08-04 17:03:19 -070093 JumpTableData(const JumpTableData &) = default;
Andrew Scull86df4e92015-07-30 13:54:44 -070094 JumpTableData(JumpTableData &&) = default;
Andrew Scull1eda90a2015-08-04 17:03:19 -070095 JumpTableData &operator=(JumpTableData &&) = default;
Andrew Scull86df4e92015-07-30 13:54:44 -070096
John Porto03077212016-04-05 06:30:21 -070097 GlobalString getName() const { return Name; }
98 GlobalString getFunctionName() const { return FuncName; }
Andrew Scull86df4e92015-07-30 13:54:44 -070099 SizeT getId() const { return Id; }
David Sehr0fe6b542015-11-19 21:47:15 -0800100 const TargetList &getTargetOffsets() const { return TargetOffsets; }
John Porto03077212016-04-05 06:30:21 -0700101 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 }
107 std::string getSectionName() const { return createSectionName(FuncName); }
Andrew Scull86df4e92015-07-30 13:54:44 -0700108
109private:
John Porto03077212016-04-05 06:30:21 -0700110 GlobalString Name;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700111 GlobalString FuncName;
Andrew Scull1eda90a2015-08-04 17:03:19 -0700112 SizeT Id;
David Sehr0fe6b542015-11-19 21:47:15 -0800113 TargetList TargetOffsets;
Andrew Scull86df4e92015-07-30 13:54:44 -0700114};
115
116using JumpTableDataList = std::vector<JumpTableData>;
117
Andrew Scull87f80c12015-07-20 10:19:16 -0700118} // end of namespace Ice
119
120#endif // SUBZERO_SRC_ICESWITCHLOWERING_H