[ARM] Add ARMv8-A semaphore/atomic instructions to ARMv8-M Baseline/Mainline

llvm-svn: 257882
This commit is contained in:
Bradley Smith 2016-01-15 10:26:51 +00:00
parent a1189106d5
commit 433c22e35c
7 changed files with 102 additions and 14 deletions

View File

@ -393,7 +393,7 @@ def ARMv8mBaseline : Architecture<"armv8-m.base", "ARMv8mBaseline",
FeatureNoARM,
FeatureDB,
FeatureHWDiv,
FeatureV7Exclusives,
FeatureV7Clrex,
FeatureAcquireRelease,
FeatureMClass]>;

View File

@ -3056,7 +3056,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
SDLoc dl(N);
SDValue Chain = N->getOperand(0);
SDValue MemAddr = N->getOperand(2);
bool isThumb = Subtarget->isThumb() && Subtarget->hasThumb2();
bool isThumb = Subtarget->isThumb() && Subtarget->hasV8MBaselineOps();
bool IsAcquire = IntNo == Intrinsic::arm_ldaexd;
unsigned NewOpc = isThumb ? (IsAcquire ? ARM::t2LDAEXD : ARM::t2LDREXD)

View File

@ -839,7 +839,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
// non-atomic form.
if (TM.Options.ThreadModel == ThreadModel::Single)
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
else if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) {
else if (Subtarget->hasAnyDataBarrier() && (!Subtarget->isThumb() ||
Subtarget->hasV8MBaselineOps())) {
// ATOMIC_FENCE needs custom lowering; the others should have been expanded
// to ldrex/strex loops already.
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);

View File

@ -3291,15 +3291,18 @@ let mayLoad = 1 in {
def t2LDREXB : T2I_ldrex<0b0100, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"ldrexb", "\t$Rt, $addr", "",
[(set rGPR:$Rt, (ldrex_1 addr_offset_none:$addr))]>;
[(set rGPR:$Rt, (ldrex_1 addr_offset_none:$addr))]>,
Requires<[IsThumb, HasV8MBaseline]>;
def t2LDREXH : T2I_ldrex<0b0101, (outs rGPR:$Rt), (ins addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"ldrexh", "\t$Rt, $addr", "",
[(set rGPR:$Rt, (ldrex_2 addr_offset_none:$addr))]>;
[(set rGPR:$Rt, (ldrex_2 addr_offset_none:$addr))]>,
Requires<[IsThumb, HasV8MBaseline]>;
def t2LDREX : Thumb2I<(outs rGPR:$Rt), (ins t2addrmode_imm0_1020s4:$addr),
AddrModeNone, 4, NoItinerary,
"ldrex", "\t$Rt, $addr", "",
[(set rGPR:$Rt, (ldrex_4 t2addrmode_imm0_1020s4:$addr))]> {
[(set rGPR:$Rt, (ldrex_4 t2addrmode_imm0_1020s4:$addr))]>,
Requires<[IsThumb, HasV8MBaseline]> {
bits<4> Rt;
bits<12> addr;
let Inst{31-27} = 0b11101;
@ -3363,20 +3366,23 @@ def t2STREXB : T2I_strex<0b0100, (outs rGPR:$Rd),
AddrModeNone, 4, NoItinerary,
"strexb", "\t$Rd, $Rt, $addr", "",
[(set rGPR:$Rd,
(strex_1 rGPR:$Rt, addr_offset_none:$addr))]>;
(strex_1 rGPR:$Rt, addr_offset_none:$addr))]>,
Requires<[IsThumb, HasV8MBaseline]>;
def t2STREXH : T2I_strex<0b0101, (outs rGPR:$Rd),
(ins rGPR:$Rt, addr_offset_none:$addr),
AddrModeNone, 4, NoItinerary,
"strexh", "\t$Rd, $Rt, $addr", "",
[(set rGPR:$Rd,
(strex_2 rGPR:$Rt, addr_offset_none:$addr))]>;
(strex_2 rGPR:$Rt, addr_offset_none:$addr))]>,
Requires<[IsThumb, HasV8MBaseline]>;
def t2STREX : Thumb2I<(outs rGPR:$Rd), (ins rGPR:$Rt,
t2addrmode_imm0_1020s4:$addr),
AddrModeNone, 4, NoItinerary,
"strex", "\t$Rd, $Rt, $addr", "",
[(set rGPR:$Rd,
(strex_4 rGPR:$Rt, t2addrmode_imm0_1020s4:$addr))]> {
(strex_4 rGPR:$Rt, t2addrmode_imm0_1020s4:$addr))]>,
Requires<[IsThumb, HasV8MBaseline]> {
bits<4> Rd;
bits<4> Rt;
bits<12> addr;
@ -3456,13 +3462,17 @@ def t2CLREX : T2I<(outs), (ins), NoItinerary, "clrex", "", [(int_arm_clrex)]>,
}
def : T2Pat<(and (ldrex_1 addr_offset_none:$addr), 0xff),
(t2LDREXB addr_offset_none:$addr)>;
(t2LDREXB addr_offset_none:$addr)>,
Requires<[IsThumb, HasV8MBaseline]>;
def : T2Pat<(and (ldrex_2 addr_offset_none:$addr), 0xffff),
(t2LDREXH addr_offset_none:$addr)>;
(t2LDREXH addr_offset_none:$addr)>,
Requires<[IsThumb, HasV8MBaseline]>;
def : T2Pat<(strex_1 (and GPR:$Rt, 0xff), addr_offset_none:$addr),
(t2STREXB GPR:$Rt, addr_offset_none:$addr)>;
(t2STREXB GPR:$Rt, addr_offset_none:$addr)>,
Requires<[IsThumb, HasV8MBaseline]>;
def : T2Pat<(strex_2 (and GPR:$Rt, 0xffff), addr_offset_none:$addr),
(t2STREXH GPR:$Rt, addr_offset_none:$addr)>;
(t2STREXH GPR:$Rt, addr_offset_none:$addr)>,
Requires<[IsThumb, HasV8MBaseline]>;
def : T2Pat<(and (ldaex_1 addr_offset_none:$addr), 0xff),
(t2LDAEXB addr_offset_none:$addr)>,

View File

@ -336,7 +336,7 @@ bool ARMSubtarget::enablePostRAScheduler() const {
}
bool ARMSubtarget::enableAtomicExpand() const {
return hasAnyDataBarrier() && !isThumb1Only();
return hasAnyDataBarrier() && (!isThumb() || hasV8MBaselineOps());
}
bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const {

View File

@ -1,4 +1,6 @@
; RUN: llc < %s -mtriple=thumbv7m-none-eabi -mcpu=cortex-m4 | FileCheck %s
; RUN: llc < %s -mtriple=thumbv8m.main-none-eabi | FileCheck %s
; RUN: llc < %s -mtriple=thumbv8m.base-none-eabi | FileCheck %s
; CHECK-LABEL: f0:
; CHECK-NOT: ldrexd

View File

@ -41,6 +41,37 @@ sdiv r1, r2, r3
// CHECK: udiv r1, r2, r3 @ encoding: [0xb2,0xfb,0xf3,0xf1]
udiv r1, r2, r3
// 'Exclusives from ARMv7-M'
// CHECK: clrex @ encoding: [0xbf,0xf3,0x2f,0x8f]
clrex
// CHECK: ldrex r1, [r2, #4] @ encoding: [0x52,0xe8,0x01,0x1f]
ldrex r1, [r2, #4]
// CHECK: ldrexb r1, [r2] @ encoding: [0xd2,0xe8,0x4f,0x1f]
ldrexb r1, [r2]
// CHECK: ldrexh r1, [r2] @ encoding: [0xd2,0xe8,0x5f,0x1f]
ldrexh r1, [r2]
// UNDEF-BASELINE: error: instruction requires: !armv*m thumb2
// UNDEF-MAINLINE: error: instruction requires: !armv*m
ldrexd r0, r1, [r2]
// CHECK: strex r1, r2, [r3, #4] @ encoding: [0x43,0xe8,0x01,0x21]
strex r1, r2, [r3, #4]
// CHECK: strexb r1, r2, [r3] @ encoding: [0xc3,0xe8,0x41,0x2f]
strexb r1, r2, [r3]
// CHECK: strexh r1, r2, [r3] @ encoding: [0xc3,0xe8,0x51,0x2f]
strexh r1, r2, [r3]
// UNDEF-BASELINE: error: instruction requires: !armv*m thumb2
// UNDEF-MAINLINE: error: instruction requires: !armv*m
strexd r0, r1, r2, [r3]
// 'XO generation'
// CHECK: movw r1, #65535 @ encoding: [0x4f,0xf6,0xff,0x71]
@ -48,3 +79,47 @@ movw r1, #0xffff
// CHECK: movt r1, #65535 @ encoding: [0xcf,0xf6,0xff,0x71]
movt r1, #0xffff
// 'Acquire/Release from ARMv8-A'
// CHECK: lda r1, [r2] @ encoding: [0xd2,0xe8,0xaf,0x1f]
lda r1, [r2]
// CHECK: ldab r1, [r2] @ encoding: [0xd2,0xe8,0x8f,0x1f]
ldab r1, [r2]
// CHECK: ldah r1, [r2] @ encoding: [0xd2,0xe8,0x9f,0x1f]
ldah r1, [r2]
// CHECK: stl r1, [r3] @ encoding: [0xc3,0xe8,0xaf,0x1f]
stl r1, [r3]
// CHECK: stlb r1, [r3] @ encoding: [0xc3,0xe8,0x8f,0x1f]
stlb r1, [r3]
// CHECK: stlh r1, [r3] @ encoding: [0xc3,0xe8,0x9f,0x1f]
stlh r1, [r3]
// CHECK: ldaex r1, [r2] @ encoding: [0xd2,0xe8,0xef,0x1f]
ldaex r1, [r2]
// CHECK: ldaexb r1, [r2] @ encoding: [0xd2,0xe8,0xcf,0x1f]
ldaexb r1, [r2]
// CHECK: ldaexh r1, [r2] @ encoding: [0xd2,0xe8,0xdf,0x1f]
ldaexh r1, [r2]
// UNDEF: error: instruction requires: !armv*m
ldaexd r0, r1, [r2]
// CHECK: stlex r1, r2, [r3] @ encoding: [0xc3,0xe8,0xe1,0x2f]
stlex r1, r2, [r3]
// CHECK: stlexb r1, r2, [r3] @ encoding: [0xc3,0xe8,0xc1,0x2f]
stlexb r1, r2, [r3]
// CHECK: stlexh r1, r2, [r3] @ encoding: [0xc3,0xe8,0xd1,0x2f]
stlexh r1, r2, [r3]
// UNDEF: error: instruction requires: !armv*m
stlexd r0, r1, r2, [r2]