Fixture 130
bitpacked codec
C · 3 functions · 4 lanes · 12 of 12 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
A wire codec that packs four fields of different widths into one word and reads them back. The shift/mask constants are the entire specification, so an off-by-one in any of them is invisible structurally and fatal behaviorally.
#include <stdint.h>
/* A wire codec that packs four fields of different widths into one word and
* reads them back. The shift/mask constants are the entire specification, so an
* off-by-one in any of them is invisible structurally and fatal behaviorally. */
#define FIELD_A_BITS 5
#define FIELD_B_BITS 7
#define FIELD_C_BITS 12
#define FIELD_D_BITS 8
__attribute__((noinline)) uint32_t
pack_fields(int32_t a, int32_t b, int32_t c, int32_t d) {
uint32_t packed = 0;
packed |= (uint32_t)a & ((1u << FIELD_A_BITS) - 1u);
packed |= ((uint32_t)b & ((1u << FIELD_B_BITS) - 1u)) << FIELD_A_BITS;
packed |= ((uint32_t)c & ((1u << FIELD_C_BITS) - 1u))
<< (FIELD_A_BITS + FIELD_B_BITS);
packed |= ((uint32_t)d & ((1u << FIELD_D_BITS) - 1u))
<< (FIELD_A_BITS + FIELD_B_BITS + FIELD_C_BITS);
return packed;
}
__attribute__((noinline)) int32_t
unpack_field(uint32_t packed, int32_t which) {
switch (which & 3) {
case 0:
return (int32_t)(packed & ((1u << FIELD_A_BITS) - 1u));
case 1:
return (int32_t)((packed >> FIELD_A_BITS) &
((1u << FIELD_B_BITS) - 1u));
case 2:
return (int32_t)((packed >> (FIELD_A_BITS + FIELD_B_BITS)) &
((1u << FIELD_C_BITS) - 1u));
default:
return (int32_t)((packed >>
(FIELD_A_BITS + FIELD_B_BITS + FIELD_C_BITS)) &
((1u << FIELD_D_BITS) - 1u));
}
}
__attribute__((noinline)) int32_t
codec_roundtrip(int32_t a, int32_t b, int32_t c, int32_t d) {
uint32_t packed = pack_fields(a, b, c, d);
return (unpack_field(packed, 0) == (a & 31)) +
(unpack_field(packed, 1) == (b & 127)) +
(unpack_field(packed, 2) == (c & 4095)) +
(unpack_field(packed, 3) == (d & 255));
} 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
3/3codec_roundtrip pass 26 lines
// glaurung: codec_roundtrip @ 0x1210
int32_t codec_roundtrip(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern unsigned int pack_fields(int, int, int, int);
extern int unpack_field(unsigned int, int);
unsigned int packed;
int local_18;
int local_1c;
int local_20;
unsigned int var0;
int var13;
int var27;
int var3;
int var41;
// x86-64 prologue: save rbp, frame 32 bytes
var0 = pack_fields((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
packed = var0;
var3 = unpack_field(packed, 0);
local_20 = ((unsigned int)(var3) == (unsigned int)(((unsigned long)((unsigned int)(arg0)) & 31)));
var13 = unpack_field(packed, 1);
local_1c = ((unsigned int)(local_20) + ((unsigned int)(var13) == (unsigned int)(((unsigned long)((unsigned int)(arg1)) & 127))));
var27 = unpack_field(packed, 2);
local_18 = ((unsigned int)(local_1c) + ((unsigned int)(var27) == (unsigned int)(((unsigned long)((unsigned int)(arg2)) & 4095))));
var41 = unpack_field(packed, 3);
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(local_18)) + ((unsigned int)(var41) == (unsigned int)(((unsigned long)((unsigned int)(arg3)) & 255)))));
} pack_fields pass 12 lines
// glaurung: pack_fields @ 0x1120
uint32_t pack_fields(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
unsigned int packed;
// x86-64 prologue: save rbp
packed = 0;
packed = ((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 31)) | packed);
packed = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 127))) << 5)) | packed);
packed = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) & 4095))) << 12)) | packed);
packed = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg3)) & 255))) << 24)) | packed);
// x86-64 epilogue: restore rbp
return packed;
} unpack_field pass 21 lines
// glaurung: unpack_field @ 0x1180
int32_t unpack_field(uint32_t arg0, int32_t arg1) {
int local_10;
int var1;
// x86-64 prologue: save rbp
var1 = ((unsigned int)(arg1) & 3);
local_10 = var1;
if (((unsigned long)((unsigned int)(var1)) == 0)) {
return (unsigned int)(((unsigned long)(arg0) & 31));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_10)) - 1))) == 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 5))) & 127));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_10)) - 2))) == 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 12))) & 4095));
} else {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 24))) & 255));
}
}
}
} clang -O2
3/3codec_roundtrip pass 34 lines
// glaurung: codec_roundtrip @ 0x1170
int32_t codec_roundtrip(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern unsigned int pack_fields(int, int, int, int);
extern int unpack_field(unsigned int, int);
unsigned int packed;
long var0;
long var1;
long var15;
int var16;
long var2;
long var25;
int var26;
long var3;
long var35;
int var36;
unsigned int var4;
int var8;
// x86-64 prologue: save callee registers, frame 56 bytes
var0 = (unsigned long)((unsigned int)(arg3));
var1 = (unsigned long)((unsigned int)(arg2));
var2 = (unsigned long)((unsigned int)(arg1));
var3 = (unsigned long)((unsigned int)(arg0));
var4 = pack_fields(arg0, arg1, arg2, arg3);
packed = var4;
var8 = unpack_field(var4, 0);
var15 = ((unsigned int)(var8) == (unsigned int)((var3 & 31)));
var16 = unpack_field(packed, 1);
var25 = (unsigned long)((unsigned int)((((unsigned int)(var16) == (unsigned int)((var2 & 127))) + var15)));
var26 = unpack_field(packed, 2);
var35 = (unsigned long)((unsigned int)((((unsigned int)(var26) == (unsigned int)((var1 & 4095))) + var25)));
var36 = unpack_field(packed, 3);
// x86-64 epilogue: restore callee registers
return (unsigned int)((((unsigned int)(var36) == (unsigned int)((unsigned char)((var0 & 255)))) + var35));
} pack_fields pass 5 lines
// glaurung: pack_fields @ 0x1120
uint32_t pack_fields(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
unsigned int packed;
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 & 127))) << 5))) + (unsigned long)((unsigned int)((arg0 & 31)))))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg2 << 12))) & 0xfff000)))))) | (unsigned long)((unsigned int)((arg3 << 24)))));
} unpack_field pass 17 lines
// glaurung: unpack_field @ 0x1140
int32_t unpack_field(uint32_t arg0, int32_t arg1) {
long var0;
long var2;
var0 = (unsigned long)(arg0);
var2 = (unsigned long)((unsigned int)((arg1 & 3)));
if (((unsigned long)((unsigned int)(var2)) == 2)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 12))) & 4095));
}
if (((unsigned long)((unsigned int)(var2)) == 1)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 5))) & 127));
}
if (((unsigned long)((unsigned int)(var2)) != 0)) {
return (unsigned int)(((unsigned long)((unsigned int)(var0)) >> 24));
}
return (unsigned int)(((unsigned long)(arg0) & 31));
} gcc -O0
3/3codec_roundtrip pass 26 lines
// glaurung: codec_roundtrip @ 0x11d8
int32_t codec_roundtrip(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern unsigned int pack_fields(int, int, int, int);
extern int unpack_field(unsigned int, int);
unsigned int packed;
unsigned int var1;
int var11;
int var13;
long var22;
int var24;
long var33;
int var35;
int var4;
// x86-64 prologue: save rbp, frame 8 bytes
var1 = pack_fields((unsigned long)((unsigned int)(arg0)), (unsigned long)((unsigned int)(arg1)), (unsigned long)((unsigned int)(arg2)), (unsigned long)((unsigned int)(arg3)));
packed = var1;
var4 = unpack_field(packed, 0);
var11 = ((unsigned int)(var4) == (unsigned int)(((unsigned long)((unsigned int)(arg0)) & 31)));
var13 = unpack_field(packed, 1);
var22 = (unsigned long)((unsigned int)((var11 + ((unsigned int)(var13) == (unsigned int)(((unsigned long)((unsigned int)(arg1)) & 127))))));
var24 = unpack_field(packed, 2);
var33 = (unsigned long)((unsigned int)((var22 + ((unsigned int)(var24) == (unsigned int)(((unsigned long)((unsigned int)(arg2)) & 4095))))));
var35 = unpack_field(packed, 3);
// x86-64 epilogue: restore rbp
return (unsigned int)((((unsigned int)(var35) == (unsigned int)((unsigned char)(((unsigned long)((unsigned int)(arg3)) & 255)))) + var33));
} pack_fields pass 12 lines
// glaurung: pack_fields @ 0x1139
uint32_t pack_fields(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
unsigned int packed;
// x86-64 prologue: save rbp
packed = 0;
packed = (packed | (unsigned int)(((unsigned long)((unsigned int)(arg0)) & 31)));
packed = (packed | (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) << 5))) & 4064)));
packed = (packed | (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg2)) << 12))) & 0xfff000)));
packed = (packed | (unsigned int)(((unsigned long)((unsigned int)(arg3)) << 24)));
// x86-64 epilogue: restore rbp
return packed;
} unpack_field pass 26 lines
// glaurung: unpack_field @ 0x1187
int32_t unpack_field(uint32_t arg0, int32_t arg1) {
int var10;
long var2;
// x86-64 prologue: save rbp
var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) & 3)));
if (((unsigned long)((unsigned int)(var2)) == 2)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 12))) & 4095));
} else {
if (((((unsigned long)((unsigned int)(var2)) == 2) | ((long)((int)(var2)) < 2)) == 0)) {
var10 = ((unsigned int)(arg0) >> 24);
// x86-64 epilogue: restore rbp
return (unsigned int)(var10);
}
if (((unsigned long)((unsigned int)(var2)) == 0)) {
return (unsigned int)(((unsigned long)(arg0) & 31));
} else {
if (((unsigned long)((unsigned int)(var2)) == 1)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 5))) & 127));
} else {
var10 = ((unsigned int)(arg0) >> 24);
return (unsigned int)(var10);
}
}
}
} gcc -O2
3/3codec_roundtrip pass 35 lines
// glaurung: codec_roundtrip @ 0x11b0
int32_t codec_roundtrip(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
extern unsigned int pack_fields(int, int, int, int);
extern int unpack_field(unsigned int, int);
unsigned int packed;
long var1;
int var11;
long var13;
int var14;
long var25;
long var27;
int var28;
long var3;
long var31;
int var32;
long var4;
int var6;
unsigned int var7;
var1 = (unsigned long)((unsigned int)(arg1));
var3 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 31)));
var4 = (unsigned long)((unsigned int)(arg2));
var6 = (unsigned int)((unsigned char)(((unsigned long)((unsigned int)(arg3)) & 255)));
var7 = pack_fields(arg0, arg1, arg2, arg3);
packed = var7;
var11 = unpack_field(var7, 0);
var13 = (unsigned long)((unsigned int)(var11));
var14 = unpack_field(packed, 1);
var25 = (unsigned long)((unsigned int)((var4 & 4095)));
var27 = (unsigned long)((unsigned int)((((unsigned int)(var3) == (unsigned int)(var13)) + ((unsigned int)((var1 & 127)) == (unsigned int)(var14)))));
var28 = unpack_field(packed, 2);
var31 = ((unsigned int)(var25) == (unsigned int)(var28));
var32 = unpack_field(packed, 3);
// x86-64 epilogue: tear down frame
return (unsigned int)((((unsigned int)(var6) == (unsigned int)(var32)) + (unsigned long)((unsigned int)(((unsigned int)((unsigned char)((var31 & 255))) + var27)))));
} pack_fields pass 4 lines
// glaurung: pack_fields @ 0x1140
uint32_t pack_fields(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg2 << 12))) & 0xfff000))) | (unsigned long)((unsigned int)((arg3 << 24)))))) | (unsigned long)((unsigned int)((arg0 & 31)))))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg1 << 5))) & 4064)))));
} unpack_field pass 12 lines
// glaurung: unpack_field @ 0x1170
int32_t unpack_field(uint32_t arg0, int32_t arg1) {
long var1;
var1 = (unsigned long)((unsigned int)((arg1 & 3)));
if (((unsigned long)((unsigned int)(var1)) == 1)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 5))) & 127));
}
if (((unsigned long)((unsigned int)(var1)) == 2)) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 12))) & 4095));
}
return (((unsigned long)((unsigned int)(var1)) != 0) ? (unsigned long)((unsigned int)(((unsigned long)(arg0) >> 24))) : (unsigned long)((unsigned int)(((unsigned long)(arg0) & 31))));
}