From: Joey Gouly Date: Thu, 5 Sep 2013 15:35:24 +0000 (+0000) Subject: [ARMv8] Implement the new DMB/DSB operands. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=4897151df698197f0eb5c4085545312dbb20c94d;p=oota-llvm.git [ARMv8] Implement the new DMB/DSB operands. This removes the custom ISD Node: MEMBARRIER and replaces it with an intrinsic. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190055 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index e29a01b011a..80affe6bff4 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -44,6 +44,11 @@ def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty]>; def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; +//===----------------------------------------------------------------------===// +// Data barrier instructions +def int_arm_dmb : Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dsb : Intrinsic<[], [llvm_i32_ty]>; + //===----------------------------------------------------------------------===// // VFP diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index df9c78a60d3..94270eda5ff 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1010,7 +1010,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::DYN_ALLOC: return "ARMISD::DYN_ALLOC"; - case ARMISD::MEMBARRIER: return "ARMISD::MEMBARRIER"; case ARMISD::MEMBARRIER_MCR: return "ARMISD::MEMBARRIER_MCR"; case ARMISD::PRELOAD: return "ARMISD::PRELOAD"; @@ -2610,7 +2609,8 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, Domain = ARM_MB::ISHST; } - return DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0), + return DAG.getNode(ISD::INTRINSIC_VOID, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(Intrinsic::arm_dmb, MVT::i32), DAG.getConstant(Domain, MVT::i32)); } diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index be7811f8feb..fca9e0e5249 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -94,7 +94,6 @@ namespace llvm { DYN_ALLOC, // Dynamic allocation on the stack. - MEMBARRIER, // Memory barrier (DMB) MEMBARRIER_MCR, // Memory barrier (MCR) PRELOAD, // Preload diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 5ebe97da7b0..c9bad1cd355 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -165,8 +165,6 @@ def ARMeh_sjlj_longjmp: SDNode<"ARMISD::EH_SJLJ_LONGJMP", SDT_ARMEH_SJLJ_Longjmp, [SDNPHasChain, SDNPSideEffect]>; -def ARMMemBarrier : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER, - [SDNPHasChain, SDNPSideEffect]>; def ARMMemBarrierMCR : SDNode<"ARMISD::MEMBARRIER_MCR", SDT_ARMMEMBARRIER, [SDNPHasChain, SDNPSideEffect]>; def ARMPreload : SDNode<"ARMISD::PRELOAD", SDT_ARMPREFETCH, @@ -4265,7 +4263,7 @@ def instsyncb_opt : Operand { // memory barriers protect the atomic sequences let hasSideEffects = 1 in { def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, - "dmb", "\t$opt", [(ARMMemBarrier (i32 imm:$opt))]>, + "dmb", "\t$opt", [(int_arm_dmb (i32 imm0_15:$opt))]>, Requires<[IsARM, HasDB]> { bits<4> opt; let Inst{31-4} = 0xf57ff05; @@ -4274,7 +4272,7 @@ def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, } def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, - "dsb", "\t$opt", []>, + "dsb", "\t$opt", [(int_arm_dsb (i32 imm0_15:$opt))]>, Requires<[IsARM, HasDB]> { bits<4> opt; let Inst{31-4} = 0xf57ff04; diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 5ba14cfa9f5..83edf16e07a 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -3155,7 +3155,7 @@ def t2MOVCCi32imm // memory barriers protect the atomic sequences let hasSideEffects = 1 in { def t2DMB : T2I<(outs), (ins memb_opt:$opt), NoItinerary, - "dmb", "\t$opt", [(ARMMemBarrier (i32 imm:$opt))]>, + "dmb", "\t$opt", [(int_arm_dmb (i32 imm0_15:$opt))]>, Requires<[HasDB]> { bits<4> opt; let Inst{31-4} = 0xf3bf8f5; @@ -3164,7 +3164,8 @@ def t2DMB : T2I<(outs), (ins memb_opt:$opt), NoItinerary, } def t2DSB : T2I<(outs), (ins memb_opt:$opt), NoItinerary, - "dsb", "\t$opt", []>, Requires<[HasDB]> { + "dsb", "\t$opt", [(int_arm_dsb (i32 imm0_15:$opt))]>, + Requires<[HasDB]> { bits<4> opt; let Inst{31-4} = 0xf3bf8f4; let Inst{3-0} = opt; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 9344810aa5b..cfa24f9f168 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -2521,7 +2521,7 @@ void ARMOperand::print(raw_ostream &OS) const { getImm()->print(OS); break; case k_MemBarrierOpt: - OS << ""; + OS << ""; break; case k_InstSyncBarrierOpt: OS << ""; @@ -3466,18 +3466,27 @@ parseMemBarrierOptOperand(SmallVectorImpl &Operands) { Opt = StringSwitch(OptStr.slice(0, OptStr.size()).lower()) .Case("sy", ARM_MB::SY) .Case("st", ARM_MB::ST) + .Case("ld", ARM_MB::LD) .Case("sh", ARM_MB::ISH) .Case("ish", ARM_MB::ISH) .Case("shst", ARM_MB::ISHST) .Case("ishst", ARM_MB::ISHST) + .Case("ishld", ARM_MB::ISHLD) .Case("nsh", ARM_MB::NSH) .Case("un", ARM_MB::NSH) .Case("nshst", ARM_MB::NSHST) + .Case("nshld", ARM_MB::NSHLD) .Case("unst", ARM_MB::NSHST) .Case("osh", ARM_MB::OSH) .Case("oshst", ARM_MB::OSHST) + .Case("oshld", ARM_MB::OSHLD) .Default(~0U); + // ishld, oshld, nshld and ld are only available from ARMv8. + if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD || + Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD)) + Opt = ~0U; + if (Opt == ~0U) return MatchOperand_NoMatch; diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 8b99c17da58..82c12944f3c 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -677,7 +677,7 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI, void ARMInstPrinter::printMemBOption(const MCInst *MI, unsigned OpNum, raw_ostream &O) { unsigned val = MI->getOperand(OpNum).getImm(); - O << ARM_MB::MemBOptToString(val); + O << ARM_MB::MemBOptToString(val, (getAvailableFeatures() & ARM::HasV8Ops)); } void ARMInstPrinter::printInstSyncBOption(const MCInst *MI, unsigned OpNum, diff --git a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h index ff9917d7936..af939fc1912 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -121,41 +121,41 @@ namespace ARM_MB { // the option field for memory barrier operations. enum MemBOpt { RESERVED_0 = 0, - RESERVED_1 = 1, + OSHLD = 1, OSHST = 2, OSH = 3, RESERVED_4 = 4, - RESERVED_5 = 5, + NSHLD = 5, NSHST = 6, NSH = 7, RESERVED_8 = 8, - RESERVED_9 = 9, + ISHLD = 9, ISHST = 10, ISH = 11, RESERVED_12 = 12, - RESERVED_13 = 13, + LD = 13, ST = 14, SY = 15 }; - inline static const char *MemBOptToString(unsigned val) { + inline static const char *MemBOptToString(unsigned val, bool HasV8) { switch (val) { default: llvm_unreachable("Unknown memory operation"); case SY: return "sy"; case ST: return "st"; - case RESERVED_13: return "#0xd"; + case LD: return HasV8 ? "ld" : "#0xd"; case RESERVED_12: return "#0xc"; case ISH: return "ish"; case ISHST: return "ishst"; - case RESERVED_9: return "#0x9"; + case ISHLD: return HasV8 ? "ishld" : "#0x9"; case RESERVED_8: return "#0x8"; case NSH: return "nsh"; case NSHST: return "nshst"; - case RESERVED_5: return "#0x5"; + case NSHLD: return HasV8 ? "nshld" : "#0x5"; case RESERVED_4: return "#0x4"; case OSH: return "osh"; case OSHST: return "oshst"; - case RESERVED_1: return "#0x1"; + case OSHLD: return HasV8 ? "oshld" : "#0x1"; case RESERVED_0: return "#0x0"; } } diff --git a/test/CodeGen/ARM/intrinsics-v8.ll b/test/CodeGen/ARM/intrinsics-v8.ll new file mode 100644 index 00000000000..a6a45459e88 --- /dev/null +++ b/test/CodeGen/ARM/intrinsics-v8.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -mtriple=armv8 -mattr=+db | FileCheck %s + +define void @test() { + ; CHECK: dmb sy + call void @llvm.arm.dmb(i32 15) + ; CHECK: dmb osh + call void @llvm.arm.dmb(i32 3) + ; CHECK: dsb sy + call void @llvm.arm.dsb(i32 15) + ; CHECK: dsb ishld + call void @llvm.arm.dsb(i32 9) + ret void +} + +declare void @llvm.arm.dmb(i32) +declare void @llvm.arm.dsb(i32) diff --git a/test/MC/ARM/basic-arm-instructions-v8.s b/test/MC/ARM/basic-arm-instructions-v8.s index 130a4c52827..a447e0f22cf 100644 --- a/test/MC/ARM/basic-arm-instructions-v8.s +++ b/test/MC/ARM/basic-arm-instructions-v8.s @@ -1,6 +1,6 @@ @ New ARMv8 A32 encodings -@ RUN: llvm-mc -triple armv8 -show-encoding < %s | FileCheck %s --check-prefix=CHECK-V8 +@ RUN: not llvm-mc -triple armv8 -show-encoding -mattr=+db < %s | FileCheck %s --check-prefix=CHECK-V8 @ RUN: not llvm-mc -triple armv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7 @ HLT @@ -15,3 +15,38 @@ hltal #0 @ CHECK-V8: hlt #0 @ encoding: [0x70,0x00,0x00,0xe1] @ CHECK-V7: error: instruction requires: armv8 + +@------------------------------------------------------------------------------ +@ DMB (v8 barriers) +@------------------------------------------------------------------------------ + dmb ishld + dmb oshld + dmb nshld + dmb ld + dmb #20 + +@ CHECK-V8: dmb ishld @ encoding: [0x59,0xf0,0x7f,0xf5] +@ CHECK-V8: dmb oshld @ encoding: [0x51,0xf0,0x7f,0xf5] +@ CHECK-V8: dmb nshld @ encoding: [0x55,0xf0,0x7f,0xf5] +@ CHECK-V8: dmb ld @ encoding: [0x5d,0xf0,0x7f,0xf5] +@ CHECK-V7: error: invalid operand for instruction +@ CHECK-V7: error: invalid operand for instruction +@ CHECK-V7: error: invalid operand for instruction +@ CHECK-V7: error: invalid operand for instruction +@ CHECK-V7: error: immediate value out of range + +@------------------------------------------------------------------------------ +@ DSB (v8 barriers) +@------------------------------------------------------------------------------ + dsb ishld + dsb oshld + dsb nshld + dsb ld + +@ CHECK-V8: dsb ishld @ encoding: [0x49,0xf0,0x7f,0xf5] +@ CHECK-V8: dsb oshld @ encoding: [0x41,0xf0,0x7f,0xf5] +@ CHECK-V8: dsb nshld @ encoding: [0x45,0xf0,0x7f,0xf5] +@ CHECK-V8: dsb ld @ encoding: [0x4d,0xf0,0x7f,0xf5] +@ CHECK-V7: error: invalid operand for instruction +@ CHECK-V7: error: invalid operand for instruction +@ CHECK-V7: error: invalid operand for instruction