; RUN: opt -S -early-cse < %s | FileCheck %s ; RUN: opt -S -gvn < %s | FileCheck %s ; RUN: opt -S -newgvn < %s | FileCheck %s ; RUN: opt -S -O3 < %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, i8* %ptr, !invariant.group !0 ; CHECK: call i8* @llvm.launder.invariant.group.p0i8 %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) ; FIXME: This one could be CSE ; CHECK: call i8* @llvm.launder.invariant.group %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) ; CHECK: call void @clobber(i8* {{.*}}%ptr) call void @clobber(i8* %ptr) ; CHECK: call void @use(i8* {{.*}}%ptr2) call void @use(i8* %ptr2) ; CHECK: call void @use(i8* {{.*}}%ptr3) call void @use(i8* %ptr3) ; CHECK: load i8, i8* %ptr3, {{.*}}!invariant.group %v = load i8, i8* %ptr3, !invariant.group !0 ret i8 %v } ; CHECK-LABEL: define i8 @unoptimizable() define i8 @unoptimizable() { entry: %ptr = alloca i8 store i8 42, i8* %ptr, !invariant.group !0 ; CHECK: call i8* @llvm.launder.invariant.group.p0i8 %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) call void @clobber(i8* %ptr) ; CHECK: call i8* @llvm.launder.invariant.group.p0i8 %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) ; CHECK: call void @clobber(i8* {{.*}}%ptr) call void @clobber(i8* %ptr) ; CHECK: call void @use(i8* {{.*}}%ptr2) call void @use(i8* %ptr2) ; CHECK: call void @use(i8* {{.*}}%ptr3) call void @use(i8* %ptr3) ; CHECK: load i8, i8* %ptr3, {{.*}}!invariant.group %v = load i8, i8* %ptr3, !invariant.group !0 ret i8 %v } ; CHECK-LABEL: define i8 @unoptimizable2() define i8 @unoptimizable2() { %ptr = alloca i8 store i8 42, i8* %ptr, !invariant.group !0 ; CHECK: call i8* @llvm.launder.invariant.group %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) store i8 43, i8* %ptr ; CHECK: call i8* @llvm.launder.invariant.group %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr) ; CHECK: call void @clobber(i8* {{.*}}%ptr) call void @clobber(i8* %ptr) ; CHECK: call void @use(i8* {{.*}}%ptr2) call void @use(i8* %ptr2) ; CHECK: call void @use(i8* {{.*}}%ptr3) call void @use(i8* %ptr3) ; CHECK: load i8, i8* %ptr3, {{.*}}!invariant.group %v = load i8, i8* %ptr3, !invariant.group !0 ret i8 %v } ; This test check if optimizer is not proving equality based on mustalias ; CHECK-LABEL: define void @dontProveEquality(i8* %a) define void @dontProveEquality(i8* %a) { %b = call i8* @llvm.launder.invariant.group.p0i8(i8* %a) %r = icmp eq i8* %b, %a ; CHECK: call void @useBool(i1 %r) call void @useBool(i1 %r) %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a) %r2 = icmp eq i8* %b2, %a ; CHECK: call void @useBool(i1 %r2) call void @useBool(i1 %r2) ret void } declare void @use(i8* readonly) declare void @useBool(i1) declare void @clobber(i8*) ; CHECK: Function Attrs: inaccessiblememonly nounwind speculatable{{$}} ; CHECK-NEXT: declare i8* @llvm.launder.invariant.group.p0i8(i8*) declare i8* @llvm.launder.invariant.group.p0i8(i8*) ; CHECK: Function Attrs: nounwind readnone speculatable{{$}} ; CHECK-NEXT: declare i8* @llvm.strip.invariant.group.p0i8(i8*) declare i8* @llvm.strip.invariant.group.p0i8(i8*) !0 = !{}