forked from OSchip/llvm-project
[ARMv8] Implement the new DMB/DSB operands.
This removes the custom ISD Node: MEMBARRIER and replaces it with an intrinsic. llvm-svn: 190055
This commit is contained in:
parent
9a53c7f40d
commit
926d3f5809
|
@ -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
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ namespace llvm {
|
|||
|
||||
DYN_ALLOC, // Dynamic allocation on the stack.
|
||||
|
||||
MEMBARRIER, // Memory barrier (DMB)
|
||||
MEMBARRIER_MCR, // Memory barrier (MCR)
|
||||
|
||||
PRELOAD, // Preload
|
||||
|
|
|
@ -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<i32> {
|
|||
// 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2521,7 +2521,7 @@ void ARMOperand::print(raw_ostream &OS) const {
|
|||
getImm()->print(OS);
|
||||
break;
|
||||
case k_MemBarrierOpt:
|
||||
OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
|
||||
OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt(), false) << ">";
|
||||
break;
|
||||
case k_InstSyncBarrierOpt:
|
||||
OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">";
|
||||
|
@ -3466,18 +3466,27 @@ parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
|||
Opt = StringSwitch<unsigned>(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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue