diff --git a/llvm/lib/Target/ARM/ARM.h b/llvm/lib/Target/ARM/ARM.h --- a/llvm/lib/Target/ARM/ARM.h +++ b/llvm/lib/Target/ARM/ARM.h @@ -37,6 +37,7 @@ Pass *createMVETailPredicationPass(); FunctionPass *createARMLowOverheadLoopsPass(); +FunctionPass *createARMLowOverheadLoopsBlockPlacementPass(); Pass *createARMParallelDSPPass(); FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOpt::Level OptLevel); diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoopBlockPlacement.h b/llvm/lib/Target/ARM/ARMLowOverheadLoopBlockPlacement.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/ARM/ARMLowOverheadLoopBlockPlacement.h @@ -0,0 +1,22 @@ +#ifndef LLVM_CODEGEN_ARMLOWOVERHEADLOOPBLOCKPLACEMENT_H +#define LLVM_CODEGEN_ARMLOWOVERHEADLOOPBLOCKPLACEMENT_H + +#include "ARMBasicBlockInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { +class ARMLowOverheadLoopBlockPlacement : public MachineFunctionPass { +private: + const ARMBaseInstrInfo *TII; + std::unique_ptr BBUtils = nullptr; + +public: + static char ID; + ARMLowOverheadLoopBlockPlacement() : MachineFunctionPass(ID) {} + + bool runOnMachineFunction(MachineFunction &MF) override; + void moveBasicBlock(MachineBasicBlock *BB, MachineBasicBlock *After); + bool blockIsBefore(MachineBasicBlock *BB, MachineBasicBlock *Other); +}; +} // namespace llvm +#endif // LLVM_CODEGEN_ARMLOWOVERHEADLOOPBLOCKPLACEMENT_H diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoopBlockPlacement.cpp b/llvm/lib/Target/ARM/ARMLowOverheadLoopBlockPlacement.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/ARM/ARMLowOverheadLoopBlockPlacement.cpp @@ -0,0 +1,114 @@ +#include "ARMLowOverheadLoopBlockPlacement.h" +#include "ARM.h" +#include "ARMBaseInstrInfo.h" +#include "ARMSubtarget.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" + +using namespace llvm; + +#define DEBUG_TYPE "arm-low-overhead-loops-block-placement" +#define DEBUG_PREFIX "ARM Loops Block Placement: " + +char ARMLowOverheadLoopBlockPlacement::ID = 0; + +static RegisterPass + X("arm-low-overhead-loops-block-placement", + "ARM low-overhead loops block placement", false, false); + +FunctionPass *llvm::createARMLowOverheadLoopsBlockPlacementPass() { + return new ARMLowOverheadLoopBlockPlacement(); +} + +bool ARMLowOverheadLoopBlockPlacement::runOnMachineFunction( + MachineFunction &MF) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Running on " << MF.getName() << "\n"); + const ARMSubtarget &ST = static_cast(MF.getSubtarget()); + if (!ST.hasLOB()) + return false; + TII = static_cast(ST.getInstrInfo()); + BBUtils = std::unique_ptr(new ARMBasicBlockUtils(MF)); + BBUtils->computeAllBlockSizes(); + BBUtils->adjustBBOffsetsAfter(&MF.front()); + bool Changed = false; + for (auto &BB : MF) { + // Check if the block has a backwards WhileLoopStart instruction and move + // the target if so + for (auto &MI : BB.terminators()) { + if (MI.getOpcode() != ARM::t2WhileLoopStart) + continue; + MachineBasicBlock *Target = MI.getOperand(1).getMBB(); + if (blockIsBefore(&BB, Target)) + continue; + LLVM_DEBUG(dbgs() << DEBUG_PREFIX + << "Found a backwards t2WhileLoopStart from " + << BB.getName() << " to " << Target->getName() << "\n"); + // Make sure that moving this block would not cause a WLS in the target BB + // to branch backwards + bool CanMove = true; + for (auto &MI : Target->terminators()) { + if (MI.getOpcode() != ARM::t2WhileLoopStart) + continue; + MachineBasicBlock *Target2 = MI.getOperand(1).getMBB(); + // We can move the block as long as the WLS doesn't become a backwards + // branch or it was already a backwards branch + if (blockIsBefore(&BB, Target2) || blockIsBefore(Target2, Target)) + continue; + CanMove = false; + break; + } + if (CanMove) { + moveBasicBlock(Target, &BB); + Changed = true; + } + } + } + return Changed; +} + +bool ARMLowOverheadLoopBlockPlacement::blockIsBefore(MachineBasicBlock *BB, + MachineBasicBlock *Other) { + return BBUtils->getOffsetOf(Other) > BBUtils->getOffsetOf(BB); +} + +void ARMLowOverheadLoopBlockPlacement::moveBasicBlock( + MachineBasicBlock *BB, MachineBasicBlock *After) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Moving " << BB->getName() << " after " + << After->getName() << "\n"); + MachineBasicBlock *BBPrevious = BB->getPrevNode(); + MachineBasicBlock *AfterNext = After->getNextNode(); + MachineBasicBlock *BBNext = BB->getNextNode(); + + BB->moveAfter(After); + + auto fixFallthrough = [&](MachineBasicBlock *From, MachineBasicBlock *To) { + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Checking for fallthrough from " + << From->getName() << " to " << To->getName() << "\n"); + assert(From->isSuccessor(To) && + "'To' is expected to be a successor of 'From'"); + MachineInstr &Terminator = *(--From->terminators().end()); + if (!Terminator.isUnconditionalBranch()) { + // The BB doesn't have an unconditional branch so it relied on + // fall-through. Fix by adding an unconditional branch to the moved BB. + MachineInstrBuilder MIB = + BuildMI(From, Terminator.getDebugLoc(), TII->get(ARM::t2B)); + MIB.addMBB(To); + MIB.addImm(ARMCC::CondCodes::AL); + MIB.addReg(ARM::NoRegister); + LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Adding unconditional branch from " + << From->getName() << " to " << To->getName() << ": " + << *MIB.getInstr()); + } + }; + + // Fix fall-through to the moved BB from the one that used to be before it + if (BBPrevious && BBPrevious->isSuccessor(BB)) + fixFallthrough(BBPrevious, BB); + // Fix fall through from the destination BB to the one that used to follow + if (AfterNext && After->isSuccessor(AfterNext)) + fixFallthrough(After, AfterNext); + // Fix fall through from the moved BB to the one that used to follow + if (BBNext && BB->isSuccessor(BBNext)) + fixFallthrough(BB, BBNext); + + BBUtils->adjustBBOffsetsAfter(After); +} diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -11,6 +11,7 @@ #include "ARMTargetMachine.h" #include "ARM.h" +#include "ARMLowOverheadLoopBlockPlacement.h" #include "ARMMacroFusion.h" #include "ARMSubtarget.h" #include "ARMTargetObjectFile.h" @@ -554,6 +555,7 @@ } void ARMPassConfig::addPreEmitPass2() { + addPass(createARMLowOverheadLoopsBlockPlacementPass()); addPass(createARMConstantIslandPass()); addPass(createARMLowOverheadLoopsPass()); diff --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt --- a/llvm/lib/Target/ARM/CMakeLists.txt +++ b/llvm/lib/Target/ARM/CMakeLists.txt @@ -41,6 +41,7 @@ ARMParallelDSP.cpp ARMLoadStoreOptimizer.cpp ARMLowOverheadLoops.cpp + ARMLowOverheadLoopBlockPlacement.cpp ARMMCInstLower.cpp ARMMachineFunctionInfo.cpp ARMMacroFusion.cpp diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/block-placement.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/block-placement.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/block-placement.mir @@ -0,0 +1,383 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=thumbv8.1m.main-none-eabi -mattr=+mve -run-pass=arm-low-overhead-loops-block-placement %s -o - | FileCheck %s +--- | + %struct.arm_fir_instance_f32 = type { i16, float*, float* } + + define void @backwards_branch(%struct.arm_fir_instance_f32* nocapture readonly %S, float* nocapture readonly %pSrc, float* nocapture %pDst, i32 %blockSize) #0 { + entry: + ret void + } + + define void @backwards_branch_fallthrough(%struct.arm_fir_instance_f32* nocapture readonly %S, float* nocapture readonly %pSrc, float* nocapture %pDst, i32 %blockSize) #0 { + entry: + ret void + } + +... +--- +name: backwards_branch +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: + - { reg: '$r0', virtual-reg: '' } + - { reg: '$r1', virtual-reg: '' } + - { reg: '$r2', virtual-reg: '' } + - { reg: '$r3', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 120 + offsetAdjustment: 0 + maxAlignment: 8 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: '', type: spill-slot, offset: -92, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: spill-slot, offset: -96, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 2, name: '', type: spill-slot, offset: -100, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 3, name: '', type: spill-slot, offset: -104, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 4, name: '', type: spill-slot, offset: -108, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 5, name: '', type: spill-slot, offset: -112, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 6, name: '', type: spill-slot, offset: -116, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 7, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 8, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r11', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 9, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r10', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 10, name: '', type: spill-slot, offset: -16, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r9', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 11, name: '', type: spill-slot, offset: -20, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r8', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 12, name: '', type: spill-slot, offset: -24, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r7', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 13, name: '', type: spill-slot, offset: -28, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r6', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 14, name: '', type: spill-slot, offset: -32, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r5', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 15, name: '', type: spill-slot, offset: -36, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r4', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 16, name: '', type: spill-slot, offset: -48, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d13', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 17, name: '', type: spill-slot, offset: -56, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d12', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 18, name: '', type: spill-slot, offset: -64, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d11', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 19, name: '', type: spill-slot, offset: -72, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d10', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 20, name: '', type: spill-slot, offset: -80, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d9', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 21, name: '', type: spill-slot, offset: -88, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d8', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + ; CHECK-LABEL: name: backwards_branch + ; CHECK: bb.0: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: liveins: $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11, $lr, $d8, $d9, $d10, $d11, $d12, $d13 + ; CHECK: t2B %bb.2, 14 /* CC::al */, $noreg + ; CHECK: bb.2: + ; CHECK: successors: %bb.3(0x40000000), %bb.1(0x40000000) + ; CHECK: liveins: $q0, $r2, $r5, $r7, $r10, $r12 + ; CHECK: $r9, $r1 = t2LDRDi8 $sp, 24, 14 /* CC::al */, $noreg + ; CHECK: renamable $r3 = tLDRspi $sp, 3, 14 /* CC::al */, $noreg + ; CHECK: t2WhileLoopStart renamable $r3, %bb.1, implicit-def dead $cpsr + ; CHECK: t2B %bb.3, 14 /* CC::al */, $noreg + ; CHECK: bb.1: + ; CHECK: successors: %bb.5(0x80000000) + ; CHECK: liveins: $q0, $r1, $r2, $r5, $r9, $r10, $r12 + ; CHECK: renamable $r10 = nsw t2SUBri killed renamable $r10, 1, 14 /* CC::al */, $noreg, def $cpsr + ; CHECK: t2B %bb.5, 14 /* CC::al */, killed $cpsr + ; CHECK: bb.3: + ; CHECK: successors: %bb.4(0x80000000) + ; CHECK: liveins: $q0, $r1, $r2, $r3, $r5, $r7, $r9, $r10, $r12 + ; CHECK: $r6 = tMOVr $r5, 14 /* CC::al */, $noreg + ; CHECK: $lr = tMOVr $r3, 14 /* CC::al */, $noreg + ; CHECK: bb.4: + ; CHECK: successors: %bb.4(0x7c000000), %bb.5(0x04000000) + ; CHECK: liveins: $lr, $q0, $r1, $r2, $r3, $r5, $r6, $r7, $r9, $r10, $r12 + ; CHECK: renamable $lr = t2LoopDec killed renamable $lr, 1 + ; CHECK: t2LoopEnd renamable $lr, %bb.4, implicit-def dead $cpsr + ; CHECK: bb.5: + ; CHECK: $sp = frame-destroy tADDspi $sp, 1, 14 /* CC::al */, $noreg + ; CHECK: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11, def $pc + bb.0: + successors: %bb.2(0x40000000) + liveins: $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11, $lr, $d8, $d9, $d10, $d11, $d12, $d13 + + t2B %bb.2, 14 /* CC::al */, $noreg + + bb.1: + successors: %bb.5(0x04000000) + liveins: $q0, $r1, $r2, $r5, $r9, $r10, $r12 + + renamable $r10 = nsw t2SUBri killed renamable $r10, 1, 14 /* CC::al */, $noreg, def $cpsr + t2B %bb.5, 14 /* CC::eq */, killed $cpsr + + bb.2: + successors: %bb.3(0x40000000), %bb.1(0x40000000) + liveins: $q0, $r2, $r5, $r7, $r10, $r12 + + $r9, $r1 = t2LDRDi8 $sp, 24, 14 /* CC::al */, $noreg + renamable $r3 = tLDRspi $sp, 3, 14 /* CC::al */, $noreg + t2WhileLoopStart renamable $r3, %bb.1, implicit-def dead $cpsr + t2B %bb.3, 14 /* CC::al */, $noreg + + bb.3: + successors: %bb.4(0x80000000) + liveins: $q0, $r1, $r2, $r3, $r5, $r7, $r9, $r10, $r12 + + $r6 = tMOVr $r5, 14 /* CC::al */, $noreg + $lr = tMOVr $r3, 14 /* CC::al */, $noreg + + bb.4: + successors: %bb.4(0x7c000000), %bb.5(0x04000000) + liveins: $lr, $q0, $r1, $r2, $r3, $r5, $r6, $r7, $r9, $r10, $r12 + + renamable $lr = t2LoopDec killed renamable $lr, 1 + t2LoopEnd renamable $lr, %bb.4, implicit-def dead $cpsr + + bb.5: + $sp = frame-destroy tADDspi $sp, 1, 14 /* CC::al */, $noreg + $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11, def $pc + +... +--- +name: backwards_branch_fallthrough +alignment: 2 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: + - { reg: '$r0', virtual-reg: '' } + - { reg: '$r1', virtual-reg: '' } + - { reg: '$r2', virtual-reg: '' } + - { reg: '$r3', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 120 + offsetAdjustment: 0 + maxAlignment: 8 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: + - { id: 0, name: '', type: spill-slot, offset: -92, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: spill-slot, offset: -96, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 2, name: '', type: spill-slot, offset: -100, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 3, name: '', type: spill-slot, offset: -104, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 4, name: '', type: spill-slot, offset: -108, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 5, name: '', type: spill-slot, offset: -112, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 6, name: '', type: spill-slot, offset: -116, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 7, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$lr', callee-saved-restored: false, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 8, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r11', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 9, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r10', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 10, name: '', type: spill-slot, offset: -16, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r9', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 11, name: '', type: spill-slot, offset: -20, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r8', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 12, name: '', type: spill-slot, offset: -24, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r7', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 13, name: '', type: spill-slot, offset: -28, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r6', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 14, name: '', type: spill-slot, offset: -32, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r5', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 15, name: '', type: spill-slot, offset: -36, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '$r4', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 16, name: '', type: spill-slot, offset: -48, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d13', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 17, name: '', type: spill-slot, offset: -56, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d12', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 18, name: '', type: spill-slot, offset: -64, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d11', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 19, name: '', type: spill-slot, offset: -72, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d10', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 20, name: '', type: spill-slot, offset: -80, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d9', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 21, name: '', type: spill-slot, offset: -88, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '$d8', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + ; CHECK-LABEL: name: backwards_branch_fallthrough + ; CHECK: bb.0: + ; CHECK: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; CHECK: liveins: $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11, $lr, $d8, $d9, $d10, $d11, $d12, $d13 + ; CHECK: t2Bcc %bb.2, 0 /* CC::eq */, $noreg + ; CHECK: tB %bb.1, 14 /* CC::al */, $noreg + ; CHECK: bb.2: + ; CHECK: successors: %bb.3(0x40000000), %bb.1(0x40000000) + ; CHECK: liveins: $q0, $r2, $r5, $r7, $r10, $r12 + ; CHECK: $r9, $r1 = t2LDRDi8 $sp, 24, 14 /* CC::al */, $noreg + ; CHECK: renamable $r3 = tLDRspi $sp, 3, 14 /* CC::al */, $noreg + ; CHECK: t2WhileLoopStart renamable $r3, %bb.1, implicit-def dead $cpsr + ; CHECK: tB %bb.3, 14 /* CC::al */, $noreg + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: liveins: $q0, $r1, $r2, $r5, $r9, $r10, $r12 + ; CHECK: renamable $r10 = nsw t2SUBri killed renamable $r10, 1, 14 /* CC::al */, $noreg, def $cpsr + ; CHECK: tB %bb.2, 14 /* CC::al */, $noreg + ; CHECK: bb.3: + ; CHECK: successors: %bb.4(0x80000000) + ; CHECK: liveins: $q0, $r1, $r2, $r5, $r9, $r10, $r12 + ; CHECK: renamable $r10 = nsw t2SUBri killed renamable $r10, 1, 14 /* CC::al */, $noreg, def $cpsr + ; CHECK: bb.4: + ; CHECK: successors: %bb.5(0x80000000) + ; CHECK: liveins: $q0, $r1, $r2, $r3, $r5, $r7, $r9, $r10, $r12 + ; CHECK: $r6 = tMOVr $r5, 14 /* CC::al */, $noreg + ; CHECK: $lr = tMOVr $r3, 14 /* CC::al */, $noreg + ; CHECK: bb.5: + ; CHECK: successors: %bb.5(0x7c000000), %bb.6(0x04000000) + ; CHECK: liveins: $lr, $q0, $r1, $r2, $r3, $r5, $r6, $r7, $r9, $r10, $r12 + ; CHECK: renamable $lr = t2LoopDec killed renamable $lr, 1 + ; CHECK: t2LoopEnd renamable $lr, %bb.5, implicit-def dead $cpsr + ; CHECK: bb.6: + ; CHECK: $sp = frame-destroy tADDspi $sp, 1, 14 /* CC::al */, $noreg + ; CHECK: $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11, def $pc + bb.0: + successors: %bb.2(0x40000000), %bb.1(0x40000000) + liveins: $r0, $r1, $r2, $r3, $r4, $r5, $r6, $r7, $r8, $r9, $r10, $r11, $lr, $d8, $d9, $d10, $d11, $d12, $d13 + + t2Bcc %bb.2, 0 /* CC::al */, $noreg + + bb.1: + successors: %bb.2(0x04000000) + liveins: $q0, $r1, $r2, $r5, $r9, $r10, $r12 + + renamable $r10 = nsw t2SUBri killed renamable $r10, 1, 14 /* CC::al */, $noreg, def $cpsr + + bb.2: + successors: %bb.3(0x40000000), %bb.1(0x40000000) + liveins: $q0, $r2, $r5, $r7, $r10, $r12 + + $r9, $r1 = t2LDRDi8 $sp, 24, 14 /* CC::al */, $noreg + renamable $r3 = tLDRspi $sp, 3, 14 /* CC::al */, $noreg + t2WhileLoopStart renamable $r3, %bb.1, implicit-def dead $cpsr + + bb.3: + successors: %bb.4(0x04000000) + liveins: $q0, $r1, $r2, $r5, $r9, $r10, $r12 + + renamable $r10 = nsw t2SUBri killed renamable $r10, 1, 14 /* CC::al */, $noreg, def $cpsr + + bb.4: + successors: %bb.5(0x80000000) + liveins: $q0, $r1, $r2, $r3, $r5, $r7, $r9, $r10, $r12 + + $r6 = tMOVr $r5, 14 /* CC::al */, $noreg + $lr = tMOVr $r3, 14 /* CC::al */, $noreg + + bb.5: + successors: %bb.5(0x7c000000), %bb.6(0x04000000) + liveins: $lr, $q0, $r1, $r2, $r3, $r5, $r6, $r7, $r9, $r10, $r12 + + renamable $lr = t2LoopDec killed renamable $lr, 1 + t2LoopEnd renamable $lr, %bb.5, implicit-def dead $cpsr + + bb.6: + $sp = frame-destroy tADDspi $sp, 1, 14 /* CC::al */, $noreg + $sp = frame-destroy t2LDMIA_RET $sp, 14 /* CC::al */, $noreg, def $r4, def $r5, def $r6, def $r7, def $r8, def $r9, def $r10, def $r11, def $pc + +...