1//===-- LanaiInstrInfo.cpp - Lanai Instruction Information ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the Lanai implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "LanaiInstrInfo.h"
14#include "LanaiAluCode.h"
15#include "LanaiCondCode.h"
16#include "LanaiSubtarget.h"
17#include "MCTargetDesc/LanaiBaseInfo.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/CodeGen/MachineInstrBuilder.h"
21#include "llvm/CodeGen/MachineRegisterInfo.h"
22#include "llvm/Support/ErrorHandling.h"
23
24using namespace llvm;
25
26#define GET_INSTRINFO_CTOR_DTOR
27#include "LanaiGenInstrInfo.inc"
28
29LanaiInstrInfo::LanaiInstrInfo(const LanaiSubtarget &STI)
30 : LanaiGenInstrInfo(STI, RegisterInfo, Lanai::ADJCALLSTACKDOWN,
31 Lanai::ADJCALLSTACKUP),
32 RegisterInfo() {}
33
34void LanaiInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
35 MachineBasicBlock::iterator Position,
36 const DebugLoc &DL,
37 Register DestinationRegister,
38 Register SourceRegister, bool KillSource,
39 bool RenamableDest, bool RenamableSrc) const {
40 if (!Lanai::GPRRegClass.contains(Reg1: DestinationRegister, Reg2: SourceRegister)) {
41 llvm_unreachable("Impossible reg-to-reg copy");
42 }
43
44 BuildMI(BB&: MBB, I: Position, MIMD: DL, MCID: get(Opcode: Lanai::OR_I_LO), DestReg: DestinationRegister)
45 .addReg(RegNo: SourceRegister, Flags: getKillRegState(B: KillSource))
46 .addImm(Val: 0);
47}
48
49void LanaiInstrInfo::storeRegToStackSlot(
50 MachineBasicBlock &MBB, MachineBasicBlock::iterator Position,
51 Register SourceRegister, bool IsKill, int FrameIndex,
52 const TargetRegisterClass *RegisterClass, Register /*VReg*/,
53 MachineInstr::MIFlag /*Flags*/) const {
54 DebugLoc DL;
55 if (Position != MBB.end()) {
56 DL = Position->getDebugLoc();
57 }
58
59 if (!Lanai::GPRRegClass.hasSubClassEq(RC: RegisterClass)) {
60 llvm_unreachable("Can't store this register to stack slot");
61 }
62 BuildMI(BB&: MBB, I: Position, MIMD: DL, MCID: get(Opcode: Lanai::SW_RI))
63 .addReg(RegNo: SourceRegister, Flags: getKillRegState(B: IsKill))
64 .addFrameIndex(Idx: FrameIndex)
65 .addImm(Val: 0)
66 .addImm(Val: LPAC::ADD);
67}
68
69void LanaiInstrInfo::loadRegFromStackSlot(
70 MachineBasicBlock &MBB, MachineBasicBlock::iterator Position,
71 Register DestinationRegister, int FrameIndex,
72 const TargetRegisterClass *RegisterClass, Register /*VReg*/,
73 unsigned /*SubReg*/, MachineInstr::MIFlag /*Flags*/) const {
74 DebugLoc DL;
75 if (Position != MBB.end()) {
76 DL = Position->getDebugLoc();
77 }
78
79 if (!Lanai::GPRRegClass.hasSubClassEq(RC: RegisterClass)) {
80 llvm_unreachable("Can't load this register from stack slot");
81 }
82 BuildMI(BB&: MBB, I: Position, MIMD: DL, MCID: get(Opcode: Lanai::LDW_RI), DestReg: DestinationRegister)
83 .addFrameIndex(Idx: FrameIndex)
84 .addImm(Val: 0)
85 .addImm(Val: LPAC::ADD);
86}
87
88bool LanaiInstrInfo::areMemAccessesTriviallyDisjoint(
89 const MachineInstr &MIa, const MachineInstr &MIb) const {
90 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
91 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
92
93 if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects() ||
94 MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
95 return false;
96
97 // Retrieve the base register, offset from the base register and width. Width
98 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4). If
99 // base registers are identical, and the offset of a lower memory access +
100 // the width doesn't overlap the offset of a higher memory access,
101 // then the memory accesses are different.
102 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
103 int64_t OffsetA = 0, OffsetB = 0;
104 LocationSize WidthA = LocationSize::precise(Value: 0),
105 WidthB = LocationSize::precise(Value: 0);
106 if (getMemOperandWithOffsetWidth(LdSt: MIa, BaseOp&: BaseOpA, Offset&: OffsetA, Width&: WidthA) &&
107 getMemOperandWithOffsetWidth(LdSt: MIb, BaseOp&: BaseOpB, Offset&: OffsetB, Width&: WidthB)) {
108 if (BaseOpA->isIdenticalTo(Other: *BaseOpB)) {
109 int LowOffset = std::min(a: OffsetA, b: OffsetB);
110 int HighOffset = std::max(a: OffsetA, b: OffsetB);
111 LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
112 if (LowWidth.hasValue() &&
113 LowOffset + (int)LowWidth.getValue() <= HighOffset)
114 return true;
115 }
116 }
117 return false;
118}
119
120bool LanaiInstrInfo::expandPostRAPseudo(MachineInstr & /*MI*/) const {
121 return false;
122}
123
124static LPCC::CondCode getOppositeCondition(LPCC::CondCode CC) {
125 switch (CC) {
126 case LPCC::ICC_T: // true
127 return LPCC::ICC_F;
128 case LPCC::ICC_F: // false
129 return LPCC::ICC_T;
130 case LPCC::ICC_HI: // high
131 return LPCC::ICC_LS;
132 case LPCC::ICC_LS: // low or same
133 return LPCC::ICC_HI;
134 case LPCC::ICC_CC: // carry cleared
135 return LPCC::ICC_CS;
136 case LPCC::ICC_CS: // carry set
137 return LPCC::ICC_CC;
138 case LPCC::ICC_NE: // not equal
139 return LPCC::ICC_EQ;
140 case LPCC::ICC_EQ: // equal
141 return LPCC::ICC_NE;
142 case LPCC::ICC_VC: // oVerflow cleared
143 return LPCC::ICC_VS;
144 case LPCC::ICC_VS: // oVerflow set
145 return LPCC::ICC_VC;
146 case LPCC::ICC_PL: // plus (note: 0 is "minus" too here)
147 return LPCC::ICC_MI;
148 case LPCC::ICC_MI: // minus
149 return LPCC::ICC_PL;
150 case LPCC::ICC_GE: // greater than or equal
151 return LPCC::ICC_LT;
152 case LPCC::ICC_LT: // less than
153 return LPCC::ICC_GE;
154 case LPCC::ICC_GT: // greater than
155 return LPCC::ICC_LE;
156 case LPCC::ICC_LE: // less than or equal
157 return LPCC::ICC_GT;
158 default:
159 llvm_unreachable("Invalid condtional code");
160 }
161}
162
163std::pair<unsigned, unsigned>
164LanaiInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
165 return std::make_pair(x&: TF, y: 0u);
166}
167
168ArrayRef<std::pair<unsigned, const char *>>
169LanaiInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
170 using namespace LanaiII;
171 static const std::pair<unsigned, const char *> TargetFlags[] = {
172 {MO_ABS_HI, "lanai-hi"},
173 {MO_ABS_LO, "lanai-lo"},
174 {MO_NO_FLAG, "lanai-nf"}};
175 return ArrayRef(TargetFlags);
176}
177
178bool LanaiInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
179 Register &SrcReg2, int64_t &CmpMask,
180 int64_t &CmpValue) const {
181 switch (MI.getOpcode()) {
182 default:
183 break;
184 case Lanai::SFSUB_F_RI_LO:
185 case Lanai::SFSUB_F_RI_HI:
186 SrcReg = MI.getOperand(i: 0).getReg();
187 SrcReg2 = Register();
188 CmpMask = ~0;
189 CmpValue = MI.getOperand(i: 1).getImm();
190 return true;
191 case Lanai::SFSUB_F_RR:
192 SrcReg = MI.getOperand(i: 0).getReg();
193 SrcReg2 = MI.getOperand(i: 1).getReg();
194 CmpMask = ~0;
195 CmpValue = 0;
196 return true;
197 }
198
199 return false;
200}
201
202// isRedundantFlagInstr - check whether the first instruction, whose only
203// purpose is to update flags, can be made redundant.
204// * SFSUB_F_RR can be made redundant by SUB_RI if the operands are the same.
205// * SFSUB_F_RI can be made redundant by SUB_I if the operands are the same.
206inline static bool isRedundantFlagInstr(MachineInstr *CmpI, unsigned SrcReg,
207 unsigned SrcReg2, int64_t ImmValue,
208 MachineInstr *OI) {
209 if (CmpI->getOpcode() == Lanai::SFSUB_F_RR &&
210 OI->getOpcode() == Lanai::SUB_R &&
211 ((OI->getOperand(i: 1).getReg() == SrcReg &&
212 OI->getOperand(i: 2).getReg() == SrcReg2) ||
213 (OI->getOperand(i: 1).getReg() == SrcReg2 &&
214 OI->getOperand(i: 2).getReg() == SrcReg)))
215 return true;
216
217 if (((CmpI->getOpcode() == Lanai::SFSUB_F_RI_LO &&
218 OI->getOpcode() == Lanai::SUB_I_LO) ||
219 (CmpI->getOpcode() == Lanai::SFSUB_F_RI_HI &&
220 OI->getOpcode() == Lanai::SUB_I_HI)) &&
221 OI->getOperand(i: 1).getReg() == SrcReg &&
222 OI->getOperand(i: 2).getImm() == ImmValue)
223 return true;
224 return false;
225}
226
227inline static unsigned flagSettingOpcodeVariant(unsigned OldOpcode) {
228 switch (OldOpcode) {
229 case Lanai::ADD_I_HI:
230 return Lanai::ADD_F_I_HI;
231 case Lanai::ADD_I_LO:
232 return Lanai::ADD_F_I_LO;
233 case Lanai::ADD_R:
234 return Lanai::ADD_F_R;
235 case Lanai::ADDC_I_HI:
236 return Lanai::ADDC_F_I_HI;
237 case Lanai::ADDC_I_LO:
238 return Lanai::ADDC_F_I_LO;
239 case Lanai::ADDC_R:
240 return Lanai::ADDC_F_R;
241 case Lanai::AND_I_HI:
242 return Lanai::AND_F_I_HI;
243 case Lanai::AND_I_LO:
244 return Lanai::AND_F_I_LO;
245 case Lanai::AND_R:
246 return Lanai::AND_F_R;
247 case Lanai::OR_I_HI:
248 return Lanai::OR_F_I_HI;
249 case Lanai::OR_I_LO:
250 return Lanai::OR_F_I_LO;
251 case Lanai::OR_R:
252 return Lanai::OR_F_R;
253 case Lanai::SL_I:
254 return Lanai::SL_F_I;
255 case Lanai::SRL_R:
256 return Lanai::SRL_F_R;
257 case Lanai::SA_I:
258 return Lanai::SA_F_I;
259 case Lanai::SRA_R:
260 return Lanai::SRA_F_R;
261 case Lanai::SUB_I_HI:
262 return Lanai::SUB_F_I_HI;
263 case Lanai::SUB_I_LO:
264 return Lanai::SUB_F_I_LO;
265 case Lanai::SUB_R:
266 return Lanai::SUB_F_R;
267 case Lanai::SUBB_I_HI:
268 return Lanai::SUBB_F_I_HI;
269 case Lanai::SUBB_I_LO:
270 return Lanai::SUBB_F_I_LO;
271 case Lanai::SUBB_R:
272 return Lanai::SUBB_F_R;
273 case Lanai::XOR_I_HI:
274 return Lanai::XOR_F_I_HI;
275 case Lanai::XOR_I_LO:
276 return Lanai::XOR_F_I_LO;
277 case Lanai::XOR_R:
278 return Lanai::XOR_F_R;
279 default:
280 return Lanai::NOP;
281 }
282}
283
284bool LanaiInstrInfo::optimizeCompareInstr(
285 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2,
286 int64_t /*CmpMask*/, int64_t CmpValue,
287 const MachineRegisterInfo *MRI) const {
288 // Get the unique definition of SrcReg.
289 MachineInstr *MI = MRI->getUniqueVRegDef(Reg: SrcReg);
290 if (!MI)
291 return false;
292
293 // Get ready to iterate backward from CmpInstr.
294 MachineBasicBlock::iterator I = CmpInstr, E = MI,
295 B = CmpInstr.getParent()->begin();
296
297 // Early exit if CmpInstr is at the beginning of the BB.
298 if (I == B)
299 return false;
300
301 // There are two possible candidates which can be changed to set SR:
302 // One is MI, the other is a SUB instruction.
303 // * For SFSUB_F_RR(r1,r2), we are looking for SUB(r1,r2) or SUB(r2,r1).
304 // * For SFSUB_F_RI(r1, CmpValue), we are looking for SUB(r1, CmpValue).
305 MachineInstr *Sub = nullptr;
306 if (SrcReg2 != 0)
307 // MI is not a candidate to transform into a flag setting instruction.
308 MI = nullptr;
309 else if (MI->getParent() != CmpInstr.getParent() || CmpValue != 0) {
310 // Conservatively refuse to convert an instruction which isn't in the same
311 // BB as the comparison. Don't return if SFSUB_F_RI and CmpValue != 0 as Sub
312 // may still be a candidate.
313 if (CmpInstr.getOpcode() == Lanai::SFSUB_F_RI_LO)
314 MI = nullptr;
315 else
316 return false;
317 }
318
319 // Check that SR isn't set between the comparison instruction and the
320 // instruction we want to change while searching for Sub.
321 const TargetRegisterInfo *TRI = &getRegisterInfo();
322 for (--I; I != E; --I) {
323 const MachineInstr &Instr = *I;
324
325 if (Instr.modifiesRegister(Reg: Lanai::SR, TRI) ||
326 Instr.readsRegister(Reg: Lanai::SR, TRI))
327 // This instruction modifies or uses SR after the one we want to change.
328 // We can't do this transformation.
329 return false;
330
331 // Check whether CmpInstr can be made redundant by the current instruction.
332 if (isRedundantFlagInstr(CmpI: &CmpInstr, SrcReg, SrcReg2, ImmValue: CmpValue, OI: &*I)) {
333 Sub = &*I;
334 break;
335 }
336
337 // Don't search outside the containing basic block.
338 if (I == B)
339 return false;
340 }
341
342 // Return false if no candidates exist.
343 if (!MI && !Sub)
344 return false;
345
346 // The single candidate is called MI.
347 if (!MI)
348 MI = Sub;
349
350 if (flagSettingOpcodeVariant(OldOpcode: MI->getOpcode()) != Lanai::NOP) {
351 bool isSafe = false;
352
353 SmallVector<std::pair<MachineOperand *, LPCC::CondCode>, 4>
354 OperandsToUpdate;
355 I = CmpInstr;
356 E = CmpInstr.getParent()->end();
357 while (!isSafe && ++I != E) {
358 const MachineInstr &Instr = *I;
359 for (unsigned IO = 0, EO = Instr.getNumOperands(); !isSafe && IO != EO;
360 ++IO) {
361 const MachineOperand &MO = Instr.getOperand(i: IO);
362 if (MO.isRegMask() && MO.clobbersPhysReg(PhysReg: Lanai::SR)) {
363 isSafe = true;
364 break;
365 }
366 if (!MO.isReg() || MO.getReg() != Lanai::SR)
367 continue;
368 if (MO.isDef()) {
369 isSafe = true;
370 break;
371 }
372 // Condition code is after the operand before SR.
373 LPCC::CondCode CC;
374 CC = (LPCC::CondCode)Instr.getOperand(i: IO - 1).getImm();
375
376 if (Sub) {
377 LPCC::CondCode NewCC = getOppositeCondition(CC);
378 if (NewCC == LPCC::ICC_T)
379 return false;
380 // If we have SUB(r1, r2) and CMP(r2, r1), the condition code based on
381 // CMP needs to be updated to be based on SUB. Push the condition
382 // code operands to OperandsToUpdate. If it is safe to remove
383 // CmpInstr, the condition code of these operands will be modified.
384 if (SrcReg2 != 0 && Sub->getOperand(i: 1).getReg() == SrcReg2 &&
385 Sub->getOperand(i: 2).getReg() == SrcReg) {
386 OperandsToUpdate.push_back(
387 Elt: std::make_pair(x: &((*I).getOperand(i: IO - 1)), y&: NewCC));
388 }
389 } else {
390 // No Sub, so this is x = <op> y, z; cmp x, 0.
391 switch (CC) {
392 case LPCC::ICC_EQ: // Z
393 case LPCC::ICC_NE: // Z
394 case LPCC::ICC_MI: // N
395 case LPCC::ICC_PL: // N
396 case LPCC::ICC_F: // none
397 case LPCC::ICC_T: // none
398 // SR can be used multiple times, we should continue.
399 break;
400 case LPCC::ICC_CS: // C
401 case LPCC::ICC_CC: // C
402 case LPCC::ICC_VS: // V
403 case LPCC::ICC_VC: // V
404 case LPCC::ICC_HI: // C Z
405 case LPCC::ICC_LS: // C Z
406 case LPCC::ICC_GE: // N V
407 case LPCC::ICC_LT: // N V
408 case LPCC::ICC_GT: // Z N V
409 case LPCC::ICC_LE: // Z N V
410 // The instruction uses the V bit or C bit which is not safe.
411 return false;
412 case LPCC::UNKNOWN:
413 return false;
414 }
415 }
416 }
417 }
418
419 // If SR is not killed nor re-defined, we should check whether it is
420 // live-out. If it is live-out, do not optimize.
421 if (!isSafe) {
422 MachineBasicBlock *MBB = CmpInstr.getParent();
423 for (const MachineBasicBlock *Succ : MBB->successors())
424 if (Succ->isLiveIn(Reg: Lanai::SR))
425 return false;
426 }
427
428 // Toggle the optional operand to SR.
429 MI->setDesc(get(Opcode: flagSettingOpcodeVariant(OldOpcode: MI->getOpcode())));
430 MI->addRegisterDefined(Reg: Lanai::SR);
431 CmpInstr.eraseFromParent();
432 return true;
433 }
434
435 return false;
436}
437
438// Identify instructions that can be folded into a SELECT instruction, and
439// return the defining instruction.
440static MachineInstr *canFoldIntoSelect(Register Reg,
441 const MachineRegisterInfo &MRI) {
442 if (!Reg.isVirtual())
443 return nullptr;
444 if (!MRI.hasOneNonDBGUse(RegNo: Reg))
445 return nullptr;
446 MachineInstr *MI = MRI.getVRegDef(Reg);
447 if (!MI)
448 return nullptr;
449 // MI is folded into the SELECT by predicating it.
450 if (!MI->isPredicable())
451 return nullptr;
452 // Check if MI has any non-dead defs or physreg uses. This also detects
453 // predicated instructions which will be reading SR.
454 for (const MachineOperand &MO : llvm::drop_begin(RangeOrContainer: MI->operands(), N: 1)) {
455 // Reject frame index operands.
456 if (MO.isFI() || MO.isCPI() || MO.isJTI())
457 return nullptr;
458 if (!MO.isReg())
459 continue;
460 // MI can't have any tied operands, that would conflict with predication.
461 if (MO.isTied())
462 return nullptr;
463 if (MO.getReg().isPhysical())
464 return nullptr;
465 if (MO.isDef() && !MO.isDead())
466 return nullptr;
467 }
468 bool DontMoveAcrossStores = true;
469 if (!MI->isSafeToMove(SawStore&: DontMoveAcrossStores))
470 return nullptr;
471 return MI;
472}
473
474MachineInstr *
475LanaiInstrInfo::optimizeSelect(MachineInstr &MI,
476 SmallPtrSetImpl<MachineInstr *> &SeenMIs,
477 bool /*PreferFalse*/) const {
478 assert(MI.getOpcode() == Lanai::SELECT && "unknown select instruction");
479 MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
480 MachineInstr *DefMI = canFoldIntoSelect(Reg: MI.getOperand(i: 1).getReg(), MRI);
481 bool Invert = !DefMI;
482 if (!DefMI)
483 DefMI = canFoldIntoSelect(Reg: MI.getOperand(i: 2).getReg(), MRI);
484 if (!DefMI)
485 return nullptr;
486
487 // Find new register class to use.
488 MachineOperand FalseReg = MI.getOperand(i: Invert ? 1 : 2);
489 Register DestReg = MI.getOperand(i: 0).getReg();
490 const TargetRegisterClass *PreviousClass = MRI.getRegClass(Reg: FalseReg.getReg());
491 if (!MRI.constrainRegClass(Reg: DestReg, RC: PreviousClass))
492 return nullptr;
493
494 // Create a new predicated version of DefMI.
495 MachineInstrBuilder NewMI =
496 BuildMI(BB&: *MI.getParent(), I&: MI, MIMD: MI.getDebugLoc(), MCID: DefMI->getDesc(), DestReg);
497
498 // Copy all the DefMI operands, excluding its (null) predicate.
499 const MCInstrDesc &DefDesc = DefMI->getDesc();
500 for (unsigned i = 1, e = DefDesc.getNumOperands();
501 i != e && !DefDesc.operands()[i].isPredicate(); ++i)
502 NewMI.add(MO: DefMI->getOperand(i));
503
504 unsigned CondCode = MI.getOperand(i: 3).getImm();
505 if (Invert)
506 NewMI.addImm(Val: getOppositeCondition(CC: LPCC::CondCode(CondCode)));
507 else
508 NewMI.addImm(Val: CondCode);
509 NewMI.copyImplicitOps(OtherMI: MI);
510
511 // The output register value when the predicate is false is an implicit
512 // register operand tied to the first def. The tie makes the register
513 // allocator ensure the FalseReg is allocated the same register as operand 0.
514 FalseReg.setImplicit();
515 NewMI.add(MO: FalseReg);
516 NewMI->tieOperands(DefIdx: 0, UseIdx: NewMI->getNumOperands() - 1);
517
518 // Update SeenMIs set: register newly created MI and erase removed DefMI.
519 SeenMIs.insert(Ptr: NewMI);
520 SeenMIs.erase(Ptr: DefMI);
521
522 // If MI is inside a loop, and DefMI is outside the loop, then kill flags on
523 // DefMI would be invalid when transferred inside the loop. Checking for a
524 // loop is expensive, but at least remove kill flags if they are in different
525 // BBs.
526 if (DefMI->getParent() != MI.getParent())
527 NewMI->clearKillInfo();
528
529 // The caller will erase MI, but not DefMI.
530 DefMI->eraseFromParent();
531 return NewMI;
532}
533
534// The analyzeBranch function is used to examine conditional instructions and
535// remove unnecessary instructions. This method is used by BranchFolder and
536// IfConverter machine function passes to improve the CFG.
537// - TrueBlock is set to the destination if condition evaluates true (it is the
538// nullptr if the destination is the fall-through branch);
539// - FalseBlock is set to the destination if condition evaluates to false (it
540// is the nullptr if the branch is unconditional);
541// - condition is populated with machine operands needed to generate the branch
542// to insert in insertBranch;
543// Returns: false if branch could successfully be analyzed.
544bool LanaiInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
545 MachineBasicBlock *&TrueBlock,
546 MachineBasicBlock *&FalseBlock,
547 SmallVectorImpl<MachineOperand> &Condition,
548 bool AllowModify) const {
549 // Iterator to current instruction being considered.
550 MachineBasicBlock::iterator Instruction = MBB.end();
551
552 // Start from the bottom of the block and work up, examining the
553 // terminator instructions.
554 while (Instruction != MBB.begin()) {
555 --Instruction;
556
557 // Skip over debug instructions.
558 if (Instruction->isDebugInstr())
559 continue;
560
561 // Working from the bottom, when we see a non-terminator
562 // instruction, we're done.
563 if (!isUnpredicatedTerminator(MI: *Instruction))
564 break;
565
566 // A terminator that isn't a branch can't easily be handled
567 // by this analysis.
568 if (!Instruction->isBranch())
569 return true;
570
571 // Handle unconditional branches.
572 if (Instruction->getOpcode() == Lanai::BT) {
573 if (!AllowModify) {
574 TrueBlock = Instruction->getOperand(i: 0).getMBB();
575 continue;
576 }
577
578 // If the block has any instructions after a branch, delete them.
579 MBB.erase(I: std::next(x: Instruction), E: MBB.end());
580
581 Condition.clear();
582 FalseBlock = nullptr;
583
584 // Delete the jump if it's equivalent to a fall-through.
585 if (MBB.isLayoutSuccessor(MBB: Instruction->getOperand(i: 0).getMBB())) {
586 TrueBlock = nullptr;
587 Instruction->eraseFromParent();
588 Instruction = MBB.end();
589 continue;
590 }
591
592 // TrueBlock is used to indicate the unconditional destination.
593 TrueBlock = Instruction->getOperand(i: 0).getMBB();
594 continue;
595 }
596
597 // Handle conditional branches
598 unsigned Opcode = Instruction->getOpcode();
599 if (Opcode != Lanai::BRCC)
600 return true; // Unknown opcode.
601
602 // Multiple conditional branches are not handled here so only proceed if
603 // there are no conditions enqueued.
604 if (Condition.empty()) {
605 LPCC::CondCode BranchCond =
606 static_cast<LPCC::CondCode>(Instruction->getOperand(i: 1).getImm());
607
608 // TrueBlock is the target of the previously seen unconditional branch.
609 FalseBlock = TrueBlock;
610 TrueBlock = Instruction->getOperand(i: 0).getMBB();
611 Condition.push_back(Elt: MachineOperand::CreateImm(Val: BranchCond));
612 continue;
613 }
614
615 // Multiple conditional branches are not handled.
616 return true;
617 }
618
619 // Return false indicating branch successfully analyzed.
620 return false;
621}
622
623// reverseBranchCondition - Reverses the branch condition of the specified
624// condition list, returning false on success and true if it cannot be
625// reversed.
626bool LanaiInstrInfo::reverseBranchCondition(
627 SmallVectorImpl<llvm::MachineOperand> &Condition) const {
628 assert((Condition.size() == 1) &&
629 "Lanai branch conditions should have one component.");
630
631 LPCC::CondCode BranchCond =
632 static_cast<LPCC::CondCode>(Condition[0].getImm());
633 Condition[0].setImm(getOppositeCondition(CC: BranchCond));
634 return false;
635}
636
637// Insert the branch with condition specified in condition and given targets
638// (TrueBlock and FalseBlock). This function returns the number of machine
639// instructions inserted.
640unsigned LanaiInstrInfo::insertBranch(MachineBasicBlock &MBB,
641 MachineBasicBlock *TrueBlock,
642 MachineBasicBlock *FalseBlock,
643 ArrayRef<MachineOperand> Condition,
644 const DebugLoc &DL,
645 int *BytesAdded) const {
646 // Shouldn't be a fall through.
647 assert(TrueBlock && "insertBranch must not be told to insert a fallthrough");
648 assert(!BytesAdded && "code size not handled");
649
650 // If condition is empty then an unconditional branch is being inserted.
651 if (Condition.empty()) {
652 assert(!FalseBlock && "Unconditional branch with multiple successors!");
653 BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: Lanai::BT)).addMBB(MBB: TrueBlock);
654 return 1;
655 }
656
657 // Else a conditional branch is inserted.
658 assert((Condition.size() == 1) &&
659 "Lanai branch conditions should have one component.");
660 unsigned ConditionalCode = Condition[0].getImm();
661 BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: Lanai::BRCC)).addMBB(MBB: TrueBlock).addImm(Val: ConditionalCode);
662
663 // If no false block, then false behavior is fall through and no branch needs
664 // to be inserted.
665 if (!FalseBlock)
666 return 1;
667
668 BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: Lanai::BT)).addMBB(MBB: FalseBlock);
669 return 2;
670}
671
672unsigned LanaiInstrInfo::removeBranch(MachineBasicBlock &MBB,
673 int *BytesRemoved) const {
674 assert(!BytesRemoved && "code size not handled");
675
676 MachineBasicBlock::iterator Instruction = MBB.end();
677 unsigned Count = 0;
678
679 while (Instruction != MBB.begin()) {
680 --Instruction;
681 if (Instruction->isDebugInstr())
682 continue;
683 if (Instruction->getOpcode() != Lanai::BT &&
684 Instruction->getOpcode() != Lanai::BRCC) {
685 break;
686 }
687
688 // Remove the branch.
689 Instruction->eraseFromParent();
690 Instruction = MBB.end();
691 ++Count;
692 }
693
694 return Count;
695}
696
697Register LanaiInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
698 int &FrameIndex) const {
699 if (MI.getOpcode() == Lanai::LDW_RI)
700 if (MI.getOperand(i: 1).isFI() && MI.getOperand(i: 2).isImm() &&
701 MI.getOperand(i: 2).getImm() == 0) {
702 FrameIndex = MI.getOperand(i: 1).getIndex();
703 return MI.getOperand(i: 0).getReg();
704 }
705 return 0;
706}
707
708Register LanaiInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr &MI,
709 int &FrameIndex) const {
710 if (MI.getOpcode() == Lanai::LDW_RI) {
711 unsigned Reg;
712 if ((Reg = isLoadFromStackSlot(MI, FrameIndex)))
713 return Reg;
714 // Check for post-frame index elimination operations
715 SmallVector<const MachineMemOperand *, 1> Accesses;
716 if (hasLoadFromStackSlot(MI, Accesses)){
717 FrameIndex =
718 cast<FixedStackPseudoSourceValue>(Val: Accesses.front()->getPseudoValue())
719 ->getFrameIndex();
720 return 1;
721 }
722 }
723 return 0;
724}
725
726Register LanaiInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
727 int &FrameIndex) const {
728 if (MI.getOpcode() == Lanai::SW_RI)
729 if (MI.getOperand(i: 0).isFI() && MI.getOperand(i: 1).isImm() &&
730 MI.getOperand(i: 1).getImm() == 0) {
731 FrameIndex = MI.getOperand(i: 0).getIndex();
732 return MI.getOperand(i: 2).getReg();
733 }
734 return 0;
735}
736
737bool LanaiInstrInfo::getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
738 const MachineOperand *&BaseOp,
739 int64_t &Offset,
740 LocationSize &Width) const {
741 // Handle only loads/stores with base register followed by immediate offset
742 // and with add as ALU op.
743 if (LdSt.getNumOperands() != 4)
744 return false;
745 if (!LdSt.getOperand(i: 1).isReg() || !LdSt.getOperand(i: 2).isImm() ||
746 !(LdSt.getOperand(i: 3).isImm() && LdSt.getOperand(i: 3).getImm() == LPAC::ADD))
747 return false;
748
749 switch (LdSt.getOpcode()) {
750 default:
751 return false;
752 case Lanai::LDW_RI:
753 case Lanai::LDW_RR:
754 case Lanai::SW_RR:
755 case Lanai::SW_RI:
756 Width = LocationSize::precise(Value: 4);
757 break;
758 case Lanai::LDHs_RI:
759 case Lanai::LDHz_RI:
760 case Lanai::STH_RI:
761 Width = LocationSize::precise(Value: 2);
762 break;
763 case Lanai::LDBs_RI:
764 case Lanai::LDBz_RI:
765 case Lanai::STB_RI:
766 Width = LocationSize::precise(Value: 1);
767 break;
768 }
769
770 BaseOp = &LdSt.getOperand(i: 1);
771 Offset = LdSt.getOperand(i: 2).getImm();
772
773 if (!BaseOp->isReg())
774 return false;
775
776 return true;
777}
778
779bool LanaiInstrInfo::getMemOperandsWithOffsetWidth(
780 const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
781 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
782 switch (LdSt.getOpcode()) {
783 default:
784 return false;
785 case Lanai::LDW_RI:
786 case Lanai::LDW_RR:
787 case Lanai::SW_RR:
788 case Lanai::SW_RI:
789 case Lanai::LDHs_RI:
790 case Lanai::LDHz_RI:
791 case Lanai::STH_RI:
792 case Lanai::LDBs_RI:
793 case Lanai::LDBz_RI:
794 const MachineOperand *BaseOp;
795 OffsetIsScalable = false;
796 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, Width))
797 return false;
798 BaseOps.push_back(Elt: BaseOp);
799 return true;
800 }
801}
802