<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">For whatever it may be worth, __builtin_assume() helps generate the right code, so it seems like this optimization is within reach:<div class=""><br class=""></div><div class="">char arr[2];</div><div class="">char *get(unsigned ind) {<br class="">  if (ind >= 1) {</div><div class="">    return 0;</div><div class="">  }</div><div class="">  __builtin_assume(ind < 1);</div><div class="">  return &(arr[ind]);</div><div class="">}</div><div class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Feb 28, 2018, at 18:33, Alexey Zhikhartsev via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" class="">llvm-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="auto" class=""><div style="font-family:sans-serif;font-size:12.8px" dir="auto" class=""><div style="height:91px" class=""><span style="color:rgb(31,73,125)" class="">Hi everybody, I see a missed optimization opportunity in LLVM that GCC catches and I'd love to hear community's input.</span></div><div style="height:91px" dir="auto" class=""><span style="color:rgb(31,73,125)" class="">Here's the original C code:</span></div><div style="margin:16px 0px" class=""><p class=""><span style="color:rgb(31,73,125)" class="">1 char arr[2];<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">2 char *get(unsigned ind) {<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">3   if (ind >= 1) {<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">4    return 0;<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">5   }<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">6   return &(arr[ind]);<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">7 }<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">The variable `ind` is unsigned so, based on the comparison, if it is not greater or equals to one, than it is must be equal to zero. GCC understands that `ind` equals to zero at line 6 and generates something like the following (in pseudocode, the x86 assembly is in the footnotes):<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">ret = 0<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">if ind == 0:<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">    ret = arr<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">return ret<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">On the other hand, the development version of LLVM produces the following IR:<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">; Function Attrs: nounwind<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">define i8* @get(i32 %ind) local_unnamed_addr #0 {<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">entry:<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  %cmp = icmp eq i32 %ind, 0<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* @arr, i32 0, i32 %ind<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  %retval.0 = select i1 %cmp, i8* %arrayidx, i8* null<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  ret i8* %retval.0<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">}<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">The variable `arrayidx` is always calculated even though we could simply return `arr` when `ind` equals to zero.<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">Is this kind of optimization already implemented somewhere in LLVM? If not, what is the best place to implement it at? Thank you very much in advance.<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">Best,<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">Alex<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">--------------------------<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">GCC x86 ASM:<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  testl %edi, %edi<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  movl  $0, %edx<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  movl  $arr, %eax<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  cmovne  %rdx, %rax<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  ret<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class=""><u class=""></u> <u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">LLVM x86 ASM:<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  xorl  %eax, %eax<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  testl %edi, %edi<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  movl  %edi, %ecx<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  leaq  arr(%rcx), %rcx<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  cmoveq  %rcx, %rax<u class=""></u><u class=""></u></span></p><p class=""><span style="color:rgb(31,73,125)" class="">  retq<u class=""></u><u class=""></u></span></p></div><div style="height:0px" class=""></div></div><div style="font-family:sans-serif;font-size:12.8px;height:176px" dir="auto" class=""></div><br class=""></div>
_______________________________________________<br class="">LLVM Developers mailing list<br class=""><a href="mailto:llvm-dev@lists.llvm.org" class="">llvm-dev@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev<br class=""></div></blockquote></div><br class=""></div></body></html>