Index: llvm/trunk/include/llvm/IR/IntrinsicsAArch64.td =================================================================== --- llvm/trunk/include/llvm/IR/IntrinsicsAArch64.td +++ llvm/trunk/include/llvm/IR/IntrinsicsAArch64.td @@ -43,6 +43,13 @@ def int_aarch64_rbit : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoMem]>; +//===----------------------------------------------------------------------===// +// Data Barrier Instructions + +def int_aarch64_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; +def int_aarch64_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; +def int_aarch64_isb : GCCBuiltin<"__builtin_arm_isb">, Intrinsic<[], [llvm_i32_ty]>; + } //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td @@ -539,6 +539,11 @@ let ParserMatchClass = Imm0_7Operand; } +// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15] +def imm32_0_15 : Operand, ImmLeaf; + // An arithmetic shifter operand: // {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr // {5-0} - imm6 @@ -821,8 +826,9 @@ let PrintMethod = "printBarrierOption"; let ParserMatchClass = BarrierAsmOperand; } -class CRmSystemI opc, string asm> - : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">, +class CRmSystemI opc, string asm, + list pattern = []> + : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>, Sched<[WriteBarrier]> { bits<4> CRm; let Inst{20-12} = 0b000110011; Index: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td @@ -331,13 +331,23 @@ def : InstAlias<"sev", (HINT 0b100)>; def : InstAlias<"sevl", (HINT 0b101)>; - // As far as LLVM is concerned this writes to the system's exclusive monitors. +// As far as LLVM is concerned this writes to the system's exclusive monitors. let mayLoad = 1, mayStore = 1 in def CLREX : CRmSystemI; -def DMB : CRmSystemI; -def DSB : CRmSystemI; -def ISB : CRmSystemI; +// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot +// model patterns with sufficiently fine granularity. +let mayLoad = ?, mayStore = ? in { +def DMB : CRmSystemI; + +def DSB : CRmSystemI; + +def ISB : CRmSystemI; +} + def : InstAlias<"clrex", (CLREX 0xf)>; def : InstAlias<"isb", (ISB 0xf)>; Index: llvm/trunk/test/CodeGen/AArch64/intrinsics-memory-barrier.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/intrinsics-memory-barrier.ll +++ llvm/trunk/test/CodeGen/AArch64/intrinsics-memory-barrier.ll @@ -0,0 +1,57 @@ +; RUN: llc < %s -mtriple=aarch64-eabi -O=3 | FileCheck %s + +define void @test() { + ; CHECK: dmb sy + call void @llvm.aarch64.dmb(i32 15) + ; CHECK: dmb osh + call void @llvm.aarch64.dmb(i32 3) + ; CHECK: dsb sy + call void @llvm.aarch64.dsb(i32 15) + ; CHECK: dsb ishld + call void @llvm.aarch64.dsb(i32 9) + ; CHECK: isb + call void @llvm.aarch64.isb(i32 15) + ret void +} + +; Important point is that the compiler should not reorder memory access +; instructions around DMB. +; Failure to do so, two STRs will collapse into one STP. +define void @test_dmb_reordering(i32 %a, i32 %b, i32* %d) { + store i32 %a, i32* %d ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}] + + call void @llvm.aarch64.dmb(i32 15); CHECK: dmb sy + + %d1 = getelementptr i32* %d, i64 1 + store i32 %b, i32* %d1 ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #4] + + ret void +} + +; Similarly for DSB. +define void @test_dsb_reordering(i32 %a, i32 %b, i32* %d) { + store i32 %a, i32* %d ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}] + + call void @llvm.aarch64.dsb(i32 15); CHECK: dsb sy + + %d1 = getelementptr i32* %d, i64 1 + store i32 %b, i32* %d1 ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #4] + + ret void +} + +; And ISB. +define void @test_isb_reordering(i32 %a, i32 %b, i32* %d) { + store i32 %a, i32* %d ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}] + + call void @llvm.aarch64.isb(i32 15); CHECK: isb + + %d1 = getelementptr i32* %d, i64 1 + store i32 %b, i32* %d1 ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #4] + + ret void +} + +declare void @llvm.aarch64.dmb(i32) +declare void @llvm.aarch64.dsb(i32) +declare void @llvm.aarch64.isb(i32)