|
|
@@ -0,0 +1,352 @@ |
|
|
; Test transactional-execution intrinsics. |
|
|
; |
|
|
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s |
|
|
|
|
|
declare i32 @llvm.s390.tbegin(i8 *, i32) |
|
|
declare i32 @llvm.s390.tbegin.nofloat(i8 *, i32) |
|
|
declare void @llvm.s390.tbeginc(i8 *, i32) |
|
|
declare i32 @llvm.s390.tend() |
|
|
declare void @llvm.s390.tabort(i64) |
|
|
declare void @llvm.s390.ntstg(i64, i64 *) |
|
|
declare i32 @llvm.s390.etnd() |
|
|
declare void @llvm.s390.ppa.txassist(i32) |
|
|
|
|
|
; TBEGIN. |
|
|
define void @test_tbegin() { |
|
|
; CHECK-LABEL: test_tbegin: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK: std %f8, |
|
|
; CHECK: std %f9, |
|
|
; CHECK: std %f10, |
|
|
; CHECK: std %f11, |
|
|
; CHECK: std %f12, |
|
|
; CHECK: std %f13, |
|
|
; CHECK: std %f14, |
|
|
; CHECK: std %f15, |
|
|
; CHECK: tbegin 0, 65292 |
|
|
; CHECK: ld %f8, |
|
|
; CHECK: ld %f9, |
|
|
; CHECK: ld %f10, |
|
|
; CHECK: ld %f11, |
|
|
; CHECK: ld %f12, |
|
|
; CHECK: ld %f13, |
|
|
; CHECK: ld %f14, |
|
|
; CHECK: ld %f15, |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin(i8 *null, i32 65292) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat). |
|
|
define void @test_tbegin_nofloat1() { |
|
|
; CHECK-LABEL: test_tbegin_nofloat1: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 65292 |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with integer CC return value. |
|
|
define i32 @test_tbegin_nofloat2() { |
|
|
; CHECK-LABEL: test_tbegin_nofloat2: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 65292 |
|
|
; CHECK: ipm %r2 |
|
|
; CHECK: srl %r2, 28 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) |
|
|
ret i32 %res |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with implicit CC check. |
|
|
define void @test_tbegin_nofloat3(i32 *%ptr) { |
|
|
; CHECK-LABEL: test_tbegin_nofloat3: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 65292 |
|
|
; CHECK: jnh {{\.L*}} |
|
|
; CHECK: mvhi 0(%r2), 0 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) |
|
|
%cmp = icmp eq i32 %res, 2 |
|
|
br i1 %cmp, label %if.then, label %if.end |
|
|
|
|
|
if.then: ; preds = %entry |
|
|
store i32 0, i32* %ptr, align 4 |
|
|
br label %if.end |
|
|
|
|
|
if.end: ; preds = %if.then, %entry |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with dual CC use. |
|
|
define i32 @test_tbegin_nofloat4(i32 %pad, i32 *%ptr) { |
|
|
; CHECK-LABEL: test_tbegin_nofloat4: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 65292 |
|
|
; CHECK: ipm %r2 |
|
|
; CHECK: srl %r2, 28 |
|
|
; CHECK: cijlh %r2, 2, {{\.L*}} |
|
|
; CHECK: mvhi 0(%r3), 0 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) |
|
|
%cmp = icmp eq i32 %res, 2 |
|
|
br i1 %cmp, label %if.then, label %if.end |
|
|
|
|
|
if.then: ; preds = %entry |
|
|
store i32 0, i32* %ptr, align 4 |
|
|
br label %if.end |
|
|
|
|
|
if.end: ; preds = %if.then, %entry |
|
|
ret i32 %res |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with register. |
|
|
define void @test_tbegin_nofloat5(i8 *%ptr) { |
|
|
; CHECK-LABEL: test_tbegin_nofloat5: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0(%r2), 65292 |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *%ptr, i32 65292) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with GRSM 0x0f00. |
|
|
define void @test_tbegin_nofloat6() { |
|
|
; CHECK-LABEL: test_tbegin_nofloat6: |
|
|
; CHECK: stmg %r6, %r15, |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 3840 |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 3840) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with GRSM 0xf100. |
|
|
define void @test_tbegin_nofloat7() { |
|
|
; CHECK-LABEL: test_tbegin_nofloat7: |
|
|
; CHECK: stmg %r8, %r15, |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 61696 |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 61696) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with GRSM 0xfe00 -- stack pointer added automatically. |
|
|
define void @test_tbegin_nofloat8() { |
|
|
; CHECK-LABEL: test_tbegin_nofloat8: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 65280 |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65024) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with GRSM 0xfb00 -- no frame pointer needed. |
|
|
define void @test_tbegin_nofloat9() { |
|
|
; CHECK-LABEL: test_tbegin_nofloat9: |
|
|
; CHECK: stmg %r10, %r15, |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 64256 |
|
|
; CHECK: br %r14 |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGIN (nofloat) with GRSM 0xfb00 -- frame pointer added automatically. |
|
|
define void @test_tbegin_nofloat10(i64 %n) { |
|
|
; CHECK-LABEL: test_tbegin_nofloat10: |
|
|
; CHECK: stmg %r11, %r15, |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbegin 0, 65280 |
|
|
; CHECK: br %r14 |
|
|
%buf = alloca i8, i64 %n |
|
|
call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TBEGINC. |
|
|
define void @test_tbeginc() { |
|
|
; CHECK-LABEL: test_tbeginc: |
|
|
; CHECK-NOT: stmg |
|
|
; CHECK-NOT: std |
|
|
; CHECK: tbeginc 0, 65288 |
|
|
; CHECK: br %r14 |
|
|
call void @llvm.s390.tbeginc(i8 *null, i32 65288) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TEND with integer CC return value. |
|
|
define i32 @test_tend1() { |
|
|
; CHECK-LABEL: test_tend1: |
|
|
; CHECK: tend |
|
|
; CHECK: ipm %r2 |
|
|
; CHECK: srl %r2, 28 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.tend() |
|
|
ret i32 %res |
|
|
} |
|
|
|
|
|
; TEND with implicit CC check. |
|
|
define void @test_tend3(i32 *%ptr) { |
|
|
; CHECK-LABEL: test_tend3: |
|
|
; CHECK: tend |
|
|
; CHECK: je {{\.L*}} |
|
|
; CHECK: mvhi 0(%r2), 0 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.tend() |
|
|
%cmp = icmp eq i32 %res, 2 |
|
|
br i1 %cmp, label %if.then, label %if.end |
|
|
|
|
|
if.then: ; preds = %entry |
|
|
store i32 0, i32* %ptr, align 4 |
|
|
br label %if.end |
|
|
|
|
|
if.end: ; preds = %if.then, %entry |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TEND with dual CC use. |
|
|
define i32 @test_tend2(i32 %pad, i32 *%ptr) { |
|
|
; CHECK-LABEL: test_tend2: |
|
|
; CHECK: tend |
|
|
; CHECK: ipm %r2 |
|
|
; CHECK: srl %r2, 28 |
|
|
; CHECK: cijlh %r2, 2, {{\.L*}} |
|
|
; CHECK: mvhi 0(%r3), 0 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.tend() |
|
|
%cmp = icmp eq i32 %res, 2 |
|
|
br i1 %cmp, label %if.then, label %if.end |
|
|
|
|
|
if.then: ; preds = %entry |
|
|
store i32 0, i32* %ptr, align 4 |
|
|
br label %if.end |
|
|
|
|
|
if.end: ; preds = %if.then, %entry |
|
|
ret i32 %res |
|
|
} |
|
|
|
|
|
; TABORT with register only. |
|
|
define void @test_tabort1(i64 %val) { |
|
|
; CHECK-LABEL: test_tabort1: |
|
|
; CHECK: tabort 0(%r2) |
|
|
; CHECK: br %r14 |
|
|
call void @llvm.s390.tabort(i64 %val) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TABORT with immediate only. |
|
|
define void @test_tabort2(i64 %val) { |
|
|
; CHECK-LABEL: test_tabort2: |
|
|
; CHECK: tabort 1234 |
|
|
; CHECK: br %r14 |
|
|
call void @llvm.s390.tabort(i64 1234) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TABORT with register + immediate. |
|
|
define void @test_tabort3(i64 %val) { |
|
|
; CHECK-LABEL: test_tabort3: |
|
|
; CHECK: tabort 1234(%r2) |
|
|
; CHECK: br %r14 |
|
|
%sum = add i64 %val, 1234 |
|
|
call void @llvm.s390.tabort(i64 %sum) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; TABORT with out-of-range immediate. |
|
|
define void @test_tabort4(i64 %val) { |
|
|
; CHECK-LABEL: test_tabort4: |
|
|
; CHECK: tabort 0({{%r[1-5]}}) |
|
|
; CHECK: br %r14 |
|
|
call void @llvm.s390.tabort(i64 4096) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; NTSTG with base pointer only. |
|
|
define void @test_ntstg1(i64 *%ptr, i64 %val) { |
|
|
; CHECK-LABEL: test_ntstg1: |
|
|
; CHECK: ntstg %r3, 0(%r2) |
|
|
; CHECK: br %r14 |
|
|
call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; NTSTG with base and index. |
|
|
; Check that VSTL doesn't allow an index. |
|
|
define void @test_ntstg2(i64 *%base, i64 %index, i64 %val) { |
|
|
; CHECK-LABEL: test_ntstg2: |
|
|
; CHECK: sllg [[REG:%r[1-5]]], %r3, 3 |
|
|
; CHECK: ntstg %r4, 0([[REG]],%r2) |
|
|
; CHECK: br %r14 |
|
|
%ptr = getelementptr i64, i64 *%base, i64 %index |
|
|
call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; NTSTG with the highest in-range displacement. |
|
|
define void @test_ntstg3(i64 *%base, i64 %val) { |
|
|
; CHECK-LABEL: test_ntstg3: |
|
|
; CHECK: ntstg %r3, 524280(%r2) |
|
|
; CHECK: br %r14 |
|
|
%ptr = getelementptr i64, i64 *%base, i64 65535 |
|
|
call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; NTSTG with an out-of-range positive displacement. |
|
|
define void @test_ntstg4(i64 *%base, i64 %val) { |
|
|
; CHECK-LABEL: test_ntstg4: |
|
|
; CHECK: ntstg %r3, 0({{%r[1-5]}}) |
|
|
; CHECK: br %r14 |
|
|
%ptr = getelementptr i64, i64 *%base, i64 65536 |
|
|
call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; NTSTG with the lowest in-range displacement. |
|
|
define void @test_ntstg5(i64 *%base, i64 %val) { |
|
|
; CHECK-LABEL: test_ntstg5: |
|
|
; CHECK: ntstg %r3, -524288(%r2) |
|
|
; CHECK: br %r14 |
|
|
%ptr = getelementptr i64, i64 *%base, i64 -65536 |
|
|
call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; NTSTG with an out-of-range negative displacement. |
|
|
define void @test_ntstg6(i64 *%base, i64 %val) { |
|
|
; CHECK-LABEL: test_ntstg6: |
|
|
; CHECK: ntstg %r3, 0({{%r[1-5]}}) |
|
|
; CHECK: br %r14 |
|
|
%ptr = getelementptr i64, i64 *%base, i64 -65537 |
|
|
call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) |
|
|
ret void |
|
|
} |
|
|
|
|
|
; ETND. |
|
|
define i32 @test_etnd() { |
|
|
; CHECK-LABEL: test_etnd: |
|
|
; CHECK: etnd %r2 |
|
|
; CHECK: br %r14 |
|
|
%res = call i32 @llvm.s390.etnd() |
|
|
ret i32 %res |
|
|
} |
|
|
|
|
|
; PPA (Transaction-Abort Assist) |
|
|
define void @test_ppa_txassist(i32 %val) { |
|
|
; CHECK-LABEL: test_ppa_txassist: |
|
|
; CHECK: ppa %r2, 0, 1 |
|
|
; CHECK: br %r14 |
|
|
call void @llvm.s390.ppa.txassist(i32 %val) |
|
|
ret void |
|
|
} |
|
|
|