LLVM  10.0.0svn
InstCombineAtomicRMW.cpp
Go to the documentation of this file.
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 
15 using namespace llvm;
16 
17 namespace {
18 /// Return true if and only if the given instruction does not modify the memory
19 /// location referenced. Note that an idemptent atomicrmw may still have
20 /// ordering effects on nearby instructions, or be volatile.
21 /// TODO: Common w/ the version in AtomicExpandPass, and change the term used.
22 /// Idemptotent is confusing in this context.
23 bool isIdempotentRMW(AtomicRMWInst& RMWI) {
24  if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
25  switch(RMWI.getOperation()) {
26  case AtomicRMWInst::FAdd: // -0.0
27  return CF->isZero() && CF->isNegative();
28  case AtomicRMWInst::FSub: // +0.0
29  return CF->isZero() && !CF->isNegative();
30  default:
31  return false;
32  };
33 
34  auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
35  if(!C)
36  return false;
37 
38  switch(RMWI.getOperation()) {
39  case AtomicRMWInst::Add:
40  case AtomicRMWInst::Sub:
41  case AtomicRMWInst::Or:
42  case AtomicRMWInst::Xor:
43  return C->isZero();
44  case AtomicRMWInst::And:
45  return C->isMinusOne();
46  case AtomicRMWInst::Min:
47  return C->isMaxValue(true);
48  case AtomicRMWInst::Max:
49  return C->isMinValue(true);
51  return C->isMaxValue(false);
53  return C->isMinValue(false);
54  default:
55  return false;
56  }
57 }
58 
59 /// Return true if the given instruction always produces a value in memory
60 /// equivalent to its value operand.
61 bool isSaturating(AtomicRMWInst& RMWI) {
62  if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
63  switch(RMWI.getOperation()) {
66  return CF->isNaN();
67  default:
68  return false;
69  };
70 
71  auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
72  if(!C)
73  return false;
74 
75  switch(RMWI.getOperation()) {
76  default:
77  return false;
79  return true;
80  case AtomicRMWInst::Or:
81  return C->isAllOnesValue();
82  case AtomicRMWInst::And:
83  return C->isZero();
84  case AtomicRMWInst::Min:
85  return C->isMinValue(true);
86  case AtomicRMWInst::Max:
87  return C->isMaxValue(true);
89  return C->isMinValue(false);
91  return C->isMaxValue(false);
92  };
93 }
94 }
95 
97 
98  // Volatile RMWs perform a load and a store, we cannot replace this by just a
99  // load or just a store. We chose not to canonicalize out of general paranoia
100  // about user expectations around volatile.
101  if (RMWI.isVolatile())
102  return nullptr;
103 
104  // Any atomicrmw op which produces a known result in memory can be
105  // replaced w/an atomicrmw xchg.
106  if (isSaturating(RMWI) &&
107  RMWI.getOperation() != AtomicRMWInst::Xchg) {
109  return &RMWI;
110  }
111 
112  AtomicOrdering Ordering = RMWI.getOrdering();
113  assert(Ordering != AtomicOrdering::NotAtomic &&
114  Ordering != AtomicOrdering::Unordered &&
115  "AtomicRMWs don't make sense with Unordered or NotAtomic");
116 
117  // Any atomicrmw xchg with no uses can be converted to a atomic store if the
118  // ordering is compatible.
119  if (RMWI.getOperation() == AtomicRMWInst::Xchg &&
120  RMWI.use_empty()) {
121  if (Ordering != AtomicOrdering::Release &&
122  Ordering != AtomicOrdering::Monotonic)
123  return nullptr;
124  auto *SI = new StoreInst(RMWI.getValOperand(),
125  RMWI.getPointerOperand(), &RMWI);
126  SI->setAtomic(Ordering, RMWI.getSyncScopeID());
127  SI->setAlignment(MaybeAlign(DL.getABITypeAlignment(RMWI.getType())));
128  return eraseInstFromFunction(RMWI);
129  }
130 
131  if (!isIdempotentRMW(RMWI))
132  return nullptr;
133 
134  // We chose to canonicalize all idempotent operations to an single
135  // operation code and constant. This makes it easier for the rest of the
136  // optimizer to match easily. The choices of or w/0 and fadd w/-0.0 are
137  // arbitrary.
138  if (RMWI.getType()->isIntegerTy() &&
139  RMWI.getOperation() != AtomicRMWInst::Or) {
141  RMWI.setOperand(1, ConstantInt::get(RMWI.getType(), 0));
142  return &RMWI;
143  } else if (RMWI.getType()->isFloatingPointTy() &&
144  RMWI.getOperation() != AtomicRMWInst::FAdd) {
147  return &RMWI;
148  }
149 
150  // Check if the required ordering is compatible with an atomic load.
151  if (Ordering != AtomicOrdering::Acquire &&
152  Ordering != AtomicOrdering::Monotonic)
153  return nullptr;
154 
155  LoadInst *Load = new LoadInst(RMWI.getType(), RMWI.getPointerOperand());
156  Load->setAtomic(Ordering, RMWI.getSyncScopeID());
158  return Load;
159 }
uint64_t CallInst * C
*p = old <signed v ? old : v
Definition: Instructions.h:731
Instruction * visitAtomicRMWInst(AtomicRMWInst &SI)
This class represents lattice values for constants.
Definition: AllocatorList.h:23
*p = old <unsigned v ? old : v
Definition: Instructions.h:735
*p = old >unsigned v ? old : v
Definition: Instructions.h:733
An instruction for reading from memory.
Definition: Instructions.h:169
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
Definition: Instructions.h:701
*p = old >signed v ? old : v
Definition: Instructions.h:729
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
Definition: Instructions.h:275
static Constant * getNegativeZero(Type *Ty)
Definition: Constants.cpp:790
bool isFloatingPointTy() const
Return true if this is one of the six floating-point types.
Definition: Type.h:162
BinOp getOperation() const
Definition: Instructions.h:760
Instruction * eraseInstFromFunction(Instruction &I)
Combiner aware instruction erasure.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:197
AtomicOrdering
Atomic ordering for LLVM&#39;s memory model.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:246
An instruction for storing to memory.
Definition: Instructions.h:325
SyncScope::ID getSyncScopeID() const
Returns the synchronization scope ID of this rmw instruction.
Definition: Instructions.h:812
void setAlignment(MaybeAlign Align)
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
Definition: Instructions.h:799
Value * getValOperand()
Definition: Instructions.h:825
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
This struct is a compact representation of a valid (power of two) or undefined (0) alignment...
Definition: Alignment.h:117
unsigned getABITypeAlignment(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Definition: DataLayout.cpp:755
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:653
void setOperand(unsigned i, Value *Val)
Definition: User.h:174
void setOperation(BinOp Operation)
Definition: Instructions.h:776
Value * getPointerOperand()
Definition: Instructions.h:821
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file provides internal interfaces used to implement the InstCombine.
bool use_empty() const
Definition: Value.h:343
bool isVolatile() const
Return true if this is a RMW on a volatile memory location.
Definition: Instructions.h:784