LLVM 20.0.0git
LowerAtomic.cpp
Go to the documentation of this file.
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
15#include "llvm/IR/Function.h"
16#include "llvm/IR/IRBuilder.h"
17
18using namespace llvm;
19
20#define DEBUG_TYPE "loweratomic"
21
23 IRBuilder<> Builder(CXI);
24 Value *Ptr = CXI->getPointerOperand();
25 Value *Cmp = CXI->getCompareOperand();
26 Value *Val = CXI->getNewValOperand();
27
28 auto [Orig, Equal] =
29 buildCmpXchgValue(Builder, Ptr, Cmp, Val, CXI->getAlign());
30
31 Value *Res =
32 Builder.CreateInsertValue(PoisonValue::get(CXI->getType()), Orig, 0);
33 Res = Builder.CreateInsertValue(Res, Equal, 1);
34
35 CXI->replaceAllUsesWith(Res);
36 CXI->eraseFromParent();
37 return true;
38}
39
40std::pair<Value *, Value *> llvm::buildCmpXchgValue(IRBuilderBase &Builder,
41 Value *Ptr, Value *Cmp,
42 Value *Val,
43 Align Alignment) {
44 LoadInst *Orig = Builder.CreateAlignedLoad(Val->getType(), Ptr, Alignment);
45 Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
46 Value *Res = Builder.CreateSelect(Equal, Val, Orig);
47 Builder.CreateAlignedStore(Res, Ptr, Alignment);
48
49 return {Orig, Equal};
50}
51
53 IRBuilderBase &Builder, Value *Loaded,
54 Value *Val) {
55 Value *NewVal;
56 switch (Op) {
58 return Val;
60 return Builder.CreateAdd(Loaded, Val, "new");
62 return Builder.CreateSub(Loaded, Val, "new");
64 return Builder.CreateAnd(Loaded, Val, "new");
66 return Builder.CreateNot(Builder.CreateAnd(Loaded, Val), "new");
68 return Builder.CreateOr(Loaded, Val, "new");
70 return Builder.CreateXor(Loaded, Val, "new");
72 NewVal = Builder.CreateICmpSGT(Loaded, Val);
73 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
75 NewVal = Builder.CreateICmpSLE(Loaded, Val);
76 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
78 NewVal = Builder.CreateICmpUGT(Loaded, Val);
79 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
81 NewVal = Builder.CreateICmpULE(Loaded, Val);
82 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
84 return Builder.CreateFAdd(Loaded, Val, "new");
86 return Builder.CreateFSub(Loaded, Val, "new");
88 return Builder.CreateMaxNum(Loaded, Val);
90 return Builder.CreateMinNum(Loaded, Val);
92 Constant *One = ConstantInt::get(Loaded->getType(), 1);
93 Value *Inc = Builder.CreateAdd(Loaded, One);
94 Value *Cmp = Builder.CreateICmpUGE(Loaded, Val);
95 Constant *Zero = ConstantInt::get(Loaded->getType(), 0);
96 return Builder.CreateSelect(Cmp, Zero, Inc, "new");
97 }
99 Constant *Zero = ConstantInt::get(Loaded->getType(), 0);
100 Constant *One = ConstantInt::get(Loaded->getType(), 1);
101
102 Value *Dec = Builder.CreateSub(Loaded, One);
103 Value *CmpEq0 = Builder.CreateICmpEQ(Loaded, Zero);
104 Value *CmpOldGtVal = Builder.CreateICmpUGT(Loaded, Val);
105 Value *Or = Builder.CreateOr(CmpEq0, CmpOldGtVal);
106 return Builder.CreateSelect(Or, Val, Dec, "new");
107 }
109 Value *Cmp = Builder.CreateICmpUGE(Loaded, Val);
110 Value *Sub = Builder.CreateSub(Loaded, Val);
111 return Builder.CreateSelect(Cmp, Sub, Loaded, "new");
112 }
114 return Builder.CreateIntrinsic(Intrinsic::usub_sat, Loaded->getType(),
115 {Loaded, Val}, nullptr, "new");
116 default:
117 llvm_unreachable("Unknown atomic op");
118 }
119}
120
122 IRBuilder<> Builder(RMWI);
123 Builder.setIsFPConstrained(
124 RMWI->getFunction()->hasFnAttribute(Attribute::StrictFP));
125
126 Value *Ptr = RMWI->getPointerOperand();
127 Value *Val = RMWI->getValOperand();
128
129 LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
130 Value *Res = buildAtomicRMWValue(RMWI->getOperation(), Builder, Orig, Val);
131 Builder.CreateStore(Res, Ptr);
132 RMWI->replaceAllUsesWith(Orig);
133 RMWI->eraseFromParent();
134 return true;
135}
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:501
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
Definition: Instructions.h:544
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:704
BinOp
This enumeration lists the possible modifications atomicrmw can make.
Definition: Instructions.h:716
@ Add
*p = old + v
Definition: Instructions.h:720
@ FAdd
*p = old + v
Definition: Instructions.h:741
@ USubCond
Subtract only if no unsigned overflow.
Definition: Instructions.h:764
@ 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
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
Definition: Instructions.h:768
@ FSub
*p = old - v
Definition: Instructions.h:744
@ UIncWrap
Increment one up to a maximum value.
Definition: Instructions.h:756
@ 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
@ UDecWrap
Decrement one until a minimum value or zero.
Definition: Instructions.h:760
@ Nand
*p = ~(old & v)
Definition: Instructions.h:726
Value * getPointerOperand()
Definition: Instructions.h:870
BinOp getOperation() const
Definition: Instructions.h:805
Value * getValOperand()
Definition: Instructions.h:874
This is an important base class in LLVM.
Definition: Constant.h:42
This class represents an Operation in the Expression.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:731
Common base class shared among various IRBuilders.
Definition: IRBuilder.h:91
Value * CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name="")
Create call to the maxnum intrinsic.
Definition: IRBuilder.h:997
Value * CreateFSub(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1583
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition: IRBuilder.h:2554
Value * CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2297
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Definition: IRBuilder.h:1830
Value * CreateFAdd(Value *L, Value *R, const Twine &Name="", MDNode *FPMD=nullptr)
Definition: IRBuilder.h:1556
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:890
Value * CreateMinNum(Value *LHS, Value *RHS, const Twine &Name="")
Create call to the minnum intrinsic.
Definition: IRBuilder.h:987
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Definition: IRBuilder.cpp:1048
Value * CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2309
Value * CreateNot(Value *V, const Twine &Name="")
Definition: IRBuilder.h:1772
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2273
void setIsFPConstrained(bool IsCon)
Enable/Disable use of constrained floating point math.
Definition: IRBuilder.h:314
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1367
Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2281
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition: IRBuilder.h:1813
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1498
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1826
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1350
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1520
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2285
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Definition: IRBuilder.h:1849
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:1542
Value * CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name="")
Definition: IRBuilder.h:2293
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:92
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:70
An instruction for reading from memory.
Definition: Instructions.h:176
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1878
LLVM Value Representation.
Definition: Value.h:74
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:534
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
std::pair< Value *, Value * > buildCmpXchgValue(IRBuilderBase &Builder, Value *Ptr, Value *Cmp, Value *Val, Align Alignment)
Emit IR to implement the given cmpxchg operation on values in registers, returning the new value.
Definition: LowerAtomic.cpp:40
Value * buildAtomicRMWValue(AtomicRMWInst::BinOp Op, IRBuilderBase &Builder, Value *Loaded, Value *Val)
Emit IR to implement the given atomicrmw operation on values in registers, returning the new value.
Definition: LowerAtomic.cpp:52
@ Or
Bitwise or logical OR of integers.
bool lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI)
Convert the given Cmpxchg into primitive load and compare.
Definition: LowerAtomic.cpp:22
bool lowerAtomicRMWInst(AtomicRMWInst *RMWI)
Convert the given RMWI into primitive load and stores, assuming that doing so is legal.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39