Hexagon: Avoid left shifting negative values (it's UB)
[oota-llvm.git] / lib / Target / Hexagon / MCTargetDesc / HexagonShuffler.h
1 //===----- HexagonShuffler.h - Instruction bundle shuffling ---------------===//
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 // This implements the shuffling of insns inside a bundle according to the
11 // packet formation rules of the Hexagon ISA.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef HEXAGONSHUFFLER_H
16 #define HEXAGONSHUFFLER_H
17
18 #include "Hexagon.h"
19 #include "MCTargetDesc/HexagonMCInstrInfo.h"
20
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/MC/MCInstrInfo.h"
23
24 using namespace llvm;
25
26 namespace llvm {
27 // Insn resources.
28 class HexagonResource {
29   // Mask of the slots or units that may execute the insn and
30   // the weight or priority that the insn requires to be assigned a slot.
31   unsigned Slots, Weight;
32
33 public:
34   HexagonResource(unsigned s) { setUnits(s); };
35
36   void setUnits(unsigned s) {
37     Slots = s & ~(~0U << HEXAGON_PACKET_SIZE);
38     setWeight(s);
39   };
40   unsigned setWeight(unsigned s);
41
42   unsigned getUnits() const { return (Slots); };
43   unsigned getWeight() const { return (Weight); };
44
45   // Check if the resources are in ascending slot order.
46   static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
47     return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
48   };
49   // Check if the resources are in ascending weight order.
50   static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
51     return (A.getWeight() < B.getWeight());
52   };
53 };
54
55 // Handle to an insn used by the shuffling algorithm.
56 class HexagonInstr {
57   friend class HexagonShuffler;
58
59   MCInst const *ID;
60   MCInst const *Extender;
61   HexagonResource Core;
62   bool SoloException;
63
64 public:
65   HexagonInstr(MCInst const *id, MCInst const *Extender, unsigned s,
66                bool x = false)
67       : ID(id), Extender(Extender), Core(s), SoloException(x){};
68
69   MCInst const *getDesc() const { return (ID); };
70
71   MCInst const *getExtender() const { return Extender; }
72
73   unsigned isSoloException() const { return (SoloException); };
74
75   // Check if the handles are in ascending order for shuffling purposes.
76   bool operator<(const HexagonInstr &B) const {
77     return (HexagonResource::lessWeight(B.Core, Core));
78   };
79   // Check if the handles are in ascending order by core slots.
80   static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
81     return (HexagonResource::lessUnits(A.Core, B.Core));
82   };
83 };
84
85 // Bundle shuffler.
86 class HexagonShuffler {
87   typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>
88       HexagonPacket;
89
90   // Insn handles in a bundle.
91   HexagonPacket Packet;
92
93   // Shuffling error code.
94   unsigned Error;
95
96 protected:
97   int64_t BundleFlags;
98   MCInstrInfo const &MCII;
99   MCSubtargetInfo const &STI;
100
101 public:
102   typedef HexagonPacket::iterator iterator;
103
104   enum {
105     SHUFFLE_SUCCESS = 0,    ///< Successful operation.
106     SHUFFLE_ERROR_INVALID,  ///< Invalid bundle.
107     SHUFFLE_ERROR_STORES,   ///< No free slots for store insns.
108     SHUFFLE_ERROR_LOADS,    ///< No free slots for load insns.
109     SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.
110     SHUFFLE_ERROR_NOSLOTS,  ///< No free slots for other insns.
111     SHUFFLE_ERROR_SLOTS,    ///< Over-subscribed slots.
112     SHUFFLE_ERROR_UNKNOWN   ///< Unknown error.
113   };
114
115   explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
116
117   // Reset to initial state.
118   void reset();
119   // Check if the bundle may be validly shuffled.
120   bool check();
121   // Reorder the insn handles in the bundle.
122   bool shuffle();
123
124   unsigned size() const { return (Packet.size()); };
125
126   iterator begin() { return (Packet.begin()); };
127   iterator end() { return (Packet.end()); };
128
129   // Add insn handle to the bundle .
130   void append(MCInst const *ID, MCInst const *Extender, unsigned S,
131               bool X = false);
132
133   // Return the error code for the last check or shuffling of the bundle.
134   void setError(unsigned Err) { Error = Err; };
135   unsigned getError() const { return (Error); };
136 };
137 }
138
139 #endif // HEXAGONSHUFFLER_H