Skip to content

Commit

Permalink
Introduce opt-pipeling for ClangIr
Browse files Browse the repository at this point in the history
  • Loading branch information
OfekShilon committed Sep 28, 2024
1 parent f715dc2 commit b0dc04c
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 5 deletions.
11 changes: 10 additions & 1 deletion lib/base-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ import {BuildEnvSetupBase, getBuildEnvTypeByKey} from './buildenvsetup/index.js'
import * as cfg from './cfg/cfg.js';
import {CompilationEnvironment} from './compilation-env.js';
import {CompilerArguments} from './compiler-arguments.js';
import {ClangCParser, ClangParser, GCCCParser, GCCParser, ICCParser} from './compilers/argument-parsers.js';
import {
ClangCParser,
ClangirParser,
ClangParser,
GCCCParser,
GCCParser,
ICCParser,
} from './compilers/argument-parsers.js';
import {BaseDemangler, getDemanglerTypeByKey} from './demangler/index.js';
import {LLVMIRDemangler} from './demangler/llvm.js';
import * as exec from './exec.js';
Expand Down Expand Up @@ -3221,6 +3228,8 @@ but nothing was dumped. Possible causes are:
const exeFilename = path.basename(exe);
if (exeFilename.includes('icc')) {
return ICCParser;
} else if (exe.includes('clangir')) {
return ClangirParser;
} else if (exeFilename.includes('clang++') || exeFilename.includes('icpx')) {
// check this first as "clang++" matches "g++"
return ClangParser;
Expand Down
14 changes: 14 additions & 0 deletions lib/compilers/argument-parsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,20 @@ export class ClangParser extends BaseParser {
}
}

export class ClangirParser extends ClangParser {
static override setCompilerSettingsFromOptions(compiler, options) {
ClangParser.setCompilerSettingsFromOptions(compiler, options);

compiler.compiler.optPipeline = {
arg: [],
moduleScopeArg: ['-mmlir', '--mlir-print-ir-before-all', '-mmlir', '--mlir-print-ir-after-all'],
noDiscardValueNamesArg: [],
supportedOptions: ['dump-full-module', 'demangle-symbols'],
supportedFilters: [],
};
}
}

export class GCCCParser extends GCCParser {
static override getLanguageSpecificHelpFlags(): string[] {
return ['-fsyntax-only', '--help=c'];
Expand Down
15 changes: 13 additions & 2 deletions lib/parsers/llvm-pass-dump-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export class LlvmPassDumpParser {
metadataLineFilters: RegExp[];
irDumpHeader: RegExp;
machineCodeDumpHeader: RegExp;
cirDumpHeader: RegExp;
functionDefine: RegExp;
machineFunctionBegin: RegExp;
functionEnd: RegExp;
Expand Down Expand Up @@ -121,6 +122,10 @@ export class LlvmPassDumpParser {
// or "(loop: %x)" at the end
this.irDumpHeader = /^;?\s?\*{3} (.+) \*{3}(?:\s+\((?:function: |loop: )(%?[\w$.]+)\))?(?:;.+)?$/;
this.machineCodeDumpHeader = /^# \*{3} (.+) \*{3}:$/;
// ClangIr dump headers look like "// -----// IR Dump Before XYZ (cir-xyz) //----- //
// and currently do not refer to functions
this.cirDumpHeader = /^\/\/ -----\/\/ (.+) \/\/----- \/\/$/;

// Ir dumps are "define T @_Z3fooi(...) . .. {" or "# Machine code for function _Z3fooi: <attributes>"
// Some interesting edge cases found when testing:
// `define internal %"struct.libassert::detail::assert_static_parameters"* @"_ZZ4mainENK3$_0clEv"(
Expand Down Expand Up @@ -149,7 +154,8 @@ export class LlvmPassDumpParser {
//}
const irMatch = line.text.match(this.irDumpHeader);
const machineMatch = line.text.match(this.machineCodeDumpHeader);
const header = irMatch || machineMatch;
const cirMatch = line.text.match(this.cirDumpHeader);
const header = irMatch || machineMatch || cirMatch;
if (header) {
if (pass !== null) {
raw_passes.push(pass);
Expand Down Expand Up @@ -481,7 +487,12 @@ export class LlvmPassDumpParser {
process(output: ResultLine[], _: ParseFiltersAndOutputOptions, optPipelineOptions: OptPipelineBackendOptions) {
// Crop out any junk before the pass dumps (e.g. warnings)
const ir = output.slice(
output.findIndex(line => line.text.match(this.irDumpHeader) || line.text.match(this.machineCodeDumpHeader)),
output.findIndex(
line =>
this.irDumpHeader.test(line.text) ||
this.machineCodeDumpHeader.test(line.text) ||
this.cirDumpHeader.test(line.text),
),
);
const preprocessed_lines = this.applyIrFilters(ir, optPipelineOptions);
return this.breakdownOutput(preprocessed_lines, optPipelineOptions);
Expand Down
9 changes: 8 additions & 1 deletion static/panes/opt-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,14 @@ export class OptPipeline extends MonacoPane<monaco.editor.IStandaloneDiffEditor,

updateButtons() {
if (!this.compiler || !this.compiler.optPipeline) return;
const {supportedOptions, supportedFilters} = this.compiler.optPipeline;

const supportedOptions = this.compiler.optPipeline.supportedOptions;
if (supportedOptions) {
for (const key of ['dump-full-module', '-fno-discard-value-names', 'demangle-symbols']) {
this.options.enableToggle(key, supportedOptions.includes(key));
}
}
const supportedFilters = this.compiler.optPipeline.supportedFilters;
if (supportedFilters) {
for (const key of ['filter-debug-info', 'filter-instruction-metadata']) {
this.filters.enableToggle(key, supportedFilters.includes(key));
Expand Down Expand Up @@ -342,6 +344,11 @@ export class OptPipeline extends MonacoPane<monaco.editor.IStandaloneDiffEditor,
if (compiler && !compiler.optPipeline) {
//this.editor.setValue('<Opt pipeline output is not supported for this compiler>');
}

// TODO: un-hackify this
if (this.compilerInfo.compilerName.includes('clangir')) {
this.options.enableToggle('dump-full-module', false, true);
}
}

updateGroupName() {
Expand Down
5 changes: 4 additions & 1 deletion static/widgets/toggles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,15 @@ export class Toggles extends EventEmitter {
this.emit('change', before, this.get());
}

enableToggle(key: string, enable: boolean) {
enableToggle(key: string, enable: boolean, lockChecked: boolean = false) {
for (const element of this.buttons) {
const widget = $(element);
const button = widget.find('button');
const bind = button.data('bind');
if (bind === key) {
if (lockChecked) {
this.set(key, true); // Ensure the toggle is checked
}
button.prop('disabled', !enable);
}
}
Expand Down

0 comments on commit b0dc04c

Please sign in to comment.