Skip to content

Commit 70f8d46

Browse files
committed
[BPF] Add load-acquire and store-release instructions under -mcpu=v5
As discussed in [1], introduce BPF instructions with load-acquire and store-release semantics under -mcpu=v5. A "load_acquire" is a BPF_LDX instruction with a new mode modifier, BPF_MEMACQ ("acquiring atomic load"). Similarly, a "store_release" is a BPF_STX instruction with another new mode modifier, BPF_MEMREL ("releasing atomic store"). BPF_MEMACQ and BPF_MEMREL share the same numeric value, 0x7 (or 0b111). For example: long foo(long *ptr) { return __atomic_load_n(ptr, __ATOMIC_ACQUIRE); } foo() can be compiled to: f9 10 00 00 00 00 00 00 r0 = load_acquire((u64 *)(r1 + 0x0)) 95 00 00 00 00 00 00 00 exit Opcode 0xf9, or 0b11111001, can be decoded as: 0b 111 11 001 BPF_MEMACQ BPF_DW BPF_LDX Similarly: void bar(short *ptr, short val) { __atomic_store_n(ptr, val, __ATOMIC_RELEASE); } bar() can be compiled to: eb 21 00 00 00 00 00 00 store_release((u16 *)(r1 + 0x0), w2) 95 00 00 00 00 00 00 00 exit Opcode 0xeb, or 0b11101011, can be decoded as: 0b 111 01 011 BPF_MEMREL BPF_H BPF_STX Inline assembly is also supported. For example: asm volatile("%0 = load_acquire((u64 *)(%1 + 0x0))" : "=r"(ret) : "r"(ptr) : "memory"); Let 'llvm-objdump -d' use -mcpu=v5 by default, just like commit 0395868 ("[BPF] Make llvm-objdump disasm default cpu v4 (#102166)"). Add two macros, __BPF_FEATURE_LOAD_ACQUIRE and __BPF_FEATURE_STORE_RELEASE, to let developers detect these new features in source code. They can also be disabled using two new llc options, -disable-load-acquire and -disable-store-release, respectively. [1] https://lore.kernel.org/all/[email protected]/
1 parent 03502a3 commit 70f8d46

File tree

14 files changed

+215
-10
lines changed

14 files changed

+215
-10
lines changed

clang/lib/Basic/Targets/BPF.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,15 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
6767
Builder.defineMacro("__BPF_FEATURE_GOTOL");
6868
Builder.defineMacro("__BPF_FEATURE_ST");
6969
}
70+
71+
if (CpuVerNum >= 5) {
72+
Builder.defineMacro("__BPF_FEATURE_LOAD_ACQUIRE");
73+
Builder.defineMacro("__BPF_FEATURE_STORE_RELEASE");
74+
}
7075
}
7176

72-
static constexpr llvm::StringLiteral ValidCPUNames[] = {"generic", "v1", "v2",
73-
"v3", "v4", "probe"};
77+
static constexpr llvm::StringLiteral ValidCPUNames[] = {
78+
"generic", "v1", "v2", "v3", "v4", "v5", "probe"};
7479

7580
bool BPFTargetInfo::isValidCPUName(StringRef Name) const {
7681
return llvm::is_contained(ValidCPUNames, Name);

clang/lib/Basic/Targets/BPF.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
106106
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
107107

108108
bool setCPU(const std::string &Name) override {
109-
if (Name == "v3" || Name == "v4") {
109+
if (Name == "v3" || Name == "v4" || Name == "v5") {
110110
HasAlu32 = true;
111111
}
112112

clang/test/Misc/target-invalid-cpu-note/bpf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// CHECK-SAME: {{^}}, v2
1111
// CHECK-SAME: {{^}}, v3
1212
// CHECK-SAME: {{^}}, v4
13+
// CHECK-SAME: {{^}}, v5
1314
// CHECK-SAME: {{^}}, probe
1415
// CHECK-SAME: {{$}}
1516

llvm/lib/Object/ELFObjectFile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ std::optional<StringRef> ELFObjectFileBase::tryGetCPUName() const {
442442
case ELF::EM_PPC64:
443443
return StringRef("future");
444444
case ELF::EM_BPF:
445-
return StringRef("v4");
445+
return StringRef("v5");
446446
default:
447447
return std::nullopt;
448448
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ struct BPFOperand : public MCParsedAsmOperand {
237237
.Case("exit", true)
238238
.Case("lock", true)
239239
.Case("ld_pseudo", true)
240+
.Case("store_release", true)
240241
.Default(false);
241242
}
242243

@@ -273,6 +274,7 @@ struct BPFOperand : public MCParsedAsmOperand {
273274
.Case("cmpxchg_64", true)
274275
.Case("cmpxchg32_32", true)
275276
.Case("addr_space_cast", true)
277+
.Case("load_acquire", true)
276278
.Default(false);
277279
}
278280
};

llvm/lib/Target/BPF/BPF.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def : Proc<"v1", []>;
3232
def : Proc<"v2", []>;
3333
def : Proc<"v3", [ALU32]>;
3434
def : Proc<"v4", [ALU32]>;
35+
def : Proc<"v5", [ALU32]>;
3536
def : Proc<"probe", []>;
3637

3738
def BPFInstPrinter : AsmWriter {

llvm/lib/Target/BPF/BPFInstrFormats.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ def BPF_IND : BPFModeModifer<0x2>;
9494
def BPF_MEM : BPFModeModifer<0x3>;
9595
def BPF_MEMSX : BPFModeModifer<0x4>;
9696
def BPF_ATOMIC : BPFModeModifer<0x6>;
97+
def BPF_MEMACQ : BPFModeModifer<0x7>;
98+
def BPF_MEMREL : BPFModeModifer<0x7>;
9799

98100
class BPFAtomicFlag<bits<4> val> {
99101
bits<4> Value = val;

llvm/lib/Target/BPF/BPFInstrInfo.td

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ 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 BPFHasLoadAcquire : Predicate<"Subtarget->hasLoadAcquire()">;
64+
def BPFHasStoreRelease : Predicate<"Subtarget->hasStoreRelease()">;
6365

6466
class ImmediateAsmOperand<string name> : AsmOperandClass {
6567
let Name = name;
@@ -514,13 +516,27 @@ class STORE<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string AsmString, list
514516
class STOREi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
515517
: STORE<Opc, BPF_MEM, "*("#OpcodeStr#" *)($addr) = $src", [(OpNode GPR:$src, ADDRri:$addr)]>;
516518

519+
class STORE_RELEASEi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
520+
: STORE<Opc, BPF_MEMREL, "store_release(("#OpcodeStr#" *)($addr), $src)",
521+
[(OpNode GPR:$src, ADDRri:$addr)]>;
522+
517523
let Predicates = [BPFNoALU32] in {
518524
def STW : STOREi64<BPF_W, "u32", truncstorei32>;
519525
def STH : STOREi64<BPF_H, "u16", truncstorei16>;
520526
def STB : STOREi64<BPF_B, "u8", truncstorei8>;
521527
}
522528
def STD : STOREi64<BPF_DW, "u64", store>;
523529

530+
class releasing_store<PatFrag base>
531+
: PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr)> {
532+
let IsAtomic = 1;
533+
let IsAtomicOrderingRelease = 1;
534+
}
535+
536+
let Predicates = [BPFHasStoreRelease] in {
537+
def STDREL : STORE_RELEASEi64<BPF_DW, "u64", releasing_store<atomic_store_64>>;
538+
}
539+
524540
class STORE_imm<BPFWidthModifer SizeOp,
525541
string OpcodeStr, dag Pattern>
526542
: TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
@@ -584,6 +600,11 @@ class LOADi64<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, Pa
584600
: LOAD<SizeOp, ModOp, "$dst = *("#OpcodeStr#" *)($addr)",
585601
[(set i64:$dst, (OpNode ADDRri:$addr))]>;
586602

603+
class LOAD_ACQUIREi64<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr,
604+
PatFrag OpNode>
605+
: LOAD<SizeOp, ModOp, "$dst = load_acquire(("#OpcodeStr#" *)($addr))",
606+
[(set i64:$dst, (OpNode ADDRri:$addr))]>;
607+
587608
let isCodeGenOnly = 1 in {
588609
class CORE_LD<RegisterClass RegClass, string Sz>
589610
: TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
@@ -621,6 +642,16 @@ let Predicates = [BPFHasLdsx] in {
621642

622643
def LDD : LOADi64<BPF_DW, BPF_MEM, "u64", load>;
623644

645+
class acquiring_load<PatFrags base>
646+
: PatFrag<(ops node:$ptr), (base node:$ptr)> {
647+
let IsAtomic = 1;
648+
let IsAtomicOrderingAcquire = 1;
649+
}
650+
651+
let Predicates = [BPFHasLoadAcquire] in {
652+
def LDDACQ : LOAD_ACQUIREi64<BPF_DW, BPF_MEMACQ, "u64", acquiring_load<atomic_load_64>>;
653+
}
654+
624655
class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
625656
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
626657
(outs),
@@ -1086,10 +1117,20 @@ class STOREi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
10861117
: STORE32<Opc, BPF_MEM, "*("#OpcodeStr#" *)($addr) = $src",
10871118
[(OpNode GPR32:$src, ADDRri:$addr)]>;
10881119

1120+
class STORE_RELEASEi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
1121+
: STORE32<Opc, BPF_MEMREL, "store_release(("#OpcodeStr#" *)($addr), $src)",
1122+
[(OpNode GPR32:$src, ADDRri:$addr)]>;
1123+
10891124
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
10901125
def STW32 : STOREi32<BPF_W, "u32", store>;
10911126
def STH32 : STOREi32<BPF_H, "u16", truncstorei16>;
10921127
def STB32 : STOREi32<BPF_B, "u8", truncstorei8>;
1128+
1129+
let Predicates = [BPFHasStoreRelease] in {
1130+
def STWREL32 : STORE_RELEASEi32<BPF_W, "u32", releasing_store<atomic_store_32>>;
1131+
def STHREL32 : STORE_RELEASEi32<BPF_H, "u16", releasing_store<atomic_store_16>>;
1132+
def STBREL32 : STORE_RELEASEi32<BPF_B, "u8", releasing_store<atomic_store_8>>;
1133+
}
10931134
}
10941135

10951136
class LOAD32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string AsmString, list<dag> Pattern>
@@ -1110,10 +1151,21 @@ class LOADi32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, Pa
11101151
: LOAD32<SizeOp, ModOp, "$dst = *("#OpcodeStr#" *)($addr)",
11111152
[(set i32:$dst, (OpNode ADDRri:$addr))]>;
11121153

1154+
class LOAD_ACQUIREi32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr,
1155+
PatFrag OpNode>
1156+
: LOAD32<SizeOp, ModOp, "$dst = load_acquire(("#OpcodeStr#" *)($addr))",
1157+
[(set i32:$dst, (OpNode ADDRri:$addr))]>;
1158+
11131159
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
11141160
def LDW32 : LOADi32<BPF_W, BPF_MEM, "u32", load>;
11151161
def LDH32 : LOADi32<BPF_H, BPF_MEM, "u16", zextloadi16>;
11161162
def LDB32 : LOADi32<BPF_B, BPF_MEM, "u8", zextloadi8>;
1163+
1164+
let Predicates = [BPFHasLoadAcquire] in {
1165+
def LDWACQ32 : LOAD_ACQUIREi32<BPF_W, BPF_MEMACQ, "u32", acquiring_load<atomic_load_32>>;
1166+
def LDHACQ32 : LOAD_ACQUIREi32<BPF_H, BPF_MEMACQ, "u16", acquiring_load<atomic_load_az_16>>;
1167+
def LDBACQ32 : LOAD_ACQUIREi32<BPF_B, BPF_MEMACQ, "u8", acquiring_load<atomic_load_az_8>>;
1168+
}
11171169
}
11181170

11191171
let Predicates = [BPFHasALU32] in {

llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,25 @@ static bool isST(unsigned Opcode) {
100100
}
101101

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

106108
static bool isSTX64(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

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

115119
static bool isLDX64(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

120124
static bool isLDSX(unsigned Opcode) {

llvm/lib/Target/BPF/BPFSubtarget.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ 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>
44+
Disable_load_acquire("disable-load-acquire", cl::Hidden, cl::init(false),
45+
cl::desc("Disable load-acquire insns"));
46+
static cl::opt<bool>
47+
Disable_store_release("disable-store-release", cl::Hidden, cl::init(false),
48+
cl::desc("Disable store-release insns"));
4349

4450
void BPFSubtarget::anchor() {}
4551

@@ -62,6 +68,8 @@ void BPFSubtarget::initializeEnvironment() {
6268
HasSdivSmod = false;
6369
HasGotol = false;
6470
HasStoreImm = false;
71+
HasLoadAcquire = false;
72+
HasStoreRelease = false;
6573
}
6674

6775
void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
@@ -89,6 +97,11 @@ void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
8997
HasGotol = !Disable_gotol;
9098
HasStoreImm = !Disable_StoreImm;
9199
}
100+
101+
if (CpuVerNum >= 5) {
102+
HasLoadAcquire = !Disable_load_acquire;
103+
HasStoreRelease = !Disable_store_release;
104+
}
92105
}
93106

94107
BPFSubtarget::BPFSubtarget(const Triple &TT, const std::string &CPU,

llvm/lib/Target/BPF/BPFSubtarget.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
6666
// whether cpu v4 insns are enabled.
6767
bool HasLdsx, HasMovsx, HasBswap, HasSdivSmod, HasGotol, HasStoreImm;
6868

69+
// whether cpu v5 insns are enabled.
70+
bool HasLoadAcquire, HasStoreRelease;
71+
6972
std::unique_ptr<CallLowering> CallLoweringInfo;
7073
std::unique_ptr<InstructionSelector> InstSelector;
7174
std::unique_ptr<LegalizerInfo> Legalizer;
@@ -92,6 +95,8 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
9295
bool hasSdivSmod() const { return HasSdivSmod; }
9396
bool hasGotol() const { return HasGotol; }
9497
bool hasStoreImm() const { return HasStoreImm; }
98+
bool hasLoadAcquire() const { return HasLoadAcquire; }
99+
bool hasStoreRelease() const { return HasStoreRelease; }
95100

96101
bool isLittleEndian() const { return IsLittleEndian; }
97102

llvm/lib/Target/BPF/Disassembler/BPFDisassembler.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ class BPFDisassembler : public MCDisassembler {
5858
BPF_IND = 0x2,
5959
BPF_MEM = 0x3,
6060
BPF_MEMSX = 0x4,
61-
BPF_ATOMIC = 0x6
61+
BPF_ATOMIC = 0x6,
62+
BPF_MEMACQ = 0x7,
63+
BPF_MEMREL = 0x7
6264
};
6365

6466
BPFDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
@@ -177,7 +179,8 @@ DecodeStatus BPFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
177179
uint8_t InstMode = getInstMode(Insn);
178180
if ((InstClass == BPF_LDX || InstClass == BPF_STX) &&
179181
getInstSize(Insn) != BPF_DW &&
180-
(InstMode == BPF_MEM || InstMode == BPF_ATOMIC) &&
182+
(InstMode == BPF_MEM || InstMode == BPF_ATOMIC ||
183+
InstMode == BPF_MEMACQ /* or BPF_MEMREL */) &&
181184
STI.hasFeature(BPF::ALU32))
182185
Result = decodeInstruction(DecoderTableBPFALU3264, Instr, Insn, Address,
183186
this, STI);
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
; RUN: llc < %s -march=bpfel -mcpu=v5 -verify-machineinstrs -show-mc-encoding | FileCheck %s
2+
;
3+
; Source:
4+
; char load_acquire_i8(char *p) {
5+
; return __atomic_load_n(p, __ATOMIC_ACQUIRE);
6+
; }
7+
; short load_acquire_i16(short *p) {
8+
; return __atomic_load_n(p, __ATOMIC_ACQUIRE);
9+
; }
10+
; int load_acquire_i32(int *p) {
11+
; return __atomic_load_n(p, __ATOMIC_ACQUIRE);
12+
; }
13+
; long load_acquire_i64(long *p) {
14+
; return __atomic_load_n(p, __ATOMIC_ACQUIRE);
15+
; }
16+
; void store_release_i8(char *p, char v) {
17+
; __atomic_store_n(p, v, __ATOMIC_RELEASE);
18+
; }
19+
; void store_release_i16(short *p, short v) {
20+
; __atomic_store_n(p, v, __ATOMIC_RELEASE);
21+
; }
22+
; void store_release_i32(int *p, int v) {
23+
; __atomic_store_n(p, v, __ATOMIC_RELEASE);
24+
; }
25+
; void store_release_i64(long *p, long v) {
26+
; __atomic_store_n(p, v, __ATOMIC_RELEASE);
27+
; }
28+
29+
; CHECK-LABEL: load_acquire_i8
30+
; CHECK: w0 = load_acquire((u8 *)(r1 + 0)) # encoding: [0xf1,0x10,0x00,0x00,0x00,0x00,0x00,0x00]
31+
define dso_local i8 @load_acquire_i8(ptr nocapture noundef readonly %p) local_unnamed_addr {
32+
entry:
33+
%0 = load atomic i8, ptr %p acquire, align 1
34+
ret i8 %0
35+
}
36+
37+
; CHECK-LABEL: load_acquire_i16
38+
; CHECK: w0 = load_acquire((u16 *)(r1 + 0)) # encoding: [0xe9,0x10,0x00,0x00,0x00,0x00,0x00,0x00]
39+
define dso_local i16 @load_acquire_i16(ptr nocapture noundef readonly %p) local_unnamed_addr {
40+
entry:
41+
%0 = load atomic i16, ptr %p acquire, align 2
42+
ret i16 %0
43+
}
44+
45+
; CHECK-LABEL: load_acquire_i32
46+
; CHECK: w0 = load_acquire((u32 *)(r1 + 0)) # encoding: [0xe1,0x10,0x00,0x00,0x00,0x00,0x00,0x00]
47+
define dso_local i32 @load_acquire_i32(ptr nocapture noundef readonly %p) local_unnamed_addr {
48+
entry:
49+
%0 = load atomic i32, ptr %p acquire, align 4
50+
ret i32 %0
51+
}
52+
53+
; CHECK-LABEL: load_acquire_i64
54+
; CHECK: r0 = load_acquire((u64 *)(r1 + 0)) # encoding: [0xf9,0x10,0x00,0x00,0x00,0x00,0x00,0x00]
55+
define dso_local i64 @load_acquire_i64(ptr nocapture noundef readonly %p) local_unnamed_addr {
56+
entry:
57+
%0 = load atomic i64, ptr %p acquire, align 8
58+
ret i64 %0
59+
}
60+
61+
; CHECK-LABEL: store_release_i8
62+
; CHECK: store_release((u8 *)(r1 + 0), w2) # encoding: [0xf3,0x21,0x00,0x00,0x00,0x00,0x00,0x00]
63+
define void @store_release_i8(ptr nocapture noundef writeonly %p,
64+
i8 noundef signext %v) local_unnamed_addr {
65+
entry:
66+
store atomic i8 %v, ptr %p release, align 1
67+
ret void
68+
}
69+
70+
; CHECK-LABEL: store_release_i16
71+
; CHECK: store_release((u16 *)(r1 + 0), w2) # encoding: [0xeb,0x21,0x00,0x00,0x00,0x00,0x00,0x00]
72+
define void @store_release_i16(ptr nocapture noundef writeonly %p,
73+
i16 noundef signext %v) local_unnamed_addr {
74+
entry:
75+
store atomic i16 %v, ptr %p release, align 2
76+
ret void
77+
}
78+
79+
; CHECK-LABEL: store_release_i32
80+
; CHECK: store_release((u32 *)(r1 + 0), w2) # encoding: [0xe3,0x21,0x00,0x00,0x00,0x00,0x00,0x00]
81+
define void @store_release_i32(ptr nocapture noundef writeonly %p,
82+
i32 noundef %v) local_unnamed_addr {
83+
entry:
84+
store atomic i32 %v, ptr %p release, align 4
85+
ret void
86+
}
87+
88+
; CHECK-LABEL: store_release_i64
89+
; CHECK: store_release((u64 *)(r1 + 0), r2) # encoding: [0xfb,0x21,0x00,0x00,0x00,0x00,0x00,0x00]
90+
define void @store_release_i64(ptr nocapture noundef writeonly %p,
91+
i64 noundef %v) local_unnamed_addr {
92+
entry:
93+
store atomic i64 %v, ptr %p release, align 8
94+
ret void
95+
}

0 commit comments

Comments
 (0)