<div dir="auto"><div style="font-family:sans-serif;font-size:12.8px" dir="auto"><div style="height:91px"><span style="color:rgb(31,73,125)">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"><span style="color:rgb(31,73,125)">Here's the original C code:</span></div><div style="margin:16px 0px"><p><span style="color:rgb(31,73,125)">1 char arr[2];<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">2 char *get(unsigned ind) {<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">3   if (ind >= 1) {<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">4    return 0;<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">5   }<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">6   return &(arr[ind]);<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">7 }<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">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></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">ret = 0<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">if ind == 0:<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">    ret = arr<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">return ret<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">On the other hand, the development version of LLVM produces the following IR:<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">; Function Attrs: nounwind<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">define i8* @get(i32 %ind) local_unnamed_addr #0 {<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">entry:<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  %cmp = icmp eq i32 %ind, 0<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* @arr, i32 0, i32 %ind<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  %retval.0 = select i1 %cmp, i8* %arrayidx, i8* null<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  ret i8* %retval.0<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">}<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">The variable `arrayidx` is always calculated even though we could simply return `arr` when `ind` equals to zero.<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">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></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">Best,<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">Alex<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">--------------------------<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">GCC x86 ASM:<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  testl %edi, %edi<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  movl  $0, %edx<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  movl  $arr, %eax<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  cmovne  %rdx, %rax<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  ret<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)"><u></u> <u></u></span></p><p><span style="color:rgb(31,73,125)">LLVM x86 ASM:<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  xorl  %eax, %eax<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  testl %edi, %edi<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  movl  %edi, %ecx<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  leaq  arr(%rcx), %rcx<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  cmoveq  %rcx, %rax<u></u><u></u></span></p><p><span style="color:rgb(31,73,125)">  retq<u></u><u></u></span></p></div><div style="height:0px"></div></div><div style="font-family:sans-serif;font-size:12.8px;height:176px" dir="auto"></div><br></div>