@@ -153,8 +153,8 @@ bool XtensaFixupHwLoops::runOnMachineFunction(MachineFunction &mf) {
153153// Scan loop and find hardware loop pseudo instructions LOOPSTART and LOOPEND.
154154// Transform LOOPSTART to Xtensa instructions and remove LOOPEND.
155155bool XtensaFixupHwLoops::fixupLoopInstrs (MachineLoop *L) {
156- // const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
157156 MachineBasicBlock &MBB = *(L->getHeader ());
157+ const TargetInstrInfo *TII = MBB.getParent ()->getSubtarget ().getInstrInfo ();
158158 bool Changed = false ;
159159 unsigned Num = MBB.getNumber ();
160160 unsigned Offset = BlockInfo[Num].Offset ;
@@ -168,10 +168,17 @@ bool XtensaFixupHwLoops::fixupLoopInstrs(MachineLoop *L) {
168168 MachineInstr *PredI1 = nullptr ;
169169 MachineInstr *FirstMI = nullptr ;
170170
171+ // Find appropriate place for the LOOPEND block
171172 for (auto MBI = L->block_begin (), MBIE = L->block_end (); MBI != MBIE; ++MBI) {
172- if (LastBlockOffset < BlockInfo[(*MBI)->getNumber ()].Offset ) {
173- LastBlockOffset = BlockInfo[(*MBI)->getNumber ()].Offset ;
174- LastBlock = (*MBI);
173+ MachineBasicBlock *TBB = nullptr , *FBB = nullptr ;
174+ SmallVector<MachineOperand, 4 > Cond;
175+ if (!TII->analyzeBranch (*(*MBI), TBB, FBB, Cond)) {
176+ if (FBB && TBB) {
177+ if (LastBlockOffset < BlockInfo[(*MBI)->getNumber ()].Offset ) {
178+ LastBlockOffset = BlockInfo[(*MBI)->getNumber ()].Offset ;
179+ LastBlock = (*MBI);
180+ }
181+ }
175182 }
176183 }
177184
@@ -220,12 +227,43 @@ bool XtensaFixupHwLoops::fixupLoopInstrs(MachineLoop *L) {
220227 DebugLoc DL = PII->getDebugLoc ();
221228 unsigned OffsetLE = BlockInfo[PMBB->getNumber ()].Offset ;
222229
223- // Check if loop end is placed before loop header
224- // In such case add special MBB after loop header and create jump
225- // from loop end to it
230+ // In most cases we expect that blocks in loop are ordered by such manner that block
231+ // with LOOPSTART instruction preceeds block with LOOPEND instruction.
232+ // But in some cases after transformations loop block which contains LOOPEND instruction
233+ // maybe placed before LOOPSTART block during code generaion. We must handle such situation
234+ // because "loop" instruction placed instead of LOOPSTART must have positive offset in the target
235+ // field to the LOOPEND block.
236+ // So, in such situation we add new LOOPEND block after the LOOPSTART block and create jump from old
237+ // LOOPEND block to the new LOOPEND block adn set new LOOPEND block then as target for "loop" instruction
226238 if (OffsetLE < LHOffset) {
227239 LoopEnd = MF->CreateMachineBasicBlock ();
228- MF->insert (++LastBlock->getIterator (), LoopEnd);
240+
241+ // If last block in the loop is whithin 256 byte offset from loop instruction
242+ // then just place LOOPEND block after the last block.
243+ if ((LastBlockOffset - LHOffset) < 256 ) {
244+ // Insert after appropriate block
245+ MF->insert (++LastBlock->getIterator (), LoopEnd);
246+ } else {
247+ // If loop is to large for hardware loop instructuin offset then
248+ // place LoopEnd block just after loop header
249+ MF->insert (++MBB.getIterator (), LoopEnd);
250+ MachineBasicBlock *TBB = nullptr , *FBB = nullptr ;
251+ SmallVector<MachineOperand, 4 > Cond;
252+ if (!TII->analyzeBranch (MBB, TBB, FBB, Cond)) {
253+ if (!FBB) {
254+ // LH block just falls through to its succ
255+ for (auto I = MBB.succ_begin (), E = MBB.succ_end (); I != E;
256+ ++I) {
257+ MachineBasicBlock *Succ = *I;
258+ if (Succ != TBB) {
259+ BuildMI (MBB, MBB.end (), DL, TII->get (Xtensa::J))
260+ .addMBB (Succ);
261+ }
262+ }
263+ }
264+ }
265+ }
266+
229267 LoopEnd->transferSuccessors (PMBB);
230268 LoopEnd->splice (LoopEnd->end (), PMBB, PII, PMBB->end ());
231269
0 commit comments