1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
//===----- HexagonMCChecker.h - Instruction bundle checking ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements the checking of insns inside a bundle according to the
// packet constraint rules of the Hexagon ISA.
//
//===----------------------------------------------------------------------===//
#ifndef HEXAGONMCCHECKER_H
#define HEXAGONMCCHECKER_H
#include "MCTargetDesc/HexagonMCShuffler.h"
#include <queue>
#include <set>
using namespace llvm;
namespace llvm {
class MCOperandInfo;
/// Check for a valid bundle.
class HexagonMCChecker {
MCContext &Context;
MCInst &MCB;
const MCRegisterInfo &RI;
MCInstrInfo const &MCII;
MCSubtargetInfo const &STI;
bool ReportErrors;
/// Set of definitions: register #, if predicated, if predicated true.
typedef std::pair<unsigned, bool> PredSense;
static const PredSense Unconditional;
typedef std::multiset<PredSense> PredSet;
typedef std::multiset<PredSense>::iterator PredSetIterator;
typedef llvm::DenseMap<unsigned, PredSet>::iterator DefsIterator;
llvm::DenseMap<unsigned, PredSet> Defs;
/// Information about how a new-value register is defined or used:
/// PredReg = predicate register, 0 if use/def not predicated,
/// Cond = true/false for if(PredReg)/if(!PredReg) respectively,
/// IsFloat = true if definition produces a floating point value
/// (not valid for uses),
/// IsNVJ = true if the use is a new-value branch (not valid for
/// definitions).
struct NewSense {
unsigned PredReg;
bool IsFloat, IsNVJ, Cond;
// The special-case "constructors":
static NewSense Jmp(bool isNVJ) {
NewSense NS = {/*PredReg=*/0, /*IsFloat=*/false, /*IsNVJ=*/isNVJ,
/*Cond=*/false};
return NS;
}
static NewSense Use(unsigned PR, bool True) {
NewSense NS = {/*PredReg=*/PR, /*IsFloat=*/false, /*IsNVJ=*/false,
/*Cond=*/True};
return NS;
}
static NewSense Def(unsigned PR, bool True, bool Float) {
NewSense NS = {/*PredReg=*/PR, /*IsFloat=*/Float, /*IsNVJ=*/false,
/*Cond=*/True};
return NS;
}
};
/// Set of definitions that produce new register:
typedef llvm::SmallVector<NewSense, 2> NewSenseList;
typedef llvm::DenseMap<unsigned, NewSenseList>::iterator NewDefsIterator;
llvm::DenseMap<unsigned, NewSenseList> NewDefs;
/// Set of weak definitions whose clashes should be enforced selectively.
typedef std::set<unsigned>::iterator SoftDefsIterator;
std::set<unsigned> SoftDefs;
/// Set of temporary definitions not committed to the register file.
typedef std::set<unsigned>::iterator TmpDefsIterator;
std::set<unsigned> TmpDefs;
/// Set of new predicates used.
typedef std::set<unsigned>::iterator NewPredsIterator;
std::set<unsigned> NewPreds;
/// Set of predicates defined late.
typedef std::multiset<unsigned>::iterator LatePredsIterator;
std::multiset<unsigned> LatePreds;
/// Set of uses.
typedef std::set<unsigned>::iterator UsesIterator;
std::set<unsigned> Uses;
/// Set of new values used: new register, if new-value jump.
typedef llvm::DenseMap<unsigned, NewSense>::iterator NewUsesIterator;
llvm::DenseMap<unsigned, NewSense> NewUses;
/// Pre-defined set of read-only registers.
typedef std::set<unsigned>::iterator ReadOnlyIterator;
std::set<unsigned> ReadOnly;
void init();
void init(MCInst const &);
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
bool registerUsed(unsigned Register);
// Checks performed.
bool checkBranches();
bool checkPredicates();
bool checkNewValues();
bool checkRegisters();
bool checkRegistersReadOnly();
bool checkEndloopBranches();
void checkRegisterCurDefs();
bool checkSolo();
bool checkShuffle();
bool checkSlots();
bool checkAXOK();
static void compoundRegisterMap(unsigned &);
bool isPredicateRegister(unsigned R) const {
return (Hexagon::P0 == R || Hexagon::P1 == R || Hexagon::P2 == R ||
Hexagon::P3 == R);
};
bool isLoopRegister(unsigned R) const {
return (Hexagon::SA0 == R || Hexagon::LC0 == R || Hexagon::SA1 == R ||
Hexagon::LC1 == R);
};
bool hasValidNewValueDef(const NewSense &Use, const NewSenseList &Defs) const;
public:
explicit HexagonMCChecker(MCContext &Context, MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst &mcb,
const MCRegisterInfo &ri, bool ReportErrors = true);
bool check(bool FullCheck = true);
void reportErrorRegisters(unsigned Register);
void reportErrorNewValue(unsigned Register);
void reportError(SMLoc Loc, llvm::Twine const &Msg);
void reportError(llvm::Twine const &Msg);
void reportWarning(llvm::Twine const &Msg);
};
} // namespace llvm
#endif // HEXAGONMCCHECKER_H
|