mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
Port memory barriers intrinsics to AArch64
Memory barrier __builtin_arm_[dmb, dsb, isb] intrinsics are required to implement their corresponding ACLE and MSVC intrinsics. This patch ports ARM dmb, dsb, isb intrinsic to AArch64. Differential Revision: http://reviews.llvm.org/D4520 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213247 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8f69856b52
commit
f33a30cdd0
@ -43,6 +43,13 @@ def int_aarch64_hint : Intrinsic<[], [llvm_i32_ty]>;
|
||||
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]>;
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -539,6 +539,11 @@ def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
|
||||
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<i32>, ImmLeaf<i32, [{
|
||||
return ((uint32_t)Imm) < 16;
|
||||
}]>;
|
||||
|
||||
// An arithmetic shifter operand:
|
||||
// {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
|
||||
// {5-0} - imm6
|
||||
@ -821,8 +826,9 @@ def barrier_op : Operand<i32> {
|
||||
let PrintMethod = "printBarrierOption";
|
||||
let ParserMatchClass = BarrierAsmOperand;
|
||||
}
|
||||
class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
|
||||
: SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
|
||||
class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
|
||||
list<dag> pattern = []>
|
||||
: SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
|
||||
Sched<[WriteBarrier]> {
|
||||
bits<4> CRm;
|
||||
let Inst{20-12} = 0b000110011;
|
||||
|
@ -331,13 +331,23 @@ def : InstAlias<"wfi", (HINT 0b011)>;
|
||||
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<imm0_15, 0b010, "clrex">;
|
||||
|
||||
def DMB : CRmSystemI<barrier_op, 0b101, "dmb">;
|
||||
def DSB : CRmSystemI<barrier_op, 0b100, "dsb">;
|
||||
def ISB : CRmSystemI<barrier_op, 0b110, "isb">;
|
||||
// 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<barrier_op, 0b101, "dmb",
|
||||
[(int_aarch64_dmb (i32 imm32_0_15:$CRm))]>;
|
||||
|
||||
def DSB : CRmSystemI<barrier_op, 0b100, "dsb",
|
||||
[(int_aarch64_dsb (i32 imm32_0_15:$CRm))]>;
|
||||
|
||||
def ISB : CRmSystemI<barrier_op, 0b110, "isb",
|
||||
[(int_aarch64_isb (i32 imm32_0_15:$CRm))]>;
|
||||
}
|
||||
|
||||
def : InstAlias<"clrex", (CLREX 0xf)>;
|
||||
def : InstAlias<"isb", (ISB 0xf)>;
|
||||
|
||||
|
57
test/CodeGen/AArch64/intrinsics-memory-barrier.ll
Normal file
57
test/CodeGen/AArch64/intrinsics-memory-barrier.ll
Normal file
@ -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)
|
Loading…
x
Reference in New Issue
Block a user