llvm.org GIT mirror llvm / 11db068
- Add subtarget feature -mattr=+db which determine whether an ARM cpu has the memory and synchronization barrier dmb and dsb instructions. - Change instruction names to something more sensible (matching name of actual instructions). - Added tests for memory barrier codegen. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110785 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 10 years ago
9 changed file(s) with 88 addition(s) and 55 deletion(s). Raw diff Collapse all Expand all
4747 "Enable divide instructions">;
4848 def FeatureT2ExtractPack: SubtargetFeature<"t2xtpk", "HasT2ExtractPack", "true",
4949 "Enable Thumb2 extract and pack instructions">;
50 def FeatureDB : SubtargetFeature<"db", "HasDataBarrier", "true",
51 "Has data barrier (dmb / dsb) instructions">;
5052 def FeatureSlowFPBrcc : SubtargetFeature<"slow-fp-brcc", "SlowFPBrcc", "true",
5153 "FP compare + branch is slow">;
5254
133135 // V7 Processors.
134136 def : Processor<"cortex-a8", CortexA8Itineraries,
135137 [ArchV7A, FeatureThumb2, FeatureNEON, FeatureHasSlowVMLx,
136 FeatureSlowFPBrcc, FeatureNEONForFP, FeatureT2ExtractPack]>;
138 FeatureSlowFPBrcc, FeatureNEONForFP, FeatureT2ExtractPack,
139 FeatureDB]>;
137140 def : Processor<"cortex-a9", CortexA9Itineraries,
138 [ArchV7A, FeatureThumb2, FeatureNEON, FeatureT2ExtractPack]>;
139 def : ProcNoItin<"cortex-m3", [ArchV7M, FeatureThumb2, FeatureHWDiv]>;
140 def : ProcNoItin<"cortex-m4", [ArchV7M, FeatureThumb2, FeatureHWDiv]>;
141 [ArchV7A, FeatureThumb2, FeatureNEON, FeatureT2ExtractPack,
142 FeatureDB]>;
143 def : ProcNoItin<"cortex-m3", [ArchV7M, FeatureThumb2, FeatureHWDiv,
144 FeatureDB]>;
145 def : ProcNoItin<"cortex-m4", [ArchV7M, FeatureThumb2, FeatureHWDiv,
146 FeatureDB]>;
141147
142148 //===----------------------------------------------------------------------===//
143149 // Register File Description
411411 // doesn't yet know how to not do that for SjLj.
412412 setExceptionSelectorRegister(ARM::R0);
413413 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
414 // Handle atomics directly for ARMv[67] (except for Thumb1), otherwise
415 // use the default expansion.
416 bool canHandleAtomics =
417 (Subtarget->hasV7Ops() ||
418 (Subtarget->hasV6Ops() && !Subtarget->isThumb1Only()));
419 if (canHandleAtomics) {
414 // ARMv6 Thumb1 (except for CPUs that support dmb / dsb) and earlier use
415 // the default expansion.
416 if (Subtarget->hasDataBarrier() ||
417 (Subtarget->hasV6Ops() && !Subtarget->isThumb1Only())) {
420418 // membarrier needs custom lowering; the rest are legal and handled
421419 // normally.
422420 setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
19911989 DebugLoc dl = Op.getDebugLoc();
19921990 SDValue Op5 = Op.getOperand(5);
19931991 unsigned isDeviceBarrier = cast(Op5)->getZExtValue();
1994 // v6 and v7 can both handle barriers directly, but need handled a bit
1995 // differently. Thumb1 and pre-v6 ARM mode use a libcall instead and should
1992 // Some subtargets which have dmb and dsb instructions can handle barriers
1993 // directly. Some ARMv6 cpus can support them with the help of mcr
1994 // instruction. Thumb1 and pre-v6 ARM mode use a libcall instead and should
19961995 // never get here.
19971996 unsigned Opc = isDeviceBarrier ? ARMISD::SYNCBARRIER : ARMISD::MEMBARRIER;
1998 if (Subtarget->hasV7Ops())
1997 if (Subtarget->hasDataBarrier())
19991998 return DAG.getNode(Opc, dl, MVT::Other, Op.getOperand(0));
2000 else if (Subtarget->hasV6Ops() && !Subtarget->isThumb1Only())
1999 else {
2000 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb1Only() &&
2001 "Unexpected ISD::MEMBARRIER encountered. Should be libcall!");
20012002 return DAG.getNode(Opc, dl, MVT::Other, Op.getOperand(0),
20022003 DAG.getConstant(0, MVT::i32));
2003 assert(0 && "Unexpected ISD::MEMBARRIER encountered. Should be libcall!");
2004 return SDValue();
2004 }
20052005 }
20062006
20072007 static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) {
5353 SDTCisInt<2>]>;
5454 def SDT_ARMEH_SJLJ_Longjmp: SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
5555
56 def SDT_ARMMEMBARRIERV7 : SDTypeProfile<0, 0, []>;
57 def SDT_ARMSYNCBARRIERV7 : SDTypeProfile<0, 0, []>;
58 def SDT_ARMMEMBARRIERV6 : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
59 def SDT_ARMSYNCBARRIERV6 : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
56 def SDT_ARMMEMBARRIER : SDTypeProfile<0, 0, []>;
57 def SDT_ARMSYNCBARRIER : SDTypeProfile<0, 0, []>;
58 def SDT_ARMMEMBARRIERMCR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
59 def SDT_ARMSYNCBARRIERMCR : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
6060
6161 def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
6262
119119 def ARMeh_sjlj_longjmp: SDNode<"ARMISD::EH_SJLJ_LONGJMP",
120120 SDT_ARMEH_SJLJ_Longjmp, [SDNPHasChain]>;
121121
122 def ARMMemBarrierV7 : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERV7,
123 [SDNPHasChain]>;
124 def ARMSyncBarrierV7 : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERV7,
125 [SDNPHasChain]>;
126 def ARMMemBarrierV6 : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERV6,
127 [SDNPHasChain]>;
128 def ARMSyncBarrierV6 : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERV6,
129 [SDNPHasChain]>;
122 def ARMMemBarrier : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER,
123 [SDNPHasChain]>;
124 def ARMSyncBarrier : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIER,
125 [SDNPHasChain]>;
126 def ARMMemBarrierMCR : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERMCR,
127 [SDNPHasChain]>;
128 def ARMSyncBarrierMCR : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERMCR,
129 [SDNPHasChain]>;
130130
131131 def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>;
132132
153153 def HasNEON : Predicate<"Subtarget->hasNEON()">;
154154 def HasDivide : Predicate<"Subtarget->hasDivide()">;
155155 def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">;
156 def HasDB : Predicate<"Subtarget->hasDataBarrier()">;
156157 def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">;
157158 def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">;
158159 def IsThumb : Predicate<"Subtarget->isThumb()">;
23682369
23692370 // memory barriers protect the atomic sequences
23702371 let hasSideEffects = 1 in {
2371 def Int_MemBarrierV7 : AInoP<(outs), (ins),
2372 Pseudo, NoItinerary,
2373 "dmb", "",
2374 [(ARMMemBarrierV7)]>,
2375 Requires<[IsARM, HasV7]> {
2372 def DMBsy : AInoP<(outs), (ins), Pseudo, NoItinerary, "dmb", "",
2373 [(ARMMemBarrier)]>, Requires<[IsARM, HasV7]> {
23762374 let Inst{31-4} = 0xf57ff05;
23772375 // FIXME: add support for options other than a full system DMB
23782376 // See DMB disassembly-only variants below.
23792377 let Inst{3-0} = 0b1111;
23802378 }
23812379
2382 def Int_SyncBarrierV7 : AInoP<(outs), (ins),
2383 Pseudo, NoItinerary,
2384 "dsb", "",
2385 [(ARMSyncBarrierV7)]>,
2386 Requires<[IsARM, HasV7]> {
2380 def DSBsy : AInoP<(outs), (ins), Pseudo, NoItinerary, "dsb", "",
2381 [(ARMSyncBarrier)]>, Requires<[IsARM, HasV7]> {
23872382 let Inst{31-4} = 0xf57ff04;
23882383 // FIXME: add support for options other than a full system DSB
23892384 // See DSB disassembly-only variants below.
23902385 let Inst{3-0} = 0b1111;
23912386 }
23922387
2393 def Int_MemBarrierV6 : AInoP<(outs), (ins GPR:$zero),
2394 Pseudo, NoItinerary,
2388 def DMB_MCR : AInoP<(outs), (ins GPR:$zero), Pseudo, NoItinerary,
23952389 "mcr", "\tp15, 0, $zero, c7, c10, 5",
2396 [(ARMMemBarrierV6 GPR:$zero)]>,
2390 [(ARMMemBarrierMCR GPR:$zero)]>,
23972391 Requires<[IsARM, HasV6]> {
23982392 // FIXME: add support for options other than a full system DMB
23992393 // FIXME: add encoding
24002394 }
24012395
2402 def Int_SyncBarrierV6 : AInoP<(outs), (ins GPR:$zero),
2403 Pseudo, NoItinerary,
2396 def DSB_MCR : AInoP<(outs), (ins GPR:$zero), Pseudo, NoItinerary,
24042397 "mcr", "\tp15, 0, $zero, c7, c10, 4",
2405 [(ARMSyncBarrierV6 GPR:$zero)]>,
2398 [(ARMSyncBarrierMCR GPR:$zero)]>,
24062399 Requires<[IsARM, HasV6]> {
24072400 // FIXME: add support for options other than a full system DSB
24082401 // FIXME: add encoding
22282228
22292229 // memory barriers protect the atomic sequences
22302230 let hasSideEffects = 1 in {
2231 def t2Int_MemBarrierV7 : AInoP<(outs), (ins),
2232 ThumbFrm, NoItinerary,
2233 "dmb", "",
2234 [(ARMMemBarrierV7)]>,
2235 Requires<[IsThumb2]> {
2231 def t2DMBsy : AInoP<(outs), (ins), ThumbFrm, NoItinerary, "dmb", "",
2232 [(ARMMemBarrier)]>, Requires<[HasDB]> {
22362233 let Inst{31-4} = 0xF3BF8F5;
22372234 // FIXME: add support for options other than a full system DMB
22382235 let Inst{3-0} = 0b1111;
22392236 }
22402237
2241 def t2Int_SyncBarrierV7 : AInoP<(outs), (ins),
2242 ThumbFrm, NoItinerary,
2243 "dsb", "",
2244 [(ARMSyncBarrierV7)]>,
2245 Requires<[IsThumb2]> {
2238 def t2DSBsy : AInoP<(outs), (ins), ThumbFrm, NoItinerary, "dsb", "",
2239 [(ARMSyncBarrier)]>, Requires<[HasDB]> {
22462240 let Inst{31-4} = 0xF3BF8F4;
22472241 // FIXME: add support for options other than a full system DSB
22482242 let Inst{3-0} = 0b1111;
4141 , HasFP16(false)
4242 , HasHardwareDivide(false)
4343 , HasT2ExtractPack(false)
44 , HasDataBarrier(false)
4445 , Pref32BitThumb(false)
4546 , stackAlignment(4)
4647 , CPUString("generic")
8383 /// instructions.
8484 bool HasT2ExtractPack;
8585
86 /// HasDataBarrier - True if the subtarget supports DMB / DSB data barrier
87 /// instructions.
88 bool HasDataBarrier;
89
8690 /// Pref32BitThumb - If true, codegen would prefer 32-bit Thumb instructions
8791 /// over 16-bit ones.
8892 bool Pref32BitThumb;
138142 return hasNEON() && UseNEONForSinglePrecisionFP; }
139143 bool hasDivide() const { return HasHardwareDivide; }
140144 bool hasT2ExtractPack() const { return HasT2ExtractPack; }
145 bool hasDataBarrier() const { return HasDataBarrier; }
141146 bool useVMLx() const {return hasVFP2() && !SlowVMLx; }
142147 bool isFPBrccSlow() const { return SlowFPBrcc; }
143148 bool prefers32BitThumb() const { return Pref32BitThumb; }
492492 static bool DisassemblePseudo(MCInst &MI, unsigned Opcode, uint32_t insn,
493493 unsigned short NumOps, unsigned &NumOpsAdded, BO) {
494494
495 if (Opcode == ARM::Int_MemBarrierV7 || Opcode == ARM::Int_SyncBarrierV7)
495 if (Opcode == ARM::DMBsy || Opcode == ARM::DSBsy)
496496 return true;
497497
498498 assert(0 && "Unexpected pseudo instruction!");
0 ; RUN: llc < %s -march=thumb -mattr=+v6 | FileCheck %s
1
2 declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1 )
3
4 define void @t1() {
5 ; CHECK: t1:
6 ; CHECK: blx {{_*}}sync_synchronize
7 call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true, i1 true )
8 ret void
9 }
10
11 define void @t2() {
12 ; CHECK: t2:
13 ; CHECK: blx {{_*}}sync_synchronize
14 call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true, i1 false )
15 ret void
16 }
0 ; RUN: llc < %s -march=thumb -mcpu=cortex-a8 | FileCheck %s
1
2 declare void @llvm.memory.barrier( i1 , i1 , i1 , i1 , i1 )
3
4 define void @t1() {
5 ; CHECK: t1:
6 ; CHECK: dsb
7 call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true, i1 true )
8 ret void
9 }
10
11 define void @t2() {
12 ; CHECK: t2:
13 ; CHECK: dmb
14 call void @llvm.memory.barrier( i1 false, i1 false, i1 false, i1 true, i1 false )
15 ret void
16 }