LLVM  13.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 #include "llvm/InitializePasses.h"
18 #include "llvm/Pass.h"
19 #include "llvm/Transforms/Scalar.h"
20 using namespace llvm;
21 
22 #define DEBUG_TYPE "loweratomic"
23 
25  IRBuilder<> Builder(CXI);
26  Value *Ptr = CXI->getPointerOperand();
27  Value *Cmp = CXI->getCompareOperand();
28  Value *Val = CXI->getNewValOperand();
29 
30  LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
31  Value *Equal = Builder.CreateICmpEQ(Orig, Cmp);
32  Value *Res = Builder.CreateSelect(Equal, Val, Orig);
33  Builder.CreateStore(Res, Ptr);
34 
35  Res = Builder.CreateInsertValue(UndefValue::get(CXI->getType()), Orig, 0);
36  Res = Builder.CreateInsertValue(Res, Equal, 1);
37 
38  CXI->replaceAllUsesWith(Res);
39  CXI->eraseFromParent();
40  return true;
41 }
42 
44  IRBuilder<> Builder(RMWI);
45  Value *Ptr = RMWI->getPointerOperand();
46  Value *Val = RMWI->getValOperand();
47 
48  LoadInst *Orig = Builder.CreateLoad(Val->getType(), Ptr);
49  Value *Res = nullptr;
50 
51  switch (RMWI->getOperation()) {
52  default: llvm_unreachable("Unexpected RMW operation");
54  Res = Val;
55  break;
56  case AtomicRMWInst::Add:
57  Res = Builder.CreateAdd(Orig, Val);
58  break;
59  case AtomicRMWInst::Sub:
60  Res = Builder.CreateSub(Orig, Val);
61  break;
62  case AtomicRMWInst::And:
63  Res = Builder.CreateAnd(Orig, Val);
64  break;
66  Res = Builder.CreateNot(Builder.CreateAnd(Orig, Val));
67  break;
68  case AtomicRMWInst::Or:
69  Res = Builder.CreateOr(Orig, Val);
70  break;
71  case AtomicRMWInst::Xor:
72  Res = Builder.CreateXor(Orig, Val);
73  break;
74  case AtomicRMWInst::Max:
75  Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
76  Val, Orig);
77  break;
78  case AtomicRMWInst::Min:
79  Res = Builder.CreateSelect(Builder.CreateICmpSLT(Orig, Val),
80  Orig, Val);
81  break;
83  Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
84  Val, Orig);
85  break;
87  Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val),
88  Orig, Val);
89  break;
91  Res = Builder.CreateFAdd(Orig, Val);
92  break;
94  Res = Builder.CreateFSub(Orig, Val);
95  break;
96  }
97  Builder.CreateStore(Res, Ptr);
98  RMWI->replaceAllUsesWith(Orig);
99  RMWI->eraseFromParent();
100  return true;
101 }
102 
103 static bool LowerFenceInst(FenceInst *FI) {
104  FI->eraseFromParent();
105  return true;
106 }
107 
108 static bool LowerLoadInst(LoadInst *LI) {
110  return true;
111 }
112 
113 static bool LowerStoreInst(StoreInst *SI) {
114  SI->setAtomic(AtomicOrdering::NotAtomic);
115  return true;
116 }
117 
119  bool Changed = false;
120  for (Instruction &Inst : make_early_inc_range(BB)) {
121  if (FenceInst *FI = dyn_cast<FenceInst>(&Inst))
122  Changed |= LowerFenceInst(FI);
123  else if (AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&Inst))
124  Changed |= LowerAtomicCmpXchgInst(CXI);
125  else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&Inst))
126  Changed |= lowerAtomicRMWInst(RMWI);
127  else if (LoadInst *LI = dyn_cast<LoadInst>(&Inst)) {
128  if (LI->isAtomic())
129  LowerLoadInst(LI);
130  } else if (StoreInst *SI = dyn_cast<StoreInst>(&Inst)) {
131  if (SI->isAtomic())
133  }
134  }
135  return Changed;
136 }
137 
138 static bool lowerAtomics(Function &F) {
139  bool Changed = false;
140  for (BasicBlock &BB : F) {
141  Changed |= runOnBasicBlock(BB);
142  }
143  return Changed;
144 }
145 
147  if (lowerAtomics(F))
148  return PreservedAnalyses::none();
149  return PreservedAnalyses::all();
150 }
151 
152 namespace {
153 class LowerAtomicLegacyPass : public FunctionPass {
154 public:
155  static char ID;
156 
157  LowerAtomicLegacyPass() : FunctionPass(ID) {
159  }
160 
161  bool runOnFunction(Function &F) override {
162  // Don't skip optnone functions; atomics still need to be lowered.
163  FunctionAnalysisManager DummyFAM;
164  auto PA = Impl.run(F, DummyFAM);
165  return !PA.areAllPreserved();
166  }
167 
168 private:
169  LowerAtomicPass Impl;
170  };
171 }
172 
174 INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic",
175  "Lower atomic intrinsics to non-atomic form", false, false)
176 
177 Pass *llvm::createLowerAtomicPass() { return new LowerAtomicLegacyPass(); }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm::object::Equal
@ Equal
Definition: COFFModuleDefinition.cpp:38
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::LowerAtomicPass
A pass that lowers atomic intrinsic into non-atomic intrinsics.
Definition: LowerAtomic.h:22
Scalar.h
llvm::Function
Definition: Function.h:61
llvm::initializeLowerAtomicLegacyPassPass
void initializeLowerAtomicLegacyPassPass(PassRegistry &)
Pass.h
llvm::AtomicRMWInst::Xor
@ Xor
*p = old ^ v
Definition: Instructions.h:752
llvm::AtomicRMWInst::getOperation
BinOp getOperation() const
Definition: Instructions.h:804
LowerAtomicCmpXchgInst
static bool LowerAtomicCmpXchgInst(AtomicCmpXchgInst *CXI)
Definition: LowerAtomic.cpp:24
LowerAtomic.h
LowerFenceInst
static bool LowerFenceInst(FenceInst *FI)
Definition: LowerAtomic.cpp:103
llvm::IRBuilder<>
llvm::PreservedAnalyses::none
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: PassManager.h:158
INITIALIZE_PASS
INITIALIZE_PASS(LowerAtomicLegacyPass, "loweratomic", "Lower atomic intrinsics to non-atomic form", false, false) Pass *llvm
Definition: LowerAtomic.cpp:174
llvm::FenceInst
An instruction for ordering other memory operations.
Definition: Instructions.h:444
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::AtomicRMWInst::getPointerOperand
Value * getPointerOperand()
Definition: Instructions.h:865
llvm::AtomicCmpXchgInst::getNewValOperand
Value * getNewValOperand()
Definition: Instructions.h:658
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
LowerStoreInst
static bool LowerStoreInst(StoreInst *SI)
Definition: LowerAtomic.cpp:113
llvm::Instruction
Definition: Instruction.h:45
llvm::AtomicRMWInst::Nand
@ Nand
*p = ~(old & v)
Definition: Instructions.h:748
llvm::UndefValue::get
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1784
llvm::AtomicRMWInst::Xchg
@ Xchg
*p = v
Definition: Instructions.h:740
llvm::AtomicRMWInst::Add
@ Add
*p = old + v
Definition: Instructions.h:742
llvm::AtomicRMWInst::UMin
@ UMin
*p = old <unsigned v ? old : v
Definition: Instructions.h:760
llvm::StoreInst
An instruction for storing to memory.
Definition: Instructions.h:304
llvm::Instruction::eraseFromParent
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:78
llvm::AtomicRMWInst::Sub
@ Sub
*p = old - v
Definition: Instructions.h:744
llvm::createLowerAtomicPass
Pass * createLowerAtomicPass()
llvm::AtomicRMWInst::Min
@ Min
*p = old <signed v ? old : v
Definition: Instructions.h:756
llvm::make_early_inc_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:572
llvm::AtomicRMWInst::Or
@ Or
*p = old | v
Definition: Instructions.h:750
llvm::lowerAtomicRMWInst
bool lowerAtomicRMWInst(AtomicRMWInst *RMWI)
Convert the given RMWI into primitive load and stores, assuming that doing so is legal.
Definition: LowerAtomic.cpp:43
IRBuilder.h
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::AtomicCmpXchgInst::getCompareOperand
Value * getCompareOperand()
Definition: Instructions.h:655
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:651
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:256
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:520
llvm::LoadInst::setAtomic
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:253
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:175
llvm::AtomicRMWInst
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:726
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::AtomicRMWInst::FSub
@ FSub
*p = old - v
Definition: Instructions.h:766
llvm::LowerAtomicPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &)
Definition: LowerAtomic.cpp:146
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
llvm::AtomicRMWInst::And
@ And
*p = old & v
Definition: Instructions.h:746
Function.h
llvm::AtomicCmpXchgInst::getPointerOperand
Value * getPointerOperand()
Definition: Instructions.h:651
llvm::AtomicRMWInst::getValOperand
Value * getValOperand()
Definition: Instructions.h:869
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
llvm::AtomicRMWInst::FAdd
@ FAdd
*p = old + v
Definition: Instructions.h:763
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::AtomicRMWInst::UMax
@ UMax
*p = old >unsigned v ? old : v
Definition: Instructions.h:758
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::AtomicCmpXchgInst
An instruction that atomically checks whether a specified value is in a memory location,...
Definition: Instructions.h:521
runOnBasicBlock
static bool runOnBasicBlock(BasicBlock &BB)
Definition: LowerAtomic.cpp:118
llvm::AtomicOrdering::NotAtomic
@ NotAtomic
lowerAtomics
static bool lowerAtomics(Function &F)
Definition: LowerAtomic.cpp:138
LowerLoadInst
static bool LowerLoadInst(LoadInst *LI)
Definition: LowerAtomic.cpp:108
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
llvm::AtomicRMWInst::Max
@ Max
*p = old >signed v ? old : v
Definition: Instructions.h:754