#!/usr/bin/env bash # 优化效果对比:测量 O0 vs O1 的编译时间和运行时间 # 用法: bash scripts/bench_ir.sh [--test-dir=] [--result-dir=] set -uo pipefail PROJECT_ROOT=$(cd "$(dirname "$0")/.." ; pwd) TEST_CASE_DIR="${PROJECT_ROOT}/test/test_case" RESULT_DIR="${PROJECT_ROOT}/test/test_result/bench" while [[ $# -gt 0 ]]; do case "$1" in --test-dir=*) TEST_CASE_DIR="${1#*=}" ;; --result-dir=*) RESULT_DIR="${1#*=}" ;; *) echo "未知参数: $1" >&2; exit 1 ;; esac shift done compiler="${PROJECT_ROOT}/build/bin/compiler" [[ -x "$compiler" ]] || { echo "错误:未找到编译器 $compiler" >&2; exit 1; } command -v llc >/dev/null 2>&1 || { echo "错误:未找到 llc" >&2; exit 1; } command -v clang >/dev/null 2>&1 || { echo "错误:未找到 clang" >&2; exit 1; } mkdir -p "$RESULT_DIR" # 时间测量:使用 date +%s.%N now() { date +%s.%N; } elapsed() { python3 -c "print(f'{float($2)-float($1):.4f}')" 2>/dev/null || awk "BEGIN{printf \"%.4f\\n\",$2-$1}"; } summary_file="${RESULT_DIR}/summary.csv" echo "test,opt,compile_s,exec_s,compile+exec_s" > "$summary_file" total=0 o0_ct_total=0; o1_ct_total=0 o0_et_total=0; o1_et_total=0 echo "=== 优化效果对比 O0 vs O1 ===" echo "" while read -r test_file; do full_path=$(readlink -f "$test_file") tcdir=$(readlink -f "$TEST_CASE_DIR") rel="${full_path#$tcdir}" [[ "${rel:0:1}" != "/" ]] && rel="/$rel" base=$(basename "$test_file") stem="${base%.sy}" idir=$(dirname "$test_file") stdin="${idir}/${stem}.in" expected="${idir}/${stem}.out" total=$((total+1)) printf "[%4d] %s" "$total" "$rel" o0_ll="${RESULT_DIR}/O0/${rel%.sy}.ll" o1_ll="${RESULT_DIR}/O1/${rel%.sy}.ll" mkdir -p "$(dirname "$o0_ll")" "$(dirname "$o1_ll")" # --- 编译 O0 --- t1=$(now) "$compiler" "$test_file" -IR -o "$o0_ll" 2>/dev/null; rc0=$? t2=$(now) if [[ $rc0 -ne 0 ]]; then echo " | O0编译失败" echo "$stem,O0,-,-,-" >> "$summary_file" echo "$stem,O1,-,-,-" >> "$summary_file" continue fi o0_ct=$(elapsed "$t1" "$t2") # --- 编译 O1 --- t1=$(now) "$compiler" "$test_file" -IR -o "$o1_ll" -O1 2>/dev/null; rc1=$? t2=$(now) if [[ $rc1 -ne 0 ]]; then echo " | O1编译失败" echo "$stem,O0,$o0_ct,-,-" >> "$summary_file" echo "$stem,O1,-,-,-" >> "$summary_file" continue fi o1_ct=$(elapsed "$t1" "$t2") # --- llc + clang O0 --- o0_obj="${RESULT_DIR}/O0/${stem}.o" o1_obj="${RESULT_DIR}/O1/${stem}.o" o0_exe="${RESULT_DIR}/O0/${stem}.exe" o1_exe="${RESULT_DIR}/O1/${stem}.exe" llc -filetype=obj "$o0_ll" -o "$o0_obj" 2>/dev/null llc -filetype=obj "$o1_ll" -o "$o1_obj" 2>/dev/null clang "$o0_obj" "${PROJECT_ROOT}/sylib/sylib.c" -o "$o0_exe" -lm 2>/dev/null clang "$o1_obj" "${PROJECT_ROOT}/sylib/sylib.c" -o "$o1_exe" -lm 2>/dev/null # --- 运行 O0 --- t1=$(now) sr0=0 if [[ -f "$stdin" ]]; then (ulimit -s unlimited; "$o0_exe" < "$stdin") > /dev/null 2>&1 || sr0=$? else (ulimit -s unlimited; "$o0_exe") > /dev/null 2>&1 || sr0=$? fi t2=$(now) o0_et=$(elapsed "$t1" "$t2") # --- 运行 O1 --- t1=$(now) sr1=0 if [[ -f "$stdin" ]]; then (ulimit -s unlimited; "$o1_exe" < "$stdin") > /dev/null 2>&1 || sr1=$? else (ulimit -s unlimited; "$o1_exe") > /dev/null 2>&1 || sr1=$? fi t2=$(now) o1_et=$(elapsed "$t1" "$t2") # 验证一致性 flag="" if [[ $sr0 -ne $sr1 ]]; then flag=" EXIT:O0=$sr0 O1=$sr1" fi # 累计 & 比率 o0_ct_total=$(awk "BEGIN{printf \"%.4f\",$o0_ct_total+$o0_ct}") o1_ct_total=$(awk "BEGIN{printf \"%.4f\",$o1_ct_total+$o1_ct}") o0_et_total=$(awk "BEGIN{printf \"%.4f\",$o0_et_total+$o0_et}") o1_et_total=$(awk "BEGIN{printf \"%.4f\",$o1_et_total+$o1_et}") cspd=$(awk "BEGIN{if($o1_ct>0)printf \"%.1fx\",$o0_ct/$o1_ct; else print \"-\"}") espd=$(awk "BEGIN{if($o1_et>0)printf \"%.1fx\",$o0_et/$o1_et; else print \"-\"}") printf " | 编译 O0:%.4fs O1:%.4fs(%s) 运行 O0:%.4fs O1:%.4fs(%s)%s\n" \ "$o0_ct" "$o1_ct" "$cspd" "$o0_et" "$o1_et" "$espd" "$flag" echo "$stem,O0,$o0_ct,$o0_et,$(awk "BEGIN{printf \"%.4f\",$o0_ct+$o0_et}")" >> "$summary_file" echo "$stem,O1,$o1_ct,$o1_et,$(awk "BEGIN{printf \"%.4f\",$o1_ct+$o1_et}")" >> "$summary_file" done < <(find "$TEST_CASE_DIR" -name "*.sy" | sort) echo "" echo "============================================" echo "总用例: $total" echo "O0 编译总耗时: ${o0_ct_total}s" echo "O1 编译总耗时: ${o1_ct_total}s" echo "O0 运行总耗时: ${o0_et_total}s" echo "O1 运行总耗时: ${o1_et_total}s" echo "CSV: $summary_file"