///   %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);
}
Example #2
0
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;
}