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

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: Rebase 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 }; 157 };
156 } 158 }
157 159
158 char RewriteAtomics::ID = 0; 160 char RewriteAtomics::ID = 0;
159 INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics", 161 INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics",
160 "rewrite atomics, volatiles and fences into stable " 162 "rewrite atomics, volatiles and fences into stable "
161 "@llvm.nacl.atomics.* intrinsics", 163 "@llvm.nacl.atomics.* intrinsics",
162 false, false) 164 false, false)
163 165
164 bool RewriteAtomics::runOnModule(Module &M) { 166 bool RewriteAtomics::runOnModule(Module &M) {
167 // rewrite nand, (u)max, (u)min rmw atomics:
168 // First we need a target machine to appease its lordship:
169
170 // Get the target specific parser.
171 std::string Error;
172 Triple TheTriple = Triple("i686-none-nacl");
173 const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple,
174 Error);
175 if (!TheTarget) {
176 errs() << "Looking up 'i686-none-nacl':" << ": " << Error;
177 report_fatal_error("Did you forget to initialize the x86 target?");
178 }
179
180 // Create the target machine:
181 std::unique_ptr<TargetMachine> Target(
182 TheTarget->createTargetMachine(TheTriple.getTriple(), "generic", "",
183 TargetOptions(), Reloc::Default,
184 CodeModel::Default, CodeGenOpt::Default));
185 assert(Target != nullptr);
186
187 std::unique_ptr<FunctionPass> AtomicRMWExpander
188 (createAtomicExpandPass(Target.get()));
JF 2015/07/10 18:07:32 Could the pass instead go in lib/Transforms/NaCl/P
Richard Diamond 2015/07/10 21:08:17 No, because -atomic-expand will expand stuff that
189
190
165 AtomicVisitor AV(M, *this); 191 AtomicVisitor AV(M, *this);
166 AV.visit(M); 192 AV.visit(M);
167 return AV.modifiedModule(); 193
194 bool Changed = AV.modifiedModule();
195
196 // Expand any leftover RMW atomics:
197 // This is done after because otherwise -atomic-expand will expand stuff we're
198 // capable of expanding, leaving us with less efficient code.
199 for(auto &F : M.functions()) {
200 if (AtomicRMWExpander->runOnFunction(F)) {
201 // revisit the function, rewriting cmpxchg to the corresponding
202 // llvm.nacl.etc.etc.
203 AV.visit(F);
204 Changed = true;
205 }
206 }
207 return Changed;
168 } 208 }
169 209
170 template <class Instruction> 210 template <class Instruction>
171 ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I, 211 ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I,
172 AtomicOrdering O) const { 212 AtomicOrdering O) const {
173 NaCl::MemoryOrder AO = NaCl::MemoryOrderInvalid; 213 NaCl::MemoryOrder AO = NaCl::MemoryOrderInvalid;
174 214
175 // TODO Volatile load/store are promoted to sequentially consistent 215 // TODO Volatile load/store are promoted to sequentially consistent
176 // for now. We could do something weaker. 216 // for now. We could do something weaker.
177 if (const LoadInst *L = dyn_cast<LoadInst>(&I)) { 217 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, 380 replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET,
341 Args); 381 Args);
342 } 382 }
343 383
344 /// %res = atomicrmw OP T* %ptr, T %val memory_order 384 /// %res = atomicrmw OP T* %ptr, T %val memory_order
345 /// becomes: 385 /// becomes:
346 /// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order) 386 /// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order)
347 void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) { 387 void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
348 NaCl::AtomicRMWOperation Op; 388 NaCl::AtomicRMWOperation Op;
349 switch (I.getOperation()) { 389 switch (I.getOperation()) {
350 default: report_fatal_error("unsupported atomicrmw operation: " + ToStr(I)); 390 default: return; // -atomic-expand will handle it.
351 case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break; 391 case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break;
352 case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break; 392 case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break;
353 case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break; 393 case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break;
354 case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break; 394 case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break;
355 case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break; 395 case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break;
356 case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break; 396 case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break;
357 } 397 }
358 PointerHelper<AtomicRMWInst> PH(*this, I); 398 PointerHelper<AtomicRMWInst> PH(*this, I);
359 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = 399 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
360 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_rmw, PH.PET); 400 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_rmw, PH.PET);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 ArrayRef<Value *>()); 460 ArrayRef<Value *>());
421 } else { 461 } else {
422 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = 462 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
423 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T); 463 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T);
424 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())}; 464 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())};
425 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args); 465 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args);
426 } 466 }
427 } 467 }
428 468
429 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); } 469 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