1*9880d681SAndroid Build Coastguard Worker //===----- HexagonMCChecker.cpp - Instruction bundle checking -------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This implements the checking of insns inside a bundle according to the
11*9880d681SAndroid Build Coastguard Worker // packet constraint rules of the Hexagon ISA.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "HexagonMCChecker.h"
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Worker #include "HexagonBaseInfo.h"
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrDesc.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> RelaxNVChecks("relax-nv-checks", cl::init(false),
28*9880d681SAndroid Build Coastguard Worker cl::ZeroOrMore, cl::Hidden, cl::desc("Relax checks of new-value validity"));
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker const HexagonMCChecker::PredSense
31*9880d681SAndroid Build Coastguard Worker HexagonMCChecker::Unconditional(Hexagon::NoRegister, false);
32*9880d681SAndroid Build Coastguard Worker
init()33*9880d681SAndroid Build Coastguard Worker void HexagonMCChecker::init() {
34*9880d681SAndroid Build Coastguard Worker // Initialize read-only registers set.
35*9880d681SAndroid Build Coastguard Worker ReadOnly.insert(Hexagon::PC);
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker // Figure out the loop-registers definitions.
38*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isInnerLoop(MCB)) {
39*9880d681SAndroid Build Coastguard Worker Defs[Hexagon::SA0].insert(Unconditional); // FIXME: define or change SA0?
40*9880d681SAndroid Build Coastguard Worker Defs[Hexagon::LC0].insert(Unconditional);
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isOuterLoop(MCB)) {
43*9880d681SAndroid Build Coastguard Worker Defs[Hexagon::SA1].insert(Unconditional); // FIXME: define or change SA0?
44*9880d681SAndroid Build Coastguard Worker Defs[Hexagon::LC1].insert(Unconditional);
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isBundle(MCB))
48*9880d681SAndroid Build Coastguard Worker // Unfurl a bundle.
49*9880d681SAndroid Build Coastguard Worker for (auto const&I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
50*9880d681SAndroid Build Coastguard Worker init(*I.getInst());
51*9880d681SAndroid Build Coastguard Worker }
52*9880d681SAndroid Build Coastguard Worker else
53*9880d681SAndroid Build Coastguard Worker init(MCB);
54*9880d681SAndroid Build Coastguard Worker }
55*9880d681SAndroid Build Coastguard Worker
init(MCInst const & MCI)56*9880d681SAndroid Build Coastguard Worker void HexagonMCChecker::init(MCInst const& MCI) {
57*9880d681SAndroid Build Coastguard Worker const MCInstrDesc& MCID = HexagonMCInstrInfo::getDesc(MCII, MCI);
58*9880d681SAndroid Build Coastguard Worker unsigned PredReg = Hexagon::NoRegister;
59*9880d681SAndroid Build Coastguard Worker bool isTrue = false;
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker // Get used registers.
62*9880d681SAndroid Build Coastguard Worker for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
63*9880d681SAndroid Build Coastguard Worker if (MCI.getOperand(i).isReg()) {
64*9880d681SAndroid Build Coastguard Worker unsigned R = MCI.getOperand(i).getReg();
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isPredicated(MCII, MCI) && isPredicateRegister(R)) {
67*9880d681SAndroid Build Coastguard Worker // Note an used predicate register.
68*9880d681SAndroid Build Coastguard Worker PredReg = R;
69*9880d681SAndroid Build Coastguard Worker isTrue = HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI);
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker // Note use of new predicate register.
72*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
73*9880d681SAndroid Build Coastguard Worker NewPreds.insert(PredReg);
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker else
76*9880d681SAndroid Build Coastguard Worker // Note register use. Super-registers are not tracked directly,
77*9880d681SAndroid Build Coastguard Worker // but their components.
78*9880d681SAndroid Build Coastguard Worker for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
79*9880d681SAndroid Build Coastguard Worker SRI.isValid();
80*9880d681SAndroid Build Coastguard Worker ++SRI)
81*9880d681SAndroid Build Coastguard Worker if (!MCSubRegIterator(*SRI, &RI).isValid())
82*9880d681SAndroid Build Coastguard Worker // Skip super-registers used indirectly.
83*9880d681SAndroid Build Coastguard Worker Uses.insert(*SRI);
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker // Get implicit register definitions.
87*9880d681SAndroid Build Coastguard Worker if (const MCPhysReg *ImpDef = MCID.getImplicitDefs())
88*9880d681SAndroid Build Coastguard Worker for (; *ImpDef; ++ImpDef) {
89*9880d681SAndroid Build Coastguard Worker unsigned R = *ImpDef;
90*9880d681SAndroid Build Coastguard Worker
91*9880d681SAndroid Build Coastguard Worker if (Hexagon::R31 != R && MCID.isCall())
92*9880d681SAndroid Build Coastguard Worker // Any register other than the LR and the PC are actually volatile ones
93*9880d681SAndroid Build Coastguard Worker // as defined by the ABI, not modified implicitly by the call insn.
94*9880d681SAndroid Build Coastguard Worker continue;
95*9880d681SAndroid Build Coastguard Worker if (Hexagon::PC == R)
96*9880d681SAndroid Build Coastguard Worker // Branches are the only insns that can change the PC,
97*9880d681SAndroid Build Coastguard Worker // otherwise a read-only register.
98*9880d681SAndroid Build Coastguard Worker continue;
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker if (Hexagon::USR_OVF == R)
101*9880d681SAndroid Build Coastguard Worker // Many insns change the USR implicitly, but only one or another flag.
102*9880d681SAndroid Build Coastguard Worker // The instruction table models the USR.OVF flag, which can be implicitly
103*9880d681SAndroid Build Coastguard Worker // modified more than once, but cannot be modified in the same packet
104*9880d681SAndroid Build Coastguard Worker // with an instruction that modifies is explicitly. Deal with such situ-
105*9880d681SAndroid Build Coastguard Worker // ations individually.
106*9880d681SAndroid Build Coastguard Worker SoftDefs.insert(R);
107*9880d681SAndroid Build Coastguard Worker else if (isPredicateRegister(R) &&
108*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isPredicateLate(MCII, MCI))
109*9880d681SAndroid Build Coastguard Worker // Include implicit late predicates.
110*9880d681SAndroid Build Coastguard Worker LatePreds.insert(R);
111*9880d681SAndroid Build Coastguard Worker else
112*9880d681SAndroid Build Coastguard Worker Defs[R].insert(PredSense(PredReg, isTrue));
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker // Figure out explicit register definitions.
116*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < MCID.getNumDefs(); ++i) {
117*9880d681SAndroid Build Coastguard Worker unsigned R = MCI.getOperand(i).getReg(),
118*9880d681SAndroid Build Coastguard Worker S = Hexagon::NoRegister;
119*9880d681SAndroid Build Coastguard Worker // USR has subregisters (while C8 does not for technical reasons), so
120*9880d681SAndroid Build Coastguard Worker // reset R to USR, since we know how to handle multiple defs of USR,
121*9880d681SAndroid Build Coastguard Worker // taking into account its subregisters.
122*9880d681SAndroid Build Coastguard Worker if (R == Hexagon::C8)
123*9880d681SAndroid Build Coastguard Worker R = Hexagon::USR;
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker // Note register definitions, direct ones as well as indirect side-effects.
126*9880d681SAndroid Build Coastguard Worker // Super-registers are not tracked directly, but their components.
127*9880d681SAndroid Build Coastguard Worker for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
128*9880d681SAndroid Build Coastguard Worker SRI.isValid();
129*9880d681SAndroid Build Coastguard Worker ++SRI) {
130*9880d681SAndroid Build Coastguard Worker if (MCSubRegIterator(*SRI, &RI).isValid())
131*9880d681SAndroid Build Coastguard Worker // Skip super-registers defined indirectly.
132*9880d681SAndroid Build Coastguard Worker continue;
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker if (R == *SRI) {
135*9880d681SAndroid Build Coastguard Worker if (S == R)
136*9880d681SAndroid Build Coastguard Worker // Avoid scoring the defined register multiple times.
137*9880d681SAndroid Build Coastguard Worker continue;
138*9880d681SAndroid Build Coastguard Worker else
139*9880d681SAndroid Build Coastguard Worker // Note that the defined register has already been scored.
140*9880d681SAndroid Build Coastguard Worker S = R;
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker if (Hexagon::P3_0 != R && Hexagon::P3_0 == *SRI)
144*9880d681SAndroid Build Coastguard Worker // P3:0 is a special case, since multiple predicate register definitions
145*9880d681SAndroid Build Coastguard Worker // in a packet is allowed as the equivalent of their logical "and".
146*9880d681SAndroid Build Coastguard Worker // Only an explicit definition of P3:0 is noted as such; if a
147*9880d681SAndroid Build Coastguard Worker // side-effect, then note as a soft definition.
148*9880d681SAndroid Build Coastguard Worker SoftDefs.insert(*SRI);
149*9880d681SAndroid Build Coastguard Worker else if (HexagonMCInstrInfo::isPredicateLate(MCII, MCI) && isPredicateRegister(*SRI))
150*9880d681SAndroid Build Coastguard Worker // Some insns produce predicates too late to be used in the same packet.
151*9880d681SAndroid Build Coastguard Worker LatePreds.insert(*SRI);
152*9880d681SAndroid Build Coastguard Worker else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCVI_VM_CUR_LD)
153*9880d681SAndroid Build Coastguard Worker // Current loads should be used in the same packet.
154*9880d681SAndroid Build Coastguard Worker // TODO: relies on the impossibility of a current and a temporary loads
155*9880d681SAndroid Build Coastguard Worker // in the same packet.
156*9880d681SAndroid Build Coastguard Worker CurDefs.insert(*SRI), Defs[*SRI].insert(PredSense(PredReg, isTrue));
157*9880d681SAndroid Build Coastguard Worker else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCVI_VM_TMP_LD)
158*9880d681SAndroid Build Coastguard Worker // Temporary loads should be used in the same packet, but don't commit
159*9880d681SAndroid Build Coastguard Worker // results, so it should be disregarded if another insn changes the same
160*9880d681SAndroid Build Coastguard Worker // register.
161*9880d681SAndroid Build Coastguard Worker // TODO: relies on the impossibility of a current and a temporary loads
162*9880d681SAndroid Build Coastguard Worker // in the same packet.
163*9880d681SAndroid Build Coastguard Worker TmpDefs.insert(*SRI);
164*9880d681SAndroid Build Coastguard Worker else if (i <= 1 && llvm::HexagonMCInstrInfo::hasNewValue2(MCII, MCI) )
165*9880d681SAndroid Build Coastguard Worker // vshuff(Vx, Vy, Rx) <- Vx(0) and Vy(1) are both source and
166*9880d681SAndroid Build Coastguard Worker // destination registers with this instruction. same for vdeal(Vx,Vy,Rx)
167*9880d681SAndroid Build Coastguard Worker Uses.insert(*SRI);
168*9880d681SAndroid Build Coastguard Worker else
169*9880d681SAndroid Build Coastguard Worker Defs[*SRI].insert(PredSense(PredReg, isTrue));
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker }
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker // Figure out register definitions that produce new values.
174*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::hasNewValue(MCII, MCI)) {
175*9880d681SAndroid Build Coastguard Worker unsigned R = HexagonMCInstrInfo::getNewValueOperand(MCII, MCI).getReg();
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isCompound(MCII, MCI))
178*9880d681SAndroid Build Coastguard Worker compoundRegisterMap(R); // Compound insns have a limited register range.
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker for(MCRegAliasIterator SRI(R, &RI, !MCSubRegIterator(R, &RI).isValid());
181*9880d681SAndroid Build Coastguard Worker SRI.isValid();
182*9880d681SAndroid Build Coastguard Worker ++SRI)
183*9880d681SAndroid Build Coastguard Worker if (!MCSubRegIterator(*SRI, &RI).isValid())
184*9880d681SAndroid Build Coastguard Worker // No super-registers defined indirectly.
185*9880d681SAndroid Build Coastguard Worker NewDefs[*SRI].push_back(NewSense::Def(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
186*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isFloat(MCII, MCI)));
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker // For fairly unique 2-dot-new producers, example:
189*9880d681SAndroid Build Coastguard Worker // vdeal(V1, V9, R0) V1.new and V9.new can be used by consumers.
190*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::hasNewValue2(MCII, MCI)) {
191*9880d681SAndroid Build Coastguard Worker unsigned R2 = HexagonMCInstrInfo::getNewValueOperand2(MCII, MCI).getReg();
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker for(MCRegAliasIterator SRI(R2, &RI, !MCSubRegIterator(R2, &RI).isValid());
194*9880d681SAndroid Build Coastguard Worker SRI.isValid();
195*9880d681SAndroid Build Coastguard Worker ++SRI)
196*9880d681SAndroid Build Coastguard Worker if (!MCSubRegIterator(*SRI, &RI).isValid())
197*9880d681SAndroid Build Coastguard Worker NewDefs[*SRI].push_back(NewSense::Def(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI),
198*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isFloat(MCII, MCI)));
199*9880d681SAndroid Build Coastguard Worker }
200*9880d681SAndroid Build Coastguard Worker }
201*9880d681SAndroid Build Coastguard Worker
202*9880d681SAndroid Build Coastguard Worker // Figure out definitions of new predicate registers.
203*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
204*9880d681SAndroid Build Coastguard Worker for (unsigned i = MCID.getNumDefs(); i < MCID.getNumOperands(); ++i)
205*9880d681SAndroid Build Coastguard Worker if (MCI.getOperand(i).isReg()) {
206*9880d681SAndroid Build Coastguard Worker unsigned P = MCI.getOperand(i).getReg();
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker if (isPredicateRegister(P))
209*9880d681SAndroid Build Coastguard Worker NewPreds.insert(P);
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker // Figure out uses of new values.
213*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isNewValue(MCII, MCI)) {
214*9880d681SAndroid Build Coastguard Worker unsigned N = HexagonMCInstrInfo::getNewValueOperand(MCII, MCI).getReg();
215*9880d681SAndroid Build Coastguard Worker
216*9880d681SAndroid Build Coastguard Worker if (!MCSubRegIterator(N, &RI).isValid()) {
217*9880d681SAndroid Build Coastguard Worker // Super-registers cannot use new values.
218*9880d681SAndroid Build Coastguard Worker if (MCID.isBranch())
219*9880d681SAndroid Build Coastguard Worker NewUses[N] = NewSense::Jmp(llvm::HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNV);
220*9880d681SAndroid Build Coastguard Worker else
221*9880d681SAndroid Build Coastguard Worker NewUses[N] = NewSense::Use(PredReg, HexagonMCInstrInfo::isPredicatedTrue(MCII, MCI));
222*9880d681SAndroid Build Coastguard Worker }
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker
HexagonMCChecker(MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & mcb,MCInst & mcbdx,MCRegisterInfo const & ri)226*9880d681SAndroid Build Coastguard Worker HexagonMCChecker::HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &mcb, MCInst &mcbdx,
227*9880d681SAndroid Build Coastguard Worker MCRegisterInfo const &ri)
228*9880d681SAndroid Build Coastguard Worker : MCB(mcb), MCBDX(mcbdx), RI(ri), MCII(MCII), STI(STI),
229*9880d681SAndroid Build Coastguard Worker bLoadErrInfo(false) {
230*9880d681SAndroid Build Coastguard Worker init();
231*9880d681SAndroid Build Coastguard Worker }
232*9880d681SAndroid Build Coastguard Worker
check()233*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::check() {
234*9880d681SAndroid Build Coastguard Worker bool chkB = checkBranches();
235*9880d681SAndroid Build Coastguard Worker bool chkP = checkPredicates();
236*9880d681SAndroid Build Coastguard Worker bool chkNV = checkNewValues();
237*9880d681SAndroid Build Coastguard Worker bool chkR = checkRegisters();
238*9880d681SAndroid Build Coastguard Worker bool chkS = checkSolo();
239*9880d681SAndroid Build Coastguard Worker bool chkSh = checkShuffle();
240*9880d681SAndroid Build Coastguard Worker bool chkSl = checkSlots();
241*9880d681SAndroid Build Coastguard Worker bool chk = chkB && chkP && chkNV && chkR && chkS && chkSh && chkSl;
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard Worker return chk;
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker
checkSlots()246*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkSlots()
247*9880d681SAndroid Build Coastguard Worker
248*9880d681SAndroid Build Coastguard Worker {
249*9880d681SAndroid Build Coastguard Worker unsigned slotsUsed = 0;
250*9880d681SAndroid Build Coastguard Worker for (auto HMI: HexagonMCInstrInfo::bundleInstructions(MCBDX)) {
251*9880d681SAndroid Build Coastguard Worker MCInst const& MCI = *HMI.getInst();
252*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isImmext(MCI))
253*9880d681SAndroid Build Coastguard Worker continue;
254*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isDuplex(MCII, MCI))
255*9880d681SAndroid Build Coastguard Worker slotsUsed += 2;
256*9880d681SAndroid Build Coastguard Worker else
257*9880d681SAndroid Build Coastguard Worker ++slotsUsed;
258*9880d681SAndroid Build Coastguard Worker }
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker if (slotsUsed > HEXAGON_PACKET_SIZE) {
261*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
262*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_NOSLOTS);
263*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
264*9880d681SAndroid Build Coastguard Worker return false;
265*9880d681SAndroid Build Coastguard Worker }
266*9880d681SAndroid Build Coastguard Worker return true;
267*9880d681SAndroid Build Coastguard Worker }
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker // Check legal use of branches.
checkBranches()270*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkBranches() {
271*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
272*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isBundle(MCB)) {
273*9880d681SAndroid Build Coastguard Worker bool hasConditional = false;
274*9880d681SAndroid Build Coastguard Worker unsigned Branches = 0, Returns = 0, NewIndirectBranches = 0,
275*9880d681SAndroid Build Coastguard Worker NewValueBranches = 0, Conditional = HEXAGON_PRESHUFFLE_PACKET_SIZE,
276*9880d681SAndroid Build Coastguard Worker Unconditional = HEXAGON_PRESHUFFLE_PACKET_SIZE;
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker for (unsigned i = HexagonMCInstrInfo::bundleInstructionsOffset;
279*9880d681SAndroid Build Coastguard Worker i < MCB.size(); ++i) {
280*9880d681SAndroid Build Coastguard Worker MCInst const &MCI = *MCB.begin()[i].getInst();
281*9880d681SAndroid Build Coastguard Worker
282*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isImmext(MCI))
283*9880d681SAndroid Build Coastguard Worker continue;
284*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch() ||
285*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::getDesc(MCII, MCI).isCall()) {
286*9880d681SAndroid Build Coastguard Worker ++Branches;
287*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::getDesc(MCII, MCI).isIndirectBranch() &&
288*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isPredicatedNew(MCII, MCI))
289*9880d681SAndroid Build Coastguard Worker ++NewIndirectBranches;
290*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isNewValue(MCII, MCI))
291*9880d681SAndroid Build Coastguard Worker ++NewValueBranches;
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isPredicated(MCII, MCI) ||
294*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isPredicatedNew(MCII, MCI)) {
295*9880d681SAndroid Build Coastguard Worker hasConditional = true;
296*9880d681SAndroid Build Coastguard Worker Conditional = i; // Record the position of the conditional branch.
297*9880d681SAndroid Build Coastguard Worker } else {
298*9880d681SAndroid Build Coastguard Worker Unconditional = i; // Record the position of the unconditional branch.
299*9880d681SAndroid Build Coastguard Worker }
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::getDesc(MCII, MCI).isReturn() &&
302*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::getDesc(MCII, MCI).mayLoad())
303*9880d681SAndroid Build Coastguard Worker ++Returns;
304*9880d681SAndroid Build Coastguard Worker }
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker if (Branches) // FIXME: should "Defs.count(Hexagon::PC)" be here too?
307*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isInnerLoop(MCB) ||
308*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isOuterLoop(MCB)) {
309*9880d681SAndroid Build Coastguard Worker // Error out if there's any branch in a loop-end packet.
310*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_ENDLOOP, Hexagon::PC);
311*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
312*9880d681SAndroid Build Coastguard Worker return false;
313*9880d681SAndroid Build Coastguard Worker }
314*9880d681SAndroid Build Coastguard Worker if (Branches > 1)
315*9880d681SAndroid Build Coastguard Worker if (!hasConditional || Conditional > Unconditional) {
316*9880d681SAndroid Build Coastguard Worker // Error out if more than one unconditional branch or
317*9880d681SAndroid Build Coastguard Worker // the conditional branch appears after the unconditional one.
318*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_BRANCHES);
319*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
320*9880d681SAndroid Build Coastguard Worker return false;
321*9880d681SAndroid Build Coastguard Worker }
322*9880d681SAndroid Build Coastguard Worker }
323*9880d681SAndroid Build Coastguard Worker
324*9880d681SAndroid Build Coastguard Worker return true;
325*9880d681SAndroid Build Coastguard Worker }
326*9880d681SAndroid Build Coastguard Worker
327*9880d681SAndroid Build Coastguard Worker // Check legal use of predicate registers.
checkPredicates()328*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkPredicates() {
329*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
330*9880d681SAndroid Build Coastguard Worker // Check for proper use of new predicate registers.
331*9880d681SAndroid Build Coastguard Worker for (const auto& I : NewPreds) {
332*9880d681SAndroid Build Coastguard Worker unsigned P = I;
333*9880d681SAndroid Build Coastguard Worker
334*9880d681SAndroid Build Coastguard Worker if (!Defs.count(P) || LatePreds.count(P)) {
335*9880d681SAndroid Build Coastguard Worker // Error out if the new predicate register is not defined,
336*9880d681SAndroid Build Coastguard Worker // or defined "late"
337*9880d681SAndroid Build Coastguard Worker // (e.g., "{ if (p3.new)... ; p3 = sp1loop0(#r7:2, Rs) }").
338*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_NEWP, P);
339*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
340*9880d681SAndroid Build Coastguard Worker return false;
341*9880d681SAndroid Build Coastguard Worker }
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
344*9880d681SAndroid Build Coastguard Worker // Check for proper use of auto-anded of predicate registers.
345*9880d681SAndroid Build Coastguard Worker for (const auto& I : LatePreds) {
346*9880d681SAndroid Build Coastguard Worker unsigned P = I;
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker if (LatePreds.count(P) > 1 || Defs.count(P)) {
349*9880d681SAndroid Build Coastguard Worker // Error out if predicate register defined "late" multiple times or
350*9880d681SAndroid Build Coastguard Worker // defined late and regularly defined
351*9880d681SAndroid Build Coastguard Worker // (e.g., "{ p3 = sp1loop0(...); p3 = cmp.eq(...) }".
352*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, P);
353*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
354*9880d681SAndroid Build Coastguard Worker return false;
355*9880d681SAndroid Build Coastguard Worker }
356*9880d681SAndroid Build Coastguard Worker }
357*9880d681SAndroid Build Coastguard Worker
358*9880d681SAndroid Build Coastguard Worker return true;
359*9880d681SAndroid Build Coastguard Worker }
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker // Check legal use of new values.
checkNewValues()362*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkNewValues() {
363*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
364*9880d681SAndroid Build Coastguard Worker memset(&errInfo, 0, sizeof(errInfo));
365*9880d681SAndroid Build Coastguard Worker for (auto& I : NewUses) {
366*9880d681SAndroid Build Coastguard Worker unsigned R = I.first;
367*9880d681SAndroid Build Coastguard Worker NewSense &US = I.second;
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker if (!hasValidNewValueDef(US, NewDefs[R])) {
370*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_NEWV, R);
371*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
372*9880d681SAndroid Build Coastguard Worker return false;
373*9880d681SAndroid Build Coastguard Worker }
374*9880d681SAndroid Build Coastguard Worker }
375*9880d681SAndroid Build Coastguard Worker
376*9880d681SAndroid Build Coastguard Worker return true;
377*9880d681SAndroid Build Coastguard Worker }
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker // Check for legal register uses and definitions.
checkRegisters()380*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkRegisters() {
381*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
382*9880d681SAndroid Build Coastguard Worker // Check for proper register definitions.
383*9880d681SAndroid Build Coastguard Worker for (const auto& I : Defs) {
384*9880d681SAndroid Build Coastguard Worker unsigned R = I.first;
385*9880d681SAndroid Build Coastguard Worker
386*9880d681SAndroid Build Coastguard Worker if (ReadOnly.count(R)) {
387*9880d681SAndroid Build Coastguard Worker // Error out for definitions of read-only registers.
388*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_READONLY, R);
389*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
390*9880d681SAndroid Build Coastguard Worker return false;
391*9880d681SAndroid Build Coastguard Worker }
392*9880d681SAndroid Build Coastguard Worker if (isLoopRegister(R) && Defs.count(R) > 1 &&
393*9880d681SAndroid Build Coastguard Worker (HexagonMCInstrInfo::isInnerLoop(MCB) ||
394*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::isOuterLoop(MCB))) {
395*9880d681SAndroid Build Coastguard Worker // Error out for definitions of loop registers at the end of a loop.
396*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_LOOP, R);
397*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
398*9880d681SAndroid Build Coastguard Worker return false;
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker if (SoftDefs.count(R)) {
401*9880d681SAndroid Build Coastguard Worker // Error out for explicit changes to registers also weakly defined
402*9880d681SAndroid Build Coastguard Worker // (e.g., "{ usr = r0; r0 = sfadd(...) }").
403*9880d681SAndroid Build Coastguard Worker unsigned UsrR = Hexagon::USR; // Silence warning about mixed types in ?:.
404*9880d681SAndroid Build Coastguard Worker unsigned BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
405*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, BadR);
406*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
407*9880d681SAndroid Build Coastguard Worker return false;
408*9880d681SAndroid Build Coastguard Worker }
409*9880d681SAndroid Build Coastguard Worker if (!isPredicateRegister(R) && Defs[R].size() > 1) {
410*9880d681SAndroid Build Coastguard Worker // Check for multiple register definitions.
411*9880d681SAndroid Build Coastguard Worker PredSet &PM = Defs[R];
412*9880d681SAndroid Build Coastguard Worker
413*9880d681SAndroid Build Coastguard Worker // Check for multiple unconditional register definitions.
414*9880d681SAndroid Build Coastguard Worker if (PM.count(Unconditional)) {
415*9880d681SAndroid Build Coastguard Worker // Error out on an unconditional change when there are any other
416*9880d681SAndroid Build Coastguard Worker // changes, conditional or not.
417*9880d681SAndroid Build Coastguard Worker unsigned UsrR = Hexagon::USR;
418*9880d681SAndroid Build Coastguard Worker unsigned BadR = RI.isSubRegister(Hexagon::USR, R) ? UsrR : R;
419*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, BadR);
420*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
421*9880d681SAndroid Build Coastguard Worker return false;
422*9880d681SAndroid Build Coastguard Worker }
423*9880d681SAndroid Build Coastguard Worker // Check for multiple conditional register definitions.
424*9880d681SAndroid Build Coastguard Worker for (const auto& J : PM) {
425*9880d681SAndroid Build Coastguard Worker PredSense P = J;
426*9880d681SAndroid Build Coastguard Worker
427*9880d681SAndroid Build Coastguard Worker // Check for multiple uses of the same condition.
428*9880d681SAndroid Build Coastguard Worker if (PM.count(P) > 1) {
429*9880d681SAndroid Build Coastguard Worker // Error out on conditional changes based on the same predicate
430*9880d681SAndroid Build Coastguard Worker // (e.g., "{ if (!p0) r0 =...; if (!p0) r0 =... }").
431*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, R);
432*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
433*9880d681SAndroid Build Coastguard Worker return false;
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker // Check for the use of the complementary condition.
436*9880d681SAndroid Build Coastguard Worker P.second = !P.second;
437*9880d681SAndroid Build Coastguard Worker if (PM.count(P) && PM.size() > 2) {
438*9880d681SAndroid Build Coastguard Worker // Error out on conditional changes based on the same predicate
439*9880d681SAndroid Build Coastguard Worker // multiple times
440*9880d681SAndroid Build Coastguard Worker // (e.g., "{ if (p0) r0 =...; if (!p0) r0 =... }; if (!p0) r0 =... }").
441*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_REGISTERS, R);
442*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
443*9880d681SAndroid Build Coastguard Worker return false;
444*9880d681SAndroid Build Coastguard Worker }
445*9880d681SAndroid Build Coastguard Worker }
446*9880d681SAndroid Build Coastguard Worker }
447*9880d681SAndroid Build Coastguard Worker }
448*9880d681SAndroid Build Coastguard Worker
449*9880d681SAndroid Build Coastguard Worker // Check for use of current definitions.
450*9880d681SAndroid Build Coastguard Worker for (const auto& I : CurDefs) {
451*9880d681SAndroid Build Coastguard Worker unsigned R = I;
452*9880d681SAndroid Build Coastguard Worker
453*9880d681SAndroid Build Coastguard Worker if (!Uses.count(R)) {
454*9880d681SAndroid Build Coastguard Worker // Warn on an unused current definition.
455*9880d681SAndroid Build Coastguard Worker errInfo.setWarning(HexagonMCErrInfo::CHECK_WARN_CURRENT, R);
456*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
457*9880d681SAndroid Build Coastguard Worker return true;
458*9880d681SAndroid Build Coastguard Worker }
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker
461*9880d681SAndroid Build Coastguard Worker // Check for use of temporary definitions.
462*9880d681SAndroid Build Coastguard Worker for (const auto& I : TmpDefs) {
463*9880d681SAndroid Build Coastguard Worker unsigned R = I;
464*9880d681SAndroid Build Coastguard Worker
465*9880d681SAndroid Build Coastguard Worker if (!Uses.count(R)) {
466*9880d681SAndroid Build Coastguard Worker // special case for vhist
467*9880d681SAndroid Build Coastguard Worker bool vHistFound = false;
468*9880d681SAndroid Build Coastguard Worker for (auto const&HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
469*9880d681SAndroid Build Coastguard Worker if(llvm::HexagonMCInstrInfo::getType(MCII, *HMI.getInst()) == HexagonII::TypeCVI_HIST) {
470*9880d681SAndroid Build Coastguard Worker vHistFound = true; // vhist() implicitly uses ALL REGxx.tmp
471*9880d681SAndroid Build Coastguard Worker break;
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker }
474*9880d681SAndroid Build Coastguard Worker // Warn on an unused temporary definition.
475*9880d681SAndroid Build Coastguard Worker if (vHistFound == false) {
476*9880d681SAndroid Build Coastguard Worker errInfo.setWarning(HexagonMCErrInfo::CHECK_WARN_TEMPORARY, R);
477*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
478*9880d681SAndroid Build Coastguard Worker return true;
479*9880d681SAndroid Build Coastguard Worker }
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker }
482*9880d681SAndroid Build Coastguard Worker
483*9880d681SAndroid Build Coastguard Worker return true;
484*9880d681SAndroid Build Coastguard Worker }
485*9880d681SAndroid Build Coastguard Worker
486*9880d681SAndroid Build Coastguard Worker // Check for legal use of solo insns.
checkSolo()487*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkSolo() {
488*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
489*9880d681SAndroid Build Coastguard Worker if (HexagonMCInstrInfo::isBundle(MCB) &&
490*9880d681SAndroid Build Coastguard Worker HexagonMCInstrInfo::bundleSize(MCB) > 1) {
491*9880d681SAndroid Build Coastguard Worker for (auto const&I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
492*9880d681SAndroid Build Coastguard Worker if (llvm::HexagonMCInstrInfo::isSolo(MCII, *I.getInst())) {
493*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SOLO);
494*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
495*9880d681SAndroid Build Coastguard Worker return false;
496*9880d681SAndroid Build Coastguard Worker }
497*9880d681SAndroid Build Coastguard Worker }
498*9880d681SAndroid Build Coastguard Worker }
499*9880d681SAndroid Build Coastguard Worker
500*9880d681SAndroid Build Coastguard Worker return true;
501*9880d681SAndroid Build Coastguard Worker }
502*9880d681SAndroid Build Coastguard Worker
checkShuffle()503*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::checkShuffle() {
504*9880d681SAndroid Build Coastguard Worker HexagonMCErrInfo errInfo;
505*9880d681SAndroid Build Coastguard Worker // Branch info is lost when duplexing. The unduplexed insns must be
506*9880d681SAndroid Build Coastguard Worker // checked and only branch errors matter for this case.
507*9880d681SAndroid Build Coastguard Worker HexagonMCShuffler MCS(MCII, STI, MCB);
508*9880d681SAndroid Build Coastguard Worker if (!MCS.check()) {
509*9880d681SAndroid Build Coastguard Worker if (MCS.getError() == HexagonShuffler::SHUFFLE_ERROR_BRANCHES) {
510*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
511*9880d681SAndroid Build Coastguard Worker errInfo.setShuffleError(MCS.getError());
512*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
513*9880d681SAndroid Build Coastguard Worker return false;
514*9880d681SAndroid Build Coastguard Worker }
515*9880d681SAndroid Build Coastguard Worker }
516*9880d681SAndroid Build Coastguard Worker HexagonMCShuffler MCSDX(MCII, STI, MCBDX);
517*9880d681SAndroid Build Coastguard Worker if (!MCSDX.check()) {
518*9880d681SAndroid Build Coastguard Worker errInfo.setError(HexagonMCErrInfo::CHECK_ERROR_SHUFFLE);
519*9880d681SAndroid Build Coastguard Worker errInfo.setShuffleError(MCSDX.getError());
520*9880d681SAndroid Build Coastguard Worker addErrInfo(errInfo);
521*9880d681SAndroid Build Coastguard Worker return false;
522*9880d681SAndroid Build Coastguard Worker }
523*9880d681SAndroid Build Coastguard Worker return true;
524*9880d681SAndroid Build Coastguard Worker }
525*9880d681SAndroid Build Coastguard Worker
compoundRegisterMap(unsigned & Register)526*9880d681SAndroid Build Coastguard Worker void HexagonMCChecker::compoundRegisterMap(unsigned& Register) {
527*9880d681SAndroid Build Coastguard Worker switch (Register) {
528*9880d681SAndroid Build Coastguard Worker default:
529*9880d681SAndroid Build Coastguard Worker break;
530*9880d681SAndroid Build Coastguard Worker case Hexagon::R15:
531*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R23;
532*9880d681SAndroid Build Coastguard Worker break;
533*9880d681SAndroid Build Coastguard Worker case Hexagon::R14:
534*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R22;
535*9880d681SAndroid Build Coastguard Worker break;
536*9880d681SAndroid Build Coastguard Worker case Hexagon::R13:
537*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R21;
538*9880d681SAndroid Build Coastguard Worker break;
539*9880d681SAndroid Build Coastguard Worker case Hexagon::R12:
540*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R20;
541*9880d681SAndroid Build Coastguard Worker break;
542*9880d681SAndroid Build Coastguard Worker case Hexagon::R11:
543*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R19;
544*9880d681SAndroid Build Coastguard Worker break;
545*9880d681SAndroid Build Coastguard Worker case Hexagon::R10:
546*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R18;
547*9880d681SAndroid Build Coastguard Worker break;
548*9880d681SAndroid Build Coastguard Worker case Hexagon::R9:
549*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R17;
550*9880d681SAndroid Build Coastguard Worker break;
551*9880d681SAndroid Build Coastguard Worker case Hexagon::R8:
552*9880d681SAndroid Build Coastguard Worker Register = Hexagon::R16;
553*9880d681SAndroid Build Coastguard Worker break;
554*9880d681SAndroid Build Coastguard Worker }
555*9880d681SAndroid Build Coastguard Worker }
556*9880d681SAndroid Build Coastguard Worker
hasValidNewValueDef(const NewSense & Use,const NewSenseList & Defs) const557*9880d681SAndroid Build Coastguard Worker bool HexagonMCChecker::hasValidNewValueDef(const NewSense &Use,
558*9880d681SAndroid Build Coastguard Worker const NewSenseList &Defs) const {
559*9880d681SAndroid Build Coastguard Worker bool Strict = !RelaxNVChecks;
560*9880d681SAndroid Build Coastguard Worker
561*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, n = Defs.size(); i < n; ++i) {
562*9880d681SAndroid Build Coastguard Worker const NewSense &Def = Defs[i];
563*9880d681SAndroid Build Coastguard Worker // NVJ cannot use a new FP value [7.6.1]
564*9880d681SAndroid Build Coastguard Worker if (Use.IsNVJ && (Def.IsFloat || Def.PredReg != 0))
565*9880d681SAndroid Build Coastguard Worker continue;
566*9880d681SAndroid Build Coastguard Worker // If the definition was not predicated, then it does not matter if
567*9880d681SAndroid Build Coastguard Worker // the use is.
568*9880d681SAndroid Build Coastguard Worker if (Def.PredReg == 0)
569*9880d681SAndroid Build Coastguard Worker return true;
570*9880d681SAndroid Build Coastguard Worker // With the strict checks, both the definition and the use must be
571*9880d681SAndroid Build Coastguard Worker // predicated on the same register and condition.
572*9880d681SAndroid Build Coastguard Worker if (Strict) {
573*9880d681SAndroid Build Coastguard Worker if (Def.PredReg == Use.PredReg && Def.Cond == Use.Cond)
574*9880d681SAndroid Build Coastguard Worker return true;
575*9880d681SAndroid Build Coastguard Worker } else {
576*9880d681SAndroid Build Coastguard Worker // With the relaxed checks, if the definition was predicated, the only
577*9880d681SAndroid Build Coastguard Worker // detectable violation is if the use is predicated on the opposing
578*9880d681SAndroid Build Coastguard Worker // condition, otherwise, it's ok.
579*9880d681SAndroid Build Coastguard Worker if (Def.PredReg != Use.PredReg || Def.Cond == Use.Cond)
580*9880d681SAndroid Build Coastguard Worker return true;
581*9880d681SAndroid Build Coastguard Worker }
582*9880d681SAndroid Build Coastguard Worker }
583*9880d681SAndroid Build Coastguard Worker return false;
584*9880d681SAndroid Build Coastguard Worker }
585*9880d681SAndroid Build Coastguard Worker
586