@@ -88,88 +88,36 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
8888
8989    uint64_t  SyncScopeID =
9090        cast<ConstantSDNode>(Node->getOperand (2 ).getNode ())->getZExtValue ();
91+     MachineSDNode *Fence = nullptr ;
9192    switch  (SyncScopeID) {
92-     case  SyncScope::SingleThread: { 
93+     case  SyncScope::SingleThread:
9394      //  We lower a single-thread fence to a pseudo compiler barrier instruction
9495      //  preventing instruction reordering. This will not be emitted in final
9596      //  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 ;
170114    default :
171115      llvm_unreachable (" Unknown scope!"  );
172116    }
117+ 
118+     ReplaceNode (Node, Fence);
119+     CurDAG->RemoveDeadNode (Node);
120+     return ;
173121  }
174122
175123  case  ISD::GlobalTLSAddress: {
0 commit comments