LLVM 17.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"
18#include "llvm/Pass.h"
19using namespace llvm;
20
21#define DEBUG_TYPE "loweratomic"
22
25 Value *Ptr = CXI->getPointerOperand();
26 Value *Cmp = CXI->getCompareOperand();
27 Value *Val = CXI->getNewValOperand();
28
29 LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
30 Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
31 Value *Res = Builder.CreateSelect(Equal, Val, Orig);
32 Builder.CreateStore(Res, Ptr);
33
34 Res = Builder.CreateInsertValue(PoisonValue::get(CXI->getType()), Orig, 0);
35 Res = Builder.CreateInsertValue(Res, Equal, 1);
36
37 CXI->replaceAllUsesWith(Res);
38 CXI->eraseFromParent();
39 return true;
40}
41
43 IRBuilderBase &Builder, Value *Loaded,
44 Value *Val) {
45 Value *NewVal;
46 switch (Op) {
48 return Val;
50 return Builder.CreateAdd(Loaded, Val, "new");
52 return Builder.CreateSub(Loaded, Val, "new");
54 return Builder.CreateAnd(Loaded, Val, "new");
56 return Builder.CreateNot(Builder.CreateAnd(Loaded, Val), "new");
58 return Builder.CreateOr(Loaded, Val, "new");
60 return Builder.CreateXor(Loaded, Val, "new");
62 NewVal = Builder.CreateICmpSGT(Loaded, Val);
63 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
65 NewVal = Builder.CreateICmpSLE(Loaded, Val);
66 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
68 NewVal = Builder.CreateICmpUGT(Loaded, Val);
69 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
71 NewVal = Builder.CreateICmpULE(Loaded, Val);
72 return Builder.CreateSelect(NewVal, Loaded, Val, "new");
74 return Builder.CreateFAdd(Loaded, Val, "new");
76 return Builder.CreateFSub(Loaded, Val, "new");
78 return Builder.CreateMaxNum(Loaded, Val);
80 return Builder.CreateMinNum(Loaded, Val);
82 Constant *One = ConstantInt::get(Loaded->getType(), 1);
83 Value *Inc = Builder.CreateAdd(Loaded, One);
84 Value *Cmp = Builder.CreateICmpUGE(Loaded, Val);
85 Constant *Zero = ConstantInt::get(Loaded->getType(), 0);
86 return Builder.CreateSelect(Cmp, Zero, Inc, "new");
87 }
89 Constant *Zero = ConstantInt::get(Loaded->getType(), 0);
90 Constant *One = ConstantInt::get(Loaded->getType(), 1);
91
92 Value *Dec = Builder.CreateSub(Loaded, One);
93 Value *CmpEq0 = Builder.CreateICmpEQ(Loaded, Zero);
94 Value *CmpOldGtVal = Builder.CreateICmpUGT(Loaded, Val);
95 Value *Or = Builder.CreateOr(CmpEq0, CmpOldGtVal);
96 return Builder.CreateSelect(Or, Val, Dec, "new");
97 }
98 default:
99 llvm_unreachable("Unknown atomic op");
100 }
101}
102
104 IRBuilder<> Builder(RMWI);
105 Value *Ptr = RMWI->getPointerOperand();
106 Value *Val = RMWI->getValOperand();
107
108 LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
109 Value *Res = buildAtomicRMWValue(RMWI->getOperation(), Builder, Orig, Val);
110 Builder.CreateStore(Res, Ptr);
111 RMWI->replaceAllUsesWith(Orig);
112 RMWI->eraseFromParent();
113 return true;
114}
assume Assume Builder
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:513
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:718
BinOp
This enumeration lists the possible modifications atomicrmw can make.
Definition: Instructions.h:730
@ Add
*p = old + v
Definition: Instructions.h:734
@ FAdd
*p = old + v
Definition: Instructions.h:755
@ Min
*p = old <signed v ? old : v
Definition: Instructions.h:748
@ Or
*p = old | v
Definition: Instructions.h:742
@ Sub
*p = old - v
Definition: Instructions.h:736
@ And
*p = old & v
Definition: Instructions.h:738
@ Xor
*p = old ^ v
Definition: Instructions.h:744
@ FSub
*p = old - v
Definition: Instructions.h:758
@ UIncWrap
Increment one up to a maximum value.
Definition: Instructions.h:770
@ Max
*p = old >signed v ? old : v
Definition: Instructions.h:746
@ UMin
*p = old <unsigned v ? old : v
Definition: Instructions.h:752
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
Definition: Instructions.h:766
@ UMax
*p = old >unsigned v ? old : v
Definition: Instructions.h:750
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
Definition: Instructions.h:762
@ UDecWrap
Decrement one until a minimum value or zero.
Definition: Instructions.h:774
@ Nand
*p = ~(old & v)
Definition: Instructions.h:740
Value * getPointerOperand()
Definition: Instructions.h:877
BinOp getOperation() const
Definition: Instructions.h:812
Value * getValOperand()
Definition: Instructions.h:881
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:888
This is an important base class in LLVM.
Definition: Constant.h:41
Common base class shared among various IRBuilders.
Definition: IRBuilder.h:94
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2558
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:82
An instruction for reading from memory.
Definition: Instructions.h:177
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1750
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:532
#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
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:42
@ Or
Bitwise or logical OR of integers.
bool lowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI)
Convert the given Cmpxchg into primitive load and compare.
Definition: LowerAtomic.cpp:23
bool lowerAtomicRMWInst(AtomicRMWInst *RMWI)
Convert the given RMWI into primitive load and stores, assuming that doing so is legal.