LowerAtomic.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This pass lowers atomic intrinsics to non-atomic form for use in a known
  11. // non-preemptible environment.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/Transforms/Scalar.h"
  15. #include "llvm/IR/Function.h"
  16. #include "llvm/IR/IRBuilder.h"
  17. #include "llvm/IR/IntrinsicInst.h"
  18. #include "llvm/Pass.h"
  19. using namespace llvm;
  20. #define DEBUG_TYPE "loweratomic"
  21. static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
  22. IRBuilder<> Builder(CXI->getParent(), CXI);
  23. Value *Ptr = CXI->getPointerOperand();
  24. Value *Cmp = CXI->getCompareOperand();
  25. Value *Val = CXI->getNewValOperand();
  26. LoadInst *Orig = Builder.CreateLoad(Ptr);
  27. Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
  28. Value *Res = Builder.CreateSelect(Equal, Val, Orig);
  29. Builder.CreateStore(Res, Ptr);
  30. Res = Builder.CreateInsertValue(UndefValue::get(CXI->getType()), Orig, 0);
  31. Res = Builder.CreateInsertValue(Res, Equal, 1);
  32. CXI->replaceAllUsesWith(Res);
  33. CXI->eraseFromParent();
  34. return true;
  35. }
  36. static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) {
  37. IRBuilder<> Builder(RMWI->getParent(), RMWI);
  38. Value *Ptr = RMWI->getPointerOperand();
  39. Value *Val = RMWI->getValOperand();
  40. LoadInst *Orig = Builder.CreateLoad(Ptr);
  41. Value *Res = nullptr;
  42. switch (RMWI->getOperation()) {
  43. default: llvm_unreachable("Unexpected RMW operation");
  44. case AtomicRMWInst::Xchg:
  45. Res = Val;
  46. break;
  47. case AtomicRMWInst::Add:
  48. Res = Builder.CreateAdd(Orig, Val);
  49. break;
  50. case AtomicRMWInst::Sub:
  51. Res = Builder.CreateSub(Orig, Val);
  52. break;
  53. case AtomicRMWInst::And:
  54. Res = Builder.CreateAnd(Orig, Val);
  55. break;
  56. case AtomicRMWInst::Nand:
  57. Res = Builder.CreateNot(Builder.CreateAnd(Orig, Val));
  58. break;
  59. case AtomicRMWInst::Or:
  60. Res = Builder.CreateOr(Orig, Val);
  61. break;
  62. case AtomicRMWInst::Xor:
  63. Res = Builder.CreateXor(Orig, Val);
  64. break;
  65. case AtomicRMWInst::Max:
  66. Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
  67. Val, Orig);
  68. break;
  69. case AtomicRMWInst::Min:
  70. Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
  71. Orig, Val);
  72. break;
  73. case AtomicRMWInst::UMax:
  74. Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
  75. Val, Orig);
  76. break;
  77. case AtomicRMWInst::UMin:
  78. Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
  79. Orig, Val);
  80. break;
  81. }
  82. Builder.CreateStore(Res, Ptr);
  83. RMWI->replaceAllUsesWith(Orig);
  84. RMWI->eraseFromParent();
  85. return true;
  86. }
  87. static bool LowerFenceInst(FenceInst *FI) {
  88. FI->eraseFromParent();
  89. return true;
  90. }
  91. static bool LowerLoadInst(LoadInst *LI) {
  92. LI->setAtomic(NotAtomic);
  93. return true;
  94. }
  95. static bool LowerStoreInst(StoreInst *SI) {
  96. SI->setAtomic(NotAtomic);
  97. return true;
  98. }
  99. namespace {
  100. struct LowerAtomic : public BasicBlockPass {
  101. static char ID;
  102. LowerAtomic() : BasicBlockPass(ID) {
  103. initializeLowerAtomicPass(*PassRegistry::getPassRegistry());
  104. }
  105. bool runOnBasicBlock(BasicBlock &BB) override {
  106. if (skipOptnoneFunction(BB))
  107. return false;
  108. bool Changed = false;
  109. for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {
  110. Instruction *Inst = DI++;
  111. if (FenceInst *FI = dyn_cast<FenceInst>(Inst))
  112. Changed |= LowerFenceInst(FI);
  113. else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(Inst))
  114. Changed |= LowerAtomicCmpXchgInst(CXI);
  115. else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(Inst))
  116. Changed |= LowerAtomicRMWInst(RMWI);
  117. else if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
  118. if (LI->isAtomic())
  119. LowerLoadInst(LI);
  120. } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
  121. if (SI->isAtomic())
  122. LowerStoreInst(SI);
  123. }
  124. }
  125. return Changed;
  126. }
  127. };
  128. }
  129. char LowerAtomic::ID = 0;
  130. INITIALIZE_PASS(LowerAtomic, "loweratomic",
  131. "Lower atomic intrinsics to non-atomic form",
  132. false, false)
  133. Pass *llvm::createLowerAtomicPass() { return new LowerAtomic(); }