1; RUN: opt -S -early-cse -earlycse-debug-hash < %s | FileCheck %s
2; RUN: opt -S -gvn < %s | FileCheck %s
3; RUN: opt -S -newgvn < %s | FileCheck %s
4; RUN: opt -S -O3 < %s | FileCheck %s
5
6; These tests checks if passes with CSE functionality can do CSE on
7; launder.invariant.group, that is prohibited if there is a memory clobber
8; between barriers call.
9
10; CHECK-LABEL: define i8 @optimizable()
11define i8 @optimizable() {
12entry:
13    %ptr = alloca i8
14    store i8 42, i8* %ptr, !invariant.group !0
15; CHECK: call i8* @llvm.launder.invariant.group.p0i8
16    %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
17; FIXME: This one could be CSE
18; CHECK: call i8* @llvm.launder.invariant.group
19    %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
20; CHECK: call void @clobber(i8* {{.*}}%ptr)
21    call void @clobber(i8* %ptr)
22
23; CHECK: call void @use(i8* {{.*}}%ptr2)
24    call void @use(i8* %ptr2)
25; CHECK: call void @use(i8* {{.*}}%ptr3)
26    call void @use(i8* %ptr3)
27; CHECK: load i8, i8* %ptr3, {{.*}}!invariant.group
28    %v = load i8, i8* %ptr3, !invariant.group !0
29
30    ret i8 %v
31}
32
33; CHECK-LABEL: define i8 @unoptimizable()
34define i8 @unoptimizable() {
35entry:
36    %ptr = alloca i8
37    store i8 42, i8* %ptr, !invariant.group !0
38; CHECK: call i8* @llvm.launder.invariant.group.p0i8
39    %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
40    call void @clobber(i8* %ptr)
41; CHECK: call i8* @llvm.launder.invariant.group.p0i8
42    %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
43; CHECK: call void @clobber(i8* {{.*}}%ptr)
44    call void @clobber(i8* %ptr)
45; CHECK: call void @use(i8* {{.*}}%ptr2)
46    call void @use(i8* %ptr2)
47; CHECK: call void @use(i8* {{.*}}%ptr3)
48    call void @use(i8* %ptr3)
49; CHECK: load i8, i8* %ptr3, {{.*}}!invariant.group
50    %v = load i8, i8* %ptr3, !invariant.group !0
51
52    ret i8 %v
53}
54
55; CHECK-LABEL: define i8 @unoptimizable2()
56define i8 @unoptimizable2() {
57    %ptr = alloca i8
58    store i8 42, i8* %ptr, !invariant.group !0
59; CHECK: call i8* @llvm.launder.invariant.group
60    %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
61    store i8 43, i8* %ptr
62; CHECK: call i8* @llvm.launder.invariant.group
63    %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
64; CHECK: call void @clobber(i8* {{.*}}%ptr)
65    call void @clobber(i8* %ptr)
66; CHECK: call void @use(i8* {{.*}}%ptr2)
67    call void @use(i8* %ptr2)
68; CHECK: call void @use(i8* {{.*}}%ptr3)
69    call void @use(i8* %ptr3)
70; CHECK: load i8, i8* %ptr3, {{.*}}!invariant.group
71    %v = load i8, i8* %ptr3, !invariant.group !0
72    ret i8 %v
73}
74
75; This test check if optimizer is not proving equality based on mustalias
76; CHECK-LABEL: define void @dontProveEquality(i8* %a)
77define void @dontProveEquality(i8* %a) {
78  %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %a)
79  %r = icmp eq i8* %b, %a
80; CHECK: call void @useBool(i1 %r)
81  call void @useBool(i1 %r)
82
83  %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
84  %r2 = icmp eq i8* %b2, %a
85; CHECK: call void @useBool(i1 %r2)
86  call void @useBool(i1 %r2)
87
88  ret void
89}
90
91declare void @use(i8* readonly)
92declare void @useBool(i1)
93
94declare void @clobber(i8*)
95; CHECK: Function Attrs: inaccessiblememonly nofree nosync nounwind speculatable willreturn{{$}}
96; CHECK-NEXT: declare i8* @llvm.launder.invariant.group.p0i8(i8*)
97declare i8* @llvm.launder.invariant.group.p0i8(i8*)
98
99; CHECK: Function Attrs: nofree nosync nounwind readnone speculatable willreturn{{$}}
100; CHECK-NEXT: declare i8* @llvm.strip.invariant.group.p0i8(i8*)
101declare i8* @llvm.strip.invariant.group.p0i8(i8*)
102
103
104!0 = !{}
105