refactor codes in CDSPass.cpp and also add support for function-like atomic operation...
authorweiyu <weiyuluo1232@gmail.com>
Fri, 14 Jun 2019 00:41:34 +0000 (17:41 -0700)
committerweiyu <weiyuluo1232@gmail.com>
Fri, 14 Jun 2019 00:41:34 +0000 (17:41 -0700)
CDSPass.cpp
initializeCallbacks.hpp [new file with mode: 0644]
instrumentAtomicCall.hpp [new file with mode: 0644]
isAtomicCall.hpp [new file with mode: 0644]

index 4483c22..605a028 100644 (file)
@@ -33,6 +33,7 @@
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PassManager.h"
+#include "llvm/IR/DebugLoc.h"
 #include "llvm/Pass.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/raw_ostream.h"
@@ -42,9 +43,7 @@
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include <list>
 #include <vector>
-// #include "llvm/Support/MathExtras.h"
 
 #define DEBUG_TYPE "CDS"
 using namespace llvm;
@@ -78,10 +77,12 @@ Type * VoidTy;
 
 Constant * CDSLoad[FUNCARRAYSIZE];
 Constant * CDSStore[FUNCARRAYSIZE];
+Constant * CDSAtomicInit[FUNCARRAYSIZE];
 Constant * CDSAtomicLoad[FUNCARRAYSIZE];
 Constant * CDSAtomicStore[FUNCARRAYSIZE];
 Constant * CDSAtomicRMW[AtomicRMWInst::LAST_BINOP + 1][FUNCARRAYSIZE];
-Constant * CDSAtomicCAS[FUNCARRAYSIZE];
+Constant * CDSAtomicCAS_V1[FUNCARRAYSIZE];
+Constant * CDSAtomicCAS_V2[FUNCARRAYSIZE];
 Constant * CDSAtomicThreadFence;
 
 bool start = false;
@@ -107,13 +108,13 @@ int getAtomicOrderIndex(AtomicOrdering order){
 }
 
 int getTypeSize(Type* type) {
-  if (type==Int32PtrTy) {
-    return sizeof(int)*8;
-  } else if (type==Int8PtrTy) {
+  if (type == Int8PtrTy) {
     return sizeof(char)*8;
-  } else if (type==Int16PtrTy) {
+  } else if (type == Int16PtrTy) {
     return sizeof(short)*8;
-  } else if (type==Int64PtrTy) {
+  } else if (type == Int32PtrTy) {
+    return sizeof(int)*8;
+  } else if (type == Int64PtrTy) {
     return sizeof(long long int)*8;
   } else {
     return sizeof(void*)*8;
@@ -141,91 +142,26 @@ namespace {
   private:
     void initializeCallbacks(Module &M);
     bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
-    bool instrumentAtomic(Instruction *I);
+    bool instrumentAtomic(Instruction *I, const DataLayout &DL);
+    bool instrumentAtomicCall(CallInst *CI, const DataLayout &DL);
     void chooseInstructionsToInstrument(SmallVectorImpl<Instruction *> &Local,
                                       SmallVectorImpl<Instruction *> &All,
                                       const DataLayout &DL);
     bool addrPointsToConstantData(Value *Addr);
+    int getMemoryAccessFuncIndex(Value *Addr, const DataLayout &DL);
   };
 }
 
-void CDSPass::initializeCallbacks(Module &M) {
-  LLVMContext &Ctx = M.getContext();
-
-  Int8Ty  = Type::getInt8Ty(Ctx);
-  Int16Ty = Type::getInt16Ty(Ctx);
-  Int32Ty = Type::getInt32Ty(Ctx);
-  Int64Ty = Type::getInt64Ty(Ctx);
-  OrdTy = Type::getInt32Ty(Ctx);
-
-  Int8PtrTy  = Type::getInt8PtrTy(Ctx);
-  Int16PtrTy = Type::getInt16PtrTy(Ctx);
-  Int32PtrTy = Type::getInt32PtrTy(Ctx);
-  Int64PtrTy = Type::getInt64PtrTy(Ctx);
-
-  VoidTy = Type::getVoidTy(Ctx);
-  
-
-  // Get the function to call from our untime library.
-  for (unsigned i = 0; i < FUNCARRAYSIZE; i++) {
-    const unsigned ByteSize = 1U << i;
-    const unsigned BitSize = ByteSize * 8;
-//    errs() << BitSize << "\n";
-    std::string ByteSizeStr = utostr(ByteSize);
-    std::string BitSizeStr = utostr(BitSize);
-
-    Type *Ty = Type::getIntNTy(Ctx, BitSize);
-    Type *PtrTy = Ty->getPointerTo();
-
-    // uint8_t cds_atomic_load8 (void * obj, int atomic_index)
-    // void cds_atomic_store8 (void * obj, int atomic_index, uint8_t val)
-    SmallString<32> LoadName("cds_load" + BitSizeStr);
-    SmallString<32> StoreName("cds_store" + BitSizeStr);
-    SmallString<32> AtomicLoadName("cds_atomic_load" + BitSizeStr);
-    SmallString<32> AtomicStoreName("cds_atomic_store" + BitSizeStr);
-
-    CDSLoad[i]  = M.getOrInsertFunction(LoadName, VoidTy, PtrTy);
-    CDSStore[i] = M.getOrInsertFunction(StoreName, VoidTy, PtrTy);
-    CDSAtomicLoad[i]  = M.getOrInsertFunction(AtomicLoadName, Ty, PtrTy, OrdTy);
-    CDSAtomicStore[i] = M.getOrInsertFunction(AtomicStoreName, VoidTy, PtrTy, OrdTy, Ty);
-
-    for (int op = AtomicRMWInst::FIRST_BINOP; op <= AtomicRMWInst::LAST_BINOP; ++op) {
-      CDSAtomicRMW[op][i] = nullptr;
-      std::string NamePart;
-
-      if (op == AtomicRMWInst::Xchg)
-        NamePart = "_exchange";
-      else if (op == AtomicRMWInst::Add) 
-        NamePart = "_fetch_add";
-      else if (op == AtomicRMWInst::Sub)
-        NamePart = "_fetch_sub";
-      else if (op == AtomicRMWInst::And)
-        NamePart = "_fetch_and";
-      else if (op == AtomicRMWInst::Or)
-        NamePart = "_fetch_or";
-      else if (op == AtomicRMWInst::Xor)
-        NamePart = "_fetch_xor";
-      else
-        continue;
-
-      SmallString<32> AtomicRMWName("cds_atomic" + NamePart + BitSizeStr);
-      CDSAtomicRMW[op][i] = M.getOrInsertFunction(AtomicRMWName, Ty, PtrTy, OrdTy, Ty);
-    }
-
-    // only supportes strong version
-    SmallString<32> AtomicCASName("cds_atomic_compare_exchange" + BitSizeStr);    
-    CDSAtomicCAS[i]   = M.getOrInsertFunction(AtomicCASName, Ty, PtrTy, Ty, Ty, OrdTy, OrdTy);
-  }
-
-  CDSAtomicThreadFence = M.getOrInsertFunction("cds_atomic_thread_fence", VoidTy, OrdTy);
-}
-
 static bool isVtableAccess(Instruction *I) {
   if (MDNode *Tag = I->getMetadata(LLVMContext::MD_tbaa))
     return Tag->isTBAAVtableAccess();
   return false;
 }
 
+#include "initializeCallbacks.hpp"
+#include "isAtomicCall.hpp"
+#include "instrumentAtomicCall.hpp"
+
 static bool shouldInstrumentReadWriteFromAddress(const Module *M, Value *Addr) {
   // Peel off GEPs and BitCasts.
   Addr = Addr->stripInBoundsOffsets();
@@ -281,11 +217,10 @@ bool CDSPass::addrPointsToConstantData(Value *Addr) {
 bool CDSPass::runOnFunction(Function &F) {
   if (F.getName() == "main") {
     F.setName("user_main");
-//    errs() << "main replaced by user_main\n";
+    errs() << "main replaced by user_main\n";
   }
 
   if (true) {
-
     initializeCallbacks( *F.getParent() );
 
     SmallVector<Instruction*, 8> AllLoadsAndStores;
@@ -296,17 +231,29 @@ bool CDSPass::runOnFunction(Function &F) {
 
     bool Res = false;
     const DataLayout &DL = F.getParent()->getDataLayout();
-  
+
+    errs() << "--- " << F.getName() << "---\n";
+
     for (auto &B : F) {
       for (auto &I : B) {
-        if ( (&I)->isAtomic() ) {
+        if ( (&I)->isAtomic() || isAtomicCall(&I) ) {
           AtomicAccesses.push_back(&I);
+
+          const llvm::DebugLoc & debug_location = I.getDebugLoc();
+          std::string position_string;
+          {
+            llvm::raw_string_ostream position_stream (position_string);
+            debug_location . print (position_stream);
+          }
+
+          errs() << I << "\n" << (position_string) << "\n\n";
         } else if (isa<LoadInst>(I) || isa<StoreInst>(I)) {
           LocalLoadsAndStores.push_back(&I);
         } else if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
           // not implemented yet
         }
       }
+
       chooseInstructionsToInstrument(LocalLoadsAndStores, AllLoadsAndStores, DL);
     }
 
@@ -316,17 +263,15 @@ bool CDSPass::runOnFunction(Function &F) {
     }
 
     for (auto Inst : AtomicAccesses) {
-      Res |= instrumentAtomic(Inst);
+      Res |= instrumentAtomic(Inst, DL);
+    }
+
+    if (F.getName() == "user_main") {
+      // F.dump();
     }
-  }
 
-/*
-  if (Res) {
-    errs() << F.getName();
-    errs() << " has above instructions replaced\n";
   }
-*/
-  
+
   return false;
 }
 
@@ -436,18 +381,22 @@ bool CDSPass::instrumentLoadOrStore(Instruction *I,
   return true;
 }
 
-
-bool CDSPass::instrumentAtomic(Instruction * I) {
+// todo: replace getTypeSize with the getMemoryAccessFuncIndex
+bool CDSPass::instrumentAtomic(Instruction * I, const DataLayout &DL) {
   IRBuilder<> IRB(I);
   // LLVMContext &Ctx = IRB.getContext();
 
+  if (auto *CI = dyn_cast<CallInst>(I)) {
+    return instrumentAtomicCall(CI, DL);
+  }
+
   if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
     int atomic_order_index = getAtomicOrderIndex(SI->getOrdering());
 
     Value *val = SI->getValueOperand();
     Value *ptr = SI->getPointerOperand();
     Value *order = ConstantInt::get(OrdTy, atomic_order_index);
-    Value *args[] = {ptr, order, val};
+    Value *args[] = {ptr, val, order};
 
     int size=getTypeSize(ptr->getType());
     int index=sizetoindex(size);
@@ -474,7 +423,7 @@ bool CDSPass::instrumentAtomic(Instruction * I) {
     Value *val = RMWI->getValOperand();
     Value *ptr = RMWI->getPointerOperand();
     Value *order = ConstantInt::get(OrdTy, atomic_order_index);
-    Value *args[] = {ptr, order, val};
+    Value *args[] = {ptr, val, order};
 
     int size = getTypeSize(ptr->getType());
     int index = sizetoindex(size);
@@ -507,7 +456,7 @@ bool CDSPass::instrumentAtomic(Instruction * I) {
                      CmpOperand, NewOperand,
                      order_succ, order_fail};
 
-    CallInst *funcInst = IRB.CreateCall(CDSAtomicCAS[index], Args);
+    CallInst *funcInst = IRB.CreateCall(CDSAtomicCAS_V1[index], Args);
     Value *Success = IRB.CreateICmpEQ(funcInst, CmpOperand);
 
     Value *OldVal = funcInst;
@@ -535,16 +484,31 @@ bool CDSPass::instrumentAtomic(Instruction * I) {
   return true;
 }
 
+int CDSPass::getMemoryAccessFuncIndex(Value *Addr,
+                                              const DataLayout &DL) {
+  Type *OrigPtrTy = Addr->getType();
+  Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
+  assert(OrigTy->isSized());
+  uint32_t TypeSize = DL.getTypeStoreSizeInBits(OrigTy);
+  if (TypeSize != 8  && TypeSize != 16 &&
+      TypeSize != 32 && TypeSize != 64 && TypeSize != 128) {
+    // NumAccessesWithBadSize++;
+    // Ignore all unusual sizes.
+    return -1;
+  }
+  size_t Idx = countTrailingZeros(TypeSize / 8);
+  // assert(Idx < FUNCARRAYSIZE);
+  return Idx;
+}
 
 
 char CDSPass::ID = 0;
 
 // Automatically enable the pass.
-// http://adriansampson.net/blog/clangpass.html
 static void registerCDSPass(const PassManagerBuilder &,
                          legacy::PassManagerBase &PM) {
   PM.add(new CDSPass());
 }
 static RegisterStandardPasses 
-       RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
+       RegisterMyPass(PassManagerBuilder::EP_OptimizerLast,
 registerCDSPass);
diff --git a/initializeCallbacks.hpp b/initializeCallbacks.hpp
new file mode 100644 (file)
index 0000000..df128c0
--- /dev/null
@@ -0,0 +1,77 @@
+void CDSPass::initializeCallbacks(Module &M) {
+       LLVMContext &Ctx = M.getContext();
+
+       Type * Int1Ty = Type::getInt1Ty(Ctx);
+       Int8Ty  = Type::getInt8Ty(Ctx);
+       Int16Ty = Type::getInt16Ty(Ctx);
+       Int32Ty = Type::getInt32Ty(Ctx);
+       Int64Ty = Type::getInt64Ty(Ctx);
+       OrdTy = Type::getInt32Ty(Ctx);
+
+       Int8PtrTy  = Type::getInt8PtrTy(Ctx);
+       Int16PtrTy = Type::getInt16PtrTy(Ctx);
+       Int32PtrTy = Type::getInt32PtrTy(Ctx);
+       Int64PtrTy = Type::getInt64PtrTy(Ctx);
+
+       VoidTy = Type::getVoidTy(Ctx);
+  
+       // Get the function to call from our untime library.
+       for (unsigned i = 0; i < FUNCARRAYSIZE; i++) {
+               const unsigned ByteSize = 1U << i;
+               const unsigned BitSize = ByteSize * 8;
+
+               std::string ByteSizeStr = utostr(ByteSize);
+               std::string BitSizeStr = utostr(BitSize);
+
+               Type *Ty = Type::getIntNTy(Ctx, BitSize);
+               Type *PtrTy = Ty->getPointerTo();
+
+               // uint8_t cds_atomic_load8 (void * obj, int atomic_index)
+               // void cds_atomic_store8 (void * obj, int atomic_index, uint8_t val)
+               SmallString<32> LoadName("cds_load" + BitSizeStr);
+               SmallString<32> StoreName("cds_store" + BitSizeStr);
+               SmallString<32> AtomicInitName("cds_atomic_init" + BitSizeStr);
+               SmallString<32> AtomicLoadName("cds_atomic_load" + BitSizeStr);
+               SmallString<32> AtomicStoreName("cds_atomic_store" + BitSizeStr);
+
+               CDSLoad[i]  = M.getOrInsertFunction(LoadName, VoidTy, PtrTy);
+               CDSStore[i] = M.getOrInsertFunction(StoreName, VoidTy, PtrTy);
+               CDSAtomicInit[i] = M.getOrInsertFunction(AtomicInitName, VoidTy, PtrTy, Ty);
+               CDSAtomicLoad[i]  = M.getOrInsertFunction(AtomicLoadName, Ty, PtrTy, OrdTy);
+               CDSAtomicStore[i] = M.getOrInsertFunction(AtomicStoreName, VoidTy, PtrTy, Ty, OrdTy);
+
+               for (int op = AtomicRMWInst::FIRST_BINOP; 
+                       op <= AtomicRMWInst::LAST_BINOP; ++op) {
+                       CDSAtomicRMW[op][i] = nullptr;
+                       std::string NamePart;
+
+                       if (op == AtomicRMWInst::Xchg)
+                               NamePart = "_exchange";
+                       else if (op == AtomicRMWInst::Add) 
+                               NamePart = "_fetch_add";
+                       else if (op == AtomicRMWInst::Sub)
+                               NamePart = "_fetch_sub";
+                       else if (op == AtomicRMWInst::And)
+                               NamePart = "_fetch_and";
+                       else if (op == AtomicRMWInst::Or)
+                               NamePart = "_fetch_or";
+                       else if (op == AtomicRMWInst::Xor)
+                               NamePart = "_fetch_xor";
+                       else
+                               continue;
+
+                       SmallString<32> AtomicRMWName("cds_atomic" + NamePart + BitSizeStr);
+                       CDSAtomicRMW[op][i] = M.getOrInsertFunction(AtomicRMWName, Ty, PtrTy, Ty, OrdTy);
+               }
+
+               // only supportes strong version
+               SmallString<32> AtomicCASName_V1("cds_atomic_compare_exchange" + BitSizeStr + "_v1");
+               SmallString<32> AtomicCASName_V2("cds_atomic_compare_exchange" + BitSizeStr + "_v2");
+               CDSAtomicCAS_V1[i] = M.getOrInsertFunction(AtomicCASName_V1, 
+                                                               Ty, PtrTy, Ty, Ty, OrdTy, OrdTy);
+               CDSAtomicCAS_V2[i] = M.getOrInsertFunction(AtomicCASName_V2, 
+                                                               Int1Ty, PtrTy, PtrTy, Ty, OrdTy, OrdTy);
+       }
+
+       CDSAtomicThreadFence = M.getOrInsertFunction("cds_atomic_thread_fence", VoidTy, OrdTy);
+}
\ No newline at end of file
diff --git a/instrumentAtomicCall.hpp b/instrumentAtomicCall.hpp
new file mode 100644 (file)
index 0000000..0c96df8
--- /dev/null
@@ -0,0 +1,152 @@
+bool containsStr() {
+
+}
+
+bool CDSPass::instrumentAtomicCall(CallInst *CI, const DataLayout &DL) {
+       IRBuilder<> IRB(CI);
+       Function *fun = CI->getCalledFunction();
+       StringRef funName = fun->getName();
+       std::vector<Value *> parameters;
+
+       User::op_iterator begin = CI->arg_begin();
+       User::op_iterator end = CI->arg_end();
+       for (User::op_iterator it = begin; it != end; ++it) {
+               Value *param = *it;
+               parameters.push_back(param);
+       }
+
+       // the pointer to the address is always the first argument
+       Value *OrigPtr = parameters[0];
+       int Idx = getMemoryAccessFuncIndex(OrigPtr, DL);
+       if (Idx < 0)
+               return false;
+
+       const unsigned ByteSize = 1U << Idx;
+       const unsigned BitSize = ByteSize * 8;
+       Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize);
+       Type *PtrTy = Ty->getPointerTo();
+
+       // atomic_init; args = {obj, order}
+       if (funName.contains("atomic_init")) {
+               Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+               Value *val = IRB.CreateBitOrPointerCast(parameters[1], Ty);
+               Value *args[] = {ptr, val};
+
+               Instruction* funcInst=CallInst::Create(CDSAtomicInit[Idx], args,"");
+               ReplaceInstWithInst(CI, funcInst);
+
+               return true;
+       }
+
+       // atomic_load; args = {obj, order}
+       if (funName.contains("atomic_load")) {
+               bool isExplicit = funName.contains("atomic_load_explicit");
+
+               Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+               Value *order;
+               if (isExplicit)
+                       order = IRB.CreateBitOrPointerCast(parameters[1], OrdTy);
+               else 
+                       order = ConstantInt::get(OrdTy, 
+                                                       (int) AtomicOrderingCABI::seq_cst);
+               Value *args[] = {ptr, order};
+               
+               Instruction* funcInst=CallInst::Create(CDSAtomicLoad[Idx], args,"");
+               ReplaceInstWithInst(CI, funcInst);
+
+               return true;
+       }
+
+       // atomic_store; args = {obj, val, order}
+       if (funName.contains("atomic_store")) {
+               bool isExplicit = funName.contains("atomic_store_explicit");
+               Value *OrigVal = parameters[1];
+
+               Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+               Value *val = IRB.CreatePointerCast(OrigVal, Ty);
+               Value *order;
+               if (isExplicit)
+                       order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
+               else 
+                       order = ConstantInt::get(OrdTy, 
+                                                       (int) AtomicOrderingCABI::seq_cst);
+               Value *args[] = {ptr, val, order};
+               
+               Instruction* funcInst=CallInst::Create(CDSAtomicStore[Idx], args,"");
+               ReplaceInstWithInst(CI, funcInst);
+
+               return true;
+       }
+
+       // atomic_fetch_*; args = {obj, val, order}
+       if (funName.contains("atomic_fetch_") || 
+                       funName.contains("atomic_exchange") ) {
+               bool isExplicit = funName.contains("_explicit");
+               Value *OrigVal = parameters[1];
+
+               int op;
+               if ( funName.contains("_fetch_add") )
+                       op = AtomicRMWInst::Add;
+               else if ( funName.contains("_fetch_sub") )
+                       op = AtomicRMWInst::Sub;
+               else if ( funName.contains("_fetch_and") )
+                       op = AtomicRMWInst::And;
+               else if ( funName.contains("_fetch_or") )
+                       op = AtomicRMWInst::Or;
+               else if ( funName.contains("_fetch_xor") )
+                       op = AtomicRMWInst::Xor;
+               else if ( funName.contains("atomic_exchange") )
+                       op = AtomicRMWInst::Xchg;
+               else {
+                       errs() << "Unknown atomic read modify write operation\n";
+                       return false;
+               }
+
+               Value *ptr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+               Value *val = IRB.CreatePointerCast(OrigVal, Ty);
+               Value *order;
+               if (isExplicit)
+                       order = IRB.CreateBitOrPointerCast(parameters[2], OrdTy);
+               else 
+                       order = ConstantInt::get(OrdTy, 
+                                                       (int) AtomicOrderingCABI::seq_cst);
+               Value *args[] = {ptr, val, order};
+               
+               Instruction* funcInst=CallInst::Create(CDSAtomicRMW[op][Idx], args,"");
+               ReplaceInstWithInst(CI, funcInst);
+
+               return true;
+       }
+
+       /* atomic_compare_exchange_*; 
+          args = {obj, expected, new value, order1, order2}
+       */
+       if ( funName.contains("atomic_compare_exchange_") ) {
+               bool isExplicit = funName.contains("_explicit");
+
+               Value *Addr = IRB.CreatePointerCast(OrigPtr, PtrTy);
+               Value *CmpOperand = IRB.CreatePointerCast(parameters[1], PtrTy);
+               Value *NewOperand = IRB.CreateBitOrPointerCast(parameters[2], Ty);
+
+               Value *order_succ, *order_fail;
+               if (isExplicit) {
+                       order_succ = IRB.CreateBitOrPointerCast(parameters[3], OrdTy);
+                       order_fail = IRB.CreateBitOrPointerCast(parameters[4], OrdTy);
+               } else  {
+                       order_succ = ConstantInt::get(OrdTy, 
+                                                       (int) AtomicOrderingCABI::seq_cst);
+                       order_fail = ConstantInt::get(OrdTy, 
+                                                       (int) AtomicOrderingCABI::seq_cst);
+               }
+
+               Value *args[] = {Addr, CmpOperand, NewOperand, 
+                                                                       order_succ, order_fail};
+               
+               Instruction* funcInst=CallInst::Create(CDSAtomicCAS_V2[Idx], args,"");
+               ReplaceInstWithInst(CI, funcInst);
+
+               return true;
+       }
+
+       return false;
+}
diff --git a/isAtomicCall.hpp b/isAtomicCall.hpp
new file mode 100644 (file)
index 0000000..419312c
--- /dev/null
@@ -0,0 +1,39 @@
+#pragma once
+
+void printArgs(CallInst *);
+
+bool isAtomicCall(Instruction *I)
+{
+       if ( auto *CI = dyn_cast<CallInst>(I) ) {
+               Function *fun = CI->getCalledFunction();
+               StringRef funName = fun->getName();
+
+               if ( (CI->isTailCall() && funName.contains("atomic_")) ||
+                       funName.contains("atomic_compare_exchange_") ) {
+                       printArgs(CI);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+void printArgs (CallInst *CI)
+{
+       Function *fun = CI->getCalledFunction();
+       StringRef funName = fun->getName();
+
+       User::op_iterator begin = CI->arg_begin();
+       User::op_iterator end = CI->arg_end();
+
+       if (funName.find("atomic_") != -1) {
+               std::vector<Value *> parameters;
+
+               for (User::op_iterator it = begin; it != end; ++it) {
+                       Value *param = *it;
+                       parameters.push_back(param);
+                       errs() << *param << " type: " << *param->getType()  << "\n";
+               }
+       }
+
+}