5 changes: 4 additions & 1 deletion llvm/lib/Target/SystemZ/SystemZLongBranch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,10 @@ static unsigned getInstSizeInBytes(const MachineInstr &MI,
MI.isImplicitDef() || MI.getOpcode() == TargetOpcode::MEMBARRIER ||
// These have a size that may be zero:
MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP ||
MI.getOpcode() == SystemZ::PATCHPOINT) &&
MI.getOpcode() == SystemZ::PATCHPOINT ||
// EH_SjLj_Setup is a dummy terminator instruction of size 0,
// It is used to handle the clobber register for builtin setjmp.
MI.getOpcode() == SystemZ::EH_SjLj_Setup) &&
"Missing size value for instruction.");
return Size;
}
Expand Down
12 changes: 12 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZOperators.td
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,12 @@ def SDT_ZTest : SDTypeProfile<1, 2,
[SDTCisVT<0, i32>,
SDTCisVT<2, i64>]>;

def SDT_ZSetJmp : SDTypeProfile<1, 1,
[SDTCisInt<0>,
SDTCisPtrTy<1>]>;
def SDT_ZLongJmp : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;


//===----------------------------------------------------------------------===//
// Node definitions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -314,6 +320,12 @@ def z_stckf : SDNode<"SystemZISD::STCKF", SDT_ZStoreInherent,

def z_tdc : SDNode<"SystemZISD::TDC", SDT_ZTest>;

def z_eh_sjlj_setjmp : SDNode<"ISD::EH_SJLJ_SETJMP", SDT_ZSetJmp,
[SDNPHasChain, SDNPSideEffect]>;
def z_eh_sjlj_longjmp : SDNode<"ISD::EH_SJLJ_LONGJMP", SDT_ZLongJmp,
[SDNPHasChain, SDNPSideEffect]>;


// Defined because the index is an i32 rather than a pointer.
def z_vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT",
SDT_ZInsertVectorElt>;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
return Regs->getCallPreservedMask(MF, CC);
}

const uint32_t *SystemZRegisterInfo::getNoPreservedMask() const {
return CSR_SystemZ_NoRegs_RegMask;
}

BitVector
SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SystemZ/SystemZRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const override;
const uint32_t *getNoPreservedMask() const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
bool eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, unsigned FIOperandNum,
Expand Down
49 changes: 49 additions & 0 deletions llvm/test/CodeGen/SystemZ/builtin-longjmp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Test longjmp load from jmp_buf.
; Frame pointer from Slot 1.
; Jump address from Slot 2.
; Backchain Value from Slot 3.
; Stack Pointer from Slot 4.
; Literal Pool Pointer from Slot 5.

; RUN: llc < %s -mtriple=s390x-linux-gnu -O2 | FileCheck %s

@buf = global [20 x ptr] zeroinitializer, align 8

define void @foo() {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r11, %r15, 88(%r15)
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: lg %r2, 8(%r1)
; CHECK-NEXT: lg %r11, 0(%r1)
; CHECK-NEXT: lg %r13, 32(%r1)
; CHECK-NEXT: lg %r15, 24(%r1)
; CHECK-NEXT: br %r2
entry:
tail call void @llvm.eh.sjlj.longjmp(ptr nonnull @buf)
unreachable
}

define void @bar() "backchain" {
; CHECK-LABEL: bar:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r11, %r15, 88(%r15)
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: lg %r2, 8(%r1)
; CHECK-NEXT: lg %r11, 0(%r1)
; CHECK-NEXT: lg %r13, 32(%r1)
; CHECK-NEXT: lg %r3, 16(%r1)
; CHECK-NEXT: lg %r15, 24(%r1)
; CHECK-NEXT: stg %r3, 0(%r15)
; CHECK-NEXT: br %r2
entry:
tail call void @llvm.eh.sjlj.longjmp(ptr nonnull @buf)
unreachable
}
156 changes: 156 additions & 0 deletions llvm/test/CodeGen/SystemZ/builtin-setjmp-alloca.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Test setjmp store to jmp_buf when frame pointer is used and saved
; because of variable size alloca.
; Frame Pointer is stored in slot 1.
; Return address in slot 2.
; Backchain value is stored in slot 3 for -mbackchain option.
; Stack Pointer in slot 4.
; Clobber %r6-%r15, %f8-%f15.

; RUN: llc < %s -mtriple=s390x-linux-gnu -O2 | FileCheck %s

declare i32 @llvm.eh.sjlj.setjmp(ptr)
@buf = global [20 x ptr] zeroinitializer, align 8

define signext i32 @foo() "frame-pointer"="all" {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r6, %r15, 48(%r15)
; CHECK-NEXT: .cfi_offset %r6, -112
; CHECK-NEXT: .cfi_offset %r7, -104
; CHECK-NEXT: .cfi_offset %r8, -96
; CHECK-NEXT: .cfi_offset %r9, -88
; CHECK-NEXT: .cfi_offset %r10, -80
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r12, -64
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r14, -48
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: aghi %r15, -240
; CHECK-NEXT: .cfi_def_cfa_offset 400
; CHECK-NEXT: lgr %r11, %r15
; CHECK-NEXT: .cfi_def_cfa_register %r11
; CHECK-NEXT: std %f8, 232(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f9, 224(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f10, 216(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f11, 208(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f12, 200(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f13, 192(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f14, 184(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f15, 176(%r11) # 8-byte Folded Spill
; CHECK-NEXT: .cfi_offset %f8, -168
; CHECK-NEXT: .cfi_offset %f9, -176
; CHECK-NEXT: .cfi_offset %f10, -184
; CHECK-NEXT: .cfi_offset %f11, -192
; CHECK-NEXT: .cfi_offset %f12, -200
; CHECK-NEXT: .cfi_offset %f13, -208
; CHECK-NEXT: .cfi_offset %f14, -216
; CHECK-NEXT: .cfi_offset %f15, -224
; CHECK-NEXT: la %r0, 160(%r11)
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: stg %r0, 168(%r11)
; CHECK-NEXT: mvhi 160(%r11), 10
; CHECK-NEXT: larl %r0, .LBB0_1
; CHECK-NEXT: stg %r0, 8(%r1)
; CHECK-NEXT: stg %r11, 0(%r1)
; CHECK-NEXT: stg %r15, 24(%r1)
; CHECK-NEXT: .LBB0_1: # Block address taken
; CHECK-NEXT: # %entry
; CHECK-NEXT: .LBB0_2: # %entry
; CHECK-NEXT: lg %r1, 168(%r11)
; CHECK-NEXT: lgf %r2, 0(%r1)
; CHECK-NEXT: ld %f8, 232(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f9, 224(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f10, 216(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f11, 208(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f12, 200(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f13, 192(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f14, 184(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f15, 176(%r11) # 8-byte Folded Reload
; CHECK-NEXT: lmg %r6, %r15, 288(%r11)
; CHECK-NEXT: br %r14
entry:
%val = alloca ptr, align 8
%0 = alloca i8, i64 4, align 8
store ptr %0, ptr %val, align 8
%1 = load ptr, ptr %val, align 8
store volatile i32 10, ptr %1, align 4
%2 = call i32 @llvm.eh.sjlj.setjmp(ptr @buf)
%3 = load ptr, ptr %val, align 8
%4 = load volatile i32, ptr %3, align 4
ret i32 %4
}

define signext i32 @foo1() "backchain" "frame-pointer"="all" {
; CHECK-LABEL: foo1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r6, %r15, 48(%r15)
; CHECK-NEXT: .cfi_offset %r6, -112
; CHECK-NEXT: .cfi_offset %r7, -104
; CHECK-NEXT: .cfi_offset %r8, -96
; CHECK-NEXT: .cfi_offset %r9, -88
; CHECK-NEXT: .cfi_offset %r10, -80
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r12, -64
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r14, -48
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: lgr %r1, %r15
; CHECK-NEXT: aghi %r15, -240
; CHECK-NEXT: .cfi_def_cfa_offset 400
; CHECK-NEXT: stg %r1, 0(%r15)
; CHECK-NEXT: lgr %r11, %r15
; CHECK-NEXT: .cfi_def_cfa_register %r11
; CHECK-NEXT: std %f8, 232(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f9, 224(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f10, 216(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f11, 208(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f12, 200(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f13, 192(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f14, 184(%r11) # 8-byte Folded Spill
; CHECK-NEXT: std %f15, 176(%r11) # 8-byte Folded Spill
; CHECK-NEXT: .cfi_offset %f8, -168
; CHECK-NEXT: .cfi_offset %f9, -176
; CHECK-NEXT: .cfi_offset %f10, -184
; CHECK-NEXT: .cfi_offset %f11, -192
; CHECK-NEXT: .cfi_offset %f12, -200
; CHECK-NEXT: .cfi_offset %f13, -208
; CHECK-NEXT: .cfi_offset %f14, -216
; CHECK-NEXT: .cfi_offset %f15, -224
; CHECK-NEXT: la %r0, 160(%r11)
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: stg %r0, 168(%r11)
; CHECK-NEXT: mvhi 160(%r11), 10
; CHECK-NEXT: larl %r0, .LBB1_1
; CHECK-NEXT: stg %r0, 8(%r1)
; CHECK-NEXT: stg %r11, 0(%r1)
; CHECK-NEXT: stg %r15, 24(%r1)
; CHECK-NEXT: lg %r0, 0(%r15)
; CHECK-NEXT: stg %r0, 16(%r1)
; CHECK-NEXT: .LBB1_1: # Block address taken
; CHECK-NEXT: # %entry
; CHECK-NEXT: .LBB1_2: # %entry
; CHECK-NEXT: lg %r1, 168(%r11)
; CHECK-NEXT: lgf %r2, 0(%r1)
; CHECK-NEXT: ld %f8, 232(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f9, 224(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f10, 216(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f11, 208(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f12, 200(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f13, 192(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f14, 184(%r11) # 8-byte Folded Reload
; CHECK-NEXT: ld %f15, 176(%r11) # 8-byte Folded Reload
; CHECK-NEXT: lmg %r6, %r15, 288(%r11)
; CHECK-NEXT: br %r14
entry:
%val = alloca ptr, align 8
%0 = alloca i8, i64 4, align 8
store ptr %0, ptr %val, align 8
%1 = load ptr, ptr %val, align 8
store volatile i32 10, ptr %1, align 4
%2 = call i32 @llvm.eh.sjlj.setjmp(ptr @buf)
%3 = load ptr, ptr %val, align 8
%4 = load volatile i32, ptr %3, align 4
ret i32 %4
}

254 changes: 254 additions & 0 deletions llvm/test/CodeGen/SystemZ/builtin-setjmp-spills.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Simulate register pressure around setjmp call and check all virtual registers
; are saved to stack before setjmp call and restored from stack after the call.
; And these registers are not live across the setjmp call.
; setjmp storing to jmp_buf.
; Return address in slot 2.
; Stack Pointer in slot 4.
; Clobber %r6-%r15, %f8-%f15.

; RUN: llc < %s -mtriple=s390x-linux-gnu -O3 | FileCheck %s

declare i32 @llvm.eh.sjlj.setjmp(ptr)

@t = global i32 0, align 4
@s = global i32 0, align 4
@r = global i32 0, align 4
@q = global i32 0, align 4
@p = global i32 0, align 4
@o = global i32 0, align 4
@n = global i32 0, align 4
@m = global i32 0, align 4
@l = global i32 0, align 4
@k = global i32 0, align 4
@j = global i32 0, align 4
@i = global i32 0, align 4
@h = global i32 0, align 4
@g = global i32 0, align 4
@f = global i32 0, align 4
@e = global i32 0, align 4
@d = global i32 0, align 4
@c = global i32 0, align 4
@b = global i32 0, align 4
@a = global i32 0, align 4
@buf = global [10 x ptr] zeroinitializer, align 8

define signext i32 @func() {
; CHECK-LABEL: func:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r6, %r15, 48(%r15)
; CHECK-NEXT: .cfi_offset %r6, -112
; CHECK-NEXT: .cfi_offset %r7, -104
; CHECK-NEXT: .cfi_offset %r8, -96
; CHECK-NEXT: .cfi_offset %r9, -88
; CHECK-NEXT: .cfi_offset %r10, -80
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r12, -64
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r14, -48
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: aghi %r15, -384
; CHECK-NEXT: .cfi_def_cfa_offset 544
; CHECK-NEXT: std %f8, 376(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f9, 368(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f10, 360(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f11, 352(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f12, 344(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f13, 336(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f14, 328(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f15, 320(%r15) # 8-byte Folded Spill
; CHECK-NEXT: .cfi_offset %f8, -168
; CHECK-NEXT: .cfi_offset %f9, -176
; CHECK-NEXT: .cfi_offset %f10, -184
; CHECK-NEXT: .cfi_offset %f11, -192
; CHECK-NEXT: .cfi_offset %f12, -200
; CHECK-NEXT: .cfi_offset %f13, -208
; CHECK-NEXT: .cfi_offset %f14, -216
; CHECK-NEXT: .cfi_offset %f15, -224
; CHECK-NEXT: lgrl %r1, t@GOT
; CHECK-NEXT: lgrl %r2, s@GOT
; CHECK-NEXT: stg %r1, 312(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: lgrl %r1, r@GOT
; CHECK-NEXT: lgrl %r3, q@GOT
; CHECK-NEXT: stg %r2, 304(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: lgrl %r2, p@GOT
; CHECK-NEXT: stg %r1, 296(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: stg %r3, 288(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r3), 1
; CHECK-NEXT: lgrl %r1, o@GOT
; CHECK-NEXT: stg %r2, 280(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: lgrl %r2, n@GOT
; CHECK-NEXT: lgrl %r3, m@GOT
; CHECK-NEXT: stg %r1, 272(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: lgrl %r1, l@GOT
; CHECK-NEXT: stg %r2, 264(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: stg %r3, 256(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r3), 1
; CHECK-NEXT: lgrl %r2, k@GOT
; CHECK-NEXT: stg %r1, 248(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: lgrl %r1, j@GOT
; CHECK-NEXT: lgrl %r3, i@GOT
; CHECK-NEXT: stg %r2, 240(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: lgrl %r2, h@GOT
; CHECK-NEXT: stg %r1, 232(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: stg %r3, 224(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r3), 1
; CHECK-NEXT: lgrl %r1, g@GOT
; CHECK-NEXT: stg %r2, 216(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: lgrl %r2, f@GOT
; CHECK-NEXT: lgrl %r3, e@GOT
; CHECK-NEXT: stg %r1, 208(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: lgrl %r1, d@GOT
; CHECK-NEXT: stg %r2, 200(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: stg %r3, 192(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r3), 1
; CHECK-NEXT: lgrl %r2, c@GOT
; CHECK-NEXT: stg %r1, 184(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r1), 1
; CHECK-NEXT: lgrl %r3, b@GOT
; CHECK-NEXT: lgrl %r4, a@GOT
; CHECK-NEXT: stg %r2, 176(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r2), 1
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: stg %r3, 168(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r3), 1
; CHECK-NEXT: stg %r4, 160(%r15) # 8-byte Folded Spill
; CHECK-NEXT: mvhi 0(%r4), 1
; CHECK-NEXT: larl %r0, .LBB0_2
; CHECK-NEXT: stg %r0, 8(%r1)
; CHECK-NEXT: stg %r15, 24(%r1)
; CHECK-NEXT: .LBB0_1: # %entry
; CHECK-NEXT: lhi %r0, 0
; CHECK-NEXT: j .LBB0_3
; CHECK-NEXT: .LBB0_2: # Block address taken
; CHECK-NEXT: # %entry
; CHECK-NEXT: lhi %r0, 1
; CHECK-NEXT: .LBB0_3: # %entry
; CHECK-NEXT: lg %r1, 160(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 168(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 176(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 184(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 192(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 200(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 208(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 216(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 224(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 232(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 240(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 248(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 256(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 264(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 272(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 280(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 288(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 296(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 304(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lg %r1, 312(%r15) # 8-byte Folded Reload
; CHECK-NEXT: a %r0, 0(%r1)
; CHECK-NEXT: lgfr %r2, %r0
; CHECK-NEXT: ld %f8, 376(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f9, 368(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f10, 360(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f11, 352(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f12, 344(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f13, 336(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f14, 328(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f15, 320(%r15) # 8-byte Folded Reload
; CHECK-NEXT: lmg %r6, %r15, 432(%r15)
; CHECK-NEXT: br %r14
entry:
store i32 1, ptr @t, align 4
store i32 1, ptr @s, align 4
store i32 1, ptr @r, align 4
store i32 1, ptr @q, align 4
store i32 1, ptr @p, align 4
store i32 1, ptr @o, align 4
store i32 1, ptr @n, align 4
store i32 1, ptr @m, align 4
store i32 1, ptr @l, align 4
store i32 1, ptr @k, align 4
store i32 1, ptr @j, align 4
store i32 1, ptr @i, align 4
store i32 1, ptr @h, align 4
store i32 1, ptr @g, align 4
store i32 1, ptr @f, align 4
store i32 1, ptr @e, align 4
store i32 1, ptr @d, align 4
store i32 1, ptr @c, align 4
store i32 1, ptr @b, align 4
store i32 1, ptr @a, align 4
%0 = tail call i32 @llvm.eh.sjlj.setjmp(ptr nonnull @buf)
%1 = load i32, ptr @a, align 4
%2 = load i32, ptr @b, align 4
%3 = load i32, ptr @c, align 4
%4 = load i32, ptr @d, align 4
%5 = load i32, ptr @e, align 4
%6 = load i32, ptr @f, align 4
%7 = load i32, ptr @g, align 4
%8 = load i32, ptr @h, align 4
%9 = load i32, ptr @i, align 4
%10 = load i32, ptr @j, align 4
%11 = load i32, ptr @k, align 4
%12 = load i32, ptr @l, align 4
%13 = load i32, ptr @m, align 4
%14 = load i32, ptr @n, align 4
%15 = load i32, ptr @o, align 4
%16 = load i32, ptr @p, align 4
%17 = load i32, ptr @q, align 4
%18 = load i32, ptr @r, align 4
%19 = load i32, ptr @s, align 4
%20 = load i32, ptr @t, align 4
%add = add i32 %1, %0
%add1 = add i32 %add, %2
%add2 = add i32 %add1, %3
%add3 = add i32 %add2, %4
%add4 = add i32 %add3, %5
%add5 = add i32 %add4, %6
%add6 = add i32 %add5, %7
%add7 = add i32 %add6, %8
%add8 = add i32 %add7, %9
%add9 = add i32 %add8, %10
%add10 = add i32 %add9, %11
%add11 = add i32 %add10, %12
%add12 = add i32 %add11, %13
%add13 = add i32 %add12, %14
%add14 = add i32 %add13, %15
%add15 = add i32 %add14, %16
%add16 = add i32 %add15, %17
%add17 = add i32 %add16, %18
%add18 = add i32 %add17, %19
%add19 = add i32 %add18, %20
ret i32 %add19
}

124 changes: 124 additions & 0 deletions llvm/test/CodeGen/SystemZ/builtin-setjmp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; Test setjmp store jmp_buf
; Return address in slot 2.
; Backchain value is stored in slot 3 for -mbackchain option.
; Stack Pointer in slot 4.
; Clobber %r6-%r15, %f8-%f15.

; RUN: llc < %s -mtriple=s390x-linux-gnu -O2 | FileCheck %s

declare i32 @llvm.eh.sjlj.setjmp(ptr)
@buf = global [20 x ptr] zeroinitializer, align 8

define void @foo() {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r6, %r15, 48(%r15)
; CHECK-NEXT: .cfi_offset %r6, -112
; CHECK-NEXT: .cfi_offset %r7, -104
; CHECK-NEXT: .cfi_offset %r8, -96
; CHECK-NEXT: .cfi_offset %r9, -88
; CHECK-NEXT: .cfi_offset %r10, -80
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r12, -64
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r14, -48
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: aghi %r15, -64
; CHECK-NEXT: .cfi_def_cfa_offset 224
; CHECK-NEXT: std %f8, 56(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f9, 48(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f10, 40(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f11, 32(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f12, 24(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f13, 16(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f14, 8(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f15, 0(%r15) # 8-byte Folded Spill
; CHECK-NEXT: .cfi_offset %f8, -168
; CHECK-NEXT: .cfi_offset %f9, -176
; CHECK-NEXT: .cfi_offset %f10, -184
; CHECK-NEXT: .cfi_offset %f11, -192
; CHECK-NEXT: .cfi_offset %f12, -200
; CHECK-NEXT: .cfi_offset %f13, -208
; CHECK-NEXT: .cfi_offset %f14, -216
; CHECK-NEXT: .cfi_offset %f15, -224
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: larl %r0, .LBB0_1
; CHECK-NEXT: stg %r0, 8(%r1)
; CHECK-NEXT: stg %r15, 24(%r1)
; CHECK-NEXT: .LBB0_1: # Block address taken
; CHECK-NEXT: # %entry
; CHECK-NEXT: .LBB0_2: # %entry
; CHECK-NEXT: ld %f8, 56(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f9, 48(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f10, 40(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f11, 32(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f12, 24(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f13, 16(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f14, 8(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f15, 0(%r15) # 8-byte Folded Reload
; CHECK-NEXT: lmg %r6, %r15, 112(%r15)
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 @llvm.eh.sjlj.setjmp(ptr nonnull @buf)
ret void
}

define void @foo1() "backchain" {
; CHECK-LABEL: foo1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: stmg %r6, %r15, 48(%r15)
; CHECK-NEXT: .cfi_offset %r6, -112
; CHECK-NEXT: .cfi_offset %r7, -104
; CHECK-NEXT: .cfi_offset %r8, -96
; CHECK-NEXT: .cfi_offset %r9, -88
; CHECK-NEXT: .cfi_offset %r10, -80
; CHECK-NEXT: .cfi_offset %r11, -72
; CHECK-NEXT: .cfi_offset %r12, -64
; CHECK-NEXT: .cfi_offset %r13, -56
; CHECK-NEXT: .cfi_offset %r14, -48
; CHECK-NEXT: .cfi_offset %r15, -40
; CHECK-NEXT: lgr %r1, %r15
; CHECK-NEXT: aghi %r15, -64
; CHECK-NEXT: .cfi_def_cfa_offset 224
; CHECK-NEXT: stg %r1, 0(%r15)
; CHECK-NEXT: std %f8, 56(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f9, 48(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f10, 40(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f11, 32(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f12, 24(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f13, 16(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f14, 8(%r15) # 8-byte Folded Spill
; CHECK-NEXT: std %f15, 0(%r15) # 8-byte Folded Spill
; CHECK-NEXT: .cfi_offset %f8, -168
; CHECK-NEXT: .cfi_offset %f9, -176
; CHECK-NEXT: .cfi_offset %f10, -184
; CHECK-NEXT: .cfi_offset %f11, -192
; CHECK-NEXT: .cfi_offset %f12, -200
; CHECK-NEXT: .cfi_offset %f13, -208
; CHECK-NEXT: .cfi_offset %f14, -216
; CHECK-NEXT: .cfi_offset %f15, -224
; CHECK-NEXT: lgrl %r1, buf@GOT
; CHECK-NEXT: larl %r0, .LBB1_1
; CHECK-NEXT: stg %r0, 8(%r1)
; CHECK-NEXT: stg %r15, 24(%r1)
; CHECK-NEXT: lg %r0, 0(%r15)
; CHECK-NEXT: stg %r0, 16(%r1)
; CHECK-NEXT: .LBB1_1: # Block address taken
; CHECK-NEXT: # %entry
; CHECK-NEXT: .LBB1_2: # %entry
; CHECK-NEXT: ld %f8, 56(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f9, 48(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f10, 40(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f11, 32(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f12, 24(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f13, 16(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f14, 8(%r15) # 8-byte Folded Reload
; CHECK-NEXT: ld %f15, 0(%r15) # 8-byte Folded Reload
; CHECK-NEXT: lmg %r6, %r15, 112(%r15)
; CHECK-NEXT: br %r14
entry:
%0 = tail call i32 @llvm.eh.sjlj.setjmp(ptr nonnull @buf)
ret void
}