InstCombineAtomicRMW.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //===- InstCombineAtomicRMW.cpp -------------------------------------------===//
  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 file implements the visit functions for atomic rmw instructions.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "InstCombineInternal.h"
  13. #include "llvm/IR/Instructions.h"
  14. using namespace llvm;
  15. namespace {
  16. /// Return true if and only if the given instruction does not modify the memory
  17. /// location referenced. Note that an idemptent atomicrmw may still have
  18. /// ordering effects on nearby instructions, or be volatile.
  19. /// TODO: Common w/ the version in AtomicExpandPass, and change the term used.
  20. /// Idemptotent is confusing in this context.
  21. bool isIdempotentRMW(AtomicRMWInst& RMWI) {
  22. if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
  23. switch(RMWI.getOperation()) {
  24. case AtomicRMWInst::FAdd: // -0.0
  25. return CF->isZero() && CF->isNegative();
  26. case AtomicRMWInst::FSub: // +0.0
  27. return CF->isZero() && !CF->isNegative();
  28. default:
  29. return false;
  30. };
  31. auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
  32. if(!C)
  33. return false;
  34. switch(RMWI.getOperation()) {
  35. case AtomicRMWInst::Add:
  36. case AtomicRMWInst::Sub:
  37. case AtomicRMWInst::Or:
  38. case AtomicRMWInst::Xor:
  39. return C->isZero();
  40. case AtomicRMWInst::And:
  41. return C->isMinusOne();
  42. case AtomicRMWInst::Min:
  43. return C->isMaxValue(true);
  44. case AtomicRMWInst::Max:
  45. return C->isMinValue(true);
  46. case AtomicRMWInst::UMin:
  47. return C->isMaxValue(false);
  48. case AtomicRMWInst::UMax:
  49. return C->isMinValue(false);
  50. default:
  51. return false;
  52. }
  53. }
  54. /// Return true if the given instruction always produces a value in memory
  55. /// equivalent to its value operand.
  56. bool isSaturating(AtomicRMWInst& RMWI) {
  57. if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
  58. switch (RMWI.getOperation()) {
  59. case AtomicRMWInst::FMax:
  60. // maxnum(x, +inf) -> +inf
  61. return !CF->isNegative() && CF->isInfinity();
  62. case AtomicRMWInst::FMin:
  63. // minnum(x, -inf) -> +inf
  64. return CF->isNegative() && CF->isInfinity();
  65. case AtomicRMWInst::FAdd:
  66. case AtomicRMWInst::FSub:
  67. return CF->isNaN();
  68. default:
  69. return false;
  70. };
  71. auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
  72. if(!C)
  73. return false;
  74. switch(RMWI.getOperation()) {
  75. default:
  76. return false;
  77. case AtomicRMWInst::Xchg:
  78. return true;
  79. case AtomicRMWInst::Or:
  80. return C->isAllOnesValue();
  81. case AtomicRMWInst::And:
  82. return C->isZero();
  83. case AtomicRMWInst::Min:
  84. return C->isMinValue(true);
  85. case AtomicRMWInst::Max:
  86. return C->isMaxValue(true);
  87. case AtomicRMWInst::UMin:
  88. return C->isMinValue(false);
  89. case AtomicRMWInst::UMax:
  90. return C->isMaxValue(false);
  91. };
  92. }
  93. } // namespace
  94. Instruction *InstCombinerImpl::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
  95. // Volatile RMWs perform a load and a store, we cannot replace this by just a
  96. // load or just a store. We chose not to canonicalize out of general paranoia
  97. // about user expectations around volatile.
  98. if (RMWI.isVolatile())
  99. return nullptr;
  100. // Any atomicrmw op which produces a known result in memory can be
  101. // replaced w/an atomicrmw xchg.
  102. if (isSaturating(RMWI) &&
  103. RMWI.getOperation() != AtomicRMWInst::Xchg) {
  104. RMWI.setOperation(AtomicRMWInst::Xchg);
  105. return &RMWI;
  106. }
  107. AtomicOrdering Ordering = RMWI.getOrdering();
  108. assert(Ordering != AtomicOrdering::NotAtomic &&
  109. Ordering != AtomicOrdering::Unordered &&
  110. "AtomicRMWs don't make sense with Unordered or NotAtomic");
  111. // Any atomicrmw xchg with no uses can be converted to a atomic store if the
  112. // ordering is compatible.
  113. if (RMWI.getOperation() == AtomicRMWInst::Xchg &&
  114. RMWI.use_empty()) {
  115. if (Ordering != AtomicOrdering::Release &&
  116. Ordering != AtomicOrdering::Monotonic)
  117. return nullptr;
  118. new StoreInst(RMWI.getValOperand(), RMWI.getPointerOperand(),
  119. /*isVolatile*/ false, RMWI.getAlign(), Ordering,
  120. RMWI.getSyncScopeID(), &RMWI);
  121. return eraseInstFromFunction(RMWI);
  122. }
  123. if (!isIdempotentRMW(RMWI))
  124. return nullptr;
  125. // We chose to canonicalize all idempotent operations to an single
  126. // operation code and constant. This makes it easier for the rest of the
  127. // optimizer to match easily. The choices of or w/0 and fadd w/-0.0 are
  128. // arbitrary.
  129. if (RMWI.getType()->isIntegerTy() &&
  130. RMWI.getOperation() != AtomicRMWInst::Or) {
  131. RMWI.setOperation(AtomicRMWInst::Or);
  132. return replaceOperand(RMWI, 1, ConstantInt::get(RMWI.getType(), 0));
  133. } else if (RMWI.getType()->isFloatingPointTy() &&
  134. RMWI.getOperation() != AtomicRMWInst::FAdd) {
  135. RMWI.setOperation(AtomicRMWInst::FAdd);
  136. return replaceOperand(RMWI, 1, ConstantFP::getNegativeZero(RMWI.getType()));
  137. }
  138. return nullptr;
  139. }