c# – 编译器何时优化我的代码
发布时间:2020-12-15 04:06:54 所属栏目:百科 来源:网络整理
导读:I’m trying to build a code sample显示编译器与2个数字相乘时的代码优化.然而当我转向IL上的优化代码仍然主要是相同的.任何想法我在这里做错什么? 代码: int nr;int result;var stopwatch = new Stopwatch();nr = 5;stopwatch.Start(); result = nr * 4;
I’m trying to build a code sample显示编译器与2个数字相乘时的代码优化.然而当我转向IL上的优化代码仍然主要是相同的.任何想法我在这里做错什么?
代码: int nr; int result; var stopwatch = new Stopwatch(); nr = 5; stopwatch.Start(); result = nr * 4; stopwatch.Stop(); Console.WriteLine(result); Console.WriteLine(stopwatch.Elapsed.ToString() + "ms ellapsed"); stopwatch.Reset(); stopwatch.Start(); result = nr << 2; stopwatch.Stop(); Console.WriteLine(result); Console.WriteLine(stopwatch.Elapsed.ToString() + "ms ellapsed"); 非优化IL: .method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 130 (0x82) .maxstack 2 .locals init ([0] int32 nr,[1] int32 result,[2] class [System]System.Diagnostics.Stopwatch stopwatch,[3] valuetype [mscorlib]System.TimeSpan CS$0$0000,[4] valuetype [mscorlib]System.TimeSpan CS$0$0001) IL_0000: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor() IL_0005: stloc.2 IL_0006: ldc.i4.5 IL_0007: stloc.0 IL_0008: ldloc.2 IL_0009: callvirt instance void [System]System.Diagnostics.Stopwatch::Start() IL_000e: ldloc.0 IL_000f: ldc.i4.4 IL_0010: mul IL_0011: stloc.1 IL_0012: ldloc.2 IL_0013: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop() IL_0018: ldloc.1 IL_0019: call void [mscorlib]System.Console::WriteLine(int32) IL_001e: ldloc.2 IL_001f: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed() IL_0024: stloc.3 IL_0025: ldloca.s CS$0$0000 IL_0027: constrained. [mscorlib]System.TimeSpan IL_002d: callvirt instance string [mscorlib]System.Object::ToString() IL_0032: ldstr "ms ellapsed" IL_0037: call string [mscorlib]System.String::Concat(string,string) IL_003c: call void [mscorlib]System.Console::WriteLine(string) IL_0041: ldloc.2 IL_0042: callvirt instance void [System]System.Diagnostics.Stopwatch::Reset() IL_0047: ldloc.2 IL_0048: callvirt instance void [System]System.Diagnostics.Stopwatch::Start() IL_004d: ldloc.0 IL_004e: ldc.i4.2 IL_004f: shl IL_0050: stloc.1 IL_0051: ldloc.2 IL_0052: callvirt instance void [System]System.Diagnostics.Stopwatch::Stop() IL_0057: ldloc.1 IL_0058: call void [mscorlib]System.Console::WriteLine(int32) IL_005d: ldloc.2 IL_005e: callvirt instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed() IL_0063: stloc.s CS$0$0001 IL_0065: ldloca.s CS$0$0001 IL_0067: constrained. [mscorlib]System.TimeSpan IL_006d: callvirt instance string [mscorlib]System.Object::ToString() IL_0072: ldstr "ms ellapsed" IL_0077: call string [mscorlib]System.String::Concat(string,string) IL_007c: call void [mscorlib]System.Console::WriteLine(string) IL_0081: ret } // end of method Program::Main 优化IL: .method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 130 (0x82) .maxstack 2 .locals init ([0] int32 nr,string) IL_007c: call void [mscorlib]System.Console::WriteLine(string) IL_0081: ret } // end of method Program::Main 我以为编译器会将mul语句优化为一个shl语句? 解决方法
这是由Release版本中的抖动生成的代码:
0000003e mov ecx,14h 当知道操作数值时,优化器太聪明,无法生成乘法代码.如果更换nr = 5;使用nr = int.Parse(“5”),使得抖动不能知道操作数值,然后生成此乘法的代码: 0000005c lea ebx,[rdi*4+00000000h] 这利用内置在cpu中的地址生成逻辑中的乘数,允许指令与另一个使用ALU的指令重叠.这使得乘法基本上是免费的.这是64位抖动的输出,32位抖动产生: 0000004d shl edi,2 这是你所希望的.我记录了this post中抖动执行的优化方式. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |