/// %res = cmpxchg [weak] T* %ptr, T %old, T %new, memory_order_success /// memory_order_failure /// %val = extractvalue { T, i1 } %res, 0 /// %success = extractvalue { T, i1 } %res, 1 /// becomes: /// %val = call T @llvm.nacl.atomic.cmpxchg.i<size>( /// %object, %expected, %desired, memory_order_success, /// memory_order_failure) /// %success = icmp eq %old, %val /// Note: weak is currently dropped if present, the cmpxchg is always strong. void AtomicVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { PointerHelper<AtomicCmpXchgInst> PH(*this, I); const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = findAtomicIntrinsic(I, Intrinsic::nacl_atomic_cmpxchg, PH.PET); checkSizeMatchesType(I, PH.BitSize, I.getCompareOperand()->getType()); checkSizeMatchesType(I, PH.BitSize, I.getNewValOperand()->getType()); auto Order = freezeMemoryOrder(I, I.getSuccessOrdering(), I.getFailureOrdering()); Value *Args[] = {PH.P, I.getCompareOperand(), I.getNewValOperand(), Order.first, Order.second}; replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET, Args); }
void GraphBuilder::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { if (isa<PointerType>(I.getType())) { visitInstruction (I); return; } // // Create a DSNode for the dereferenced pointer . If the DSNode is NULL, do // nothing more (this can occur if the pointer is a NULL constant; bugpoint // can generate such code). // DSNodeHandle Ptr = getValueDest(I.getPointerOperand()); if (Ptr.isNull()) return; // // Make that the memory object is read and written. // Ptr.getNode()->setReadMarker(); Ptr.getNode()->setModifiedMarker(); // // If the result of the compare-and-swap is a pointer, then we need to do // a few things: // o Merge the compare and swap values (which are pointers) with the result // o Merge the DSNode of the pointer *within* the memory object with the // DSNode of the compare, swap, and result DSNode. // if (isa<PointerType>(I.getType())) { // // Get the DSNodeHandle of the memory object returned from the load. Make // it the DSNodeHandle of the instruction's result. // DSNodeHandle FieldPtr = getLink (Ptr); setDestTo(I, getLink(Ptr)); // // Merge the result, compare, and swap values of the instruction. // FieldPtr.mergeWith (getValueDest (I.getCompareOperand())); FieldPtr.mergeWith (getValueDest (I.getNewValOperand())); } // // Modify the DSNode so that it has the loaded/written type at the // appropriate offset. // Ptr.getNode()->growSizeForType(I.getType(), Ptr.getOffset()); Ptr.getNode()->mergeTypeInfo(I.getType(), Ptr.getOffset()); return; }