<div dir="ltr"><div dir="ltr"><div dir="ltr"><div>Hi LLVM, clang,</div><div><br></div><div>I'm trying to write a portable version of __builtin_add_overflow() it a way that the compiler would <br></div><div>recognize the pattern and use the add_overflow intrinsic / the best possible machine instruction.</div><div><br></div><div>Here are docs about these builtins: <a href="https://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins">https://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins</a>.<br></div><div><br></div><div>With unsigned types this is easy:</div><div><br></div><div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> uaddo_native(</span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)"> a, </span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)"> b, </span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)">* s)</span></div><div><span style="color:rgb(0,0,0)">{</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">return</span><span style="color:rgb(0,0,0)"> __builtin_add_overflow(a, b, s);</span></div><div><span style="color:rgb(0,0,0)">}</span></div><br><div><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> uaddo_portable(</span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)"> a, </span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)"> b, </span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)">* s)</span></div><div><span style="color:rgb(0,0,0)">{</span></div><div><span style="color:rgb(0,0,0)">    *s = a + b;</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">return</span><span style="color:rgb(0,0,0)"> *s < a;</span></div><div><span style="color:rgb(0,0,0)">}</span></div><div><span style="color:rgb(0,0,0)"><br></span></div><div><span style="color:rgb(0,0,0)">We get exactly the same assembly:</span></div><div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div><span style="color:rgb(0,128,128)">uaddo_native:</span><span style="color:rgb(0,0,0)">                           </span><span style="color:rgb(0,128,0)"># @uaddo_native</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">xor</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">eax</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">add</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">edi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">esi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">setb</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">mov</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(0,128,128)">dword</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,128,128)">ptr</span><span style="color:rgb(0,0,0)"> [</span><span style="color:rgb(72,100,170)">rdx</span><span style="color:rgb(0,0,0)">], </span><span style="color:rgb(72,100,170)">edi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">ret</span></div><div><span style="color:rgb(0,128,128)">uaddo_portable:</span><span style="color:rgb(0,0,0)">                         </span><span style="color:rgb(0,128,0)"># @uaddo_portable</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">xor</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">eax</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">add</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">edi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">esi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">setb</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">mov</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(0,128,128)">dword</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,128,128)">ptr</span><span style="color:rgb(0,0,0)"> [</span><span style="color:rgb(72,100,170)">rdx</span><span style="color:rgb(0,0,0)">], </span><span style="color:rgb(72,100,170)">edi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">ret</span></div><div><span style="color:rgb(0,0,255)"><br></span></div>But with signed types it is not so easy. I tried 2 versions, but the result is quite far away from the optimal assembly.</div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br><div><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> saddo_native(</span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> a, </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> b, </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)">* s)</span></div><div><span style="color:rgb(0,0,0)">{</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">return</span><span style="color:rgb(0,0,0)"> __builtin_add_overflow(a, b, s);</span></div><div><span style="color:rgb(0,0,0)">}</span></div><br><div><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> saddo_portable(</span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> a, </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> b, </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)">* s)</span></div><div><span style="color:rgb(0,0,0)">{</span></div><div><span style="color:rgb(0,0,0)">    *s = (</span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)">)a + (</span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)">)b;</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">return</span><span style="color:rgb(0,0,0)"> (a > </span><span style="color:rgb(9,136,90)">0</span><span style="color:rgb(0,0,0)">) ? *s <= b : *s > b;</span></div><div><span style="color:rgb(0,0,0)">}</span></div><br><div><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> saddo_portable2(</span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> a, </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> b, </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)">* s)</span></div><div><span style="color:rgb(0,0,0)">{</span></div><div><span style="color:rgb(0,0,0)">    *s = (</span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)">)a + (</span><span style="color:rgb(0,0,255)">unsigned</span><span style="color:rgb(0,0,0)">)b;</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> cond = a > </span><span style="color:rgb(9,136,90)">0</span><span style="color:rgb(0,0,0)">;</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">int</span><span style="color:rgb(0,0,0)"> check = *s > b;</span></div><div><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(0,0,255)">return</span><span style="color:rgb(0,0,0)"> (cond & !check) | (!cond & check);</span></div><div><span style="color:rgb(0,0,0)">}</span></div></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)">Assembly:</div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div><span style="color:rgb(0,128,128)">saddo_native:</span><span style="color:rgb(0,0,0)">                           </span><span style="color:rgb(0,128,0)"># @saddo_native</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">xor</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">eax</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">add</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">edi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">esi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">seto</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">mov</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(0,128,128)">dword</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,128,128)">ptr</span><span style="color:rgb(0,0,0)"> [</span><span style="color:rgb(72,100,170)">rdx</span><span style="color:rgb(0,0,0)">], </span><span style="color:rgb(72,100,170)">edi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">ret</span></div><div><span style="color:rgb(0,128,128)">saddo_portable:</span><span style="color:rgb(0,0,0)">                         </span><span style="color:rgb(0,128,0)"># @saddo_portable</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">lea</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, [</span><span style="color:rgb(72,100,170)">rsi</span><span style="color:rgb(0,0,0)"> + </span><span style="color:rgb(72,100,170)">rdi</span><span style="color:rgb(0,0,0)">]</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">mov</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(0,128,128)">dword</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,128,128)">ptr</span><span style="color:rgb(0,0,0)"> [</span><span style="color:rgb(72,100,170)">rdx</span><span style="color:rgb(0,0,0)">], </span><span style="color:rgb(72,100,170)">eax</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">cmp</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">esi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">setle</span><span style="color:rgb(0,0,0)">   </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">setg</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">cl</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">test</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">edi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">edi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">jg</span><span style="color:rgb(0,0,0)">      </span><span style="color:rgb(0,128,128)">.LBB3_2</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">mov</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">ecx</span></div><div><span style="color:rgb(0,128,128)">.LBB3_2:</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">movzx</span><span style="color:rgb(0,0,0)">   </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">ret</span></div><div><span style="color:rgb(0,128,128)">saddo_portable2:</span><span style="color:rgb(0,0,0)">                        </span><span style="color:rgb(0,128,0)"># @saddo_portable2</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">lea</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, [</span><span style="color:rgb(72,100,170)">rsi</span><span style="color:rgb(0,0,0)"> + </span><span style="color:rgb(72,100,170)">rdi</span><span style="color:rgb(0,0,0)">]</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">mov</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(0,128,128)">dword</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,128,128)">ptr</span><span style="color:rgb(0,0,0)"> [</span><span style="color:rgb(72,100,170)">rdx</span><span style="color:rgb(0,0,0)">], </span><span style="color:rgb(72,100,170)">eax</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">test</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">edi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">edi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">setg</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">cl</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">cmp</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">esi</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">setg</span><span style="color:rgb(0,0,0)">    </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">xor</span><span style="color:rgb(0,0,0)">     </span><span style="color:rgb(72,100,170)">al</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">cl</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">movzx</span><span style="color:rgb(0,0,0)">   </span><span style="color:rgb(72,100,170)">eax</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(72,100,170)">al</span></div><div><span style="color:rgb(0,0,0)">        </span><span style="color:rgb(0,0,255)">ret</span></div><div><span style="color:rgb(0,0,255)"><br></span></div><div><span style="color:rgb(0,0,255)"><br></span></div><div>Do you know the trick to force the compiler to use the seto instruction?<br><br></div><div>I also noticed that the transformation for uaddo_portable happens in CodeGen, not in IR.</div><div><br></div><div>Bests,</div><div>PaweÅ‚<br></div></div></div></div><span style="color:rgb(0,0,0)"></span></div><div><span style="color:rgb(0,0,0)"><br></span></div></div></div><div><br></div></div></div></div>