Fixture 48
gray code
C · 4 functions · 4 lanes · 16 of 16 function-lanes behave identically
All 4 lanes recompile and return the same results as the original.
Gray-code conversion and a bit-reversal permutation. The decode is an xor-shift reduction whose loop cannot be strength-reduced away, and the reversal is a masked swap ladder.
#include <stdint.h>
/* Gray-code conversion and a bit-reversal permutation. The decode is an
* xor-shift reduction whose loop cannot be strength-reduced away, and the
* reversal is a masked swap ladder. */
#define GRAY_MAX 16
__attribute__((noinline)) uint32_t binary_to_gray(uint32_t value) {
return value ^ (value >> 1);
}
__attribute__((noinline)) uint32_t gray_to_binary(uint32_t gray) {
uint32_t value = gray;
value ^= value >> 16;
value ^= value >> 8;
value ^= value >> 4;
value ^= value >> 2;
value ^= value >> 1;
return value;
}
__attribute__((noinline)) uint32_t reverse_bits32(uint32_t value) {
value = ((value & 0x55555555u) << 1) | ((value >> 1) & 0x55555555u);
value = ((value & 0x33333333u) << 2) | ((value >> 2) & 0x33333333u);
value = ((value & 0x0F0F0F0Fu) << 4) | ((value >> 4) & 0x0F0F0F0Fu);
value = ((value & 0x00FF00FFu) << 8) | ((value >> 8) & 0x00FF00FFu);
return (value << 16) | (value >> 16);
}
__attribute__((noinline)) int32_t
gray_sequence(uint32_t *output, int32_t count) {
int32_t index;
if (output == 0 || count < 0 || count > GRAY_MAX) {
return -1;
}
for (index = 0; index < count; ++index) {
output[index] = binary_to_gray((uint32_t)index);
}
return count;
} 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
4/4binary_to_gray pass 6 lines
// glaurung: binary_to_gray @ 0x1110
uint32_t binary_to_gray(uint32_t arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)(arg0) ^ (unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1)))));
} gray_sequence pass 30 lines
// glaurung: gray_sequence @ 0x1210
int32_t gray_sequence(uint32_t * arg0, int32_t arg1) {
extern unsigned int binary_to_gray(unsigned int);
int index;
int local_4;
unsigned int var5;
// x86-64 prologue: save rbp, frame 32 bytes
if ((arg0 == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((long)(arg1) < 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
local_4 = -1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
}
for (index = 0; (index < arg1); index++) {
var5 = binary_to_gray((unsigned long)((unsigned int)(index)));
arg0[(long)(index)] = var5;
}
local_4 = arg1;
// x86-64 epilogue: restore rbp
return (unsigned int)(local_4);
} gray_to_binary pass 13 lines
// glaurung: gray_to_binary @ 0x1130
uint32_t gray_to_binary(uint32_t arg0) {
unsigned int value;
// x86-64 prologue: save rbp
value = arg0;
value = ((unsigned int)(((unsigned int)(value) >> 16)) ^ value);
value = ((unsigned int)(((unsigned int)(value) >> 8)) ^ value);
value = ((unsigned int)(((unsigned int)(value) >> 4)) ^ value);
value = ((unsigned int)(((unsigned int)(value) >> 2)) ^ value);
value = ((unsigned int)(((unsigned int)(value) >> 1)) ^ value);
// x86-64 epilogue: restore rbp
return value;
} reverse_bits32 pass 10 lines
// glaurung: reverse_bits32 @ 0x1180
uint32_t reverse_bits32(uint32_t arg0) {
// x86-64 prologue: save rbp
arg0 = ((unsigned int)(((unsigned long)((unsigned int)((arg0 & 0x55555555))) << 1)) | (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555)));
arg0 = ((unsigned int)(((unsigned long)((unsigned int)((arg0 & 0x33333333))) << 2)) | (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 2))) & 0x33333333)));
arg0 = ((unsigned int)(((unsigned long)((unsigned int)((arg0 & 0xf0f0f0f))) << 4)) | (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 4))) & 0xf0f0f0f)));
arg0 = ((unsigned int)(((unsigned long)((unsigned int)((arg0 & 0xff00ff))) << 8)) | (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 8))) & 0xff00ff)));
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) << 16))) | (unsigned long)((unsigned int)(((unsigned long)(arg0) >> 16)))));
} clang -O2
4/4binary_to_gray pass 4 lines
// glaurung: binary_to_gray @ 0x1110
uint32_t binary_to_gray(uint32_t arg0) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1))) ^ arg0));
} gray_sequence pass 39 lines
// glaurung: gray_sequence @ 0x1190
int32_t gray_sequence(uint32_t * arg0, int32_t arg1) {
extern unsigned int binary_to_gray(unsigned int);
int index;
long local_10;
long local_18;
long local_8;
long var0;
long var1;
unsigned int var12;
long var2;
long var3;
long var8;
local_8 = var0;
local_10 = var1;
local_18 = var2;
var3 = 0xffffffff;
if ((arg0 == 0)) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var3);
}
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
// x86-64 epilogue: tear down frame
return (unsigned int)(var3);
}
if (((unsigned long)((unsigned int)(arg1)) == 0)) {
return 0;
}
var8 = (long)arg0;
var3 = (unsigned long)((unsigned int)(arg1));
index = 0;
do {
var12 = binary_to_gray((unsigned long)((unsigned int)(index)));
*(int *)((var8 + index * 4)) = var12;
index = (index + 1);
} while ((var3 != index));
// x86-64 epilogue: tear down frame
return (unsigned int)(var3);
} gray_to_binary pass 13 lines
// glaurung: gray_to_binary @ 0x1120
uint32_t gray_to_binary(uint32_t arg0) {
unsigned int value;
long var11;
long var17;
long var23;
long var5;
var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 16))) ^ arg0)));
var11 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) >> 8))) ^ var5)));
var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var11)) >> 4))) ^ var11)));
var23 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var17)) >> 2))) ^ var17)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var23)) >> 1))) ^ var23));
} reverse_bits32 pass 10 lines
// glaurung: reverse_bits32 @ 0x1150
uint32_t reverse_bits32(uint32_t arg0) {
int var0;
long var12;
long var21;
var0 = (unsigned int)((((((arg0 & 255) << 24) | (((arg0 >> 8) & 255) << 16)) | (((arg0 >> 16) & 255) << 8)) | ((arg0 >> 24) & 255)));
var12 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) >> 4))) & 0xf0f0f0f))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var0)) & 0xf0f0f0f))) << 4))))));
var21 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var12)) >> 2))) & 0x33333333))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var12)) & 0x33333333))) * 4))));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) >> 1))) & 0x55555555))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var21)) & 0x55555555))) * 2)));
} gcc -O0
4/4binary_to_gray pass 6 lines
// glaurung: binary_to_gray @ 0x1119
uint32_t binary_to_gray(uint32_t arg0) {
// x86-64 prologue: save rbp
// x86-64 epilogue: restore rbp
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1))) ^ arg0));
} gray_sequence pass 27 lines
// glaurung: gray_sequence @ 0x11f5
int32_t gray_sequence(uint32_t * arg0, int32_t arg1) {
extern unsigned int binary_to_gray(unsigned int);
int index;
long var7;
unsigned int var8;
// x86-64 prologue: save rbp, frame 8 bytes
if ((arg0 == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((long)(arg1) < 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
// x86-64 epilogue: restore rbp
return 0xffffffff;
}
for (index = 0; (index < arg1); index++) {
var7 = (long)((((long)(index) * 4) + (long)arg0));
var8 = binary_to_gray((unsigned long)((unsigned int)(index)));
*(int *)((var7)) = var8;
}
// x86-64 epilogue: restore rbp
return (unsigned int)(arg1);
} gray_to_binary pass 13 lines
// glaurung: gray_to_binary @ 0x112e
uint32_t gray_to_binary(uint32_t arg0) {
unsigned int value;
// x86-64 prologue: save rbp
value = arg0;
value = (value ^ (unsigned int)(((unsigned int)(value) >> 16)));
value = (value ^ (unsigned int)(((unsigned int)(value) >> 8)));
value = (value ^ (unsigned int)(((unsigned int)(value) >> 4)));
value = (value ^ (unsigned int)(((unsigned int)(value) >> 2)));
value = (value ^ (unsigned int)(((unsigned int)(value) >> 1)));
// x86-64 epilogue: restore rbp
return value;
} reverse_bits32 pass 10 lines
// glaurung: reverse_bits32 @ 0x1170
uint32_t reverse_bits32(uint32_t arg0) {
// x86-64 prologue: save rbp
arg0 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555)) | (unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) & -0x55555556LL)));
arg0 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 2))) & 0x33333333)) | (unsigned int)(((unsigned long)((unsigned int)((arg0 << 2))) & -0x33333334LL)));
arg0 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 4))) & 0xf0f0f0f)) | (unsigned int)(((unsigned long)((unsigned int)((arg0 << 4))) & -0xf0f0f10LL)));
arg0 = ((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 8))) & 0xff00ff)) | (unsigned int)(((unsigned long)((unsigned int)((arg0 << 8))) & -0xff0100LL)));
// x86-64 epilogue: restore rbp
return (((unsigned long)(arg0) << 16) | ((unsigned long)(arg0) >> 16));
} gcc -O2
4/4binary_to_gray pass 4 lines
// glaurung: binary_to_gray @ 0x1120
uint32_t binary_to_gray(uint32_t arg0) {
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg0) >> 1))) ^ arg0));
} gray_sequence pass 30 lines
// glaurung: gray_sequence @ 0x11b0
int32_t gray_sequence(uint32_t * arg0, int32_t arg1) {
extern unsigned int binary_to_gray(unsigned int);
int index;
long var1;
long var2;
long var3;
unsigned int var6;
long zf_8;
if ((arg0 == 0)) {
return (unsigned int)(-1);
}
var1 = (unsigned long)((unsigned int)(arg1));
if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
return 0xffffffff;
} else {
var2 = (long)arg0;
var3 = (unsigned long)((unsigned int)((arg1 - 1)));
index = 0;
if (((unsigned long)((unsigned int)(arg1)) != 0)) {
do {
var6 = binary_to_gray((unsigned long)((unsigned int)(index)));
*(int *)((var2 + index * 4)) = var6;
zf_8 = (index == var3);
index = (index + 1);
} while ((zf_8 == 0));
}
return (unsigned int)(var1);
}
} gray_to_binary pass 13 lines
// glaurung: gray_to_binary @ 0x1130
uint32_t gray_to_binary(uint32_t arg0) {
unsigned int value;
long var11;
long var17;
long var23;
long var5;
var5 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 16))) ^ arg0)));
var11 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) >> 8))) ^ var5)));
var17 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var11)) >> 4))) ^ var11)));
var23 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var17)) >> 2))) ^ var17)));
return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var23)) >> 1))) ^ var23));
} reverse_bits32 pass 10 lines
// glaurung: reverse_bits32 @ 0x1160
uint32_t reverse_bits32(uint32_t arg0) {
long var10;
long var20;
long var32;
var10 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 + arg0))) & -0x55555556LL))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)(arg0) >> 1))) & 0x55555555))))));
var20 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var10 * 4))) & -0x33333334LL))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var10)) >> 2))) & 0x33333333))))));
var32 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var20)) << 4))) & -0xf0f0f10LL))) | (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var20)) >> 4))) & 0xf0f0f0f))))));
return (unsigned int)(((((((unsigned int)(var32) & 255) << 24) | ((((unsigned int)(var32) >> 8) & 255) << 16)) | ((((unsigned int)(var32) >> 16) & 255) << 8)) | (((unsigned int)(var32) >> 24) & 255)));
}