Skip to content

Commit 17bfc00

Browse files
authored
[BPF] Add load-acquire and store-release instructions under -mcpu=v4 (#108636)
As discussed in [1], introduce BPF instructions with load-acquire and store-release semantics under -mcpu=v4. Define 2 new flags: BPF_LOAD_ACQ 0x100 BPF_STORE_REL 0x110 A "load-acquire" is a BPF_STX | BPF_ATOMIC instruction with the 'imm' field set to BPF_LOAD_ACQ (0x100). Similarly, a "store-release" is a BPF_STX | BPF_ATOMIC instruction with the 'imm' field set to BPF_STORE_REL (0x110). Unlike existing atomic read-modify-write operations that only support BPF_W (32-bit) and BPF_DW (64-bit) size modifiers, load-acquires and store-releases also support BPF_B (8-bit) and BPF_H (16-bit). An 8- or 16-bit load-acquire zero-extends the value before writing it to a 32-bit register, just like ARM64 instruction LDAPRH and friends. As an example (assuming little-endian): long foo(long *ptr) { return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); } foo() can be compiled to: db 10 00 00 00 01 00 00 r0 = load_acquire((u64 *)(r1 + 0x0)) 95 00 00 00 00 00 00 00 exit opcode (0xdb): BPF_ATOMIC | BPF_DW | BPF_STX imm (0x00000100): BPF_LOAD_ACQ Similarly: void bar(short *ptr, short val) { __atomic_store_n(ptr, val, __ATOMIC_RELEASE); } bar() can be compiled to: cb 21 00 00 10 01 00 00 store_release((u16 *)(r1 + 0x0), w2) 95 00 00 00 00 00 00 00 exit opcode (0xcb): BPF_ATOMIC | BPF_H | BPF_STX imm (0x00000110): BPF_STORE_REL Inline assembly is also supported. Add a pre-defined macro, __BPF_FEATURE_LOAD_ACQ_STORE_REL, to let developers detect this new feature. It can also be disabled using a new llc option, -disable-load-acq-store-rel. Using __ATOMIC_RELAXED for __atomic_store{,_n}() will generate a "plain" store (BPF_MEM | BPF_STX) instruction: void foo(short *ptr, short val) { __atomic_store_n(ptr, val, __ATOMIC_RELAXED); } 6b 21 00 00 00 00 00 00 *(u16 *)(r1 + 0x0) = w2 95 00 00 00 00 00 00 00 exit Similarly, using __ATOMIC_RELAXED for __atomic_load{,_n}() will generate a zero-extending, "plain" load (BPF_MEM | BPF_LDX) instruction: int foo(char *ptr) { return __atomic_load_n(ptr, __ATOMIC_RELAXED); } 71 11 00 00 00 00 00 00 w1 = *(u8 *)(r1 + 0x0) bc 10 08 00 00 00 00 00 w0 = (s8)w1 95 00 00 00 00 00 00 00 exit Currently __ATOMIC_CONSUME is an alias for __ATOMIC_ACQUIRE. Using __ATOMIC_SEQ_CST ("sequentially consistent") is not supported yet and will cause an error: $ clang --target=bpf -mcpu=v4 -c bar.c > /dev/null bar.c:1:5: error: sequentially consistent (seq_cst) atomic load/store is not supported 1 | int foo(int *ptr) { return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); } | ^ ... Finally, rename those isST*() and isLD*() helper functions in BPFMISimplifyPatchable.cpp based on what the instructions actually do, rather than their instruction class. [1] https://lore.kernel.org/all/[email protected]/
1 parent 9e1eaff commit 17bfc00

File tree

12 files changed

+355
-17
lines changed

12 files changed

+355
-17
lines changed

clang/lib/Basic/Targets/BPF.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
7575
Builder.defineMacro("__BPF_FEATURE_SDIV_SMOD");
7676
Builder.defineMacro("__BPF_FEATURE_GOTOL");
7777
Builder.defineMacro("__BPF_FEATURE_ST");
78+
Builder.defineMacro("__BPF_FEATURE_LOAD_ACQ_STORE_REL");
7879
}
7980
}
8081

clang/test/Preprocessor/bpf-predefined-macros.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ int t;
6767
#ifdef __BPF_FEATURE_MAY_GOTO
6868
int u;
6969
#endif
70+
#ifdef __BPF_FEATURE_LOAD_ACQ_STORE_REL
71+
int v;
72+
#endif
7073

7174
// CHECK: int b;
7275
// CHECK: int c;
@@ -106,6 +109,8 @@ int u;
106109
// CPU_V3: int u;
107110
// CPU_V4: int u;
108111

112+
// CPU_V4: int v;
113+
109114
// CPU_GENERIC: int g;
110115

111116
// CPU_PROBE: int f;

llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ struct BPFOperand : public MCParsedAsmOperand {
235235
.Case("exit", true)
236236
.Case("lock", true)
237237
.Case("ld_pseudo", true)
238+
.Case("store_release", true)
238239
.Default(false);
239240
}
240241

@@ -271,6 +272,7 @@ struct BPFOperand : public MCParsedAsmOperand {
271272
.Case("cmpxchg_64", true)
272273
.Case("cmpxchg32_32", true)
273274
.Case("addr_space_cast", true)
275+
.Case("load_acquire", true)
274276
.Default(false);
275277
}
276278
};

llvm/lib/Target/BPF/BPFISelLowering.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
9292
setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Custom);
9393
}
9494

95+
for (auto VT : {MVT::i32, MVT::i64}) {
96+
setOperationAction(ISD::ATOMIC_LOAD, VT, Custom);
97+
setOperationAction(ISD::ATOMIC_STORE, VT, Custom);
98+
}
99+
95100
for (auto VT : { MVT::i32, MVT::i64 }) {
96101
if (VT == MVT::i32 && !STI.getHasAlu32())
97102
continue;
@@ -290,6 +295,9 @@ void BPFTargetLowering::ReplaceNodeResults(
290295
else
291296
Msg = "unsupported atomic operation, please use 64 bit version";
292297
break;
298+
case ISD::ATOMIC_LOAD:
299+
case ISD::ATOMIC_STORE:
300+
return;
293301
}
294302

295303
SDLoc DL(N);
@@ -315,6 +323,9 @@ SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
315323
return LowerSDIVSREM(Op, DAG);
316324
case ISD::DYNAMIC_STACKALLOC:
317325
return LowerDYNAMIC_STACKALLOC(Op, DAG);
326+
case ISD::ATOMIC_LOAD:
327+
case ISD::ATOMIC_STORE:
328+
return LowerATOMIC_LOAD_STORE(Op, DAG);
318329
}
319330
}
320331

@@ -701,6 +712,20 @@ SDValue BPFTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
701712
return DAG.getNode(BPFISD::SELECT_CC, DL, Op.getValueType(), Ops);
702713
}
703714

715+
SDValue BPFTargetLowering::LowerATOMIC_LOAD_STORE(SDValue Op,
716+
SelectionDAG &DAG) const {
717+
SDNode *N = Op.getNode();
718+
SDLoc DL(N);
719+
720+
if (cast<AtomicSDNode>(N)->getMergedOrdering() ==
721+
AtomicOrdering::SequentiallyConsistent)
722+
fail(DL, DAG,
723+
"sequentially consistent (seq_cst) "
724+
"atomic load/store is not supported");
725+
726+
return Op;
727+
}
728+
704729
const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const {
705730
switch ((BPFISD::NodeType)Opcode) {
706731
case BPFISD::FIRST_NUMBER:

llvm/lib/Target/BPF/BPFISelLowering.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class BPFTargetLowering : public TargetLowering {
7777
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
7878
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
7979
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
80-
80+
SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) const;
8181
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
8282
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
8383

llvm/lib/Target/BPF/BPFInstrFormats.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ def BPF_END : BPFArithOp<0xd>;
4848
def BPF_XCHG : BPFArithOp<0xe>;
4949
def BPF_CMPXCHG : BPFArithOp<0xf>;
5050

51+
class BPFAtomicOp<bits<5> val> {
52+
bits<5> Value = val;
53+
}
54+
55+
def BPF_LOAD_ACQ : BPFAtomicOp<0x10>;
56+
def BPF_STORE_REL : BPFAtomicOp<0x11>;
57+
5158
class BPFEndDir<bits<1> val> {
5259
bits<1> Value = val;
5360
}

llvm/lib/Target/BPF/BPFInstrInfo.td

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def BPFHasSdivSmod : Predicate<"Subtarget->hasSdivSmod()">;
6060
def BPFNoMovsx : Predicate<"!Subtarget->hasMovsx()">;
6161
def BPFNoBswap : Predicate<"!Subtarget->hasBswap()">;
6262
def BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">;
63+
def BPFHasLoadAcqStoreRel : Predicate<"Subtarget->hasLoadAcqStoreRel()">;
6364

6465
class ImmediateAsmOperand<string name> : AsmOperandClass {
6566
let Name = name;
@@ -566,6 +567,47 @@ let Predicates = [BPFHasALU32, BPFHasStoreImm] in {
566567
(STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
567568
}
568569

570+
class STORE_RELEASE<BPFWidthModifer SizeOp, string OpcodeStr, RegisterClass RegTp>
571+
: TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
572+
(outs),
573+
(ins RegTp:$src, MEMri:$addr),
574+
"store_release(("#OpcodeStr#" *)($addr), $src)",
575+
[]> {
576+
bits<4> src;
577+
bits<20> addr;
578+
579+
let Inst{51-48} = addr{19-16}; // base reg
580+
let Inst{55-52} = src;
581+
let Inst{47-32} = addr{15-0}; // offset
582+
let Inst{8-4} = BPF_STORE_REL.Value;
583+
let BPFClass = BPF_STX;
584+
}
585+
586+
class STORE_RELEASEi64<BPFWidthModifer Opc, string OpcodeStr>
587+
: STORE_RELEASE<Opc, OpcodeStr, GPR>;
588+
589+
class relaxed_store<PatFrag base>
590+
: PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {
591+
let IsAtomic = 1;
592+
let IsAtomicOrderingReleaseOrStronger = 0;
593+
}
594+
595+
class releasing_store<PatFrag base>
596+
: PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {
597+
let IsAtomic = 1;
598+
let IsAtomicOrderingRelease = 1;
599+
}
600+
601+
let Predicates = [BPFHasLoadAcqStoreRel] in {
602+
def STDREL : STORE_RELEASEi64<BPF_DW, "u64">;
603+
604+
foreach P = [[relaxed_store<atomic_store_64>, STD],
605+
[releasing_store<atomic_store_64>, STDREL],
606+
] in {
607+
def : Pat<(P[0] GPR:$val, ADDRri:$addr), (P[1] GPR:$val, ADDRri:$addr)>;
608+
}
609+
}
610+
569611
// LOAD instructions
570612
class LOAD<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern>
571613
: TYPE_LD_ST<ModOp.Value, SizeOp.Value,
@@ -622,6 +664,47 @@ let Predicates = [BPFHasLdsx] in {
622664

623665
def LDD : LOADi64<BPF_DW, BPF_MEM, "u64", load>;
624666

667+
class LOAD_ACQUIRE<BPFWidthModifer SizeOp, string OpcodeStr, RegisterClass RegTp>
668+
: TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
669+
(outs RegTp:$dst),
670+
(ins MEMri:$addr),
671+
"$dst = load_acquire(("#OpcodeStr#" *)($addr))",
672+
[]> {
673+
bits<4> dst;
674+
bits<20> addr;
675+
676+
let Inst{51-48} = dst;
677+
let Inst{55-52} = addr{19-16}; // base reg
678+
let Inst{47-32} = addr{15-0}; // offset
679+
let Inst{8-4} = BPF_LOAD_ACQ.Value;
680+
let BPFClass = BPF_STX;
681+
}
682+
683+
class LOAD_ACQUIREi64<BPFWidthModifer SizeOp, string OpcodeStr>
684+
: LOAD_ACQUIRE<SizeOp, OpcodeStr, GPR>;
685+
686+
class relaxed_load<PatFrags base>
687+
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
688+
let IsAtomic = 1;
689+
let IsAtomicOrderingAcquireOrStronger = 0;
690+
}
691+
692+
class acquiring_load<PatFrags base>
693+
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
694+
let IsAtomic = 1;
695+
let IsAtomicOrderingAcquire = 1;
696+
}
697+
698+
let Predicates = [BPFHasLoadAcqStoreRel] in {
699+
def LDDACQ : LOAD_ACQUIREi64<BPF_DW, "u64">;
700+
701+
foreach P = [[relaxed_load<atomic_load_64>, LDD],
702+
[acquiring_load<atomic_load_64>, LDDACQ],
703+
] in {
704+
def : Pat<(P[0] ADDRri:$addr), (P[1] ADDRri:$addr)>;
705+
}
706+
}
707+
625708
class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
626709
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
627710
(outs),
@@ -1181,10 +1264,19 @@ class STORE32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
11811264
class STOREi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
11821265
: STORE32<Opc, OpcodeStr, [(OpNode GPR32:$src, ADDRri:$addr)]>;
11831266

1267+
class STORE_RELEASEi32<BPFWidthModifer Opc, string OpcodeStr>
1268+
: STORE_RELEASE<Opc, OpcodeStr, GPR32>;
1269+
11841270
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
11851271
def STW32 : STOREi32<BPF_W, "u32", store>;
11861272
def STH32 : STOREi32<BPF_H, "u16", truncstorei16>;
11871273
def STB32 : STOREi32<BPF_B, "u8", truncstorei8>;
1274+
1275+
let Predicates = [BPFHasLoadAcqStoreRel] in {
1276+
def STWREL32 : STORE_RELEASEi32<BPF_W, "u32">;
1277+
def STHREL32 : STORE_RELEASEi32<BPF_H, "u16">;
1278+
def STBREL32 : STORE_RELEASEi32<BPF_B, "u8">;
1279+
}
11881280
}
11891281

11901282
class LOAD32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern>
@@ -1205,10 +1297,19 @@ class LOAD32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, lis
12051297
class LOADi32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode>
12061298
: LOAD32<SizeOp, ModOp, OpcodeStr, [(set i32:$dst, (OpNode ADDRri:$addr))]>;
12071299

1300+
class LOAD_ACQUIREi32<BPFWidthModifer SizeOp, string OpcodeStr>
1301+
: LOAD_ACQUIRE<SizeOp, OpcodeStr, GPR32>;
1302+
12081303
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
12091304
def LDW32 : LOADi32<BPF_W, BPF_MEM, "u32", load>;
12101305
def LDH32 : LOADi32<BPF_H, BPF_MEM, "u16", zextloadi16>;
12111306
def LDB32 : LOADi32<BPF_B, BPF_MEM, "u8", zextloadi8>;
1307+
1308+
let Predicates = [BPFHasLoadAcqStoreRel] in {
1309+
def LDWACQ32 : LOAD_ACQUIREi32<BPF_W, "u32">;
1310+
def LDHACQ32 : LOAD_ACQUIREi32<BPF_H, "u16">;
1311+
def LDBACQ32 : LOAD_ACQUIREi32<BPF_B, "u8">;
1312+
}
12121313
}
12131314

12141315
let Predicates = [BPFHasALU32] in {
@@ -1238,6 +1339,30 @@ let Predicates = [BPFHasALU32] in {
12381339
(SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>;
12391340
def : Pat<(i64 (extloadi32 ADDRri:$src)),
12401341
(SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>;
1342+
1343+
let Predicates = [BPFHasLoadAcqStoreRel] in {
1344+
foreach P = [[relaxed_load<atomic_load_32>, LDW32],
1345+
[relaxed_load<atomic_load_az_16>, LDH32],
1346+
[relaxed_load<atomic_load_az_8>, LDB32],
1347+
[acquiring_load<atomic_load_32>, LDWACQ32],
1348+
[acquiring_load<atomic_load_az_16>, LDHACQ32],
1349+
[acquiring_load<atomic_load_az_8>, LDBACQ32],
1350+
] in {
1351+
def : Pat<(P[0] ADDRri:$addr), (P[1] ADDRri:$addr)>;
1352+
}
1353+
}
1354+
1355+
let Predicates = [BPFHasLoadAcqStoreRel] in {
1356+
foreach P = [[relaxed_store<atomic_store_32>, STW32],
1357+
[relaxed_store<atomic_store_16>, STH32],
1358+
[relaxed_store<atomic_store_8>, STB32],
1359+
[releasing_store<atomic_store_32>, STWREL32],
1360+
[releasing_store<atomic_store_16>, STHREL32],
1361+
[releasing_store<atomic_store_8>, STBREL32],
1362+
] in {
1363+
def : Pat<(P[0] GPR32:$val, ADDRri:$addr), (P[1] GPR32:$val, ADDRri:$addr)>;
1364+
}
1365+
}
12411366
}
12421367

12431368
let usesCustomInserter = 1, isCodeGenOnly = 1 in {

llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,35 +94,39 @@ void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
9494
LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n");
9595
}
9696

97-
static bool isST(unsigned Opcode) {
97+
static bool isStoreImm(unsigned Opcode) {
9898
return Opcode == BPF::STB_imm || Opcode == BPF::STH_imm ||
9999
Opcode == BPF::STW_imm || Opcode == BPF::STD_imm;
100100
}
101101

102-
static bool isSTX32(unsigned Opcode) {
103-
return Opcode == BPF::STB32 || Opcode == BPF::STH32 || Opcode == BPF::STW32;
102+
static bool isStore32(unsigned Opcode) {
103+
return Opcode == BPF::STB32 || Opcode == BPF::STH32 || Opcode == BPF::STW32 ||
104+
Opcode == BPF::STBREL32 || Opcode == BPF::STHREL32 ||
105+
Opcode == BPF::STWREL32;
104106
}
105107

106-
static bool isSTX64(unsigned Opcode) {
108+
static bool isStore64(unsigned Opcode) {
107109
return Opcode == BPF::STB || Opcode == BPF::STH || Opcode == BPF::STW ||
108-
Opcode == BPF::STD;
110+
Opcode == BPF::STD || Opcode == BPF::STDREL;
109111
}
110112

111-
static bool isLDX32(unsigned Opcode) {
112-
return Opcode == BPF::LDB32 || Opcode == BPF::LDH32 || Opcode == BPF::LDW32;
113+
static bool isLoad32(unsigned Opcode) {
114+
return Opcode == BPF::LDB32 || Opcode == BPF::LDH32 || Opcode == BPF::LDW32 ||
115+
Opcode == BPF::LDBACQ32 || Opcode == BPF::LDHACQ32 ||
116+
Opcode == BPF::LDWACQ32;
113117
}
114118

115-
static bool isLDX64(unsigned Opcode) {
119+
static bool isLoad64(unsigned Opcode) {
116120
return Opcode == BPF::LDB || Opcode == BPF::LDH || Opcode == BPF::LDW ||
117-
Opcode == BPF::LDD;
121+
Opcode == BPF::LDD || Opcode == BPF::LDDACQ;
118122
}
119123

120-
static bool isLDSX(unsigned Opcode) {
124+
static bool isLoadSext(unsigned Opcode) {
121125
return Opcode == BPF::LDBSX || Opcode == BPF::LDHSX || Opcode == BPF::LDWSX;
122126
}
123127

124128
bool BPFMISimplifyPatchable::isLoadInst(unsigned Opcode) {
125-
return isLDX32(Opcode) || isLDX64(Opcode) || isLDSX(Opcode);
129+
return isLoad32(Opcode) || isLoad64(Opcode) || isLoadSext(Opcode);
126130
}
127131

128132
void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
@@ -143,11 +147,11 @@ void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
143147
MachineInstr *DefInst = MO.getParent();
144148
unsigned Opcode = DefInst->getOpcode();
145149
unsigned COREOp;
146-
if (isLDX64(Opcode) || isLDSX(Opcode))
150+
if (isLoad64(Opcode) || isLoadSext(Opcode))
147151
COREOp = BPF::CORE_LD64;
148-
else if (isLDX32(Opcode))
152+
else if (isLoad32(Opcode))
149153
COREOp = BPF::CORE_LD32;
150-
else if (isSTX64(Opcode) || isSTX32(Opcode) || isST(Opcode))
154+
else if (isStore64(Opcode) || isStore32(Opcode) || isStoreImm(Opcode))
151155
COREOp = BPF::CORE_ST;
152156
else
153157
continue;
@@ -160,7 +164,7 @@ void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
160164
// Reject the form:
161165
// %1 = ADD_rr %2, %3
162166
// *(type *)(%2 + 0) = %1
163-
if (isSTX64(Opcode) || isSTX32(Opcode)) {
167+
if (isStore64(Opcode) || isStore32(Opcode)) {
164168
const MachineOperand &Opnd = DefInst->getOperand(0);
165169
if (Opnd.isReg() && Opnd.getReg() == MO.getReg())
166170
continue;

llvm/lib/Target/BPF/BPFSubtarget.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ static cl::opt<bool> Disable_gotol("disable-gotol", cl::Hidden, cl::init(false),
4040
static cl::opt<bool>
4141
Disable_StoreImm("disable-storeimm", cl::Hidden, cl::init(false),
4242
cl::desc("Disable BPF_ST (immediate store) insn"));
43+
static cl::opt<bool> Disable_load_acq_store_rel(
44+
"disable-load-acq-store-rel", cl::Hidden, cl::init(false),
45+
cl::desc("Disable load-acquire and store-release insns"));
4346

4447
void BPFSubtarget::anchor() {}
4548

@@ -62,6 +65,7 @@ void BPFSubtarget::initializeEnvironment() {
6265
HasSdivSmod = false;
6366
HasGotol = false;
6467
HasStoreImm = false;
68+
HasLoadAcqStoreRel = false;
6569
}
6670

6771
void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
@@ -91,6 +95,7 @@ void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
9195
HasSdivSmod = !Disable_sdiv_smod;
9296
HasGotol = !Disable_gotol;
9397
HasStoreImm = !Disable_StoreImm;
98+
HasLoadAcqStoreRel = !Disable_load_acq_store_rel;
9499
return;
95100
}
96101
}

0 commit comments

Comments
 (0)