From 64bcd0915e2c6fd2aac665834b60197a29009ca0 Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Thu, 17 Apr 2025 15:56:36 +0800 Subject: [PATCH] spec: allow using gcc for SPEC compiler --- assets/specTemplate.cfg | 10 +++---- src/bin/runcpu.ts | 45 ++++++++++++++++++++++-------- src/spec/index.ts | 62 +++++++++++++++++++++++++++++++++++------ 3 files changed, 91 insertions(+), 26 deletions(-) diff --git a/assets/specTemplate.cfg b/assets/specTemplate.cfg index 0b0e3b3..3459dff 100644 --- a/assets/specTemplate.cfg +++ b/assets/specTemplate.cfg @@ -110,7 +110,6 @@ default: # EDIT: the directory where your compiler is installed %ifndef %{gcc_dir} #% define gcc_dir /SW/compilers/GCC/Linux/x86_64/gcc-6.3.0 -% define gcc_dir @@GCCDIR@@ % define sysroot_dir @@SYSROOT@@ %endif @@ -120,13 +119,12 @@ default: # and: https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html LDFLAGS = @@LDFLAGS@@ - LIBS = %{gcc_dir}/lib/libpgmath.a %{gcc_dir}/lib/libflang.a %{gcc_dir}/lib/libflangrti.a -lompstub + LIBS = @@LIBS@@ #preENV_LD_LIBRARY_PATH = %{gcc_dir}/lib64/:%{gcc_dir}/lib/:/lib64:%{ENV_LD_LIBRARY_PATH} - SPECLANG = %{gcc_dir}/bin - CC = $(SPECLANG)/clang --sysroot %{sysroot_dir} # -std=c99 %{model} - CXX = $(SPECLANG)/clang++ --sysroot %{sysroot_dir} # %{model} - FC = $(SPECLANG)/flang --sysroot %{sysroot_dir} # %{model} + CC = @@CompilerCC@@ # -std=c99 %{model} + CXX = @@CompilerCXX@@ # %{model} + FC = @@CompilerFC@@ # %{model} # How to say "Show me your version, please" CC_VERSION_OPTION = -v CXX_VERSION_OPTION = -v diff --git a/src/bin/runcpu.ts b/src/bin/runcpu.ts index 3782bae..c046414 100644 --- a/src/bin/runcpu.ts +++ b/src/bin/runcpu.ts @@ -4,8 +4,8 @@ import { promisifySpawn } from '../cli.js'; import { RunCPUOptions, runcpuOptions } from '../commands/spec.js'; import { systemdRunOptions } from '../commands/systemd.js'; import path from 'path'; -import { mkSPEC, renderConfig } from '../spec/index.js'; -import { optimizeOptions, sw64TargetOptions } from '../commands/compiler.js'; +import { ConfigOptions, mkSPEC, renderConfig } from '../spec/index.js'; +import { sw64TargetOptions } from '../commands/compiler.js'; import crypto from 'crypto'; import { hideBin } from 'yargs/helpers'; import * as sunway from '../sunway.js'; @@ -13,9 +13,15 @@ import chalk from 'chalk'; // Define the yargs options const argv = await yargs(hideBin(process.argv)) - .option('llvm', { + .option('compiler-prefix', { type: 'string', - description: 'The llvm path for this test', + description: 'The compiler prefix for this test', + demandOption: true, + }) + .option('compiler-suite', { + type: 'string', + description: 'Compiler suite for config rendering', + choices: ['llvm', 'gcc'], demandOption: true, }) .option('workload', { @@ -120,24 +126,41 @@ function systemdRunSPEC({ // Generate a random UUID for this run const uuid = crypto.randomUUID(); -const llvmPrefix = path.resolve(argv.llvm); +const prefix = path.resolve(argv.compilerPrefix); + +console.log(prefix); + +const o3LTOFlags = [ + "-O3", + "-flto", + "-fuse-ld=lld", + "-Wl,-plugin-opt,--mattr=simd" +]; + +const unalignedFlags = [ + "-mllvm", + "-sw64-allows-misaligned-memory-accesses", +]; + // SPEC configuration const specConfig = renderConfig({ - gccdir: llvmPrefix, + prefix, optimize: [ - ...optimizeOptions({ optimize: '2' }), + "-O2", ...sw64TargetOptions({ simd: argv.simd }), - sunway.mcpu(sunwayGeneration), + ...argv.compilerSuite == "llvm" ? [sunway.mcpu(sunwayGeneration)] : [], // Only add -mcpu for llvm ], ldflags: [ '-static', - `-L${path.resolve(llvmPrefix, 'lib')}`, + `-L${path.resolve(prefix, 'lib')}`, ], - sysroot + sysroot, + compiler: argv.compilerSuite as ConfigOptions["compiler"], }); -console.log(`Running SPEC compiled from ${llvmPrefix} as ${uuid}`); +console.log(`Running SPEC compiled from ${prefix} as ${uuid}`); + await promisifySpawn(systemdRunSPEC({ specConfig, id: uuid, diff --git a/src/spec/index.ts b/src/spec/index.ts index 129452b..de5ca6e 100644 --- a/src/spec/index.ts +++ b/src/spec/index.ts @@ -4,9 +4,9 @@ import { promisify } from "util"; import { ChildProcessByStdio } from 'child_process'; import { Readable, Writable } from 'stream'; import { createInterface } from 'readline'; -import { projectRoot } from '../environment/index.js'; import { SPECBenchData, benchpath, exepath, buildpath } from './benchData.js'; import specTemplate from '../../assets/specTemplate.cfg'; +import assert from 'assert'; @@ -60,20 +60,64 @@ export function mkBench(spec: SPEC, bench: SPECBenchData): Bench { const writeFile = promisify(fs.writeFile); export interface ConfigOptions { - gccdir: string; + prefix: string; optimize: string[]; ldflags: string[]; sysroot: string; + compiler: "llvm" | "gcc"; } -export function renderConfig(options: ConfigOptions) { - return `# Rendered from TypeScript ${new Date().toLocaleString()}, do not edit!\n\n\n` + specTemplate - .replace("@@GCCDIR@@", options.gccdir) - .replace("@@OPTIMIZE@@", options.optimize.join(' ')) - .replace("@@LDFLAGS@@", options.ldflags.join(' ')) - .replace("@@SYSROOT@@", options.sysroot); -} +// Pure function to get compiler names based on the compiler type +const getCompilerNames = (compiler: ConfigOptions["compiler"]) => +({ + llvm: { CXX: "clang++", CC: "clang", FC: "flang" }, + gcc: { CXX: "g++", CC: "gcc", FC: "gfortran" }, +}[compiler]); +// Pure function to get compiler directory structure +const getCompilerDir = (compiler: ConfigOptions["compiler"]) => + compiler === "llvm" ? ["bin"] : ["usr", "bin"]; + +// Helper function to resolve paths for compilers +const resolveCompilerPaths = ( + prefix: string, + compiler: ConfigOptions["compiler"], + compilerNames: ReturnType +) => ({ + CC: path.resolve(prefix, ...getCompilerDir(compiler), compilerNames.CC), + CXX: path.resolve(prefix, ...getCompilerDir(compiler), compilerNames.CXX), + FC: path.resolve(prefix, ...getCompilerDir(compiler), compilerNames.FC), +}); + +// Helper function to generate library paths for LLVM +const getLlvmLibs = (prefix: string) => + [ + "pgmath", + "flangrti", + "flang", + ].map(lib => path.resolve(prefix, "lib", `lib${lib}.a`)).concat(["-lompstub"]); + +// Pure function to render configuration +export const renderConfig = (options: ConfigOptions): string => { + const compilerNames = getCompilerNames(options.compiler); + const compilerPaths = resolveCompilerPaths(options.prefix, options.compiler, compilerNames); + + const libs = + options.compiler === "llvm" + ? getLlvmLibs(options.prefix) + : []; + + return `# Rendered from TypeScript ${new Date().toLocaleString()}, do not edit!\n\n\n` + + specTemplate + .replace("@@OPTIMIZE@@", options.optimize.join(" ")) + .replace("@@LDFLAGS@@", options.ldflags.join(" ")) + .replace("@@SYSROOT@@", options.sysroot) + .replace("@@CompilerCC@@", compilerPaths.CC) + .replace("@@CompilerCXX@@", compilerPaths.CXX) + .replace("@@CompilerFC@@", compilerPaths.FC) + .replace("@@LIBS@@", libs.join(" ")) + ; +}; export interface SPECResult { outputFiles: { [key: string]: string[], };