[PATCH] D63629: [JumpThreading][PR42085] Fold constant TIs before calculating LoopHeaders

Brian Rzycki via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 08:44:11 PDT 2019


brzycki added a comment.

Hello @efriedma,

> How do we actually get a miscompile?

The new test-case below, `pr42085-loopheader-detection.ll` exhibits the miscompile on unpatched tip LLVM. In PR42085 <https://bugs.llvm.org/show_bug.cgi?id=42085> I've attached a test harness which runs the code using a simple `main.c` and a shell script. The `main.c` looks like:

  #include <libgen.h>
  #include <stdio.h>
  #include <stdlib.h>
  
  extern int test(unsigned char);
  
  char *name;
  
  int main(int arc, char *argv[]) {
    unsigned char arg = atoi(argv[1]);
    name = basename(argv[0]);
    printf("    [%-10s] test == %d\n", name, test(arg));
    return 0;
  }

And we compile `pr42085-loopheader-detection.ll` two different ways to thread and not thread the code:

  echo build main.o
  "$clang" -O3 -c "$main" $debug -o main.o
  
  echo build pr.o
  "$llc" -O0 "$pr" -o pr.s
  "$clang" -c pr.s -o pr.o
  
  echo build jt.o
  "$opt" -passes=jump-threading -S -o jt.ll "$pr"
  "$llc" -O0 jt.ll -o jt.s
  "$clang" -c jt.s -o jt.o
  
  echo link
  "$clang" jt.o main.o -o runme_jt
  "$clang" pr.o main.o -o runme_pr

In the above code `pr.o` is not JumpThreaded while `jt.o` is.

the output of execution shows the miscompile. When input of `(0, 0)` or `(0, 1)` is passed into `test()` we see different returned values:

  [ INPUT ==> arg1=0 arg1=0 ]
      [runme_pr  ] test == 2
      [runme_jt  ] test == 3
  
  [ INPUT ==> arg1=0 arg1=1 ]
      [runme_pr  ] test == 2
      [runme_jt  ] test == 3
  
  [ INPUT ==> arg1=1 arg1=0 ]
      [runme_pr  ] test == -1
      [runme_jt  ] test == -1
  
  [ INPUT ==> arg1=1 arg1=1 ]
      [runme_pr  ] test == -1
      [runme_jt  ] test == -1

In the miscompile case we thread `body1 ==> body2 ==> latch1` to `body1 ==> body2.thread ==> latch1`. We find the following backedges from `FindFunctionBackedges()`. We store the destination `Edge.second` as each `BB` entry in `LoopHeaders`:

  latch2 ==> body1
  body1  ==> pre_head

With the fix (removing trivial constant terminators) before calculating `LoopHeaders`, the function `FindFunctionBackedges()` finds the following edges:

  body1 ==> body2
  body1 ==> pre_head

And correctly promoting `body2` to a loop header pessimizes threads across it.

> I'm worried this fix is covering up a bug in our handling of [loop header] code.

It's entirely possible, I'm not an expert on loop transforms. The reason I went down this path is I noticed the change in `LoopHeaders` when I made the following single change to the IR:

  --- pr42085.ll  2019-06-27 09:55:57.501853639 -0500
  +++ pr42085_good.ll     2019-06-27 10:36:57.667534318 -0500
  @@ -15,7 +15,7 @@
     br i1 %ARG1, label %exit, label %head2
  
   head2:
  -  br i1 false, label %head3, label %body2
  +  br label %body2
  
   head3:
     %tmp8 = add i32 %tmp3, 1

Using the above IR with  `opt -S -jump-threading` on an unpatched LLVM compiler does not exhibit the miscompile. But, as you say, this may be masking a deeper issue that I haven't noticed. I'd definitely appreciate your expertise or any suggestions you may have.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63629/new/

https://reviews.llvm.org/D63629





More information about the llvm-commits mailing list