Index: lib/Target/ARM/ARM.td =================================================================== --- lib/Target/ARM/ARM.td +++ lib/Target/ARM/ARM.td @@ -393,7 +393,7 @@ FeatureNoARM, FeatureDB, FeatureHWDiv, - FeatureV7Exclusives, + FeatureV7Clrex, FeatureAcquireRelease, FeatureMClass]>; Index: lib/Target/ARM/ARMISelDAGToDAG.cpp =================================================================== --- lib/Target/ARM/ARMISelDAGToDAG.cpp +++ lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -3056,7 +3056,7 @@ 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) Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -839,7 +839,8 @@ // 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); Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -3291,15 +3291,18 @@ 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 @@ 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 : 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)>, Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -336,7 +336,7 @@ } bool ARMSubtarget::enableAtomicExpand() const { - return hasAnyDataBarrier() && !isThumb1Only(); + return hasAnyDataBarrier() && (!isThumb() || hasV8MBaselineOps()); } bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const { Index: test/CodeGen/ARM/ldstrex-m.ll =================================================================== --- test/CodeGen/ARM/ldstrex-m.ll +++ test/CodeGen/ARM/ldstrex-m.ll @@ -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 Index: test/MC/ARM/thumbv8m.s =================================================================== --- test/MC/ARM/thumbv8m.s +++ test/MC/ARM/thumbv8m.s @@ -41,6 +41,37 @@ // 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 @@ // 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]