| ; RUN: opt -S -passes=early-cse -earlycse-debug-hash < %s | FileCheck %s |
| ; RUN: opt -S -passes=gvn < %s | FileCheck %s |
| ; RUN: opt -S -passes=newgvn < %s | FileCheck %s |
| |
| ; These tests checks if passes with CSE functionality can do CSE on |
| ; launder.invariant.group, that is prohibited if there is a memory clobber |
| ; between barriers call. |
| |
| ; CHECK-LABEL: define i8 @optimizable() |
| define i8 @optimizable() { |
| entry: |
| %ptr = alloca i8 |
| store i8 42, ptr %ptr, !invariant.group !0 |
| ; CHECK: call ptr @llvm.launder.invariant.group.p0 |
| %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) |
| ; FIXME: This one could be CSE |
| ; CHECK: call ptr @llvm.launder.invariant.group |
| %ptr3 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) |
| ; CHECK: call void @clobber(ptr {{.*}}%ptr) |
| call void @clobber(ptr %ptr) |
| |
| ; CHECK: call void @use(ptr {{.*}}%ptr2) |
| call void @use(ptr %ptr2) |
| ; CHECK: call void @use(ptr {{.*}}%ptr3) |
| call void @use(ptr %ptr3) |
| ; CHECK: load i8, ptr %ptr3, {{.*}}!invariant.group |
| %v = load i8, ptr %ptr3, !invariant.group !0 |
| |
| ret i8 %v |
| } |
| |
| ; CHECK-LABEL: define i8 @unoptimizable() |
| define i8 @unoptimizable() { |
| entry: |
| %ptr = alloca i8 |
| store i8 42, ptr %ptr, !invariant.group !0 |
| ; CHECK: call ptr @llvm.launder.invariant.group.p0 |
| %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) |
| call void @clobber(ptr %ptr) |
| ; CHECK: call ptr @llvm.launder.invariant.group.p0 |
| %ptr3 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) |
| ; CHECK: call void @clobber(ptr {{.*}}%ptr) |
| call void @clobber(ptr %ptr) |
| ; CHECK: call void @use(ptr {{.*}}%ptr2) |
| call void @use(ptr %ptr2) |
| ; CHECK: call void @use(ptr {{.*}}%ptr3) |
| call void @use(ptr %ptr3) |
| ; CHECK: load i8, ptr %ptr3, {{.*}}!invariant.group |
| %v = load i8, ptr %ptr3, !invariant.group !0 |
| |
| ret i8 %v |
| } |
| |
| ; CHECK-LABEL: define i8 @unoptimizable2() |
| define i8 @unoptimizable2() { |
| %ptr = alloca i8 |
| store i8 42, ptr %ptr, !invariant.group !0 |
| ; CHECK: call ptr @llvm.launder.invariant.group |
| %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) |
| store i8 43, ptr %ptr |
| ; CHECK: call ptr @llvm.launder.invariant.group |
| %ptr3 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) |
| ; CHECK: call void @clobber(ptr {{.*}}%ptr) |
| call void @clobber(ptr %ptr) |
| ; CHECK: call void @use(ptr {{.*}}%ptr2) |
| call void @use(ptr %ptr2) |
| ; CHECK: call void @use(ptr {{.*}}%ptr3) |
| call void @use(ptr %ptr3) |
| ; CHECK: load i8, ptr %ptr3, {{.*}}!invariant.group |
| %v = load i8, ptr %ptr3, !invariant.group !0 |
| ret i8 %v |
| } |
| |
| ; This test check if optimizer is not proving equality based on mustalias |
| ; CHECK-LABEL: define void @dontProveEquality(ptr %a) |
| define void @dontProveEquality(ptr %a) { |
| %b = call ptr @llvm.launder.invariant.group.p0(ptr %a) |
| %r = icmp eq ptr %b, %a |
| ; CHECK: call void @useBool(i1 %r) |
| call void @useBool(i1 %r) |
| |
| %b2 = call ptr @llvm.strip.invariant.group.p0(ptr %a) |
| %r2 = icmp eq ptr %b2, %a |
| ; CHECK: call void @useBool(i1 %r2) |
| call void @useBool(i1 %r2) |
| |
| ret void |
| } |
| |
| declare void @use(ptr readonly) |
| declare void @useBool(i1) |
| |
| declare void @clobber(ptr) |
| ; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite){{$}} |
| ; CHECK-NEXT: declare ptr @llvm.launder.invariant.group.p0(ptr) |
| declare ptr @llvm.launder.invariant.group.p0(ptr) |
| |
| ; CHECK: Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none){{$}} |
| ; CHECK-NEXT: declare ptr @llvm.strip.invariant.group.p0(ptr) |
| declare ptr @llvm.strip.invariant.group.p0(ptr) |
| |
| |
| !0 = !{} |