353 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; 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: bnhr %r14
 | 
						|
; 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: ciblh %r2, 2, 0(%r14)
 | 
						|
; 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: ber %r14
 | 
						|
; 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: ciblh %r2, 2, 0(%r14)
 | 
						|
; 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
 | 
						|
}
 | 
						|
 |