| ; RUN: opt -passes=instcombine -S %s | FileCheck %s |
| |
| ; Make sure we collapse the fences in this case |
| |
| ; CHECK-LABEL: define void @tinkywinky |
| ; CHECK-NEXT: fence seq_cst |
| ; CHECK-NEXT: fence syncscope("singlethread") acquire |
| ; CHECK-NEXT: ret void |
| ; CHECK-NEXT: } |
| |
| define void @tinkywinky() { |
| fence seq_cst |
| fence seq_cst |
| fence seq_cst |
| fence syncscope("singlethread") acquire |
| fence syncscope("singlethread") acquire |
| fence syncscope("singlethread") acquire |
| ret void |
| } |
| |
| ; Arbitrary target dependent scope |
| ; Is this transform really needed? |
| ; CHECK-LABEL: test_target_dependent_scope |
| ; CHECK-NEXT: fence syncscope("MSP430") acquire |
| ; CHECK-NEXT: ret void |
| define void @test_target_dependent_scope() { |
| fence syncscope("MSP430") acquire |
| fence syncscope("MSP430") acquire |
| ret void |
| } |
| |
| ; CHECK-LABEL: define void @dipsy |
| ; CHECK-NEXT: fence seq_cst |
| ; CHECK-NEXT: fence syncscope("singlethread") seq_cst |
| ; CHECK-NEXT: ret void |
| ; CHECK-NEXT: } |
| |
| define void @dipsy() { |
| fence seq_cst |
| fence syncscope("singlethread") seq_cst |
| ret void |
| } |
| |
| ; CHECK-LABEL: define void @patatino |
| ; CHECK-NEXT: fence seq_cst |
| ; CHECK-NEXT: ret void |
| ; CHECK-NEXT: } |
| |
| define void @patatino() { |
| fence acquire |
| fence seq_cst |
| fence acquire |
| fence seq_cst |
| ret void |
| } |
| |
| ; CHECK-LABEL: define void @weaker_fence_1 |
| ; CHECK-NEXT: fence seq_cst |
| ; CHECK-NEXT: ret void |
| define void @weaker_fence_1() { |
| fence seq_cst |
| fence release |
| fence seq_cst |
| ret void |
| } |
| |
| ; CHECK-LABEL: define void @weaker_fence_2 |
| ; CHECK-NEXT: fence seq_cst |
| ; CHECK-NEXT: ret void |
| define void @weaker_fence_2() { |
| fence seq_cst |
| fence release |
| fence seq_cst |
| fence acquire |
| ret void |
| } |
| |
| ; Although acquire is a weaker ordering than seq_cst, it has a system scope, |
| ; compare to singlethread scope in seq_cst. |
| ; CHECK-LABEL: acquire_global_neg_test |
| ; CHECK-NEXT: fence acquire |
| ; CHECK-NEXT: fence syncscope("singlethread") seq_cst |
| define void @acquire_global_neg_test() { |
| fence acquire |
| fence acquire |
| fence syncscope("singlethread") seq_cst |
| ret void |
| } |
| |
| ; CHECK-LABEL: acquire_single_thread_scope |
| ; CHECK-NEXT: fence syncscope("singlethread") seq_cst |
| define void @acquire_single_thread_scope() { |
| fence syncscope("singlethread") acquire |
| fence syncscope("singlethread") seq_cst |
| ret void |
| } |
| |
| ; CHECK-LABEL: define void @debug |
| ; CHECK-NOT: fence |
| ; CHECK: call void @llvm.dbg.value |
| ; CHECK: fence seq_cst |
| define void @debug() { |
| fence seq_cst |
| tail call void @llvm.dbg.value(metadata i32 5, metadata !1, metadata !DIExpression()), !dbg !9 |
| fence seq_cst |
| ret void |
| } |
| |
| declare void @llvm.dbg.value(metadata, metadata, metadata) |
| |
| !llvm.dbg.cu = !{!0} |
| !llvm.module.flags = !{!5, !6, !7, !8} |
| |
| !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "Me", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: null, retainedTypes: null, imports: null) |
| !1 = !DILocalVariable(name: "", arg: 1, scope: !2, file: null, line: 1, type: null) |
| !2 = distinct !DISubprogram(name: "debug", linkageName: "debug", scope: null, file: null, line: 0, type: null, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0) |
| !3 = !DIFile(filename: "consecutive-fences.ll", directory: "") |
| !5 = !{i32 2, !"Dwarf Version", i32 4} |
| !6 = !{i32 2, !"Debug Info Version", i32 3} |
| !7 = !{i32 1, !"wchar_size", i32 4} |
| !8 = !{i32 7, !"PIC Level", i32 2} |
| !9 = !DILocation(line: 0, column: 0, scope: !2) |