@@ -185,3 +185,298 @@ void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
185185 report_fatal_error (" Unsupported load immediate value" );
186186 }
187187}
188+
189+ bool XtensaInstrInfo::reverseBranchCondition (
190+ SmallVectorImpl<MachineOperand> &Cond) const {
191+ assert (Cond.size () <= 4 && " Invalid branch condition!" );
192+
193+ switch (Cond[0 ].getImm ()) {
194+ case Xtensa::BEQ:
195+ Cond[0 ].setImm (Xtensa::BNE);
196+ return false ;
197+ case Xtensa::BNE:
198+ Cond[0 ].setImm (Xtensa::BEQ);
199+ return false ;
200+ case Xtensa::BLT:
201+ Cond[0 ].setImm (Xtensa::BGE);
202+ return false ;
203+ case Xtensa::BGE:
204+ Cond[0 ].setImm (Xtensa::BLT);
205+ return false ;
206+ case Xtensa::BLTU:
207+ Cond[0 ].setImm (Xtensa::BGEU);
208+ return false ;
209+ case Xtensa::BGEU:
210+ Cond[0 ].setImm (Xtensa::BLTU);
211+ return false ;
212+ case Xtensa::BEQI:
213+ Cond[0 ].setImm (Xtensa::BNEI);
214+ return false ;
215+ case Xtensa::BNEI:
216+ Cond[0 ].setImm (Xtensa::BEQI);
217+ return false ;
218+ case Xtensa::BGEI:
219+ Cond[0 ].setImm (Xtensa::BLTI);
220+ return false ;
221+ case Xtensa::BLTI:
222+ Cond[0 ].setImm (Xtensa::BGEI);
223+ return false ;
224+ case Xtensa::BGEUI:
225+ Cond[0 ].setImm (Xtensa::BLTUI);
226+ return false ;
227+ case Xtensa::BLTUI:
228+ Cond[0 ].setImm (Xtensa::BGEUI);
229+ return false ;
230+ case Xtensa::BEQZ:
231+ Cond[0 ].setImm (Xtensa::BNEZ);
232+ return false ;
233+ case Xtensa::BNEZ:
234+ Cond[0 ].setImm (Xtensa::BEQZ);
235+ return false ;
236+ case Xtensa::BLTZ:
237+ Cond[0 ].setImm (Xtensa::BGEZ);
238+ return false ;
239+ case Xtensa::BGEZ:
240+ Cond[0 ].setImm (Xtensa::BLTZ);
241+ return false ;
242+ default :
243+ report_fatal_error (" Invalid branch condition!" );
244+ }
245+ }
246+
247+ bool XtensaInstrInfo::analyzeBranch (MachineBasicBlock &MBB,
248+ MachineBasicBlock *&TBB,
249+ MachineBasicBlock *&FBB,
250+ SmallVectorImpl<MachineOperand> &Cond,
251+ bool AllowModify = false ) const {
252+ // Most of the code and comments here are boilerplate.
253+
254+ // Start from the bottom of the block and work up, examining the
255+ // terminator instructions.
256+ MachineBasicBlock::iterator I = MBB.end ();
257+ while (I != MBB.begin ()) {
258+ --I;
259+ if (I->isDebugValue ())
260+ continue ;
261+
262+ // Working from the bottom, when we see a non-terminator instruction, we're
263+ // done.
264+ if (!isUnpredicatedTerminator (*I))
265+ break ;
266+
267+ // A terminator that isn't a branch can't easily be handled by this
268+ // analysis.
269+ SmallVector<MachineOperand, 4 > ThisCond;
270+ ThisCond.push_back (MachineOperand::CreateImm (0 ));
271+ const MachineOperand *ThisTarget;
272+ if (!isBranch (I, ThisCond, ThisTarget))
273+ return true ;
274+
275+ // Can't handle indirect branches.
276+ if (!ThisTarget->isMBB ())
277+ return true ;
278+
279+ if (ThisCond[0 ].getImm () == Xtensa::J) {
280+ // Handle unconditional branches.
281+ if (!AllowModify) {
282+ TBB = ThisTarget->getMBB ();
283+ continue ;
284+ }
285+
286+ // If the block has any instructions after a JMP, delete them.
287+ while (std::next (I) != MBB.end ())
288+ std::next (I)->eraseFromParent ();
289+
290+ Cond.clear ();
291+ FBB = 0 ;
292+
293+ // TBB is used to indicate the unconditinal destination.
294+ TBB = ThisTarget->getMBB ();
295+ continue ;
296+ }
297+
298+ // Working from the bottom, handle the first conditional branch.
299+ if (Cond.empty ()) {
300+ // FIXME: add X86-style branch swap
301+ FBB = TBB;
302+ TBB = ThisTarget->getMBB ();
303+ Cond.push_back (MachineOperand::CreateImm (ThisCond[0 ].getImm ()));
304+
305+ // push remaining operands
306+ for (unsigned int i = 0 ; i < (I->getNumExplicitOperands () - 1 ); i++)
307+ Cond.push_back (I->getOperand (i));
308+
309+ continue ;
310+ }
311+
312+ // Handle subsequent conditional branches.
313+ assert (Cond.size () <= 4 );
314+ assert (TBB);
315+
316+ // Only handle the case where all conditional branches branch to the same
317+ // destination.
318+ if (TBB != ThisTarget->getMBB ())
319+ return true ;
320+
321+ // If the conditions are the same, we can leave them alone.
322+ unsigned OldCond = Cond[0 ].getImm ();
323+ if (OldCond == ThisCond[0 ].getImm ())
324+ continue ;
325+ }
326+
327+ return false ;
328+ }
329+
330+ unsigned XtensaInstrInfo::removeBranch (MachineBasicBlock &MBB,
331+ int *BytesRemoved) const {
332+ // Most of the code and comments here are boilerplate.
333+ MachineBasicBlock::iterator I = MBB.end ();
334+ unsigned Count = 0 ;
335+ if (BytesRemoved)
336+ *BytesRemoved = 0 ;
337+
338+ while (I != MBB.begin ()) {
339+ --I;
340+ SmallVector<MachineOperand, 4 > Cond;
341+ Cond.push_back (MachineOperand::CreateImm (0 ));
342+ const MachineOperand *Target;
343+ if (!isBranch (I, Cond, Target))
344+ break ;
345+ if (!Target->isMBB ())
346+ break ;
347+ // Remove the branch.
348+ if (BytesRemoved)
349+ *BytesRemoved += getInstSizeInBytes (*I);
350+ I->eraseFromParent ();
351+ I = MBB.end ();
352+ ++Count;
353+ }
354+ return Count;
355+ }
356+
357+ unsigned XtensaInstrInfo::insertBranch (
358+ MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
359+ ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
360+ unsigned Count = 0 ;
361+ if (BytesAdded)
362+ *BytesAdded = 0 ;
363+ if (FBB) {
364+ // Need to build two branches then
365+ // one to branch to TBB on Cond
366+ // and a second one immediately after to unconditionally jump to FBB
367+ Count = insertBranchAtInst (MBB, MBB.end (), TBB, Cond, DL, BytesAdded);
368+ auto &MI = *BuildMI (&MBB, DL, get (Xtensa::J)).addMBB (FBB);
369+ Count++;
370+ if (BytesAdded)
371+ *BytesAdded += getInstSizeInBytes (MI);
372+ return Count;
373+ }
374+ // This function inserts the branch at the end of the MBB
375+ Count += insertBranchAtInst (MBB, MBB.end (), TBB, Cond, DL, BytesAdded);
376+ return Count;
377+ }
378+
379+ unsigned XtensaInstrInfo::insertBranchAtInst (MachineBasicBlock &MBB,
380+ MachineBasicBlock::iterator I,
381+ MachineBasicBlock *TBB,
382+ ArrayRef<MachineOperand> Cond,
383+ const DebugLoc &DL,
384+ int *BytesAdded) const {
385+ // Shouldn't be a fall through.
386+ assert (TBB && " InsertBranch must not be told to insert a fallthrough" );
387+ assert (Cond.size () <= 4 &&
388+ " Xtensa branch conditions have less than four components!" );
389+
390+ if (Cond.empty () || (Cond[0 ].getImm () == Xtensa::J)) {
391+ // Unconditional branch
392+ MachineInstr *MI = BuildMI (MBB, I, DL, get (Xtensa::J)).addMBB (TBB);
393+ if (BytesAdded && MI)
394+ *BytesAdded += getInstSizeInBytes (*MI);
395+ return 1 ;
396+ }
397+
398+ unsigned Count = 0 ;
399+ unsigned BR_C = Cond[0 ].getImm ();
400+ MachineInstr *MI = nullptr ;
401+ switch (BR_C) {
402+ case Xtensa::BEQ:
403+ case Xtensa::BNE:
404+ case Xtensa::BLT:
405+ case Xtensa::BLTU:
406+ case Xtensa::BGE:
407+ case Xtensa::BGEU:
408+ MI = BuildMI (MBB, I, DL, get (BR_C))
409+ .addReg (Cond[1 ].getReg ())
410+ .addReg (Cond[2 ].getReg ())
411+ .addMBB (TBB);
412+ break ;
413+ case Xtensa::BEQI:
414+ case Xtensa::BNEI:
415+ case Xtensa::BLTI:
416+ case Xtensa::BLTUI:
417+ case Xtensa::BGEI:
418+ case Xtensa::BGEUI:
419+ MI = BuildMI (MBB, I, DL, get (BR_C))
420+ .addReg (Cond[1 ].getReg ())
421+ .addImm (Cond[2 ].getImm ())
422+ .addMBB (TBB);
423+ break ;
424+ case Xtensa::BEQZ:
425+ case Xtensa::BNEZ:
426+ case Xtensa::BLTZ:
427+ case Xtensa::BGEZ:
428+ MI = BuildMI (MBB, I, DL, get (BR_C)).addReg (Cond[1 ].getReg ()).addMBB (TBB);
429+ break ;
430+ default :
431+ report_fatal_error (" Invalid branch type!" );
432+ }
433+ if (BytesAdded && MI)
434+ *BytesAdded += getInstSizeInBytes (*MI);
435+ ++Count;
436+ return Count;
437+ }
438+
439+ bool XtensaInstrInfo::isBranch (const MachineBasicBlock::iterator &MI,
440+ SmallVectorImpl<MachineOperand> &Cond,
441+ const MachineOperand *&Target) const {
442+ unsigned OpCode = MI->getOpcode ();
443+ switch (OpCode) {
444+ case Xtensa::J:
445+ case Xtensa::JX:
446+ case Xtensa::BR_JT:
447+ Cond[0 ].setImm (OpCode);
448+ Target = &MI->getOperand (0 );
449+ return true ;
450+ case Xtensa::BEQ:
451+ case Xtensa::BNE:
452+ case Xtensa::BLT:
453+ case Xtensa::BLTU:
454+ case Xtensa::BGE:
455+ case Xtensa::BGEU:
456+ Cond[0 ].setImm (OpCode);
457+ Target = &MI->getOperand (2 );
458+ return true ;
459+
460+ case Xtensa::BEQI:
461+ case Xtensa::BNEI:
462+ case Xtensa::BLTI:
463+ case Xtensa::BLTUI:
464+ case Xtensa::BGEI:
465+ case Xtensa::BGEUI:
466+ Cond[0 ].setImm (OpCode);
467+ Target = &MI->getOperand (2 );
468+ return true ;
469+
470+ case Xtensa::BEQZ:
471+ case Xtensa::BNEZ:
472+ case Xtensa::BLTZ:
473+ case Xtensa::BGEZ:
474+ Cond[0 ].setImm (OpCode);
475+ Target = &MI->getOperand (1 );
476+ return true ;
477+
478+ default :
479+ assert (!MI->getDesc ().isBranch () && " Unknown branch opcode" );
480+ return false ;
481+ }
482+ }
0 commit comments