1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-23 21:13:02 +02:00
llvm-mirror/test/CodeGen/AArch64/f16-convert.ll
Ahmed Bougacha 88db0c3c30 [CodeGen] Don't blindly combine (fp_round (fp_round x)) to (fp_round x).
We used to do this DAG combine, but it's not always correct:
If the first fp_round isn't a value preserving truncation, it might
introduce a tie in the second fp_round, that wouldn't occur in the
single-step fp_round we want to fold to.
In other words, double rounding isn't the same as rounding.

Differential Revision: http://reviews.llvm.org/D7571

llvm-svn: 228911
2015-02-12 06:15:29 +00:00

257 lines
7.4 KiB
LLVM

; RUN: llc < %s -mtriple=arm64-apple-ios -asm-verbose=false | FileCheck %s
define float @load0(i16* nocapture readonly %a) nounwind {
; CHECK-LABEL: load0:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0]
; CHECK-NEXT: fcvt s0, [[HREG]]
; CHECK-NEXT: ret
%tmp = load i16* %a, align 2
%tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
ret float %tmp1
}
define double @load1(i16* nocapture readonly %a) nounwind {
; CHECK-LABEL: load1:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0]
; CHECK-NEXT: fcvt d0, [[HREG]]
; CHECK-NEXT: ret
%tmp = load i16* %a, align 2
%conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
ret double %conv
}
define float @load2(i16* nocapture readonly %a, i32 %i) nounwind {
; CHECK-LABEL: load2:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1]
; CHECK-NEXT: fcvt s0, [[HREG]]
; CHECK-NEXT: ret
%idxprom = sext i32 %i to i64
%arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
%tmp = load i16* %arrayidx, align 2
%tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
ret float %tmp1
}
define double @load3(i16* nocapture readonly %a, i32 %i) nounwind {
; CHECK-LABEL: load3:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1]
; CHECK-NEXT: fcvt d0, [[HREG]]
; CHECK-NEXT: ret
%idxprom = sext i32 %i to i64
%arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
%tmp = load i16* %arrayidx, align 2
%conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
ret double %conv
}
define float @load4(i16* nocapture readonly %a, i64 %i) nounwind {
; CHECK-LABEL: load4:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1]
; CHECK-NEXT: fcvt s0, [[HREG]]
; CHECK-NEXT: ret
%arrayidx = getelementptr inbounds i16* %a, i64 %i
%tmp = load i16* %arrayidx, align 2
%tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
ret float %tmp1
}
define double @load5(i16* nocapture readonly %a, i64 %i) nounwind {
; CHECK-LABEL: load5:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1]
; CHECK-NEXT: fcvt d0, [[HREG]]
; CHECK-NEXT: ret
%arrayidx = getelementptr inbounds i16* %a, i64 %i
%tmp = load i16* %arrayidx, align 2
%conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
ret double %conv
}
define float @load6(i16* nocapture readonly %a) nounwind {
; CHECK-LABEL: load6:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20]
; CHECK-NEXT: fcvt s0, [[HREG]]
; CHECK-NEXT: ret
%arrayidx = getelementptr inbounds i16* %a, i64 10
%tmp = load i16* %arrayidx, align 2
%tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
ret float %tmp1
}
define double @load7(i16* nocapture readonly %a) nounwind {
; CHECK-LABEL: load7:
; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20]
; CHECK-NEXT: fcvt d0, [[HREG]]
; CHECK-NEXT: ret
%arrayidx = getelementptr inbounds i16* %a, i64 10
%tmp = load i16* %arrayidx, align 2
%conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
ret double %conv
}
define float @load8(i16* nocapture readonly %a) nounwind {
; CHECK-LABEL: load8:
; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20]
; CHECK-NEXT: fcvt s0, [[HREG]]
; CHECK-NEXT: ret
%arrayidx = getelementptr inbounds i16* %a, i64 -10
%tmp = load i16* %arrayidx, align 2
%tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
ret float %tmp1
}
define double @load9(i16* nocapture readonly %a) nounwind {
; CHECK-LABEL: load9:
; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20]
; CHECK-NEXT: fcvt d0, [[HREG]]
; CHECK-NEXT: ret
%arrayidx = getelementptr inbounds i16* %a, i64 -10
%tmp = load i16* %arrayidx, align 2
%conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
ret double %conv
}
define void @store0(i16* nocapture %a, float %val) nounwind {
; CHECK-LABEL: store0:
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0]
; CHECK-NEXT: ret
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
store i16 %tmp, i16* %a, align 2
ret void
}
define void @store1(i16* nocapture %a, double %val) nounwind {
; CHECK-LABEL: store1:
; CHECK-NEXT: fcvt s0, d0
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0]
; CHECK-NEXT: ret
%conv = fptrunc double %val to float
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
store i16 %tmp, i16* %a, align 2
ret void
}
define void @store2(i16* nocapture %a, i32 %i, float %val) nounwind {
; CHECK-LABEL: store2:
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0, w1, sxtw #1]
; CHECK-NEXT: ret
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
%idxprom = sext i32 %i to i64
%arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store3(i16* nocapture %a, i32 %i, double %val) nounwind {
; CHECK-LABEL: store3:
; CHECK-NEXT: fcvt s0, d0
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0, w1, sxtw #1]
; CHECK-NEXT: ret
%conv = fptrunc double %val to float
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
%idxprom = sext i32 %i to i64
%arrayidx = getelementptr inbounds i16* %a, i64 %idxprom
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store4(i16* nocapture %a, i64 %i, float %val) nounwind {
; CHECK-LABEL: store4:
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0, x1, lsl #1]
; CHECK-NEXT: ret
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
%arrayidx = getelementptr inbounds i16* %a, i64 %i
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store5(i16* nocapture %a, i64 %i, double %val) nounwind {
; CHECK-LABEL: store5:
; CHECK-NEXT: fcvt s0, d0
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0, x1, lsl #1]
; CHECK-NEXT: ret
%conv = fptrunc double %val to float
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
%arrayidx = getelementptr inbounds i16* %a, i64 %i
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store6(i16* nocapture %a, float %val) nounwind {
; CHECK-LABEL: store6:
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0, #20]
; CHECK-NEXT: ret
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
%arrayidx = getelementptr inbounds i16* %a, i64 10
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store7(i16* nocapture %a, double %val) nounwind {
; CHECK-LABEL: store7:
; CHECK-NEXT: fcvt s0, d0
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: str h0, [x0, #20]
; CHECK-NEXT: ret
%conv = fptrunc double %val to float
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
%arrayidx = getelementptr inbounds i16* %a, i64 10
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store8(i16* nocapture %a, float %val) nounwind {
; CHECK-LABEL: store8:
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: stur h0, [x0, #-20]
; CHECK-NEXT: ret
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
%arrayidx = getelementptr inbounds i16* %a, i64 -10
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
define void @store9(i16* nocapture %a, double %val) nounwind {
; CHECK-LABEL: store9:
; CHECK-NEXT: fcvt s0, d0
; CHECK-NEXT: fcvt h0, s0
; CHECK-NEXT: stur h0, [x0, #-20]
; CHECK-NEXT: ret
%conv = fptrunc double %val to float
%tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
%arrayidx = getelementptr inbounds i16* %a, i64 -10
store i16 %tmp, i16* %arrayidx, align 2
ret void
}
declare i16 @llvm.convert.to.fp16.f32(float) nounwind readnone
declare float @llvm.convert.from.fp16.f32(i16) nounwind readnone
declare i16 @llvm.convert.to.fp16.f64(double) nounwind readnone
declare double @llvm.convert.from.fp16.f64(i16) nounwind readnone