Hi Michael, > [...] >> Now you advise to run the '-debug-only=sil-redundant-load-elim' so I tried >> >> sil-opt [...] -debug-only=sil-redundant-load-elim >> >> but it doesn't seem happy with that. Did I misunderstand how to pass this >> option? > > What do you mean by it doesn't seem happy?
I was using a too old/wrong version of sil-opt (the one from Xcode 9 beta N)
which didn't have that option. Resolved by using the one from my own swift
build.
> [...]
>> is this roughly what you had in mind?
>
> Nope. I was suggesting that you write the SIL by hand. It will be much easier.
Ha, that's a much better idea, thanks for your help, much appreciated! No idea
why I didn't think of that. This is today's update:
--- SNIP (whole file attached as test-load-forwarding.sil) ---
// bar()
sil hidden @bar : $@convention(thin) () -> () {
bb0:
alloc_global @MyIntStorage
%int_storage = global_addr @MyIntStorage : $*Int
%value_raw = integer_literal $Builtin.Int64, 42
%value = struct $Int (%value_raw : $Builtin.Int64)
store %value to %int_storage : $*Int
%f_buz = function_ref @buz : $@convention(thin) (@in_guaranteed Int) -> ()
%r1 = apply %f_buz(%int_storage) : $@convention(thin) (@in_guaranteed Int) ->
()
%value_again = load %int_storage : $*Int
%f_test = function_ref @testNumber12345 : $@convention(thin) (Int) -> ()
%r2 = apply %f_test(%value_again) : $@convention(thin) (Int) -> ()
// just to test an illegal function
%f_bad = function_ref @bad : $@convention(thin) (@in_guaranteed Int) -> ()
%r3 = apply %f_bad(%int_storage) : $@convention(thin) (@in_guaranteed Int) ->
()
%value_again2 = load %int_storage : $*Int
%r4 = apply %f_test(%value_again2) : $@convention(thin) (Int) -> ()
return %r2 : $()
} // end sil function 'bar'
--- SNAP ---
So I make a global Int storage, store the number 42 to it, invoke buz() which
takes an @in_guaranteed Int, then load it again (this is redundant as
@in_guaranteed isn't allowed to modify it). I also pass the loaded number to
the function testNumber12345() which just tests that it's the number 12345
(which it isn't but I wanted to be sure it's actually consumed)
Then (because I believe the RLE actually works) I also introduced a function
`bad` which is a bit like `buz` but it does actually write to the *Int which I
believe is illegal (right?).
Now let's see what we get with sil-opt
I run the following command:
sil-opt -verify -assume-parsing-unqualified-ownership-sil
-redundant-load-elim -debug-only=sil-redundant-load-elim -debug
test-load-forwarding.sil
which gives me the following output (my annotations marked as [JW: ... ])
--- SNIP (whole file attached as test-load-forwarding.sil-opt) ---
*** RLE on function: testNumber12345 ***
*** RLE on function: buz ***
*** RLE on function: bad ***
*** RLE on function: bar ***
LSLocation #0 %1 = global_addr @MyIntStorage : $*Int // users: %12,
%11, %7, %6, %4
Projection Path [$*Int
Field: var _value: Int64 of: $*Builtin.Int64]
PROCESS bb0 for RLE.
WRITE alloc_global @MyIntStorage // id: %0
WRITE %6 = apply %5(%1) : $@convention(thin) (@in_guaranteed Int) -> ()
FORWARD %3 = struct $Int (%2 : $Builtin.Int64) // user: %4
to %7 = load %1 : $*Int // user: %9
WRITE %9 = apply %8(%7) : $@convention(thin) (Int) -> () // user: %14
WRITE %11 = apply %10(%1) : $@convention(thin) (@in_guaranteed Int) -> ()
WRITE %13 = apply %8(%12) : $@convention(thin) (Int) -> ()
Replacing %7 = load %1 : $*Int // user: %9
With %3 = struct $Int (%2 : $Builtin.Int64) // user: %4
[JW: ^^^^ this looks pretty promising to me, don't understand all the output
but looks like it's replacing a load :) ]
*** RLE on function: main ***
sil_stage canonical
[...]
// bar
sil hidden @bar : $@convention(thin) () -> () {
bb0:
alloc_global @MyIntStorage // id: %0
%1 = global_addr @MyIntStorage : $*Int // users: %11, %10, %6, %4
%2 = integer_literal $Builtin.Int64, 42 // user: %3
%3 = struct $Int (%2 : $Builtin.Int64) // users: %8, %4
store %3 to %1 : $*Int // id: %4
// function_ref buz
%5 = function_ref @buz : $@convention(thin) (@in_guaranteed Int) -> () //
user: %6
%6 = apply %5(%1) : $@convention(thin) (@in_guaranteed Int) -> ()
// function_ref testNumber12345
%7 = function_ref @testNumber12345 : $@convention(thin) (Int) -> () // users:
%12, %8
[JW: Indeed, it seems to have optimised out the redundant load. So that
works! ]
%8 = apply %7(%3) : $@convention(thin) (Int) -> () // user: %13
// function_ref bad
%9 = function_ref @bad : $@convention(thin) (@in_guaranteed Int) -> () //
user: %10
%10 = apply %9(%1) : $@convention(thin) (@in_guaranteed Int) -> ()
[JW: Wow, very clever, it didn't optimise out this load despite me giving the
wrong guarantee that it's not actually modified (or am I misunderstanding
something]
%11 = load %1 : $*Int // user: %12
%12 = apply %7(%11) : $@convention(thin) (Int) -> ()
return %8 : $() // id: %13
} // end sil function 'bar'
[...]
--- SNAP ---
Long story short, I think the RLE actually works for the test case I created.
It's even clever enough to see through my invalid function bad() which modified
the storage despite its claim that it doesn't. I might also be misunderstanding
something.
Does that all make sense?
Thanks,
Johannes
test-load-forwarding.sil
Description: Binary data
test-load-forwarding.sil-opt
Description: Binary data
> >> >> Thanks, >> Johannes >> >> [1]: https://bugs.swift.org/browse/SR-5403
_______________________________________________ swift-dev mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-dev
