#!/bin/bash
#
# usage: cd src; bash chooseopts.sh target filename.c formatname
# e.g.
#   $ bash chooseopts.sh linux-x86-64-native rawSHA1_ng_fmt.c raw-sha1-ng | sort -g
#

declare -a  optimizers=(
    $(gcc --help=optimizers | awk '/^[ ]*-f/ {printf "%s\n%s\n",$1,gensub(/^-f/,"-fno-",1,$1)}')
);
declare -a  scores
declare -r  compiler="gcc"

# for every optimization option gcc reports it supports, build an object file
# and benchmark it.
for ((i = 0; i < ${#optimizers[@]}; i++)); do
    # build a new john with this flag applied to this object file.
    if ! make ${1} MAKE="make -W ${2}" CC="$compiler -frandom-seed=seed ${optimizers[i]}" &> /dev/null; then
        # code doesn't compile, skip it.
        continue
    fi

    # if it built, find checksum of this code.
    checksum="$(objdump -d ${2//.c/.o} | cksum | sed 's/ //g')"

    # if another flag generated the same code, we don't need to benchmark it,
    # we can just re-use the results.
    if test -n "${scores[checksum]}"; then
        printf "optimizer %s code cached\n" ${optimizers[i]} 1>&2
    else
        # no luck, we need to run it.
        if ! results=$(../run/john --test --format=${3}); then
            # crashes, or doesn't pass test.
            continue;
        fi

        # cache the scores.
        scores[checksum]="${results}"
    fi

    # output score.
    printf "%s %s\n" "${scores[checksum]}" "${optimizers[i]}"
done

