diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp index dde4e7ab0e890..edbc3d8c3f614 100644 --- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -2529,31 +2529,64 @@ MachineBasicBlock::iterator AArch64LoadStoreOpt::findMatchingUpdateInsnForward( return E; } - for (unsigned Count = 0; MBBI != E && Count < Limit; - MBBI = next_nodbg(MBBI, E)) { - MachineInstr &MI = *MBBI; - - // Don't count transient instructions towards the search limit since there - // may be different numbers of them if e.g. debug information is present. - if (!MI.isTransient()) - ++Count; - - // If we found a match, return it. - if (isMatchingUpdateInsn(*I, MI, BaseReg, UnscaledOffset)) - return MBBI; + unsigned Count = 0; + MachineBasicBlock *CurMBB = I->getParent(); + // choice of next block to visit is liveins-based + bool VisitSucc = CurMBB->getParent()->getRegInfo().tracksLiveness(); + + while (true) { + for (MachineBasicBlock::iterator CurEnd = CurMBB->end(); + MBBI != CurEnd && Count < Limit; MBBI = next_nodbg(MBBI, CurEnd)) { + MachineInstr &MI = *MBBI; + + // Don't count transient instructions towards the search limit since there + // may be different numbers of them if e.g. debug information is present. + if (!MI.isTransient()) + ++Count; + + // If we found a match, return it. + if (isMatchingUpdateInsn(*I, MI, BaseReg, UnscaledOffset)) + return MBBI; + + // Update the status of what the instruction clobbered and used. + LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, + TRI); + + // Otherwise, if the base register is used or modified, we have no match, + // so return early. If we are optimizing SP, do not allow instructions + // that may load or store in between the load and the optimized value + // update. + if (!ModifiedRegUnits.available(BaseReg) || + !UsedRegUnits.available(BaseReg) || + (BaseRegSP && MBBI->mayLoadOrStore())) + return E; + } - // Update the status of what the instruction clobbered and used. - LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI); + if (!VisitSucc || Limit <= Count) + break; - // Otherwise, if the base register is used or modified, we have no match, so - // return early. - // If we are optimizing SP, do not allow instructions that may load or store - // in between the load and the optimized value update. - if (!ModifiedRegUnits.available(BaseReg) || - !UsedRegUnits.available(BaseReg) || - (BaseRegSP && MBBI->mayLoadOrStore())) - return E; + // Try to go downward to successors along a CF path w/o side enters + // such that BaseReg is alive along it but not at its exits + MachineBasicBlock *SuccToVisit = nullptr; + unsigned LiveSuccCount = 0; + MCRegister RegNoBAse = BaseReg; + for (MachineBasicBlock *Succ : CurMBB->successors()) { + for (MCRegAliasIterator AI(BaseReg, TRI, true); AI.isValid(); ++AI) { + if (Succ->isLiveIn(*AI)) { + if (LiveSuccCount++) + return E; + if (Succ->pred_size() == 1) + SuccToVisit = Succ; + break; + } + } + } + if (!SuccToVisit) + break; + CurMBB = SuccToVisit; + MBBI = CurMBB->begin(); } + return E; } diff --git a/llvm/test/CodeGen/AArch64/ldst_update_cfpath.mir b/llvm/test/CodeGen/AArch64/ldst_update_cfpath.mir new file mode 100644 index 0000000000000..8f541af2eb1a3 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ldst_update_cfpath.mir @@ -0,0 +1,386 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -run-pass=aarch64-ldst-opt -verify-machineinstrs %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64-none-linux-gnu" + + ; Function Attrs: nofree norecurse nosync nounwind memory(argmem: readwrite) uwtable vscale_range(1,16) + define dso_local void @test(ptr noundef captures(none) %data) local_unnamed_addr #0 { + entry: + br i1 undef, label %while.cond.preheader, label %for.body.preheader + + for.body.preheader: ; preds = %entry + br label %for.body + + while.cond.preheader.loopexit: ; preds = %for.body + br label %while.cond.preheader + + while.cond.preheader: ; preds = %while.cond.preheader.loopexit, %entry + br i1 undef, label %while.body.lr.ph.lr.ph, label %for.cond28.preheader + + while.body.lr.ph.lr.ph: ; preds = %while.cond.preheader + br label %while.body.preheader + + for.body: ; preds = %for.body, %for.body.preheader + br i1 undef, label %for.body, label %while.cond.preheader.loopexit + + for.cond28.preheader: ; preds = %if.then, %if.end, %while.cond.preheader + br i1 undef, label %for.end45, label %for.body36.preheader + + for.body36.preheader: ; preds = %for.cond28.preheader + br label %for.body36 + + while.body: ; preds = %if.end, %while.body.preheader + br i1 undef, label %if.end, label %if.then + + if.then: ; preds = %while.body + br i1 undef, label %while.body.preheader, label %for.cond28.preheader + + while.body.preheader: ; preds = %if.then, %while.body.lr.ph.lr.ph + br label %while.body + + if.end: ; preds = %while.body + br i1 undef, label %for.cond28.preheader, label %while.body + + for.body36: ; preds = %for.body36.preheader, %for.body36 + br i1 undef, label %for.body36, label %for.end45 + + for.end45: ; preds = %for.body36, %for.cond28.preheader + ret void + } + +... +--- +name: test +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +noPhis: true +isSSA: false +noVRegs: true +hasFakeUses: false +callsEHReturn: false +callsUnwindInit: false +hasEHContTarget: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: true +registers: [] +liveins: + - { reg: '$x0', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + isCalleeSavedInfoValid: true + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: + hasRedZone: false +body: | + ; CHECK-LABEL: name: test + ; CHECK: bb.0.entry: + ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.5(0x40000000) + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w8 = LDRBBui renamable $x0, 4 + ; CHECK-NEXT: TBNZW killed renamable $w8, 3, %bb.5 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: successors: %bb.2(0x80000000) + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w11 = MOVZWi 1, 0 + ; CHECK-NEXT: renamable $w9 = MOVZWi 1, 0 + ; CHECK-NEXT: renamable $w8 = MOVZWi 2, 0, implicit-def $x8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2.while.cond.preheader: + ; CHECK-NEXT: successors: %bb.3(0x60000000), %bb.8(0x20000000) + ; CHECK-NEXT: liveins: $w9, $w11, $x0, $x8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $wzr = SUBSWri renamable $w11, 299, 0, implicit-def $nzcv + ; CHECK-NEXT: Bcc 8, %bb.8, implicit $nzcv + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.3.while.cond.preheader: + ; CHECK-NEXT: successors: %bb.4(0x55555555), %bb.8(0x2aaaaaab) + ; CHECK-NEXT: liveins: $w9, $x0, $x8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x10 = nuw ADDXrx renamable $x0, renamable $w9, 18 + ; CHECK-NEXT: renamable $w11 = LDRWui renamable $x10, 0 + ; CHECK-NEXT: TBZW killed renamable $w11, 3, %bb.8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.4: + ; CHECK-NEXT: successors: %bb.14(0x80000000) + ; CHECK-NEXT: liveins: $w9, $x0, $x8, $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w9 = ORRWrs $wzr, killed renamable $w9, 0, implicit-def $x9 + ; CHECK-NEXT: B %bb.14 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.5.for.body.preheader: + ; CHECK-NEXT: successors: %bb.6(0x80000000) + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x10 = ADDXri renamable $x0, 8, 0 + ; CHECK-NEXT: renamable $w9 = MOVZWi 1, 0 + ; CHECK-NEXT: renamable $w12 = MOVZWi 2, 0, implicit-def $x12 + ; CHECK-NEXT: $x11 = ORRXrs $xzr, $x10, 0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.6.for.body: + ; CHECK-NEXT: successors: %bb.7(0x7e000000), %bb.2(0x02000000) + ; CHECK-NEXT: liveins: $w9, $x0, $x10, $x11, $x12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w8 = LDURWi renamable $x11, -4 + ; CHECK-NEXT: STRWui killed renamable $w8, renamable $x11, 0 + ; CHECK-NEXT: renamable $x8 = nuw nsw ADDXri renamable $x12, 2, 0 + ; CHECK-NEXT: renamable $w9 = nuw nsw ADDWri killed renamable $w9, 1, 0 + ; CHECK-NEXT: early-clobber renamable $x10, renamable $w13 = LDRBBpost killed renamable $x10, 4 + ; CHECK-NEXT: TBZW killed renamable $w13, 3, %bb.2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.7.for.body: + ; CHECK-NEXT: successors: %bb.6(0x7df7df7e), %bb.2(0x02082082) + ; CHECK-NEXT: liveins: $w9, $x0, $x8, $x10, $x11, $x12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDXri killed renamable $x11, 8, 0 + ; CHECK-NEXT: dead $xzr = SUBSXri killed renamable $x12, 598, 0, implicit-def $nzcv + ; CHECK-NEXT: $x12 = ORRXrs $xzr, $x8, 0 + ; CHECK-NEXT: Bcc 0, %bb.2, implicit $nzcv + ; CHECK-NEXT: B %bb.6 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.8.for.cond28.preheader: + ; CHECK-NEXT: successors: %bb.12(0x40000000), %bb.9(0x40000000) + ; CHECK-NEXT: liveins: $x0, $x8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w9 = LDRBBui renamable $x0, 4 + ; CHECK-NEXT: TBZW killed renamable $w9, 3, %bb.12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.9.for.body36.preheader: + ; CHECK-NEXT: successors: %bb.10(0x80000000) + ; CHECK-NEXT: liveins: $x0, $x8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w9 = MOVZWi 8, 0, implicit-def $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.10.for.body36: + ; CHECK-NEXT: successors: %bb.11(0x7e000000), %bb.12(0x02000000) + ; CHECK-NEXT: liveins: $x0, $x8, $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w10 = SUBWri renamable $w8, 1, 0 + ; CHECK-NEXT: renamable $w10 = LDRWroW renamable $x0, killed renamable $w10, 0, 1 + ; CHECK-NEXT: early-clobber renamable $x8 = STRWpost killed renamable $w10, renamable $x8, 2 + ; CHECK-NEXT: renamable $w10 = LDRBBroX renamable $x0, renamable $x9, 0, 0 + ; CHECK-NEXT: TBZW killed renamable $w10, 3, %bb.12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.11.for.body36: + ; CHECK-NEXT: successors: %bb.10(0x7df7df7e), %bb.12(0x02082082) + ; CHECK-NEXT: liveins: $x0, $x8, $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $xzr = SUBSXri renamable $x9, 1200, 0, implicit-def $nzcv + ; CHECK-NEXT: renamable $x9 = nuw nsw ADDXri killed renamable $x9, 4, 0 + ; CHECK-NEXT: Bcc 1, %bb.10, implicit $nzcv + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.12.for.end45: + ; CHECK-NEXT: RET undef $lr + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.13.if.end: + ; CHECK-NEXT: successors: %bb.8(0x04000000), %bb.14(0x7c000000) + ; CHECK-NEXT: liveins: $x0, $x8, $x9, $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w11 = LDRBBui renamable $x10, 0 + ; CHECK-NEXT: TBZW killed renamable $w11, 3, %bb.8 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.14.while.body: + ; CHECK-NEXT: successors: %bb.13(0x7c000000), %bb.15(0x04000000) + ; CHECK-NEXT: liveins: $x0, $x8, $x9, $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w11 = SUBWri renamable $w8, 1, 0 + ; CHECK-NEXT: renamable $w11 = LDRWroW renamable $x0, killed renamable $w11, 0, 1 + ; CHECK-NEXT: early-clobber renamable $x8 = STRWpost renamable $w11, renamable $x8, 2 + ; CHECK-NEXT: TBZW killed renamable $w11, 2, %bb.13 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.15.if.then: + ; CHECK-NEXT: successors: %bb.16(0x7e000000), %bb.8(0x02000000) + ; CHECK-NEXT: liveins: $x0, $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $w8 = LDRWui renamable $x0, 4 + ; CHECK-NEXT: STRWroX killed renamable $w8, renamable $x0, renamable $x9, 0, 1 + ; CHECK-NEXT: renamable $w8 = MOVZWi 3, 0, implicit-def $x8 + ; CHECK-NEXT: dead $xzr = SUBSXri renamable $x9, 298, 0, implicit-def $nzcv + ; CHECK-NEXT: Bcc 8, %bb.8, implicit $nzcv + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.16.if.then: + ; CHECK-NEXT: successors: %bb.14(0x7df7df7e), %bb.8(0x02082082) + ; CHECK-NEXT: liveins: $x0, $x8, $x9 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x9 = nuw nsw ADDXri killed renamable $x9, 1, 0 + ; CHECK-NEXT: renamable $x10 = nuw ADDXrs renamable $x0, renamable $x9, 2 + ; CHECK-NEXT: renamable $w11 = LDRWui renamable $x10, 0 + ; CHECK-NEXT: TBZW killed renamable $w11, 3, %bb.8 + ; CHECK-NEXT: B %bb.14 + bb.0.entry: + successors: %bb.1(0x40000000), %bb.5(0x40000000) + liveins: $x0 + + renamable $w8 = LDRBBui renamable $x0, 4 + TBNZW killed renamable $w8, 3, %bb.5 + + bb.1: + successors: %bb.2(0x80000000) + liveins: $x0 + + renamable $w11 = MOVZWi 1, 0 + renamable $w9 = MOVZWi 1, 0 + renamable $w8 = MOVZWi 2, 0, implicit-def $x8 + + bb.2.while.cond.preheader: + successors: %bb.3(0x60000000), %bb.8(0x20000000) + liveins: $w9, $w11, $x0, $x8 + + dead $wzr = SUBSWri renamable $w11, 299, 0, implicit-def $nzcv + Bcc 8, %bb.8, implicit $nzcv + + bb.3.while.cond.preheader: + successors: %bb.4(0x55555555), %bb.8(0x2aaaaaab) + liveins: $w9, $x0, $x8 + + renamable $x10 = nuw ADDXrx renamable $x0, renamable $w9, 18 + renamable $w11 = LDRWui renamable $x10, 0 + TBZW killed renamable $w11, 3, %bb.8 + + bb.4: + successors: %bb.14(0x80000000) + liveins: $w9, $x0, $x8, $x10 + + renamable $w9 = ORRWrs $wzr, killed renamable $w9, 0, implicit-def $x9 + B %bb.14 + + bb.5.for.body.preheader: + successors: %bb.6(0x80000000) + liveins: $x0 + + renamable $x10 = ADDXri renamable $x0, 8, 0 + renamable $w9 = MOVZWi 1, 0 + renamable $w12 = MOVZWi 2, 0, implicit-def $x12 + $x11 = ORRXrs $xzr, $x10, 0 + + bb.6.for.body: + successors: %bb.7(0x7e000000), %bb.2(0x02000000) + liveins: $w9, $x0, $x10, $x11, $x12 + + renamable $w8 = LDURWi renamable $x11, -4 + STRWui killed renamable $w8, renamable $x11, 0 + renamable $x8 = nuw nsw ADDXri renamable $x12, 2, 0 + renamable $w9 = nuw nsw ADDWri killed renamable $w9, 1, 0 + early-clobber renamable $x10, renamable $w13 = LDRBBpost killed renamable $x10, 4 + TBZW killed renamable $w13, 3, %bb.2 + + bb.7.for.body: + successors: %bb.6(0x7df7df7e), %bb.2(0x02082082) + liveins: $w9, $x0, $x8, $x10, $x11, $x12 + + renamable $x11 = ADDXri killed renamable $x11, 8, 0 + dead $xzr = SUBSXri killed renamable $x12, 598, 0, implicit-def $nzcv + $x12 = ORRXrs $xzr, $x8, 0 + Bcc 0, %bb.2, implicit $nzcv + B %bb.6 + + bb.8.for.cond28.preheader: + successors: %bb.12(0x40000000), %bb.9(0x40000000) + liveins: $x0, $x8 + + renamable $w9 = LDRBBui renamable $x0, 4 + TBZW killed renamable $w9, 3, %bb.12 + + bb.9.for.body36.preheader: + successors: %bb.10(0x80000000) + liveins: $x0, $x8 + + renamable $w9 = MOVZWi 8, 0, implicit-def $x9 + + bb.10.for.body36: + successors: %bb.11(0x7e000000), %bb.12(0x02000000) + liveins: $x0, $x8, $x9 + + renamable $w10 = SUBWri renamable $w8, 1, 0 + renamable $w10 = LDRWroW renamable $x0, killed renamable $w10, 0, 1 + STRWui killed renamable $w10, renamable $x8, 0 + renamable $w10 = LDRBBroX renamable $x0, renamable $x9, 0, 0 + TBZW killed renamable $w10, 3, %bb.12 + + bb.11.for.body36: + successors: %bb.10(0x7df7df7e), %bb.12(0x02082082) + liveins: $x0, $x8, $x9 + + renamable $x8 = ADDXri renamable $x8, 2, 0, implicit killed $x8, implicit-def $x8 + dead $xzr = SUBSXri renamable $x9, 1200, 0, implicit-def $nzcv + renamable $x9 = nuw nsw ADDXri killed renamable $x9, 4, 0 + Bcc 1, %bb.10, implicit $nzcv + + bb.12.for.end45: + RET undef $lr + + bb.13.if.end: + successors: %bb.8(0x04000000), %bb.14(0x7c000000) + liveins: $x0, $x8, $x9, $x10 + + renamable $x8 = ADDXri renamable $x8, 2, 0, implicit killed $x8, implicit-def $x8 + renamable $w11 = LDRBBui renamable $x10, 0 + TBZW killed renamable $w11, 3, %bb.8 + + bb.14.while.body: + successors: %bb.13(0x7c000000), %bb.15(0x04000000) + liveins: $x0, $x8, $x9, $x10 + + renamable $w11 = SUBWri renamable $w8, 1, 0 + renamable $w11 = LDRWroW renamable $x0, killed renamable $w11, 0, 1 + STRWui renamable $w11, renamable $x8, 0 + TBZW killed renamable $w11, 2, %bb.13 + + bb.15.if.then: + successors: %bb.16(0x7e000000), %bb.8(0x02000000) + liveins: $x0, $x9 + + renamable $w8 = LDRWui renamable $x0, 4 + STRWroX killed renamable $w8, renamable $x0, renamable $x9, 0, 1 + renamable $w8 = MOVZWi 3, 0, implicit-def $x8 + dead $xzr = SUBSXri renamable $x9, 298, 0, implicit-def $nzcv + Bcc 8, %bb.8, implicit $nzcv + + bb.16.if.then: + successors: %bb.14(0x7df7df7e), %bb.8(0x02082082) + liveins: $x0, $x8, $x9 + + renamable $x9 = nuw nsw ADDXri killed renamable $x9, 1, 0 + renamable $x10 = nuw ADDXrs renamable $x0, renamable $x9, 2 + renamable $w11 = LDRWui renamable $x10, 0 + TBZW killed renamable $w11, 3, %bb.8 + B %bb.14 +... diff --git a/llvm/test/Transforms/LoopStrengthReduce/AArch64/pr53625.ll b/llvm/test/Transforms/LoopStrengthReduce/AArch64/pr53625.ll index 3c1094f2ee31d..ff2527d5bb6ad 100644 --- a/llvm/test/Transforms/LoopStrengthReduce/AArch64/pr53625.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/AArch64/pr53625.ll @@ -131,12 +131,11 @@ define i32 @negative_test_type_is_struct(i32 %c, ptr %a, ptr %b) { ; CHECK-NEXT: mov w8, w0 ; CHECK-NEXT: .LBB2_2: // %for.body ; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 -; CHECK-NEXT: ldr w9, [x1] +; CHECK-NEXT: ldr w9, [x1], #4 ; CHECK-NEXT: cbnz w9, .LBB2_5 ; CHECK-NEXT: // %bb.3: // %for.cond ; CHECK-NEXT: // in Loop: Header=BB2_2 Depth=1 ; CHECK-NEXT: subs x8, x8, #1 -; CHECK-NEXT: add x1, x1, #4 ; CHECK-NEXT: b.ne .LBB2_2 ; CHECK-NEXT: .LBB2_4: ; CHECK-NEXT: mov w0, wzr