@@ -88,88 +88,36 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
88
88
89
89
uint64_t SyncScopeID =
90
90
cast<ConstantSDNode>(Node->getOperand (2 ).getNode ())->getZExtValue ();
91
+ MachineSDNode *Fence = nullptr ;
91
92
switch (SyncScopeID) {
92
- case SyncScope::SingleThread: {
93
+ case SyncScope::SingleThread:
93
94
// We lower a single-thread fence to a pseudo compiler barrier instruction
94
95
// preventing instruction reordering. This will not be emitted in final
95
96
// binary.
96
- MachineSDNode *Fence =
97
- CurDAG->getMachineNode (WebAssembly::COMPILER_FENCE,
98
- DL, // debug loc
99
- MVT::Other, // outchain type
100
- Node->getOperand (0 ) // inchain
101
- );
102
- ReplaceNode (Node, Fence);
103
- CurDAG->RemoveDeadNode (Node);
104
- return ;
105
- }
106
-
107
- case SyncScope::System: {
108
- // For non-emscripten systems, we have not decided on what we should
109
- // traslate fences to yet.
110
- if (!Subtarget->getTargetTriple ().isOSEmscripten ())
111
- report_fatal_error (
112
- " ATOMIC_FENCE is not yet supported in non-emscripten OSes" );
113
-
114
- // Wasm does not have a fence instruction, but because all atomic
115
- // instructions in wasm are sequentially consistent, we translate a
116
- // fence to an idempotent atomic RMW instruction to a linear memory
117
- // address. All atomic instructions in wasm are sequentially consistent,
118
- // but this is to ensure a fence also prevents reordering of non-atomic
119
- // instructions in the VM. Even though LLVM IR's fence instruction does
120
- // not say anything about its relationship with non-atomic instructions,
121
- // we think this is more user-friendly.
122
- //
123
- // While any address can work, here we use a value stored in
124
- // __stack_pointer wasm global because there's high chance that area is
125
- // in cache.
126
- //
127
- // So the selected instructions will be in the form of:
128
- // %addr = get_global $__stack_pointer
129
- // %0 = i32.const 0
130
- // i32.atomic.rmw.or %addr, %0
131
- SDValue StackPtrSym = CurDAG->getTargetExternalSymbol (
132
- " __stack_pointer" , TLI->getPointerTy (CurDAG->getDataLayout ()));
133
- MachineSDNode *GetGlobal =
134
- CurDAG->getMachineNode (WebAssembly::GLOBAL_GET_I32, // opcode
135
- DL, // debug loc
136
- MVT::i32, // result type
137
- StackPtrSym // __stack_pointer symbol
138
- );
139
-
140
- SDValue Zero = CurDAG->getTargetConstant (0 , DL, MVT::i32);
141
- auto *MMO = MF.getMachineMemOperand (
142
- MachinePointerInfo::getUnknownStack (MF),
143
- // FIXME Volatile isn't really correct, but currently all LLVM
144
- // atomic instructions are treated as volatiles in the backend, so
145
- // we should be consistent.
146
- MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad |
147
- MachineMemOperand::MOStore,
148
- 4 , 4 , AAMDNodes (), nullptr , SyncScope::System,
149
- AtomicOrdering::SequentiallyConsistent);
150
- MachineSDNode *Const0 =
151
- CurDAG->getMachineNode (WebAssembly::CONST_I32, DL, MVT::i32, Zero);
152
- MachineSDNode *AtomicRMW = CurDAG->getMachineNode (
153
- WebAssembly::ATOMIC_RMW_OR_I32, // opcode
154
- DL, // debug loc
155
- MVT::i32, // result type
156
- MVT::Other, // outchain type
157
- {
158
- Zero, // alignment
159
- Zero, // offset
160
- SDValue (GetGlobal, 0 ), // __stack_pointer
161
- SDValue (Const0, 0 ), // OR with 0 to make it idempotent
162
- Node->getOperand (0 ) // inchain
163
- });
164
-
165
- CurDAG->setNodeMemRefs (AtomicRMW, {MMO});
166
- ReplaceUses (SDValue (Node, 0 ), SDValue (AtomicRMW, 1 ));
167
- CurDAG->RemoveDeadNode (Node);
168
- return ;
169
- }
97
+ Fence = CurDAG->getMachineNode (WebAssembly::COMPILER_FENCE,
98
+ DL, // debug loc
99
+ MVT::Other, // outchain type
100
+ Node->getOperand (0 ) // inchain
101
+ );
102
+ break ;
103
+ case SyncScope::System:
104
+ // Currently wasm only supports sequentially consistent atomics, so we
105
+ // always set the order to 0 (sequentially consistent).
106
+ Fence = CurDAG->getMachineNode (
107
+ WebAssembly::ATOMIC_FENCE,
108
+ DL, // debug loc
109
+ MVT::Other, // outchain type
110
+ CurDAG->getTargetConstant (0 , DL, MVT::i32), // order
111
+ Node->getOperand (0 ) // inchain
112
+ );
113
+ break ;
170
114
default :
171
115
llvm_unreachable (" Unknown scope!" );
172
116
}
117
+
118
+ ReplaceNode (Node, Fence);
119
+ CurDAG->RemoveDeadNode (Node);
120
+ return ;
173
121
}
174
122
175
123
case ISD::GlobalTLSAddress: {
0 commit comments