Chromium Code Reviews

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: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
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 // TODO(jfb) Keep the default of this option to true for Chrome 42, and change 39 // TODO(jfb) Keep the default of this option to true for Chrome 42, and change
38 // it to false for Chrome 43. This allows the PNaCl translator to be 40 // it to false for Chrome 43. This allows the PNaCl translator to be
39 // updated before the SDK starts emitting atomic memory orders that 41 // updated before the SDK starts emitting atomic memory orders that
40 // the old translator rejected. 42 // the old translator rejected.
(...skipping 121 matching lines...)
162 }; 164 };
163 } 165 }
164 166
165 char RewriteAtomics::ID = 0; 167 char RewriteAtomics::ID = 0;
166 INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics", 168 INITIALIZE_PASS(RewriteAtomics, "nacl-rewrite-atomics",
167 "rewrite atomics, volatiles and fences into stable " 169 "rewrite atomics, volatiles and fences into stable "
168 "@llvm.nacl.atomics.* intrinsics", 170 "@llvm.nacl.atomics.* intrinsics",
169 false, false) 171 false, false)
170 172
171 bool RewriteAtomics::runOnModule(Module &M) { 173 bool RewriteAtomics::runOnModule(Module &M) {
174 // rewrite nand, (u)max, (u)min rmw atomics:
175 // First we need a target machine to appease its lordship:
176
177 // Get the target specific parser.
178 std::string Error;
179 Triple TheTriple = Triple("i686-none-nacl");
JF 2015/02/16 21:09:01 Does it need to be i686? Can you just have unknown
Richard Diamond 2015/02/16 23:36:31 The other option is `x86_64`. Arm expands into som
180 const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple,
181 Error);
182 if (!TheTarget) {
183 errs() << "Looking up 'i686-none-nacl':" << ": " << Error;
184 report_fatal_error("Did you forget to initialize the x86 target?");
185 }
186
187 // Create the target machine:
188 std::unique_ptr<TargetMachine> target(
189 TheTarget->createTargetMachine(TheTriple.getTriple(), "generic", "i686",
190 TargetOptions(), Reloc::Default,
191 CodeModel::Default, CodeGenOpt::Default));
192
193 std::unique_ptr<FunctionPass> AtomicRMWExpander
194 (createAtomicExpandPass(target.get()));
195
196
172 AtomicVisitor AV(M, *this); 197 AtomicVisitor AV(M, *this);
173 AV.visit(M); 198 AV.visit(M);
174 return AV.modifiedModule(); 199
200 bool Changed = AV.modifiedModule();
201
202 // Expand any leftover RMW atomics:
203 // This is done after because otherwise -atomic-expand will expand stuff we're
204 // capable of expanding, leaving us with less efficient code.
205 for(auto &F : M.functions()) {
206 if (AtomicRMWExpander->runOnFunction(F)) {
207 // revisit the function, rewriting cmpxchg to the corresponding
208 // llvm.nacl.etc.etc.
209 AV.visit(F);
210 }
211 }
JF 2015/02/16 21:09:01 Could you invoke the -atomic-expand pass after thi
Richard Diamond 2015/02/16 23:36:31 No, because it would force this kluge onto users.
212 return Changed;
175 } 213 }
176 214
177 template <class Instruction> 215 template <class Instruction>
178 ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I, 216 ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I,
179 AtomicOrdering O) const { 217 AtomicOrdering O) const {
180 NaCl::MemoryOrder AO = NaCl::MemoryOrderInvalid; 218 NaCl::MemoryOrder AO = NaCl::MemoryOrderInvalid;
181 219
182 // TODO Volatile load/store are promoted to sequentially consistent 220 // TODO Volatile load/store are promoted to sequentially consistent
183 // for now. We could do something weaker. 221 // for now. We could do something weaker.
184 if (const LoadInst *L = dyn_cast<LoadInst>(&I)) { 222 if (const LoadInst *L = dyn_cast<LoadInst>(&I)) {
(...skipping 162 matching lines...)
347 replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET, 385 replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET,
348 Args); 386 Args);
349 } 387 }
350 388
351 /// %res = atomicrmw OP T* %ptr, T %val memory_order 389 /// %res = atomicrmw OP T* %ptr, T %val memory_order
352 /// becomes: 390 /// becomes:
353 /// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order) 391 /// %res = call T @llvm.nacl.atomic.rmw.i<size>(OP, %ptr, %val, memory_order)
354 void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) { 392 void AtomicVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
355 NaCl::AtomicRMWOperation Op; 393 NaCl::AtomicRMWOperation Op;
356 switch (I.getOperation()) { 394 switch (I.getOperation()) {
357 default: report_fatal_error("unsupported atomicrmw operation: " + ToStr(I)); 395 default: return; // -atomic-expand will handle it.
JF 2015/02/16 21:09:01 It would be good to assert that the second pass of
Richard Diamond 2015/02/16 23:36:31 The second pass never reaches this. The other RMW
358 case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break; 396 case AtomicRMWInst::Add: Op = NaCl::AtomicAdd; break;
359 case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break; 397 case AtomicRMWInst::Sub: Op = NaCl::AtomicSub; break;
360 case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break; 398 case AtomicRMWInst::And: Op = NaCl::AtomicAnd; break;
361 case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break; 399 case AtomicRMWInst::Or: Op = NaCl::AtomicOr; break;
362 case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break; 400 case AtomicRMWInst::Xor: Op = NaCl::AtomicXor; break;
363 case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break; 401 case AtomicRMWInst::Xchg: Op = NaCl::AtomicExchange; break;
364 } 402 }
365 PointerHelper<AtomicRMWInst> PH(*this, I); 403 PointerHelper<AtomicRMWInst> PH(*this, I);
366 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = 404 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
367 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_rmw, PH.PET); 405 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_rmw, PH.PET);
(...skipping 59 matching lines...)
427 ArrayRef<Value *>()); 465 ArrayRef<Value *>());
428 } else { 466 } else {
429 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic = 467 const NaCl::AtomicIntrinsics::AtomicIntrinsic *Intrinsic =
430 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T); 468 findAtomicIntrinsic(I, Intrinsic::nacl_atomic_fence, T);
431 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())}; 469 Value *Args[] = {freezeMemoryOrder(I, I.getOrdering())};
432 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args); 470 replaceInstructionWithIntrinsicCall(I, Intrinsic, T, T, Args);
433 } 471 }
434 } 472 }
435 473
436 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); } 474 ModulePass *llvm::createRewriteAtomicsPass() { return new RewriteAtomics(); }
OLDNEW

Powered by Google App Engine