-
-
Notifications
You must be signed in to change notification settings - Fork 11k
BUG: Don't produce undefined behavior for a << b if b >= bitsof(a) #13739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
24b2a2d
b12a869
e487889
ff11d01
fca077c
79d7bc2
6cf6ece
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -716,3 +716,44 @@ npy_@func@@c@(@type@ a, @type@ b) | |
return npy_@func@u@c@(a < 0 ? -a : a, b < 0 ? -b : b); | ||
} | ||
/**end repeat**/ | ||
|
||
/* Unlike LCM and GCD, we need byte and short variants for the shift operators, | ||
* since the result is dependent on the width of the type | ||
*/ | ||
/**begin repeat | ||
* | ||
* #type = byte, short, int, long, longlong# | ||
* #c = hh,h,,l,ll# | ||
*/ | ||
/**begin repeat1 | ||
* | ||
* #u = u,# | ||
* #is_signed = 0,1# | ||
*/ | ||
NPY_INPLACE npy_@u@@type@ | ||
npy_lshift@u@@c@(npy_@u@@type@ a, npy_@u@@type@ b) | ||
{ | ||
if (NPY_LIKELY((size_t)b < sizeof(a) * CHAR_BIT)) { | ||
return a << b; | ||
} | ||
else { | ||
return 0; | ||
} | ||
} | ||
NPY_INPLACE npy_@u@@type@ | ||
npy_rshift@u@@c@(npy_@u@@type@ a, npy_@u@@type@ b) | ||
{ | ||
if (NPY_LIKELY((size_t)b < sizeof(a) * CHAR_BIT)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to deal with the possibility that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that currently the shift value is cast to unsigned and masked, at least on my hardware.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there was a comment in the old/new code about that as well. Maybe we can push it off to another PR? That seems the easiest way forward? We can ignore the codecov failures. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. xref gh-13898 |
||
return a >> b; | ||
} | ||
#if @is_signed@ | ||
else if (a < 0) { | ||
return (npy_@u@@type@)-1; /* preserve the sign bit */ | ||
} | ||
#endif | ||
else { | ||
return 0; | ||
} | ||
} | ||
/**end repeat1**/ | ||
/**end repeat**/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -699,6 +699,7 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED | |
* #ftype = npy_float, npy_float, npy_float, npy_float, npy_double, npy_double, | ||
* npy_double, npy_double, npy_double, npy_double# | ||
* #SIGNED = 1, 0, 1, 0, 1, 0, 1, 0, 1, 0# | ||
* #c = hh,uhh,h,uh,,u,l,ul,ll,ull# | ||
*/ | ||
|
||
#define @TYPE@_floor_divide @TYPE@_divide | ||
|
@@ -776,16 +777,15 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void | |
|
||
/**begin repeat2 | ||
* Arithmetic | ||
* #kind = add, subtract, multiply, bitwise_and, bitwise_or, bitwise_xor, | ||
* left_shift, right_shift# | ||
* #OP = +, -,*, &, |, ^, <<, >># | ||
* #kind = add, subtract, multiply, bitwise_and, bitwise_or, bitwise_xor# | ||
* #OP = +, -, *, &, |, ^# | ||
*/ | ||
|
||
#if @CHK@ | ||
NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void | ||
@TYPE@_@kind@@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) | ||
{ | ||
if(IS_BINARY_REDUCE) { | ||
if (IS_BINARY_REDUCE) { | ||
BINARY_REDUCE_LOOP(@type@) { | ||
io1 @OP@= *(@type@ *)ip2; | ||
} | ||
|
@@ -799,6 +799,47 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void | |
|
||
/**end repeat2**/ | ||
|
||
/* | ||
* Arithmetic bit shift operations. | ||
* | ||
* Intel hardware masks bit shift values, so large shifts wrap around | ||
* and can produce surprising results. The special handling ensures that | ||
* behavior is independent of compiler or hardware. | ||
* TODO: We could implement consistent behavior for negative shifts, | ||
* which is undefined in C. | ||
*/ | ||
|
||
#define INT_left_shift_needs_clear_floatstatus | ||
#define UINT_left_shift_needs_clear_floatstatus | ||
|
||
NPY_NO_EXPORT NPY_GCC_OPT_3 void | ||
@TYPE@_left_shift@isa@(char **args, npy_intp *dimensions, npy_intp *steps, | ||
void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_FAST(@type@, @type@, *out = npy_lshift@c@(in1, in2)); | ||
|
||
#ifdef @TYPE@_left_shift_needs_clear_floatstatus | ||
// For some reason, our macOS CI sets an "invalid" flag here, but only | ||
// for some types. | ||
npy_clear_floatstatus_barrier((char*)dimensions); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no idea why this happens. Is our macOS run x86, or something else? Do we have a resident macOS expert? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no idea, was thinking about putting it in godbold, but it is quite a lot of code around it (and I am not sure it is likely to show anything in any case). @charris, I think I am good with this as is. But you had a look at it before and know There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could be a clang thing. |
||
#endif | ||
} | ||
|
||
#undef INT_left_shift_needs_clear_floatstatus | ||
#undef UINT_left_shift_needs_clear_floatstatus | ||
|
||
NPY_NO_EXPORT | ||
#ifndef NPY_DO_NOT_OPTIMIZE_@TYPE@_right_shift | ||
NPY_GCC_OPT_3 | ||
#endif | ||
void | ||
@TYPE@_right_shift@isa@(char **args, npy_intp *dimensions, npy_intp *steps, | ||
void *NPY_UNUSED(func)) | ||
{ | ||
BINARY_LOOP_FAST(@type@, @type@, *out = npy_rshift@c@(in1, in2)); | ||
} | ||
|
||
|
||
/**begin repeat2 | ||
* #kind = equal, not_equal, greater, greater_equal, less, less_equal, | ||
* logical_and, logical_or# | ||
|
Uh oh!
There was an error while loading. Please reload this page.