LLVM 20.0.0git
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
13#include "InstCombineInternal.h"
15
16using namespace llvm;
17
18namespace {
19/// Return true if and only if the given instruction does not modify the memory
20/// location referenced. Note that an idemptent atomicrmw may still have
21/// ordering effects on nearby instructions, or be volatile.
22/// TODO: Common w/ the version in AtomicExpandPass, and change the term used.
23/// Idemptotent is confusing in this context.
24bool isIdempotentRMW(AtomicRMWInst& RMWI) {
25 if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
26 switch(RMWI.getOperation()) {
27 case AtomicRMWInst::FAdd: // -0.0
28 return CF->isZero() && CF->isNegative();
29 case AtomicRMWInst::FSub: // +0.0
30 return CF->isZero() && !CF->isNegative();
31 default:
32 return false;
33 };
34
35 auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
36 if(!C)
37 return false;
38
39 switch(RMWI.getOperation()) {
44 return C->isZero();
46 return C->isMinusOne();
48 return C->isMaxValue(true);
50 return C->isMinValue(true);
52 return C->isMaxValue(false);
54 return C->isMinValue(false);
55 default:
56 return false;
57 }
58}
59
60/// Return true if the given instruction always produces a value in memory
61/// equivalent to its value operand.
62bool isSaturating(AtomicRMWInst& RMWI) {
63 if (auto CF = dyn_cast<ConstantFP>(RMWI.getValOperand()))
64 switch (RMWI.getOperation()) {
66 // maxnum(x, +inf) -> +inf
67 return !CF->isNegative() && CF->isInfinity();
69 // minnum(x, -inf) -> +inf
70 return CF->isNegative() && CF->isInfinity();
73 return CF->isNaN();
74 default:
75 return false;
76 };
77
78 auto C = dyn_cast<ConstantInt>(RMWI.getValOperand());
79 if(!C)
80 return false;
81
82 switch(RMWI.getOperation()) {
83 default:
84 return false;
86 return true;
88 return C->isAllOnesValue();
90 return C->isZero();
92 return C->isMinValue(true);
94 return C->isMaxValue(true);
96 return C->isMinValue(false);
98 return C->isMaxValue(false);
99 };
100}
101} // namespace
102
104
105 // Volatile RMWs perform a load and a store, we cannot replace this by just a
106 // load or just a store. We chose not to canonicalize out of general paranoia
107 // about user expectations around volatile.
108 if (RMWI.isVolatile())
109 return nullptr;
110
111 // Any atomicrmw op which produces a known result in memory can be
112 // replaced w/an atomicrmw xchg.
113 if (isSaturating(RMWI) &&
116 return &RMWI;
117 }
118
121 "AtomicRMWs don't make sense with Unordered or NotAtomic");
122
123 if (!isIdempotentRMW(RMWI))
124 return nullptr;
125
126 // We chose to canonicalize all idempotent operations to an single
127 // operation code and constant. This makes it easier for the rest of the
128 // optimizer to match easily. The choices of or w/0 and fadd w/-0.0 are
129 // arbitrary.
130 if (RMWI.getType()->isIntegerTy() &&
133 return replaceOperand(RMWI, 1, ConstantInt::get(RMWI.getType(), 0));
134 } else if (RMWI.getType()->isFloatingPointTy() &&
137 return replaceOperand(RMWI, 1, ConstantFP::getNegativeZero(RMWI.getType()));
138 }
139
140 return nullptr;
141}
This file provides internal interfaces used to implement the InstCombine.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:704
bool isVolatile() const
Return true if this is a RMW on a volatile memory location.
Definition: Instructions.h:837
@ Add
*p = old + v
Definition: Instructions.h:720
@ FAdd
*p = old + v
Definition: Instructions.h:741
@ Min
*p = old <signed v ? old : v
Definition: Instructions.h:734
@ Or
*p = old | v
Definition: Instructions.h:728
@ Sub
*p = old - v
Definition: Instructions.h:722
@ And
*p = old & v
Definition: Instructions.h:724
@ Xor
*p = old ^ v
Definition: Instructions.h:730
@ FSub
*p = old - v
Definition: Instructions.h:744
@ Max
*p = old >signed v ? old : v
Definition: Instructions.h:732
@ UMin
*p = old <unsigned v ? old : v
Definition: Instructions.h:738
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
Definition: Instructions.h:752
@ UMax
*p = old >unsigned v ? old : v
Definition: Instructions.h:736
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
Definition: Instructions.h:748
void setOperation(BinOp Operation)
Definition: Instructions.h:821
BinOp getOperation() const
Definition: Instructions.h:805
Value * getValOperand()
Definition: Instructions.h:874
AtomicOrdering getOrdering() const
Returns the ordering constraint of this rmw instruction.
Definition: Instructions.h:847
static Constant * getNegativeZero(Type *Ty)
Definition: Constants.h:309
Instruction * visitAtomicRMWInst(AtomicRMWInst &SI)
Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)
Replace operand of instruction and add old operand to the worklist.
Definition: InstCombiner.h:418
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition: Type.h:184
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:237
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18