[llvm-dev] Mem2reg: load before single store

László Radnai via llvm-dev llvm-dev at lists.llvm.org
Mon Sep 14 07:01:24 PDT 2020


Hi again!

The initial code: (test.c)

#include <stdio.h>

int a; // or, equally, int a=0;

int main(){
 int b;
 if (b) // (*)
   b=a;
 if (b)
   puts("This will be called");
}

In LLVM IR:

define dso_local i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 0, i32* %1, align 4
  %3 = load i32, i32* %2, align 4
  %4 = icmp ne i32 %3, 0
  br i1 %4, label %5, label %7

5:                                                ; preds = %0
  %6 = load i32, i32* @a, align 4
  store i32 %6, i32* %2, align 4
  br label %7

7:                                                ; preds = %5, %0
  %8 = load i32, i32* %2, align 4
  %9 = icmp ne i32 %8, 0
  br i1 %9, label %10, label %12

10:                                               ; preds = %7
  %11 = call i32 @puts(i8* getelementptr inbounds ([20 x i8], [20 x i8]*
@.str, i64 0, i64 0))
  br label %12

12:                                               ; preds = %10, %7
  %13 = load i32, i32* %1, align 4
  ret i32 %13
}

After optimizing: `clang -S -emit-llvm test.c -O0 -o - | sed 's/optnone//g'
| opt asd.ll -mem2reg | llvm-dis`
(Note: optnone is removed to have mem2reg optimize the main function)

define dso_local i32 @main() #0 {
  %1 = icmp ne i32 undef, 0 ; <- undef!!
  br i1 %1, label %2, label %4

2:                                                ; preds = %0
  %3 = load i32, i32* @a, align 4
  br label %4

4:                                                ; preds = %2, %0
  %.0 = phi i32 [ %3, %2 ], [ undef, %0 ] ; <- undef!!
  %5 = icmp ne i32 %.0, 0
  br i1 %5, label %6, label %8

6:                                                ; preds = %4
  %7 = call i32 @puts(i8* getelementptr inbounds ([20 x i8], [20 x i8]*
@.str, i64 0, i64 0))
  br label %8

8:                                                ; preds = %6, %4
  ret i32 0
}

My problem is the two annotated "undef!!" comments. They are the same undef
value, and, by decoupling these, the program changes.
I'm not really sure, because the C standard has some really weird undefined
behaviour definitions.
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.

Please reach back if you need more information.

László

On Mon, Sep 14, 2020 at 9:19 AM László Radnai <radlaci97 at gmail.com> wrote:

> Hi all!
>
> While playing with LLVM, I've found a weird behavior in mem2reg pass.
>
> 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).
>
> This is the line that is responsible for the behavior: (LLVM9 does the
> same)
>
> https://llvm.org/doxygen/PromoteMemoryToRegister_8cpp_source.html#l00629
>
> A problem arises, and I am not sure if it is really a problem or just
> weird C-compliant behavior.
>
> int a; // or, equally, int a=0;
>
> int main(){
>  int b;
>  if (b) // (*)
>    b=a;
>  if (b)
>    printf("This will be called");
> }
>
> 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.
>
> I'm concerned that this is an LLVM bug.
>
> Reproduction:
>
> clang -S -emit-llvm test.c
> opt -mem2reg test.ll
>
> I'm not at the computer right now, so I cannot show the exact generated
> code.
>
> Radnai László
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200914/6aacb4e4/attachment-0001.html>


More information about the llvm-dev mailing list