Pass Infrastructure基础架构(下)
Pass Infrastructure基礎(chǔ)架構(gòu)(下)
pass注冊(cè)
PassRegistration該類(lèi)在示例中簡(jiǎn)要顯示了各種pass類(lèi)型的定義 。該機(jī)制允許注冊(cè)pass類(lèi),以便可以在文本pass管道描述中創(chuàng)建它們 。注冊(cè)示例如下所示:
void registerMyPass() {
PassRegistration(“argument”, “description”);
}
? MyPass 是派生密碼類(lèi)的名稱(chēng)。
? “參數(shù)”是用于以文本格式引用過(guò)程的參數(shù)。
? “說(shuō)明”是pass的簡(jiǎn)短說(shuō)明。
對(duì)于無(wú)法默認(rèn)構(gòu)造的pass,PassRegistration接受可選的第三個(gè)參數(shù),該參數(shù)接受回調(diào)以創(chuàng)建pass:
void registerMyPass() {
PassRegistration(
“argument”, “description”,
-> std::unique_ptr {
std::unique_ptr p = std::make_unique(/options/);
/… non-trivial-logic to configure the pass …/;
return p;
});
}
例如,可以使用這種注冊(cè)變體來(lái)接受命令行參數(shù)的傳遞配置,并將其傳遞給pass構(gòu)造函數(shù)。
注意:請(qǐng)確保該pass以不共享數(shù)據(jù)的方式是可復(fù)制構(gòu)造的,因?yàn)?pass管理器 可能會(huì)創(chuàng)建該pass的副本以并行運(yùn)行。
pass管道注冊(cè)
上面描述的是用于注冊(cè)特定派生pass類(lèi)的機(jī)制。最重要的是,MLIR允許以類(lèi)似的方式注冊(cè)自定義傳遞管道。這允許自定義管道以與傳遞相同的方式提供給mlir-opt之類(lèi)的工具,這對(duì)于封裝常見(jiàn)的管道(例如“ -O1”傳遞系列)很有用。管道pass類(lèi)似的機(jī)制注冊(cè),形式為PassPipelineRegistration。與之相比PassRegistration,此類(lèi)采用管道構(gòu)造器形式的附加參數(shù),該參數(shù)修改提供的參數(shù)OpPassManager。
void pipelineBuilder(OpPassManager &pm) {
pm.addPass(std::make_unique());
pm.addPass(std::make_unique());
}
void registerMyPasses() {
// Register an existing pipeline builder function.
PassPipelineRegistration<>(
“argument”, “description”, pipelineBuilder);
// Register an inline pipeline builder.
PassPipelineRegistration<>(
“argument”, “description”, [](OpPassManager &pm) {
pm.addPass(std::make_unique());
pm.addPass(std::make_unique());
});
}
文本傳遞管道規(guī)范
前面的部分詳細(xì)介紹了如何使用特定的參數(shù)和說(shuō)明注冊(cè)pass和pass管道。一旦注冊(cè),就可以使用它們從字符串描述中配置通道管理器。這對(duì)于mlir-opt從命令行配置過(guò)程管理器的工具,或作為利用動(dòng)態(tài)過(guò)程管道的過(guò)程的選項(xiàng)的 工具尤其有用 。
為了支持描述傳遞管道的完整結(jié)構(gòu)的能力,MLIR支持對(duì)傳遞管道的自定義文本描述。文字描述包括嵌套結(jié)構(gòu),運(yùn)行的傳遞和傳遞管道的參數(shù)以及這些傳遞和管道的任何選項(xiàng)。文本管道定義為一系列名稱(chēng),每個(gè)名稱(chēng)本身都可以遞歸包含嵌套的管道描述。該規(guī)范的語(yǔ)法如下:
pipeline ::= op-name ( pipeline-element (, pipeline-element)* )
pipeline-element ::= pipeline | (pass-name | pass-pipeline-name) options?
options ::= ‘{’ (key (’=’ value)?)+ ‘}’
? op-name
o 這對(duì)應(yīng)于要繼續(xù)運(yùn)行的算子的助記符名稱(chēng),例如func或module。
? pass-name | pass-pipeline-name
o 這對(duì)應(yīng)于已注冊(cè)的pass或pass管道的參數(shù),例如cse或canonicalize。
? options
o 選項(xiàng)是特定的鍵值對(duì),代表pass或傳遞管道定義的選項(xiàng),如 “實(shí)例特定的傳遞選項(xiàng)” 部分所述。有關(guān)文本管道中的用法示例,請(qǐng)參見(jiàn)本節(jié)。
例如,以下管道:
$ mlir-opt foo.mlir -cse -canonicalize -convert-std-to-llvm=‘use-bare-ptr-memref-call-conv=1’
也可以指定為(pass-pass-pipeline標(biāo)志):
$ mlir-opt foo.mlir -pass-pipeline=‘func(cse,canonicalize),convert-std-to-llvm{use-bare-ptr-memref-call-conv=1}’
為了支持使用來(lái)回傳遞一個(gè)通向文本表示的傳遞 OpPassManager::printAsTextualPipeline(raw_ostream&),請(qǐng)重寫(xiě)StringRef Pass::getArgument()以指定注冊(cè)傳遞時(shí)使用的參數(shù)。
聲明式pass規(guī)范
可以pass類(lèi)似于算子的形式聲明性地指定pass的某些方面 。該規(guī)范簡(jiǎn)化了定義通道時(shí)使用的幾種機(jī)制。它可用于生成過(guò)程注冊(cè)調(diào)用,定義樣板過(guò)程實(shí)用程序以及生成過(guò)程文檔。
考慮以下在C ++中指定的過(guò)程:
struct MyPass : PassWrapper<MyPass, OperationPass> {
MyPass() = default;
MyPass(const MyPass &) {}
…
// Specify any options.
Option option{
*this, “example-option”,
llvm:🆑:desc(“An example option”), llvm:🆑:init(true)};
ListOption<int64_t> listOption{
*this, “example-list”,
llvm:🆑:desc(“An example list option”), llvm:🆑:ZeroOrMore,
llvm:🆑:MiscFlags::CommaSeparated};
// Specify any statistics.
Statistic statistic{this, “example-statistic”, “An example statistic”};
};
/// Expose this pass to the outside world.
std::unique_ptr foo::createMyPass() {
return std::make_unique();
}
/// Register this pass.
void foo::registerMyPass() {
PassRegistration(“my-pass”, “My pass summary”);
}
此pass可以這樣聲明地指定:
def MyPass : Pass<“my-pass”, “ModuleOp”> {
let summary = “My Pass Summary”;
let description = [{
Here we can now give a much larger description of MyPass, including all of
its various constraints and behavior.
}];
// A constructor must be provided to specify how to create a default instance
// of MyPass.
let constructor = “foo::createMyPass()”;
// Specify any options.
let options = [
Option<“option”, “example-option”, “bool”, /default=/“true”,
“An example option”>,
ListOption<“l(fā)istOption”, “example-list”, “int64_t”,
“An example list option”,
“l(fā)lvm:🆑:ZeroOrMore, llvm:🆑:MiscFlags::CommaSeparated”>
];
// Specify any statistics.
let statistics = [
Statistic<“statistic”, “example-statistic”, “An example statistic”>
];
}
使用gen-pass-decls生成器,可以自動(dòng)生成上面的大多數(shù)樣板。該生成器將一個(gè)-name參數(shù)作為輸入,該參數(shù)為正在生成的一組pass提供標(biāo)簽。該生成器產(chǎn)生兩個(gè)輸出塊:
第一個(gè)是用于在全局注冊(cè)表中注冊(cè)聲明性傳遞的代碼塊。對(duì)于每次pass,生成器都會(huì)生成一個(gè)registerFooPasswhereFoo 是tablegen中指定的定義的名稱(chēng)。它還會(huì)生成一個(gè) registerGroupPasses,其中Group是pass-name輸入?yún)?shù)提供的標(biāo)記,該標(biāo)記會(huì)注冊(cè)所有存在的pass。
// gen-pass-decls -name=“Example”
#define GEN_PASS_REGISTRATION
#include “Passes.h.inc”
void registerMyPasses() {
// Register all of the passes.
registerExamplePasses();
// Register MyPass specifically.
registerMyPassPass();
}
第二個(gè)是每個(gè)通道的基類(lèi),其中包含與通道定義相關(guān)的大多數(shù)樣板。這些類(lèi)以的形式命名 MyPassBase,其中MyPass是tablegen中傳遞定義的名稱(chēng)。可以這樣更新原始的C ++傳遞定義:
/// Include the generated base pass class definitions.
#define GEN_PASS_CLASSES
#include “Passes.h.inc”
/// Define the main class as deriving from the generated base class.
struct MyPass : MyPassBase {
/// The explicit constructor is no longer explicitly necessary when defining
/// pass options and statistics, the base class takes care of that
/// automatically.
…
/// The definitions of the options and statistics are now generated within
/// the base class, but are accessible in the same way.
};
/// Expose this pass to the outside world.
std::unique_ptr foo::createMyPass() {
return std::make_unique();
}
使用gen-pass-doc生成器,可以生成每個(gè)pass的降價(jià)文檔。參閱 Passes.md 以獲取實(shí)際MLIRpass的示例輸出。
Tablegen規(guī)范
該P(yáng)ass級(jí)用來(lái)啟動(dòng)一個(gè)新的通行定義。此類(lèi)將傳遞給屬性的注冊(cè)表參數(shù)以及與傳遞所算子的算子類(lèi)型相對(duì)應(yīng)的可選字符串作為參數(shù)。該類(lèi)包含以下字段:
? summary
o 該pass的簡(jiǎn)短摘要,用作注冊(cè)pass時(shí)的描述。
? description
o pass的更長(zhǎng),更詳細(xì)的描述。在生成pass文件時(shí)使用。
? dependentDialects
o 代表Dialect此過(guò)程的類(lèi)的字符串列表可能會(huì)引入實(shí)體,屬性/算子/類(lèi)型/等。
? constructor
o 用于創(chuàng)建pass的默認(rèn)實(shí)例的代碼塊。
? options
o pass使用的pass選項(xiàng)列表。
? statistics
o pass使用的pass統(tǒng)計(jì)信息列表。
選項(xiàng)
選項(xiàng)可以passOption和ListOption類(lèi)指定。該Option 班采用下列模板參數(shù):
? C ++變量名稱(chēng)
o 用于生成的選項(xiàng)變量的名稱(chēng)。
? 論據(jù)
o 選項(xiàng)的參數(shù)名稱(chēng)。
? 類(lèi)型
o 選項(xiàng)的C ++類(lèi)型。
? 默認(rèn)值
o 默認(rèn)選項(xiàng)值。
? 描述
o 選項(xiàng)的一行描述。
? 附加選項(xiàng)標(biāo)志
o 一個(gè)字符串,其中包含構(gòu)造選項(xiàng)所必需的任何其它選項(xiàng)。
def MyPass : Pass<“my-pass”> {
let options = [
Option<“option”, “example-option”, “bool”, /default=/“true”,
“An example option”>,
];
}
該ListOption班采取以下字段:
? C ++變量名稱(chēng)
o 用于生成的選項(xiàng)變量的名稱(chēng)。
? 論據(jù)
o 選項(xiàng)的參數(shù)名稱(chēng)。
? 元素類(lèi)型
o 列表元素的C ++類(lèi)型。
? 描述
o 選項(xiàng)的一行描述。
? 附加選項(xiàng)標(biāo)志
o 一個(gè)字符串,其中包含構(gòu)造選項(xiàng)所必需的任何其它選項(xiàng)。
def MyPass : Pass<“my-pass”> {
let options = [
ListOption<“l(fā)istOption”, “example-list”, “int64_t”,
“An example list option”,
“l(fā)lvm:🆑:ZeroOrMore, llvm:🆑:MiscFlags::CommaSeparated”>
];
}
統(tǒng)計(jì)
可以pass來(lái)指定統(tǒng)計(jì)信息Statistic,該參數(shù)采用以下模板參數(shù):
? C ++變量名稱(chēng)
o 用于生成的統(tǒng)計(jì)變量的名稱(chēng)。
? 顯示名稱(chēng)
o 顯示統(tǒng)計(jì)信息時(shí)使用的名稱(chēng)。
? 描述
o 統(tǒng)計(jì)信息的一行描述。
def MyPass : Pass<“my-pass”> {
let statistics = [
Statistic<“statistic”, “example-statistic”, “An example statistic”>
];
}
pass檢測(cè)
MLIRpass該類(lèi)提供了一個(gè)可定制的框架,以pass過(guò)程執(zhí)行和分析計(jì)算PassInstrumentation。此類(lèi)提供了通向PassManager的鉤子,用于觀察各種事件:
? runBeforePipeline
o 該回調(diào)僅在執(zhí)行傳遞管道(即傳遞管理器)之前運(yùn)行。
? runAfterPipeline
o 成功執(zhí)行傳遞管道之后,無(wú)論是否成功執(zhí)行此回調(diào)。
? runBeforePass
o 該回調(diào)將在執(zhí)行傳遞之前運(yùn)行。
? runAfterPass
o 成功執(zhí)行傳遞后立即運(yùn)行此回調(diào)。如果執(zhí)行此鉤子,runAfterPassFailed則不會(huì)。
? runAfterPassFailed
o 傳遞執(zhí)行失敗后立即運(yùn)行此回調(diào)。如果執(zhí)行此鉤子,runAfterPass則不會(huì)。
? runBeforeAnalysis
o 該回調(diào)在計(jì)算分析之前運(yùn)行。
? runAfterAnalysis
o 在計(jì)算分析后立即運(yùn)行此回調(diào)。
PassInstrumentation實(shí)例可以 pass方法直接向PassManager實(shí)例注冊(cè) addInstrumentation。添加到PassManager的工具以類(lèi)似堆棧的方式運(yùn)行,即最后一個(gè)執(zhí)行runBefore鉤子的工具將是第一個(gè)執(zhí)行相應(yīng)runAfter鉤子的工具。PassInstrumentation 保證類(lèi)的鉤子以線程安全的方式執(zhí)行,因此不需要額外的同步。在下面的示例設(shè)備中,該設(shè)備對(duì)計(jì)算DominanceInfo分析的次數(shù)進(jìn)行計(jì)數(shù):
struct DominanceCounterInstrumentation : public PassInstrumentation {
/// The cumulative count of how many times dominance has been calculated.
unsigned &count;
DominanceCounterInstrumentation(unsigned &count) : count(count) {}
void runAfterAnalysis(llvm::StringRef, TypeID id, Operation *) override {
if (id == TypeID::get())
++count;
}
};
MLIRContext *ctx = …;
PassManager pm(ctx);
// Add the instrumentation to the pass manager.
unsigned domInfoCount;
pm.addInstrumentation(
std::make_unique(domInfoCount));
// Run the pass manager on a module operation.
ModuleOp m = …;
if (failed(pm.run(m)))
…
llvm::errs() << “DominanceInfo was computed " << domInfoCount << " times!\n”;
標(biāo)準(zhǔn)設(shè)備
MLIR利用pass工具框架提供一些有用的開(kāi)發(fā)人員工具和實(shí)用程序。這些工具中的每一個(gè)均可直接用于MLIR Pass框架的所有用戶(hù)。
pass時(shí)間
PassTiming設(shè)備提供有關(guān)pass執(zhí)行和分析計(jì)算的時(shí)序信息。這可以快速了解哪些通道花費(fèi)了最多的時(shí)間來(lái)執(zhí)行,以及通道對(duì)管道總執(zhí)行時(shí)間的影響。用戶(hù)可以pass直接在PassManager上啟用此檢測(cè)enableTiming。也可以pass-pass-timing標(biāo)志在mlir-opt中使用此工具。PassTiming設(shè)備為計(jì)時(shí)結(jié)果提供了幾種不同的顯示模式,下面分別介紹每種模式:
列表顯示模式
在這種模式下,結(jié)果顯示在一個(gè)列表中,該列表按總時(shí)間排序,每個(gè)pass/分析實(shí)例匯總為一個(gè)唯一的結(jié)果。此視圖有助于大致了解分析/pass最多花費(fèi)的時(shí)間。此顯示模式可在mlir-opt via中使用 -pass-timing-display=list。
$ mlir-opt foo.mlir -mlir-disable-threading -pass-pipeline=‘func(cse,canonicalize)’ -convert-std-to-llvm -pass-timing -pass-timing-display=list
=-------------------------------------------------------------------------=
… Pass execution timing report …
=-------------------------------------------------------------------------=
Total Execution Time: 0.0203 seconds
—Wall Time— — Name —
0.0047 ( 55.9%) Canonicalizer
0.0019 ( 22.2%) VerifierPass
0.0016 ( 18.5%) LLVMLoweringPass
0.0003 ( 3.4%) CSE
0.0002 ( 1.9%) (A) DominanceInfo
0.0084 (100.0%) Total
管道顯示模式
在這種模式下,結(jié)果將顯示在嵌套管道視圖中,該視圖鏡像在通道管理器中執(zhí)行的內(nèi)部通道管道。該視圖對(duì)于特定地了解流水線中哪個(gè)部分花費(fèi)最多的時(shí)間很有用,并且還可用于識(shí)別何時(shí)使分析無(wú)效和重新計(jì)算。這是默認(rèn)顯示模式。
$ mlir-opt foo.mlir -mlir-disable-threading -pass-pipeline=‘func(cse,canonicalize)’ -convert-std-to-llvm -pass-timing
=-------------------------------------------------------------------------=
… Pass execution timing report …
=-------------------------------------------------------------------------=
Total Execution Time: 0.0249 seconds
—Wall Time— — Name —
0.0058 ( 70.8%) ‘func’ Pipeline
0.0004 ( 4.3%) CSE
0.0002 ( 2.6%) (A) DominanceInfo
0.0004 ( 4.8%) VerifierPass
0.0046 ( 55.4%) Canonicalizer
0.0005 ( 6.2%) VerifierPass
0.0005 ( 5.8%) VerifierPass
0.0014 ( 17.2%) LLVMLoweringPass
0.0005 ( 6.2%) VerifierPass
0.0082 (100.0%) Total
多線程傳遞時(shí)序
在pass管理器中啟用多線程后,顯示的含義會(huì)稍有變化。首先,添加一個(gè)新的計(jì)時(shí)列User Time,顯示所有線程花費(fèi)的總時(shí)間。其次,該Wall Time 列顯示在所有線程中花費(fèi)的最長(zhǎng)的個(gè)人時(shí)間。這意味著該Wall Time列將繼續(xù)提供感知時(shí)間或時(shí)鐘時(shí)間的指示符,而User Time則將顯示總的cpu時(shí)間。
$ mlir-opt foo.mlir -pass-pipeline=‘func(cse,canonicalize)’ -convert-std-to-llvm -pass-timing
=-------------------------------------------------------------------------=
… Pass execution timing report …
=-------------------------------------------------------------------------=
Total Execution Time: 0.0078 seconds
—User Time— —Wall Time— — Name —
0.0177 ( 88.5%) 0.0057 ( 71.3%) ‘func’ Pipeline
0.0044 ( 22.0%) 0.0015 ( 18.9%) CSE
0.0029 ( 14.5%) 0.0012 ( 15.2%) (A) DominanceInfo
0.0038 ( 18.9%) 0.0015 ( 18.7%) VerifierPass
0.0089 ( 44.6%) 0.0025 ( 31.1%) Canonicalizer
0.0006 ( 3.0%) 0.0002 ( 2.6%) VerifierPass
0.0004 ( 2.2%) 0.0004 ( 5.4%) VerifierPass
0.0013 ( 6.5%) 0.0013 ( 16.3%) LLVMLoweringPass
0.0006 ( 2.8%) 0.0006 ( 7.0%) VerifierPass
0.0200 (100.0%) 0.0081 (100.0%) Total
IR打印
調(diào)試時(shí),通常在傳遞管道的各個(gè)階段轉(zhuǎn)儲(chǔ)IR很有用。這是IR打印設(shè)備發(fā)揮作用的地方。pass選擇性地對(duì)正在執(zhí)行的遍歷進(jìn)行過(guò)濾,該設(shè)備可以在遍歷執(zhí)行之前和之后有條件地打印IR。該工具可以passenableIRPrinting方法直接添加到PassManager 。mlir-opt提供了一些使用此工具的有用標(biāo)志:
? print-ir-before=(comma-separated-pass-list)
o 在pass列表中提供的每個(gè)pass之前打印IR。
? print-ir-before-all
o 在管道中的每一次pass之前都要打印IR。
$ mlir-opt foo.mlir -pass-pipeline=‘func(cse)’ -print-ir-before=cse
*** IR Dump Before CSE ***
func @simple_constant() -> (i32, i32) {
%c1_i32 = constant 1 : i32
%c1_i32_0 = constant 1 : i32
return %c1_i32, %c1_i32_0 : i32, i32
}
? print-ir-after=(comma-separated-pass-list)
o 在pass列表中提供的每個(gè)pass之后,打印IR。
? print-ir-after-all
o 每次pass管道后,請(qǐng)打印IR。
$ mlir-opt foo.mlir -pass-pipeline=‘func(cse)’ -print-ir-after=cse
*** IR Dump After CSE ***
func @simple_constant() -> (i32, i32) {
%c1_i32 = constant 1 : i32
return %c1_i32, %c1_i32 : i32, i32
}
? print-ir-after-change
o 如果pass更改了IR,則僅在pass之后打印IR。這有助于減少“無(wú)趣”pass的IR轉(zhuǎn)儲(chǔ)數(shù)量。
o 注意:pass比較傳遞前后算子的哈希值來(lái)檢測(cè)更改。這增加了額外的運(yùn)行時(shí)間來(lái)計(jì)算IR的哈希值,在極少數(shù)情況下,取決于所使用的哈希算法的沖突率,可能會(huì)導(dǎo)致假陽(yáng)性。
o 注意:此選項(xiàng)應(yīng)與上面的其它“以后打印”選項(xiàng)一起使用,因?yàn)閮H此選項(xiàng)無(wú)法啟用打印。
$ mlir-opt foo.mlir -pass-pipeline=‘func(cse,cse)’ -print-ir-after=cse -print-ir-after-change
*** IR Dump After CSE ***
func @simple_constant() -> (i32, i32) {
%c1_i32 = constant 1 : i32
return %c1_i32, %c1_i32 : i32, i32
}
? print-ir-module-scope
o 無(wú)論pass類(lèi)型或算子嵌套級(jí)別如何,始終打印頂層模塊算子。
o 注意:僅在禁用多線程(-mlir-disable-threading)時(shí)才應(yīng)使用在模塊范圍內(nèi)打印
$ mlir-opt foo.mlir -mlir-disable-threading -pass-pipeline=‘func(cse)’ -print-ir-after=cse -print-ir-module-scope
*** IR Dump After CSE *** (‘func’ operation: @bar)
func @bar(%arg0: f32, %arg1: f32) -> f32 {
…
}
func @simple_constant() -> (i32, i32) {
%c1_i32 = constant 1 : i32
%c1_i32_0 = constant 1 : i32
return %c1_i32, %c1_i32_0 : i32, i32
}
*** IR Dump After CSE *** (‘func’ operation: @simple_constant)
func @bar(%arg0: f32, %arg1: f32) -> f32 {
…
}
func @simple_constant() -> (i32, i32) {
%c1_i32 = constant 1 : i32
return %c1_i32, %c1_i32 : i32, i32
}
崩潰和失敗復(fù)制
MLIR中的 pass管理器包含一個(gè)內(nèi)置的機(jī)制,即使發(fā)生崩潰或pass失敗,也可以生成可復(fù)制的內(nèi)容 。可以passPassManager::enableCrashReproducerGeneration或pass命令行標(biāo)志 啟用此功能 pass-pipeline-crash-reproducer。在任何一種情況下,都提供一個(gè)參數(shù),該參數(shù)對(duì)應(yīng)于.mlir應(yīng)將可復(fù)制文件寫(xiě)入的輸出文件名。可復(fù)制的內(nèi)容包含正在執(zhí)行的過(guò)程管理器的配置,以及運(yùn)行任何過(guò)程之前的初始IR。潛在的可復(fù)制性可能具有以下形式:
// configuration: -pass-pipeline=‘func(cse,canonicalize),inline’
// note: verifyPasses=false
module {
func @foo() {
…
}
}
本地復(fù)制器生成
可以向命令行傳遞一個(gè)附加標(biāo)志PassManager::enableCrashReproducerGeneration,并passpass-pipeline-local-reproducer命令行指定 該附加標(biāo)志 ,以表明pass管理器應(yīng)嘗試生成“本地”再現(xiàn)器。這將嘗試在pass失敗之前立即生成包含IR的復(fù)制器。這對(duì)于已知崩潰是在特定遍內(nèi)或原始輸入依賴(lài)于可能并不總是可用的成分(如語(yǔ)言或遍)的情況很有用。
例如,如果先前示例中的失敗來(lái)自canonicalize,則將生成以下復(fù)制器:
// configuration: -pass-pipeline=‘func(canonicalize)’
// note: verifyPasses=false
module {
func @foo() {
…
}
}
總結(jié)
以上是生活随笔為你收集整理的Pass Infrastructure基础架构(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。