Skip to content

Commit 60f24be

Browse files
committed
keep sugar length-check errors out of line
With the error path inlined, the compiler could no longer propagate constants into the loops following these checks (e.g. `m(_, j) = m(_, j) * 2.0` lost its constant multiplier and vectorized half as wide).
1 parent 617bb03 commit 60f24be

1 file changed

Lines changed: 13 additions & 4 deletions

File tree

‎inst/include/Rcpp/sugar/tools/check_sizes.h‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,32 @@
2525
namespace Rcpp{
2626
namespace sugar{
2727

28+
// Kept out of line: inlining the error path keeps the compiler from
29+
// optimizing the loops that follow these checks.
30+
#if defined(__GNUC__)
31+
__attribute__((noinline, cold))
32+
#endif
33+
inline void NORET stop_sizes(const char* fmt, R_xlen_t n1, R_xlen_t n2) {
34+
stop(fmt, n1, n2);
35+
}
36+
2837
// Sugar doesn't recycle the way R does: the vectors an expression
2938
// combines must all have the same length.
3039
inline void check_sizes(R_xlen_t n1, R_xlen_t n2) {
3140
if (n1 != n2)
32-
stop("sugar operands have different lengths (%d and %d)", n1, n2);
41+
stop_sizes("sugar operands have different lengths (%d and %d)", n1, n2);
3342
}
3443

3544
inline void check_sizes(R_xlen_t n1, R_xlen_t n2, R_xlen_t n3) {
36-
if (n1 != n2 || n1 != n3)
37-
stop("sugar operands have different lengths (%d, %d and %d)", n1, n2, n3);
45+
check_sizes(n1, n2);
46+
check_sizes(n1, n3);
3847
}
3948

4049
// Likewise, a vector assigned into a range, row or column must have the
4150
// same length as that target.
4251
inline void check_assign_size(R_xlen_t target, R_xlen_t value) {
4352
if (target != value)
44-
stop("cannot assign a vector of length %d to a target of length %d", value, target);
53+
stop_sizes("cannot assign a vector of length %d to a target of length %d", value, target);
4554
}
4655

4756
} // sugar

0 commit comments

Comments
 (0)