Fixture 194

narrow return widths

C · 10 functions · 4 lanes · 40 of 40 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

tests/decompiler_fixtures/src/194_narrow_return_widths.c source
#include <stdint.h>

/* RETURN VALUES NARROWER THAN A REGISTER.
 *
 * A census of every function definition in this corpus (900 of them, across
 * `.c`, `.cpp` and `.rs`) found that the returned type is a full machine word
 * almost everywhere:
 *
 *   int32_t / int / uint32_t / i32     704 definitions
 *   double / float                      22
 *   64-bit (long, int64_t, uint64_t)    14
 *   uint8_t                              2   (11_call_shapes:wrap_byte,
 *                                             43_base64:encode_symbol)
 *   uint16_t                             1   (07_packet_parser:read_be16,
 *                                             not a REQUIRED function)
 *   int8_t, int16_t, char, _Bool         0
 *
 * So the corpus asks "what happens when only the low 8 or 16 bits of the result
 * register are architecturally meaningful?" exactly twice, never in the SIGNED
 * direction, and never for `_Bool`. That is the shape this fixture adds.
 *
 * Why it is a distinct question from a narrow LOCAL (which `02_integer_widths`
 * already covers): a narrow local is a value the compiler may keep in any width
 * it likes, while a narrow return is an ABI contract about `al`/`ax` — the
 * high bits of `eax` are dead, so `movsbl`/`movzwl` around the return are the
 * only thing that distinguishes `int8_t f()` from `int32_t f()` in the machine
 * code. A decompiler that models every result as a 32-bit register produces C
 * that compiles and that agrees on every input whose value happens to fit.
 *
 * Each positive case therefore narrows and then does arithmetic that the
 * narrowing CHANGES, so the low bits differ rather than only the dead high
 * ones: signed division after truncation is not truncation after division.
 *
 * THREE NEGATIVE CONTROLS, each aimed at a different wrong generalisation:
 *
 *   `nrw194_i32_control`      computes the same expression as `nrw194_i8_divide`
 *                             at full width. A recovery that narrows every
 *                             return satisfies the positives and fails here.
 *   `nrw194_u8_value_control` has the same BODY as `nrw194_u8_mix` — the value
 *                             is narrowed to 8 bits — but returns `int32_t`.
 *                             It separates "models the return width" from
 *                             "models the value width"; conflating the two
 *                             passes every other case in this file.
 *   `nrw194_bool_wide_control` spells `nrw194_bool_and`'s boolean normalisation
 *                             out explicitly with `!= 0` and returns `int32_t`,
 *                             so the `_Bool` case is measuring the CONVERSION
 *                             and not the arithmetic around it.
 *
 * Every function is a pure function of its integer arguments: no memory, no
 * I/O, no undefined behaviour. Intermediate products are formed in `uint32_t`
 * so the boundary sweep's `INT_MIN`/`INT_MAX` vectors cannot overflow a signed
 * multiply, and every divisor is a nonzero constant.
 *
 * ONE DELIBERATE CROSS-ARCHITECTURE ARTIFACT: plain `char` is SIGNED on x86 and
 * x86-64 and UNSIGNED on both ARM targets, so `nrw194_char_divide` has a
 * genuinely different DWARF return type in an AArch64/ARMv7 build than in the
 * host reference. `diff_decompile.abi_incomparable` should decline those two
 * lanes with `incomparable` rather than compare a truncation against a
 * zero-extension and call the difference a lifter bug. That refusal is part of
 * what this fixture is for; the i386 lane shares x86's signed `char` and must
 * stay comparable. */

/* --- signed narrow returns ------------------------------------------------ */

/* int8_t: truncate to 8 bits, THEN divide. `x = 300` narrows to 44 and returns
 * 22; dividing first and truncating afterwards returns 106. The two disagree in
 * the low byte, which is the only byte the ABI defines. */
__attribute__((noinline)) int8_t nrw194_i8_divide(int32_t x) {
    int8_t narrowed = (int8_t)((uint32_t)x * 3u);
    return (int8_t)(narrowed / 2);
}

/* int16_t: the same question one width up, where a 16-bit truncation is a
 * different instruction (`movswl` rather than `movsbl`). */
__attribute__((noinline)) int16_t nrw194_i16_divide(int32_t x) {
    int16_t narrowed = (int16_t)((uint32_t)x * 5u);
    return (int16_t)(narrowed / 7);
}

/* --- unsigned narrow returns ---------------------------------------------- */

/* uint8_t: division and a logical shift of a ZERO-extended byte. Reading the
 * same bits as signed makes `narrowed >> 5` an arithmetic shift and changes the
 * answer for every input with bit 7 set. */
__attribute__((noinline)) uint8_t nrw194_u8_mix(int32_t x) {
    uint8_t narrowed = (uint8_t)x;
    return (uint8_t)(narrowed / 3u + (uint32_t)(narrowed >> 5));
}

/* uint16_t: the same, one width up. */
__attribute__((noinline)) uint16_t nrw194_u16_mix(int32_t x) {
    uint16_t narrowed = (uint16_t)x;
    return (uint16_t)(narrowed / 9u + (uint32_t)(narrowed >> 11));
}

/* --- plain `char`, whose signedness is a property of the TARGET ------------ */

/* Signed on x86/x86-64, unsigned on AArch64 and ARMv7. The host lanes divide a
 * sign-extended byte; a naive cross-architecture comparison would divide a
 * zero-extended one and blame the lifter. See the header note. */
__attribute__((noinline)) char nrw194_char_divide(int32_t x) {
    char narrowed = (char)x;
    return (char)(narrowed / 2);
}

/* --- _Bool, where the ABI value is NORMALISED and not merely truncated ----- */

/* `(x & 0x100)` is 0 or 256; converting it to `_Bool` is `test`/`setne`, so the
 * returned byte is 0 or 1. A recovery that keeps the raw mask returns 0 for
 * EVERY input, because 256's low byte is zero — the one case where the dead
 * high bits are what carried the answer. */
__attribute__((noinline)) _Bool nrw194_bool_bit(int32_t x) {
    return (_Bool)(x & 0x100);
}

/* Two `_Bool` conversions combined with a bitwise AND. Both operands must be
 * normalised to 0/1 first: `4 & 8` is 0, so a recovery that ANDs the raw masks
 * answers 0 where the original answers 1. */
__attribute__((noinline)) _Bool nrw194_bool_and(int32_t x, int32_t y) {
    _Bool a = (_Bool)(x & 4);
    _Bool b = (_Bool)(y & 8);
    return (_Bool)(a & b);
}

/* --- CONTROLS ------------------------------------------------------------- */

/* CONTROL: `nrw194_i8_divide`'s expression at FULL width. A decompiler that
 * applies a narrowing to every return fails exactly here. */
__attribute__((noinline)) int32_t nrw194_i32_control(int32_t x) {
    int32_t wide = (int32_t)((uint32_t)x * 3u);
    return wide / 2;
}

/* CONTROL: `nrw194_u8_mix`'s BODY, returned at full width. The value is narrow
 * and the result is not, so conflating the two is visible here and nowhere
 * else in this file. */
__attribute__((noinline)) int32_t nrw194_u8_value_control(int32_t x) {
    uint8_t narrowed = (uint8_t)x;
    return (int32_t)(narrowed / 3u + (uint32_t)(narrowed >> 5));
}

/* CONTROL: `nrw194_bool_and` with the normalisation written out by hand and an
 * `int32_t` result. If this passes while `nrw194_bool_and` fails, the defect is
 * in the `_Bool` return conversion rather than in the surrounding arithmetic. */
__attribute__((noinline)) int32_t nrw194_bool_wide_control(int32_t x, int32_t y) {
    int32_t a = (x & 4) != 0;
    int32_t b = (y & 8) != 0;
    return a & b;
}

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

10/10
nrw194_bool_and pass 8 lines
// glaurung: nrw194_bool_and @ 0x11e0
_Bool nrw194_bool_and(int32_t arg0, int32_t arg1) {
    int a;
    int b;
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return ((unsigned long)((unsigned int)((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 4))) != 0) & ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 8))) != 0)))) != 0);
}
nrw194_bool_bit pass 6 lines
// glaurung: nrw194_bool_bit @ 0x11c0
_Bool nrw194_bool_bit(int32_t arg0) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 256))) != 0);
}
nrw194_bool_wide_control pass 8 lines
// glaurung: nrw194_bool_wide_control @ 0x1280
int32_t nrw194_bool_wide_control(int32_t arg0, int32_t arg1) {
    int a;
    int b;
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return (unsigned int)((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 4))) != 0) & ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 8))) != 0)));
}
nrw194_char_divide pass 8 lines
// glaurung: nrw194_char_divide @ 0x11a0
char nrw194_char_divide(int32_t arg0) {
    signed char narrowed;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    // x86-64 epilogue: restore rbp
    return (int)((signed char)((((int)((((long long)(int)((((unsigned long)((long)((int)(narrowed))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(narrowed)) / (int)(2))) & 255)));
}
nrw194_i16_divide pass 8 lines
// glaurung: nrw194_i16_divide @ 0x1120
int16_t nrw194_i16_divide(int32_t arg0) {
    short narrowed;
    // x86-64 prologue: save rbp
    narrowed = (arg0 * 5);
    // x86-64 epilogue: restore rbp
    return (int)((short)(((int)((((long long)(int)((((unsigned long)((long)((int)(narrowed))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(narrowed)) / (int)(7)))));
}
nrw194_i32_control pass 8 lines
// glaurung: nrw194_i32_control @ 0x1230
int32_t nrw194_i32_control(int32_t arg0) {
    int wide;
    // x86-64 prologue: save rbp
    wide = (arg0 * 3);
    // x86-64 epilogue: restore rbp
    return ((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(wide))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(wide)))) / (int)(2)));
}
nrw194_i8_divide pass 8 lines
// glaurung: nrw194_i8_divide @ 0x1100
int8_t nrw194_i8_divide(int32_t arg0) {
    signed char narrowed;
    // x86-64 prologue: save rbp
    narrowed = (arg0 * 3);
    // x86-64 epilogue: restore rbp
    return (int)((signed char)((((int)((((long long)(int)((((unsigned long)((long)((int)(narrowed))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)(narrowed)) / (int)(2))) & 255)));
}
nrw194_u16_mix pass 8 lines
// glaurung: nrw194_u16_mix @ 0x1170
uint16_t nrw194_u16_mix(int32_t arg0) {
    unsigned short narrowed;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    // x86-64 epilogue: restore rbp
    return (unsigned int)((unsigned short)(((unsigned long)((unsigned int)((((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned int)(narrowed))) / (unsigned int)(9)))) + (unsigned long)((unsigned int)(((int)(narrowed) >> 11)))))) & 0xffff)));
}
nrw194_u8_mix pass 8 lines
// glaurung: nrw194_u8_mix @ 0x1140
uint8_t nrw194_u8_mix(int32_t arg0) {
    unsigned char narrowed;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    // x86-64 epilogue: restore rbp
    return (unsigned int)((unsigned char)(((unsigned long)((unsigned int)((((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned int)(narrowed))) / (unsigned int)(3)))) + (unsigned long)((unsigned int)(((int)(narrowed) >> 5)))))) & 255)));
}
nrw194_u8_value_control pass 8 lines
// glaurung: nrw194_u8_value_control @ 0x1250
int32_t nrw194_u8_value_control(int32_t arg0) {
    unsigned char narrowed;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    // x86-64 epilogue: restore rbp
    return (unsigned int)((((unsigned int)(((((unsigned long long)(unsigned int)((unsigned long)((unsigned int)(0))) << 32) | (unsigned int)((unsigned int)(narrowed))) / (unsigned int)(3)))) + (unsigned long)((unsigned int)(((int)(narrowed) >> 5)))));
}

clang -O2

10/10
nrw194_bool_and pass 6 lines
// glaurung: nrw194_bool_and @ 0x11a0
_Bool nrw194_bool_and(int32_t arg0, int32_t arg1) {
    long var8;
    var8 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 3))) & (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 2))))));
    return ((unsigned char)(((var8 & -256) | (var8 & 1))) != 0);
}
nrw194_bool_bit pass 4 lines
// glaurung: nrw194_bool_bit @ 0x1190
_Bool nrw194_bool_bit(int32_t arg0) {
    return ((unsigned char)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 8))) & 1))) != 0);
}
nrw194_bool_wide_control pass 4 lines
// glaurung: nrw194_bool_wide_control @ 0x11e0
int32_t nrw194_bool_wide_control(int32_t arg0, int32_t arg1) {
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 3))) & (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 2)))))) & 1));
}
nrw194_char_divide pass 8 lines
// glaurung: nrw194_char_divide @ 0x1180
char nrw194_char_divide(int32_t arg0) {
    long var2;
    long var4;
    var2 = (((unsigned long)((unsigned int)(arg0)) & -256) | (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(arg0)) & 255))) >> 7) & 255));
    var4 = ((var2 & -256) | (((var2 & 255) + ((unsigned long)((unsigned int)(arg0)) & 255)) & 255));
    return ((var4 & -256) | (((signed char)((var4 & 255)) >> 1) & 255));
}
nrw194_i16_divide pass 8 lines
// glaurung: nrw194_i16_divide @ 0x1120
int16_t nrw194_i16_divide(int32_t arg0) {
    long var1;
    int var6;
    var1 = (unsigned long)((unsigned int)((arg0 << 16)));
    var6 = ((unsigned int)(((int)((var1 + (var1 * 4))) >> 16)) * 0x4925);
    return (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(var6) >> 17))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var6)) >> 31))))));
}
nrw194_i32_control pass 6 lines
// glaurung: nrw194_i32_control @ 0x11b0
int32_t nrw194_i32_control(int32_t arg0) {
    int wide;
    wide = (unsigned long)((unsigned int)((arg0 + (arg0 * 2))));
    return (unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(wide)) >> 31))) + wide)) >> 1));
}
nrw194_i8_divide pass 12 lines
// glaurung: nrw194_i8_divide @ 0x1100
int8_t nrw194_i8_divide(int32_t arg0) {
    long var1;
    long var11;
    long var2;
    long var9;
    var1 = (unsigned long)((unsigned int)((arg0 << 24)));
    var2 = (unsigned long)((unsigned int)((var1 + (var1 * 2))));
    var9 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) >> 31)));
    var11 = ((var9 & -256) | (((var9 & 255) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) >> 24))) & 255)) & 255));
    return ((var11 & -256) | (((signed char)((var11 & 255)) >> 1) & 255));
}
nrw194_u16_mix pass 6 lines
// glaurung: nrw194_u16_mix @ 0x1160
uint16_t nrw194_u16_mix(int32_t arg0) {
    int var0;
    var0 = (unsigned int)((unsigned short)((arg0 & 0xffff)));
    return (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 11))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var0 * 0xe38f))) >> 19))))));
}
nrw194_u8_mix pass 8 lines
// glaurung: nrw194_u8_mix @ 0x1140
uint8_t nrw194_u8_mix(int32_t arg0) {
    int var0;
    long var6;
    var0 = (unsigned int)((unsigned char)((arg0 & 255)));
    var6 = (((unsigned long)((unsigned int)(var0)) & -256) | (((unsigned long)((unsigned char)((var0 & 255))) >> 5) & 255));
    return ((var6 & -256) | (((var6 & 255) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var0 * 171))) >> 9))) & 255)) & 255));
}
nrw194_u8_value_control pass 5 lines
// glaurung: nrw194_u8_value_control @ 0x11c0
int32_t nrw194_u8_value_control(int32_t arg0) {
    unsigned char narrowed;
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)((arg0 & 255))) * 171))) >> 9))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 5))) & 7)))));
}

gcc -O0

10/10
nrw194_bool_and pass 10 lines
// glaurung: nrw194_bool_and @ 0x11f8
_Bool nrw194_bool_and(int32_t arg0, int32_t arg1) {
    int a;
    int b;
    long var13;
    // x86-64 prologue: save rbp
    var13 = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 8))) != 0) & ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 4))) != 0))));
    // x86-64 epilogue: restore rbp
    return ((unsigned char)(((var13 & -256) | ((unsigned long)((unsigned int)(var13)) != 0))) != 0);
}
nrw194_bool_bit pass 8 lines
// glaurung: nrw194_bool_bit @ 0x11de
_Bool nrw194_bool_bit(int32_t arg0) {
    long var2;
    // x86-64 prologue: save rbp
    var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 256)));
    // x86-64 epilogue: restore rbp
    return ((unsigned char)(((var2 & -256) | ((unsigned long)((unsigned int)(var2)) != 0))) != 0);
}
nrw194_bool_wide_control pass 8 lines
// glaurung: nrw194_bool_wide_control @ 0x128b
int32_t nrw194_bool_wide_control(int32_t arg0, int32_t arg1) {
    int a;
    int b;
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return (unsigned int)((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 4))) != 0) & ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 8))) != 0)));
}
nrw194_char_divide pass 10 lines
// glaurung: nrw194_char_divide @ 0x11be
char nrw194_char_divide(int32_t arg0) {
    signed char narrowed;
    int var5;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    var5 = ((unsigned int)((unsigned char)(narrowed)) + (((unsigned int)((unsigned char)(narrowed)) & -256) | (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)((unsigned char)(narrowed))) & 255))) >> 7) & 255)));
    // x86-64 epilogue: restore rbp
    return (((unsigned long)((unsigned int)(var5)) & -256) | (((signed char)(((unsigned long)((unsigned int)(var5)) & 255)) >> 1) & 255));
}
nrw194_i16_divide pass 10 lines
// glaurung: nrw194_i16_divide @ 0x1121
int16_t nrw194_i16_divide(int32_t arg0) {
    short narrowed;
    long var12;
    // x86-64 prologue: save rbp
    narrowed = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) << 2))) + (unsigned long)((unsigned int)(arg0)));
    var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)((short)(((unsigned int)((unsigned short)(narrowed)) & 0xffff))) * 0x4925))) >> 16)));
    // x86-64 epilogue: restore rbp
    return (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((var12 & -0x10000LL) | (((short)((var12 & 0xffff)) >> 1) & 0xffff)))) - (unsigned long)((unsigned int)((((unsigned int)((unsigned short)(narrowed)) & -0x10000LL) | (((short)(((unsigned int)((unsigned short)(narrowed)) & 0xffff)) >> 15) & 0xffff)))))));
}
nrw194_i32_control pass 8 lines
// glaurung: nrw194_i32_control @ 0x1233
int32_t nrw194_i32_control(int32_t arg0) {
    int wide;
    // x86-64 prologue: save rbp
    wide = ((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0)))) + (unsigned int)(arg0));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((int)(((unsigned long)((unsigned int)(wide)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(wide)) >> 31))))) >> 1));
}
nrw194_i8_divide pass 10 lines
// glaurung: nrw194_i8_divide @ 0x10f9
int8_t nrw194_i8_divide(int32_t arg0) {
    signed char narrowed;
    int var11;
    // x86-64 prologue: save rbp
    narrowed = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) + (unsigned long)((unsigned int)(arg0))))) + (unsigned long)((unsigned int)(arg0)));
    var11 = ((unsigned int)((unsigned char)(narrowed)) + (((unsigned int)((unsigned char)(narrowed)) & -256) | (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)((unsigned char)(narrowed))) & 255))) >> 7) & 255)));
    // x86-64 epilogue: restore rbp
    return (((unsigned long)((unsigned int)(var11)) & -256) | (((signed char)(((unsigned long)((unsigned int)(var11)) & 255)) >> 1) & 255));
}
nrw194_u16_mix pass 10 lines
// glaurung: nrw194_u16_mix @ 0x118a
uint16_t nrw194_u16_mix(int32_t arg0) {
    unsigned short narrowed;
    long var7;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    var7 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned short)((narrowed & 0xffff))) * 0xe38f))) >> 16)));
    // x86-64 epilogue: restore rbp
    return (unsigned long)((unsigned int)(((((unsigned int)(narrowed) & -0x10000LL) | (((unsigned long)((unsigned short)(((unsigned int)(narrowed) & 0xffff))) >> 11) & 0xffff)) + ((var7 & -0x10000LL) | (((unsigned long)((unsigned short)((var7 & 0xffff))) >> 3) & 0xffff)))));
}
nrw194_u8_mix pass 12 lines
// glaurung: nrw194_u8_mix @ 0x115b
uint8_t nrw194_u8_mix(int32_t arg0) {
    unsigned char narrowed;
    long var6;
    long var9;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    var6 = (((unsigned long)(narrowed) & -0x10000LL) | ((((unsigned char)(((unsigned short)(unsigned char)((narrowed & 255)) * (unsigned short)(unsigned char)((0xffffffab & 255))) >> 8)) & 255) << 8));
    var9 = (unsigned long)((unsigned int)(((var6 & -0x10000LL) | (((unsigned long)((unsigned short)((var6 & 0xffff))) >> 8) & 0xffff))));
    // x86-64 epilogue: restore rbp
    return (unsigned long)((unsigned int)(((((unsigned int)(narrowed) & -256) | (((unsigned long)((unsigned char)(((unsigned int)(narrowed) & 255))) >> 5) & 255)) + ((var9 & -256) | (((unsigned long)((unsigned char)((var9 & 255))) >> 1) & 255)))));
}
nrw194_u8_value_control pass 8 lines
// glaurung: nrw194_u8_value_control @ 0x1258
int32_t nrw194_u8_value_control(int32_t arg0) {
    unsigned char narrowed;
    // x86-64 prologue: save rbp
    narrowed = arg0;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned int)((unsigned char)((((unsigned long)((unsigned char)(((unsigned int)(narrowed) & 255))) >> 5) & 255))) + (unsigned int)((unsigned char)((((unsigned long)((unsigned char)((((unsigned long)((unsigned short)((((((unsigned char)(((unsigned short)(unsigned char)(((unsigned int)(narrowed) & 255)) * (unsigned short)(unsigned char)((0xffffffab & 255))) >> 8)) & 255) << 8) & 0xffff))) >> 8) & 255))) >> 1) & 255)))));
}

gcc -O2

10/10
nrw194_bool_and pass 4 lines
// glaurung: nrw194_bool_and @ 0x11a0
_Bool nrw194_bool_and(int32_t arg0, int32_t arg1) {
    return ((unsigned char)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 3))) & 1))) & (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 2)))))) != 0);
}
nrw194_bool_bit pass 4 lines
// glaurung: nrw194_bool_bit @ 0x1190
_Bool nrw194_bool_bit(int32_t arg0) {
    return ((unsigned char)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 8))) & 1))) != 0);
}
nrw194_bool_wide_control pass 4 lines
// glaurung: nrw194_bool_wide_control @ 0x1200
int32_t nrw194_bool_wide_control(int32_t arg0, int32_t arg1) {
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 3))) & (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) >> 2)))))) & 1));
}
nrw194_char_divide pass 6 lines
// glaurung: nrw194_char_divide @ 0x1180
char nrw194_char_divide(int32_t arg0) {
    int var3;
    var3 = ((((unsigned int)(arg0) & -256) | (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(arg0)) & 255))) >> 7) & 255)) + arg0);
    return (((unsigned long)((unsigned int)(var3)) & -256) | (((signed char)(((unsigned long)((unsigned int)(var3)) & 255)) >> 1) & 255));
}
nrw194_i16_divide pass 6 lines
// glaurung: nrw194_i16_divide @ 0x1120
int16_t nrw194_i16_divide(int32_t arg0) {
    long var0;
    var0 = (unsigned long)((unsigned int)((arg0 + (arg0 * 4))));
    return (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(((int)((short)((var0 & 0xffff))) * 0x4925)) >> 17))) - ((var0 & -0x10000LL) | (((short)((var0 & 0xffff)) >> 15) & 0xffff)))));
}
nrw194_i32_control pass 6 lines
// glaurung: nrw194_i32_control @ 0x11c0
int32_t nrw194_i32_control(int32_t arg0) {
    long var0;
    var0 = (unsigned long)((unsigned int)((arg0 + (arg0 * 2))));
    return (unsigned int)(((int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 31))) + var0)) >> 1));
}
nrw194_i8_divide pass 8 lines
// glaurung: nrw194_i8_divide @ 0x1100
int8_t nrw194_i8_divide(int32_t arg0) {
    long var0;
    int var4;
    var0 = (unsigned long)((unsigned int)((arg0 + (arg0 * 2))));
    var4 = ((((unsigned int)(var0) & -256) | (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(var0)) & 255))) >> 7) & 255)) + var0);
    return (((unsigned long)((unsigned int)(var4)) & -256) | (((signed char)(((unsigned long)((unsigned int)(var4)) & 255)) >> 1) & 255));
}
nrw194_u16_mix pass 4 lines
// glaurung: nrw194_u16_mix @ 0x1160
uint16_t nrw194_u16_mix(int32_t arg0) {
    return (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned short)((arg0 & 0xffff))) * 0xe38f))) >> 19))) + ((arg0 & -0x10000LL) | (((unsigned long)((unsigned short)((arg0 & 0xffff))) >> 11) & 0xffff)))));
}
nrw194_u8_mix pass 6 lines
// glaurung: nrw194_u8_mix @ 0x1140
uint8_t nrw194_u8_mix(int32_t arg0) {
    long var4;
    var4 = (0xffff0000 | ((((unsigned char)(((unsigned short)(unsigned char)((0xffffffab & 255)) * (unsigned short)(unsigned char)((arg0 & 255))) >> 8)) & 255) << 8));
    return (unsigned long)((unsigned int)((((var4 & -0x10000LL) | (((unsigned long)((unsigned short)((var4 & 0xffff))) >> 9) & 0xffff)) + ((arg0 & -256) | (((unsigned long)((unsigned char)((arg0 & 255))) >> 5) & 255)))));
}
nrw194_u8_value_control pass 4 lines
// glaurung: nrw194_u8_value_control @ 0x11e0
int32_t nrw194_u8_value_control(int32_t arg0) {
    return (unsigned int)(((unsigned int)((unsigned char)((((unsigned long)((unsigned short)((((((unsigned char)(((unsigned short)(unsigned char)((0xffffffab & 255)) * (unsigned short)(unsigned char)((arg0 & 255))) >> 8)) & 255) << 8) & 0xffff))) >> 9) & 255))) + (unsigned int)((unsigned char)((((unsigned long)((unsigned char)((arg0 & 255))) >> 5) & 255)))));
}

← 213 fixtures