OpenASIP 2.2
Loading...
Searching...
No Matches
TCEInstrInfo.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2009 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file TCEInstrInfo.cpp
26 *
27 * Implementation of TCEInstrInfo class.
28 *
29 * NOTE: Normal TCE coding guidelines do not apply here to makeo it
30 * easier to track and copy paste changes from LLVM.
31 * So please follow LLVM style when adding or fixing things.
32 *
33 * @author Veli-Pekka Jääskeläinen 2007 (vjaaskel-no.spam-cs.tut.fi)
34 * @author Mikael Lepistö 2009 (mikael.lepisto-no.spam-tut.fi)
35 * @author Heikki Kultala 2011-2012 (heikki.kultala-no.spam-tut.fi)
36 */
37
38#include "TCEInstrInfo.hh"
39
40#include <llvm/ADT/STLExtras.h>
41#include <llvm/CodeGen/DFAPacketizer.h>
42#include <llvm/CodeGen/MachineInstrBuilder.h>
43#include <llvm/CodeGen/MachineRegisterInfo.h>
44#include <llvm/Support/ErrorHandling.h>
45
46#include "TCETargetMachine.hh"
48/*
49#include <llvm/CodeGen/MachineInstrBuilder.h>
50#include <llvm/ADT/SmallVector.h>
51
52#include "TCEInstrInfo.hh"
53*/
54#include "TCEPlugin.hh"
55//#include "tce_config.h"
56
57// Include code generated with tceplugingen:
58
59#define GET_INSTRINFO_CTOR_DTOR
60#define GET_INSTRINFO_MC_DESC
61#include "TCEGenInstrInfo.inc"
62#undef GET_INSTRINFO_CTOR_DTOR
63#undef GET_INSTRINFO_MC_DESC
64
65using namespace llvm;
66
67#define GET_INSTRMAP_INFO
68#include "TCEGenDFAPacketizer.inc"
69
70/**
71 * Constructor.
72 */
74 const TCETargetMachinePlugin* plugin) :
75 TCEGenInstrInfo(TCE::ADJCALLSTACKDOWN, TCE::ADJCALLSTACKUP),
76 ri_(*this), plugin_(plugin) {
77}
78
79/**
80 * Destructor.
81 */
84
85/**
86 * Inserts a branch instruction or brach instructions into llvm MBB.
87 *
88 * If the MBB already has an unconditional branch at end, does nothing.
89 *
90 * @param mbb where to insert the branch instructions.
91 * @param tbb jump target basic block
92 * @param fbb false condition jump target, if insertin 2 branches
93 *
94 * @return number of branch instructions inserted
95 */
96unsigned
98 MachineBasicBlock& mbb,
99 MachineBasicBlock* tbb,
100 MachineBasicBlock* fbb,
101 ArrayRef<MachineOperand> cond,
102 const DebugLoc& dl
103 , int *BytesAdded) const {
104 assert(cond.size() == 0 || cond.size() == 2 || cond.size() == 3);
105
106 if (mbb.size() != 0) {
107 // already has a uncond branch, no need for another.
108 // asserts to make sure it's to same BB in order to not create
109 // broken code.
110 if (mbb.back().getOpcode() == TCE::TCEBR ||
111 mbb.back().getOpcode() == TCE::TCEBRIND) {
112 assert(cond.size() == 0);
113 return 0;
114 }
115 if (cond.size() != 0) {
116 assert (mbb.back().getOpcode() != TCE::TCEBRCOND && "c branch!");
117 assert (mbb.back().getOpcode() != TCE::TCEBRICOND && "ic branch!");
118 assert (mbb.back().getOpcode() != TCE::TCEBR && "has branch!(1)");
119 } else {
120 assert (mbb.back().getOpcode() != TCE::TCEBR && "has branch(2)!");
121 }
122
123 }
124
125 if (fbb == 0) {
126 if (cond.empty()) {
127 // Can only insert uncond branches so far.
128 BuildMI(&mbb, dl, get(TCE::TCEBR)).addMBB(tbb);
129 return 1;
130 } else {
131 if (cond.size() == 2 && cond[1].getImm() == false) {
132 // false jump
133 BuildMI(&mbb, dl, get(TCE::TCEBRICOND)).
134 addReg(cond[0].getReg()).addMBB(tbb);
135 return 1;
136 } else if (cond.size() == 2 && cond[1].getImm() == true) {
137 BuildMI(&mbb, dl, get(TCE::TCEBRCOND)).addReg(cond[0].getReg())
138 .addMBB(tbb);
139 return 1;
140 } else {
141 insertCCBranch(mbb, *tbb, cond, dl);
142 return 1;
143 }
144 }
145 }
146
147 assert(
148 !cond.empty() &&
149 "Two jumps need a condition"); // not allowed to have conditional
150 // jump because we have an fbb
151
152 if (cond.size() == 2 && cond[1].getImm() == false) {
153 BuildMI(&mbb, dl, get(TCE::TCEBRICOND)).
154 addReg(cond[0].getReg()).addMBB(tbb);
155 } else if (cond.size() == 1 ||
156 (cond.size() == 2 && cond[1].getImm() == true)) {
157 BuildMI(&mbb, dl, get(TCE::TCEBRCOND)).
158 addReg(cond[0].getReg()).addMBB(tbb);
159 } else {
160 insertCCBranch(mbb, *tbb, cond, dl);
161 }
162 BuildMI(&mbb, dl, get(TCE::TCEBR)).addMBB(fbb);
163
164 return 2;
165}
166
167/**
168 * Removes branch or branches form end of llvm MachineBasicBlock
169 *
170 * @param mbb where to remove the branches from
171 * @return number of braches removed
172 */
173unsigned
175 MachineBasicBlock &mbb, int *BytesRemoved) const {
176 int j = 0;
177 MachineBasicBlock::iterator i = mbb.end();
178 while (i != mbb.begin()) {
179 i--;
180 int opc = i->getOpcode();
181 if (i->getDesc().isBranch()) {
182 i->eraseFromParent();
183 i = mbb.end(); // not optimal, but we will not miss any
184 // instruction
185 j++;
186 }
187 }
188 return j;
189}
190
191/**
192 * Returns true if program control can't fall through the last instruction
193 * in the basic block, false otherwise.
194 */
195bool
196TCEInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock& MBB) const {
197 /* Mips inspired */
198 if (MBB.empty()) return false;
199 switch (MBB.back().getOpcode()) {
200 case TCE::RETL: // Return.
201 case TCE::TCEBR: // Uncond branch.
202 case TCE::TCEBRIND: // Uncond indirect branch.
203 return true;
204 default: return false;
205 }
206}
207
209storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
210 unsigned SrcReg, bool isKill, int FI,
211 #ifdef LLVM_OLDER_THAN_16
212 const TargetRegisterClass *RC) const {
213 #else
214 const TargetRegisterClass *RC, Register vReg) const {
215 #endif
216 DebugLoc DL;
217
218 if (I != MBB.end()) DL = I->getDebugLoc();
219
220 BuildMI(MBB, I, DL, get(plugin_->getStore(RC))).addFrameIndex(FI).addImm(0)
221 .addReg(SrcReg, getKillRegState(isKill));
222
223 LLVMContext& context = MBB.getParent()->getFunction().getContext();
224 llvm::Metadata* md = llvm::MDString::get(context, "AA_CATEGORY_STACK_SLOT");
225 MDNode* mdNode =
226 MDNode::get(context, llvm::ArrayRef<llvm::Metadata*>(&md, 1));
227 MachineOperand metaDataOperand = MachineOperand::CreateMetadata(mdNode);
228 I--; // buildmi moves the iterator to next ins, point to the created one.
229 I->addOperand(metaDataOperand);
230}
231
233loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
234 unsigned DestReg, int FI,
235 #ifdef LLVM_OLDER_THAN_16
236 const TargetRegisterClass *RC) const {
237 #else
238 const TargetRegisterClass *RC, Register vReg) const {
239 #endif
240 DebugLoc DL;
241
242 if (I != MBB.end()) DL = I->getDebugLoc();
243 BuildMI(MBB, I, DL, get(plugin_->getLoad(RC)), DestReg).addFrameIndex(FI)
244 .addImm(0);
245
246 LLVMContext& context = MBB.getParent()->getFunction().getContext();
247 llvm::Metadata* md = llvm::MDString::get(context, "AA_CATEGORY_STACK_SLOT");
248 MDNode* mdNode =
249 MDNode::get(context, llvm::ArrayRef<llvm::Metadata*>(&md, 1));
250 MachineOperand metaDataOperand = MachineOperand::CreateMetadata(mdNode);
251 I--; // buildmi moves the iterator to next ins, point to the created one.
252 I->addOperand(metaDataOperand);
253}
254
255/**
256 * Creates instruction for copying value from a register to another.
257 *
258 * @param mbb Basic block where the copy is done.
259 * @param mbbi Iterator to the place where the copy instruction is added.
260 * @param srcReg Register where the value is copied from.
261 * @param destReg Register where the value is copied to.
262 * @param rc Class of the register to copy.
263 */
265 MachineBasicBlock& mbb,
266 MachineBasicBlock::iterator mbbi,
267 const DebugLoc& DL,
268 MCRegister destReg, MCRegister srcReg,
269 bool killSrc) const
270{
271 DebugLoc dl;
272 if (mbbi != mbb.end()) dl = mbbi->getDebugLoc();
273/*
274 BuildMI(mbb, mbbi, dl,
275 get(plugin_->getRegCopy(destReg, srcReg)), destReg).
276 .addReg(SrcReg, getKillRegState(isKillSrc));
277*/
278 if (copyPhysVectorReg(mbb, mbbi, dl, destReg, srcReg, killSrc)) {
279 return;
280 }
281
282 if (TCE::R1RegsRegClass.contains(destReg, srcReg)) {
283 BuildMI(mbb, mbbi, dl, get(TCE::MOVI1rr), destReg)
284 .addReg(srcReg, getKillRegState(killSrc));
285 } else if (TCE::R32IRegsRegClass.contains(destReg, srcReg)) {
286 BuildMI(mbb, mbbi, dl, get(TCE::MOVI32rr), destReg)
287 .addReg(srcReg, getKillRegState(killSrc));
288 } else if (TCE::R64RegsRegClass.contains(destReg, srcReg)) {
289 BuildMI(mbb, mbbi, dl, get(TCE::MOV64ss), destReg)
290 .addReg(srcReg, getKillRegState(killSrc));
291 } else if (TCE::FPRegsRegClass.contains(destReg, srcReg)) {
292 BuildMI(mbb, mbbi, dl, get(TCE::MOVff), destReg)
293 .addReg(srcReg, getKillRegState(killSrc));
294 } else if (TCE::HFPRegsRegClass.contains(destReg, srcReg)) {
295 BuildMI(mbb, mbbi, dl, get(TCE::MOVhh), destReg)
296 .addReg(srcReg, getKillRegState(killSrc));
297 } else if (TCE::R1RegsRegClass.contains(destReg) &&
298 TCE::R32IRegsRegClass.contains(srcReg)) {
299 BuildMI(mbb, mbbi, dl, get(TCE::MOVI32I1rr), destReg)
300 .addReg(srcReg, getKillRegState(killSrc));
301 } else if (TCE::R1RegsRegClass.contains(srcReg) &&
302 TCE::R32IRegsRegClass.contains(destReg)) {
303 BuildMI(mbb, mbbi, dl, get(TCE::MOVI1I32rr), destReg)
304 .addReg(srcReg, getKillRegState(killSrc));
305 } else if (TCE::GuardRegsRegClass.contains(destReg, srcReg)) {
306 BuildMI(mbb, mbbi, dl, get(TCE::MOVGrr), destReg)
307 .addReg(srcReg, getKillRegState(killSrc));
308 } else if (TCE::GuardRegsRegClass.contains(srcReg) &&
309 TCE::R32IRegsRegClass.contains(destReg)) {
310 BuildMI(mbb, mbbi, dl, get(TCE::MOVGI32rr), destReg)
311 .addReg(srcReg, getKillRegState(killSrc));
312 } else if (TCE::R32IRegsRegClass.contains(srcReg) &&
313 TCE::GuardRegsRegClass.contains(destReg)) {
314 BuildMI(mbb, mbbi, dl, get(TCE::MOVI32Grr), destReg)
315 .addReg(srcReg, getKillRegState(killSrc));
316 } else if (TCE::GuardRegsRegClass.contains(srcReg) &&
317 TCE::R1RegsRegClass.contains(destReg)) {
318 BuildMI(mbb, mbbi, dl, get(TCE::MOVGI1rr), destReg)
319 .addReg(srcReg, getKillRegState(killSrc));
320 } else if (TCE::R1RegsRegClass.contains(srcReg) &&
321 TCE::GuardRegsRegClass.contains(destReg)) {
322 BuildMI(mbb, mbbi, dl, get(TCE::MOVI1Grr), destReg)
323 .addReg(srcReg, getKillRegState(killSrc));
324 } else {
325 assert(
326 false && "TCERegisterInfo::copyPhysReg(): Can't copy register");
327
328 }
329}
330
331/*
332 * Reverses a condition.
333 *
334 * @param cond condition to reverse. This is modified.
335 *
336 * @return false if did reverse condition, true if could not.
337 */
338bool
340 llvm::SmallVectorImpl<llvm::MachineOperand>& cond) const {
341 assert(cond.size() != 0);
342
343 // from true to false
344 if (cond.size() == 1) {
345 cond.push_back(MachineOperand::CreateImm(false));
346 return false;
347 } else if (cond.size() == 2) {
348 // from false to true
349 if (cond[1].getImm() == false) {
350 cond[1].setImm(true);
351 } else {
352 // from true to false
353 assert(cond[1].getImm() == true);
354 cond[1].setImm(false);
355 }
356 return false;
357 } else if (cond.size() == 3) {
358 switch (cond[2].getImm()) {
359 case 2:
360 // eq -> ne
361 cond[2].setImm(3);
362 return false;
363 case 3:
364 // ne -> eq
365 cond[2].setImm(2);
366 return false;
367 case 4:
368 // gt -> le
369 cond[2].setImm(5);
370 return false;
371 case 5:
372 // le -> gt
373 cond[2].setImm(4);
374 return false;
375 case 6:
376 // ltu -> geu
377 cond[2].setImm(7);
378 return false;
379 case 7:
380 // geu -> ltu
381 cond[2].setImm(6);
382 return false;
383 case 14:
384 // lt -> ge
385 cond[2].setImm(16);
386 return false;
387 case 15:
388 // ltu -> geu
389 cond[2].setImm(17);
390 return false;
391 case 16:
392 // ge -> lt
393 cond[2].setImm(14);
394 return false;
395 case 17:
396 // geu -> ltu
397 cond[2].setImm(15);
398 return false;
399 // case 100+: register-immediate versions of branch ops
400 case 102:
401 // eg -> ne
402 cond[2].setImm(103);
403 return false;
404 case 103:
405 // ne -> eq
406 cond[2].setImm(102);
407 return false;
408 case 104:
409 // gt -> le
410 cond[2].setImm(105);
411 return false;
412 case 105:
413 // le -> gt
414 cond[2].setImm(104);
415 return false;
416 case 106:
417 // ltu -> geu
418 cond[2].setImm(107);
419 return false;
420 case 107:
421 // geu -> ltu
422 cond[2].setImm(106);
423 return false;
424 case 114:
425 // lt -> ge
426 cond[2].setImm(116);
427 return false;
428 case 115:
429 // ltu -> geu
430 cond[2].setImm(117);
431 return false;
432 case 116:
433 // ge -> lt
434 cond[2].setImm(114);
435 return false;
436 case 117:
437 // geu -> ltu
438 cond[2].setImm(115);
439 return false;
440 default:
441 return true;
442 }
443 }
444 return true;
445}
446
447/**
448 * Analyzes branches of MBB.
449 *
450 * @param mbb MBB to analyze
451 * @param tbb Puts the jump target or condition true target MBB here
452 * @param fbb Puts the condition false target here, if not fall-thru
453 * @param cond puts the condition data (predcate reg and T/F) here
454 * @return false if could analyze, true if could not analyze
455 */
456bool
458 MachineBasicBlock &mbb, MachineBasicBlock *&tbb,
459 MachineBasicBlock *&fbb,
460 llvm::SmallVectorImpl<llvm::MachineOperand>& cond, bool allowModify)
461 const {
462 if (mbb.empty()) {
463 return false;
464 }
465
466 MachineBasicBlock::iterator i = mbb.end(); i--;
467
468 MachineInstr& lastIns = *i;
469 switch (lastIns.getOpcode()) {
470 case TCE::TCEBRCOND:
471 tbb = lastIns.getOperand(1).getMBB();
472 cond.push_back(i->getOperand(0));
473 cond.push_back(MachineOperand::CreateImm(true));
474 return false;
475 case TCE::TCEBRICOND:
476 tbb = lastIns.getOperand(1).getMBB();
477 cond.push_back(i->getOperand(0));
478 cond.push_back(MachineOperand::CreateImm(false));
479 return false;
480 case TCE::TCEBRIND:
481 case TCE::TCEBR: {
482 // indirect jump cannot be analyzed
483 if (!lastIns.getOperand(0).isMBB()) {
484 return true;
485 }
486
487 if (i == mbb.begin()) {
488 tbb = lastIns.getOperand(0).getMBB();
489 return false; // uncond jump only ins in mbb.
490 }
491 i--;
492 if (i->getOpcode() == TCE::TCEBRCOND) {
493 tbb = i->getOperand(1).getMBB();
494 fbb = lastIns.getOperand(0).getMBB();
495 cond.push_back(i->getOperand(0));
496 cond.push_back(MachineOperand::CreateImm(true));
497 return false;
498 }
499 if (i->getOpcode() == TCE::TCEBRICOND) {
500 tbb = i->getOperand(1).getMBB();
501 fbb = lastIns.getOperand(0).getMBB();
502 cond.push_back(i->getOperand(0));
503 cond.push_back(MachineOperand::CreateImm(false));
504 return false;
505 }
506 // two uncond branches not allowed
507 assert(i->getOpcode() != TCE::TCEBR);
508
509 if (i->getDesc().isBranch()) {
510 tbb = i->getOperand(2).getMBB();
511 fbb = lastIns.getOperand(0).getMBB();
512 return plugin_->analyzeCCBranch(*i, cond);
513 } else { // only conditional branch.
514 tbb = lastIns.getOperand(0).getMBB();
515 return false;
516 }
517 }
518 default:
519 // if some another branch, it's unknown brach
520 // if not brannch, it's fallthourgh
521 if (lastIns.getDesc().isBranch()) {
522 tbb = lastIns.getOperand(2).getMBB();
523 return plugin_->analyzeCCBranch(lastIns, cond);
524 } else {
525 return false;
526 }
527 }
528 // should never be here
529 return true;
530}
531
532namespace {
533class TCEPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
534public:
535 TCEPipelinerLoopInfo() {}
536 bool
537 shouldIgnoreForPipelining(const MachineInstr *MI) const override {
538 return false;
539 }
540
541 // If the trip count is statically known to be greater than TC, return
542 // true. If the trip count is statically known to be not greater than TC,
543 // return false. Otherwise return nullopt and fill out Cond with the test
544 // condition.
545 #ifdef LLVM_OLDER_THAN_16
546 Optional<bool>
547 #else
548 std::optional<bool>
549 #endif
550 createTripCountGreaterCondition(
551 int TC, MachineBasicBlock &MBB,
552 SmallVectorImpl<MachineOperand> &Cond) override {
553 return true;
554 }
555
556 void setPreheader(MachineBasicBlock *NewPreheader) override{};
557
558 void adjustTripCount(int TripCountAdjust) override{};
559
560 void disposed() override{};
561};
562} // namespace
563
564std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
565TCEInstrInfo::analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const {
566 return std::make_unique<TCEPipelinerLoopInfo>();
567}
568
569bool
570TCEInstrInfo::isPredicated(const MachineInstr& mi_ref) const {
571 const MachineInstr* mi = &mi_ref;
572 // TODO: should be conditional move here..
573 if (mi->getOpcode() == TCE::RETL) {
574 return false;
575 }
576
577 // KILL is not a predicated instruction.
578 if (mi->getOpcode() == TCE::KILL) {
579 return false;
580 }
581
582 TCEString opName = plugin_->operationName(mi->getOpcode());
583 return opName[0] == '?' || opName[0] == '!';
584}
585
586bool
587TCEInstrInfo::isPredicable(const MachineInstr& mi_ref) const {
588 const MachineInstr* mi = &mi_ref;
589 if (mi->getOpcode() == TCE::COPY) {
590 return false;
591 }
592
593 // TODO: why is RETL not predicable?
594 if (mi->getOpcode() == TCE::RETL) {
595 return false;
596 }
597
598 if (isPredicated(*mi)) {
599 return false;
600 }
601
602 if (getMatchingCondBranchOpcode(mi->getOpcode(),false) == -1) {
603 return false;
604 }
605
606 for (int oper = mi->getNumOperands() - 1; oper >= 0; --oper) {
607 MachineOperand mo = mi->getOperand(oper);
608
609 if ((mo.isReg() && !mo.isUse() && !mo.isImplicit())) {
610 continue;
611 }
612
613 // TODO: support operand changing for fp imms etc.!
614 if (!mo.isReg() && !mo.isImm()) {
615 return false;
616 }
617 }
618 return true;
619}
620
621// todo: mostlly ripped from hexagon.
622// check the legal things
624 MachineInstr& mi_ref,
625 ArrayRef<MachineOperand> cond
626) const {
627
628 MachineInstr *mi = &mi_ref;
629
630 int opc = mi->getOpcode();
631
632 assert (isPredicable(*mi) && "Expected predicable instruction");
633
634 bool invertJump = (cond.size() >1 && cond[1].isImm() &&
635 (cond[1].getImm() == 0));
636
637 mi->setDesc(get(getMatchingCondBranchOpcode(opc, invertJump)));
638 //
639 // This assumes that the predicate is always the first operand
640 // in the set of inputs.
641 //
642 mi->addOperand(mi->getOperand(mi->getNumOperands()-1));
643 int oper;
644 // why -3 in hexagon?
645 for (oper = mi->getNumOperands() - 2; oper >= 0; --oper) {
646 MachineOperand mo = mi->getOperand(oper);
647 // todo: why this break in hexagon?
648 if ((mo.isReg() && !mo.isUse() && !mo.isImplicit())) {
649 break;
650 }
651
652 if (mo.isReg()) {
653 mi->getOperand(oper+1).ChangeToRegister(mo.getReg(), mo.isDef(),
654 mo.isImplicit(), mo.isKill(),
655 mo.isDead(), mo.isUndef(),
656 mo.isDebug());
657 } else if (mo.isImm()) {
658 mi->getOperand(oper+1).ChangeToImmediate(mo.getImm());
659 } else if (mo.isFPImm()) {
660 mi->getOperand(oper+1).ChangeToFPImmediate(mo.getFPImm());
661 } else if (mo.isGlobal()) {
662 // TODO: what to do here?
663 llvm_unreachable("Unexpected operand type");
664 mi->getOperand(oper+1).ChangeToImmediate(mo.getImm());
665 } else {
666 llvm_unreachable("Unexpected operand type");
667 }
668 }
669
670 MachineOperand PredMO = cond[0];
671 mi->getOperand(oper+1).ChangeToRegister(PredMO.getReg(), PredMO.isDef(),
672 PredMO.isImplicit(), PredMO.isKill(),
673 PredMO.isDead(), PredMO.isUndef(),
674 PredMO.isDebug());
675
676 return true;
677}
678
679
680int TCEInstrInfo::getMatchingCondBranchOpcode(int opc, bool inv) const {
681
682 if (!inv) {
683 return plugin_->getTruePredicateOpcode(opc);
684 } else {
685 return plugin_->getFalsePredicateOpcode(opc);
686 }
687}
688
689
690bool
692 MachineInstr& MI, std::vector<MachineOperand>& Pred,
693 bool SkipDead) const {
694 for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) {
695 MachineOperand MO = MI.getOperand(oper);
696 if (MO.isReg() && MO.isDef()) {
697 const TargetRegisterClass* RC =
698 ri_.getMinimalPhysRegClass(MO.getReg());
699 if (RC == &TCE::GuardRegsRegClass || RC == &TCE::R1RegsRegClass) {
700 Pred.push_back(MO);
701 return true;
702 }
703 }
704 }
705 return false;
706}
707
708bool
710isProfitableToIfCvt(MachineBasicBlock &MBB,
711 unsigned NumCycles,
712 unsigned ExtraPredCycles,
713 BranchProbability Probability) const {
714 return true;
715}
716
717
718bool
720isProfitableToIfCvt(MachineBasicBlock &TMBB,
721 unsigned NumTCycles,
722 unsigned ExtraTCycles,
723 MachineBasicBlock &FMBB,
724 unsigned NumFCycles,
725 unsigned ExtraFCycles,
726 BranchProbability Probability) const {
727 return true;
728}
729
730
731std::tuple<int, int>
733 return plugin_->getPointerAdjustment(offset);
734}
735
736DFAPacketizer *
738 const TargetSubtargetInfo &STI) const {
739 const InstrItineraryData *II = STI.getInstrItineraryData();
740 DFAPacketizer *dfa =
741 static_cast<const TCESubtarget &>(STI).createDFAPacketizer(II);
742 assert(dfa != nullptr);
743 return dfa;
744}
745
#define assert(condition)
int getMatchingCondBranchOpcode(int Opc, bool inverted) const
const TCERegisterInfo ri_
virtual void storeRegToStackSlot(MachineBasicBlock &mbb, MachineBasicBlock::iterator mbbi, unsigned srcReg, bool isKill, int frameIndex, const TargetRegisterClass *rc, Register vReg) const
virtual bool isPredicated(const MachineInstr &MI) const override
unsigned removeBranch(MachineBasicBlock &mbb, int *BytesRemoved=nullptr) const override
virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, llvm::SmallVectorImpl< llvm::MachineOperand > &cond, bool allowModify=false) const override
virtual void copyPhysReg(MachineBasicBlock &mbb, MachineBasicBlock::iterator mbbi, const DebugLoc &DL, MCRegister destReg, MCRegister srcReg, bool KillSrc) const override
std::tuple< int, int > getPointerAdjustment(int offset) const
TCEInstrInfo(const TCETargetMachinePlugin *plugin)
virtual bool reverseBranchCondition(llvm::SmallVectorImpl< llvm::MachineOperand > &cond) const override
virtual ~TCEInstrInfo()
virtual bool isPredicable(const MachineInstr &MI) const override
virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const
virtual void loadRegFromStackSlot(MachineBasicBlock &mbb, MachineBasicBlock::iterator mbbi, unsigned destReg, int frameIndex, const TargetRegisterClass *rc, Register vReg) const
virtual DFAPacketizer * CreateTargetScheduleState(const TargetSubtargetInfo &) const override
virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override
bool copyPhysVectorReg(MachineBasicBlock &mbb, MachineBasicBlock::iterator mbbi, const DebugLoc &DL, MCRegister destReg, MCRegister srcReg, bool killSrc) const
virtual bool PredicateInstruction(MachineInstr &mi, ArrayRef< MachineOperand > cond) const override
virtual unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
const TCETargetMachinePlugin * plugin_
virtual void insertCCBranch(MachineBasicBlock &mbb, MachineBasicBlock &tbb, ArrayRef< MachineOperand > cond, const DebugLoc &dl) const
std::unique_ptr< PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
Analyze loop L, which must be a single-basic-block loop, and if the conditions can be understood enou...
virtual bool ClobbersPredicate(MachineInstr &MI, std::vector< MachineOperand > &Pred, bool SkipDead) const override
virtual int getStore(const TargetRegisterClass *rc) const =0
virtual int getTruePredicateOpcode(unsigned opc) const =0
virtual bool analyzeCCBranch(llvm::MachineInstr &i, llvm::SmallVectorImpl< llvm::MachineOperand > &cond) const
virtual int getFalsePredicateOpcode(unsigned opc) const =0
virtual std::tuple< int, int > getPointerAdjustment(int offset) const =0
virtual std::string operationName(unsigned opc) const =0
Returns operation name corresponding to llvm target opcode.
virtual int getLoad(const TargetRegisterClass *rc) const =0