{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/1741","labels_url":"https://api.github.com/repos/dotnet/coreclr/issues/1741/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/coreclr/issues/1741/comments","events_url":"https://api.github.com/repos/dotnet/coreclr/issues/1741/events","html_url":"https://github.com/dotnet/coreclr/issues/1741","id":110852799,"number":1741,"title":"Optimize shifts better","user":{"login":"GSPP","id":12032350,"avatar_url":"https://avatars.githubusercontent.com/u/12032350?v=3","gravatar_id":"","url":"https://api.github.com/users/GSPP","html_url":"https://github.com/GSPP","followers_url":"https://api.github.com/users/GSPP/followers","following_url":"https://api.github.com/users/GSPP/following{/other_user}","gists_url":"https://api.github.com/users/GSPP/gists{/gist_id}","starred_url":"https://api.github.com/users/GSPP/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GSPP/subscriptions","organizations_url":"https://api.github.com/users/GSPP/orgs","repos_url":"https://api.github.com/users/GSPP/repos","events_url":"https://api.github.com/users/GSPP/events{/privacy}","received_events_url":"https://api.github.com/users/GSPP/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":8,"created_at":"2015-10-11T12:21:25Z","updated_at":"2015-10-12T08:57:32Z","closed_at":null,"body":"Let's look at the following code performing some shifts:\r\n\r\n        [MethodImpl(MethodImplOptions.NoInlining)]\r\n        static void Shift()\r\n        {\r\n            var x = Havoc(0x1234);\r\n            var y = Havoc(0x1235);\r\n\r\n            Sink(x << y);\r\n            Sink(x << (y & 0x1F));\r\n            Sink(x << (y & 0x1));\r\n        }\r\n        [MethodImpl(MethodImplOptions.NoInlining)]\r\n        static int Havoc(int x)\r\n        {\r\n            return x;\r\n        }\r\n        [MethodImpl(MethodImplOptions.NoInlining)]\r\n        static void Sink(int x)\r\n        {\r\n        }\r\n\r\nUnder VS15, x64, Release this compiles to:\r\n\r\n```\r\n            var x = Havoc(0x1234);\r\n00000000  push        rdi \r\n00000001  push        rsi \r\n00000002  push        rbx \r\n00000003  sub         rsp,20h \r\n00000007  mov         ecx,1234h \r\n0000000c  call        FFFFFFFFFFFFECD0 //havoc\r\n00000011  mov         esi,eax \r\n00000013  mov         ecx,1235h \r\n00000018  call        FFFFFFFFFFFFECD0 //havoc\r\n0000001d  mov         edi,eax \r\n0000001f  mov         ebx,edi //unnecessary register move\r\n00000021  and         ebx,1Fh\r\n00000024  mov         ecx,ebx \r\n00000026  mov         eax,esi  //unnecessary register move\r\n00000028  shl         eax,cl \r\n0000002a  mov         ecx,eax \r\n0000002c  call        FFFFFFFFFFFFEAD0 \r\n            Sink(x << (y & 0x1F));\r\n00000031  mov         ecx,ebx \r\n00000033  and         ecx,1Fh \r\n00000036  mov         eax,esi  //unnecessary register move\r\n00000038  shl         eax,cl \r\n0000003a  mov         ecx,eax  //unnecessary register move\r\n0000003c  call        FFFFFFFFFFFFEAD0 \r\n            Sink(x << (y & 0x1));\r\n00000041  mov         ecx,edi \r\n00000043  and         ecx,1 \r\n00000046  and         ecx,1Fh //should be combined with the and above\r\n00000049  mov         eax,esi  //unnecessary register move\r\n0000004b  shl         eax,cl \r\n0000004d  mov         ecx,eax  //unnecessary register move\r\n0000004f  call        FFFFFFFFFFFFEAD0 \r\n00000054  nop \r\n        }\r\n00000055  add         rsp,20h \r\n00000059  pop         rbx \r\n0000005a  pop         rsi \r\n0000005b  pop         rdi \r\n0000005c  ret \r\n```\r\n\r\nI have marked some code gen issues. I think it's worth looking into those. The unnecessary moves might be an issue that is present in other code patterns as well."},"comment":{"url":"https://api.github.com/repos/dotnet/coreclr/issues/comments/147334730","html_url":"https://github.com/dotnet/coreclr/issues/1741#issuecomment-147334730","issue_url":"https://api.github.com/repos/dotnet/coreclr/issues/1741","id":147334730,"user":{"login":"mikedn","id":9973420,"avatar_url":"https://avatars.githubusercontent.com/u/9973420?v=3","gravatar_id":"","url":"https://api.github.com/users/mikedn","html_url":"https://github.com/mikedn","followers_url":"https://api.github.com/users/mikedn/followers","following_url":"https://api.github.com/users/mikedn/following{/other_user}","gists_url":"https://api.github.com/users/mikedn/gists{/gist_id}","starred_url":"https://api.github.com/users/mikedn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mikedn/subscriptions","organizations_url":"https://api.github.com/users/mikedn/orgs","repos_url":"https://api.github.com/users/mikedn/repos","events_url":"https://api.github.com/users/mikedn/events{/privacy}","received_events_url":"https://api.github.com/users/mikedn/received_events","type":"User","site_admin":false},"created_at":"2015-10-12T08:57:32Z","updated_at":"2015-10-12T08:57:32Z","body":"> LLVM seems to twist the calling convention so that the shift result ends up in a convenient register \r\n\r\nNot really, that compiler targets Linux and Linux uses a different calling convention. Function arguments are passed in edi, esi, edx, ecx while Windows uses ecx, edx, r8, r9.\r\n\r\n"}}