This was originally committed at rL328921 and reverted at rL329920 to
investigate failures in Chrome. This time I've added to the ReleaseNotes
to warn users of the potential of exposing UB and let me repeat that
here for more exposure:
Optimization of floating-point casts is improved. This may cause surprising
results for code that is relying on undefined behavior. Code sanitizers can
be used to detect affected patterns such as this:
int main() {
float x = 4294967296.0f;
x = (float)((int)x);
printf("junk in the ftrunc: %f\n", x);
return 0;
}
$ clang -O1 ftrunc.c -fsanitize=undefined ; ./a.out
ftrunc.c:5:15: runtime error: 4.29497e+09 is outside the range of
representable values of type 'int'
junk in the ftrunc: 0.000000
Original commit message:
fptosi / fptoui round towards zero, and that's the same behavior as ISD::FTRUNC,
so replace a pair of casts with the equivalent node. We don't have to account for
special cases (NaN, INF) because out-of-range casts are undefined.
Differential Revision: https://reviews.llvm.org/D44909
llvm-svn: 330437
44 lines
1.1 KiB
LLVM
44 lines
1.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s
|
|
|
|
define float @trunc_unsigned_f32(float %x) {
|
|
; CHECK-LABEL: trunc_unsigned_f32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: frintz s0, s0
|
|
; CHECK-NEXT: ret
|
|
%i = fptoui float %x to i32
|
|
%r = uitofp i32 %i to float
|
|
ret float %r
|
|
}
|
|
|
|
define double @trunc_unsigned_f64(double %x) {
|
|
; CHECK-LABEL: trunc_unsigned_f64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: frintz d0, d0
|
|
; CHECK-NEXT: ret
|
|
%i = fptoui double %x to i64
|
|
%r = uitofp i64 %i to double
|
|
ret double %r
|
|
}
|
|
|
|
define float @trunc_signed_f32(float %x) {
|
|
; CHECK-LABEL: trunc_signed_f32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: frintz s0, s0
|
|
; CHECK-NEXT: ret
|
|
%i = fptosi float %x to i32
|
|
%r = sitofp i32 %i to float
|
|
ret float %r
|
|
}
|
|
|
|
define double @trunc_signed_f64(double %x) {
|
|
; CHECK-LABEL: trunc_signed_f64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: frintz d0, d0
|
|
; CHECK-NEXT: ret
|
|
%i = fptosi double %x to i64
|
|
%r = sitofp i64 %i to double
|
|
ret double %r
|
|
}
|
|
|