Understanding Compiler Optimizations












3















I'm trying to understand what the compiler is doing to very simple piece of code:



if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}


After compiling in Debug configuration, then decompiling I see this:



if (group.ImageHeight <= 1 || group.ImageWidth <= 1);


Decompiling a Release configuration results in



if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}


More complete (original) code:



public class Group 
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}

//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}


Here are my guesses and observations so far:




  • When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.

  • I believe that it's important that group type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition for group.

  • In the Release config the possible side effects appear to be the same as my code: ImageHeight is evaluated and if meets the > 1 condition will evaluate ImageWidth (although through assignment rather than comparison)


Now, for my specific questions:




  • Why does the Release config use an assignment (int imageWidth = group.ImageWidth) rather than my original comparison? Is it faster to run an assignment?

  • Why does the Debug configuration completely change the possibility of side effects? In this configuration both ImageHeight and ImageWidth will always be evaluated.










share|improve this question

























  • Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.

    – Sql Surfer
    Jan 18 at 18:00








  • 1





    Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.

    – Damien_The_Unbeliever
    Jan 18 at 18:39











  • @Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)

    – MikeH
    Jan 18 at 18:43











  • Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines

    – Damien_The_Unbeliever
    Jan 18 at 19:16
















3















I'm trying to understand what the compiler is doing to very simple piece of code:



if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}


After compiling in Debug configuration, then decompiling I see this:



if (group.ImageHeight <= 1 || group.ImageWidth <= 1);


Decompiling a Release configuration results in



if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}


More complete (original) code:



public class Group 
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}

//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}


Here are my guesses and observations so far:




  • When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.

  • I believe that it's important that group type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition for group.

  • In the Release config the possible side effects appear to be the same as my code: ImageHeight is evaluated and if meets the > 1 condition will evaluate ImageWidth (although through assignment rather than comparison)


Now, for my specific questions:




  • Why does the Release config use an assignment (int imageWidth = group.ImageWidth) rather than my original comparison? Is it faster to run an assignment?

  • Why does the Debug configuration completely change the possibility of side effects? In this configuration both ImageHeight and ImageWidth will always be evaluated.










share|improve this question

























  • Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.

    – Sql Surfer
    Jan 18 at 18:00








  • 1





    Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.

    – Damien_The_Unbeliever
    Jan 18 at 18:39











  • @Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)

    – MikeH
    Jan 18 at 18:43











  • Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines

    – Damien_The_Unbeliever
    Jan 18 at 19:16














3












3








3








I'm trying to understand what the compiler is doing to very simple piece of code:



if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}


After compiling in Debug configuration, then decompiling I see this:



if (group.ImageHeight <= 1 || group.ImageWidth <= 1);


Decompiling a Release configuration results in



if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}


More complete (original) code:



public class Group 
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}

//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}


Here are my guesses and observations so far:




  • When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.

  • I believe that it's important that group type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition for group.

  • In the Release config the possible side effects appear to be the same as my code: ImageHeight is evaluated and if meets the > 1 condition will evaluate ImageWidth (although through assignment rather than comparison)


Now, for my specific questions:




  • Why does the Release config use an assignment (int imageWidth = group.ImageWidth) rather than my original comparison? Is it faster to run an assignment?

  • Why does the Debug configuration completely change the possibility of side effects? In this configuration both ImageHeight and ImageWidth will always be evaluated.










share|improve this question
















I'm trying to understand what the compiler is doing to very simple piece of code:



if (group.ImageHeight > 1 && group.ImageWidth > 1)
{ //No code exists between the braces
}


After compiling in Debug configuration, then decompiling I see this:



if (group.ImageHeight <= 1 || group.ImageWidth <= 1);


Decompiling a Release configuration results in



if (group.ImageHeight > 1)
{
int imageWidth = group.ImageWidth;
}


More complete (original) code:



public class Group 
{
public int ImageHeight { get; set; }
public int ImageWidth { get; set; }
}

//The following belongs to a different project than `Group`
static void Main(string args)
{
Group group = new Group();
MyMethod(group);
}
static void MyMethod(Group group)
{
if (group.ImageHeight > 1 && group.ImageWidth > 1)
{
}
}


Here are my guesses and observations so far:




  • When I first started this I expected the compiler to completely drop the entire statement. I think that it's not because the evaluation of the properties could have side effects.

  • I believe that it's important that group type belongs to another project in my solution. I say this because the compiler probably can't "know" what the side effects of evaluating the properties could be in the future. For instance, I could, after compiling, replace the DLL that contains the definition for group.

  • In the Release config the possible side effects appear to be the same as my code: ImageHeight is evaluated and if meets the > 1 condition will evaluate ImageWidth (although through assignment rather than comparison)


Now, for my specific questions:




  • Why does the Release config use an assignment (int imageWidth = group.ImageWidth) rather than my original comparison? Is it faster to run an assignment?

  • Why does the Debug configuration completely change the possibility of side effects? In this configuration both ImageHeight and ImageWidth will always be evaluated.







c# .net compiler-construction compiler-optimization






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 18 at 18:30









Amy

21.7k1874131




21.7k1874131










asked Jan 18 at 17:28









MikeHMikeH

3,268927




3,268927













  • Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.

    – Sql Surfer
    Jan 18 at 18:00








  • 1





    Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.

    – Damien_The_Unbeliever
    Jan 18 at 18:39











  • @Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)

    – MikeH
    Jan 18 at 18:43











  • Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines

    – Damien_The_Unbeliever
    Jan 18 at 19:16



















  • Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.

    – Sql Surfer
    Jan 18 at 18:00








  • 1





    Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.

    – Damien_The_Unbeliever
    Jan 18 at 18:39











  • @Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)

    – MikeH
    Jan 18 at 18:43











  • Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines

    – Damien_The_Unbeliever
    Jan 18 at 19:16

















Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.

– Sql Surfer
Jan 18 at 18:00







Since group is declared in Main() and is logically on the heap and since MyMethod is static and is passed in the "global" Main variable group... Your are giving the optimizer a free pass to make some big assumptions. If the variables and code blocks went in and out of scope you might see results closer to what you would expect. Also you have no code in your int property accessors, another free pass. That's my 2 bits.

– Sql Surfer
Jan 18 at 18:00






1




1





Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.

– Damien_The_Unbeliever
Jan 18 at 18:39





Bear in mind that the C# compiler itself doesn't tend to do lots of "strong" optimizations. A lot of the stronger optimizations are left to the JIT compiler instead. Also, you have to consider that whatever decompiler you're using has as much influence over what you see "after" as the C# compiler. If you want to know what the C# compiler is doing, you ought to be looking at the IL level, not at what some other tools re-interprets the IL as.

– Damien_The_Unbeliever
Jan 18 at 18:39













@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)

– MikeH
Jan 18 at 18:43





@Damien_The_Unbeliever Thanks, that makes sense and something I'll keep in mind. IL level is a bit above my head...maybe I should learn one of these days :)

– MikeH
Jan 18 at 18:43













Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines

– Damien_The_Unbeliever
Jan 18 at 19:16





Yeah, IL is one of those things that is remarkably "simple" or remarkably "complex". It depends to a good extent on whether you "get" Stack Machines

– Damien_The_Unbeliever
Jan 18 at 19:16












1 Answer
1






active

oldest

votes


















3














For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.



if (group.ImageHeight > 1)



IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012


int imageWidth = group.ImageWidth;



IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop

IL_0012: ret


For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.



IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015

IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016

IL_0015: ldc.i4.0

IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c

IL_001a: nop
IL_001b: nop

IL_001c: ret





share|improve this answer
























  • "so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

    – MikeH
    Jan 18 at 18:45











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54258811%2funderstanding-compiler-optimizations%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.



if (group.ImageHeight > 1)



IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012


int imageWidth = group.ImageWidth;



IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop

IL_0012: ret


For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.



IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015

IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016

IL_0015: ldc.i4.0

IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c

IL_001a: nop
IL_001b: nop

IL_001c: ret





share|improve this answer
























  • "so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

    – MikeH
    Jan 18 at 18:45
















3














For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.



if (group.ImageHeight > 1)



IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012


int imageWidth = group.ImageWidth;



IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop

IL_0012: ret


For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.



IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015

IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016

IL_0015: ldc.i4.0

IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c

IL_001a: nop
IL_001b: nop

IL_001c: ret





share|improve this answer
























  • "so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

    – MikeH
    Jan 18 at 18:45














3












3








3







For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.



if (group.ImageHeight > 1)



IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012


int imageWidth = group.ImageWidth;



IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop

IL_0012: ret


For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.



IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015

IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016

IL_0015: ldc.i4.0

IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c

IL_001a: nop
IL_001b: nop

IL_001c: ret





share|improve this answer













For the first specific question. When you look at IL on sharplab.io
The simple assignment is 1 compare instruction short. Whose "then" and "else" would point to the same instruction (in this case IL_0012) so compare there is not needed for calling function and two pops are enough. Weird is only loading the Int32 constant 1 which will be discarded immidiately.



if (group.ImageHeight > 1)



IL_0000: ldarg.0
IL_0001: callvirt instance int32 Group::get_ImageHeight()
IL_0006: ldc.i4.1
IL_0007: ble.s IL_0012


int imageWidth = group.ImageWidth;



IL_0009: ldarg.0
IL_000a: callvirt instance int32 Group::get_ImageWidth()
IL_000f: ldc.i4.1
IL_0010: pop
IL_0011: pop

IL_0012: ret


For second specific question. If you look at IL on the same page with Debug mode, you'll see, that the code is identical only with some additional instructions for debuging and the compare itself so you can watch the result of it in debuger.



IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance int32 Group::get_ImageHeight()
IL_0007: ldc.i4.1
IL_0008: ble.s IL_0015

IL_000a: ldarg.0
IL_000b: callvirt instance int32 Group::get_ImageWidth()
IL_0010: ldc.i4.1
IL_0011: cgt
IL_0013: br.s IL_0016

IL_0015: ldc.i4.0

IL_0016: stloc.0
// sequence point: hidden
IL_0017: ldloc.0
IL_0018: brfalse.s IL_001c

IL_001a: nop
IL_001b: nop

IL_001c: ret






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 18 at 18:27









Ondřej KubíčekOndřej Kubíček

1013




1013













  • "so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

    – MikeH
    Jan 18 at 18:45



















  • "so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

    – MikeH
    Jan 18 at 18:45

















"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

– MikeH
Jan 18 at 18:45





"so you can watch the result of it in debuger". That line right there is very helpful. I was struggling to see why the result would be different between debug/release.

– MikeH
Jan 18 at 18:45


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54258811%2funderstanding-compiler-optimizations%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Liquibase includeAll doesn't find base path

How to use setInterval in EJS file?

Petrus Granier-Deferre