Skip to content

Commit 878b7b8

Browse files
papparapajacobly0
authored andcommitted
libc: Prevent FCSEL instruction from being used to avoid raising an unintended exception
If you write an if expression in mem.doNotOptimizeAway like doNotOptimizeAway(if (ix < 0x00100000) x / 0x1p120 else x + 0x1p120);, FCSEL instruction is used on AArch64. FCSEL instruction selects one of the two registers according to the condition and copies its value. In this example, `x / 0x1p120` and `x + 0x1p120` are expressions that raise different floating-point exceptions. However, since both are actually evaluated before the FCSEL instruction, the exception not intended by the programmer may also be raised. To prevent FCSEL instruction from being used here, this commit splits doNotOptimizeAway in two.
1 parent 3ce8d19 commit 878b7b8

File tree

3 files changed

+42
-6
lines changed

3 files changed

+42
-6
lines changed

lib/compiler_rt/sin.zig

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ pub fn sinf(x: f32) callconv(.c) f32 {
4949
if (ix <= 0x3f490fda) { // |x| ~<= pi/4
5050
if (ix < 0x39800000) { // |x| < 2**-12
5151
// raise inexact if x!=0 and underflow if subnormal
52-
if (common.want_float_exceptions) mem.doNotOptimizeAway(if (ix < 0x00800000) x / 0x1p120 else x + 0x1p120);
52+
if (common.want_float_exceptions) {
53+
if (ix < 0x00800000) {
54+
mem.doNotOptimizeAway(x / 0x1p120);
55+
} else {
56+
mem.doNotOptimizeAway(x + 0x1p120);
57+
}
58+
}
5359
return x;
5460
}
5561
return trig.__sindf(x);
@@ -98,7 +104,13 @@ pub fn sin(x: f64) callconv(.c) f64 {
98104
if (ix <= 0x3fe921fb) {
99105
if (ix < 0x3e500000) { // |x| < 2**-26
100106
// raise inexact if x != 0 and underflow if subnormal
101-
if (common.want_float_exceptions) mem.doNotOptimizeAway(if (ix < 0x00100000) x / 0x1p120 else x + 0x1p120);
107+
if (common.want_float_exceptions) {
108+
if (ix < 0x00100000) {
109+
mem.doNotOptimizeAway(x / 0x1p120);
110+
} else {
111+
mem.doNotOptimizeAway(x + 0x1p120);
112+
}
113+
}
102114
return x;
103115
}
104116
return trig.__sin(x, 0.0, 0);

lib/compiler_rt/sincos.zig

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void {
4646
// |x| < 2**-12
4747
if (ix < 0x39800000) {
4848
// raise inexact if x!=0 and underflow if subnormal
49-
if (common.want_float_exceptions) mem.doNotOptimizeAway(if (ix < 0x00100000) x / 0x1p120 else x + 0x1p120);
49+
if (common.want_float_exceptions) {
50+
if (ix < 0x00100000) {
51+
mem.doNotOptimizeAway(x / 0x1p120);
52+
} else {
53+
mem.doNotOptimizeAway(x + 0x1p120);
54+
}
55+
}
5056
r_sin.* = x;
5157
r_cos.* = 1.0;
5258
return;
@@ -134,7 +140,13 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void {
134140
// if |x| < 2**-27 * sqrt(2)
135141
if (ix < 0x3e46a09e) {
136142
// raise inexact if x != 0 and underflow if subnormal
137-
if (common.want_float_exceptions) mem.doNotOptimizeAway(if (ix < 0x00100000) x / 0x1p120 else x + 0x1p120);
143+
if (common.want_float_exceptions) {
144+
if (ix < 0x00100000) {
145+
mem.doNotOptimizeAway(x / 0x1p120);
146+
} else {
147+
mem.doNotOptimizeAway(x + 0x1p120);
148+
}
149+
}
138150
r_sin.* = x;
139151
r_cos.* = 1.0;
140152
return;

lib/compiler_rt/tan.zig

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,13 @@ pub fn tanf(x: f32) callconv(.c) f32 {
5151
if (ix <= 0x3f490fda) { // |x| ~<= pi/4
5252
if (ix < 0x39800000) { // |x| < 2**-12
5353
// raise inexact if x!=0 and underflow if subnormal
54-
if (common.want_float_exceptions) mem.doNotOptimizeAway(if (ix < 0x00800000) x / 0x1p120 else x + 0x1p120);
54+
if (common.want_float_exceptions) {
55+
if (ix < 0x00800000) {
56+
mem.doNotOptimizeAway(x / 0x1p120);
57+
} else {
58+
mem.doNotOptimizeAway(x + 0x1p120);
59+
}
60+
}
5561
return x;
5662
}
5763
return kernel.__tandf(x, false);
@@ -89,7 +95,13 @@ pub fn tan(x: f64) callconv(.c) f64 {
8995
if (ix <= 0x3fe921fb) {
9096
if (ix < 0x3e400000) { // |x| < 2**-27
9197
// raise inexact if x!=0 and underflow if subnormal
92-
if (common.want_float_exceptions) mem.doNotOptimizeAway(if (ix < 0x00100000) x / 0x1p120 else x + 0x1p120);
98+
if (common.want_float_exceptions) {
99+
if (ix < 0x00100000) {
100+
mem.doNotOptimizeAway(x / 0x1p120);
101+
} else {
102+
mem.doNotOptimizeAway(x + 0x1p120);
103+
}
104+
}
93105
return x;
94106
}
95107
return kernel.__tan(x, 0.0, false);

0 commit comments

Comments
 (0)