[llvm] 3aab9d2 - [GVN] Pre-commit test case showing miscompile in github issue #57025

Bjorn Pettersson via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 1 05:44:54 PDT 2022


Author: Bjorn Pettersson
Date: 2022-09-01T14:43:24+02:00
New Revision: 3aab9d2bb7f38f4d00b16817711fbfac8f75b51b

URL: https://github.com/llvm/llvm-project/commit/3aab9d2bb7f38f4d00b16817711fbfac8f75b51b
DIFF: https://github.com/llvm/llvm-project/commit/3aab9d2bb7f38f4d00b16817711fbfac8f75b51b.diff

LOG: [GVN] Pre-commit test case showing miscompile in github issue #57025

This commit adds a reproducer for
  https://github.com/llvm/llvm-project/issues/57025
showing a miscompile in GVN.

Not sure how likely this kind of faults would be in a normal pipeline,
considering that the input IR has some dead code in it. On the other
hand, GVN itself sometimes creates dead basic blocks when splitting
critical edges. Anyway, the fault was found when doing fuzzy testing
using random pass pipelines.

Differential Revision: https://reviews.llvm.org/D131775

Added: 
    llvm/test/Transforms/GVN/memdep-unknown-deadblocks.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/GVN/memdep-unknown-deadblocks.ll b/llvm/test/Transforms/GVN/memdep-unknown-deadblocks.ll
new file mode 100644
index 0000000000000..02e9baab712a5
--- /dev/null
+++ b/llvm/test/Transforms/GVN/memdep-unknown-deadblocks.ll
@@ -0,0 +1,129 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes='function(gvn)' -S | FileCheck -check-prefixes=CHECK-GVN %s
+
+; Also do some runs using an GVN+O1 pipeline, using O1 to clean up after GVN.
+; This is to easier see the semantic of the resulting IR and that it hopefully
+; is the same as if only running O1 directly.
+;
+; RUN: opt < %s -passes='function(gvn),default<O1>' -S | FileCheck -check-prefixes=CHECK-GVN-O1 %s
+; RUN: opt < %s -passes='default<O1>' -S | FileCheck -check-prefixes=CHECK-O1 %s
+
+; This is a reproducer for the miscompile reported here:
+;   https://github.com/llvm/llvm-project/issues/57025
+;
+; Explanation of the test case:
+;  - Outer loop will do three iterations i:=0, i:=1 and i:=2
+;  - When is i==0 the value 7 is stored to arr[0]
+;  - When is i!=0 the value 42 is stored to arr[i]
+;  - There is a nestled while loop reduced down to something just setting j:=i
+;    and then exiting.
+;  - In while.end arr[j] (i.e. the just stored to arr[i]) is loaded,
+;    and the loaded value is passed to the verify function.
+;  - There is a dead load of the not yet initialized arr[j+1] in the epilog
+;    block. This might seem irrelevant, but is needed to reproduce the
+;    miscompile.
+;
+; Expected semantic of the function is that verify() will be called three
+; times, with the values 7, 42 and 42.
+
+; FIXME: The value passed to the verify function is loaded by
+;           %value = load i16, ptr %arr.j, align 1
+;        but currently GVN is replacing it with a faulty PHI in the
+;        store.done block.
+
+declare void @verify(i16)
+
+define void @test(i16 %g) {
+; CHECK-GVN-LABEL: @test(
+; CHECK-GVN-NEXT:  entry:
+; CHECK-GVN-NEXT:    [[ARR:%.*]] = alloca [4 x i16], align 1
+; CHECK-GVN-NEXT:    br label [[FOR_BODY:%.*]]
+; CHECK-GVN:       for.body:
+; CHECK-GVN-NEXT:    [[VALUE2:%.*]] = phi i16 [ undef, [[ENTRY:%.*]] ], [ [[DEAD:%.*]], [[WHILE_END:%.*]] ]
+; CHECK-GVN-NEXT:    [[I:%.*]] = phi i16 [ 0, [[ENTRY]] ], [ [[NEXT_I:%.*]], [[WHILE_END]] ]
+; CHECK-GVN-NEXT:    [[CMP0:%.*]] = icmp eq i16 [[I]], 0
+; CHECK-GVN-NEXT:    br i1 [[CMP0]], label [[STORE_IDX_0:%.*]], label [[STORE_IDX_I:%.*]]
+; CHECK-GVN:       store.idx.0:
+; CHECK-GVN-NEXT:    store i16 7, ptr [[ARR]], align 1
+; CHECK-GVN-NEXT:    br label [[STORE_DONE:%.*]]
+; CHECK-GVN:       store.idx.i:
+; CHECK-GVN-NEXT:    [[ARR_I:%.*]] = getelementptr [4 x i16], ptr [[ARR]], i16 0, i16 [[I]]
+; CHECK-GVN-NEXT:    store i16 42, ptr [[ARR_I]], align 1
+; CHECK-GVN-NEXT:    br label [[STORE_DONE]]
+; CHECK-GVN:       store.done:
+; CHECK-GVN-NEXT:    [[VALUE:%.*]] = phi i16 [ 42, [[STORE_IDX_I]] ], [ [[VALUE2]], [[STORE_IDX_0]] ]
+; CHECK-GVN-NEXT:    br label [[WHILE_BODY:%.*]]
+; CHECK-GVN:       while.body:
+; CHECK-GVN-NEXT:    br i1 false, label [[WHILE_BODY_WHILE_BODY_CRIT_EDGE:%.*]], label [[WHILE_END]]
+; CHECK-GVN:       while.body.while.body_crit_edge:
+; CHECK-GVN-NEXT:    br label [[WHILE_BODY]]
+; CHECK-GVN:       while.end:
+; CHECK-GVN-NEXT:    [[ARR_J:%.*]] = getelementptr [4 x i16], ptr [[ARR]], i16 0, i16 [[I]]
+; CHECK-GVN-NEXT:    tail call void @verify(i16 [[VALUE]])
+; CHECK-GVN-NEXT:    [[NEXT_I]] = add i16 [[I]], 1
+; CHECK-GVN-NEXT:    [[ARR_NEXT_I:%.*]] = getelementptr [4 x i16], ptr [[ARR]], i16 0, i16 [[NEXT_I]]
+; CHECK-GVN-NEXT:    [[DEAD]] = load i16, ptr [[ARR_NEXT_I]], align 1
+; CHECK-GVN-NEXT:    [[CMP4:%.*]] = icmp slt i16 [[NEXT_I]], 3
+; CHECK-GVN-NEXT:    br i1 [[CMP4]], label [[FOR_BODY]], label [[FOR_END:%.*]]
+; CHECK-GVN:       for.end:
+; CHECK-GVN-NEXT:    ret void
+;
+; CHECK-GVN-O1-LABEL: @test(
+; CHECK-GVN-O1-NEXT:  entry:
+; CHECK-GVN-O1-NEXT:    tail call void @verify(i16 42)
+; CHECK-GVN-O1-NEXT:    tail call void @verify(i16 42)
+; CHECK-GVN-O1-NEXT:    tail call void @verify(i16 42)
+; CHECK-GVN-O1-NEXT:    ret void
+;
+; CHECK-O1-LABEL: @test(
+; CHECK-O1-NEXT:  entry:
+; CHECK-O1-NEXT:    tail call void @verify(i16 7)
+; CHECK-O1-NEXT:    tail call void @verify(i16 42)
+; CHECK-O1-NEXT:    tail call void @verify(i16 42)
+; CHECK-O1-NEXT:    ret void
+;
+entry:
+  %arr = alloca [4 x i16], align 1
+  br label %for.body
+
+for.body:                                         ; preds = %epilog, %entry
+  %i = phi i16 [ 0, %entry ], [ %next.i, %epilog ]
+  %cmp0 = icmp eq i16 %i, 0
+  br i1 %cmp0, label %store.idx.0, label %store.idx.i
+
+store.idx.0:                                      ; preds = %for.body
+  store i16 7, ptr %arr, align 1
+  br label %store.done
+
+store.idx.i:                                      ; preds = %for.body
+  %arr.i = getelementptr [4 x i16], ptr %arr, i16 0, i16 %i
+  store i16 42, ptr %arr.i, align 1
+  br label %store.done
+
+store.done:                                        ; preds = %store.idx.i, %store.idx.0
+  br label %while.body
+
+while.body:                                       ; preds = %while.body, %store.done
+  %j = phi i16 [ %i, %store.done ], [ 0, %while.body ]
+  ; Constant foldable conditional branch.
+  ; Needed to reproduce the fault!
+  br i1 false, label %while.body, label %while.end
+
+while.end:                                        ; preds = %while.body
+  %arr.j = getelementptr [4 x i16], ptr %arr, i16 0, i16 %j
+  %value = load i16, ptr %arr.j, align 1
+  tail call void @verify(i16 %value)
+  br label %epilog
+
+epilog:                                          ; preds = %while.end
+  %next.i = add i16 %j, 1
+  %arr.next.i = getelementptr [4 x i16], ptr %arr, i16 0, i16 %next.i
+  ; A dead load.
+  ;  Needed to reproduce the fault!
+  %dead = load i16, ptr %arr.next.i, align 1
+  %cmp4 = icmp slt i16 %next.i, 3
+  br i1 %cmp4, label %for.body, label %for.end
+
+for.end:                                          ; preds = %epilog
+  ret void
+}


        


More information about the llvm-commits mailing list