[llvm] r372085 - [ARM] LE support in ConstantIslands
Sam Parker via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 17 02:08:05 PDT 2019
Author: sam_parker
Date: Tue Sep 17 02:08:05 2019
New Revision: 372085
URL: http://llvm.org/viewvc/llvm-project?rev=372085&view=rev
Log:
[ARM] LE support in ConstantIslands
The low-overhead branch extension provides a loop-end 'LE' instruction
that performs no decrement nor compare, it just jumps backwards. This
patch modifies the constant islands pass to try to insert LE
instructions in place of a Thumb2 conditional branch, instead of
shrinking it. This only happens if a cmp can be converted to a cbn/z
and used to exit the loop.
Differential Revision: https://reviews.llvm.org/D67404
Added:
llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-cbnz.mir
llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-le-simple.ll
llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-reorder.mir
llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec.mir
Modified:
llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
llvm/trunk/test/CodeGen/ARM/O3-pipeline.ll
Modified: llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp?rev=372085&r1=372084&r2=372085&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp Tue Sep 17 02:08:05 2019
@@ -29,6 +29,7 @@
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -70,6 +71,7 @@ STATISTIC(NumT2BrShrunk, "Number of Thum
STATISTIC(NumCBZ, "Number of CBZ / CBNZ formed");
STATISTIC(NumJTMoved, "Number of jump table destination blocks moved");
STATISTIC(NumJTInserted, "Number of jump table intermediate blocks inserted");
+STATISTIC(NumLEInserted, "Number of LE backwards branches inserted");
static cl::opt<bool>
AdjustJumpTableBlocks("arm-adjust-jump-tables", cl::Hidden, cl::init(true),
@@ -213,6 +215,7 @@ namespace {
const ARMBaseInstrInfo *TII;
const ARMSubtarget *STI;
ARMFunctionInfo *AFI;
+ MachineDominatorTree *DT = nullptr;
bool isThumb;
bool isThumb1;
bool isThumb2;
@@ -225,6 +228,12 @@ namespace {
bool runOnMachineFunction(MachineFunction &MF) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesCFG();
+ AU.addRequired<MachineDominatorTree>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
MachineFunctionProperties getRequiredProperties() const override {
return MachineFunctionProperties().set(
MachineFunctionProperties::Property::NoVRegs);
@@ -350,6 +359,7 @@ bool ARMConstantIslands::runOnMachineFun
isPositionIndependentOrROPI =
STI->getTargetLowering()->isPositionIndependent() || STI->isROPI();
AFI = MF->getInfo<ARMFunctionInfo>();
+ DT = &getAnalysis<MachineDominatorTree>();
isThumb = AFI->isThumbFunction();
isThumb1 = AFI->isThumb1OnlyFunction();
@@ -1809,16 +1819,10 @@ bool ARMConstantIslands::optimizeThumb2I
return MadeChange;
}
+
bool ARMConstantIslands::optimizeThumb2Branches() {
- bool MadeChange = false;
- // The order in which branches appear in ImmBranches is approximately their
- // order within the function body. By visiting later branches first, we reduce
- // the distance between earlier forward branches and their targets, making it
- // more likely that the cbn?z optimization, which can only apply to forward
- // branches, will succeed.
- for (unsigned i = ImmBranches.size(); i != 0; --i) {
- ImmBranch &Br = ImmBranches[i-1];
+ auto TryShrinkBranch = [this](ImmBranch &Br) {
unsigned Opcode = Br.MI->getOpcode();
unsigned NewOpc = 0;
unsigned Scale = 1;
@@ -1846,47 +1850,115 @@ bool ARMConstantIslands::optimizeThumb2B
BBUtils->adjustBBSize(MBB, -2);
BBUtils->adjustBBOffsetsAfter(MBB);
++NumT2BrShrunk;
- MadeChange = true;
+ return true;
}
}
+ return false;
+ };
- Opcode = Br.MI->getOpcode();
- if (Opcode != ARM::tBcc)
- continue;
+ struct ImmCompare {
+ MachineInstr* MI = nullptr;
+ unsigned NewOpc = 0;
+ };
+
+ auto FindCmpForCBZ = [this](ImmBranch &Br, ImmCompare &ImmCmp,
+ MachineBasicBlock *DestBB) {
+ ImmCmp.MI = nullptr;
+ ImmCmp.NewOpc = 0;
// If the conditional branch doesn't kill CPSR, then CPSR can be liveout
// so this transformation is not safe.
if (!Br.MI->killsRegister(ARM::CPSR))
- continue;
+ return false;
- NewOpc = 0;
unsigned PredReg = 0;
+ unsigned NewOpc = 0;
ARMCC::CondCodes Pred = getInstrPredicate(*Br.MI, PredReg);
if (Pred == ARMCC::EQ)
NewOpc = ARM::tCBZ;
else if (Pred == ARMCC::NE)
NewOpc = ARM::tCBNZ;
- if (!NewOpc)
- continue;
- MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
+ else
+ return false;
+
// Check if the distance is within 126. Subtract starting offset by 2
// because the cmp will be eliminated.
unsigned BrOffset = BBUtils->getOffsetOf(Br.MI) + 4 - 2;
BBInfoVector &BBInfo = BBUtils->getBBInfo();
unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset;
if (BrOffset >= DestOffset || (DestOffset - BrOffset) > 126)
- continue;
+ return false;
// Search backwards to find a tCMPi8
auto *TRI = STI->getRegisterInfo();
MachineInstr *CmpMI = findCMPToFoldIntoCBZ(Br.MI, TRI);
if (!CmpMI || CmpMI->getOpcode() != ARM::tCMPi8)
+ return false;
+
+ ImmCmp.MI = CmpMI;
+ ImmCmp.NewOpc = NewOpc;
+ return true;
+ };
+
+ auto TryConvertToLE = [this](ImmBranch &Br, ImmCompare &Cmp) {
+ if (Br.MI->getOpcode() != ARM::t2Bcc || !STI->hasLOB() ||
+ STI->hasMinSize())
+ return false;
+
+ MachineBasicBlock *MBB = Br.MI->getParent();
+ MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
+ if (BBUtils->getOffsetOf(MBB) < BBUtils->getOffsetOf(DestBB) ||
+ !BBUtils->isBBInRange(Br.MI, DestBB, 4094))
+ return false;
+
+ if (!DT->dominates(DestBB, MBB))
+ return false;
+
+ // We queried for the CBN?Z opcode based upon the 'ExitBB', the opposite
+ // target of Br. So now we need to reverse the condition.
+ Cmp.NewOpc = Cmp.NewOpc == ARM::tCBZ ? ARM::tCBNZ : ARM::tCBZ;
+
+ MachineInstrBuilder MIB = BuildMI(*MBB, Br.MI, Br.MI->getDebugLoc(),
+ TII->get(ARM::t2LE));
+ MIB.add(Br.MI->getOperand(0));
+ Br.MI->eraseFromParent();
+ Br.MI = MIB;
+ ++NumLEInserted;
+ return true;
+ };
+
+ bool MadeChange = false;
+
+ // The order in which branches appear in ImmBranches is approximately their
+ // order within the function body. By visiting later branches first, we reduce
+ // the distance between earlier forward branches and their targets, making it
+ // more likely that the cbn?z optimization, which can only apply to forward
+ // branches, will succeed.
+ for (ImmBranch &Br : reverse(ImmBranches)) {
+ MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB();
+ MachineBasicBlock *MBB = Br.MI->getParent();
+ MachineBasicBlock *ExitBB = &MBB->back() == Br.MI ?
+ MBB->getFallThrough() :
+ MBB->back().getOperand(0).getMBB();
+
+ ImmCompare Cmp;
+ if (FindCmpForCBZ(Br, Cmp, ExitBB) && TryConvertToLE(Br, Cmp)) {
+ DestBB = ExitBB;
+ MadeChange = true;
+ } else {
+ FindCmpForCBZ(Br, Cmp, DestBB);
+ MadeChange |= TryShrinkBranch(Br);
+ }
+
+ unsigned Opcode = Br.MI->getOpcode();
+ if ((Opcode != ARM::tBcc && Opcode != ARM::t2LE) || !Cmp.NewOpc)
continue;
- Register Reg = CmpMI->getOperand(0).getReg();
+ Register Reg = Cmp.MI->getOperand(0).getReg();
// Check for Kill flags on Reg. If they are present remove them and set kill
// on the new CBZ.
+ auto *TRI = STI->getRegisterInfo();
MachineBasicBlock::iterator KillMI = Br.MI;
bool RegKilled = false;
do {
@@ -1896,19 +1968,32 @@ bool ARMConstantIslands::optimizeThumb2B
RegKilled = true;
break;
}
- } while (KillMI != CmpMI);
+ } while (KillMI != Cmp.MI);
// Create the new CBZ/CBNZ
- MachineBasicBlock *MBB = Br.MI->getParent();
- LLVM_DEBUG(dbgs() << "Fold: " << *CmpMI << " and: " << *Br.MI);
+ LLVM_DEBUG(dbgs() << "Fold: " << *Cmp.MI << " and: " << *Br.MI);
MachineInstr *NewBR =
- BuildMI(*MBB, Br.MI, Br.MI->getDebugLoc(), TII->get(NewOpc))
+ BuildMI(*MBB, Br.MI, Br.MI->getDebugLoc(), TII->get(Cmp.NewOpc))
.addReg(Reg, getKillRegState(RegKilled))
.addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags());
- CmpMI->eraseFromParent();
- Br.MI->eraseFromParent();
- Br.MI = NewBR;
+
+ Cmp.MI->eraseFromParent();
+ BBInfoVector &BBInfo = BBUtils->getBBInfo();
BBInfo[MBB->getNumber()].Size -= 2;
+
+ if (Br.MI->getOpcode() == ARM::tBcc) {
+ Br.MI->eraseFromParent();
+ Br.MI = NewBR;
+ } else if (&MBB->back() != Br.MI) {
+ // We've generated an LE and already erased the original conditional
+ // branch. The CBN?Z is now used to branch to the other successor, so an
+ // unconditional branch terminator is now redundant.
+ MachineInstr *LastMI = &MBB->back();
+ if (LastMI != Br.MI) {
+ BBInfo[MBB->getNumber()].Size -= LastMI->getDesc().getSize();
+ LastMI->eraseFromParent();
+ }
+ }
BBUtils->adjustBBOffsetsAfter(MBB);
++NumCBZ;
MadeChange = true;
Modified: llvm/trunk/test/CodeGen/ARM/O3-pipeline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/O3-pipeline.ll?rev=372085&r1=372084&r2=372085&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/O3-pipeline.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/O3-pipeline.ll Tue Sep 17 02:08:05 2019
@@ -143,8 +143,8 @@
; CHECK-NEXT: Thumb2 instruction size reduce pass
; CHECK-NEXT: Unpack machine instruction bundles
; CHECK-NEXT: optimise barriers pass
-; CHECK-NEXT: ARM constant island placement and branch shortening pass
; CHECK-NEXT: MachineDominator Tree Construction
+; CHECK-NEXT: ARM constant island placement and branch shortening pass
; CHECK-NEXT: Machine Natural Loop Construction
; CHECK-NEXT: ARM Low Overhead Loops pass
; CHECK-NEXT: Contiguously Lay Out Funclets
Added: llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-cbnz.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-cbnz.mir?rev=372085&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-cbnz.mir (added)
+++ llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-cbnz.mir Tue Sep 17 02:08:05 2019
@@ -0,0 +1,201 @@
+# RUN: llc -mtriple=thumbv8.1m.main %s -run-pass=arm-cp-islands --verify-machineinstrs -o - | FileCheck %s --check-prefix=CHECK-LOB
+# RUN: llc -mtriple=thumbv8.1m.main -mattr=-lob %s -run-pass=arm-cp-islands --verify-machineinstrs -o - | FileCheck %s --check-prefix=CHECK-NOLOB
+
+# CHECK-NOLOB-NOT: t2LE
+
+# CHECK-LOB: bb.3.land.rhs:
+# CHECK-LOB: renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg
+# CHECK-LOB: tCBNZ $r0, %bb.8
+# CHECK-LOB: t2LE %bb.3
+# CHECK-LOB: bb.7.while.body19:
+# CHECK-LOB: tCBZ $r0, %bb.8
+# CHECK-LOB: t2LE %bb.6
+# CHECK-LOB: bb.8:
+
+--- |
+ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ target triple = "thumbv8.1m.main"
+
+ %struct.head_s = type { %struct.head_s*, %struct.data_s* }
+ %struct.data_s = type { i16, i16 }
+
+ ; Function Attrs: norecurse nounwind readonly
+ define dso_local arm_aapcscc %struct.head_s* @search(%struct.head_s* readonly %list, %struct.data_s* nocapture readonly %info) local_unnamed_addr #0 {
+ entry:
+ %idx = getelementptr inbounds %struct.data_s, %struct.data_s* %info, i32 0, i32 1
+ %0 = load i16, i16* %idx, align 2
+ %cmp = icmp sgt i16 %0, -1
+ br i1 %cmp, label %while.cond.preheader, label %while.cond9.preheader
+
+ while.cond9.preheader: ; preds = %entry
+ %1 = icmp eq %struct.head_s* %list, null
+ br i1 %1, label %return, label %land.rhs11.lr.ph
+
+ land.rhs11.lr.ph: ; preds = %while.cond9.preheader
+ %data16143 = bitcast %struct.data_s* %info to i16*
+ %2 = load i16, i16* %data16143, align 2
+ %conv15 = sext i16 %2 to i32
+ br label %land.rhs11
+
+ while.cond.preheader: ; preds = %entry
+ %3 = icmp eq %struct.head_s* %list, null
+ br i1 %3, label %return, label %land.rhs.preheader
+
+ land.rhs.preheader: ; preds = %while.cond.preheader
+ br label %land.rhs
+
+ land.rhs: ; preds = %land.rhs.preheader, %while.body
+ %list.addr.033 = phi %struct.head_s* [ %6, %while.body ], [ %list, %land.rhs.preheader ]
+ %info2 = getelementptr inbounds %struct.head_s, %struct.head_s* %list.addr.033, i32 0, i32 1
+ %4 = load %struct.data_s*, %struct.data_s** %info2, align 4
+ %idx3 = getelementptr inbounds %struct.data_s, %struct.data_s* %4, i32 0, i32 1
+ %5 = load i16, i16* %idx3, align 2
+ %cmp7 = icmp eq i16 %5, %0
+ br i1 %cmp7, label %return, label %while.body
+
+ while.body: ; preds = %land.rhs
+ %next4 = bitcast %struct.head_s* %list.addr.033 to %struct.head_s**
+ %6 = load %struct.head_s*, %struct.head_s** %next4, align 4
+ %tobool = icmp ne %struct.head_s* %6, null
+ br i1 %tobool, label %return, label %land.rhs
+
+ land.rhs11: ; preds = %while.body19, %land.rhs11.lr.ph
+ %list.addr.136 = phi %struct.head_s* [ %list, %land.rhs11.lr.ph ], [ %10, %while.body19 ]
+ %info12 = getelementptr inbounds %struct.head_s, %struct.head_s* %list.addr.136, i32 0, i32 1
+ %7 = load %struct.data_s*, %struct.data_s** %info12, align 4
+ %data165 = bitcast %struct.data_s* %7 to i16*
+ %8 = load i16, i16* %data165, align 2
+ %9 = and i16 %8, 255
+ %and = zext i16 %9 to i32
+ %cmp16 = icmp eq i32 %and, %conv15
+ br i1 %cmp16, label %return, label %while.body19
+
+ while.body19: ; preds = %land.rhs11
+ %next206 = bitcast %struct.head_s* %list.addr.136 to %struct.head_s**
+ %10 = load %struct.head_s*, %struct.head_s** %next206, align 4
+ %tobool10 = icmp eq %struct.head_s* %10, null
+ br i1 %tobool10, label %return, label %land.rhs11
+
+ return: ; preds = %while.body19, %land.rhs11, %while.body, %land.rhs, %while.cond.preheader, %while.cond9.preheader
+ %retval.0 = phi %struct.head_s* [ null, %while.cond.preheader ], [ null, %while.cond9.preheader ], [ %list.addr.033, %land.rhs ], [ null, %while.body ], [ %list.addr.136, %land.rhs11 ], [ null, %while.body19 ]
+ ret %struct.head_s* %retval.0
+ }
+
+ attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv8.1-m.main,+hwdiv,+lob,+ras,+soft-float,+strict-align,+thumb-mode,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-neon,-vfp2,-vfp2d16,-vfp2d16sp,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "unsafe-fp-math"="false" "use-soft-float"="true" }
+
+...
+---
+name: search
+alignment: 1
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+registers: []
+liveins:
+ - { reg: '$r0', virtual-reg: '' }
+ - { reg: '$r1', virtual-reg: '' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 0
+ offsetAdjustment: 0
+ maxAlignment: 1
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ localFrameSize: 0
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack: []
+callSites: []
+constants: []
+machineFunctionInfo: {}
+body: |
+ bb.0.entry:
+ successors: %bb.5(0x50000000), %bb.1(0x30000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = t2LDRSHi12 renamable $r1, 2, 14, $noreg :: (load 2 from %ir.idx)
+ t2CMPri renamable $r2, -1, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.1, 13, killed $cpsr
+
+ bb.5.while.cond.preheader:
+ successors: %bb.8(0x30000000), %bb.6(0x50000000)
+ liveins: $r0, $r2
+
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.8, 0, killed $cpsr
+
+ bb.6.land.rhs.preheader:
+ successors: %bb.7(0x80000000)
+ liveins: $r0, $r2
+
+ renamable $r1 = tUXTH killed renamable $r2, 14, $noreg
+
+ bb.7.land.rhs:
+ successors: %bb.8(0x04000000), %bb.7(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info2)
+ renamable $r2 = tLDRHi killed renamable $r2, 1, 14, $noreg :: (load 2 from %ir.idx3)
+ tCMPr killed renamable $r2, renamable $r1, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 8, implicit-def $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next4)
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.7, 0, killed $cpsr
+ t2B %bb.8, 14, $noreg
+
+ bb.1.while.cond9.preheader:
+ successors: %bb.8(0x30000000), %bb.2(0x50000000)
+ liveins: $r0, $r1
+
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.8, 0, killed $cpsr
+
+ bb.2.land.rhs11.lr.ph:
+ successors: %bb.3(0x80000000)
+ liveins: $r0, $r1
+
+ renamable $r1 = t2LDRSHi12 killed renamable $r1, 0, 14, $noreg :: (load 2 from %ir.data16143)
+
+ bb.3.land.rhs11:
+ successors: %bb.9(0x04000000), %bb.4(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info12)
+ renamable $r2 = tLDRBi killed renamable $r2, 0, 14, $noreg :: (load 1 from %ir.data165, align 2)
+ tCMPr killed renamable $r2, renamable $r1, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.9, 0, killed $cpsr
+
+ bb.4.while.body19:
+ successors: %bb.8(0x04000000), %bb.3(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next206)
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.3, 1, killed $cpsr
+
+ bb.8:
+ successors: %bb.9(0x80000000)
+
+ renamable $r0, dead $cpsr = tMOVi8 0, 14, $noreg
+
+ bb.9.return:
+ liveins: $r0
+
+ tBX_RET 14, $noreg, implicit killed $r0
+
+...
Added: llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-le-simple.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-le-simple.ll?rev=372085&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-le-simple.ll (added)
+++ llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-le-simple.ll Tue Sep 17 02:08:05 2019
@@ -0,0 +1,158 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=thumbv8.1m.main %s -o - | FileCheck %s
+
+define void @cbz_exit(i32* %in, i32* %res) {
+; CHECK-LABEL: cbz_exit:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: subs r2, r0, #4
+; CHECK-NEXT: mov.w r0, #-1
+; CHECK-NEXT: .LBB0_1: @ %loop
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldr r3, [r2, #4]!
+; CHECK-NEXT: adds r0, #1
+; CHECK-NEXT: cbz r3, .LBB0_2
+; CHECK-NEXT: le .LBB0_1
+; CHECK-NEXT: .LBB0_2: @ %exit
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: bx lr
+entry:
+ br label %loop
+
+loop:
+ %offset = phi i32 [ 0, %entry ], [ %next, %loop ]
+ %ptr = getelementptr i32, i32* %in, i32 %offset
+ %val = load i32, i32* %ptr
+ %next = add i32 %offset, 1
+ %cmp = icmp eq i32 %val, 0
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ store i32 %offset, i32* %res
+ ret void
+}
+
+define void @cbnz_exit(i32* %in, i32* %res) {
+; CHECK-LABEL: cbnz_exit:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: subs r2, r0, #4
+; CHECK-NEXT: mov.w r0, #-1
+; CHECK-NEXT: .LBB1_1: @ %loop
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldr r3, [r2, #4]!
+; CHECK-NEXT: adds r0, #1
+; CHECK-NEXT: cbnz r3, .LBB1_2
+; CHECK-NEXT: le .LBB1_1
+; CHECK-NEXT: .LBB1_2: @ %exit
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: bx lr
+entry:
+ br label %loop
+
+loop:
+ %offset = phi i32 [ 0, %entry ], [ %next, %loop ]
+ %ptr = getelementptr i32, i32* %in, i32 %offset
+ %val = load i32, i32* %ptr
+ %next = add i32 %offset, 1
+ %cmp = icmp ne i32 %val, 0
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ store i32 %offset, i32* %res
+ ret void
+}
+
+define void @cbnz_exit_too_large(i32* %in, i32* %res) {
+; CHECK-LABEL: cbnz_exit_too_large:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: subs r2, r0, #4
+; CHECK-NEXT: mov.w r0, #-1
+; CHECK-NEXT: .LBB2_1: @ %loop
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldr r12, [r2, #4]!
+; CHECK-NEXT: .zero 4090
+; CHECK-NEXT: adds r0, #1
+; CHECK-NEXT: cmp.w r12, #0
+; CHECK-NEXT: beq.w .LBB2_1
+; CHECK-NEXT: @ %bb.2: @ %exit
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: bx lr
+entry:
+ br label %loop
+
+loop:
+ %offset = phi i32 [ 0, %entry ], [ %next, %loop ]
+ %ptr = getelementptr i32, i32* %in, i32 %offset
+ %val = load i32, i32* %ptr
+ %next = add i32 %offset, 1
+ %cmp = icmp ne i32 %val, 0
+ %size = call i32 @llvm.arm.space(i32 4090, i32 undef)
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ store i32 %offset, i32* %res
+ ret void
+}
+
+define void @cbz_exit_minsize(i32* %in, i32* %res) #0 {
+; CHECK-LABEL: cbz_exit_minsize:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: movs r2, #0
+; CHECK-NEXT: .LBB3_1: @ %loop
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldr.w r3, [r0, r2, lsl #2]
+; CHECK-NEXT: adds r2, #1
+; CHECK-NEXT: cmp r3, #0
+; CHECK-NEXT: bne .LBB3_1
+; CHECK-NEXT: @ %bb.2: @ %exit
+; CHECK-NEXT: subs r0, r2, #1
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: bx lr
+entry:
+ br label %loop
+
+loop:
+ %offset = phi i32 [ 0, %entry ], [ %next, %loop ]
+ %ptr = getelementptr i32, i32* %in, i32 %offset
+ %val = load i32, i32* %ptr
+ %next = add i32 %offset, 1
+ %cmp = icmp eq i32 %val, 0
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ store i32 %offset, i32* %res
+ ret void
+}
+
+define void @cbnz_exit_minsize(i32* %in, i32* %res) #0 {
+; CHECK-LABEL: cbnz_exit_minsize:
+; CHECK: @ %bb.0: @ %entry
+; CHECK-NEXT: movs r2, #0
+; CHECK-NEXT: .LBB4_1: @ %loop
+; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: ldr.w r3, [r0, r2, lsl #2]
+; CHECK-NEXT: adds r2, #1
+; CHECK-NEXT: cmp r3, #0
+; CHECK-NEXT: beq .LBB4_1
+; CHECK-NEXT: @ %bb.2: @ %exit
+; CHECK-NEXT: subs r0, r2, #1
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: bx lr
+entry:
+ br label %loop
+
+loop:
+ %offset = phi i32 [ 0, %entry ], [ %next, %loop ]
+ %ptr = getelementptr i32, i32* %in, i32 %offset
+ %val = load i32, i32* %ptr
+ %next = add i32 %offset, 1
+ %cmp = icmp ne i32 %val, 0
+ br i1 %cmp, label %exit, label %loop
+
+exit:
+ store i32 %offset, i32* %res
+ ret void
+}
+
+attributes #0 = { minsize optsize }
+
+declare i32 @llvm.arm.space(i32 immarg, i32);
Added: llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-reorder.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-reorder.mir?rev=372085&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-reorder.mir (added)
+++ llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec-reorder.mir Tue Sep 17 02:08:05 2019
@@ -0,0 +1,184 @@
+# RUN: llc -mtriple=thumbv8.1m.main %s -run-pass=arm-cp-islands --verify-machineinstrs -o - | FileCheck %s
+# CHECK-NOT: t2LE
+
+--- |
+ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ target triple = "thumbv8.1m.main-unknown-unknown"
+
+ %struct.head_s = type { %struct.head_s*, %struct.data_s* }
+ %struct.data_s = type { i16, i16 }
+
+ ; Function Attrs: norecurse nounwind readonly
+ define dso_local arm_aapcscc %struct.head_s* @search(%struct.head_s* readonly %list, %struct.data_s* nocapture readonly %info) local_unnamed_addr #0 {
+ entry:
+ %idx = getelementptr inbounds %struct.data_s, %struct.data_s* %info, i32 0, i32 1
+ %tmp = load i16, i16* %idx, align 2
+ %cmp = icmp sgt i16 %tmp, -1
+ br i1 %cmp, label %while.cond.preheader, label %while.cond9.preheader
+
+ while.cond9.preheader: ; preds = %entry
+ %0 = icmp eq %struct.head_s* %list, null
+ br i1 %0, label %return, label %land.rhs11.lr.ph
+
+ land.rhs11.lr.ph: ; preds = %while.cond9.preheader
+ %data16143 = bitcast %struct.data_s* %info to i16*
+ %tmp1 = load i16, i16* %data16143, align 2
+ %conv15 = sext i16 %tmp1 to i32
+ br label %land.rhs11
+
+ while.cond.preheader: ; preds = %entry
+ %1 = icmp eq %struct.head_s* %list, null
+ br i1 %1, label %return, label %land.rhs.preheader
+
+ land.rhs.preheader: ; preds = %while.cond.preheader
+ br label %land.rhs
+
+ while.body: ; preds = %land.rhs
+ %next4 = bitcast %struct.head_s* %list.addr.033 to %struct.head_s**
+ %tmp4 = load %struct.head_s*, %struct.head_s** %next4, align 4
+ %tobool = icmp eq %struct.head_s* %tmp4, null
+ br i1 %tobool, label %return, label %land.rhs
+
+ land.rhs: ; preds = %land.rhs.preheader, %while.body
+ %list.addr.033 = phi %struct.head_s* [ %tmp4, %while.body ], [ %list, %land.rhs.preheader ]
+ %info2 = getelementptr inbounds %struct.head_s, %struct.head_s* %list.addr.033, i32 0, i32 1
+ %tmp2 = load %struct.data_s*, %struct.data_s** %info2, align 4
+ %idx3 = getelementptr inbounds %struct.data_s, %struct.data_s* %tmp2, i32 0, i32 1
+ %tmp3 = load i16, i16* %idx3, align 2
+ %cmp7 = icmp eq i16 %tmp3, %tmp
+ br i1 %cmp7, label %return, label %while.body
+
+ while.body19: ; preds = %land.rhs11
+ %next205 = bitcast %struct.head_s* %list.addr.136 to %struct.head_s**
+ %tmp8 = load %struct.head_s*, %struct.head_s** %next205, align 4
+ %tobool10 = icmp eq %struct.head_s* %tmp8, null
+ br i1 %tobool10, label %return, label %land.rhs11
+
+ land.rhs11: ; preds = %while.body19, %land.rhs11.lr.ph
+ %list.addr.136 = phi %struct.head_s* [ %list, %land.rhs11.lr.ph ], [ %tmp8, %while.body19 ]
+ %info12 = getelementptr inbounds %struct.head_s, %struct.head_s* %list.addr.136, i32 0, i32 1
+ %tmp5 = load %struct.data_s*, %struct.data_s** %info12, align 4
+ %data166 = bitcast %struct.data_s* %tmp5 to i16*
+ %tmp6 = load i16, i16* %data166, align 2
+ %2 = and i16 %tmp6, 255
+ %and = zext i16 %2 to i32
+ %cmp16 = icmp eq i32 %and, %conv15
+ br i1 %cmp16, label %return, label %while.body19
+
+ return: ; preds = %land.rhs11, %while.body19, %land.rhs, %while.body, %while.cond.preheader, %while.cond9.preheader
+ %retval.0 = phi %struct.head_s* [ null, %while.cond.preheader ], [ null, %while.cond9.preheader ], [ %list.addr.033, %land.rhs ], [ null, %while.body ], [ %list.addr.136, %land.rhs11 ], [ null, %while.body19 ]
+ ret %struct.head_s* %retval.0
+ }
+
+ attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv8.1-m.main,+hwdiv,+lob,+ras,+soft-float,+strict-align,+thumb-mode,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-neon,-vfp2,-vfp2d16,-vfp2d16sp,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "unsafe-fp-math"="false" "use-soft-float"="true" }
+
+...
+---
+name: search
+alignment: 1
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+registers: []
+liveins:
+ - { reg: '$r0', virtual-reg: '' }
+ - { reg: '$r1', virtual-reg: '' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 0
+ offsetAdjustment: 0
+ maxAlignment: 1
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ localFrameSize: 0
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack: []
+callSites: []
+constants: []
+machineFunctionInfo: {}
+body: |
+ bb.0.entry:
+ successors: %bb.3(0x50000000), %bb.1(0x30000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = t2LDRSHi12 renamable $r1, 2, 14, $noreg :: (load 2 from %ir.idx)
+ t2CMPri renamable $r2, -1, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.1, 13, killed $cpsr
+
+ bb.3.while.cond.preheader:
+ successors: %bb.4(0x80000000)
+ liveins: $r0, $r2
+
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 4, implicit-def $itstate
+ renamable $r0 = tMOVi8 $noreg, 0, 0, $cpsr, implicit killed $r0, implicit $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ renamable $r1 = tUXTH killed renamable $r2, 14, $noreg
+
+ bb.4.land.rhs:
+ successors: %bb.6(0x04000000), %bb.5(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info2)
+ renamable $r2 = tLDRHi killed renamable $r2, 1, 14, $noreg :: (load 2 from %ir.idx3)
+ tCMPr killed renamable $r2, renamable $r1, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.6, 0, killed $cpsr
+
+ bb.5.while.body:
+ successors: %bb.4(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next4)
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 4, implicit-def $itstate
+ renamable $r0 = tMOVi8 $noreg, 0, 0, $cpsr, implicit killed $r0, implicit $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ t2B %bb.4, 14, $noreg
+
+ bb.6.return:
+ liveins: $r0
+
+ tBX_RET 14, $noreg, implicit $r0
+
+ bb.1.while.cond9.preheader:
+ successors: %bb.2(0x80000000)
+ liveins: $r0, $r1
+
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 4, implicit-def $itstate
+ renamable $r0 = tMOVi8 $noreg, 0, 0, $cpsr, implicit killed $r0, implicit $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ renamable $r1 = t2LDRSHi12 killed renamable $r1, 0, 14, $noreg :: (load 2 from %ir.data16143)
+
+ bb.2.land.rhs11:
+ successors: %bb.2(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info12)
+ renamable $r2 = tLDRBi killed renamable $r2, 0, 14, $noreg :: (load 1 from %ir.data166, align 2)
+ tCMPr killed renamable $r2, renamable $r1, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 8, implicit-def $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next205)
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 4, implicit-def $itstate
+ renamable $r0 = tMOVi8 $noreg, 0, 0, $cpsr, implicit killed $r0, implicit $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ t2B %bb.2, 14, $noreg
+
+...
Added: llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec.mir?rev=372085&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec.mir (added)
+++ llvm/trunk/test/CodeGen/Thumb2/LowOverheadLoops/no-dec.mir Tue Sep 17 02:08:05 2019
@@ -0,0 +1,201 @@
+# RUN: llc -mtriple=thumbv8.1m.main %s -run-pass=arm-cp-islands --verify-machineinstrs -o - | FileCheck %s --check-prefix=CHECK-LOB
+# RUN: llc -mtriple=thumbv8.1m.main -mattr=-lob %s -run-pass=arm-cp-islands --verify-machineinstrs -o - | FileCheck %s --check-prefix=CHECK-NOLOB
+
+# CHECK-NOLOB-NOT: t2LE
+
+# CHECK-LOB: bb.3.land.rhs:
+# CHECK-LOB: tCBZ $r0, %bb.8
+# CHECK-LOB: t2LE %bb.3
+# CHECK-LOB: bb.6.land.rhs11:
+# CHECK-LOB: bb.7.while.body19:
+# CHECK-LOB: tCBZ $r0, %bb.8
+# CHECK-LOB: t2LE %bb.6
+# CHECK-LOB: bb.8:
+
+--- |
+ target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
+ target triple = "thumbv8.1m.main-unknown-unknown"
+
+ %struct.head_s = type { %struct.head_s*, %struct.data_s* }
+ %struct.data_s = type { i16, i16 }
+
+ ; Function Attrs: norecurse nounwind readonly
+ define dso_local arm_aapcscc %struct.head_s* @search(%struct.head_s* readonly %list, %struct.data_s* nocapture readonly %info) local_unnamed_addr #0 {
+ entry:
+ %idx = getelementptr inbounds %struct.data_s, %struct.data_s* %info, i32 0, i32 1
+ %0 = load i16, i16* %idx, align 2
+ %cmp = icmp sgt i16 %0, -1
+ br i1 %cmp, label %while.cond.preheader, label %while.cond9.preheader
+
+ while.cond9.preheader: ; preds = %entry
+ %1 = icmp eq %struct.head_s* %list, null
+ br i1 %1, label %return, label %land.rhs11.lr.ph
+
+ land.rhs11.lr.ph: ; preds = %while.cond9.preheader
+ %data16143 = bitcast %struct.data_s* %info to i16*
+ %2 = load i16, i16* %data16143, align 2
+ %conv15 = sext i16 %2 to i32
+ br label %land.rhs11
+
+ while.cond.preheader: ; preds = %entry
+ %3 = icmp eq %struct.head_s* %list, null
+ br i1 %3, label %return, label %land.rhs.preheader
+
+ land.rhs.preheader: ; preds = %while.cond.preheader
+ br label %land.rhs
+
+ land.rhs: ; preds = %land.rhs.preheader, %while.body
+ %list.addr.033 = phi %struct.head_s* [ %6, %while.body ], [ %list, %land.rhs.preheader ]
+ %info2 = getelementptr inbounds %struct.head_s, %struct.head_s* %list.addr.033, i32 0, i32 1
+ %4 = load %struct.data_s*, %struct.data_s** %info2, align 4
+ %idx3 = getelementptr inbounds %struct.data_s, %struct.data_s* %4, i32 0, i32 1
+ %5 = load i16, i16* %idx3, align 2
+ %cmp7 = icmp eq i16 %5, %0
+ br i1 %cmp7, label %return, label %while.body
+
+ while.body: ; preds = %land.rhs
+ %next4 = bitcast %struct.head_s* %list.addr.033 to %struct.head_s**
+ %6 = load %struct.head_s*, %struct.head_s** %next4, align 4
+ %tobool = icmp eq %struct.head_s* %6, null
+ br i1 %tobool, label %return, label %land.rhs
+
+ land.rhs11: ; preds = %while.body19, %land.rhs11.lr.ph
+ %list.addr.136 = phi %struct.head_s* [ %list, %land.rhs11.lr.ph ], [ %10, %while.body19 ]
+ %info12 = getelementptr inbounds %struct.head_s, %struct.head_s* %list.addr.136, i32 0, i32 1
+ %7 = load %struct.data_s*, %struct.data_s** %info12, align 4
+ %data165 = bitcast %struct.data_s* %7 to i16*
+ %8 = load i16, i16* %data165, align 2
+ %9 = and i16 %8, 255
+ %and = zext i16 %9 to i32
+ %cmp16 = icmp eq i32 %and, %conv15
+ br i1 %cmp16, label %return, label %while.body19
+
+ while.body19: ; preds = %land.rhs11
+ %next206 = bitcast %struct.head_s* %list.addr.136 to %struct.head_s**
+ %10 = load %struct.head_s*, %struct.head_s** %next206, align 4
+ %tobool10 = icmp eq %struct.head_s* %10, null
+ br i1 %tobool10, label %return, label %land.rhs11
+
+ return: ; preds = %while.body19, %land.rhs11, %while.body, %land.rhs, %while.cond.preheader, %while.cond9.preheader
+ %retval.0 = phi %struct.head_s* [ null, %while.cond.preheader ], [ null, %while.cond9.preheader ], [ %list.addr.033, %land.rhs ], [ null, %while.body ], [ %list.addr.136, %land.rhs11 ], [ null, %while.body19 ]
+ ret %struct.head_s* %retval.0
+ }
+
+ attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+armv8.1-m.main,+hwdiv,+lob,+ras,+soft-float,+strict-align,+thumb-mode,-crypto,-d32,-dotprod,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fp64,-fpregs,-fullfp16,-neon,-vfp2,-vfp2d16,-vfp2d16sp,-vfp2sp,-vfp3,-vfp3d16,-vfp3d16sp,-vfp3sp,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp" "unsafe-fp-math"="false" "use-soft-float"="true" }
+
+...
+---
+name: search
+alignment: 1
+exposesReturnsTwice: false
+legalized: false
+regBankSelected: false
+selected: false
+failedISel: false
+tracksRegLiveness: true
+hasWinCFI: false
+registers: []
+liveins:
+ - { reg: '$r0', virtual-reg: '' }
+ - { reg: '$r1', virtual-reg: '' }
+frameInfo:
+ isFrameAddressTaken: false
+ isReturnAddressTaken: false
+ hasStackMap: false
+ hasPatchPoint: false
+ stackSize: 0
+ offsetAdjustment: 0
+ maxAlignment: 1
+ adjustsStack: false
+ hasCalls: false
+ stackProtector: ''
+ maxCallFrameSize: 0
+ cvBytesOfCalleeSavedRegisters: 0
+ hasOpaqueSPAdjustment: false
+ hasVAStart: false
+ hasMustTailInVarArgFunc: false
+ localFrameSize: 0
+ savePoint: ''
+ restorePoint: ''
+fixedStack: []
+stack: []
+callSites: []
+constants: []
+machineFunctionInfo: {}
+body: |
+ bb.0.entry:
+ successors: %bb.5(0x50000000), %bb.1(0x30000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = t2LDRSHi12 renamable $r1, 2, 14, $noreg :: (load 2 from %ir.idx)
+ t2CMPri renamable $r2, -1, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.1, 13, killed $cpsr
+
+ bb.5.while.cond.preheader:
+ successors: %bb.8(0x30000000), %bb.6(0x50000000)
+ liveins: $r0, $r2
+
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.8, 0, killed $cpsr
+
+ bb.6.land.rhs.preheader:
+ successors: %bb.7(0x80000000)
+ liveins: $r0, $r2
+
+ renamable $r1 = tUXTH killed renamable $r2, 14, $noreg
+
+ bb.7.land.rhs:
+ successors: %bb.8(0x04000000), %bb.7(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info2)
+ renamable $r2 = tLDRHi killed renamable $r2, 1, 14, $noreg :: (load 2 from %ir.idx3)
+ tCMPr killed renamable $r2, renamable $r1, 14, $noreg, implicit-def $cpsr
+ t2IT 0, 8, implicit-def $itstate
+ tBX_RET 0, killed $cpsr, implicit $r0, implicit killed $itstate
+ renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next4)
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.7, 1, killed $cpsr
+ t2B %bb.8, 14, $noreg
+
+ bb.1.while.cond9.preheader:
+ successors: %bb.8(0x30000000), %bb.2(0x50000000)
+ liveins: $r0, $r1
+
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.8, 0, killed $cpsr
+
+ bb.2.land.rhs11.lr.ph:
+ successors: %bb.3(0x80000000)
+ liveins: $r0, $r1
+
+ renamable $r1 = t2LDRSHi12 killed renamable $r1, 0, 14, $noreg :: (load 2 from %ir.data16143)
+
+ bb.3.land.rhs11:
+ successors: %bb.9(0x04000000), %bb.4(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r2 = tLDRi renamable $r0, 1, 14, $noreg :: (load 4 from %ir.info12)
+ renamable $r2 = tLDRBi killed renamable $r2, 0, 14, $noreg :: (load 1 from %ir.data165, align 2)
+ tCMPr killed renamable $r2, renamable $r1, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.9, 0, killed $cpsr
+
+ bb.4.while.body19:
+ successors: %bb.8(0x04000000), %bb.3(0x7c000000)
+ liveins: $r0, $r1
+
+ renamable $r0 = tLDRi killed renamable $r0, 0, 14, $noreg :: (load 4 from %ir.next206)
+ tCMPi8 renamable $r0, 0, 14, $noreg, implicit-def $cpsr
+ t2Bcc %bb.3, 1, killed $cpsr
+
+ bb.8:
+ successors: %bb.9(0x80000000)
+
+ renamable $r0, dead $cpsr = tMOVi8 0, 14, $noreg
+
+ bb.9.return:
+ liveins: $r0
+
+ tBX_RET 14, $noreg, implicit killed $r0
+
+...
More information about the llvm-commits
mailing list