LowerAtomic.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //===- LowerAtomic.cpp - Lower atomic intrinsics --------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This pass lowers atomic intrinsics to non-atomic form for use in a known
  10. // non-preemptible environment.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Transforms/Utils/LowerAtomic.h"
  14. #include "llvm/IR/Function.h"
  15. #include "llvm/IR/IRBuilder.h"
  16. #include "llvm/InitializePasses.h"
  17. #include "llvm/Pass.h"
  18. using namespace llvm;
  19. #define DEBUG_TYPE "loweratomic"
  20. bool llvm::lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI) {
  21. IRBuilder<> Builder(CXI);
  22. Value *Ptr = CXI->getPointerOperand();
  23. Value *Cmp = CXI->getCompareOperand();
  24. Value *Val = CXI->getNewValOperand();
  25. LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
  26. Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
  27. Value *Res = Builder.CreateSelect(Equal, Val, Orig);
  28. Builder.CreateStore(Res, Ptr);
  29. Res = Builder.CreateInsertValue(PoisonValue::get(CXI->getType()), Orig, 0);
  30. Res = Builder.CreateInsertValue(Res, Equal, 1);
  31. CXI->replaceAllUsesWith(Res);
  32. CXI->eraseFromParent();
  33. return true;
  34. }
  35. Value *llvm::buildAtomicRMWValue(AtomicRMWInst::BinOp Op,
  36. IRBuilderBase &Builder, Value *Loaded,
  37. Value *Val) {
  38. Value *NewVal;
  39. switch (Op) {
  40. case AtomicRMWInst::Xchg:
  41. return Val;
  42. case AtomicRMWInst::Add:
  43. return Builder.CreateAdd(Loaded, Val, "new");
  44. case AtomicRMWInst::Sub:
  45. return Builder.CreateSub(Loaded, Val, "new");
  46. case AtomicRMWInst::And:
  47. return Builder.CreateAnd(Loaded, Val, "new");
  48. case AtomicRMWInst::Nand:
  49. return Builder.CreateNot(Builder.CreateAnd(Loaded, Val), "new");
  50. case AtomicRMWInst::Or:
  51. return Builder.CreateOr(Loaded, Val, "new");
  52. case AtomicRMWInst::Xor:
  53. return Builder.CreateXor(Loaded, Val, "new");
  54. case AtomicRMWInst::Max:
  55. NewVal = Builder.CreateICmpSGT(Loaded, Val);
  56. return Builder.CreateSelect(NewVal, Loaded, Val, "new");
  57. case AtomicRMWInst::Min:
  58. NewVal = Builder.CreateICmpSLE(Loaded, Val);
  59. return Builder.CreateSelect(NewVal, Loaded, Val, "new");
  60. case AtomicRMWInst::UMax:
  61. NewVal = Builder.CreateICmpUGT(Loaded, Val);
  62. return Builder.CreateSelect(NewVal, Loaded, Val, "new");
  63. case AtomicRMWInst::UMin:
  64. NewVal = Builder.CreateICmpULE(Loaded, Val);
  65. return Builder.CreateSelect(NewVal, Loaded, Val, "new");
  66. case AtomicRMWInst::FAdd:
  67. return Builder.CreateFAdd(Loaded, Val, "new");
  68. case AtomicRMWInst::FSub:
  69. return Builder.CreateFSub(Loaded, Val, "new");
  70. case AtomicRMWInst::FMax:
  71. return Builder.CreateMaxNum(Loaded, Val);
  72. case AtomicRMWInst::FMin:
  73. return Builder.CreateMinNum(Loaded, Val);
  74. case AtomicRMWInst::UIncWrap: {
  75. Constant *One = ConstantInt::get(Loaded->getType(), 1);
  76. Value *Inc = Builder.CreateAdd(Loaded, One);
  77. Value *Cmp = Builder.CreateICmpUGE(Loaded, Val);
  78. Constant *Zero = ConstantInt::get(Loaded->getType(), 0);
  79. return Builder.CreateSelect(Cmp, Zero, Inc, "new");
  80. }
  81. case AtomicRMWInst::UDecWrap: {
  82. Constant *Zero = ConstantInt::get(Loaded->getType(), 0);
  83. Constant *One = ConstantInt::get(Loaded->getType(), 1);
  84. Value *Dec = Builder.CreateSub(Loaded, One);
  85. Value *CmpEq0 = Builder.CreateICmpEQ(Loaded, Zero);
  86. Value *CmpOldGtVal = Builder.CreateICmpUGT(Loaded, Val);
  87. Value *Or = Builder.CreateOr(CmpEq0, CmpOldGtVal);
  88. return Builder.CreateSelect(Or, Val, Dec, "new");
  89. }
  90. default:
  91. llvm_unreachable("Unknown atomic op");
  92. }
  93. }
  94. bool llvm::lowerAtomicRMWInst(AtomicRMWInst *RMWI) {
  95. IRBuilder<> Builder(RMWI);
  96. Value *Ptr = RMWI->getPointerOperand();
  97. Value *Val = RMWI->getValOperand();
  98. LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
  99. Value *Res = buildAtomicRMWValue(RMWI->getOperation(), Builder, Orig, Val);
  100. Builder.CreateStore(Res, Ptr);
  101. RMWI->replaceAllUsesWith(Orig);
  102. RMWI->eraseFromParent();
  103. return true;
  104. }