128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#!/bin/bash
228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#
328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#  findmisopt
428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#
528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      This is a quick and dirty hack to potentially find a misoptimization
628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      problem. Mostly its to work around problems in bugpoint that prevent
728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      it from finding a problem unless the set of failing optimizations are
828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      known and given to it on the command line.
928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#
1018d52f2fb551c295bbce4c7d7357f4050b06e926Duncan Sands#      Given a bitcode file that produces correct output (or return code), 
1128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      this script will run through all the optimizations passes that gccas
1228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      uses (in the same order) and will narrow down which optimizations
1328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      cause the program either generate different output or return a 
1428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      different result code. When the passes have been narrowed down, 
15a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer#      bugpoint is invoked to further refine the problem to its origin. If a
16a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer#      release version of bugpoint is available it will be used, otherwise 
17a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer#      debug.
1828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#
1928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#   Usage:
2028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      findmisopt bcfile outdir progargs [match]
2128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#
2228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#   Where:
2328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      bcfile 
2418d52f2fb551c295bbce4c7d7357f4050b06e926Duncan Sands#          is the bitcode file input (the unoptimized working case)
2528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      outdir
2628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#          is a directory into which intermediate results are placed
2728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#      progargs
2828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#          is a single argument containing all the arguments the program needs
292232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencer#      proginput
302232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencer#          is a file name from which stdin should be directed
31a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer#      match
3228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#          if specified to any value causes the result code of the program to
3328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#          be used to determine success/fail. If not specified success/fail is
3428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#          determined by diffing the program's output with the non-optimized
3528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#          output.
3628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer#       
37e4d8f33b0f1dfe0e6b2741c6936b26f21031ac90Reid Spencerif [ "$#" -lt 3 ] ; then
38e4d8f33b0f1dfe0e6b2741c6936b26f21031ac90Reid Spencer  echo "usage: findmisopt bcfile outdir progargs [match]"
39e4d8f33b0f1dfe0e6b2741c6936b26f21031ac90Reid Spencer  exit 1
40e4d8f33b0f1dfe0e6b2741c6936b26f21031ac90Reid Spencerfi
41e4d8f33b0f1dfe0e6b2741c6936b26f21031ac90Reid Spencer
42a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencerdir="${0%%/utils/findmisopt}"
43a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencerif [ -x "$dir/Release/bin/bugpoint" ] ; then
44a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer  bugpoint="$dir/Release/bin/bugpoint"
45a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencerelif [ -x "$dir/Debug/bin/bugpoint" ] ; then
46a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer  bugpoint="$dir/Debug/bin/bugpoint"
47a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencerelse
48a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer  echo "findmisopt: bugpoint not found"
49a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer  exit 1
50a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencerfi
51a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer
5228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerbcfile="$1"
5328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spenceroutdir="$2"
5428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerargs="$3"
552232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencerinput="$4"
562232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencerif [ ! -f "$input" ] ; then
572232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencer  input="/dev/null"
582232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencerfi
592232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencermatch="$5"
6028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencername=`basename $bcfile .bc`
6128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerll="$outdir/${name}.ll"
6228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencers="$outdir/${name}.s"
6328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerprog="$outdir/${name}"
6428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerout="$outdir/${name}.out"
6528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spenceroptbc="$outdir/${name}.opt.bc"
6628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spenceroptll="$outdir/${name}.opt.ll"
6728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spenceropts="$outdir/${name}.opt.s"
6828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spenceroptprog="$outdir/${name}.opt"
6928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spenceroptout="$outdir/${name}.opt.out"
70f8463a38bf04b822d009e9e4eaae2e4a3c930da4Reid Spencerldflags="-lstdc++ -lm -ldl -lc"
7128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
7228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerecho "Test Name: $name"
7328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerecho "Unoptimized program: $prog"
7428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerecho "  Optimized program: $optprog"
7528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
76f6101ac7bcb06ec3488bd5afab38f20ae6855e35Reid Spencer# Define the list of optimizations to run. This comprises the same set of 
77f6101ac7bcb06ec3488bd5afab38f20ae6855e35Reid Spencer# optimizations that opt -std-compile-opts and gccld run, in the same order.
78f6101ac7bcb06ec3488bd5afab38f20ae6855e35Reid Spenceropt_switches=`llvm-as < /dev/null -o - | opt -std-compile-opts -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'`
7975338097c786eea1c461e744a2c45af78f56286fMichael J. Spencerall_switches="$opt_switches"
80f6101ac7bcb06ec3488bd5afab38f20ae6855e35Reid Spencerecho "Passes : $all_switches"
81f6101ac7bcb06ec3488bd5afab38f20ae6855e35Reid Spencer
82024409995684ed37250a0d6dec4956316368a42aReid Spencer# Create output directory if it doesn't exist
83024409995684ed37250a0d6dec4956316368a42aReid Spencerif [ -f "$outdir" ] ; then
84024409995684ed37250a0d6dec4956316368a42aReid Spencer  echo "$outdir is not a directory"
85024409995684ed37250a0d6dec4956316368a42aReid Spencer  exit 1
86024409995684ed37250a0d6dec4956316368a42aReid Spencerfi
87024409995684ed37250a0d6dec4956316368a42aReid Spencer
88024409995684ed37250a0d6dec4956316368a42aReid Spencerif [ ! -d "$outdir" ] ; then
89024409995684ed37250a0d6dec4956316368a42aReid Spencer  mkdir "$outdir" || exit 1
90024409995684ed37250a0d6dec4956316368a42aReid Spencerfi
9128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
9228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer# Generate the disassembly
9328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerllvm-dis "$bcfile" -o "$ll" -f || exit 1
9428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
952232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencer# Generate the non-optimized program and its output
9628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerllc "$bcfile" -o "$s" -f || exit 1
97f8463a38bf04b822d009e9e4eaae2e4a3c930da4Reid Spencergcc "$s" -o "$prog" $ldflags || exit 1
982232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencer"$prog" $args > "$out" 2>&1 <$input
992232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencerex1=$?
10028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
10128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer# Current set of switches is empty
10228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerfunction tryit {
10328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  switches_to_use="$1"
10428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  opt $switches_to_use "$bcfile" -o "$optbc" -f || exit
10528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  llvm-dis "$optbc" -o "$optll" -f || exit
10628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  llc "$optbc" -o "$opts" -f || exit
107f8463a38bf04b822d009e9e4eaae2e4a3c930da4Reid Spencer  gcc "$opts" -o "$optprog" $ldflags || exit
1082232a80ef13537c2ea840e4d877655b6e1ca8f62Reid Spencer  "$optprog" $args > "$optout" 2>&1 <"$input"
10928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  ex2=$?
11028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
11128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  if [ -n "$match" ] ; then
11228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    if [ "$ex1" -ne "$ex2" ] ; then
11328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo "Return code not the same with these switches:"
11428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo $switches
11528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo "Unoptimized returned: $ex1"
11628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo "Optimized   returned: $ex2"
11728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      return 0
11828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    fi
11928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  else
12028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    diff "$out" "$optout" > /dev/null
12128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    if [ $? -ne 0 ] ; then
12228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo "Diff fails with these switches:"
12328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo $switches
12428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      echo "Differences:"
125ba07a6922289d65690ce5f39301cd7e75c97d89eReid Spencer      diff "$out" "$optout" | head
12628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer      return 0;
12728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    fi
12828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  fi
12928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  return 1
13028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer}
13128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
132024409995684ed37250a0d6dec4956316368a42aReid Spencerecho "Trying to find optimization that breaks program:"
13328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerfor sw in $all_switches ; do
134024409995684ed37250a0d6dec4956316368a42aReid Spencer  echo -n " $sw"
13528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  switches="$switches $sw"
13628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  if tryit "$switches" ; then
13728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    break;
13828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  fi
13928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerdone
14028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
1416d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencer# Terminate the previous output with a newline
1426d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencerecho ""
1436d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencer
1446d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencer# Determine if we're done because none of the optimizations broke the program
1456d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencerif [ "$switches" == " $all_switches" ] ; then
1466d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencer  echo "The program did not miscompile"
1476d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencer  exit 0
1486d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencerfi
1496d0fbd4185ae24f342459b1ed4ab45062bff1a66Reid Spencer
15028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerfinal=""
15128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerwhile [ ! -z "$switches" ] ; do
15228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  trimmed=`echo "$switches" | sed -e 's/^ *\(-[^ ]*\).*/\1/'`
15328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  switches=`echo "$switches" | sed -e 's/^ *-[^ ]* *//'`
15428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  echo "Trimmed $trimmed from left"
15528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  tryit "$final $switches"
15628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  if [ "$?" -eq "0" ] ; then
15728b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    echo "Still Failing .. continuing ..."
15828b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    continue
15928b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  else
16028b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    echo "Found required early pass: $trimmed"
16128b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    final="$final $trimmed"
16228b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer    continue
16328b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  fi
16428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer  echo "Next Loop"
16528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerdone
16628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
167dd2b95534f866ec6f31df101624a715612c97ffaReid Spencerif [ "$final" == " $all_switches" ] ; then
168024409995684ed37250a0d6dec4956316368a42aReid Spencer  echo "findmisopt: All optimizations pass. Perhaps this isn't a misopt?"
169dd2b95534f866ec6f31df101624a715612c97ffaReid Spencer  exit 0
170dd2b95534f866ec6f31df101624a715612c97ffaReid Spencerfi
171dd2b95534f866ec6f31df101624a715612c97ffaReid Spencerecho "Smallest Optimization list=$final"
172a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencer
173a8c3ff456aedbc55ac5ccd853e721812d0369ea0Reid Spencerbpcmd="$bugpoint -run-llc -disable-loop-extraction --output "$out" --input /dev/null $bcfile $final --args $args"
17428b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer
17528b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencerecho "Running: $bpcmd"
17628b7c7feab6219f4c9c7efc3b71a0a3f4880a14dReid Spencer$bpcmd
177dd2b95534f866ec6f31df101624a715612c97ffaReid Spencerecho "findmisopt finished."
178