<div dir="ltr"><div>Hi again!</div><div><br></div><div>The initial code: (test.c)<br></div><div><br></div><div>#include <stdio.h><br><br>int a; // or, equally, int a=0;<br><br><span style="font-family:monospace">int main(){<br> int b;<br> if (b) // (*)<br>   b=a;<br> if (b)<br>   puts("This will be called");<br>}</span></div><div><br></div><div>In LLVM IR:<br></div><div><br><span style="font-family:monospace">define dso_local i32 @main() #0 {<br>  %1 = alloca i32, align 4<br>  %2 = alloca i32, align 4<br>  store i32 0, i32* %1, align 4<br>  %3 = load i32, i32* %2, align 4<br>  %4 = icmp ne i32 %3, 0<br>  br i1 %4, label %5, label %7<br><br>5:                                                ; preds = %0<br>  %6 = load i32, i32* @a, align 4<br>  store i32 %6, i32* %2, align 4<br>  br label %7<br><br>7:                                                ; preds = %5, %0<br>  %8 = load i32, i32* %2, align 4<br>  %9 = icmp ne i32 %8, 0<br>  br i1 %9, label %10, label %12<br><br>10:                                               ; preds = %7<br>  %11 = call i32 @puts(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str, i64 0, i64 0))<br>  br label %12<br><br>12:                                               ; preds = %10, %7<br>  %13 = load i32, i32* %1, align 4<br>  ret i32 %13<br>}</span><br></div><div><br></div><div>After optimizing: `clang -S -emit-llvm test.c -O0 -o - | sed 's/optnone//g' | opt asd.ll -mem2reg | llvm-dis`</div><div>(Note: optnone is removed to have mem2reg optimize the main function)<br></div><div><br></div><div><span style="font-family:monospace">define dso_local i32 @main() #0 {<br>  %1 = icmp ne i32 undef, 0 ; <- undef!!<br>  br i1 %1, label %2, label %4<br><br>2:                                                ; preds = %0<br>  %3 = load i32, i32* @a, align 4<br>  br label %4<br><br>4:                                                ; preds = %2, %0<br>  %.0 = phi i32 [ %3, %2 ], [ undef, %0 ] ; <- undef!!<br>  %5 = icmp ne i32 %.0, 0<br>  br i1 %5, label %6, label %8<br><br>6:                                                ; preds = %4<br>  %7 = call i32 @puts(i8* getelementptr inbounds ([20 x i8], [20 x i8]* @.str, i64 0, i64 0))<br>  br label %8<br><br>8:                                                ; preds = %6, %4<br>  ret i32 0<br>}</span></div><div><br></div><div>My problem is the two annotated "undef!!" comments. They are the same undef value, and, by decoupling these, the program changes.</div><div>I'm not really sure, because the C standard has some really weird undefined behaviour definitions.</div><div>Also, I don't know how LLVM "undef" should work. If "undef" is an unspecified-like value, not an undefined-behavior-causing value, then it could also be a bug in LLVM.</div><div><br></div><div>Please reach back if you need more information.<br></div><br>László</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Sep 14, 2020 at 9:19 AM László Radnai <<a href="mailto:radlaci97@gmail.com">radlaci97@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi all!<br><br>While playing with LLVM, I've found a weird behavior in mem2reg pass.<br><br>When optimizing single stores, undefined value is placed before any load preceding the store (based on basicblock's ordering and simple dominator analysis, if I remember correctly).<br><br>This is the line that is responsible for the behavior: (LLVM9 does the same)<br><br><a href="https://llvm.org/doxygen/PromoteMemoryToRegister_8cpp_source.html#l00629" target="_blank">https://llvm.org/doxygen/PromoteMemoryToRegister_8cpp_source.html#l00629</a><br><br>A problem arises, and I am not sure if it is really a problem or just weird C-compliant behavior.<br><br>int a; // or, equally, int a=0;<br><br>int main(){<br>  int b;<br>  if (b) // (*)<br>    b=a;<br>  if (b)<br>    printf("This will be called");<br>}<br><br>The first load of variable b, before the single store (the first branching) is replaced by undef, so the second branch will be replaced by a phi node, if the (*) branch is taken, the value is 0, else undef.<br><br>I'm concerned that this is an LLVM bug.<br><br>Reproduction:<br><br>clang -S -emit-llvm test.c<br>opt -mem2reg test.ll<br><br>I'm not at the computer right now, so I cannot show the exact generated code.<br><br>Radnai László<br>
</blockquote></div>