
Stores can be issued faster if the result is kept in the SIMD/FP registers. The `HasOneUse` guards against creating two floating point conversions, if for example there's some arithmetic done on the converted value as well. Another approach would be to inspect the user instructions during lowering, but I don't see that type of check in the lowering too often.
132 lines
3.1 KiB
LLVM
132 lines
3.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: llc -verify-machineinstrs -mtriple=aarch64 < %s | FileCheck %s
|
|
|
|
define void @f32_to_u8(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_u8:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzu s0, s0
|
|
; CHECK-NEXT: str b0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptoui float %f to i32
|
|
%trunc = trunc i32 %conv to i8
|
|
store i8 %trunc, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f32_to_s8(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_s8:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzs s0, s0
|
|
; CHECK-NEXT: str b0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi float %f to i32
|
|
%trunc = trunc i32 %conv to i8
|
|
store i8 %trunc, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f32_to_u16(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_u16:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzu s0, s0
|
|
; CHECK-NEXT: str h0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptoui float %f to i32
|
|
%trunc = trunc i32 %conv to i16
|
|
store i16 %trunc, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f32_to_s16(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_s16:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzs s0, s0
|
|
; CHECK-NEXT: str h0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi float %f to i32
|
|
%trunc = trunc i32 %conv to i16
|
|
store i16 %trunc, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f32_to_u32(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_u32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzu s0, s0
|
|
; CHECK-NEXT: str s0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptoui float %f to i32
|
|
store i32 %conv, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f32_to_s32(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_s32:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzs s0, s0
|
|
; CHECK-NEXT: str s0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi float %f to i32
|
|
store i32 %conv, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f32_to_s64(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_s64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzs w8, s0
|
|
; CHECK-NEXT: sxtw x8, w8
|
|
; CHECK-NEXT: str x8, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi float %f to i32
|
|
%ext = sext i32 %conv to i64
|
|
store i64 %ext, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f64_to_u64(double %d, ptr %dst) {
|
|
; CHECK-LABEL: f64_to_u64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzu d0, d0
|
|
; CHECK-NEXT: str d0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptoui double %d to i64
|
|
store i64 %conv, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define void @f64_to_s64(double %d, ptr %dst) {
|
|
; CHECK-LABEL: f64_to_s64:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzs d0, d0
|
|
; CHECK-NEXT: str d0, [x0]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi double %d to i64
|
|
store i64 %conv, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
define i32 @f32_to_i32_multiple_uses(float %f, ptr %dst) {
|
|
; CHECK-LABEL: f32_to_i32_multiple_uses:
|
|
; CHECK: // %bb.0: // %entry
|
|
; CHECK-NEXT: fcvtzs w8, s0
|
|
; CHECK-NEXT: mov x9, x0
|
|
; CHECK-NEXT: mov w0, w8
|
|
; CHECK-NEXT: strb w8, [x9]
|
|
; CHECK-NEXT: ret
|
|
entry:
|
|
%conv = fptosi float %f to i32
|
|
%trunc = trunc i32 %conv to i8
|
|
store i8 %trunc, ptr %dst
|
|
ret i32 %conv
|
|
}
|