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 
43 static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) {
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
This class represents lattice values for constants.
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:728
llvm::AtomicRMWInst::getOperation
BinOp getOperation() const
Definition: Instructions.h:781
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:842
llvm::AtomicCmpXchgInst::getNewValOperand
Value * getNewValOperand()
Definition: Instructions.h:634
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
SI
@ SI
Definition: SIInstrInfo.cpp:7358
llvm::Instruction
Definition: Instruction.h:45
llvm::AtomicRMWInst::Nand
@ Nand
*p = ~(old & v)
Definition: Instructions.h:724
llvm::UndefValue::get
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1751
llvm::AtomicRMWInst::Xchg
@ Xchg
*p = v
Definition: Instructions.h:716
llvm::AtomicRMWInst::Add
@ Add
*p = old + v
Definition: Instructions.h:718
llvm::AtomicRMWInst::UMin
@ UMin
*p = old <unsigned v ? old : v
Definition: Instructions.h:736
llvm::StoreInst
An instruction for storing to memory.
Definition: Instructions.h:303
llvm::Instruction::eraseFromParent
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:77
llvm::AtomicRMWInst::Sub
@ Sub
*p = old - v
Definition: Instructions.h:720
llvm::createLowerAtomicPass
Pass * createLowerAtomicPass()
llvm::AtomicRMWInst::Min
@ Min
*p = old <signed v ? old : v
Definition: Instructions.h:732
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:581
llvm::AtomicRMWInst::Or
@ Or
*p = old | v
Definition: Instructions.h:726
IRBuilder.h
llvm::AtomicCmpXchgInst::getCompareOperand
Value * getCompareOperand()
Definition: Instructions.h:631
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:643
LowerAtomicRMWInst
static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI)
Definition: LowerAtomic.cpp:43
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:246
llvm::Value::replaceAllUsesWith
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:523
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:252
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:174
llvm::AtomicRMWInst
an instruction that atomically reads a memory location, combines it with another value,...
Definition: Instructions.h:702
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::AtomicRMWInst::FSub
@ FSub
*p = old - v
Definition: Instructions.h:742
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:722
Function.h
llvm::AtomicCmpXchgInst::getPointerOperand
Value * getPointerOperand()
Definition: Instructions.h:627
llvm::AtomicRMWInst::getValOperand
Value * getValOperand()
Definition: Instructions.h:846
llvm::Pass
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:91
llvm::AtomicRMWInst::FAdd
@ FAdd
*p = old + v
Definition: Instructions.h:739
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:43
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:734
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:522
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:37
llvm::AtomicRMWInst::Max
@ Max
*p = old >signed v ? old : v
Definition: Instructions.h:730