| ; 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 |
| } |
| |