416 lines
10 KiB
LLVM
416 lines
10 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
|
|
; Test 128-bit arithmetic in vector registers on z13
|
|
;
|
|
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s
|
|
|
|
; Sign extension from i64.
|
|
define i128 @f1(i64 %a) {
|
|
; CHECK-LABEL: f1:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: srag %r0, %r3, 63
|
|
; CHECK-NEXT: vlvgp %v0, %r0, %r3
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = sext i64 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Sign extension from i64 from memory.
|
|
define i128 @f2(ptr %ptr) {
|
|
; CHECK-LABEL: f2:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vlrepg %v0, 0(%r3)
|
|
; CHECK-NEXT: vrepib %v1, 64
|
|
; CHECK-NEXT: vsrab %v0, %v0, %v1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i64, ptr %ptr
|
|
%res = sext i64 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i64.
|
|
define i128 @f3(i64 %a) {
|
|
; CHECK-LABEL: f3:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vlvgg %v0, %r3, 1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = zext i64 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i64 from memory.
|
|
define i128 @f4(ptr %ptr) {
|
|
; CHECK-LABEL: f4:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vleg %v0, 0(%r3), 1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i64, ptr %ptr
|
|
%res = zext i64 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Truncation to i64.
|
|
define i64 @f5(i128 %a) {
|
|
; CHECK-LABEL: f5:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r2), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vlgvg %r2, %v0, 1
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i64
|
|
ret i64 %res
|
|
}
|
|
|
|
; Truncation to i64 in memory.
|
|
define void @f6(ptr %ptr, i128 %a) {
|
|
; CHECK-LABEL: f6:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r3), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vsteg %v0, 0(%r2), 1
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i64
|
|
store i64 %res, ptr %ptr
|
|
ret void
|
|
}
|
|
|
|
; Sign extension from i32.
|
|
define i128 @f7(i32 %a) {
|
|
; CHECK-LABEL: f7:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: lgfr %r0, %r3
|
|
; CHECK-NEXT: srag %r1, %r0, 63
|
|
; CHECK-NEXT: vlvgp %v0, %r1, %r0
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = sext i32 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Sign extension from i32 from memory.
|
|
define i128 @f8(ptr %ptr) {
|
|
; CHECK-LABEL: f8:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vlrepf %v0, 0(%r3)
|
|
; CHECK-NEXT: vrepib %v1, 96
|
|
; CHECK-NEXT: vsrab %v0, %v0, %v1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i32, ptr %ptr
|
|
%res = sext i32 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i32.
|
|
define i128 @f9(i32 %a) {
|
|
; CHECK-LABEL: f9:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vlvgf %v0, %r3, 3
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = zext i32 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i32 from memory.
|
|
define i128 @f10(ptr %ptr) {
|
|
; CHECK-LABEL: f10:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vlef %v0, 0(%r3), 3
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i32, ptr %ptr
|
|
%res = zext i32 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Truncation to i32.
|
|
define i32 @f11(i128 %a) {
|
|
; CHECK-LABEL: f11:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r2), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vlgvf %r2, %v0, 3
|
|
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i32
|
|
ret i32 %res
|
|
}
|
|
|
|
; Truncation to i32 in memory.
|
|
define void @f12(ptr %ptr, i128 %a) {
|
|
; CHECK-LABEL: f12:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r3), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vstef %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i32
|
|
store i32 %res, ptr %ptr
|
|
ret void
|
|
}
|
|
|
|
; Sign extension from i16.
|
|
define i128 @f13(i16 %a) {
|
|
; CHECK-LABEL: f13:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: # kill: def $r3l killed $r3l def $r3d
|
|
; CHECK-NEXT: lghr %r0, %r3
|
|
; CHECK-NEXT: srag %r1, %r0, 63
|
|
; CHECK-NEXT: vlvgp %v0, %r1, %r0
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = sext i16 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Sign extension from i16 from memory.
|
|
define i128 @f14(ptr %ptr) {
|
|
; CHECK-LABEL: f14:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vlreph %v0, 0(%r3)
|
|
; CHECK-NEXT: vrepib %v1, 112
|
|
; CHECK-NEXT: vsrab %v0, %v0, %v1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i16, ptr %ptr
|
|
%res = sext i16 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i16.
|
|
define i128 @f15(i16 %a) {
|
|
; CHECK-LABEL: f15:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vlvgh %v0, %r3, 7
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = zext i16 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i16 from memory.
|
|
define i128 @f16(ptr %ptr) {
|
|
; CHECK-LABEL: f16:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vleh %v0, 0(%r3), 7
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i16, ptr %ptr
|
|
%res = zext i16 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Truncation to i16.
|
|
define i16 @f17(i128 %a) {
|
|
; CHECK-LABEL: f17:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r2), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vlgvf %r2, %v0, 3
|
|
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i16
|
|
ret i16 %res
|
|
}
|
|
|
|
; Truncation to i16 in memory.
|
|
define void @f18(ptr %ptr, i128 %a) {
|
|
; CHECK-LABEL: f18:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r3), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vsteh %v0, 0(%r2), 7
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i16
|
|
store i16 %res, ptr %ptr
|
|
ret void
|
|
}
|
|
|
|
; Sign extension from i8.
|
|
define i128 @f19(i8 %a) {
|
|
; CHECK-LABEL: f19:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: # kill: def $r3l killed $r3l def $r3d
|
|
; CHECK-NEXT: lgbr %r0, %r3
|
|
; CHECK-NEXT: srag %r1, %r0, 63
|
|
; CHECK-NEXT: vlvgp %v0, %r1, %r0
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = sext i8 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Sign extension from i8 from memory.
|
|
define i128 @f20(ptr %ptr) {
|
|
; CHECK-LABEL: f20:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vlrepb %v0, 0(%r3)
|
|
; CHECK-NEXT: vrepib %v1, 120
|
|
; CHECK-NEXT: vsrab %v0, %v0, %v1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i8, ptr %ptr
|
|
%res = sext i8 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i8.
|
|
define i128 @f21(i8 %a) {
|
|
; CHECK-LABEL: f21:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vlvgb %v0, %r3, 15
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = zext i8 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i8 from memory.
|
|
define i128 @f22(ptr %ptr) {
|
|
; CHECK-LABEL: f22:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vleb %v0, 0(%r3), 15
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i8, ptr %ptr
|
|
%res = zext i8 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Truncation to i8.
|
|
define i8 @f23(i128 %a) {
|
|
; CHECK-LABEL: f23:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r2), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vlgvf %r2, %v0, 3
|
|
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i8
|
|
ret i8 %res
|
|
}
|
|
|
|
; Truncation to i8 in memory.
|
|
define void @f24(ptr %ptr, i128 %a) {
|
|
; CHECK-LABEL: f24:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r3), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vsteb %v0, 0(%r2), 15
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i8
|
|
store i8 %res, ptr %ptr
|
|
ret void
|
|
}
|
|
|
|
; Sign extension from i1.
|
|
define i128 @f25(i1 %a) {
|
|
; CHECK-LABEL: f25:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: larl %r1, .LCPI24_0
|
|
; CHECK-NEXT: vl %v1, 0(%r1), 3
|
|
; CHECK-NEXT: vlvgp %v0, %r3, %r3
|
|
; CHECK-NEXT: vn %v0, %v0, %v1
|
|
; CHECK-NEXT: vgbm %v1, 0
|
|
; CHECK-NEXT: vsq %v0, %v1, %v0
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = sext i1 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Sign extension from i1 from memory.
|
|
define i128 @f26(ptr %ptr) {
|
|
; CHECK-LABEL: f26:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v1, 0
|
|
; CHECK-NEXT: vleb %v1, 0(%r3), 15
|
|
; CHECK-NEXT: larl %r1, .LCPI25_0
|
|
; CHECK-NEXT: vl %v2, 0(%r1), 3
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vn %v1, %v1, %v2
|
|
; CHECK-NEXT: vsq %v0, %v0, %v1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i1, ptr %ptr
|
|
%res = sext i1 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i1.
|
|
define i128 @f27(i1 %a) {
|
|
; CHECK-LABEL: f27:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: larl %r1, .LCPI26_0
|
|
; CHECK-NEXT: vl %v1, 0(%r1), 3
|
|
; CHECK-NEXT: vlvgp %v0, %r3, %r3
|
|
; CHECK-NEXT: vn %v0, %v0, %v1
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%res = zext i1 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Zero extension from i1 from memory.
|
|
define i128 @f28(ptr %ptr) {
|
|
; CHECK-LABEL: f28:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vgbm %v0, 0
|
|
; CHECK-NEXT: vleb %v0, 0(%r3), 15
|
|
; CHECK-NEXT: vst %v0, 0(%r2), 3
|
|
; CHECK-NEXT: br %r14
|
|
%a = load i1, ptr %ptr
|
|
%res = zext i1 %a to i128
|
|
ret i128 %res
|
|
}
|
|
|
|
; Truncation to i1.
|
|
define i1 @f29(i128 %a) {
|
|
; CHECK-LABEL: f29:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r2), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vlgvf %r2, %v0, 3
|
|
; CHECK-NEXT: # kill: def $r2l killed $r2l killed $r2d
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i1
|
|
ret i1 %res
|
|
}
|
|
|
|
; Truncation to i1 in memory.
|
|
define void @f30(ptr %ptr, i128 %a) {
|
|
; CHECK-LABEL: f30:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: vl %v0, 0(%r3), 3
|
|
; CHECK-NEXT: larl %r1, .LCPI29_0
|
|
; CHECK-NEXT: vl %v1, 0(%r1), 3
|
|
; CHECK-NEXT: vaq %v0, %v0, %v0
|
|
; CHECK-NEXT: vn %v0, %v0, %v1
|
|
; CHECK-NEXT: vsteb %v0, 0(%r2), 15
|
|
; CHECK-NEXT: br %r14
|
|
%op = add i128 %a, %a
|
|
%res = trunc i128 %op to i1
|
|
store i1 %res, ptr %ptr
|
|
ret void
|
|
}
|