[FIX] Forces shrink wrapping to consider any memory access as aliasing with the stack

Summary:
Relate bug: https://bugs.llvm.org/show_bug.cgi?id=37472

The shrink wrapping pass prematurally restores the stack, at a point where the stack might still be accessed.
Taking an exception can cause the stack to be corrupted.

As a first approach, this patch is overly conservative, assuming that any instruction that may load or store could access
the stack.

Reviewers: dmgreen, qcolombet

Reviewed By: qcolombet

Subscribers: simpal01, efriedma, eli.friedman, javed.absar, llvm-commits, eugenis, chill, carwil, thegameg

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63152

llvm-svn: 363265
This commit is contained in:
Diogo N. Sampaio 2019-06-13 13:56:19 +00:00
parent 86b510aa58
commit 0be2d25ecc
22 changed files with 4998 additions and 1492 deletions

View File

@ -258,6 +258,15 @@ INITIALIZE_PASS_END(ShrinkWrap, DEBUG_TYPE, "Shrink Wrap Pass", false, false)
bool ShrinkWrap::useOrDefCSROrFI(const MachineInstr &MI,
RegScavenger *RS) const {
// This prevents premature stack popping when occurs a indirect stack
// access. It is overly aggressive for the moment.
// TODO: - Obvious non-stack loads and store, such as global values,
// are known to not access the stack.
// - Further, data dependency and alias analysis can validate
// that load and stores never derive from the stack pointer.
if (MI.mayLoadOrStore())
return true;
if (MI.getOpcode() == FrameSetupOpcode ||
MI.getOpcode() == FrameDestroyOpcode) {
LLVM_DEBUG(dbgs() << "Frame instruction: " << MI << '\n');

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64-apple-darwin -aarch64-cbz-offset-bits=3 < %s | FileCheck %s
; CHECK-LABEL: _split_block_no_fallthrough:
; CHECK: cmn x{{[0-9]+}}, #5
; CHECK-NEXT: b.le [[B2:LBB[0-9]+_[0-9]+]]
; CHECK-NEXT: ; %bb.1: ; %b3
; CHECK: ldr [[LOAD:w[0-9]+]]
; CHECK: cbnz [[LOAD]], [[B8:LBB[0-9]+_[0-9]+]]
; CHECK-NEXT: b [[B7:LBB[0-9]+_[0-9]+]]
; CHECK-NEXT: [[B8]]: ; %b8
; CHECK-NEXT: ret
; CHECK-NEXT: [[B2]]: ; %b2
; CHECK: mov w{{[0-9]+}}, #93
; CHECK: bl _extfunc
; CHECK: cbz w{{[0-9]+}}, [[B7]]
; CHECK-NEXT: b [[B8]]
; CHECK-NEXT: [[B7]]: ; %b7
; CHECK: mov w{{[0-9]+}}, #13
; CHECK: b _extfunc
define void @split_block_no_fallthrough(i64 %val) #0 {
; CHECK-LABEL: split_block_no_fallthrough:
; CHECK: ; %bb.0: ; %bb
; CHECK-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
; CHECK-NEXT: cmn x0, #5 ; =5
; CHECK-NEXT: b.le LBB0_3
; CHECK-NEXT: ; %bb.1: ; %b3
; CHECK-NEXT: ldr w8, [x8]
; CHECK-NEXT: cbnz w8, LBB0_2
; CHECK-NEXT: b LBB0_4
; CHECK-NEXT: LBB0_2: ; %b8
; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; CHECK-NEXT: ret
; CHECK-NEXT: LBB0_3: ; %b2
; CHECK-NEXT: mov w0, #93
; CHECK-NEXT: bl _extfunc
; CHECK-NEXT: cbnz w0, LBB0_2
; CHECK-NEXT: LBB0_4: ; %b7
; CHECK-NEXT: mov w0, #13
; CHECK-NEXT: ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; CHECK-NEXT: b _extfunc
bb:
%c0 = icmp sgt i64 %val, -5
br i1 %c0, label %b3, label %b2

View File

@ -0,0 +1,229 @@
--- |
; pr37472
; These test verify that shrink-wrap does not set the restore point
; to a position where the stack might still be accessed by a load or store
; RUN: llc -x=mir -simplify-mir -run-pass=shrink-wrap -o - %s | FileCheck %s
; CHECK: name: compiler_pop_stack
; CHECK: frameInfo:
; CHECK-NOT: savePoint:
; CHECK-NOT: restorePoint:
; CHECK: stack:
; CHECK: name: f
; CHECK: frameInfo:
; CHECK: savePoint: '%bb.2'
; CHECK-NEXT: restorePoint: '%bb.4'
; CHECK-NEXT: stack:
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-arm-none-eabi"
%struct.S = type { i32, i32 }
@__const.f.arr = private unnamed_addr constant [4 x i8] c"\01\02\03\04", align 1
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1 immarg)
; Test from: https://bugs.llvm.org/show_bug.cgi?id=42136
define void @compiler_pop_stack(i32 %num) {
entry:
%rstack = alloca [16 x i32], align 4
%tmp = bitcast [16 x i32]* %rstack to i8*
call void @llvm.lifetime.start.p0i8(i64 64, i8* nonnull %tmp)
%cmp = icmp ult i32 %num, 2
br i1 %cmp, label %cleanup, label %if.end
if.end:
%arrayidx1 = bitcast [16 x i32]* %rstack to i32*
store volatile i32 %num, i32* %arrayidx1, align 4
br label %while.body
while.body:
%ptr.017 = phi i32 [ 1, %if.end ], [ %ptr.1, %if.end7 ]
%dec = add i32 %ptr.017, -1
%idxprom = zext i32 %dec to i64
%arrayidx2 = getelementptr inbounds [16 x i32], [16 x i32]* %rstack, i64 0, i64 %idxprom
%tmp1 = load volatile i32, i32* %arrayidx2, align 4
%cmp3 = icmp eq i32 %tmp1, 0
br i1 %cmp3, label %if.end7, label %if.then4
if.then4:
%sunkaddr = mul i64 %idxprom, 4
%0 = bitcast [16 x i32]* %rstack to i8*
%sunkaddr2 = getelementptr inbounds i8, i8* %0, i64 %sunkaddr
%1 = bitcast i8* %sunkaddr2 to i32*
store volatile i32 %tmp1, i32* %1, align 4
br label %if.end7
if.end7:
%ptr.1 = phi i32 [ %ptr.017, %if.then4 ], [ %dec, %while.body ]
%cmp1 = icmp eq i32 %ptr.1, 0
br i1 %cmp1, label %cleanup, label %while.body
cleanup:
%2 = bitcast [16 x i32]* %rstack to i8*
call void @llvm.lifetime.end.p0i8(i64 64, i8* nonnull %2)
ret void
}
; Test from: https://bugs.llvm.org/show_bug.cgi?id=37472
define i32 @f(%struct.S* nocapture %arg, i32 %arg1) {
bb:
%tmp = alloca [4 x i8], align 1
%tmp2 = icmp ugt i32 %arg1, 4
br i1 %tmp2, label %bb16, label %bb3
bb3:
%tmp41 = bitcast [4 x i8]* %tmp to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp41)
call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 %tmp41, i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @__const.f.arr, i64 0, i64 0), i64 4, i1 true)
%tmp5 = zext i32 %arg1 to i64
%tmp6 = getelementptr inbounds [4 x i8], [4 x i8]* %tmp, i64 0, i64 %tmp5
%tmp7 = load volatile i8, i8* %tmp6, align 1
%tmp8 = zext i8 %tmp7 to i32
%tmp92 = bitcast %struct.S* %arg to i32*
store i32 %tmp8, i32* %tmp92, align 4
%tmp10 = icmp ult i32 %arg1, 3
br i1 %tmp10, label %bb11, label %bb15
bb11:
%0 = bitcast [4 x i8]* %tmp to i8*
%sunkaddr = getelementptr inbounds i8, i8* %0, i64 %tmp5
%tmp12 = load volatile i8, i8* %sunkaddr, align 1
%tmp13 = zext i8 %tmp12 to i32
%tmp14 = getelementptr inbounds %struct.S, %struct.S* %arg, i64 0, i32 1
store i32 %tmp13, i32* %tmp14, align 4
br label %bb15
bb15:
%1 = bitcast [4 x i8]* %tmp to i8*
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1)
br label %bb16
bb16:
%tmp17 = phi i32 [ 0, %bb15 ], [ 1, %bb ]
ret i32 %tmp17
}
declare void @llvm.stackprotector(i8*, i8**)
...
---
name: compiler_pop_stack
alignment: 2
tracksRegLiveness: true
liveins:
- { reg: '$w0' }
frameInfo:
maxAlignment: 4
maxCallFrameSize: 0
localFrameSize: 64
stack:
- { id: 0, name: rstack, size: 64, alignment: 4, stack-id: 0, local-offset: -64 }
machineFunctionInfo: {}
body: |
bb.0.entry:
liveins: $w0
dead $wzr = SUBSWri renamable $w0, 2, 0, implicit-def $nzcv
Bcc 3, %bb.6, implicit killed $nzcv
B %bb.1
bb.1.if.end:
liveins: $w0
STRWui killed renamable $w0, %stack.0.rstack, 0 :: (volatile store 4 into %ir.arrayidx1)
renamable $w9 = MOVi32imm 1
renamable $x8 = ADDXri %stack.0.rstack, 0, 0
bb.2.while.body:
successors: %bb.3(0x30000000), %bb.4(0x50000000)
liveins: $w9, $x8
renamable $w10 = SUBWri renamable $w9, 1, 0, implicit-def $x10
renamable $w11 = LDRWroW renamable $x8, renamable $w10, 0, 1 :: (volatile load 4 from %ir.arrayidx2)
CBNZW renamable $w11, %bb.4
bb.3:
liveins: $x8, $x10
renamable $w9 = COPY renamable $w10, implicit killed $x10
B %bb.5
bb.4.if.then4:
liveins: $w9, $w11, $x8, $x10
STRWroX killed renamable $w11, renamable $x8, killed renamable $x10, 0, 1 :: (volatile store 4 into %ir.1)
bb.5.if.end7:
successors: %bb.6(0x04000000), %bb.2(0x7c000000)
liveins: $w9, $x8
CBNZW renamable $w9, %bb.2
B %bb.6
bb.6.cleanup:
RET_ReallyLR
...
---
name: f
alignment: 2
tracksRegLiveness: true
liveins:
- { reg: '$x0' }
- { reg: '$w1' }
frameInfo:
maxAlignment: 4
maxCallFrameSize: 0
localFrameSize: 4
stack:
- { id: 0, name: tmp, size: 4, alignment: 4, stack-id: 0, local-offset: -4 }
machineFunctionInfo: {}
body: |
bb.0.bb:
successors: %bb.1, %bb.2
liveins: $w1, $x0
dead $wzr = SUBSWri renamable $w1, 4, 0, implicit-def $nzcv
Bcc 9, %bb.2, implicit killed $nzcv
bb.1:
renamable $w0 = MOVi32imm 1
B %bb.5
bb.2.bb3:
successors: %bb.3, %bb.4
liveins: $w1, $x0
renamable $w9 = MOVi32imm 67305985
renamable $w8 = ORRWrs $wzr, renamable $w1, 0, implicit-def $x8
STRWui killed renamable $w9, %stack.0.tmp, 0 :: (volatile store 4 into %ir.tmp41)
renamable $x9 = ADDXri %stack.0.tmp, 0, 0
renamable $w10 = LDRBBroX renamable $x9, renamable $x8, 0, 0 :: (volatile load 1 from %ir.tmp6)
dead $wzr = SUBSWri killed renamable $w1, 2, 0, implicit-def $nzcv
STRWui killed renamable $w10, renamable $x0, 0 :: (store 4 into %ir.tmp92)
Bcc 8, %bb.4, implicit killed $nzcv
B %bb.3
bb.3.bb11:
liveins: $x0, $x8, $x9
renamable $w8 = LDRBBroX killed renamable $x9, killed renamable $x8, 0, 0 :: (volatile load 1 from %ir.sunkaddr)
STRWui killed renamable $w8, killed renamable $x0, 1 :: (store 4 into %ir.tmp14)
bb.4.bb15:
renamable $w0 = COPY $wzr
bb.5.bb16:
liveins: $w0
RET_ReallyLR implicit $w0
...

View File

@ -32,7 +32,7 @@ if.then: ; preds = %entry
store i32 0, i32* @f, align 4, !tbaa !2
br label %if.end
; DARWIN-NOT: Merging into block
; DARWIN: Merging into block
; LINUX: Merging into block
if.end: ; preds = %entry.if.end_crit_edge, %if.then

View File

@ -1,5 +1,6 @@
; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=ENABLE
; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=DISABLE
; We cannot merge this test with the main test for shrink-wrapping, because
; the code path we want to exerce is not taken with ios lowering.
target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64"
@ -12,53 +13,185 @@ target triple = "armv7--linux-gnueabi"
; The exit block of the loop happens to also lead to defs/uses of CSRs.
; It also post-dominates the loop body and we use to generate invalid
; restore sequence. I.e., we restored too early.
;
; CHECK-LABEL: wrongUseOfPostDominate:
;
; The prologue is the first thing happening in the function
; without shrink-wrapping.
; DISABLE: push
;
; CHECK: cmn r1, #1
;
; With shrink-wrapping, we branch to a pre-header, where the prologue
; is located.
; ENABLE-NEXT: ble [[LOOP_PREHEADER:[.a-zA-Z0-9_]+]]
; Without shrink-wrapping, we go straight into the loop.
; DISABLE-NEXT: ble [[LOOP_HEADER:[.a-zA-Z0-9_]+]]
;
; CHECK: @ %if.end29
; DISABLE-NEXT: pop
; ENABLE-NEXT: bx lr
;
; ENABLE: [[LOOP_PREHEADER]]
; ENABLE: push
; We must not find a pop here, otherwise that means we are in the loop
; and are restoring before using the saved CSRs.
; ENABLE-NOT: pop
; ENALBE-NEXT: [[LOOP_HEADER:[.a-zA-Z0-9_]+]]: @ %while.cond2.outer
;
; DISABLE: [[LOOP_HEADER]]: @ %while.cond2.outer
;
; ENABLE-NOT: pop
;
; CHECK: @ %while.cond2
; CHECK: add
; CHECK-NEXT: cmp r{{[0-1]+}}, #1
; Jump to the return block
; CHECK-NEXT: beq [[RETURN_BLOCK:[.a-zA-Z0-9_]+]]
;
; Use the back edge to check we get the label of the loop right.
; This is to make sure we check the right loop pattern.
; CHECK: @ %while.body24.land.rhs14_crit_edge
; CHECK: cmp r{{[0-9]+}}, #192
; CHECK-NEXT bhs [[LOOP_HEADER]]
;
; CHECK: [[RETURN_BLOCK]]:
; Set the return value.
; CHECK-NEXT: mov r0,
; CHECK-NEXT: pop
define fastcc i8* @wrongUseOfPostDominate(i8* readonly %s, i32 %off, i8* readnone %lim) {
; ENABLE-LABEL: wrongUseOfPostDominate:
; ENABLE: @ %bb.0: @ %entry
; ENABLE-NEXT: .save {r11, lr}
; ENABLE-NEXT: push {r11, lr}
; ENABLE-NEXT: cmn r1, #1
; ENABLE-NEXT: ble .LBB0_6
; ENABLE-NEXT: @ %bb.1: @ %while.cond.preheader
; ENABLE-NEXT: cmp r1, #0
; ENABLE-NEXT: beq .LBB0_5
; ENABLE-NEXT: @ %bb.2: @ %while.cond.preheader
; ENABLE-NEXT: cmp r0, r2
; ENABLE-NEXT: pophs {r11, pc}
; ENABLE-NEXT: movw r12, :lower16:skip
; ENABLE-NEXT: sub r1, r1, #1
; ENABLE-NEXT: movt r12, :upper16:skip
; ENABLE-NEXT: .LBB0_3: @ %while.body
; ENABLE-NEXT: @ =>This Inner Loop Header: Depth=1
; ENABLE-NEXT: ldrb r3, [r0]
; ENABLE-NEXT: ldrb r3, [r12, r3]
; ENABLE-NEXT: add r0, r0, r3
; ENABLE-NEXT: sub r3, r1, #1
; ENABLE-NEXT: cmp r3, r1
; ENABLE-NEXT: bhs .LBB0_5
; ENABLE-NEXT: @ %bb.4: @ %while.body
; ENABLE-NEXT: @ in Loop: Header=BB0_3 Depth=1
; ENABLE-NEXT: cmp r0, r2
; ENABLE-NEXT: mov r1, r3
; ENABLE-NEXT: blo .LBB0_3
; ENABLE-NEXT: .LBB0_5: @ %if.end29
; ENABLE-NEXT: pop {r11, pc}
; ENABLE-NEXT: .LBB0_6: @ %while.cond2.outer
; ENABLE-NEXT: @ =>This Loop Header: Depth=1
; ENABLE-NEXT: @ Child Loop BB0_7 Depth 2
; ENABLE-NEXT: @ Child Loop BB0_14 Depth 2
; ENABLE-NEXT: mov r3, r0
; ENABLE-NEXT: .LBB0_7: @ %while.cond2
; ENABLE-NEXT: @ Parent Loop BB0_6 Depth=1
; ENABLE-NEXT: @ => This Inner Loop Header: Depth=2
; ENABLE-NEXT: add r1, r1, #1
; ENABLE-NEXT: cmp r1, #1
; ENABLE-NEXT: beq .LBB0_17
; ENABLE-NEXT: @ %bb.8: @ %while.body4
; ENABLE-NEXT: @ in Loop: Header=BB0_7 Depth=2
; ENABLE-NEXT: cmp r3, r2
; ENABLE-NEXT: bls .LBB0_7
; ENABLE-NEXT: @ %bb.9: @ %if.then7
; ENABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; ENABLE-NEXT: mov r0, r3
; ENABLE-NEXT: ldrb r12, [r0, #-1]!
; ENABLE-NEXT: sxtb lr, r12
; ENABLE-NEXT: cmn lr, #1
; ENABLE-NEXT: bgt .LBB0_6
; ENABLE-NEXT: @ %bb.10: @ %if.then7
; ENABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; ENABLE-NEXT: cmp r0, r2
; ENABLE-NEXT: bls .LBB0_6
; ENABLE-NEXT: @ %bb.11: @ %land.rhs14.preheader
; ENABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; ENABLE-NEXT: cmn lr, #1
; ENABLE-NEXT: bgt .LBB0_6
; ENABLE-NEXT: @ %bb.12: @ %land.rhs14.preheader
; ENABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; ENABLE-NEXT: cmp r12, #191
; ENABLE-NEXT: bhi .LBB0_6
; ENABLE-NEXT: @ %bb.13: @ %while.body24.preheader
; ENABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; ENABLE-NEXT: sub r3, r3, #2
; ENABLE-NEXT: .LBB0_14: @ %while.body24
; ENABLE-NEXT: @ Parent Loop BB0_6 Depth=1
; ENABLE-NEXT: @ => This Inner Loop Header: Depth=2
; ENABLE-NEXT: mov r0, r3
; ENABLE-NEXT: cmp r3, r2
; ENABLE-NEXT: bls .LBB0_6
; ENABLE-NEXT: @ %bb.15: @ %while.body24.land.rhs14_crit_edge
; ENABLE-NEXT: @ in Loop: Header=BB0_14 Depth=2
; ENABLE-NEXT: mov r3, r0
; ENABLE-NEXT: ldrsb lr, [r3], #-1
; ENABLE-NEXT: cmn lr, #1
; ENABLE-NEXT: uxtb r12, lr
; ENABLE-NEXT: bgt .LBB0_6
; ENABLE-NEXT: @ %bb.16: @ %while.body24.land.rhs14_crit_edge
; ENABLE-NEXT: @ in Loop: Header=BB0_14 Depth=2
; ENABLE-NEXT: cmp r12, #192
; ENABLE-NEXT: blo .LBB0_14
; ENABLE-NEXT: b .LBB0_6
; ENABLE-NEXT: .LBB0_17:
; ENABLE-NEXT: mov r0, r3
; ENABLE-NEXT: pop {r11, pc}
;
; DISABLE-LABEL: wrongUseOfPostDominate:
; DISABLE: @ %bb.0: @ %entry
; DISABLE-NEXT: .save {r11, lr}
; DISABLE-NEXT: push {r11, lr}
; DISABLE-NEXT: cmn r1, #1
; DISABLE-NEXT: ble .LBB0_6
; DISABLE-NEXT: @ %bb.1: @ %while.cond.preheader
; DISABLE-NEXT: cmp r1, #0
; DISABLE-NEXT: beq .LBB0_5
; DISABLE-NEXT: @ %bb.2: @ %while.cond.preheader
; DISABLE-NEXT: cmp r0, r2
; DISABLE-NEXT: pophs {r11, pc}
; DISABLE-NEXT: movw r12, :lower16:skip
; DISABLE-NEXT: sub r1, r1, #1
; DISABLE-NEXT: movt r12, :upper16:skip
; DISABLE-NEXT: .LBB0_3: @ %while.body
; DISABLE-NEXT: @ =>This Inner Loop Header: Depth=1
; DISABLE-NEXT: ldrb r3, [r0]
; DISABLE-NEXT: ldrb r3, [r12, r3]
; DISABLE-NEXT: add r0, r0, r3
; DISABLE-NEXT: sub r3, r1, #1
; DISABLE-NEXT: cmp r3, r1
; DISABLE-NEXT: bhs .LBB0_5
; DISABLE-NEXT: @ %bb.4: @ %while.body
; DISABLE-NEXT: @ in Loop: Header=BB0_3 Depth=1
; DISABLE-NEXT: cmp r0, r2
; DISABLE-NEXT: mov r1, r3
; DISABLE-NEXT: blo .LBB0_3
; DISABLE-NEXT: .LBB0_5: @ %if.end29
; DISABLE-NEXT: pop {r11, pc}
; DISABLE-NEXT: .LBB0_6: @ %while.cond2.outer
; DISABLE-NEXT: @ =>This Loop Header: Depth=1
; DISABLE-NEXT: @ Child Loop BB0_7 Depth 2
; DISABLE-NEXT: @ Child Loop BB0_14 Depth 2
; DISABLE-NEXT: mov r3, r0
; DISABLE-NEXT: .LBB0_7: @ %while.cond2
; DISABLE-NEXT: @ Parent Loop BB0_6 Depth=1
; DISABLE-NEXT: @ => This Inner Loop Header: Depth=2
; DISABLE-NEXT: add r1, r1, #1
; DISABLE-NEXT: cmp r1, #1
; DISABLE-NEXT: beq .LBB0_17
; DISABLE-NEXT: @ %bb.8: @ %while.body4
; DISABLE-NEXT: @ in Loop: Header=BB0_7 Depth=2
; DISABLE-NEXT: cmp r3, r2
; DISABLE-NEXT: bls .LBB0_7
; DISABLE-NEXT: @ %bb.9: @ %if.then7
; DISABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; DISABLE-NEXT: mov r0, r3
; DISABLE-NEXT: ldrb r12, [r0, #-1]!
; DISABLE-NEXT: sxtb lr, r12
; DISABLE-NEXT: cmn lr, #1
; DISABLE-NEXT: bgt .LBB0_6
; DISABLE-NEXT: @ %bb.10: @ %if.then7
; DISABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; DISABLE-NEXT: cmp r0, r2
; DISABLE-NEXT: bls .LBB0_6
; DISABLE-NEXT: @ %bb.11: @ %land.rhs14.preheader
; DISABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; DISABLE-NEXT: cmn lr, #1
; DISABLE-NEXT: bgt .LBB0_6
; DISABLE-NEXT: @ %bb.12: @ %land.rhs14.preheader
; DISABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; DISABLE-NEXT: cmp r12, #191
; DISABLE-NEXT: bhi .LBB0_6
; DISABLE-NEXT: @ %bb.13: @ %while.body24.preheader
; DISABLE-NEXT: @ in Loop: Header=BB0_6 Depth=1
; DISABLE-NEXT: sub r3, r3, #2
; DISABLE-NEXT: .LBB0_14: @ %while.body24
; DISABLE-NEXT: @ Parent Loop BB0_6 Depth=1
; DISABLE-NEXT: @ => This Inner Loop Header: Depth=2
; DISABLE-NEXT: mov r0, r3
; DISABLE-NEXT: cmp r3, r2
; DISABLE-NEXT: bls .LBB0_6
; DISABLE-NEXT: @ %bb.15: @ %while.body24.land.rhs14_crit_edge
; DISABLE-NEXT: @ in Loop: Header=BB0_14 Depth=2
; DISABLE-NEXT: mov r3, r0
; DISABLE-NEXT: ldrsb lr, [r3], #-1
; DISABLE-NEXT: cmn lr, #1
; DISABLE-NEXT: uxtb r12, lr
; DISABLE-NEXT: bgt .LBB0_6
; DISABLE-NEXT: @ %bb.16: @ %while.body24.land.rhs14_crit_edge
; DISABLE-NEXT: @ in Loop: Header=BB0_14 Depth=2
; DISABLE-NEXT: cmp r12, #192
; DISABLE-NEXT: blo .LBB0_14
; DISABLE-NEXT: b .LBB0_6
; DISABLE-NEXT: .LBB0_17:
; DISABLE-NEXT: mov r0, r3
; DISABLE-NEXT: pop {r11, pc}
entry:
%cmp = icmp sgt i32 %off, -1
br i1 %cmp, label %while.cond.preheader, label %while.cond2.outer

File diff suppressed because it is too large Load Diff

View File

@ -203,8 +203,8 @@ target triple = "powerpc64le-unknown-linux-gnu"
; Load a value into R0 before saving the LR
; CHECK: lwz 0, {{[0-9]+([0-9]+)}}
; Ensure the LR is saved using a different register
; CHECK: mflr {{[1-9]+}}
; Ensure the LR is saved using a different register - edit:D63152 prevents stack pop befor loads and stores
; CHECK-NOT: mflr {{[1-9]+}}
; Ensure the LR is restored using a different register
; CHECK: mtlr {{[0-9]+}}

View File

@ -10,7 +10,8 @@ entry:
br i1 undef, label %land.lhs.true, label %if.end
; CHECK: # %land.lhs.true
; CHECK-NEXT: bclr
; Test updated due D63152 where any load/store prevents shrink-wrapping
; CHECK-NEXT: bc
; CHECK-NEXT: # %if.end4
land.lhs.true: ; preds = %entry
br i1 undef, label %return, label %if.end4

View File

@ -61,11 +61,11 @@
@ga = external global i32, align 4
@gb = external global i32, align 4
define signext i32 @test(i32 (i32)* nocapture %FP) local_unnamed_addr #0 {
; CHECK-LABEL: test:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: addis 4, 2, .LC0@toc@ha
; CHECK-NEXT: mflr 0
; CHECK: addis 4, 2, .LC0@toc@ha
; CHECK-NEXT: addis 5, 2, .LC1@toc@ha
; CHECK-NEXT: mr 12, 3
; CHECK-NEXT: ld 4, .LC0@toc@l(4)

View File

@ -1,8 +1,8 @@
; RUN: llc -relocation-model=static -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -disable-ppc-sco=false --enable-shrink-wrap=false | FileCheck %s -check-prefix=CHECK-SCO-ONLY
; RUN: llc -relocation-model=static -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -disable-ppc-sco=false --enable-shrink-wrap=true | FileCheck %s -check-prefix=CHECK-SCO-SHRK
; RUN: llc -relocation-model=static -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -disable-ppc-sco=false --enable-shrink-wrap=true | FileCheck %s -check-prefix=CHECK-SCO-ONLY
; RUN: llc -relocation-model=static -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu -disable-ppc-sco=false --enable-shrink-wrap=false | FileCheck %s -check-prefix=CHECK-SCO-ONLY
; RUN: llc -relocation-model=static -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu -disable-ppc-sco=false --enable-shrink-wrap=true | FileCheck %s -check-prefix=CHECK-SCO-SHRK
; RUN: llc -relocation-model=static -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux-gnu -disable-ppc-sco=false --enable-shrink-wrap=true | FileCheck %s -check-prefix=CHECK-SCO-ONLY
; Edit: D63152 prevents stack popping before loads and stores, so shrink-wrap does nothing here
%"class.clang::NamedDecl" = type { i32 }
declare void @__assert_fail();

View File

@ -2,9 +2,9 @@
define void @ILLBeBack() #0 {
; CHECK-LABEL @ILLBeBack
; CHECK: beq {{[0-9]+}}, [[LABEL:\.[a-zA-Z0-9_]+]]
; CHECK: bl __xray_FunctionExit
; CHECK: bne {{[0-9]+}}, [[LABEL:\.[a-zA-Z0-9_]+]]
; CHECK: [[LABEL]]:
; CHECK: bl __xray_FunctionExit
bb:
br i1 undef, label %bb1, label %bb8

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
define i32 @main() nounwind {
; CHECK-LABEL: main:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: cmpq {{.*}}(%rip), %rax
; CHECK-NEXT: sbbb %al, %al
@ -21,7 +22,6 @@ define i32 @main() nounwind {
; CHECK-NEXT: .LBB0_1: # %entry.if.end_crit_edge
; CHECK-NEXT: movl {{.*}}(%rip), %esi
; CHECK-NEXT: .LBB0_3: # %if.end
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: movl $.L.str, %edi
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: callq printf

View File

@ -14,6 +14,7 @@ target triple = "x86_64-pc-linux"
define void @foo(i8* nocapture %_stubArgs) nounwind {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: subq $152, %rsp
; CHECK-NEXT: movq 48(%rdi), %rax
; CHECK-NEXT: movl 64(%rdi), %edx
; CHECK-NEXT: movl $200, %esi
@ -29,14 +30,14 @@ define void @foo(i8* nocapture %_stubArgs) nounwind {
; CHECK-NEXT: jne .LBB0_1
; CHECK-NEXT: # %bb.2: # %entry
; CHECK-NEXT: xorps %xmm1, %xmm1
; CHECK-NEXT: jmp .LBB0_3
; CHECK-NEXT: movaps %xmm1, -{{[0-9]+}}(%rsp)
; CHECK-NEXT: je .LBB0_4
; CHECK-NEXT: jmp .LBB0_5
; CHECK-NEXT: .LBB0_1:
; CHECK-NEXT: movaps (%rax,%rcx), %xmm1
; CHECK-NEXT: .LBB0_3: # %entry
; CHECK-NEXT: leaq -{{[0-9]+}}(%rsp), %rsp
; CHECK-NEXT: movaps %xmm1, -{{[0-9]+}}(%rsp)
; CHECK-NEXT: jne .LBB0_5
; CHECK-NEXT: # %bb.4: # %entry
; CHECK-NEXT: .LBB0_4: # %entry
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: .LBB0_5: # %entry
; CHECK-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp)

View File

@ -78,6 +78,7 @@ define void @test3(i64 %a, i64 %b, i1 %p) nounwind {
define i1 @test4() nounwind {
; CHECK-LABEL: test4:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: movsbl {{.*}}(%rip), %edx
; CHECK-NEXT: movzbl %dl, %ecx
; CHECK-NEXT: shrl $7, %ecx
@ -90,7 +91,6 @@ define i1 @test4() nounwind {
; CHECK-NEXT: # %bb.1: # %bb.i.i.i
; CHECK-NEXT: movb {{.*}}(%rip), %cl
; CHECK-NEXT: .LBB3_2: # %func_4.exit.i
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: xorl %esi, %esi
; CHECK-NEXT: testb %dl, %dl
; CHECK-NEXT: setne %bl

View File

@ -43,6 +43,7 @@ define i32 @test1() nounwind {
;
; X64-LABEL: test1:
; X64: # %bb.0: # %entry
; X64-NEXT: pushq %rax
; X64-NEXT: movb {{.*}}(%rip), %cl
; X64-NEXT: leal 1(%rcx), %eax
; X64-NEXT: movb %al, {{.*}}(%rip)
@ -56,12 +57,11 @@ define i32 @test1() nounwind {
; X64-NEXT: testb %dl, %dl
; X64-NEXT: jne .LBB0_2
; X64-NEXT: # %bb.1: # %if.then
; X64-NEXT: pushq %rax
; X64-NEXT: movsbl %al, %edi
; X64-NEXT: callq external
; X64-NEXT: addq $8, %rsp
; X64-NEXT: .LBB0_2: # %if.end
; X64-NEXT: xorl %eax, %eax
; X64-NEXT: popq %rcx
; X64-NEXT: retq
entry:
%bval = load i8, i8* @b

View File

@ -17,16 +17,18 @@
define void @program_1(%struct._image2d_t* %dest, %struct._image2d_t* %t0, <4 x float> %p0, <4 x float> %p1, <4 x float> %p4, <4 x float> %p5, <4 x float> %p6) nounwind {
; X32-LABEL: program_1:
; X32: ## %bb.0: ## %entry
; X32-NEXT: pushl %esi
; X32-NEXT: subl $88, %esp
; X32-NEXT: cmpl $0, 0
; X32-NEXT: jle LBB0_2
; X32-NEXT: ## %bb.1: ## %forcond
; X32-NEXT: cmpl $0, 0
; X32-NEXT: jg LBB0_3
; X32-NEXT: LBB0_2: ## %ifthen
; X32-NEXT: addl $88, %esp
; X32-NEXT: popl %esi
; X32-NEXT: retl
; X32-NEXT: LBB0_3: ## %forbody
; X32-NEXT: pushl %esi
; X32-NEXT: subl $88, %esp
; X32-NEXT: movaps {{.*#+}} xmm1 = [1.28E+2,1.28E+2,1.28E+2,1.28E+2]
; X32-NEXT: minps LCPI0_3, %xmm1
; X32-NEXT: cvttps2dq %xmm1, %xmm0
@ -99,16 +101,18 @@ define void @program_1(%struct._image2d_t* %dest, %struct._image2d_t* %t0, <4 x
;
; X64-LABEL: program_1:
; X64: ## %bb.0: ## %entry
; X64-NEXT: pushq %rbx
; X64-NEXT: subq $64, %rsp
; X64-NEXT: cmpl $0, 0
; X64-NEXT: jle LBB0_2
; X64-NEXT: ## %bb.1: ## %forcond
; X64-NEXT: cmpl $0, 0
; X64-NEXT: jg LBB0_3
; X64-NEXT: LBB0_2: ## %ifthen
; X64-NEXT: addq $64, %rsp
; X64-NEXT: popq %rbx
; X64-NEXT: retq
; X64-NEXT: LBB0_3: ## %forbody
; X64-NEXT: pushq %rbx
; X64-NEXT: subq $64, %rsp
; X64-NEXT: xorps %xmm0, %xmm0
; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill
; X64-NEXT: movaps {{.*#+}} xmm1 = [1.28E+2,1.28E+2,1.28E+2,1.28E+2]

View File

@ -1,5 +1,6 @@
; RUN: llc %s -o - -enable-shrink-wrap=true -no-x86-call-frame-opt | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
; RUN: llc %s -o - -enable-shrink-wrap=false -no-x86-call-frame-opt | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc %s -o - -enable-shrink-wrap=true -no-x86-call-frame-opt | FileCheck %s --check-prefix=ENABLE
; RUN: llc %s -o - -enable-shrink-wrap=false -no-x86-call-frame-opt | FileCheck %s --check-prefix=DISABLE
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i386-apple-macosx10.5"
@ -15,53 +16,83 @@ target triple = "i386-apple-macosx10.5"
; Check that we are clobbering the flags when they are live-in of the
; prologue block and the prologue needs to adjust the stack.
; PR25607.
;
; CHECK-LABEL: eflagsLiveInPrologue:
;
; DISABLE: pushl
; DISABLE-NEXT: subl $8, %esp
;
; CHECK: movl L_a$non_lazy_ptr, [[A:%[a-z]+]]
; CHECK-NEXT: cmpl $0, ([[A]])
; CHECK-NEXT: je [[PREHEADER_LABEL:LBB[0-9_]+]]
;
; CHECK: movb $1, _d
;
; CHECK: [[PREHEADER_LABEL]]:
; CHECK-NEXT: movl L_b$non_lazy_ptr, [[B:%[a-z]+]]
; CHECK-NEXT: movl ([[B]]), [[TMP1:%[a-z]+]]
; CHECK-NEXT: testl [[TMP1]], [[TMP1]]
; CHECK-NEXT: je [[FOREND_LABEL:LBB[0-9_]+]]
;
; Skip the loop.
; [...]
;
; The for.end block is split to accomadate the different selects.
; We are interested in the one with the call, so skip until the branch.
; CHECK: [[FOREND_LABEL]]:
; ENABLE: pushl
; ENABLE-NEXT: subl $8, %esp
; CHECK: xorl [[CMOVE_VAL:%edx]], [[CMOVE_VAL]]
; CHECK-NEXT: cmpb $0, _d
; CHECK-NEXT: movl $6, [[IMM_VAL:%ecx]]
; The eflags is used in the next instruction.
; If that instruction disappear, we are not exercising the bug
; anymore.
; CHECK-NEXT: cmovnel [[CMOVE_VAL]], [[IMM_VAL]]
; CHECK-NEXT: L_e$non_lazy_ptr, [[E:%[a-z]+]]
; CHECK-NEXT: movb %cl, ([[E]])
; CHECK-NEXT: leal 1(%ecx), %esi
; CHECK: calll _varfunc
; Set the return value to 0.
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: addl $8, %esp
; CHECK-NEXT: popl
; CHECK-NEXT: retl
define i32 @eflagsLiveInPrologue() #0 {
; ENABLE-LABEL: eflagsLiveInPrologue:
; ENABLE: ## %bb.0: ## %entry
; ENABLE-NEXT: pushl %esi
; ENABLE-NEXT: subl $8, %esp
; ENABLE-NEXT: movl L_a$non_lazy_ptr, %eax
; ENABLE-NEXT: cmpl $0, (%eax)
; ENABLE-NEXT: je LBB0_2
; ENABLE-NEXT: ## %bb.1: ## %if.then
; ENABLE-NEXT: movb $1, _d
; ENABLE-NEXT: LBB0_2: ## %for.cond.preheader
; ENABLE-NEXT: movl L_b$non_lazy_ptr, %eax
; ENABLE-NEXT: movl (%eax), %eax
; ENABLE-NEXT: testl %eax, %eax
; ENABLE-NEXT: je LBB0_4
; ENABLE-NEXT: .p2align 4, 0x90
; ENABLE-NEXT: LBB0_3: ## %for.body
; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1
; ENABLE-NEXT: jmp LBB0_3
; ENABLE-NEXT: LBB0_4: ## %for.end
; ENABLE-NEXT: xorl %edx, %edx
; ENABLE-NEXT: cmpb $0, _d
; ENABLE-NEXT: movl $6, %ecx
; ENABLE-NEXT: cmovnel %edx, %ecx
; ENABLE-NEXT: movl L_e$non_lazy_ptr, %edx
; ENABLE-NEXT: movb %cl, (%edx)
; ENABLE-NEXT: leal 1(%ecx), %esi
; ENABLE-NEXT: cltd
; ENABLE-NEXT: idivl %esi
; ENABLE-NEXT: movl L_c$non_lazy_ptr, %eax
; ENABLE-NEXT: movl %edx, (%eax)
; ENABLE-NEXT: movl %ecx, {{[0-9]+}}(%esp)
; ENABLE-NEXT: movl $L_.str, (%esp)
; ENABLE-NEXT: calll _varfunc
; ENABLE-NEXT: xorl %eax, %eax
; ENABLE-NEXT: addl $8, %esp
; ENABLE-NEXT: popl %esi
; ENABLE-NEXT: retl
;
; DISABLE-LABEL: eflagsLiveInPrologue:
; DISABLE: ## %bb.0: ## %entry
; DISABLE-NEXT: pushl %esi
; DISABLE-NEXT: subl $8, %esp
; DISABLE-NEXT: movl L_a$non_lazy_ptr, %eax
; DISABLE-NEXT: cmpl $0, (%eax)
; DISABLE-NEXT: je LBB0_2
; DISABLE-NEXT: ## %bb.1: ## %if.then
; DISABLE-NEXT: movb $1, _d
; DISABLE-NEXT: LBB0_2: ## %for.cond.preheader
; DISABLE-NEXT: movl L_b$non_lazy_ptr, %eax
; DISABLE-NEXT: movl (%eax), %eax
; DISABLE-NEXT: testl %eax, %eax
; DISABLE-NEXT: je LBB0_4
; DISABLE-NEXT: .p2align 4, 0x90
; DISABLE-NEXT: LBB0_3: ## %for.body
; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1
; DISABLE-NEXT: jmp LBB0_3
; DISABLE-NEXT: LBB0_4: ## %for.end
; DISABLE-NEXT: xorl %edx, %edx
; DISABLE-NEXT: cmpb $0, _d
; DISABLE-NEXT: movl $6, %ecx
; DISABLE-NEXT: cmovnel %edx, %ecx
; DISABLE-NEXT: movl L_e$non_lazy_ptr, %edx
; DISABLE-NEXT: movb %cl, (%edx)
; DISABLE-NEXT: leal 1(%ecx), %esi
; DISABLE-NEXT: cltd
; DISABLE-NEXT: idivl %esi
; DISABLE-NEXT: movl L_c$non_lazy_ptr, %eax
; DISABLE-NEXT: movl %edx, (%eax)
; DISABLE-NEXT: movl %ecx, {{[0-9]+}}(%esp)
; DISABLE-NEXT: movl $L_.str, (%esp)
; DISABLE-NEXT: calll _varfunc
; DISABLE-NEXT: xorl %eax, %eax
; DISABLE-NEXT: addl $8, %esp
; DISABLE-NEXT: popl %esi
; DISABLE-NEXT: retl
entry:
%tmp = load i32, i32* @a, align 4
%tobool = icmp eq i32 %tmp, 0

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-windows-gnu -exception-model=dwarf < %s | FileCheck %s
%struct.A = type { [4096 x i8] }
@ -6,6 +7,29 @@
@b = common global i32 0, align 4
define void @fn1() nounwind uwtable {
; CHECK-LABEL: fn1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: movl $4136, %eax # imm = 0x1028
; CHECK-NEXT: callq ___chkstk_ms
; CHECK-NEXT: subq %rax, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 4144
; CHECK-NEXT: movl {{.*}}(%rip), %eax
; CHECK-NEXT: testl %eax, %eax
; CHECK-NEXT: jne .LBB0_2
; CHECK-NEXT: # %bb.1: # %select.true.sink
; CHECK-NEXT: cltq
; CHECK-NEXT: imulq $715827883, %rax, %rax # imm = 0x2AAAAAAB
; CHECK-NEXT: movq %rax, %rcx
; CHECK-NEXT: shrq $63, %rcx
; CHECK-NEXT: shrq $32, %rax
; CHECK-NEXT: addl %ecx, %eax
; CHECK-NEXT: .LBB0_2: # %select.end
; CHECK-NEXT: movl %eax, {{.*}}(%rip)
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rcx
; CHECK-NEXT: # kill: def $ecx killed $ecx killed $rcx
; CHECK-NEXT: callq fn2
; CHECK-NEXT: addq $4136, %rsp # imm = 0x1028
; CHECK-NEXT: retq
entry:
%ctx = alloca %struct.A, align 1
%0 = load i32, i32* @a, align 4
@ -26,11 +50,3 @@ declare void @fn2(i32)
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
; CHECK-LABEL: fn1:
; CHECK: pushq %rax
; CHECK: movl $4128, %eax
; CHECK: callq ___chkstk_ms
; CHECK: subq %rax, %rsp
; CHECK: movq 4128(%rsp), %rax
; CHECK: addq $4136, %rsp

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@
define zeroext i1 @_Z3fooRSt6atomicIbEb(%"struct.std::atomic"* nocapture dereferenceable(1) %a, i1 returned zeroext %b) nounwind {
; CHECK-LABEL: _Z3fooRSt6atomicIbEb:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: movq %rdi, %rcx
; CHECK-NEXT: shrq $3, %rcx
@ -24,9 +25,9 @@ define zeroext i1 @_Z3fooRSt6atomicIbEb(%"struct.std::atomic"* nocapture derefer
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: xchgb %cl, (%rdi)
; CHECK-NEXT: # kill: def $al killed $al killed $eax
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: retq
; CHECK-NEXT: .LBB0_2:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: callq __asan_report_store1
; CHECK-NEXT: #APP
; CHECK-NEXT: #NO_APP