; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s ; ARM64 dmb intrinsics target triple = "aarch64-unknown-linux-gnu" declare void @llvm.aarch64.dmb(i32) declare void @llvm.aarch64.dsb(i32) declare void @clobber() declare void @pure() memory(none) willreturn nounwind declare i32 @llvm.ctlz.i32(i32, i1) define void @simple() #0 { ; CHECK-LABEL: define void @simple() { ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; call void @llvm.aarch64.dmb(i32 10) call void @llvm.aarch64.dmb(i32 10) ret void } ; dmb ish (0xb) is technically stronger than ishst (0xa) but we don't merge for now define void @simple_nonmatching() #0 { ; CHECK-LABEL: define void @simple_nonmatching() { ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 11) ; CHECK-NEXT: ret void ; call void @llvm.aarch64.dmb(i32 10) call void @llvm.aarch64.dmb(i32 11) ret void } define ptr @simple_safe_instruction(ptr %p) #0 { ; CHECK-LABEL: define ptr @simple_safe_instruction( ; CHECK-SAME: ptr [[P:%.*]]) { ; CHECK-NEXT: [[RES:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret ptr [[RES]] ; call void @llvm.aarch64.dmb(i32 10) %res = getelementptr inbounds i8, ptr %p, i32 8 call void @llvm.aarch64.dmb(i32 10) ret ptr %res } define i32 @simple_safe_intrinsic(i32 %n) #0 { ; CHECK-LABEL: define i32 @simple_safe_intrinsic( ; CHECK-SAME: i32 [[N:%.*]]) { ; CHECK-NEXT: [[RES:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[N]], i1 false) ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret i32 [[RES]] ; call void @llvm.aarch64.dmb(i32 10) %res = call i32 @llvm.ctlz.i32(i32 %n, i1 false) call void @llvm.aarch64.dmb(i32 10) ret i32 %res } define void @simple_unsafe_intrinsic() #0 { ; CHECK-LABEL: define void @simple_unsafe_intrinsic() { ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: call void @llvm.aarch64.dsb(i32 10) ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; call void @llvm.aarch64.dmb(i32 10) call void @llvm.aarch64.dsb(i32 10) call void @llvm.aarch64.dmb(i32 10) ret void } define void @simple_safe_unsafe_instruction(ptr %p) #0 { ; CHECK-LABEL: define void @simple_safe_unsafe_instruction( ; CHECK-SAME: ptr [[P:%.*]]) { ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: store i32 42, ptr [[P]], align 4 ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; call void @llvm.aarch64.dmb(i32 10) store i32 42, ptr %p call void @llvm.aarch64.dmb(i32 10) ret void } define void @simple_safe_unsafe_call(ptr %p) #0 { ; CHECK-LABEL: define void @simple_safe_unsafe_call( ; CHECK-SAME: ptr [[P:%.*]]) { ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: call void @clobber() ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; call void @llvm.aarch64.dmb(i32 10) call void @clobber() call void @llvm.aarch64.dmb(i32 10) ret void } define void @simple_safe_safe_call(ptr %p) #0 { ; CHECK-LABEL: define void @simple_safe_safe_call( ; CHECK-SAME: ptr [[P:%.*]]) { ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; call void @llvm.aarch64.dmb(i32 10) call void @pure() call void @llvm.aarch64.dmb(i32 10) ret void } define void @multiple_bbs1(i1 %f) #0 { ; CHECK-LABEL: define void @multiple_bbs1( ; CHECK-SAME: i1 [[F:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]] ; CHECK: [[BB_T]]: ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[BB_F]]: ; CHECK-NEXT: br label %[[EXIT]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; entry: br i1 %f, label %bb_t, label %bb_f bb_t: call void @llvm.aarch64.dmb(i32 10) br label %exit bb_f: call void @llvm.aarch64.dmb(i32 10) br label %exit exit: call void @llvm.aarch64.dmb(i32 10) ret void } define void @multiple_bbs2(i1 %f) #0 { ; CHECK-LABEL: define void @multiple_bbs2( ; CHECK-SAME: i1 [[F:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]] ; CHECK: [[BB_T]]: ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[BB_F]]: ; CHECK-NEXT: br label %[[EXIT]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; entry: br i1 %f, label %bb_t, label %bb_f bb_t: call void @llvm.aarch64.dmb(i32 10) br label %exit bb_f: br label %exit exit: call void @llvm.aarch64.dmb(i32 10) ret void } define void @multiple_bbs3(i1 %f, ptr %p) #0 { ; CHECK-LABEL: define void @multiple_bbs3( ; CHECK-SAME: i1 [[F:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]] ; CHECK: [[BB_T]]: ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[BB_F]]: ; CHECK-NEXT: store i32 42, ptr [[P]], align 4 ; CHECK-NEXT: br label %[[EXIT]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; entry: br i1 %f, label %bb_t, label %bb_f bb_t: call void @llvm.aarch64.dmb(i32 10) br label %exit bb_f: store i32 42, ptr %p br label %exit exit: call void @llvm.aarch64.dmb(i32 10) ret void } define void @multiple_bbs_unsafe(i1 %f, ptr %p) #0 { ; CHECK-LABEL: define void @multiple_bbs_unsafe( ; CHECK-SAME: i1 [[F:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: br i1 [[F]], label %[[BB_T:.*]], label %[[BB_F:.*]] ; CHECK: [[BB_T]]: ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: store i32 42, ptr [[P]], align 4 ; CHECK-NEXT: br label %[[EXIT:.*]] ; CHECK: [[BB_F]]: ; CHECK-NEXT: br label %[[EXIT]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: call void @llvm.aarch64.dmb(i32 10) ; CHECK-NEXT: ret void ; entry: br i1 %f, label %bb_t, label %bb_f bb_t: call void @llvm.aarch64.dmb(i32 10) store i32 42, ptr %p br label %exit bb_f: call void @llvm.aarch64.dmb(i32 10) br label %exit exit: call void @llvm.aarch64.dmb(i32 10) ret void }