Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: lib/Transforms/NaCl/RewriteAtomics.cpp

Issue 927493002: PNaCl: Impl the other atomicrmw operations: nand, max, min, umax, and umin. Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Reduce big-O cost. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/Transforms/NaCl/LLVMBuild.txt ('k') | test/Transforms/NaCl/atomic/extra-rmw-operations.ll » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- RewriteAtomics.cpp - Stabilize instructions used for concurrency ---===// 1 //===- RewriteAtomics.cpp - Stabilize instructions used for concurrency ---===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This pass encodes atomics, volatiles and fences using NaCl intrinsics 10 // This pass encodes atomics, volatiles and fences using NaCl intrinsics
11 // instead of LLVM's regular IR instructions. 11 // instead of LLVM's regular IR instructions.
12 // 12 //
13 // All of the above are transformed into one of the 13 // All of the above are transformed into one of the
14 // @llvm.nacl.atomic.* intrinsics. 14 // @llvm.nacl.atomic.* intrinsics.
15 // 15 //
16 //===----------------------------------------------------------------------===// 16 //===----------------------------------------------------------------------===//
17 17
18 #include "llvm/ADT/Triple.h"
18 #include "llvm/ADT/Twine.h" 19 #include "llvm/ADT/Twine.h"
19 #include "llvm/IR/DataLayout.h" 20 #include "llvm/IR/DataLayout.h"
20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/Function.h"
21 #include "llvm/IR/InlineAsm.h" 22 #include "llvm/IR/InlineAsm.h"
22 #include "llvm/IR/InstVisitor.h" 23 #include "llvm/IR/InstVisitor.h"
23 #include "llvm/IR/Instructions.h" 24 #include "llvm/IR/Instructions.h"
24 #include "llvm/IR/Intrinsics.h" 25 #include "llvm/IR/Intrinsics.h"
25 #include "llvm/IR/Module.h" 26 #include "llvm/IR/Module.h"
26 #include "llvm/IR/NaClAtomicIntrinsics.h" 27 #include "llvm/IR/NaClAtomicIntrinsics.h"
27 #include "llvm/Pass.h" 28 #include "llvm/Pass.h"
28 #include "llvm/Support/CommandLine.h" 29 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/Compiler.h"
30 #include "llvm/Support/raw_ostream.h" 31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Support/TargetRegistry.h"
31 #include "llvm/Transforms/NaCl.h" 33 #include "llvm/Transforms/NaCl.h"
32 #include <climits> 34 #include <climits>
33 #include <string> 35 #include <string>
34 36
35 using namespace llvm; 37 using namespace llvm;
36 38
37 static cl::opt<bool> PNaClMemoryOrderSeqCstOnly( 39 static cl::opt<bool> PNaClMemoryOrderSeqCstOnly(
38 "pnacl-memory-order-seq-cst-only", 40 "pnacl-memory-order-seq-cst-only",
39 cl::desc("PNaCl should upgrade all atomic memory orders to seq_cst"), 41 cl::desc("PNaCl should upgrade all atomic memory orders to seq_cst"),
40 cl::init(false)); 42 cl::init(false));
(...skipping 27 matching lines...) Expand all
68 ModifiedModule(false) {} 70 ModifiedModule(false) {}
69 ~AtomicVisitor() {} 71 ~AtomicVisitor() {}
70 bool modifiedModule() const { return ModifiedModule; } 72 bool modifiedModule() const { return ModifiedModule; }
71 73
72 void visitLoadInst(LoadInst &I); 74 void visitLoadInst(LoadInst &I);
73 void visitStoreInst(StoreInst &I); 75 void visitStoreInst(StoreInst &I);
74 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I); 76 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
75 void visitAtomicRMWInst(AtomicRMWInst &I); 77 void visitAtomicRMWInst(AtomicRMWInst &I);
76 void visitFenceInst(FenceInst &I); 78 void visitFenceInst(FenceInst &I);
77 79
80 SmallVectorImpl<Function*>& getFunsWithExtraRMWOps() { return FunsWithExtraRMW Ops; }
81
78 private: 82 private:
79 Module &M; 83 Module &M;
80 LLVMContext &C; 84 LLVMContext &C;
81 const DataLayout TD; 85 const DataLayout TD;
82 NaCl::AtomicIntrinsics AI; 86 NaCl::AtomicIntrinsics AI;
83 bool ModifiedModule; 87 bool ModifiedModule;
84 88
89 /// These functions have atomic instructions which we expand with
90 /// -atomic-expand. We collect them here so we don't have to check every
91 /// instruction of every basicblock of every function in the module twice over
92 /// the coarse of the pass (under the assumption that atomic operations are
93 /// the expection rather than the rule).
JF 2015/07/23 22:44:38 "exception"
94 SmallVector<Function*, 32> FunsWithExtraRMWOps;
95
85 AtomicVisitor() = delete; 96 AtomicVisitor() = delete;
86 AtomicVisitor(const AtomicVisitor &) = delete; 97 AtomicVisitor(const AtomicVisitor &) = delete;
87 AtomicVisitor &operator=(const AtomicVisitor &) = delete; 98 AtomicVisitor &operator=(const AtomicVisitor &) = delete;
88 99
89 /// Create an integer constant holding a NaCl::MemoryOrder that can be 100 /// Create an integer constant holding a NaCl::MemoryOrder that can be
90 /// passed as an argument to one of the @llvm.nacl.atomic.* 101 /// passed as an argument to one of the @llvm.nacl.atomic.*
91 /// intrinsics. This function may strengthen the ordering initially 102 /// intrinsics. This function may strengthen the ordering initially
92 /// specified by the instruction \p I for stability purpose. 103 /// specified by the instruction \p I for stability purpose.
93 template <class Instruction> 104 template <class Instruction>
94 ConstantInt *freezeMemoryOrder(const Instruction &I, AtomicOrdering O) const; 105 ConstantInt *freezeMemoryOrder(const Instruction &I, AtomicOrdering O) const;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 }; 166 };
156 } 167 }
157 168
158 char RewriteAtomics::ID = 0; 169 char RewriteAtomics::ID = 0;
159 INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics", 170 INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics",
160 "rewrite atomics, volatiles and fences into stable " 171 "rewrite atomics, volatiles and fences into stable "
161 "@llvm.nacl.atomics.* intrinsics", 172 "@llvm.nacl.atomics.* intrinsics",
162 false, false) 173 false, false)
163 174
164 bool RewriteAtomics::runOnModule(Module &M) { 175 bool RewriteAtomics::runOnModule(Module &M) {
176 // rewrite nand, (u)max, (u)min rmw atomics:
177 // First we need a target machine to appease its lordship:
178
179 // Get the target specific parser.
180 std::string Error;
181 Triple TheTriple = Triple("i686-none-nacl");
182 const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple,
183 Error);
184 if (!TheTarget) {
185 errs() << "Looking up 'i686-none-nacl':" << ": " << Error;
186 report_fatal_error("Did you forget to initialize the x86 target?");
187 }
188
189 // Create the target machine:
190 std::unique_ptr<TargetMachine> Target(
191 TheTarget->createTargetMachine(TheTriple.getTriple(), "generic", "",
192 TargetOptions(), Reloc::Default,
193 CodeModel::Default, CodeGenOpt::Default));
194 assert(Target != nullptr);
195
196 std::unique_ptr<FunctionPass> AtomicRMWExpander
197 (createAtomicExpandPass(Target.get()));
198
199
165 AtomicVisitor AV(M, *this); 200 AtomicVisitor AV(M, *this);
166 AV.visit(M); 201 AV.visit(M);
167 return AV.modifiedModule(); 202
203 bool Changed = AV.modifiedModule();
204
205 // Expand any leftover RMW atomics:
206 // This is done after because otherwise -atomic-expand will expand stuff we're
207 // capable of expanding, leaving us with less efficient code.
208 const size_t PrevLen = AV.getFunsWithExtraRMWOps().size();
209 for(auto *F : AV.getFunsWithExtraRMWOps()) {
210 const bool Expanded = AtomicRMWExpander->runOnFunction(*F);
211 (void)Expanded;
212 assert(Expanded);
213 // revisit the function, rewriting cmpxchg to the corresponding
214 // llvm.nacl.etc.etc.
215 AV.visit(*F);
216 Changed = true;
217 }
218 // assert that -atomic-expand didn't leave things we can't expand.
219 (void)PrevLen;
220 assert(PrevLen == AV.getFunsWithExtraRMWOps().size());
221
222 return Changed;
168 } 223 }
169 224
170 template <class Instruction> 225 template <class Instruction>
171 ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I, 226 ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I,
172 AtomicOrdering O) const { 227 AtomicOrdering O) const {
173 NaCl::MemoryOrder AO = NaCl::MemoryOrderInvalid; 228 NaCl::MemoryOrder AO = NaCl::MemoryOrderInvalid;
174 229
175 // TODO Volatile load/store are promoted to sequentially consistent 230 // TODO Volatile load/store are promoted to sequentially consistent
176 // for now. We could do something weaker. 231 // for now. We could do something weaker.
177 if (const LoadInst *L = dyn_cast<LoadInst>(&I)) { 232 if (const LoadInst *L = dyn_cast<LoadInst>(&I)) {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET, 395 replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET,
341 Args); 396 Args);
342 } 397 }
343 398
344 /// %res = atomicrmw OP T* %ptr, T %val memory_order 399 /// %res = atomicrmw OP T* %ptr, T %val memory_order
345 /// becomes: 400 /// becomes:
346 /// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order) 401 /// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order)
347 void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) { 402 void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
348 NaCl::AtomicRMWOperation Op; 403 NaCl::AtomicRMWOperation Op;
349 switch (I.getOperation()) { 404 switch (I.getOperation()) {
350 default: report_fatal_error("unsupported atomicrmw operation: " + ToStr(I)); 405 default: {
406 // delegate to -atomic-expand
407 FunsWithExtraRMWOps.push_back(I.getParent()->getParent());
408 return;
409 }
351 case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break; 410 case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break;
352 case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break; 411 case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break;
353 case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break; 412 case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break;
354 case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break; 413 case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break;
355 case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break; 414 case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break;
356 case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break; 415 case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break;
357 } 416 }
358 PointerHelper<AtomicRMWInst> PH(*this, I); 417 PointerHelper<AtomicRMWInst> PH(*this, I);
359 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = 418 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
360 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_rmw, PH.PET); 419 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_rmw, PH.PET);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 ArrayRef<Value *>()); 479 ArrayRef<Value *>());
421 } else { 480 } else {
422 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = 481 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
423 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T); 482 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T);
424 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())}; 483 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())};
425 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args); 484 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args);
426 } 485 }
427 } 486 }
428 487
429 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); } 488 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); }
OLDNEW
« no previous file with comments | « lib/Transforms/NaCl/LLVMBuild.txt ('k') | test/Transforms/NaCl/atomic/extra-rmw-operations.ll » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698