@@ -153,8 +153,8 @@ bool XtensaFixupHwLoops::runOnMachineFunction(MachineFunction &mf) {
153
153
// Scan loop and find hardware loop pseudo instructions LOOPSTART and LOOPEND.
154
154
// Transform LOOPSTART to Xtensa instructions and remove LOOPEND.
155
155
bool XtensaFixupHwLoops::fixupLoopInstrs (MachineLoop *L) {
156
- // const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
157
156
MachineBasicBlock &MBB = *(L->getHeader ());
157
+ const TargetInstrInfo *TII = MBB.getParent ()->getSubtarget ().getInstrInfo ();
158
158
bool Changed = false ;
159
159
unsigned Num = MBB.getNumber ();
160
160
unsigned Offset = BlockInfo[Num].Offset ;
@@ -168,10 +168,17 @@ bool XtensaFixupHwLoops::fixupLoopInstrs(MachineLoop *L) {
168
168
MachineInstr *PredI1 = nullptr ;
169
169
MachineInstr *FirstMI = nullptr ;
170
170
171
+ // Find appropriate place for the LOOPEND block
171
172
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
+ }
175
182
}
176
183
}
177
184
@@ -220,12 +227,43 @@ bool XtensaFixupHwLoops::fixupLoopInstrs(MachineLoop *L) {
220
227
DebugLoc DL = PII->getDebugLoc ();
221
228
unsigned OffsetLE = BlockInfo[PMBB->getNumber ()].Offset ;
222
229
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
226
238
if (OffsetLE < LHOffset) {
227
239
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
+
229
267
LoopEnd->transferSuccessors (PMBB);
230
268
LoopEnd->splice (LoopEnd->end (), PMBB, PII, PMBB->end ());
231
269
0 commit comments