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

Side by Side Diff: lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp

Issue 321733002: PNaCl SIMD: allow element-aligned vector load/store (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: s/,/./ Created 6 years, 6 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 | « no previous file | lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- PNaClABIVerifyFunctions.cpp - Verify PNaCl ABI rules ---------------===// 1 //===- PNaClABIVerifyFunctions.cpp - Verify PNaCl ABI rules ---------------===//
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 // Verify function-level PNaCl ABI requirements. 10 // Verify function-level PNaCl ABI requirements.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry()); 49 initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry());
50 } 50 }
51 ~PNaClABIVerifyFunctions() { 51 ~PNaClABIVerifyFunctions() {
52 if (ReporterIsOwned) 52 if (ReporterIsOwned)
53 delete Reporter; 53 delete Reporter;
54 } 54 }
55 virtual bool doInitialization(Module &M) { 55 virtual bool doInitialization(Module &M) {
56 AtomicIntrinsics.reset(new NaCl::AtomicIntrinsics(M.getContext())); 56 AtomicIntrinsics.reset(new NaCl::AtomicIntrinsics(M.getContext()));
57 return false; 57 return false;
58 } 58 }
59 virtual void getAnalysisUsage(AnalysisUsage &Info) const {
60 Info.setPreservesAll();
61 Info.addRequired<DataLayout>();
62 }
59 bool runOnFunction(Function &F); 63 bool runOnFunction(Function &F);
60 virtual void print(raw_ostream &O, const Module *M) const; 64 virtual void print(raw_ostream &O, const Module *M) const;
61 private: 65 private:
62 bool IsWhitelistedMetadata(unsigned MDKind); 66 bool IsWhitelistedMetadata(unsigned MDKind);
63 const char *checkInstruction(const Instruction *Inst); 67 const char *checkInstruction(const DataLayout *DL, const Instruction *Inst);
64 PNaClABIErrorReporter *Reporter; 68 PNaClABIErrorReporter *Reporter;
65 bool ReporterIsOwned; 69 bool ReporterIsOwned;
66 OwningPtr<NaCl::AtomicIntrinsics> AtomicIntrinsics; 70 OwningPtr<NaCl::AtomicIntrinsics> AtomicIntrinsics;
67 }; 71 };
68 72
69 } // and anonymous namespace 73 } // and anonymous namespace
70 74
71 // There's no built-in way to get the name of an MDNode, so use a 75 // There's no built-in way to get the name of an MDNode, so use a
72 // string ostream to print it. 76 // string ostream to print it.
73 static std::string getMDNodeString(unsigned Kind, 77 static std::string getMDNodeString(unsigned Kind,
74 const SmallVectorImpl<StringRef> &MDNames) { 78 const SmallVectorImpl<StringRef> &MDNames) {
75 std::string MDName; 79 std::string MDName;
76 raw_string_ostream N(MDName); 80 raw_string_ostream N(MDName);
77 if (Kind < MDNames.size()) { 81 if (Kind < MDNames.size()) {
78 N << "!" << MDNames[Kind]; 82 N << "!" << MDNames[Kind];
79 } else { 83 } else {
80 N << "!<unknown kind #" << Kind << ">"; 84 N << "!<unknown kind #" << Kind << ">";
81 } 85 }
82 return N.str(); 86 return N.str();
83 } 87 }
84 88
85 bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) { 89 bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) {
86 return MDKind == LLVMContext::MD_dbg && PNaClABIAllowDebugMetadata; 90 return MDKind == LLVMContext::MD_dbg && PNaClABIAllowDebugMetadata;
87 } 91 }
88 92
89 // A valid pointer type is either: 93 // A valid pointer type is either:
90 // * a pointer to a valid PNaCl scalar type (except i1), or 94 // * a pointer to a valid PNaCl scalar type (except i1), or
95 // * a pointer to a valid PNaCl vector type (except i1), or
91 // * a function pointer (with valid argument and return types). 96 // * a function pointer (with valid argument and return types).
92 // 97 //
93 // i1 is disallowed so that all loads and stores are a whole number of 98 // i1 is disallowed so that all loads and stores are a whole number of
94 // bytes, and so that we do not need to define whether a store of i1 99 // bytes, and so that we do not need to define whether a store of i1
95 // zero-extends. 100 // zero-extends.
96 //
97 // Vector pointer types aren't currently allowed because vector memory
98 // accesses go through their scalar elements.
99 static bool isValidPointerType(Type *Ty) { 101 static bool isValidPointerType(Type *Ty) {
100 if (PointerType *PtrTy = dyn_cast<PointerType>(Ty)) { 102 if (PointerType *PtrTy = dyn_cast<PointerType>(Ty)) {
101 if (PtrTy->getAddressSpace() != 0) 103 if (PtrTy->getAddressSpace() != 0)
102 return false; 104 return false;
103 Type *EltTy = PtrTy->getElementType(); 105 Type *EltTy = PtrTy->getElementType();
104 if (PNaClABITypeChecker::isValidScalarType(EltTy) && !EltTy->isIntegerTy(1)) 106 if (PNaClABITypeChecker::isValidScalarType(EltTy) && !EltTy->isIntegerTy(1))
105 return true; 107 return true;
108 if (PNaClABITypeChecker::isValidVectorType(EltTy) &&
109 !cast<VectorType>(EltTy)->getElementType()->isIntegerTy(1))
110 return true;
106 if (FunctionType *FTy = dyn_cast<FunctionType>(EltTy)) 111 if (FunctionType *FTy = dyn_cast<FunctionType>(EltTy))
107 return PNaClABITypeChecker::isValidFunctionType(FTy); 112 return PNaClABITypeChecker::isValidFunctionType(FTy);
108 } 113 }
109 return false; 114 return false;
110 } 115 }
111 116
112 static bool isIntrinsicFunc(const Value *Val) { 117 static bool isIntrinsicFunc(const Value *Val) {
113 if (const Function *F = dyn_cast<Function>(Val)) 118 if (const Function *F = dyn_cast<Function>(Val))
114 return F->isIntrinsic(); 119 return F->isIntrinsic();
115 return false; 120 return false;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 if (isa<Instruction>(Val) || isa<Argument>(Val)) 164 if (isa<Instruction>(Val) || isa<Argument>(Val))
160 return true; 165 return true;
161 // Contrary to scalars, constant vector values aren't allowed on 166 // Contrary to scalars, constant vector values aren't allowed on
162 // instructions, except undefined. Constant vectors are loaded from 167 // instructions, except undefined. Constant vectors are loaded from
163 // constant global memory instead, and can be rematerialized as 168 // constant global memory instead, and can be rematerialized as
164 // constants by the backend if need be. 169 // constants by the backend if need be.
165 return PNaClABITypeChecker::isValidVectorType(Val->getType()) && 170 return PNaClABITypeChecker::isValidVectorType(Val->getType()) &&
166 isa<UndefValue>(Val); 171 isa<UndefValue>(Val);
167 } 172 }
168 173
169 static bool isAllowedAlignment(unsigned Alignment, Type *Ty) { 174 static bool isAllowedAlignment(const DataLayout *DL, uint64_t Alignment,
170 // Non-atomic integer operations must always use "align 1", since we 175 Type *Ty) {
171 // do not want the backend to generate code with non-portable 176 // Non-atomic integer operations must always use "align 1", since we do not
172 // undefined behaviour (such as misaligned access faults) if user 177 // want the backend to generate code with non-portable undefined behaviour
173 // code specifies "align 4" but uses a misaligned pointer. As a 178 // (such as misaligned access faults) if user code specifies "align 4" but
174 // concession to performance, we allow larger alignment values for 179 // uses a misaligned pointer. As a concession to performance, we allow larger
175 // floating point types. 180 // alignment values for floating point types, and we only allow vectors to be
181 // aligned by their element's size.
176 // 182 //
177 // To reduce the set of alignment values that need to be encoded in 183 // TODO(jfb) Allow vectors to be marked as align == 1. This requires proper
178 // pexes, we disallow other alignment values. We require alignments 184 // testing on each supported ISA, and is probably not as common as
179 // to be explicit by disallowing Alignment == 0. 185 // align == elemsize.
180 // 186 //
181 // Vector memory accesses go through their scalar elements, there is 187 // To reduce the set of alignment values that need to be encoded in pexes, we
182 // therefore no such thing as vector alignment. 188 // disallow other alignment values. We require alignments to be explicit by
183 return Alignment == 1 || 189 // disallowing Alignment == 0.
184 (Ty->isDoubleTy() && Alignment == 8) || 190 if (Alignment > std::numeric_limits<uint64_t>::max() / CHAR_BIT)
185 (Ty->isFloatTy() && Alignment == 4); 191 return false; // No overflow assumed below.
192 else if (VectorType *VTy = dyn_cast<VectorType>(Ty))
193 return !VTy->getElementType()->isIntegerTy(1) &&
194 (Alignment * CHAR_BIT ==
195 DL->getTypeSizeInBits(VTy->getElementType()));
196 else
197 return Alignment == 1 ||
198 (Ty->isDoubleTy() && Alignment == 8) ||
199 (Ty->isFloatTy() && Alignment == 4);
186 } 200 }
187 201
188 static bool hasAllowedAtomicRMWOperation( 202 static bool hasAllowedAtomicRMWOperation(
189 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) { 203 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) {
190 for (size_t P = 0; P != I->NumParams; ++P) { 204 for (size_t P = 0; P != I->NumParams; ++P) {
191 if (I->ParamType[P] != NaCl::AtomicIntrinsics::RMW) 205 if (I->ParamType[P] != NaCl::AtomicIntrinsics::RMW)
192 continue; 206 continue;
193 207
194 const Value *Operation = Call->getOperand(P); 208 const Value *Operation = Call->getOperand(P);
195 if (!Operation) 209 if (!Operation)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 if (I == 1 || I == 2 || I == 4 || I == 8) 260 if (I == 1 || I == 2 || I == 4 || I == 8)
247 return true; 261 return true;
248 return false; 262 return false;
249 } 263 }
250 264
251 // Check the instruction's opcode and its operands. The operands may 265 // Check the instruction's opcode and its operands. The operands may
252 // require opcode-specific checking. 266 // require opcode-specific checking.
253 // 267 //
254 // This returns an error string if the instruction is rejected, or 268 // This returns an error string if the instruction is rejected, or
255 // NULL if the instruction is allowed. 269 // NULL if the instruction is allowed.
256 const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { 270 const char *PNaClABIVerifyFunctions::checkInstruction(const DataLayout *DL,
271 const Instruction *Inst) {
257 // If the instruction has a single pointer operand, PtrOperandIndex is 272 // If the instruction has a single pointer operand, PtrOperandIndex is
258 // set to its operand index. 273 // set to its operand index.
259 unsigned PtrOperandIndex = -1; 274 unsigned PtrOperandIndex = -1;
260 275
261 switch (Inst->getOpcode()) { 276 switch (Inst->getOpcode()) {
262 // Disallowed instructions. Default is to disallow. 277 // Disallowed instructions. Default is to disallow.
263 // We expand GetElementPtr out into arithmetic. 278 // We expand GetElementPtr out into arithmetic.
264 case Instruction::GetElementPtr: 279 case Instruction::GetElementPtr:
265 // VAArg is expanded out by ExpandVarArgs. 280 // VAArg is expanded out by ExpandVarArgs.
266 case Instruction::VAArg: 281 case Instruction::VAArg:
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 // Memory accesses. 372 // Memory accesses.
358 case Instruction::Load: { 373 case Instruction::Load: {
359 const LoadInst *Load = cast<LoadInst>(Inst); 374 const LoadInst *Load = cast<LoadInst>(Inst);
360 PtrOperandIndex = Load->getPointerOperandIndex(); 375 PtrOperandIndex = Load->getPointerOperandIndex();
361 if (Load->isAtomic()) 376 if (Load->isAtomic())
362 return "atomic load"; 377 return "atomic load";
363 if (Load->isVolatile()) 378 if (Load->isVolatile())
364 return "volatile load"; 379 return "volatile load";
365 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) 380 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
366 return "bad pointer"; 381 return "bad pointer";
367 if (!isAllowedAlignment(Load->getAlignment(), 382 if (!isAllowedAlignment(DL, Load->getAlignment(), Load->getType()))
368 Load->getType()))
369 return "bad alignment"; 383 return "bad alignment";
370 break; 384 break;
371 } 385 }
372 case Instruction::Store: { 386 case Instruction::Store: {
373 const StoreInst *Store = cast<StoreInst>(Inst); 387 const StoreInst *Store = cast<StoreInst>(Inst);
374 PtrOperandIndex = Store->getPointerOperandIndex(); 388 PtrOperandIndex = Store->getPointerOperandIndex();
375 if (Store->isAtomic()) 389 if (Store->isAtomic())
376 return "atomic store"; 390 return "atomic store";
377 if (Store->isVolatile()) 391 if (Store->isVolatile())
378 return "volatile store"; 392 return "volatile store";
379 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) 393 if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
380 return "bad pointer"; 394 return "bad pointer";
381 if (!isAllowedAlignment(Store->getAlignment(), 395 if (!isAllowedAlignment(DL, Store->getAlignment(),
382 Store->getValueOperand()->getType())) 396 Store->getValueOperand()->getType()))
383 return "bad alignment"; 397 return "bad alignment";
384 break; 398 break;
385 } 399 }
386 400
387 // Casts. 401 // Casts.
388 case Instruction::BitCast: 402 case Instruction::BitCast:
389 if (Inst->getType()->isPointerTy()) { 403 if (Inst->getType()->isPointerTy()) {
390 PtrOperandIndex = 0; 404 PtrOperandIndex = 0;
391 if (!isInherentPtr(Inst->getOperand(PtrOperandIndex))) 405 if (!isInherentPtr(Inst->getOperand(PtrOperandIndex)))
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 dyn_cast<PossiblyExactOperator>(Inst)) { 548 dyn_cast<PossiblyExactOperator>(Inst)) {
535 if (Op->isExact()) 549 if (Op->isExact())
536 return "has \"exact\" attribute"; 550 return "has \"exact\" attribute";
537 } 551 }
538 552
539 // Allow the instruction. 553 // Allow the instruction.
540 return NULL; 554 return NULL;
541 } 555 }
542 556
543 bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { 557 bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
558 const DataLayout *DL = &getAnalysis<DataLayout>();
544 SmallVector<StringRef, 8> MDNames; 559 SmallVector<StringRef, 8> MDNames;
545 F.getContext().getMDKindNames(MDNames); 560 F.getContext().getMDKindNames(MDNames);
546 561
547 for (Function::const_iterator FI = F.begin(), FE = F.end(); 562 for (Function::const_iterator FI = F.begin(), FE = F.end();
548 FI != FE; ++FI) { 563 FI != FE; ++FI) {
549 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); 564 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end();
550 BBI != BBE; ++BBI) { 565 BBI != BBE; ++BBI) {
551 const Instruction *Inst = BBI; 566 const Instruction *Inst = BBI;
552 // Check the instruction opcode first. This simplifies testing, 567 // Check the instruction opcode first. This simplifies testing,
553 // because some instruction opcodes must be rejected out of hand 568 // because some instruction opcodes must be rejected out of hand
554 // (regardless of the instruction's result type) and the tests 569 // (regardless of the instruction's result type) and the tests
555 // check the reason for rejection. 570 // check the reason for rejection.
556 const char *Error = checkInstruction(BBI); 571 const char *Error = checkInstruction(DL, BBI);
557 // Check the instruction's result type. 572 // Check the instruction's result type.
558 bool BadResult = false; 573 bool BadResult = false;
559 if (!Error && !(PNaClABITypeChecker::isValidScalarType(Inst->getType()) || 574 if (!Error && !(PNaClABITypeChecker::isValidScalarType(Inst->getType()) ||
560 PNaClABITypeChecker::isValidVectorType(Inst->getType()) || 575 PNaClABITypeChecker::isValidVectorType(Inst->getType()) ||
561 isNormalizedPtr(Inst) || 576 isNormalizedPtr(Inst) ||
562 isa<AllocaInst>(Inst))) { 577 isa<AllocaInst>(Inst))) {
563 Error = "bad result type"; 578 Error = "bad result type";
564 BadResult = true; 579 BadResult = true;
565 } 580 }
566 if (Error) { 581 if (Error) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 } 614 }
600 615
601 char PNaClABIVerifyFunctions::ID = 0; 616 char PNaClABIVerifyFunctions::ID = 0;
602 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", 617 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions",
603 "Verify functions for PNaCl", false, true) 618 "Verify functions for PNaCl", false, true)
604 619
605 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( 620 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass(
606 PNaClABIErrorReporter *Reporter) { 621 PNaClABIErrorReporter *Reporter) {
607 return new PNaClABIVerifyFunctions(Reporter); 622 return new PNaClABIVerifyFunctions(Reporter);
608 } 623 }
OLDNEW
« no previous file with comments | « no previous file | lib/Transforms/NaCl/FixVectorLoadStoreAlignment.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698