{"id":43,"date":"2016-10-04T10:57:27","date_gmt":"2016-10-04T10:57:27","guid":{"rendered":"http:\/\/vordhosbn.com\/?p=43"},"modified":"2016-11-23T15:38:59","modified_gmt":"2016-11-23T15:38:59","slug":"gcc-vs-clang-vs-icc-for-32-bit-register-manipulation","status":"publish","type":"post","link":"https:\/\/vordhosbn.com\/index.php\/blog\/cpp\/gcc-vs-clang-vs-icc-for-32-bit-register-manipulation\/","title":{"rendered":"GCC vs Clang vs ICC for 32-bit register manipulation"},"content":{"rendered":"<p>Today <a href=\"http:\/\/godbolt.org\/\">godbolt<\/a>\u00a0released a new compiler comparison feature and I decided to quickly try to compare C++ vs C style register manipulation and see what kind of optimizations will be applied across the different compilers.<!--more--><\/p>\n<h1>Source code<\/h1>\n<p>So I wrote a naive\u00a0C++ class that would represent a 32-bit register.<\/p>\n<p>Note that I am trying here to test compilers&#8217; optimization on class member manipulation, rather than making the case for embedded C++ (where bits in registers would be volatile, since the order of bit setting is significant most of the time).<\/p>\n<pre class=\"theme:mm-dark-blue height-set:true striped:false nums:false scroll:false trim-whitespace:false lang:c++ decode:true \" title=\"C++ Register class\">struct Register\r\n{\r\nunsigned int b0:1;\r\nunsigned int b1:1;\r\nunsigned int b2:1;\r\nunsigned int b3:1;\r\nunsigned int b4:1;\r\nunsigned int b5:1;\r\nunsigned int b6:1;\r\nunsigned int b7:1;\r\nunsigned int b8:1;\r\nunsigned int b9:1;\r\nunsigned int b10:1;\r\nunsigned int b11:1;\r\nunsigned int b12:1;\r\nunsigned int b13:1;\r\nunsigned int b14:1;\r\nunsigned int b15:1;\r\nunsigned int b16:1;\r\nunsigned int b17:1;\r\nunsigned int b18:1;\r\nunsigned int b19:1;\r\nunsigned int b20:1;\r\nunsigned int b21:1;\r\nunsigned int b22:1;\r\nunsigned int b23:1;\r\nunsigned int b24:1;\r\nunsigned int b25:1;\r\nunsigned int b26:1;\r\nunsigned int b27:1;\r\nunsigned int b28:1;\r\nunsigned int b29:1;\r\nunsigned int b30:1;\r\nunsigned int b31:1;\r\n\r\ninline void Set(unsigned char bitNumber, bool value)\r\n{\r\n    switch(bitNumber)\r\n    {\r\n        case 0: b0 = value; break;\r\n        case 1: b1 = value; break;\r\n        case 2: b2 = value; break;\r\n        case 3: b3 = value; break;\r\n        case 4: b4 = value; break;\r\n        case 5: b5 = value; break;\r\n        case 6: b6 = value; break;\r\n        case 7: b7 = value; break;\r\n        case 8: b8 = value; break;\r\n        case 9: b9 = value; break;\r\n        case 10: b10 = value; break;\r\n        case 11: b11 = value; break;\r\n        case 12: b12 = value; break;\r\n        case 13: b13 = value; break;\r\n        case 14: b14 = value; break;\r\n        case 15: b15 = value; break;\r\n        case 16: b16 = value; break;\r\n        case 17: b17 = value; break;\r\n        case 18: b18 = value; break;\r\n        case 19: b19 = value; break;\r\n        case 20: b20 = value; break;\r\n        case 21: b21 = value; break;\r\n        case 22: b22 = value; break;\r\n        case 23: b23 = value; break;\r\n        case 24: b24 = value; break;\r\n        case 25: b25 = value; break;\r\n        case 26: b26 = value; break;\r\n        case 27: b27 = value; break;\r\n        case 28: b28 = value; break;\r\n        case 29: b29 = value; break;\r\n        case 30: b30 = value; break;\r\n        case 31: b31 = value; break;\r\n    }\r\n}\r\n};<\/pre>\n<p>After that you can see I am using it to set the 0, 1, 3, 5, 13 and 30th bits of the register:<\/p>\n<pre title=\"C++ usage\" class=\"theme:mm-dark-blue font:droid-sans-mono font-size:13 height-set:true striped:false nums:false plain:false scroll:true lang:c++ decode:true\">void cppFunction(Register&amp; reg) \r\n{\r\n  reg.Set(0,true);\r\n  reg.Set(1,true);\r\n  reg.Set(3,true);\r\n  reg.Set(5,true);\r\n  reg.Set(13, true);\r\n  reg.Set(30, true);\r\n}<\/pre>\n<p>the corresponding C\u00a0implementation is:<\/p>\n<pre title=\"C usage\" class=\"theme:mm-dark-blue font:droid-sans-mono height-set:true width-set:false striped:false nums:false plain:false scroll:true lang:c++ decode:true\">void cFunction(int* reg)\r\n{\r\n  *reg |= (1 &lt;&lt; 0) | (1 &lt;&lt; 1) | (1 &lt;&lt; 3) | (1 &lt;&lt; 5) | (1 &lt;&lt; 13) | (1 &lt;&lt; 30);\r\n}<\/pre>\n<p>I am also calling the above functions from a third one to see if\u00a0the compilers will inline it:<\/p>\n<pre title=\"Caller function\" class=\"theme:mm-dark-blue font:droid-sans-mono height-set:true width-set:true striped:false nums:false plain:false scroll:true lang:c++ decode:true\">void Caller(Register&amp; reg1, int *reg2)\r\n{\r\n  cppFunction(reg1);\r\n  cFunction(reg2);\r\n}<\/pre>\n<h1>The compilers<\/h1>\n<p>I am comparing\u00a0three compilers:<\/p>\n<ul>\n<li>gcc 6.2<\/li>\n<li>clang 3.9.0<\/li>\n<li>icc 17<\/li>\n<\/ul>\n<p>All are using the following options:\u00a0<span style=\"font-family: terminal, monaco, monospace;\">-O3 -mtune=native -march=native<\/span><\/p>\n<p>I would expect that the compilers &#8220;see trough&#8221; the C++ code and optimize it completely with a simple instruction.<\/p>\n<p>Let&#8217;s see the assembly of GCC:<\/p>\n<pre class=\"striped:false nums:false scroll:true lang:asm decode:true\">cppFunction(Register&amp;):\r\n        or      BYTE PTR [rdi], 43\r\n        or      BYTE PTR [rdi+1], 32\r\n        or      BYTE PTR [rdi+3], 64\r\n        ret\r\ncFunction(int*):\r\n        or      DWORD PTR [rdi], 1073750059\r\n        ret\r\nCaller(Register&amp;, int*):\r\n        or      BYTE PTR [rdi], 43\r\n        or      BYTE PTR [rdi+1], 32\r\n        or      BYTE PTR [rdi+3], 64\r\n        or      DWORD PTR [rsi], 1073750059\r\n        ret\r\n<\/pre>\n<p>We see that the cFunction() was correctly optimized and the rdi register representing the register is set correctly with \u00a0one \u00a0&#8216;<strong>or<\/strong>&#8216; instruction.<\/p>\n<p>The cppFunction() on the other is less than ideal &#8211; it uses BYTE_PTR addressing\u00a0three times instead of one DWORD.<\/p>\n<p>The\u00a0above functions has been correctly inlined in the Caller() function, which does nothing but function calls.<\/p>\n<p>Now lets see Clang:<\/p>\n<pre class=\"width-set:false striped:false nums:false scroll:true lang:asm decode:true\">cppFunction(Register&amp;):              # @cppFunction(Register&amp;)\r\n        or      dword ptr [rdi], 1073750059\r\n        ret\r\n\r\ncFunction(int*):                         # @cFunction(int*)\r\n        or      dword ptr [rdi], 1073750059\r\n        ret\r\n\r\nCaller(Register&amp;, int*):                  # @Caller(Register&amp;, int*)\r\n        or      dword ptr [rdi], 1073750059\r\n        or      dword ptr [rsi], 1073750059\r\n        ret<\/pre>\n<p>Wow, we see correct optimization on all three points there&#8230; nothing could be done better.<\/p>\n<p>What about the Intel Compiler:<\/p>\n<pre class=\"nums:false scroll:true lang:asm decode:true \">cppFunction(Register&amp;):\r\n        push      rbp                                           #80.1\r\n        xor       esi, esi                                      #81.7\r\n        mov       edx, 1                                        #81.7\r\n        mov       rbp, rdi                                      #80.1\r\n        call      Register::Set(unsigned char, bool)                           #81.7\r\n        mov       esi, 1                                        #82.7\r\n        mov       rdi, rbp                                      #82.7\r\n        mov       edx, esi                                      #82.7\r\n        call      Register::Set(unsigned char, bool)                           #82.7\r\n        mov       rdi, rbp                                      #83.7\r\n        mov       esi, 3                                        #83.7\r\n        mov       edx, 1                                        #83.7\r\n        call      Register::Set(unsigned char, bool)                           #83.7\r\n        or        BYTE PTR [rbp], 32                            #48.15\r\n        or        BYTE PTR [1+rbp], 32                          #56.16\r\n        or        BYTE PTR [3+rbp], 64                          #73.16\r\n        pop       rbp                                           #87.1\r\n        ret                                                     #87.1\r\nRegister::Set(unsigned char, bool):\r\n        movzx     esi, sil                                      #40.3\r\n        cmp       esi, 31                                       #41.5\r\n        ja        ..B2.67       # Prob 50%                      #41.5\r\n        jmp       QWORD PTR [.2.10_2.switchtab.3+rsi*8]         #41.5\r\n..1.1_0.TAG.31.0.1:\r\n        movzx     eax, BYTE PTR [3+rdi]                         #74.16\r\n        shl       edx, 7                                        #74.16\r\n        and       eax, 127                                      #74.16\r\n        or        eax, edx                                      #74.16\r\n        mov       BYTE PTR [3+rdi], al                          #74.16\r\n        jmp       ..B2.67       # Prob 100%                     #74.16\r\n..1.1_0.TAG.30.0.1:\r\n        and       edx, 1                                        #73.16\r\n        movzx     eax, BYTE PTR [3+rdi]                         #73.16\r\n        shl       edx, 6                                        #73.16\r\n        and       eax, -65                                      #73.16\r\n        or        eax, edx                                      #73.16\r\n        mov       BYTE PTR [3+rdi], al                          #73.16\r\n        jmp       ..B2.67       # Prob 100%                     #73.16\r\n..1.1_0.TAG.29.0.1:\r\n        and       edx, 1                                        #72.16\r\n        movzx     eax, BYTE PTR [3+rdi]                         #72.16\r\n        shl       edx, 5                                        #72.16\r\n        and       eax, -33                                      #72.16\r\n        or        eax, edx                                      #72.16\r\n        mov       BYTE PTR [3+rdi], al                          #72.16\r\n        jmp       ..B2.67       # Prob 100%                     #72.16\r\n..1.1_0.TAG.28.0.1:\r\n        and       edx, 1                                        #71.16\r\n        movzx     eax, BYTE PTR [3+rdi]                         #71.16\r\n        shl       edx, 4                                        #71.16\r\n        and       eax, -17                                      #71.16\r\n        or        eax, edx                                      #71.16\r\n        mov       BYTE PTR [3+rdi], al                          #71.16\r\n        jmp       ..B2.67       # Prob 100%                     #71.16\r\n..1.1_0.TAG.27.0.1:\r\n..B2.12:                        # Preds ..B2.2\r\n        and       edx, 1                                        #70.16\r\n        movzx     eax, BYTE PTR [3+rdi]                         #70.16\r\n        shl       edx, 3                                        #70.16\r\n        and       eax, -9                                       #70.16\r\n        or        eax, edx                                      #70.16\r\n        mov       BYTE PTR [3+rdi], al                          #70.16\r\n        jmp       ..B2.67       # Prob 100%                     #70.16\r\n..1.1_0.TAG.26.0.1:\r\n..B2.14:                        # Preds ..B2.2\r\n        and       edx, 1                                        #69.16\r\n        movzx     eax, BYTE PTR [3+rdi]                         #69.16\r\n        shl       edx, 2                                        #69.16\r\n        and       eax, -5                                       #69.16\r\n        or        eax, edx                                      #69.16\r\n        mov       BYTE PTR [3+rdi], al                          #69.16\r\n        jmp       ..B2.67       # Prob 100%                     #69.16\r\n..1.1_0.TAG.25.0.1:\r\n..B2.16:                        # Preds ..B2.2\r\n        and       edx, 1                                        #68.16\r\n        movzx     eax, BYTE PTR [3+rdi]                         #68.16\r\n        add       edx, edx                                      #68.16\r\n        and       eax, -3                                       #68.16\r\n        or        eax, edx                                      #68.16\r\n        mov       BYTE PTR [3+rdi], al                          #68.16\r\n        jmp       ..B2.67       # Prob 100%                     #68.16\r\n..1.1_0.TAG.24.0.1:\r\n..B2.18:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [3+rdi]                         #67.16\r\n        and       edx, 1                                        #67.16\r\n        and       eax, -2                                       #67.16\r\n        or        eax, edx                                      #67.16\r\n        mov       BYTE PTR [3+rdi], al                          #67.16\r\n        jmp       ..B2.67       # Prob 100%                     #67.16\r\n..1.1_0.TAG.23.0.1:\r\n..B2.20:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [2+rdi]                         #66.16\r\n        shl       edx, 7                                        #66.16\r\n        and       eax, 127                                      #66.16\r\n        or        eax, edx                                      #66.16\r\n        mov       BYTE PTR [2+rdi], al                          #66.16\r\n        jmp       ..B2.67       # Prob 100%                     #66.16\r\n..1.1_0.TAG.22.0.1:\r\n..B2.22:                        # Preds ..B2.2\r\n        and       edx, 1                                        #65.16\r\n        movzx     eax, BYTE PTR [2+rdi]                         #65.16\r\n        shl       edx, 6                                        #65.16\r\n        and       eax, -65                                      #65.16\r\n        or        eax, edx                                      #65.16\r\n        mov       BYTE PTR [2+rdi], al                          #65.16\r\n        jmp       ..B2.67       # Prob 100%                     #65.16\r\n..1.1_0.TAG.21.0.1:\r\n..B2.24:                        # Preds ..B2.2\r\n        and       edx, 1                                        #64.16\r\n        movzx     eax, BYTE PTR [2+rdi]                         #64.16\r\n        shl       edx, 5                                        #64.16\r\n        and       eax, -33                                      #64.16\r\n        or        eax, edx                                      #64.16\r\n        mov       BYTE PTR [2+rdi], al                          #64.16\r\n        jmp       ..B2.67       # Prob 100%                     #64.16\r\n..1.1_0.TAG.20.0.1:\r\n..B2.26:                        # Preds ..B2.2\r\n        and       edx, 1                                        #63.16\r\n        movzx     eax, BYTE PTR [2+rdi]                         #63.16\r\n        shl       edx, 4                                        #63.16\r\n        and       eax, -17                                      #63.16\r\n        or        eax, edx                                      #63.16\r\n        mov       BYTE PTR [2+rdi], al                          #63.16\r\n        jmp       ..B2.67       # Prob 100%                     #63.16\r\n..1.1_0.TAG.19.0.1:\r\n..B2.28:                        # Preds ..B2.2\r\n        and       edx, 1                                        #62.16\r\n        movzx     eax, BYTE PTR [2+rdi]                         #62.16\r\n        shl       edx, 3                                        #62.16\r\n        and       eax, -9                                       #62.16\r\n        or        eax, edx                                      #62.16\r\n        mov       BYTE PTR [2+rdi], al                          #62.16\r\n        jmp       ..B2.67       # Prob 100%                     #62.16\r\n..1.1_0.TAG.18.0.1:\r\n..B2.30:                        # Preds ..B2.2\r\n        and       edx, 1                                        #61.16\r\n        movzx     eax, BYTE PTR [2+rdi]                         #61.16\r\n        shl       edx, 2                                        #61.16\r\n        and       eax, -5                                       #61.16\r\n        or        eax, edx                                      #61.16\r\n        mov       BYTE PTR [2+rdi], al                          #61.16\r\n        jmp       ..B2.67       # Prob 100%                     #61.16\r\n..1.1_0.TAG.17.0.1:\r\n..B2.32:                        # Preds ..B2.2\r\n        and       edx, 1                                        #60.16\r\n        movzx     eax, BYTE PTR [2+rdi]                         #60.16\r\n        add       edx, edx                                      #60.16\r\n        and       eax, -3                                       #60.16\r\n        or        eax, edx                                      #60.16\r\n        mov       BYTE PTR [2+rdi], al                          #60.16\r\n        jmp       ..B2.67       # Prob 100%                     #60.16\r\n..1.1_0.TAG.16.0.1:\r\n..B2.34:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [2+rdi]                         #59.16\r\n        and       edx, 1                                        #59.16\r\n        and       eax, -2                                       #59.16\r\n        or        eax, edx                                      #59.16\r\n        mov       BYTE PTR [2+rdi], al                          #59.16\r\n        jmp       ..B2.67       # Prob 100%                     #59.16\r\n..1.1_0.TAG.15.0.1:\r\n..B2.36:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [1+rdi]                         #58.16\r\n        shl       edx, 7                                        #58.16\r\n        and       eax, 127                                      #58.16\r\n        or        eax, edx                                      #58.16\r\n        mov       BYTE PTR [1+rdi], al                          #58.16\r\n        jmp       ..B2.67       # Prob 100%                     #58.16\r\n..1.1_0.TAG.14.0.1:\r\n..B2.38:                        # Preds ..B2.2\r\n        and       edx, 1                                        #57.16\r\n        movzx     eax, BYTE PTR [1+rdi]                         #57.16\r\n        shl       edx, 6                                        #57.16\r\n        and       eax, -65                                      #57.16\r\n        or        eax, edx                                      #57.16\r\n        mov       BYTE PTR [1+rdi], al                          #57.16\r\n        jmp       ..B2.67       # Prob 100%                     #57.16\r\n..1.1_0.TAG.13.0.1:\r\n..B2.40:                        # Preds ..B2.2\r\n        and       edx, 1                                        #56.16\r\n        movzx     eax, BYTE PTR [1+rdi]                         #56.16\r\n        shl       edx, 5                                        #56.16\r\n        and       eax, -33                                      #56.16\r\n        or        eax, edx                                      #56.16\r\n        mov       BYTE PTR [1+rdi], al                          #56.16\r\n        jmp       ..B2.67       # Prob 100%                     #56.16\r\n..1.1_0.TAG.12.0.1:\r\n..B2.42:                        # Preds ..B2.2\r\n        and       edx, 1                                        #55.16\r\n        movzx     eax, BYTE PTR [1+rdi]                         #55.16\r\n        shl       edx, 4                                        #55.16\r\n        and       eax, -17                                      #55.16\r\n        or        eax, edx                                      #55.16\r\n        mov       BYTE PTR [1+rdi], al                          #55.16\r\n        jmp       ..B2.67       # Prob 100%                     #55.16\r\n..1.1_0.TAG.11.0.1:\r\n..B2.44:                        # Preds ..B2.2\r\n        and       edx, 1                                        #54.16\r\n        movzx     eax, BYTE PTR [1+rdi]                         #54.16\r\n        shl       edx, 3                                        #54.16\r\n        and       eax, -9                                       #54.16\r\n        or        eax, edx                                      #54.16\r\n        mov       BYTE PTR [1+rdi], al                          #54.16\r\n        jmp       ..B2.67       # Prob 100%                     #54.16\r\n..1.1_0.TAG.10.0.1:\r\n..B2.46:                        # Preds ..B2.2\r\n        and       edx, 1                                        #53.16\r\n        movzx     eax, BYTE PTR [1+rdi]                         #53.16\r\n        shl       edx, 2                                        #53.16\r\n        and       eax, -5                                       #53.16\r\n        or        eax, edx                                      #53.16\r\n        mov       BYTE PTR [1+rdi], al                          #53.16\r\n        jmp       ..B2.67       # Prob 100%                     #53.16\r\n..1.1_0.TAG.9.0.1:\r\n..B2.48:                        # Preds ..B2.2\r\n        and       edx, 1                                        #52.15\r\n        movzx     eax, BYTE PTR [1+rdi]                         #52.15\r\n        add       edx, edx                                      #52.15\r\n        and       eax, -3                                       #52.15\r\n        or        eax, edx                                      #52.15\r\n        mov       BYTE PTR [1+rdi], al                          #52.15\r\n        jmp       ..B2.67       # Prob 100%                     #52.15\r\n..1.1_0.TAG.8.0.1:\r\n..B2.50:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [1+rdi]                         #51.15\r\n        and       edx, 1                                        #51.15\r\n        and       eax, -2                                       #51.15\r\n        or        eax, edx                                      #51.15\r\n        mov       BYTE PTR [1+rdi], al                          #51.15\r\n        jmp       ..B2.67       # Prob 100%                     #51.15\r\n..1.1_0.TAG.7.0.1:\r\n..B2.52:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [rdi]                           #50.15\r\n        shl       edx, 7                                        #50.15\r\n        and       eax, 127                                      #50.15\r\n        or        eax, edx                                      #50.15\r\n        mov       BYTE PTR [rdi], al                            #50.15\r\n        jmp       ..B2.67       # Prob 100%                     #50.15\r\n..1.1_0.TAG.6.0.1:\r\n..B2.54:                        # Preds ..B2.2\r\n        and       edx, 1                                        #49.15\r\n        movzx     eax, BYTE PTR [rdi]                           #49.15\r\n        shl       edx, 6                                        #49.15\r\n        and       eax, -65                                      #49.15\r\n        or        eax, edx                                      #49.15\r\n        mov       BYTE PTR [rdi], al                            #49.15\r\n        jmp       ..B2.67       # Prob 100%                     #49.15\r\n..1.1_0.TAG.5.0.1:\r\n..B2.56:                        # Preds ..B2.2\r\n        and       edx, 1                                        #48.15\r\n        movzx     eax, BYTE PTR [rdi]                           #48.15\r\n        shl       edx, 5                                        #48.15\r\n        and       eax, -33                                      #48.15\r\n        or        eax, edx                                      #48.15\r\n        mov       BYTE PTR [rdi], al                            #48.15\r\n        jmp       ..B2.67       # Prob 100%                     #48.15\r\n..1.1_0.TAG.4.0.1:\r\n..B2.58:                        # Preds ..B2.2\r\n        and       edx, 1                                        #47.15\r\n        movzx     eax, BYTE PTR [rdi]                           #47.15\r\n        shl       edx, 4                                        #47.15\r\n        and       eax, -17                                      #47.15\r\n        or        eax, edx                                      #47.15\r\n        mov       BYTE PTR [rdi], al                            #47.15\r\n        jmp       ..B2.67       # Prob 100%                     #47.15\r\n..1.1_0.TAG.3.0.1:\r\n..B2.60:                        # Preds ..B2.2\r\n        and       edx, 1                                        #46.15\r\n        movzx     eax, BYTE PTR [rdi]                           #46.15\r\n        shl       edx, 3                                        #46.15\r\n        and       eax, -9                                       #46.15\r\n        or        eax, edx                                      #46.15\r\n        mov       BYTE PTR [rdi], al                            #46.15\r\n        jmp       ..B2.67       # Prob 100%                     #46.15\r\n..1.1_0.TAG.2.0.1:\r\n..B2.62:                        # Preds ..B2.2\r\n        and       edx, 1                                        #45.15\r\n        movzx     eax, BYTE PTR [rdi]                           #45.15\r\n        shl       edx, 2                                        #45.15\r\n        and       eax, -5                                       #45.15\r\n        or        eax, edx                                      #45.15\r\n        mov       BYTE PTR [rdi], al                            #45.15\r\n        jmp       ..B2.67       # Prob 100%                     #45.15\r\n..1.1_0.TAG.1.0.1:\r\n..B2.64:                        # Preds ..B2.2\r\n        and       edx, 1                                        #44.15\r\n        movzx     eax, BYTE PTR [rdi]                           #44.15\r\n        add       edx, edx                                      #44.15\r\n        and       eax, -3                                       #44.15\r\n        or        eax, edx                                      #44.15\r\n        mov       BYTE PTR [rdi], al                            #44.15\r\n        jmp       ..B2.67       # Prob 100%                     #44.15\r\n..1.1_0.TAG.0.0.1:\r\n..B2.66:                        # Preds ..B2.2\r\n        movzx     eax, BYTE PTR [rdi]                           #43.15\r\n        and       edx, 1                                        #43.15\r\n        and       eax, -2                                       #43.15\r\n        or        eax, edx                                      #43.15\r\n        mov       BYTE PTR [rdi], al                            #43.15\r\n..B2.67:                        # Preds ..B2.1 ..B2.4 ..B2.6 ..B2.8 ..B2.10\r\n        ret                                                     #76.3\r\n.2.10_2.switchtab.3:\r\n        .quad   ..1.1_0.TAG.0.0.1\r\n        .quad   ..1.1_0.TAG.1.0.1\r\n        .quad   ..1.1_0.TAG.2.0.1\r\n        .quad   ..1.1_0.TAG.3.0.1\r\n        .quad   ..1.1_0.TAG.4.0.1\r\n        .quad   ..1.1_0.TAG.5.0.1\r\n        .quad   ..1.1_0.TAG.6.0.1\r\n        .quad   ..1.1_0.TAG.7.0.1\r\n        .quad   ..1.1_0.TAG.8.0.1\r\n        .quad   ..1.1_0.TAG.9.0.1\r\n        .quad   ..1.1_0.TAG.10.0.1\r\n        .quad   ..1.1_0.TAG.11.0.1\r\n        .quad   ..1.1_0.TAG.12.0.1\r\n        .quad   ..1.1_0.TAG.13.0.1\r\n        .quad   ..1.1_0.TAG.14.0.1\r\n        .quad   ..1.1_0.TAG.15.0.1\r\n        .quad   ..1.1_0.TAG.16.0.1\r\n        .quad   ..1.1_0.TAG.17.0.1\r\n        .quad   ..1.1_0.TAG.18.0.1\r\n        .quad   ..1.1_0.TAG.19.0.1\r\n        .quad   ..1.1_0.TAG.20.0.1\r\n        .quad   ..1.1_0.TAG.21.0.1\r\n        .quad   ..1.1_0.TAG.22.0.1\r\n        .quad   ..1.1_0.TAG.23.0.1\r\n        .quad   ..1.1_0.TAG.24.0.1\r\n        .quad   ..1.1_0.TAG.25.0.1\r\n        .quad   ..1.1_0.TAG.26.0.1\r\n        .quad   ..1.1_0.TAG.27.0.1\r\n        .quad   ..1.1_0.TAG.28.0.1\r\n        .quad   ..1.1_0.TAG.29.0.1\r\n        .quad   ..1.1_0.TAG.30.0.1\r\n        .quad   ..1.1_0.TAG.31.0.1\r\ncFunction(int*):\r\n        or        DWORD PTR [rdi], 1073750059                   #92.4\r\n        ret                                                     #93.1\r\nCaller(Register&amp;, int*):\r\n        push      r13                                           #97.1\r\n        push      r14                                           #97.1\r\n        push      rsi                                           #97.1\r\n        mov       r14, rsi                                      #97.1\r\n        xor       esi, esi                                      #81.7\r\n        mov       edx, 1                                        #81.7\r\n        mov       r13, rdi                                      #97.1\r\n        call      Register::Set(unsigned char, bool)                           #81.7\r\n        mov       esi, 1                                        #82.7\r\n        mov       rdi, r13                                      #82.7\r\n        mov       edx, esi                                      #82.7\r\n        call      Register::Set(unsigned char, bool)                           #82.7\r\n        mov       rdi, r13                                      #83.7\r\n        mov       esi, 3                                        #83.7\r\n        mov       edx, 1                                        #83.7\r\n        call      Register::Set(unsigned char, bool)                           #83.7\r\n        or        BYTE PTR [r13], 32                            #48.15\r\n        or        BYTE PTR [1+r13], 32                          #56.16\r\n        or        BYTE PTR [3+r13], 64                          #73.16\r\n        or        DWORD PTR [r14], 1073750059                   #92.4\r\n        pop       rcx                                           #100.1\r\n        pop       r14                                           #100.1\r\n        pop       r13                                           #100.1\r\n        ret                                                     #100.1\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-52\" src=\"http:\/\/vordhosbn.com\/wp-content\/uploads\/2016\/10\/tom-delonge-wtf1.gif\" alt=\"tom-delonge-wtf1\" width=\"370\" height=\"335\" \/><\/p>\n<h1>The conclusion<\/h1>\n<p>So it seems that GCC does a good job on the C code, but not so much on the C++ one.<\/p>\n<p>Clang makes the perfect optimization both in C and C++<\/p>\n<p>And Intel&#8230; well that&#8217;s just embarrassing.<\/p>\n<p>You can play with the godbolt comparison <a href=\"https:\/\/godbolt.org\/g\/MGvQcX\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today godbolt\u00a0released a new compiler comparison feature and I decided to quickly try to compare C++ vs C style register manipulation and see what kind of optimizations will be applied across the different compilers.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[3],"tags":[9,10,12,14,11,7,13,8],"class_list":["post-43","post","type-post","status-publish","format-standard","hentry","category-cpp","tag-assembly","tag-c","tag-clang","tag-compiler","tag-gcc","tag-goldbolt","tag-icc","tag-x86"],"_links":{"self":[{"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/posts\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/comments?post=43"}],"version-history":[{"count":25,"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":170,"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/posts\/43\/revisions\/170"}],"wp:attachment":[{"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/media?parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/categories?post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vordhosbn.com\/index.php\/wp-json\/wp\/v2\/tags?post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}