Created
February 6, 2020 20:49
-
-
Save lambdageek/1d0b334fd736b4d3040604d5e645b5af to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// compiled with: | |
// csc /target:library /unsafe /O foo.cs | |
using System; | |
using System.Runtime.InteropServices; | |
public struct S { | |
public int a; | |
public int b; | |
} | |
public unsafe class P { | |
[DllImport ("Bar")] | |
static extern void Bar (int *x, int *y); | |
public static void Plop (S[] x, bool b) | |
{ | |
if (b) { | |
fixed (S* p = x) | |
{ | |
Bar (&p->a, &p->b); | |
} | |
Plop (x, !b); | |
} else | |
Plop (x, !b); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// method line 2 | |
.method public static hidebysig | |
default void Plop (valuetype S[] x, bool b) cil managed | |
{ | |
// Method begins at RVA 0x2050 | |
// Code size 70 (0x46) | |
.maxstack 3 | |
.locals init ( | |
valuetype S* V_0, | |
valuetype S[] pinned V_1) | |
IL_0000: ldarg.1 | |
IL_0001: brfalse.s IL_003b | |
IL_0003: ldarg.0 | |
IL_0004: dup | |
IL_0005: stloc.1 | |
IL_0006: brfalse.s IL_000d | |
IL_0008: ldloc.1 | |
IL_0009: ldlen | |
IL_000a: conv.i4 | |
IL_000b: brtrue.s IL_0012 | |
IL_000d: ldc.i4.0 | |
IL_000e: conv.u | |
IL_000f: stloc.0 | |
IL_0010: br.s IL_001b | |
IL_0012: ldloc.1 | |
IL_0013: ldc.i4.0 | |
IL_0014: ldelema S | |
IL_0019: conv.u | |
IL_001a: stloc.0 | |
IL_001b: ldloc.0 | |
IL_001c: ldflda int32 S::a | |
IL_0021: conv.u | |
IL_0022: ldloc.0 | |
IL_0023: ldflda int32 S::b | |
IL_0028: conv.u | |
IL_0029: call void class P::Bar(int32*, int32*) | |
IL_002e: ldnull | |
IL_002f: stloc.1 // <- zeroes out the fixed pointer | |
IL_0030: ldarg.0 | |
IL_0031: ldarg.1 | |
IL_0032: ldc.i4.0 | |
IL_0033: ceq | |
IL_0035: call void class P::Plop(valuetype S[], bool) | |
IL_003a: ret | |
IL_003b: ldarg.0 | |
IL_003c: ldarg.1 | |
IL_003d: ldc.i4.0 | |
IL_003e: ceq | |
IL_0040: call void class P::Plop(valuetype S[], bool) | |
IL_0045: ret | |
} // end of method P::Plop |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Var R16 live at enter, add range to R16: [1c0001, 200001) | |
Var R17 live at enter, add range to R17: [1c0001, 200001) | |
Var R19 live at enter, add range to R19: [1c0001, 200001) | |
LIVENESS BLOCK BB9: | |
180013: br [B1] | |
180012: il_seq_point il: 0x3a | |
180011: il_seq_point il: 0x3a, nonempty-stack | |
180010: voidcall [void P:Plop (S[],bool)] [%rdi <- R49] [%rsi <- R50] clobbers: c | |
18000f: move R50 <- R48 | |
18000e: move R49 <- R16 | |
last use of R16 set to 18000e | |
18000d: int_ceq R48 <- | |
18000c: icompare_imm R17 [0] | |
last use of R17 set to 18000c | |
18000b: il_seq_point il: 0x30 | |
18000a: i8const R19 <- [0] | |
dead def of R19, eliminated // store to fixed pointer eliminated! | |
180009: il_seq_point il: 0x2e | |
180008: il_seq_point il: 0x2e, nonempty-stack | |
180007: voidcall [void P:Bar (int*,int*)] [%rdi <- R42] [%rsi <- R43] clobbers: c | |
180006: move R43 <- R41 | |
180005: move R42 <- R18 | |
last use of R18 set to 180005 | |
180004: long_add_imm R41 <- R18 [4] clobbers: 1 | |
180003: il_seq_point il: 0x1b |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// I believe R19 is the fixed pointer | |
LIVENESS: | |
BLOCK BB0 (BB3, ): | |
1 aotconst R57 <- | |
1 gc_safe_point R57 clobbers: c | |
GEN BB0: {} | |
KILL BB0: {} | |
BLOCK BB3 (BB4, BB5, ): | |
1 i8const R18 <- [0] | |
KILL: R18(2) | |
1 i8const R19 <- [0] | |
KILL: R19(3) | |
1 il_seq_point il: 0x0 | |
1 icompare_imm R17 [0] | |
GEN: R17(1) | |
1 int_beq [B4B5] | |
GEN BB3: {1} | |
KILL BB3: {2, 3} | |
BLOCK BB4 (BB1, ): | |
1 il_seq_point il: 0x3b | |
1 icompare_imm R17 [0] | |
GEN: R17(1) | |
1 int_ceq R54 <- | |
1 move R55 <- R16 | |
GEN: R16(0) | |
1 move R56 <- R54 | |
1 voidcall [void P:Plop (S[],bool)] [%rdi <- R55] [%rsi <- R56] clobbers: c | |
1 il_seq_point il: 0x45, nonempty-stack | |
1 il_seq_point il: 0x45 | |
GEN BB4: {0, 1} | |
KILL BB4: {} | |
BLOCK BB1 (): | |
GEN BB1: {} | |
KILL BB1: {} | |
BLOCK BB5 (BB6, BB7, ): | |
1 il_seq_point il: 0x3 | |
1 move R19 <- R16 | |
GEN: R16(0) | |
KILL: R19(3) | |
1 lcompare_imm R16 | |
GEN: R16(0) | |
1 long_beq [B6B7] | |
GEN BB5: {0} | |
KILL BB5: {3} | |
BLOCK BB6 (BB9, ): | |
1 il_seq_point il: 0xd | |
1 iconst R28 <- [0] | |
1 zext_i4 R18 <- R28 | |
KILL: R18(2) | |
1 il_seq_point il: 0x10 | |
1 br [B9] | |
GEN BB6: {} | |
KILL BB6: {2} | |
BLOCK BB9 (BB1, ): | |
1 il_seq_point il: 0x1b | |
1 long_add_imm R41 <- R18 [4] clobbers: 1 | |
GEN: R18(2) | |
1 move R42 <- R18 | |
GEN: R18(2) | |
1 move R43 <- R41 | |
1 voidcall [void P:Bar (int*,int*)] [%rdi <- R42] [%rsi <- R43] clobbers: c | |
1 il_seq_point il: 0x2e, nonempty-stack | |
1 il_seq_point il: 0x2e | |
1 i8const R19 <- [0] | |
KILL: R19(3) | |
1 il_seq_point il: 0x30 | |
1 icompare_imm R17 [0] | |
GEN: R17(1) | |
1 int_ceq R48 <- | |
1 move R49 <- R16 | |
GEN: R16(0) | |
1 move R50 <- R48 | |
1 voidcall [void P:Plop (S[],bool)] [%rdi <- R49] [%rsi <- R50] clobbers: c | |
1 il_seq_point il: 0x3a, nonempty-stack | |
1 il_seq_point il: 0x3a | |
1 br [B1] | |
GEN BB9: {0, 1, 2} | |
KILL BB9: {3} | |
BLOCK BB7 (BB8, BB6, ): | |
1 il_seq_point il: 0x8 | |
1 not_null R19 | |
GEN: R19(3) | |
1 loadi4_membase R26 <- [R19 + 0x18] | |
GEN: R19(3) | |
1 not_null R19 | |
GEN: R19(3) | |
1 icompare_imm R26 [0] | |
1 int_bne_un [B8B6] | |
GEN BB7: {3} | |
KILL BB7: {} | |
BLOCK BB8 (BB9, ): | |
1 il_seq_point il: 0x12 | |
1 not_null R19 | |
GEN: R19(3) | |
1 amd64_icompare_membase_imm [R19 + 0x18] | |
GEN: R19(3) | |
1 cond_exc_le_un IndexOutOfRangeException | |
1 long_add_imm R18 <- R19 [32] clobbers: 1 | |
GEN: R19(3) | |
KILL: R18(2) | |
GEN BB8: {3} | |
KILL BB8: {2} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now that the store is eliminated, there's nothing left: | |
LOCAL REGALLOC BLOCK 9: | |
1 il_seq_point il: 0x1b | |
2 amd64_lea_membase R41 <- %r13 | |
3 move R42 <- %r13 | |
4 move R43 <- R41 | |
5 voidcall [void P:Bar (int*,int*)] [%rdi <- R42] [%rsi <- R43] clobbers: c | |
6 il_seq_point il: 0x2e, nonempty-stack | |
7 il_seq_point il: 0x2e | |
8 il_seq_point il: 0x30 | |
9 loadu1_membase R59 <- [%rsp + 0x10] | |
10 x86_test_null R59 | |
11 int_ceq R48 <- | |
12 move R49 <- %r14 | |
13 move R50 <- R48 | |
14 voidcall [void P:Plop (S[],bool)] [%rdi <- R49] [%rsi <- R50] clobbers: c | |
15 il_seq_point il: 0x3a, nonempty-stack | |
16 il_seq_point il: 0x3a | |
17 br [B1] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment