Skip to content

Commit 0ed0cb6

Browse files
committed
CIRToLLVMLowering: Lower to LLVM FenceOp
1 parent 9e8d54f commit 0ed0cb6

File tree

5 files changed

+130
-86
lines changed

5 files changed

+130
-86
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

+5-3
Original file line numberDiff line numberDiff line change
@@ -5437,16 +5437,18 @@ def AtomicFence : CIR_Op<"atomic.fence"> {
54375437
- `__c11_atomic_signal_fence`
54385438

54395439
Example:
5440-
5440+
```mlir
5441+
cir.atomic.fence system seq_cst
5442+
cir.atomic.fence single_thread seq_cst
5443+
```
54415444

54425445
}];
54435446
let results = (outs);
54445447
let arguments = (ins Arg<MemScopeKind, "sync scope">:$sync_scope,
54455448
Arg<MemOrder, "memory order">:$ordering);
54465449

54475450
let assemblyFormat = [{
5448-
`(` `sync_scope` `=` $sync_scope `,`
5449-
`ordering` `=` $ordering `)` attr-dict
5451+
$sync_scope $ordering attr-dict
54505452
}];
54515453

54525454
let hasVerifier = 0;

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ static mlir::Value MakeAtomicCmpXchgValue(CIRGenFunction &cgf,
339339
return returnBool ? op.getResult(1) : op.getResult(0);
340340
}
341341

342-
static mlir::Value MakeAtomicFenceValue(CIRGenFunction &cgf,
342+
static mlir::Value makeAtomicFenceValue(CIRGenFunction &cgf,
343343
const CallExpr *expr,
344344
cir::MemScopeKind syncScope) {
345345
auto &builder = cgf.getBuilder();
@@ -1894,9 +1894,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
18941894

18951895
case Builtin::BI__atomic_thread_fence:
18961896
return RValue::get(
1897-
MakeAtomicFenceValue(*this, E, cir::MemScopeKind::MemScope_System));
1897+
makeAtomicFenceValue(*this, E, cir::MemScopeKind::MemScope_System));
18981898
case Builtin::BI__atomic_signal_fence:
1899-
return RValue::get(MakeAtomicFenceValue(
1899+
return RValue::get(makeAtomicFenceValue(
19001900
*this, E, cir::MemScopeKind::MemScope_SingleThread));
19011901
case Builtin::BI__c11_atomic_thread_fence:
19021902
case Builtin::BI__c11_atomic_signal_fence:

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+17-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "mlir/Dialect/DLTI/DLTI.h"
2020
#include "mlir/Dialect/Func/IR/FuncOps.h"
2121
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
22+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
2223
#include "mlir/Dialect/LLVMIR/Transforms/Passes.h"
2324
#include "mlir/IR/Attributes.h"
2425
#include "mlir/IR/Builders.h"
@@ -42,7 +43,6 @@
4243
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
4344
#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
4445
#include "mlir/Target/LLVMIR/Export.h"
45-
#include "clang/CIR/Dialect/IR/CIRAttrVisitor.h"
4646
#include "clang/CIR/Dialect/IR/CIRDialect.h"
4747
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
4848
#include "clang/CIR/Dialect/Passes.h"
@@ -3202,9 +3202,10 @@ mlir::LLVM::AtomicOrdering getLLVMAtomicOrder(cir::MemOrder memo) {
32023202
llvm_unreachable("shouldn't get here");
32033203
}
32043204

3205-
// mlir::LLVM::AtomicSyncScope getLLVMSyncScope(cir::MemScopeKind syncScope) {
3206-
//
3207-
// }
3205+
llvm::StringRef getLLVMSyncScope(cir::MemScopeKind syncScope) {
3206+
return syncScope == cir::MemScopeKind::MemScope_SingleThread ? "singlethread"
3207+
: "";
3208+
}
32083209

32093210
mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite(
32103211
cir::AtomicCmpXchg op, OpAdaptor adaptor,
@@ -3374,11 +3375,17 @@ mlir::LogicalResult CIRToLLVMAtomicFetchLowering::matchAndRewrite(
33743375
return mlir::success();
33753376
}
33763377

3377-
// mlir::LogicalResult CIRToLLVMAtomicFenceLowering::matchAndRewrite(
3378-
// cir::AtomicFence op, OpAdaptor adaptor,
3379-
// mlir::ConversionPatternRewriter &rewriter) const {
3380-
// return mlir::success();
3381-
// }
3378+
mlir::LogicalResult CIRToLLVMAtomicFenceLowering::matchAndRewrite(
3379+
cir::AtomicFence op, OpAdaptor adaptor,
3380+
mlir::ConversionPatternRewriter &rewriter) const {
3381+
auto llvmOrder = getLLVMAtomicOrder(adaptor.getOrdering());
3382+
auto llvmSyncScope = getLLVMSyncScope(adaptor.getSyncScope());
3383+
3384+
rewriter.replaceOpWithNewOp<mlir::LLVM::FenceOp>(op, llvmOrder,
3385+
llvmSyncScope);
3386+
3387+
return mlir::success();
3388+
}
33823389

33833390
mlir::LogicalResult CIRToLLVMByteswapOpLowering::matchAndRewrite(
33843391
cir::ByteswapOp op, OpAdaptor adaptor,
@@ -4141,6 +4148,7 @@ void populateCIRToLLVMConversionPatterns(
41414148
CIRToLLVMAtomicCmpXchgLowering,
41424149
CIRToLLVMAtomicFetchLowering,
41434150
CIRToLLVMAtomicXchgLowering,
4151+
CIRToLLVMAtomicFenceLowering,
41444152
CIRToLLVMBaseClassAddrOpLowering,
41454153
CIRToLLVMBinOpLowering,
41464154
CIRToLLVMBinOpOverflowOpLowering,

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

+9-9
Original file line numberDiff line numberDiff line change
@@ -822,15 +822,15 @@ class CIRToLLVMAtomicFetchLowering
822822
mlir::ConversionPatternRewriter &) const override;
823823
};
824824

825-
// class CIRToLLVMAtomicFenceLowering
826-
// : public mlir::OpConversionPattern<cir::AtomicFence> {
827-
// public:
828-
// using mlir::OpConversionPattern<cir::AtomicFence>::OpConversionPattern;
829-
//
830-
// mlir::LogicalResult
831-
// matchAndRewrite(cir::AtomicFence op, OpAdaptor,
832-
// mlir::ConversionPatternRewriter &) const override;
833-
// };
825+
class CIRToLLVMAtomicFenceLowering
826+
: public mlir::OpConversionPattern<cir::AtomicFence> {
827+
public:
828+
using mlir::OpConversionPattern<cir::AtomicFence>::OpConversionPattern;
829+
830+
mlir::LogicalResult
831+
matchAndRewrite(cir::AtomicFence op, OpAdaptor,
832+
mlir::ConversionPatternRewriter &) const override;
833+
};
834834

835835
class CIRToLLVMByteswapOpLowering
836836
: public mlir::OpConversionPattern<cir::ByteswapOp> {
+96-62
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir
22
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3-
// UN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
4-
// UN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
4+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
55

66

77
struct Data {
@@ -12,88 +12,122 @@ struct Data {
1212
typedef struct Data *DataPtr;
1313

1414
void applyThreadFence() {
15-
__atomic_thread_fence(5);
15+
__atomic_thread_fence(__ATOMIC_SEQ_CST);
1616
}
1717

18-
// CIR-LABEL: cir.func no_proto @applyThreadFence
19-
// CIR: %0 = cir.const #cir.int<5> : !s32i
20-
// CIR: cir.atomic.fence(sync_scope = system, ordering = seq_cst)
18+
// CIR-LABEL: @applyThreadFence
19+
// CIR: cir.atomic.fence system seq_cst
2120
// CIR: cir.return
2221

22+
// LLVM-LABEL: @applyThreadFence
23+
// LLVM: fence seq_cst
24+
// LLVM: ret void
25+
2326
void applySignalFence() {
24-
__atomic_signal_fence(5);
27+
__atomic_signal_fence(__ATOMIC_SEQ_CST);
2528
}
26-
// CIR-LABEL: cir.func no_proto @applySignalFence
27-
// CIR: %0 = cir.const #cir.int<5> : !s32i
28-
// CIR: cir.atomic.fence(sync_scope = single_thread, ordering = seq_cst)
29+
// CIR-LABEL: @applySignalFence
30+
// CIR: cir.atomic.fence single_thread seq_cst
2931
// CIR: cir.return
3032

33+
// LLVM-LABEL: @applySignalFence
34+
// LLVM: fence syncscope("singlethread") seq_cst
35+
// LLVM: ret void
36+
3137
void modifyWithThreadFence(DataPtr d) {
32-
__atomic_thread_fence(5);
38+
__atomic_thread_fence(__ATOMIC_SEQ_CST);
3339
d->value = 42;
3440
}
35-
// CIR-LABEL: cir.func @modifyWithThreadFence
36-
// CIR: %0 = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
37-
// CIR: cir.store %arg0, %0 : !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>
38-
// CIR: %1 = cir.const #cir.int<5> : !s32i
39-
// CIR: cir.atomic.fence(sync_scope = system, ordering = seq_cst)
40-
// CIR: %2 = cir.const #cir.int<42> : !s32i
41-
// CIR: %3 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
42-
// CIR: %4 = cir.get_member %3[0] {name = "value"} : !cir.ptr<!ty_Data> -> !cir.ptr<!s32i>
43-
// CIR: cir.store %2, %4 : !s32i, !cir.ptr<!s32i>
41+
// CIR-LABEL: @modifyWithThreadFence
42+
// CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
43+
// CIR: cir.atomic.fence system seq_cst
44+
// CIR: %[[VAL_42:.*]] = cir.const #cir.int<42> : !s32i
45+
// CIR: %[[LOAD_DATA:.*]] = cir.load %[[DATA]] : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
46+
// CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr<!ty_Data> -> !cir.ptr<!s32i>
47+
// CIR: cir.store %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr<!s32i>
4448
// CIR: cir.return
4549

50+
// LLVM-LABEL: @modifyWithThreadFence
51+
// LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
52+
// LLVM: fence seq_cst
53+
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
54+
// LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
55+
// LLVM: store i32 42, ptr %[[DATA_VALUE]], align 4
56+
// LLVM: ret void
57+
4658
void modifyWithSignalFence(DataPtr d) {
47-
__atomic_signal_fence(5);
59+
__atomic_signal_fence(__ATOMIC_SEQ_CST);
4860
d->value = 24;
4961
}
50-
// CIR-LABEL: cir.func @modifyWithSignalFence
51-
// CIR: %0 = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
52-
// CIR: cir.store %arg0, %0 : !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>
53-
// CIR: %1 = cir.const #cir.int<5> : !s32i
54-
// CIR: cir.atomic.fence(sync_scope = single_thread, ordering = seq_cst)
55-
// CIR: %2 = cir.const #cir.int<24> : !s32i
56-
// CIR: %3 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
57-
// CIR: %4 = cir.get_member %3[0] {name = "value"} : !cir.ptr<!ty_Data> -> !cir.ptr<!s32i>
58-
// CIR: cir.store %2, %4 : !s32i, !cir.ptr<!s32i>
62+
// CIR-LABEL: @modifyWithSignalFence
63+
// CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
64+
// CIR: cir.atomic.fence single_thread seq_cst
65+
// CIR: %[[VAL_42:.*]] = cir.const #cir.int<24> : !s32i
66+
// CIR: %[[LOAD_DATA:.*]] = cir.load %[[DATA]] : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
67+
// CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr<!ty_Data> -> !cir.ptr<!s32i>
68+
// CIR: cir.store %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr<!s32i>
5969
// CIR: cir.return
6070

71+
// LLVM-LABEL: @modifyWithSignalFence
72+
// LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
73+
// LLVM: fence syncscope("singlethread") seq_cst
74+
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
75+
// LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
76+
// LLVM: store i32 24, ptr %[[DATA_VALUE]], align 4
77+
// LLVM: ret void
78+
6179
void loadWithThreadFence(DataPtr d) {
62-
__atomic_thread_fence(5);
63-
__atomic_load_n(&d->ptr, 5);
80+
__atomic_thread_fence(__ATOMIC_SEQ_CST);
81+
__atomic_load_n(&d->ptr, __ATOMIC_SEQ_CST);
6482
}
65-
// CIR-LABEL: cir.func @loadWithThreadFence
66-
// CIR: %0 = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
67-
// CIR: %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["atomic-temp"] {alignment = 8 : i64}
68-
// CIR: cir.store %arg0, %0 : !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>
69-
// CIR: %2 = cir.const #cir.int<5> : !s32i
70-
// CIR: cir.atomic.fence(sync_scope = system, ordering = seq_cst)
71-
// CIR: %3 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
72-
// CIR: %4 = cir.get_member %3[1] {name = "ptr"} : !cir.ptr<!ty_Data> -> !cir.ptr<!cir.ptr<!void>>
73-
// CIR: %5 = cir.const #cir.int<5> : !s32i
74-
// CIR: %6 = cir.cast(bitcast, %4 : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
75-
// CIR: %7 = cir.load atomic(seq_cst) %6 : !cir.ptr<!u64i>, !u64i
76-
// CIR: %8 = cir.cast(bitcast, %1 : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
77-
// CIR: cir.store %7, %8 : !u64i, !cir.ptr<!u64i>
78-
// CIR: %9 = cir.load %1 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
83+
// CIR-LABEL: @loadWithThreadFence
84+
// CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
85+
// CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["atomic-temp"] {alignment = 8 : i64}
86+
// CIR: cir.atomic.fence system seq_cst
87+
// CIR: %[[LOAD_DATA:.*]] = cir.load %[[DATA]] : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
88+
// CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr<!ty_Data> -> !cir.ptr<!cir.ptr<!void>>
89+
// CIR: %[[CASTED_DATA_VALUE:.*]] = cir.cast(bitcast, %[[DATA_VALUE]] : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
90+
// CIR: %[[ATOMIC_LOAD:.*]] = cir.load atomic(seq_cst) %[[CASTED_DATA_VALUE]] : !cir.ptr<!u64i>, !u64i
91+
// CIR: %[[CASTED_ATOMIC_TEMP:.*]] = cir.cast(bitcast, %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
92+
// CIR: cir.store %[[ATOMIC_LOAD]], %[[CASTED_ATOMIC_TEMP]] : !u64i, !cir.ptr<!u64i>
93+
// CIR: %[[ATOMIC_LOAD_PTR:.*]] = cir.load %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
7994
// CIR: cir.return
8095

96+
// LLVM-LABEL: @loadWithThreadFence
97+
// LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
98+
// LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8
99+
// LLVM: fence seq_cst
100+
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
101+
// LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
102+
// LLVM: %[[ATOMIC_LOAD:.*]] = load atomic i64, ptr %[[DATA_VALUE]] seq_cst, align 8
103+
// LLVM: store i64 %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
104+
// LLVM: %[[DATA_TEMP_LOAD:.*]] = load ptr, ptr %[[DATA_TEMP]], align 8
105+
// LLVM: ret void
106+
81107
void loadWithSignalFence(DataPtr d) {
82-
__atomic_signal_fence(5);
83-
__atomic_load_n(&d->ptr, 5);
108+
__atomic_signal_fence(__ATOMIC_SEQ_CST);
109+
__atomic_load_n(&d->ptr, __ATOMIC_SEQ_CST);
84110
}
85-
// CIR-LABEL: cir.func @loadWithSignalFence
86-
// CIR: %0 = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
87-
// CIR: %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["atomic-temp"] {alignment = 8 : i64}
88-
// CIR: cir.store %arg0, %0 : !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>
89-
// CIR: %2 = cir.const #cir.int<5> : !s32i
90-
// CIR: cir.atomic.fence(sync_scope = single_thread, ordering = seq_cst)
91-
// CIR: %3 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
92-
// CIR: %4 = cir.get_member %3[1] {name = "ptr"} : !cir.ptr<!ty_Data> -> !cir.ptr<!cir.ptr<!void>>
93-
// CIR: %5 = cir.const #cir.int<5> : !s32i
94-
// CIR: %6 = cir.cast(bitcast, %4 : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
95-
// CIR: %7 = cir.load atomic(seq_cst) %6 : !cir.ptr<!u64i>, !u64i
96-
// CIR: %8 = cir.cast(bitcast, %1 : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
97-
// CIR: cir.store %7, %8 : !u64i, !cir.ptr<!u64i>
98-
// CIR: %9 = cir.load %1 : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
111+
// CIR-LABEL: @loadWithSignalFence
112+
// CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!ty_Data>, !cir.ptr<!cir.ptr<!ty_Data>>, ["d", init] {alignment = 8 : i64}
113+
// CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["atomic-temp"] {alignment = 8 : i64}
114+
// CIR: cir.atomic.fence single_thread seq_cst
115+
// CIR: %[[LOAD_DATA:.*]] = cir.load %[[DATA]] : !cir.ptr<!cir.ptr<!ty_Data>>, !cir.ptr<!ty_Data>
116+
// CIR: %[[DATA_PTR:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr<!ty_Data> -> !cir.ptr<!cir.ptr<!void>>
117+
// CIR: %[[CASTED_DATA_PTR:.*]] = cir.cast(bitcast, %[[DATA_PTR]] : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
118+
// CIR: %[[ATOMIC_LOAD:.*]] = cir.load atomic(seq_cst) %[[CASTED_DATA_PTR]] : !cir.ptr<!u64i>, !u64i
119+
// CIR: %[[CASTED_ATOMIC_TEMP:.*]] = cir.cast(bitcast, %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>), !cir.ptr<!u64i>
120+
// CIR: cir.store %[[ATOMIC_LOAD]], %[[CASTED_ATOMIC_TEMP]] : !u64i, !cir.ptr<!u64i>
121+
// CIR: %[[LOAD_ATOMIC_TEMP:.*]] = cir.load %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
99122
// CIR: cir.return
123+
124+
// LLVM-LABEL: @loadWithSignalFence
125+
// LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
126+
// LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8
127+
// LLVM: fence syncscope("singlethread") seq_cst
128+
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
129+
// LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
130+
// LLVM: %[[ATOMIC_LOAD:.*]] = load atomic i64, ptr %[[DATA_VALUE]] seq_cst, align 8
131+
// LLVM: store i64 %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
132+
// LLVM: %[[DATA_TEMP_LOAD]] = load ptr, ptr %[[DATA_TEMP]], align 8
133+
// LLVM: ret void

0 commit comments

Comments
 (0)