Leslie Zhai via llvm-dev
2017-Oct-26 02:07 UTC
[llvm-dev] LLVM v6.0 Internalize and GlobalDCE PASS can not work together?
Hi Hal,
Thanks for your hint!
$ /opt/llvm-svn/bin/opt -S -internalize
-internalize-public-api-list=main -globaldce hello3.ll -o
hello3.dce.ll it works :)
But I argue that `main` Function should be inserted into ExternalNames
by default:
Index: lib/Transforms/IPO/Internalize.cpp
==================================================================---
lib/Transforms/IPO/Internalize.cpp (revision 316540)
+++ lib/Transforms/IPO/Internalize.cpp (working copy)
@@ -61,6 +61,7 @@
if (!APIFile.empty())
LoadFile(APIFile);
ExternalNames.insert(APIList.begin(), APIList.end());
+ ExternalNames.insert("main");
}
bool operator()(const GlobalValue &GV) {
在 2017年10月25日 21:20, Hal Finkel 写道:> Hi, Leslie,
>
> When you use internalize, you need to provide it with a list of
> symbols to preserve as external (otherwise everything will be
> internalized, including main, and then DCE will remove everything).
> You can use -internalize-public-api-list=main (a comma-separated list)
> or -internalize-public-api-file=some_file_name where some_file_name
> has the list of symbols. See the comments in
> lib/Transforms/IPO/Internalize.cpp.
>
> -Hal
>
> On 10/24/2017 11:22 PM, Leslie Zhai via llvm-dev wrote:
>> Hi LLVM developers,
>>
>> $ cat hello.c
>> #include <stdio.h>
>>
>> void foo() {
>> }
>>
>> int main(int argc, char *argv[]) {
>> for (int i = 0; i < 10; i++) {
>> printf("%d\n", i);
>> }
>> return 0;
>> }
>>
>> $ /opt/llvm-svn/bin/clang --version
>> Fedora clang version 6.0.0 (trunk 316308) (based on LLVM 6.0.0svn)
>> Target: x86_64-redhat-linux
>> Thread model: posix
>> InstalledDir: /opt/llvm-svn/bin
>>
>> $ /opt/llvm-svn/bin/clang -Xclang -disable-O0-optnone -S -emit-llvm
>> hello.c -o hello2.ll
>>
>> $ cat hello2.ll
>> ; ModuleID = 'hello.c'
>> source_filename = "hello.c"
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00",
align 1
>>
>> ; Function Attrs: noinline nounwind uwtable
>> define void @foo() #0 {
>> entry:
>> ret void
>> }
>>
>> ; Function Attrs: noinline nounwind uwtable
>> define i32 @main(i32 %argc, i8** %argv) #0 {
>> entry:
>> %retval = alloca i32, align 4
>> %argc.addr = alloca i32, align 4
>> %argv.addr = alloca i8**, align 8
>> %i = alloca i32, align 4
>> store i32 0, i32* %retval, align 4
>> store i32 %argc, i32* %argc.addr, align 4
>> store i8** %argv, i8*** %argv.addr, align 8
>> store i32 0, i32* %i, align 4
>> br label %for.cond
>>
>> for.cond: ; preds = %for.inc,
>> %entry
>> %0 = load i32, i32* %i, align 4
>> %cmp = icmp slt i32 %0, 10
>> br i1 %cmp, label %for.body, label %for.end
>>
>> for.body: ; preds = %for.cond
>> %1 = load i32, i32* %i, align 4
>> %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4
>> x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1)
>> br label %for.inc
>>
>> for.inc: ; preds = %for.body
>> %2 = load i32, i32* %i, align 4
>> %inc = add nsw i32 %2, 1
>> store i32 %inc, i32* %i, align 4
>> br label %for.cond
>>
>> for.end: ; preds = %for.cond
>> ret i32 0
>> }
>>
>> declare i32 @printf(i8*, ...) #1
>>
>> attributes #0 = { noinline nounwind uwtable
>> "correctly-rounded-divide-sqrt-fp-math"="false"
>> "disable-tail-calls"="false"
"less-precise-fpmad"="false"
>> "no-frame-pointer-elim"="true"
"no-frame-pointer-elim-non-leaf"
>> "no-infs-fp-math"="false"
"no-jump-tables"="false"
>> "no-nans-fp-math"="false"
"no-signed-zeros-fp-math"="false"
>> "no-trapping-math"="false"
"stack-protector-buffer-size"="8"
>> "target-cpu"="x86-64"
"target-features"="+fxsr,+mmx,+sse,+sse2,+x87"
>> "unsafe-fp-math"="false"
"use-soft-float"="false" }
>> attributes #1 = {
"correctly-rounded-divide-sqrt-fp-math"="false"
>> "disable-tail-calls"="false"
"less-precise-fpmad"="false"
>> "no-frame-pointer-elim"="true"
"no-frame-pointer-elim-non-leaf"
>> "no-infs-fp-math"="false"
"no-nans-fp-math"="false"
>> "no-signed-zeros-fp-math"="false"
"no-trapping-math"="false"
>> "stack-protector-buffer-size"="8"
"target-cpu"="x86-64"
>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87"
>> "unsafe-fp-math"="false"
"use-soft-float"="false" }
>>
>> !llvm.module.flags = !{!0}
>> !llvm.ident = !{!1}
>>
>> !0 = !{i32 1, !"wchar_size", i32 4}
>> !1 = !{!"clang version 6.0.0 (git at
github.com:llvm-mirror/clang.git
>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04)
>> (git at github.com:llvm-mirror/llvm.git
>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"}
>>
>> $ /opt/llvm-svn/bin/opt -S -internalize -globaldce hello2.ll -o
>> hello2.dce.ll
>>
>> $ cat hello2.dce.ll
>> ; ModuleID = 'hello2.ll'
>> source_filename = "hello.c"
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> !llvm.module.flags = !{!0}
>> !llvm.ident = !{!1}
>>
>> !0 = !{i32 1, !"wchar_size", i32 4}
>> !1 = !{!"clang version 6.0.0 (git at
github.com:llvm-mirror/clang.git
>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04)
>> (git at github.com:llvm-mirror/llvm.git
>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"}
>>
>> $ /opt/llvm-svn/bin/lli hello2.dce.ll
>> 'main' function not found in module.
>>
>>
>> *No* more Alive Functions, so LLVM v6.0 Internalize and GlobalDCE
>> PASS failed to MarkLive Function together?
>>
>>
>> But LLVM 3.1 is able to work together:
>>
>> $ ./build/Release+Asserts/bin/opt --version
>> LLVM (http://llvm.org/):
>> LLVM version 3.1
>> Optimized build with assertions.
>> Built Oct 23 2017 (16:22:51).
>> Default target: x86_64-unknown-linux-gnu
>> Host CPU: corei7-avx
>>
>> $ ./build/Release+Asserts/bin/clang -S -emit-llvm hello.c -o hello0.ll
>>
>> $ cat hello0.ll
>> ; ModuleID = 'hello.c'
>> target datalayout =
>>
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00",
align 1
>>
>> define void @foo() nounwind uwtable {
>> entry:
>> ret void
>> }
>>
>> define i32 @main(i32 %argc, i8** %argv) nounwind uwtable {
>> entry:
>> %retval = alloca i32, align 4
>> %argc.addr = alloca i32, align 4
>> %argv.addr = alloca i8**, align 8
>> %i = alloca i32, align 4
>> store i32 0, i32* %retval
>> store i32 %argc, i32* %argc.addr, align 4
>> store i8** %argv, i8*** %argv.addr, align 8
>> store i32 0, i32* %i, align 4
>> br label %for.cond
>>
>> for.cond: ; preds = %for.inc,
>> %entry
>> %0 = load i32* %i, align 4
>> %cmp = icmp slt i32 %0, 10
>> br i1 %cmp, label %for.body, label %for.end
>>
>> for.body: ; preds = %for.cond
>> %1 = load i32* %i, align 4
>> %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4
>> x i8]* @.str, i32 0, i32 0), i32 %1)
>> br label %for.inc
>>
>> for.inc: ; preds = %for.body
>> %2 = load i32* %i, align 4
>> %inc = add nsw i32 %2, 1
>> store i32 %inc, i32* %i, align 4
>> br label %for.cond
>>
>> for.end: ; preds = %for.cond
>> ret i32 0
>> }
>>
>> declare i32 @printf(i8*, ...)
>>
>> $ ./build/Release+Asserts/bin/opt -S -internalize -globaldce
>> hello0.ll -o hello0.dce.ll
>>
>> $ cat hello0.dce.ll
>> ; ModuleID = 'hello0.ll'
>> target datalayout =
>>
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00",
align 1
>>
>> define i32 @main(i32 %argc, i8** %argv) nounwind uwtable {
>> entry:
>> %retval = alloca i32, align 4
>> %argc.addr = alloca i32, align 4
>> %argv.addr = alloca i8**, align 8
>> %i = alloca i32, align 4
>> store i32 0, i32* %retval
>> store i32 %argc, i32* %argc.addr, align 4
>> store i8** %argv, i8*** %argv.addr, align 8
>> store i32 0, i32* %i, align 4
>> br label %for.cond
>>
>> for.cond: ; preds = %for.inc,
>> %entry
>> %0 = load i32* %i, align 4
>> %cmp = icmp slt i32 %0, 10
>> br i1 %cmp, label %for.body, label %for.end
>>
>> for.body: ; preds = %for.cond
>> %1 = load i32* %i, align 4
>> %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4
>> x i8]* @.str, i32 0, i32 0), i32 %1)
>> br label %for.inc
>>
>> for.inc: ; preds = %for.body
>> %2 = load i32* %i, align 4
>> %inc = add nsw i32 %2, 1
>> store i32 %inc, i32* %i, align 4
>> br label %for.cond
>>
>> for.end: ; preds = %for.cond
>> ret i32 0
>> }
>>
>> declare i32 @printf(i8*, ...)
>>
>>
>> Succeeded drop DeadFunction foo.
>>
>> Maybe I wrongly use the Internalize and GlobalDCE PASS together?
>> please give me some hints, thanks a lot!
>>
>>
>> PS: LLVM 6.0 Internalize PASS is able to work, internal foo:
>>
>> $ /opt/llvm-svn/bin/opt -S -internalize hello2.ll -o hello2.internal.ll
>>
>> $ cat hello2.internal.ll
>> ; ModuleID = 'hello2.ll'
>> source_filename = "hello.c"
>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00",
align 1
>>
>> ; Function Attrs: noinline nounwind uwtable
>> define internal void @foo() #0 {
>> entry:
>> ret void
>> }
>>
>> ; Function Attrs: noinline nounwind uwtable
>> define internal i32 @main(i32 %argc, i8** %argv) #0 {
>> entry:
>> %retval = alloca i32, align 4
>> %argc.addr = alloca i32, align 4
>> %argv.addr = alloca i8**, align 8
>> %i = alloca i32, align 4
>> store i32 0, i32* %retval, align 4
>> store i32 %argc, i32* %argc.addr, align 4
>> store i8** %argv, i8*** %argv.addr, align 8
>> store i32 0, i32* %i, align 4
>> br label %for.cond
>>
>> for.cond: ; preds = %for.inc,
>> %entry
>> %0 = load i32, i32* %i, align 4
>> %cmp = icmp slt i32 %0, 10
>> br i1 %cmp, label %for.body, label %for.end
>>
>> for.body: ; preds = %for.cond
>> %1 = load i32, i32* %i, align 4
>> %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4
>> x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1)
>> br label %for.inc
>>
>> for.inc: ; preds = %for.body
>> %2 = load i32, i32* %i, align 4
>> %inc = add nsw i32 %2, 1
>> store i32 %inc, i32* %i, align 4
>> br label %for.cond
>>
>> for.end: ; preds = %for.cond
>> ret i32 0
>> }
>>
>> declare i32 @printf(i8*, ...) #1
>>
>> attributes #0 = { noinline nounwind uwtable
>> "correctly-rounded-divide-sqrt-fp-math"="false"
>> "disable-tail-calls"="false"
"less-precise-fpmad"="false"
>> "no-frame-pointer-elim"="true"
"no-frame-pointer-elim-non-leaf"
>> "no-infs-fp-math"="false"
"no-jump-tables"="false"
>> "no-nans-fp-math"="false"
"no-signed-zeros-fp-math"="false"
>> "no-trapping-math"="false"
"stack-protector-buffer-size"="8"
>> "target-cpu"="x86-64"
"target-features"="+fxsr,+mmx,+sse,+sse2,+x87"
>> "unsafe-fp-math"="false"
"use-soft-float"="false" }
>> attributes #1 = {
"correctly-rounded-divide-sqrt-fp-math"="false"
>> "disable-tail-calls"="false"
"less-precise-fpmad"="false"
>> "no-frame-pointer-elim"="true"
"no-frame-pointer-elim-non-leaf"
>> "no-infs-fp-math"="false"
"no-nans-fp-math"="false"
>> "no-signed-zeros-fp-math"="false"
"no-trapping-math"="false"
>> "stack-protector-buffer-size"="8"
"target-cpu"="x86-64"
>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87"
>> "unsafe-fp-math"="false"
"use-soft-float"="false" }
>>
>> !llvm.module.flags = !{!0}
>> !llvm.ident = !{!1}
>>
>> !0 = !{i32 1, !"wchar_size", i32 4}
>> !1 = !{!"clang version 6.0.0 (git at
github.com:llvm-mirror/clang.git
>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04)
>> (git at github.com:llvm-mirror/llvm.git
>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"}
>>
>
--
Regards,
Leslie Zhai - https://reviews.llvm.org/p/xiangzhai/
Hal Finkel via llvm-dev
2017-Oct-26 02:20 UTC
[llvm-dev] LLVM v6.0 Internalize and GlobalDCE PASS can not work together?
On 10/25/2017 09:07 PM, Leslie Zhai wrote:> Hi Hal, > > Thanks for your hint! > > $ /opt/llvm-svn/bin/opt -S -internalize > -internalize-public-api-list=main -globaldce hello3.ll -o > hello3.dce.ll it works :) > > But I argue that `main` Function should be inserted into ExternalNames > by default:But "main" is neither necessary nor sufficient depending on the target/configuration. Internalize is really intended to be used by a linker plugin (or in some other context where a callback can be provided that has the right information). Using the pass as you're doing is really a development aid - it's not a user-facing tool by itself. -Hal> > Index: lib/Transforms/IPO/Internalize.cpp > ==================================================================> --- lib/Transforms/IPO/Internalize.cpp (revision 316540) > +++ lib/Transforms/IPO/Internalize.cpp (working copy) > @@ -61,6 +61,7 @@ > if (!APIFile.empty()) > LoadFile(APIFile); > ExternalNames.insert(APIList.begin(), APIList.end()); > + ExternalNames.insert("main"); > } > > bool operator()(const GlobalValue &GV) { > > > 在 2017年10月25日 21:20, Hal Finkel 写道: >> Hi, Leslie, >> >> When you use internalize, you need to provide it with a list of >> symbols to preserve as external (otherwise everything will be >> internalized, including main, and then DCE will remove everything). >> You can use -internalize-public-api-list=main (a comma-separated >> list) or -internalize-public-api-file=some_file_name where >> some_file_name has the list of symbols. See the comments in >> lib/Transforms/IPO/Internalize.cpp. >> >> -Hal >> >> On 10/24/2017 11:22 PM, Leslie Zhai via llvm-dev wrote: >>> Hi LLVM developers, >>> >>> $ cat hello.c >>> #include <stdio.h> >>> >>> void foo() { >>> } >>> >>> int main(int argc, char *argv[]) { >>> for (int i = 0; i < 10; i++) { >>> printf("%d\n", i); >>> } >>> return 0; >>> } >>> >>> $ /opt/llvm-svn/bin/clang --version >>> Fedora clang version 6.0.0 (trunk 316308) (based on LLVM 6.0.0svn) >>> Target: x86_64-redhat-linux >>> Thread model: posix >>> InstalledDir: /opt/llvm-svn/bin >>> >>> $ /opt/llvm-svn/bin/clang -Xclang -disable-O0-optnone -S -emit-llvm >>> hello.c -o hello2.ll >>> >>> $ cat hello2.ll >>> ; ModuleID = 'hello.c' >>> source_filename = "hello.c" >>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >>> target triple = "x86_64-unknown-linux-gnu" >>> >>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>> >>> ; Function Attrs: noinline nounwind uwtable >>> define void @foo() #0 { >>> entry: >>> ret void >>> } >>> >>> ; Function Attrs: noinline nounwind uwtable >>> define i32 @main(i32 %argc, i8** %argv) #0 { >>> entry: >>> %retval = alloca i32, align 4 >>> %argc.addr = alloca i32, align 4 >>> %argv.addr = alloca i8**, align 8 >>> %i = alloca i32, align 4 >>> store i32 0, i32* %retval, align 4 >>> store i32 %argc, i32* %argc.addr, align 4 >>> store i8** %argv, i8*** %argv.addr, align 8 >>> store i32 0, i32* %i, align 4 >>> br label %for.cond >>> >>> for.cond: ; preds = >>> %for.inc, %entry >>> %0 = load i32, i32* %i, align 4 >>> %cmp = icmp slt i32 %0, 10 >>> br i1 %cmp, label %for.body, label %for.end >>> >>> for.body: ; preds = %for.cond >>> %1 = load i32, i32* %i, align 4 >>> %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 >>> x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1) >>> br label %for.inc >>> >>> for.inc: ; preds = %for.body >>> %2 = load i32, i32* %i, align 4 >>> %inc = add nsw i32 %2, 1 >>> store i32 %inc, i32* %i, align 4 >>> br label %for.cond >>> >>> for.end: ; preds = %for.cond >>> ret i32 0 >>> } >>> >>> declare i32 @printf(i8*, ...) #1 >>> >>> attributes #0 = { noinline nounwind uwtable >>> "correctly-rounded-divide-sqrt-fp-math"="false" >>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>> "no-infs-fp-math"="false" "no-jump-tables"="false" >>> "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" >>> "no-trapping-math"="false" "stack-protector-buffer-size"="8" >>> "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>> attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" >>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>> "no-infs-fp-math"="false" "no-nans-fp-math"="false" >>> "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" >>> "stack-protector-buffer-size"="8" "target-cpu"="x86-64" >>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>> >>> !llvm.module.flags = !{!0} >>> !llvm.ident = !{!1} >>> >>> !0 = !{i32 1, !"wchar_size", i32 4} >>> !1 = !{!"clang version 6.0.0 (git at github.com:llvm-mirror/clang.git >>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04) >>> (git at github.com:llvm-mirror/llvm.git >>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"} >>> >>> $ /opt/llvm-svn/bin/opt -S -internalize -globaldce hello2.ll -o >>> hello2.dce.ll >>> >>> $ cat hello2.dce.ll >>> ; ModuleID = 'hello2.ll' >>> source_filename = "hello.c" >>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >>> target triple = "x86_64-unknown-linux-gnu" >>> >>> !llvm.module.flags = !{!0} >>> !llvm.ident = !{!1} >>> >>> !0 = !{i32 1, !"wchar_size", i32 4} >>> !1 = !{!"clang version 6.0.0 (git at github.com:llvm-mirror/clang.git >>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04) >>> (git at github.com:llvm-mirror/llvm.git >>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"} >>> >>> $ /opt/llvm-svn/bin/lli hello2.dce.ll >>> 'main' function not found in module. >>> >>> >>> *No* more Alive Functions, so LLVM v6.0 Internalize and GlobalDCE >>> PASS failed to MarkLive Function together? >>> >>> >>> But LLVM 3.1 is able to work together: >>> >>> $ ./build/Release+Asserts/bin/opt --version >>> LLVM (http://llvm.org/): >>> LLVM version 3.1 >>> Optimized build with assertions. >>> Built Oct 23 2017 (16:22:51). >>> Default target: x86_64-unknown-linux-gnu >>> Host CPU: corei7-avx >>> >>> $ ./build/Release+Asserts/bin/clang -S -emit-llvm hello.c -o hello0.ll >>> >>> $ cat hello0.ll >>> ; ModuleID = 'hello.c' >>> target datalayout = >>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" >>> target triple = "x86_64-unknown-linux-gnu" >>> >>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>> >>> define void @foo() nounwind uwtable { >>> entry: >>> ret void >>> } >>> >>> define i32 @main(i32 %argc, i8** %argv) nounwind uwtable { >>> entry: >>> %retval = alloca i32, align 4 >>> %argc.addr = alloca i32, align 4 >>> %argv.addr = alloca i8**, align 8 >>> %i = alloca i32, align 4 >>> store i32 0, i32* %retval >>> store i32 %argc, i32* %argc.addr, align 4 >>> store i8** %argv, i8*** %argv.addr, align 8 >>> store i32 0, i32* %i, align 4 >>> br label %for.cond >>> >>> for.cond: ; preds = >>> %for.inc, %entry >>> %0 = load i32* %i, align 4 >>> %cmp = icmp slt i32 %0, 10 >>> br i1 %cmp, label %for.body, label %for.end >>> >>> for.body: ; preds = %for.cond >>> %1 = load i32* %i, align 4 >>> %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds >>> ([4 x i8]* @.str, i32 0, i32 0), i32 %1) >>> br label %for.inc >>> >>> for.inc: ; preds = %for.body >>> %2 = load i32* %i, align 4 >>> %inc = add nsw i32 %2, 1 >>> store i32 %inc, i32* %i, align 4 >>> br label %for.cond >>> >>> for.end: ; preds = %for.cond >>> ret i32 0 >>> } >>> >>> declare i32 @printf(i8*, ...) >>> >>> $ ./build/Release+Asserts/bin/opt -S -internalize -globaldce >>> hello0.ll -o hello0.dce.ll >>> >>> $ cat hello0.dce.ll >>> ; ModuleID = 'hello0.ll' >>> target datalayout = >>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" >>> target triple = "x86_64-unknown-linux-gnu" >>> >>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>> >>> define i32 @main(i32 %argc, i8** %argv) nounwind uwtable { >>> entry: >>> %retval = alloca i32, align 4 >>> %argc.addr = alloca i32, align 4 >>> %argv.addr = alloca i8**, align 8 >>> %i = alloca i32, align 4 >>> store i32 0, i32* %retval >>> store i32 %argc, i32* %argc.addr, align 4 >>> store i8** %argv, i8*** %argv.addr, align 8 >>> store i32 0, i32* %i, align 4 >>> br label %for.cond >>> >>> for.cond: ; preds = >>> %for.inc, %entry >>> %0 = load i32* %i, align 4 >>> %cmp = icmp slt i32 %0, 10 >>> br i1 %cmp, label %for.body, label %for.end >>> >>> for.body: ; preds = %for.cond >>> %1 = load i32* %i, align 4 >>> %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds >>> ([4 x i8]* @.str, i32 0, i32 0), i32 %1) >>> br label %for.inc >>> >>> for.inc: ; preds = %for.body >>> %2 = load i32* %i, align 4 >>> %inc = add nsw i32 %2, 1 >>> store i32 %inc, i32* %i, align 4 >>> br label %for.cond >>> >>> for.end: ; preds = %for.cond >>> ret i32 0 >>> } >>> >>> declare i32 @printf(i8*, ...) >>> >>> >>> Succeeded drop DeadFunction foo. >>> >>> Maybe I wrongly use the Internalize and GlobalDCE PASS together? >>> please give me some hints, thanks a lot! >>> >>> >>> PS: LLVM 6.0 Internalize PASS is able to work, internal foo: >>> >>> $ /opt/llvm-svn/bin/opt -S -internalize hello2.ll -o hello2.internal.ll >>> >>> $ cat hello2.internal.ll >>> ; ModuleID = 'hello2.ll' >>> source_filename = "hello.c" >>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >>> target triple = "x86_64-unknown-linux-gnu" >>> >>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>> >>> ; Function Attrs: noinline nounwind uwtable >>> define internal void @foo() #0 { >>> entry: >>> ret void >>> } >>> >>> ; Function Attrs: noinline nounwind uwtable >>> define internal i32 @main(i32 %argc, i8** %argv) #0 { >>> entry: >>> %retval = alloca i32, align 4 >>> %argc.addr = alloca i32, align 4 >>> %argv.addr = alloca i8**, align 8 >>> %i = alloca i32, align 4 >>> store i32 0, i32* %retval, align 4 >>> store i32 %argc, i32* %argc.addr, align 4 >>> store i8** %argv, i8*** %argv.addr, align 8 >>> store i32 0, i32* %i, align 4 >>> br label %for.cond >>> >>> for.cond: ; preds = >>> %for.inc, %entry >>> %0 = load i32, i32* %i, align 4 >>> %cmp = icmp slt i32 %0, 10 >>> br i1 %cmp, label %for.body, label %for.end >>> >>> for.body: ; preds = %for.cond >>> %1 = load i32, i32* %i, align 4 >>> %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 >>> x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1) >>> br label %for.inc >>> >>> for.inc: ; preds = %for.body >>> %2 = load i32, i32* %i, align 4 >>> %inc = add nsw i32 %2, 1 >>> store i32 %inc, i32* %i, align 4 >>> br label %for.cond >>> >>> for.end: ; preds = %for.cond >>> ret i32 0 >>> } >>> >>> declare i32 @printf(i8*, ...) #1 >>> >>> attributes #0 = { noinline nounwind uwtable >>> "correctly-rounded-divide-sqrt-fp-math"="false" >>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>> "no-infs-fp-math"="false" "no-jump-tables"="false" >>> "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" >>> "no-trapping-math"="false" "stack-protector-buffer-size"="8" >>> "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>> attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" >>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>> "no-infs-fp-math"="false" "no-nans-fp-math"="false" >>> "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" >>> "stack-protector-buffer-size"="8" "target-cpu"="x86-64" >>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>> >>> !llvm.module.flags = !{!0} >>> !llvm.ident = !{!1} >>> >>> !0 = !{i32 1, !"wchar_size", i32 4} >>> !1 = !{!"clang version 6.0.0 (git at github.com:llvm-mirror/clang.git >>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04) >>> (git at github.com:llvm-mirror/llvm.git >>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"} >>> >> >-- Hal Finkel Lead, Compiler Technology and Programming Languages Leadership Computing Facility Argonne National Laboratory
Leslie Zhai via llvm-dev
2017-Oct-26 02:45 UTC
[llvm-dev] LLVM v6.0 Internalize and GlobalDCE PASS can not work together?
在 2017年10月26日 10:20, Hal Finkel 写道:> > On 10/25/2017 09:07 PM, Leslie Zhai wrote: >> Hi Hal, >> >> Thanks for your hint! >> >> $ /opt/llvm-svn/bin/opt -S -internalize >> -internalize-public-api-list=main -globaldce hello3.ll -o >> hello3.dce.ll it works :) >> >> But I argue that `main` Function should be inserted into >> ExternalNames by default: > > But "main" is neither necessary nor sufficient depending on the > target/configuration. Internalize is really intended to be used by a > linker plugin (or in some other context where a callback can be > provided that has the right information). Using the pass as you're > doing is really a development aid - it's not a user-facing tool by > itself.Thanks for your teaching! yes, I just use it to remove DeadFunctions for ScaffCC https://github.com/ScaffCC/ScaffCC/blob/master/scaffold/Scaffold.makefile#L122 Ali JavadiAbhari, Shruti Patil, Daniel Kudrow, Jeff Heckey, Alexey Lvov, Frederic Chong and Margaret Martonosi, ScaffCC: A Framework for Compilation and Analysis of Quantum Computing Programs, ACM International Conference on Computing Frontiers (CF 2014), Cagliari, Italy, May 2014> > -Hal > >> >> Index: lib/Transforms/IPO/Internalize.cpp >> ==================================================================>> --- lib/Transforms/IPO/Internalize.cpp (revision 316540) >> +++ lib/Transforms/IPO/Internalize.cpp (working copy) >> @@ -61,6 +61,7 @@ >> if (!APIFile.empty()) >> LoadFile(APIFile); >> ExternalNames.insert(APIList.begin(), APIList.end()); >> + ExternalNames.insert("main"); >> } >> >> bool operator()(const GlobalValue &GV) { >> >> >> 在 2017年10月25日 21:20, Hal Finkel 写道: >>> Hi, Leslie, >>> >>> When you use internalize, you need to provide it with a list of >>> symbols to preserve as external (otherwise everything will be >>> internalized, including main, and then DCE will remove everything). >>> You can use -internalize-public-api-list=main (a comma-separated >>> list) or -internalize-public-api-file=some_file_name where >>> some_file_name has the list of symbols. See the comments in >>> lib/Transforms/IPO/Internalize.cpp. >>> >>> -Hal >>> >>> On 10/24/2017 11:22 PM, Leslie Zhai via llvm-dev wrote: >>>> Hi LLVM developers, >>>> >>>> $ cat hello.c >>>> #include <stdio.h> >>>> >>>> void foo() { >>>> } >>>> >>>> int main(int argc, char *argv[]) { >>>> for (int i = 0; i < 10; i++) { >>>> printf("%d\n", i); >>>> } >>>> return 0; >>>> } >>>> >>>> $ /opt/llvm-svn/bin/clang --version >>>> Fedora clang version 6.0.0 (trunk 316308) (based on LLVM 6.0.0svn) >>>> Target: x86_64-redhat-linux >>>> Thread model: posix >>>> InstalledDir: /opt/llvm-svn/bin >>>> >>>> $ /opt/llvm-svn/bin/clang -Xclang -disable-O0-optnone -S -emit-llvm >>>> hello.c -o hello2.ll >>>> >>>> $ cat hello2.ll >>>> ; ModuleID = 'hello.c' >>>> source_filename = "hello.c" >>>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >>>> target triple = "x86_64-unknown-linux-gnu" >>>> >>>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>>> >>>> ; Function Attrs: noinline nounwind uwtable >>>> define void @foo() #0 { >>>> entry: >>>> ret void >>>> } >>>> >>>> ; Function Attrs: noinline nounwind uwtable >>>> define i32 @main(i32 %argc, i8** %argv) #0 { >>>> entry: >>>> %retval = alloca i32, align 4 >>>> %argc.addr = alloca i32, align 4 >>>> %argv.addr = alloca i8**, align 8 >>>> %i = alloca i32, align 4 >>>> store i32 0, i32* %retval, align 4 >>>> store i32 %argc, i32* %argc.addr, align 4 >>>> store i8** %argv, i8*** %argv.addr, align 8 >>>> store i32 0, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.cond: ; preds = >>>> %for.inc, %entry >>>> %0 = load i32, i32* %i, align 4 >>>> %cmp = icmp slt i32 %0, 10 >>>> br i1 %cmp, label %for.body, label %for.end >>>> >>>> for.body: ; preds = %for.cond >>>> %1 = load i32, i32* %i, align 4 >>>> %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds >>>> ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1) >>>> br label %for.inc >>>> >>>> for.inc: ; preds = %for.body >>>> %2 = load i32, i32* %i, align 4 >>>> %inc = add nsw i32 %2, 1 >>>> store i32 %inc, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.end: ; preds = %for.cond >>>> ret i32 0 >>>> } >>>> >>>> declare i32 @printf(i8*, ...) #1 >>>> >>>> attributes #0 = { noinline nounwind uwtable >>>> "correctly-rounded-divide-sqrt-fp-math"="false" >>>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>>> "no-infs-fp-math"="false" "no-jump-tables"="false" >>>> "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" >>>> "no-trapping-math"="false" "stack-protector-buffer-size"="8" >>>> "target-cpu"="x86-64" >>>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>>> attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" >>>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false" >>>> "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" >>>> "stack-protector-buffer-size"="8" "target-cpu"="x86-64" >>>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>>> >>>> !llvm.module.flags = !{!0} >>>> !llvm.ident = !{!1} >>>> >>>> !0 = !{i32 1, !"wchar_size", i32 4} >>>> !1 = !{!"clang version 6.0.0 (git at github.com:llvm-mirror/clang.git >>>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04) >>>> (git at github.com:llvm-mirror/llvm.git >>>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"} >>>> >>>> $ /opt/llvm-svn/bin/opt -S -internalize -globaldce hello2.ll -o >>>> hello2.dce.ll >>>> >>>> $ cat hello2.dce.ll >>>> ; ModuleID = 'hello2.ll' >>>> source_filename = "hello.c" >>>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >>>> target triple = "x86_64-unknown-linux-gnu" >>>> >>>> !llvm.module.flags = !{!0} >>>> !llvm.ident = !{!1} >>>> >>>> !0 = !{i32 1, !"wchar_size", i32 4} >>>> !1 = !{!"clang version 6.0.0 (git at github.com:llvm-mirror/clang.git >>>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04) >>>> (git at github.com:llvm-mirror/llvm.git >>>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"} >>>> >>>> $ /opt/llvm-svn/bin/lli hello2.dce.ll >>>> 'main' function not found in module. >>>> >>>> >>>> *No* more Alive Functions, so LLVM v6.0 Internalize and GlobalDCE >>>> PASS failed to MarkLive Function together? >>>> >>>> >>>> But LLVM 3.1 is able to work together: >>>> >>>> $ ./build/Release+Asserts/bin/opt --version >>>> LLVM (http://llvm.org/): >>>> LLVM version 3.1 >>>> Optimized build with assertions. >>>> Built Oct 23 2017 (16:22:51). >>>> Default target: x86_64-unknown-linux-gnu >>>> Host CPU: corei7-avx >>>> >>>> $ ./build/Release+Asserts/bin/clang -S -emit-llvm hello.c -o hello0.ll >>>> >>>> $ cat hello0.ll >>>> ; ModuleID = 'hello.c' >>>> target datalayout = >>>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" >>>> target triple = "x86_64-unknown-linux-gnu" >>>> >>>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>>> >>>> define void @foo() nounwind uwtable { >>>> entry: >>>> ret void >>>> } >>>> >>>> define i32 @main(i32 %argc, i8** %argv) nounwind uwtable { >>>> entry: >>>> %retval = alloca i32, align 4 >>>> %argc.addr = alloca i32, align 4 >>>> %argv.addr = alloca i8**, align 8 >>>> %i = alloca i32, align 4 >>>> store i32 0, i32* %retval >>>> store i32 %argc, i32* %argc.addr, align 4 >>>> store i8** %argv, i8*** %argv.addr, align 8 >>>> store i32 0, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.cond: ; preds = >>>> %for.inc, %entry >>>> %0 = load i32* %i, align 4 >>>> %cmp = icmp slt i32 %0, 10 >>>> br i1 %cmp, label %for.body, label %for.end >>>> >>>> for.body: ; preds = %for.cond >>>> %1 = load i32* %i, align 4 >>>> %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds >>>> ([4 x i8]* @.str, i32 0, i32 0), i32 %1) >>>> br label %for.inc >>>> >>>> for.inc: ; preds = %for.body >>>> %2 = load i32* %i, align 4 >>>> %inc = add nsw i32 %2, 1 >>>> store i32 %inc, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.end: ; preds = %for.cond >>>> ret i32 0 >>>> } >>>> >>>> declare i32 @printf(i8*, ...) >>>> >>>> $ ./build/Release+Asserts/bin/opt -S -internalize -globaldce >>>> hello0.ll -o hello0.dce.ll >>>> >>>> $ cat hello0.dce.ll >>>> ; ModuleID = 'hello0.ll' >>>> target datalayout = >>>> "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" >>>> target triple = "x86_64-unknown-linux-gnu" >>>> >>>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>>> >>>> define i32 @main(i32 %argc, i8** %argv) nounwind uwtable { >>>> entry: >>>> %retval = alloca i32, align 4 >>>> %argc.addr = alloca i32, align 4 >>>> %argv.addr = alloca i8**, align 8 >>>> %i = alloca i32, align 4 >>>> store i32 0, i32* %retval >>>> store i32 %argc, i32* %argc.addr, align 4 >>>> store i8** %argv, i8*** %argv.addr, align 8 >>>> store i32 0, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.cond: ; preds = >>>> %for.inc, %entry >>>> %0 = load i32* %i, align 4 >>>> %cmp = icmp slt i32 %0, 10 >>>> br i1 %cmp, label %for.body, label %for.end >>>> >>>> for.body: ; preds = %for.cond >>>> %1 = load i32* %i, align 4 >>>> %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds >>>> ([4 x i8]* @.str, i32 0, i32 0), i32 %1) >>>> br label %for.inc >>>> >>>> for.inc: ; preds = %for.body >>>> %2 = load i32* %i, align 4 >>>> %inc = add nsw i32 %2, 1 >>>> store i32 %inc, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.end: ; preds = %for.cond >>>> ret i32 0 >>>> } >>>> >>>> declare i32 @printf(i8*, ...) >>>> >>>> >>>> Succeeded drop DeadFunction foo. >>>> >>>> Maybe I wrongly use the Internalize and GlobalDCE PASS together? >>>> please give me some hints, thanks a lot! >>>> >>>> >>>> PS: LLVM 6.0 Internalize PASS is able to work, internal foo: >>>> >>>> $ /opt/llvm-svn/bin/opt -S -internalize hello2.ll -o >>>> hello2.internal.ll >>>> >>>> $ cat hello2.internal.ll >>>> ; ModuleID = 'hello2.ll' >>>> source_filename = "hello.c" >>>> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >>>> target triple = "x86_64-unknown-linux-gnu" >>>> >>>> @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 >>>> >>>> ; Function Attrs: noinline nounwind uwtable >>>> define internal void @foo() #0 { >>>> entry: >>>> ret void >>>> } >>>> >>>> ; Function Attrs: noinline nounwind uwtable >>>> define internal i32 @main(i32 %argc, i8** %argv) #0 { >>>> entry: >>>> %retval = alloca i32, align 4 >>>> %argc.addr = alloca i32, align 4 >>>> %argv.addr = alloca i8**, align 8 >>>> %i = alloca i32, align 4 >>>> store i32 0, i32* %retval, align 4 >>>> store i32 %argc, i32* %argc.addr, align 4 >>>> store i8** %argv, i8*** %argv.addr, align 8 >>>> store i32 0, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.cond: ; preds = >>>> %for.inc, %entry >>>> %0 = load i32, i32* %i, align 4 >>>> %cmp = icmp slt i32 %0, 10 >>>> br i1 %cmp, label %for.body, label %for.end >>>> >>>> for.body: ; preds = %for.cond >>>> %1 = load i32, i32* %i, align 4 >>>> %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds >>>> ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1) >>>> br label %for.inc >>>> >>>> for.inc: ; preds = %for.body >>>> %2 = load i32, i32* %i, align 4 >>>> %inc = add nsw i32 %2, 1 >>>> store i32 %inc, i32* %i, align 4 >>>> br label %for.cond >>>> >>>> for.end: ; preds = %for.cond >>>> ret i32 0 >>>> } >>>> >>>> declare i32 @printf(i8*, ...) #1 >>>> >>>> attributes #0 = { noinline nounwind uwtable >>>> "correctly-rounded-divide-sqrt-fp-math"="false" >>>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>>> "no-infs-fp-math"="false" "no-jump-tables"="false" >>>> "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" >>>> "no-trapping-math"="false" "stack-protector-buffer-size"="8" >>>> "target-cpu"="x86-64" >>>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>>> attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" >>>> "disable-tail-calls"="false" "less-precise-fpmad"="false" >>>> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" >>>> "no-infs-fp-math"="false" "no-nans-fp-math"="false" >>>> "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" >>>> "stack-protector-buffer-size"="8" "target-cpu"="x86-64" >>>> "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" >>>> "unsafe-fp-math"="false" "use-soft-float"="false" } >>>> >>>> !llvm.module.flags = !{!0} >>>> !llvm.ident = !{!1} >>>> >>>> !0 = !{i32 1, !"wchar_size", i32 4} >>>> !1 = !{!"clang version 6.0.0 (git at github.com:llvm-mirror/clang.git >>>> 0aed123216ad4a38a9c2b16f1783895fd5cb1a04) >>>> (git at github.com:llvm-mirror/llvm.git >>>> d209b37aec1e392dabbf9b5324ea4a60c36fbc55)"} >>>> >>> >> >-- Regards, Leslie Zhai - https://reviews.llvm.org/p/xiangzhai/