1*9880d681SAndroid Build Coastguard Worker#!/bin/bash 2*9880d681SAndroid Build Coastguard Worker# 3*9880d681SAndroid Build Coastguard Worker# findmisopt 4*9880d681SAndroid Build Coastguard Worker# 5*9880d681SAndroid Build Coastguard Worker# This is a quick and dirty hack to potentially find a misoptimization 6*9880d681SAndroid Build Coastguard Worker# problem. Mostly its to work around problems in bugpoint that prevent 7*9880d681SAndroid Build Coastguard Worker# it from finding a problem unless the set of failing optimizations are 8*9880d681SAndroid Build Coastguard Worker# known and given to it on the command line. 9*9880d681SAndroid Build Coastguard Worker# 10*9880d681SAndroid Build Coastguard Worker# Given a bitcode file that produces correct output (or return code), 11*9880d681SAndroid Build Coastguard Worker# this script will run through all the optimizations passes that gccas 12*9880d681SAndroid Build Coastguard Worker# uses (in the same order) and will narrow down which optimizations 13*9880d681SAndroid Build Coastguard Worker# cause the program either generate different output or return a 14*9880d681SAndroid Build Coastguard Worker# different result code. When the passes have been narrowed down, 15*9880d681SAndroid Build Coastguard Worker# bugpoint is invoked to further refine the problem to its origin. If a 16*9880d681SAndroid Build Coastguard Worker# release version of bugpoint is available it will be used, otherwise 17*9880d681SAndroid Build Coastguard Worker# debug. 18*9880d681SAndroid Build Coastguard Worker# 19*9880d681SAndroid Build Coastguard Worker# Usage: 20*9880d681SAndroid Build Coastguard Worker# findmisopt bcfile outdir progargs [match] 21*9880d681SAndroid Build Coastguard Worker# 22*9880d681SAndroid Build Coastguard Worker# Where: 23*9880d681SAndroid Build Coastguard Worker# bcfile 24*9880d681SAndroid Build Coastguard Worker# is the bitcode file input (the unoptimized working case) 25*9880d681SAndroid Build Coastguard Worker# outdir 26*9880d681SAndroid Build Coastguard Worker# is a directory into which intermediate results are placed 27*9880d681SAndroid Build Coastguard Worker# progargs 28*9880d681SAndroid Build Coastguard Worker# is a single argument containing all the arguments the program needs 29*9880d681SAndroid Build Coastguard Worker# proginput 30*9880d681SAndroid Build Coastguard Worker# is a file name from which stdin should be directed 31*9880d681SAndroid Build Coastguard Worker# match 32*9880d681SAndroid Build Coastguard Worker# if specified to any value causes the result code of the program to 33*9880d681SAndroid Build Coastguard Worker# be used to determine success/fail. If not specified success/fail is 34*9880d681SAndroid Build Coastguard Worker# determined by diffing the program's output with the non-optimized 35*9880d681SAndroid Build Coastguard Worker# output. 36*9880d681SAndroid Build Coastguard Worker# 37*9880d681SAndroid Build Coastguard Workerif [ "$#" -lt 3 ] ; then 38*9880d681SAndroid Build Coastguard Worker echo "usage: findmisopt bcfile outdir progargs [match]" 39*9880d681SAndroid Build Coastguard Worker exit 1 40*9880d681SAndroid Build Coastguard Workerfi 41*9880d681SAndroid Build Coastguard Worker 42*9880d681SAndroid Build Coastguard Workerdir="${0%%/utils/findmisopt}" 43*9880d681SAndroid Build Coastguard Workerif [ -x "$dir/Release/bin/bugpoint" ] ; then 44*9880d681SAndroid Build Coastguard Worker bugpoint="$dir/Release/bin/bugpoint" 45*9880d681SAndroid Build Coastguard Workerelif [ -x "$dir/Debug/bin/bugpoint" ] ; then 46*9880d681SAndroid Build Coastguard Worker bugpoint="$dir/Debug/bin/bugpoint" 47*9880d681SAndroid Build Coastguard Workerelse 48*9880d681SAndroid Build Coastguard Worker echo "findmisopt: bugpoint not found" 49*9880d681SAndroid Build Coastguard Worker exit 1 50*9880d681SAndroid Build Coastguard Workerfi 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Workerbcfile="$1" 53*9880d681SAndroid Build Coastguard Workeroutdir="$2" 54*9880d681SAndroid Build Coastguard Workerargs="$3" 55*9880d681SAndroid Build Coastguard Workerinput="$4" 56*9880d681SAndroid Build Coastguard Workerif [ ! -f "$input" ] ; then 57*9880d681SAndroid Build Coastguard Worker input="/dev/null" 58*9880d681SAndroid Build Coastguard Workerfi 59*9880d681SAndroid Build Coastguard Workermatch="$5" 60*9880d681SAndroid Build Coastguard Workername=`basename $bcfile .bc` 61*9880d681SAndroid Build Coastguard Workerll="$outdir/${name}.ll" 62*9880d681SAndroid Build Coastguard Workers="$outdir/${name}.s" 63*9880d681SAndroid Build Coastguard Workerprog="$outdir/${name}" 64*9880d681SAndroid Build Coastguard Workerout="$outdir/${name}.out" 65*9880d681SAndroid Build Coastguard Workeroptbc="$outdir/${name}.opt.bc" 66*9880d681SAndroid Build Coastguard Workeroptll="$outdir/${name}.opt.ll" 67*9880d681SAndroid Build Coastguard Workeropts="$outdir/${name}.opt.s" 68*9880d681SAndroid Build Coastguard Workeroptprog="$outdir/${name}.opt" 69*9880d681SAndroid Build Coastguard Workeroptout="$outdir/${name}.opt.out" 70*9880d681SAndroid Build Coastguard Workerldflags="-lstdc++ -lm -ldl -lc" 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard Workerecho "Test Name: $name" 73*9880d681SAndroid Build Coastguard Workerecho "Unoptimized program: $prog" 74*9880d681SAndroid Build Coastguard Workerecho " Optimized program: $optprog" 75*9880d681SAndroid Build Coastguard Worker 76*9880d681SAndroid Build Coastguard Worker# Define the list of optimizations to run. This comprises the same set of 77*9880d681SAndroid Build Coastguard Worker# optimizations that opt -O3 runs, in the same order. 78*9880d681SAndroid Build Coastguard Workeropt_switches=`llvm-as < /dev/null -o - | opt -O3 -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'` 79*9880d681SAndroid Build Coastguard Workerall_switches="$opt_switches" 80*9880d681SAndroid Build Coastguard Workerecho "Passes : $all_switches" 81*9880d681SAndroid Build Coastguard Worker 82*9880d681SAndroid Build Coastguard Worker# Create output directory if it doesn't exist 83*9880d681SAndroid Build Coastguard Workerif [ -f "$outdir" ] ; then 84*9880d681SAndroid Build Coastguard Worker echo "$outdir is not a directory" 85*9880d681SAndroid Build Coastguard Worker exit 1 86*9880d681SAndroid Build Coastguard Workerfi 87*9880d681SAndroid Build Coastguard Worker 88*9880d681SAndroid Build Coastguard Workerif [ ! -d "$outdir" ] ; then 89*9880d681SAndroid Build Coastguard Worker mkdir "$outdir" || exit 1 90*9880d681SAndroid Build Coastguard Workerfi 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker# Generate the disassembly 93*9880d681SAndroid Build Coastguard Workerllvm-dis "$bcfile" -o "$ll" -f || exit 1 94*9880d681SAndroid Build Coastguard Worker 95*9880d681SAndroid Build Coastguard Worker# Generate the non-optimized program and its output 96*9880d681SAndroid Build Coastguard Workerllc "$bcfile" -o "$s" -f || exit 1 97*9880d681SAndroid Build Coastguard Workergcc "$s" -o "$prog" $ldflags || exit 1 98*9880d681SAndroid Build Coastguard Worker"$prog" $args > "$out" 2>&1 <$input 99*9880d681SAndroid Build Coastguard Workerex1=$? 100*9880d681SAndroid Build Coastguard Worker 101*9880d681SAndroid Build Coastguard Worker# Current set of switches is empty 102*9880d681SAndroid Build Coastguard Workerfunction tryit { 103*9880d681SAndroid Build Coastguard Worker switches_to_use="$1" 104*9880d681SAndroid Build Coastguard Worker opt $switches_to_use "$bcfile" -o "$optbc" -f || exit 105*9880d681SAndroid Build Coastguard Worker llvm-dis "$optbc" -o "$optll" -f || exit 106*9880d681SAndroid Build Coastguard Worker llc "$optbc" -o "$opts" -f || exit 107*9880d681SAndroid Build Coastguard Worker gcc "$opts" -o "$optprog" $ldflags || exit 108*9880d681SAndroid Build Coastguard Worker "$optprog" $args > "$optout" 2>&1 <"$input" 109*9880d681SAndroid Build Coastguard Worker ex2=$? 110*9880d681SAndroid Build Coastguard Worker 111*9880d681SAndroid Build Coastguard Worker if [ -n "$match" ] ; then 112*9880d681SAndroid Build Coastguard Worker if [ "$ex1" -ne "$ex2" ] ; then 113*9880d681SAndroid Build Coastguard Worker echo "Return code not the same with these switches:" 114*9880d681SAndroid Build Coastguard Worker echo $switches 115*9880d681SAndroid Build Coastguard Worker echo "Unoptimized returned: $ex1" 116*9880d681SAndroid Build Coastguard Worker echo "Optimized returned: $ex2" 117*9880d681SAndroid Build Coastguard Worker return 0 118*9880d681SAndroid Build Coastguard Worker fi 119*9880d681SAndroid Build Coastguard Worker else 120*9880d681SAndroid Build Coastguard Worker diff "$out" "$optout" > /dev/null 121*9880d681SAndroid Build Coastguard Worker if [ $? -ne 0 ] ; then 122*9880d681SAndroid Build Coastguard Worker echo "Diff fails with these switches:" 123*9880d681SAndroid Build Coastguard Worker echo $switches 124*9880d681SAndroid Build Coastguard Worker echo "Differences:" 125*9880d681SAndroid Build Coastguard Worker diff "$out" "$optout" | head 126*9880d681SAndroid Build Coastguard Worker return 0; 127*9880d681SAndroid Build Coastguard Worker fi 128*9880d681SAndroid Build Coastguard Worker fi 129*9880d681SAndroid Build Coastguard Worker return 1 130*9880d681SAndroid Build Coastguard Worker} 131*9880d681SAndroid Build Coastguard Worker 132*9880d681SAndroid Build Coastguard Workerecho "Trying to find optimization that breaks program:" 133*9880d681SAndroid Build Coastguard Workerfor sw in $all_switches ; do 134*9880d681SAndroid Build Coastguard Worker echo -n " $sw" 135*9880d681SAndroid Build Coastguard Worker switches="$switches $sw" 136*9880d681SAndroid Build Coastguard Worker if tryit "$switches" ; then 137*9880d681SAndroid Build Coastguard Worker break; 138*9880d681SAndroid Build Coastguard Worker fi 139*9880d681SAndroid Build Coastguard Workerdone 140*9880d681SAndroid Build Coastguard Worker 141*9880d681SAndroid Build Coastguard Worker# Terminate the previous output with a newline 142*9880d681SAndroid Build Coastguard Workerecho "" 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Worker# Determine if we're done because none of the optimizations broke the program 145*9880d681SAndroid Build Coastguard Workerif [ "$switches" == " $all_switches" ] ; then 146*9880d681SAndroid Build Coastguard Worker echo "The program did not miscompile" 147*9880d681SAndroid Build Coastguard Worker exit 0 148*9880d681SAndroid Build Coastguard Workerfi 149*9880d681SAndroid Build Coastguard Worker 150*9880d681SAndroid Build Coastguard Workerfinal="" 151*9880d681SAndroid Build Coastguard Workerwhile [ ! -z "$switches" ] ; do 152*9880d681SAndroid Build Coastguard Worker trimmed=`echo "$switches" | sed -e 's/^ *\(-[^ ]*\).*/\1/'` 153*9880d681SAndroid Build Coastguard Worker switches=`echo "$switches" | sed -e 's/^ *-[^ ]* *//'` 154*9880d681SAndroid Build Coastguard Worker echo "Trimmed $trimmed from left" 155*9880d681SAndroid Build Coastguard Worker tryit "$final $switches" 156*9880d681SAndroid Build Coastguard Worker if [ "$?" -eq "0" ] ; then 157*9880d681SAndroid Build Coastguard Worker echo "Still Failing .. continuing ..." 158*9880d681SAndroid Build Coastguard Worker continue 159*9880d681SAndroid Build Coastguard Worker else 160*9880d681SAndroid Build Coastguard Worker echo "Found required early pass: $trimmed" 161*9880d681SAndroid Build Coastguard Worker final="$final $trimmed" 162*9880d681SAndroid Build Coastguard Worker continue 163*9880d681SAndroid Build Coastguard Worker fi 164*9880d681SAndroid Build Coastguard Worker echo "Next Loop" 165*9880d681SAndroid Build Coastguard Workerdone 166*9880d681SAndroid Build Coastguard Worker 167*9880d681SAndroid Build Coastguard Workerif [ "$final" == " $all_switches" ] ; then 168*9880d681SAndroid Build Coastguard Worker echo "findmisopt: All optimizations pass. Perhaps this isn't a misopt?" 169*9880d681SAndroid Build Coastguard Worker exit 0 170*9880d681SAndroid Build Coastguard Workerfi 171*9880d681SAndroid Build Coastguard Workerecho "Smallest Optimization list=$final" 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Workerbpcmd="$bugpoint -run-llc -disable-loop-extraction --output "$out" --input /dev/null $bcfile $final --args $args" 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Workerecho "Running: $bpcmd" 176*9880d681SAndroid Build Coastguard Worker$bpcmd 177*9880d681SAndroid Build Coastguard Workerecho "findmisopt finished." 178