[TTI] getTypeBasedIntrinsicInstrCost - add basic handling for strided load/store...
[llvm-project.git] / llvm / test / Transforms / GVN / memdep-unknown-deadblocks.ll
blobaf1bc98dc54f0401ef48fcb9845e1cdc4926a8b0
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes='function(gvn)' -S | FileCheck -check-prefixes=CHECK-GVN %s
4 ; Also do some runs using an GVN+O1 pipeline, using O1 to clean up after GVN.
5 ; This is to easier see the semantic of the resulting IR and that it hopefully
6 ; is the same as if only running O1 directly.
8 ; RUN: opt < %s -passes='function(gvn),default<O1>' -S | FileCheck -check-prefixes=CHECK-GVN-O1 %s
9 ; RUN: opt < %s -passes='default<O1>' -S | FileCheck -check-prefixes=CHECK-O1 %s
11 ; This is a reproducer for the miscompile reported here:
12 ;   https://github.com/llvm/llvm-project/issues/57025
14 ; Explanation of the test case:
15 ;  - Outer loop will do three iterations i:=0, i:=1 and i:=2
16 ;  - When is i==0 the value 7 is stored to arr[0]
17 ;  - When is i!=0 the value 42 is stored to arr[i]
18 ;  - There is a nestled while loop reduced down to something just setting j:=i
19 ;    and then exiting.
20 ;  - In while.end arr[j] (i.e. the just stored to arr[i]) is loaded,
21 ;    and the loaded value is passed to the verify function.
22 ;  - There is a dead load of the not yet initialized arr[j+1] in the epilog
23 ;    block. This might seem irrelevant, but is needed to reproduce the
24 ;    miscompile.
26 ; Expected semantic of the function is that verify() will be called three
27 ; times, with the values 7, 42 and 42.
29 declare void @verify(i16)
31 define void @test(i16 %g) {
32 ; CHECK-GVN-LABEL: @test(
33 ; CHECK-GVN-NEXT:  entry:
34 ; CHECK-GVN-NEXT:    [[ARR:%.*]] = alloca [4 x i16], align 1
35 ; CHECK-GVN-NEXT:    br label [[FOR_BODY:%.*]]
36 ; CHECK-GVN:       for.body:
37 ; CHECK-GVN-NEXT:    [[I:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[NEXT_I:%.*]], [[WHILE_END:%.*]] ]
38 ; CHECK-GVN-NEXT:    [[CMP0:%.*]] = icmp eq i16 [[I]], 0
39 ; CHECK-GVN-NEXT:    br i1 [[CMP0]], label [[STORE_IDX_0:%.*]], label [[STORE_IDX_I:%.*]]
40 ; CHECK-GVN:       store.idx.0:
41 ; CHECK-GVN-NEXT:    store i16 7, ptr [[ARR]], align 1
42 ; CHECK-GVN-NEXT:    br label [[STORE_DONE:%.*]]
43 ; CHECK-GVN:       store.idx.i:
44 ; CHECK-GVN-NEXT:    [[ARR_I:%.*]] = getelementptr [4 x i16], ptr [[ARR]], i16 0, i16 [[I]]
45 ; CHECK-GVN-NEXT:    store i16 42, ptr [[ARR_I]], align 1
46 ; CHECK-GVN-NEXT:    br label [[STORE_DONE]]
47 ; CHECK-GVN:       store.done:
48 ; CHECK-GVN-NEXT:    br label [[WHILE_BODY:%.*]]
49 ; CHECK-GVN:       while.body:
50 ; CHECK-GVN-NEXT:    br i1 false, label [[WHILE_BODY_WHILE_BODY_CRIT_EDGE:%.*]], label [[WHILE_END]]
51 ; CHECK-GVN:       while.body.while.body_crit_edge:
52 ; CHECK-GVN-NEXT:    br label [[WHILE_BODY]]
53 ; CHECK-GVN:       while.end:
54 ; CHECK-GVN-NEXT:    [[ARR_J:%.*]] = getelementptr [4 x i16], ptr [[ARR]], i16 0, i16 [[I]]
55 ; CHECK-GVN-NEXT:    [[VALUE:%.*]] = load i16, ptr [[ARR_J]], align 1
56 ; CHECK-GVN-NEXT:    tail call void @verify(i16 [[VALUE]])
57 ; CHECK-GVN-NEXT:    [[NEXT_I]] = add i16 [[I]], 1
58 ; CHECK-GVN-NEXT:    [[ARR_NEXT_I:%.*]] = getelementptr [4 x i16], ptr [[ARR]], i16 0, i16 [[NEXT_I]]
59 ; CHECK-GVN-NEXT:    [[CMP4:%.*]] = icmp slt i16 [[NEXT_I]], 3
60 ; CHECK-GVN-NEXT:    br i1 [[CMP4]], label [[FOR_BODY]], label [[FOR_END:%.*]]
61 ; CHECK-GVN:       for.end:
62 ; CHECK-GVN-NEXT:    ret void
64 ; CHECK-GVN-O1-LABEL: @test(
65 ; CHECK-GVN-O1-NEXT:  entry:
66 ; CHECK-GVN-O1-NEXT:    tail call void @verify(i16 7)
67 ; CHECK-GVN-O1-NEXT:    tail call void @verify(i16 42)
68 ; CHECK-GVN-O1-NEXT:    tail call void @verify(i16 42)
69 ; CHECK-GVN-O1-NEXT:    ret void
71 ; CHECK-O1-LABEL: @test(
72 ; CHECK-O1-NEXT:  entry:
73 ; CHECK-O1-NEXT:    tail call void @verify(i16 7)
74 ; CHECK-O1-NEXT:    tail call void @verify(i16 42)
75 ; CHECK-O1-NEXT:    tail call void @verify(i16 42)
76 ; CHECK-O1-NEXT:    ret void
78 entry:
79   %arr = alloca [4 x i16], align 1
80   br label %for.body
82 for.body:                                         ; preds = %epilog, %entry
83   %i = phi i16 [ 0, %entry ], [ %next.i, %epilog ]
84   %cmp0 = icmp eq i16 %i, 0
85   br i1 %cmp0, label %store.idx.0, label %store.idx.i
87 store.idx.0:                                      ; preds = %for.body
88   store i16 7, ptr %arr, align 1
89   br label %store.done
91 store.idx.i:                                      ; preds = %for.body
92   %arr.i = getelementptr [4 x i16], ptr %arr, i16 0, i16 %i
93   store i16 42, ptr %arr.i, align 1
94   br label %store.done
96 store.done:                                        ; preds = %store.idx.i, %store.idx.0
97   br label %while.body
99 while.body:                                       ; preds = %while.body, %store.done
100   %j = phi i16 [ %i, %store.done ], [ 0, %while.body ]
101   ; Constant foldable conditional branch.
102   ; Needed to reproduce the fault!
103   br i1 false, label %while.body, label %while.end
105 while.end:                                        ; preds = %while.body
106   %arr.j = getelementptr [4 x i16], ptr %arr, i16 0, i16 %j
107   %value = load i16, ptr %arr.j, align 1
108   tail call void @verify(i16 %value)
109   br label %epilog
111 epilog:                                          ; preds = %while.end
112   %next.i = add i16 %j, 1
113   %arr.next.i = getelementptr [4 x i16], ptr %arr, i16 0, i16 %next.i
114   ; A dead load.
115   ;  Needed to reproduce the fault!
116   %dead = load i16, ptr %arr.next.i, align 1
117   %cmp4 = icmp slt i16 %next.i, 3
118   br i1 %cmp4, label %for.body, label %for.end
120 for.end:                                          ; preds = %epilog
121   ret void