#!/usr/bin/env python"""Reduces GlobalISel failures.This script is a utility to reduce tests that GlobalISelfails to compile.It runs llc to get the error message using a regex and createsa custom command to check that specific error. Then, it runs bugpointwith the custom command."""from__future__importprint_functionimportargparseimportreimportsubprocessimportsysimporttempfileimportosdeflog(msg):print(msg)defhr():log('-'*50)deflog_err(msg):print('ERROR: {}'.format(msg),file=sys.stderr)defcheck_path(path):ifnotos.path.exists(path):log_err('{} does not exist.'.format(path))raisereturnpathdefcheck_bin(build_dir,bin_name):file_name='{}/bin/{}'.format(build_dir,bin_name)returncheck_path(file_name)defrun_llc(llc,irfile):pr=subprocess.Popen([llc,'-o','-','-global-isel','-pass-remarks-missed=gisel',irfile],stdout=subprocess.PIPE,stderr=subprocess.PIPE)out,err=pr.communicate()res=pr.wait()ifres==0:return0re_err=re.compile(r'LLVM ERROR: ([a-z\s]+):.*(G_INTRINSIC[_A-Z]* <intrinsic:@[a-zA-Z0-9\.]+>|G_[A-Z_]+)')match=re_err.match(err)ifnotmatch:return0else:return[match.group(1),match.group(2)]defrun_bugpoint(bugpoint_bin,llc_bin,opt_bin,tmp,ir_file):compileCmd='-compile-command={} -c {} {}'.format(os.path.realpath(__file__),llc_bin,tmp)pr=subprocess.Popen([bugpoint_bin,'-compile-custom',compileCmd,'-opt-command={}'.format(opt_bin),ir_file])res=pr.wait()ifres!=0:log_err("Unable to reduce the test.")raisedefrun_bugpoint_check():path_to_llc=sys.argv[2]path_to_err=sys.argv[3]path_to_ir=sys.argv[4]withopen(path_to_err,'r')asf:err=f.read()res=run_llc(path_to_llc,path_to_ir)ifres==0:return0log('GlobalISed failed, {}: {}'.format(res[0],res[1]))ifres!=err.split(';'):return0else:return1defmain():# Check if this is called by bugpoint.iflen(sys.argv)==5andsys.argv[1]=='-c':sys.exit(run_bugpoint_check())# Parse arguments.parser=argparse.ArgumentParser(description=__doc__,formatter_class=argparse.RawTextHelpFormatter)parser.add_argument('BuildDir',help="Path to LLVM build directory")parser.add_argument('IRFile',help="Path to the input IR file")args=parser.parse_args()# Check if the binaries exist.build_dir=check_path(args.BuildDir)ir_file=check_path(args.IRFile)llc_bin=check_bin(build_dir,'llc')opt_bin=check_bin(build_dir,'opt')bugpoint_bin=check_bin(build_dir,'bugpoint')# Run llc to see if GlobalISel fails.log('Running llc...')res=run_llc(llc_bin,ir_file)ifres==0:log_err("Expected failure")raisehr()log('GlobalISel failed, {}: {}.'.format(res[0],res[1]))tmp=tempfile.NamedTemporaryFile()log('Writing error to {} for bugpoint.'.format(tmp.name))tmp.write(';'.join(res))tmp.flush()hr()# Run bugpoint.log('Running bugpoint...')run_bugpoint(bugpoint_bin,llc_bin,opt_bin,tmp.name,ir_file)hr()log('Done!')hr()output_file='bugpoint-reduced-simplified.bc'log('Run llvm-dis to disassemble the output:')log('$ {}/bin/llvm-dis -o - {}'.format(build_dir,output_file))log('Run llc to reproduce the problem:')log('$ {}/bin/llc -o - -global-isel ''-pass-remarks-missed=gisel {}'.format(build_dir,output_file))if__name__=='__main__':main()