https://bugs.llvm.org/show_bug.cgi?id=36801

            Bug ID: 36801
           Summary: [LICM] LICM promotes real value to null in store
                    instruction
           Product: new-bugs
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: new bugs
          Assignee: unassignedb...@nondot.org
          Reporter: ilia.tara...@intel.com
                CC: llvm-bugs@lists.llvm.org

This test fails with wrong result after "Loop Invariant Code Motion":

================= nice.c ==============
unsigned int y = 0;

int main () {
  unsigned int i = 0, j = 0, a = 0;
  unsigned int gc[3] = {0};
  unsigned int *p = &a;
  scanf("");
  for (i = 2; i < 4; ++i) {
    gc[i - 1] += 1;
    for (j = i; j < 1; ++j) 
      y = (*p);
    p = &gc[i - 1];
    gc[1]++;
  }
  *p = gc[0];
  printf("res = %u\n", gc[1]);
  return 0;
}
=======================================

>>> clang -v
clang version 7.0.0 (trunk 327823)
Target: x86_64-unknown-linux-gnu
Thread model: posix
...

>>> clang -o nice.exe nice.c -O0
>>> nice.exe
res = 3
>>> clang -o nice.exe nice.c -O1
>>> nice.exe
res = 2

BISECT:
>>> clang -o nice.exe nice.c -mllvm -opt-bisect-limit=...
...
BISECT: running pass (32) Unswitch loops on loop
BISECT: running pass (33) Rotate Loops on loop
res = 3
BISECT: running pass (34) Loop Invariant Code Motion on loop
res = 2
BISECT: NOT running pass (35) Unswitch loops on loop
...

Here is "small" reproducer:
================= fine.ll ==============
define dso_local i32 @main() local_unnamed_addr {
entry:
  %gc = alloca [3 x i32], align 4
  br label %for.cond

for.cond:                                         ; preds = %for.end, %entry
  %i.0 = phi i32 [ 2, %entry ], [ %inc10, %for.end ]
  %p.0 = phi i32* [ null, %entry ], [ %arrayidx, %for.end ]
  %cmp = icmp ult i32 %i.0, 4
  br i1 %cmp, label %for.body, label %for.end11

for.body:                                         ; preds = %for.cond
  %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %gc, i64 0, i64 0
  store i32 0, i32* %arrayidx, align 4
  br label %for.cond1

for.cond1:                                        ; preds = %for.body3,
%for.body
  %j.0 = phi i32 [ %i.0, %for.body ], [ 1, %for.body3 ]
  br i1 false, label %for.body3, label %for.end

for.body3:                                        ; preds = %for.cond1
  %0 = load i32, i32* %p.0, align 4
  br label %for.cond1

for.end:                                          ; preds = %for.cond1
  %arrayidx7 = getelementptr inbounds [3 x i32], [3 x i32]* %gc, i64 0, i64 1
  %inc10 = add i32 %i.0, 1
  br label %for.cond

for.end11:                                        ; preds = %for.cond
  %p.0.lcssa = phi i32* [ %p.0, %for.cond ]
  ret i32 0
}
=======================================

Original test does nothing.
>>> opt -S -o fine.post.rotate+licm.ll -loop-rotate -licm  fine.ll
>>> clang fine.post.rotate+licm.ll && a.out
Segmentation fault

After "Rotate Loops" and "Loop Invariant Code Motion", we receive "store into
null":

================= fine.post.rotate+licm.ll ==============
define dso_local i32 @main() local_unnamed_addr {
entry:
  %gc = alloca [3 x i32], align 4
  %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %gc, i64 0, i64 0
  br label %for.body

for.body:                                         ; preds = %entry, %for.end
  %i.01 = phi i32 [ 2, %entry ], [ %inc10, %for.end ]
  br i1 false, label %for.body3.lr.ph, label %for.end

for.body3.lr.ph:                                  ; preds = %for.body
  br label %for.body3

for.body3:                                        ; preds = %for.body3.lr.ph,
%for.body3
  br i1 false, label %for.body3, label %for.cond1.for.end_crit_edge

for.cond1.for.end_crit_edge:                      ; preds = %for.body3
  br label %for.end

for.end:                                          ; preds =
%for.cond1.for.end_crit_edge, %for.body
  %inc10 = add i32 %i.01, 1
  %cmp = icmp ult i32 %inc10, 4
  br i1 %cmp, label %for.body, label %for.end11

for.end11:                                        ; preds = %for.end
  store i32 0, i32* null, align 4
  %arrayidx.le = getelementptr inbounds [3 x i32], [3 x i32]* %gc, i64 0, i64 0
  ret i32 0
}
=======================================

Quick debug shows that %arrayidx aliases null. But in original code %arrayidx
always refers to array %gs.
>>>CurAST of Loop:
>>>Alias Set Tracker: 1 alias sets for 2 pointer values.
>>>  AliasSet[0x760ad30, 2] must alias, Mod/Ref   Pointers: (i32* null, 4), 
>>> (i32* %arrayidx, 4)

So maybe problem is in Loop aliasing.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to