|  | ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
|  | ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 -O3 -verify-machineinstrs | FileCheck %s | 
|  | ; | 
|  | ; Test stack clash protection probing for static allocas. | 
|  |  | 
|  | ; Small: one probe. | 
|  | define i32 @fun0() #0 { | 
|  | ; CHECK-LABEL: fun0: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    aghi %r15, -560 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 720 | 
|  | ; CHECK-NEXT:    cg %r0, 552(%r15) | 
|  | ; CHECK-NEXT:    mvhi 552(%r15), 1 | 
|  | ; CHECK-NEXT:    l %r2, 160(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 560 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  |  | 
|  | %a = alloca i32, i64 100 | 
|  | %b = getelementptr inbounds i32, ptr %a, i64 98 | 
|  | store volatile i32 1, ptr %b | 
|  | %c = load volatile i32, ptr %a | 
|  | ret i32 %c | 
|  | } | 
|  |  | 
|  | ; Medium: two probes. | 
|  | define i32 @fun1() #0 { | 
|  | ; CHECK-LABEL: fun1: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    aghi %r15, -4096 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 4256 | 
|  | ; CHECK-NEXT:    cg %r0, 4088(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, -4080 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 8336 | 
|  | ; CHECK-NEXT:    cg %r0, 4072(%r15) | 
|  | ; CHECK-NEXT:    mvhi 976(%r15), 1 | 
|  | ; CHECK-NEXT:    l %r2, 176(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 8176 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  |  | 
|  | %a = alloca i32, i64 2000 | 
|  | %b = getelementptr inbounds i32, ptr %a, i64 200 | 
|  | store volatile i32 1, ptr %b | 
|  | %c = load volatile i32, ptr %a | 
|  | ret i32 %c | 
|  | } | 
|  |  | 
|  | ; Large: Use a loop to allocate and probe in steps. | 
|  | define i32 @fun2() #0 { | 
|  | ; CHECK-LABEL: fun2: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    lgr %r0, %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r0 | 
|  | ; CHECK-NEXT:    agfi %r0, -69632 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 69792 | 
|  | ; CHECK-NEXT:  .LBB2_1: # =>This Inner Loop Header: Depth=1 | 
|  | ; CHECK-NEXT:    aghi %r15, -4096 | 
|  | ; CHECK-NEXT:    cg %r0, 4088(%r15) | 
|  | ; CHECK-NEXT:    clgrjh %r15, %r0, .LBB2_1 | 
|  | ; CHECK-NEXT:  # %bb.2: | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r15 | 
|  | ; CHECK-NEXT:    aghi %r15, -2544 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 72336 | 
|  | ; CHECK-NEXT:    cg %r0, 2536(%r15) | 
|  | ; CHECK-NEXT:    lhi %r0, 1 | 
|  | ; CHECK-NEXT:    mvhi 568(%r15), 1 | 
|  | ; CHECK-NEXT:    sty %r0, 28968(%r15) | 
|  | ; CHECK-NEXT:    l %r2, 176(%r15) | 
|  | ; CHECK-NEXT:    agfi %r15, 72176 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  |  | 
|  | %a = alloca i32, i64 18000 | 
|  | %b0 = getelementptr inbounds i32, ptr %a, i64 98 | 
|  | %b1 = getelementptr inbounds i32, ptr %a, i64 7198 | 
|  | store volatile i32 1, ptr %b0 | 
|  | store volatile i32 1, ptr %b1 | 
|  | %c = load volatile i32, ptr %a | 
|  | ret i32 %c | 
|  | } | 
|  |  | 
|  | ; Ends evenly on the step so no remainder needed. | 
|  | define void @fun3() #0 { | 
|  | ; CHECK-LABEL: fun3: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    lgr %r0, %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r0 | 
|  | ; CHECK-NEXT:    aghi %r0, -28672 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 28832 | 
|  | ; CHECK-NEXT:  .LBB3_1: # %entry | 
|  | ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1 | 
|  | ; CHECK-NEXT:    aghi %r15, -4096 | 
|  | ; CHECK-NEXT:    cg %r0, 4088(%r15) | 
|  | ; CHECK-NEXT:    clgrjh %r15, %r0, .LBB3_1 | 
|  | ; CHECK-NEXT:  # %bb.2: # %entry | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r15 | 
|  | ; CHECK-NEXT:    mvhi 180(%r15), 0 | 
|  | ; CHECK-NEXT:    l %r0, 180(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 28672 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  | entry: | 
|  | %stack = alloca [7122 x i32], align 4 | 
|  | %i = alloca i32, align 4 | 
|  | store volatile i32 0, ptr %i, align 4 | 
|  | %i.0.i.0.6 = load volatile i32, ptr %i, align 4 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; Loop with bigger step. | 
|  | define void @fun4() #0 "stack-probe-size"="8192" { | 
|  | ; CHECK-LABEL: fun4: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    lgr %r0, %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r0 | 
|  | ; CHECK-NEXT:    aghi %r0, -24576 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 24736 | 
|  | ; CHECK-NEXT:  .LBB4_1: # %entry | 
|  | ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1 | 
|  | ; CHECK-NEXT:    aghi %r15, -8192 | 
|  | ; CHECK-NEXT:    cg %r0, 8184(%r15) | 
|  | ; CHECK-NEXT:    clgrjh %r15, %r0, .LBB4_1 | 
|  | ; CHECK-NEXT:  # %bb.2: # %entry | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r15 | 
|  | ; CHECK-NEXT:    aghi %r15, -7608 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 32344 | 
|  | ; CHECK-NEXT:    cg %r0, 7600(%r15) | 
|  | ; CHECK-NEXT:    mvhi 180(%r15), 0 | 
|  | ; CHECK-NEXT:    l %r0, 180(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 32184 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  | entry: | 
|  | %stack = alloca [8000 x i32], align 4 | 
|  | %i = alloca i32, align 4 | 
|  | store volatile i32 0, ptr %i, align 4 | 
|  | %i.0.i.0.6 = load volatile i32, ptr %i, align 4 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; Probe size should be modulo stack alignment. | 
|  | define void @fun5() #0 "stack-probe-size"="4100" { | 
|  | ; CHECK-LABEL: fun5: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    aghi %r15, -4096 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 4256 | 
|  | ; CHECK-NEXT:    cg %r0, 4088(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, -88 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 4344 | 
|  | ; CHECK-NEXT:    cg %r0, 80(%r15) | 
|  | ; CHECK-NEXT:    mvhi 180(%r15), 0 | 
|  | ; CHECK-NEXT:    l %r0, 180(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 4184 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  | entry: | 
|  | %stack = alloca [1000 x i32], align 4 | 
|  | %i = alloca i32, align 4 | 
|  | store volatile i32 0, ptr %i, align 4 | 
|  | %i.0.i.0.6 = load volatile i32, ptr %i, align 4 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; The minimum probe size is the stack alignment. | 
|  | define void @fun6() #0 "stack-probe-size"="5" { | 
|  | ; CHECK-LABEL: fun6: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    lgr %r0, %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r0 | 
|  | ; CHECK-NEXT:    aghi %r0, -4184 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 4344 | 
|  | ; CHECK-NEXT:  .LBB6_1: # %entry | 
|  | ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1 | 
|  | ; CHECK-NEXT:    aghi %r15, -8 | 
|  | ; CHECK-NEXT:    cg %r0, 0(%r15) | 
|  | ; CHECK-NEXT:    clgrjh %r15, %r0, .LBB6_1 | 
|  | ; CHECK-NEXT:  # %bb.2: # %entry | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r15 | 
|  | ; CHECK-NEXT:    mvhi 180(%r15), 0 | 
|  | ; CHECK-NEXT:    l %r0, 180(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 4184 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  | entry: | 
|  | %stack = alloca [1000 x i32], align 4 | 
|  | %i = alloca i32, align 4 | 
|  | store volatile i32 0, ptr %i, align 4 | 
|  | %i.0.i.0.6 = load volatile i32, ptr %i, align 4 | 
|  | ret void | 
|  | } | 
|  |  | 
|  | ; Small with a natural probe (STMG) - needs no extra probe. | 
|  | define i32 @fun7() #0 { | 
|  | ; CHECK-LABEL: fun7: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    stmg %r14, %r15, 112(%r15) | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -48 | 
|  | ; CHECK-NEXT:    .cfi_offset %r15, -40 | 
|  | ; CHECK-NEXT:    aghi %r15, -3976 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 4136 | 
|  | ; CHECK-NEXT:    brasl %r14, foo@PLT | 
|  | ; CHECK-NEXT:    st %r2, 568(%r15) | 
|  | ; CHECK-NEXT:    l %r2, 176(%r15) | 
|  | ; CHECK-NEXT:    lmg %r14, %r15, 4088(%r15) | 
|  | ; CHECK-NEXT:    br %r14 | 
|  | %v = call i32 @foo() | 
|  | %a = alloca i32, i64 950 | 
|  | %b = getelementptr inbounds i32, ptr %a, i64 98 | 
|  | store volatile i32 %v, ptr %b | 
|  | %c = load volatile i32, ptr %a | 
|  | ret i32 %c | 
|  | } | 
|  |  | 
|  | ; Medium with an STMG - still needs probing. | 
|  | define i32 @fun8() #0 { | 
|  | ; CHECK-LABEL: fun8: | 
|  | ; CHECK:       # %bb.0: | 
|  | ; CHECK-NEXT:    stmg %r14, %r15, 112(%r15) | 
|  | ; CHECK-NEXT:    .cfi_offset %r14, -48 | 
|  | ; CHECK-NEXT:    .cfi_offset %r15, -40 | 
|  | ; CHECK-NEXT:    aghi %r15, -3984 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 4144 | 
|  | ; CHECK-NEXT:    cg %r0, 3976(%r15) | 
|  | ; CHECK-NEXT:    brasl %r14, foo@PLT | 
|  | ; CHECK-NEXT:    st %r2, 976(%r15) | 
|  | ; CHECK-NEXT:    l %r2, 176(%r15) | 
|  | ; CHECK-NEXT:    lmg %r14, %r15, 4096(%r15) | 
|  | ; CHECK-NEXT:    br %r14 | 
|  |  | 
|  | %v = call i32 @foo() | 
|  | %a = alloca i32, i64 952 | 
|  | %b = getelementptr inbounds i32, ptr %a, i64 200 | 
|  | store volatile i32 %v, ptr %b | 
|  | %c = load volatile i32, ptr %a | 
|  | ret i32 %c | 
|  | } | 
|  |  | 
|  | define void @fun9() #0 "backchain" { | 
|  | ; CHECK-LABEL: fun9: | 
|  | ; CHECK:       # %bb.0: # %entry | 
|  | ; CHECK-NEXT:    lgr %r1, %r15 | 
|  | ; CHECK-NEXT:    lgr %r0, %r15 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r0 | 
|  | ; CHECK-NEXT:    aghi %r0, -28672 | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_offset 28832 | 
|  | ; CHECK-NEXT:  .LBB9_1: # %entry | 
|  | ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1 | 
|  | ; CHECK-NEXT:    aghi %r15, -4096 | 
|  | ; CHECK-NEXT:    cg %r0, 4088(%r15) | 
|  | ; CHECK-NEXT:    clgrjh %r15, %r0, .LBB9_1 | 
|  | ; CHECK-NEXT:  # %bb.2: # %entry | 
|  | ; CHECK-NEXT:    .cfi_def_cfa_register %r15 | 
|  | ; CHECK-NEXT:    stg %r1, 0(%r15) | 
|  | ; CHECK-NEXT:    mvhi 180(%r15), 0 | 
|  | ; CHECK-NEXT:    l %r0, 180(%r15) | 
|  | ; CHECK-NEXT:    aghi %r15, 28672 | 
|  | ; CHECK-NEXT:    br %r14 | 
|  | entry: | 
|  | %stack = alloca [7122 x i32], align 4 | 
|  | %i = alloca i32, align 4 | 
|  | store volatile i32 0, ptr %i, align 4 | 
|  | %i.0.i.0.6 = load volatile i32, ptr %i, align 4 | 
|  | ret void | 
|  | } | 
|  |  | 
|  |  | 
|  | declare i32 @foo() | 
|  | attributes #0 = {  "probe-stack"="inline-asm"  } | 
|  |  |