Fixture 98
shift semantics
C · 5 functions · 4 lanes · 20 of 20 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Shift edge cases that remain well-defined: the shift count is always masked into range, unsigned left shifts are modular, and a signed right shift is implementation-defined but arithmetic on every target this corpus builds.
#include <stdint.h>
/* Shift edge cases that remain well-defined: the shift count is always masked
* into range, unsigned left shifts are modular, and a signed right shift is
* implementation-defined but arithmetic on every target this corpus builds. */
__attribute__((noinline)) uint32_t
masked_left_shift(uint32_t value, int32_t amount) {
return value << (uint32_t)(amount & 31);
}
__attribute__((noinline)) int32_t
arithmetic_right_shift(int32_t value, int32_t amount) {
/* Sign-propagating on x86/ARM/RISC-V: -8 >> 1 is -4, not a huge positive. */
return value >> (amount & 31);
}
__attribute__((noinline)) uint32_t
logical_right_shift(uint32_t value, int32_t amount) {
return value >> (uint32_t)(amount & 31);
}
__attribute__((noinline)) uint32_t
rotate_left(uint32_t value, int32_t amount) {
uint32_t rotation = (uint32_t)(amount & 31);
/* The zero case is spelled out so no shift by 32 is ever evaluated. */
if (rotation == 0u) {
return value;
}
return (value << rotation) | (value >> (32u - rotation));
}
__attribute__((noinline)) uint32_t
shift_wider_than_operand(uint32_t value, int32_t amount) {
/* Promoting to 64 bits makes a shift of 32..63 meaningful instead of UB. */
return (uint32_t)(((uint64_t)value << (uint32_t)(amount & 63)) >> 32);
} Recovered C
Generated by glaurung decompile --style decbench at b47f6b43.
baseline.json records the result after recompiling the C and calling it beside the
original with seeded inputs.
clang -O0
5/5arithmetic_right_shift pass 6 lines
// glaurung: arithmetic_right_shift @ 0x1120
int32_t arithmetic_right_shift(int32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((long)((long)(arg0)) >> ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 31))) & 31)));
} logical_right_shift pass 6 lines
// glaurung: logical_right_shift @ 0x1140
uint32_t logical_right_shift(uint32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) >> ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 31))) & 31)));
} masked_left_shift pass 6 lines
// glaurung: masked_left_shift @ 0x1100
uint32_t masked_left_shift(uint32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 31))) & 31)));
} rotate_left pass 11 lines
// glaurung: rotate_left @ 0x1160
uint32_t rotate_left(uint32_t arg0, int32_t arg1) {
unsigned int rotation;
// x86-64 prologue: save rbp
rotation = ((unsigned int)(arg1) & 31);
if ((rotation != 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) << ((unsigned long)(rotation) & 31)))) | (unsigned long)((unsigned int)(((unsigned long)(arg0) >> ((unsigned long)((unsigned int)((32 - rotation))) & 31))))));
} else {
return arg0;
}
} shift_wider_than_operand pass 6 lines
// glaurung: shift_wider_than_operand @ 0x11b0
uint32_t shift_wider_than_operand(uint32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((unsigned long)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 63))) & 63))) >> 32);
} clang -O2
5/5arithmetic_right_shift pass 4 lines
// glaurung: arithmetic_right_shift @ 0x1110
int32_t arithmetic_right_shift(int32_t arg0, int32_t arg1) {
return (unsigned int)(((long)((long)(arg0)) >> ((unsigned long)((unsigned int)(arg1)) & 31)));
} logical_right_shift pass 4 lines
// glaurung: logical_right_shift @ 0x1120
uint32_t logical_right_shift(uint32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) >> ((unsigned long)((unsigned int)(arg1)) & 31)));
} masked_left_shift pass 4 lines
// glaurung: masked_left_shift @ 0x1100
uint32_t masked_left_shift(uint32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(arg1)) & 31)));
} rotate_left pass 6 lines
// glaurung: rotate_left @ 0x1130
uint32_t rotate_left(uint32_t arg0, int32_t arg1) {
long t41;
t41 = ((unsigned long)((unsigned int)(arg1)) & 31);
return (((unsigned long)(arg0) << t41) | ((unsigned long)(arg0) >> ((32 - t41) & 31)));
} shift_wider_than_operand pass 4 lines
// glaurung: shift_wider_than_operand @ 0x1140
uint32_t shift_wider_than_operand(uint32_t arg0, int32_t arg1) {
return ((unsigned long)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(arg1)) & 63))) >> 32);
} gcc -O0
5/5arithmetic_right_shift pass 6 lines
// glaurung: arithmetic_right_shift @ 0x1118
int32_t arithmetic_right_shift(int32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((long)((long)(arg0)) >> ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 31))) & 31)));
} logical_right_shift pass 6 lines
// glaurung: logical_right_shift @ 0x1137
uint32_t logical_right_shift(uint32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) >> ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 31))) & 31)));
} masked_left_shift pass 6 lines
// glaurung: masked_left_shift @ 0x10f9
uint32_t masked_left_shift(uint32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 31))) & 31)));
} rotate_left pass 13 lines
// glaurung: rotate_left @ 0x1156
uint32_t rotate_left(uint32_t arg0, int32_t arg1) {
unsigned int rotation;
long t41;
// x86-64 prologue: save rbp
rotation = ((unsigned int)(arg1) & 31);
if ((rotation != 0)) {
t41 = ((unsigned long)(rotation) & 31);
return (unsigned int)((((unsigned long)(arg0) << t41) | ((unsigned long)(arg0) >> ((32 - t41) & 31))));
} else {
return arg0;
}
} shift_wider_than_operand pass 6 lines
// glaurung: shift_wider_than_operand @ 0x1186
uint32_t shift_wider_than_operand(uint32_t arg0, int32_t arg1) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return ((unsigned long)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 63))) & 63))) >> 32);
} gcc -O2
5/5arithmetic_right_shift pass 4 lines
// glaurung: arithmetic_right_shift @ 0x1110
int32_t arithmetic_right_shift(int32_t arg0, int32_t arg1) {
return (unsigned int)(((long)((long)(arg0)) >> ((unsigned long)((unsigned int)(arg1)) & 31)));
} logical_right_shift pass 4 lines
// glaurung: logical_right_shift @ 0x1120
uint32_t logical_right_shift(uint32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) >> ((unsigned long)((unsigned int)(arg1)) & 31)));
} masked_left_shift pass 4 lines
// glaurung: masked_left_shift @ 0x1100
uint32_t masked_left_shift(uint32_t arg0, int32_t arg1) {
return (unsigned int)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(arg1)) & 31)));
} rotate_left pass 6 lines
// glaurung: rotate_left @ 0x1130
uint32_t rotate_left(uint32_t arg0, int32_t arg1) {
long t41;
t41 = ((unsigned long)((unsigned int)(arg1)) & 31);
return (((unsigned long)(arg0) << t41) | ((unsigned long)(arg0) >> ((32 - t41) & 31)));
} shift_wider_than_operand pass 4 lines
// glaurung: shift_wider_than_operand @ 0x1140
uint32_t shift_wider_than_operand(uint32_t arg0, int32_t arg1) {
return ((unsigned long)(((unsigned long)(arg0) << ((unsigned long)((unsigned int)(arg1)) & 63))) >> 32);
}