diff options
author | David Majnemer <david.majnemer@gmail.com> | 2015-08-14 05:09:07 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2015-08-14 05:09:07 +0000 |
commit | b611e3f50e6c9fb564864e437ad8fd26809f0a19 (patch) | |
tree | c477eac6aca9a13eb68fb6f1f012b35736114e0c /llvm/lib | |
parent | fb1e7f7d1aca7bcfc341e9214bda8b554f5ae9b6 (diff) | |
download | bcm5719-llvm-b611e3f50e6c9fb564864e437ad8fd26809f0a19.tar.gz bcm5719-llvm-b611e3f50e6c9fb564864e437ad8fd26809f0a19.zip |
[IR] Add token types
This introduces the basic functionality to support "token types".
The motivation stems from the need to perform operations on a Value
whose provenance cannot be obscured.
There are several applications for such a type but my immediate
motivation stems from WinEH. Our personality routine enforces a
single-entry - single-exit regime for cleanups. After several rounds of
optimizations, we may be left with a terminator whose "cleanup-entry
block" is not entirely clear because control flow has merged two
cleanups together. We have experimented with using labels as operands
inside of instructions which are not terminators to indicate where we
came from but found that LLVM does not expect such exotic uses of
BasicBlocks.
Instead, we can use this new type to clearly associate the "entry point"
and "exit point" of our cleanup. This is done by having the cleanuppad
yield a Token and consuming it at the cleanupret.
The token type makes it impossible to obscure or otherwise hide the
Value, making it trivial to track the relationship between the two
points.
What is the burden to the optimizer? Well, it turns out we have already
paid down this cost by accepting that there are certain calls that we
are not permitted to duplicate, optimizations have to watch out for
such instructions anyway. There are additional places in the optimizer
that we will probably have to update but early examination has given me
the impression that this will not be heroic.
Differential Revision: http://reviews.llvm.org/D11861
llvm-svn: 245029
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/CodeMetrics.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Analysis/LoopInfo.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/Core.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 2 | ||||
-rw-r--r-- | llvm/lib/IR/Type.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/Target/CppBackend/CPPBackend.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/MergeFunctions.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/JumpThreading.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 8 |
16 files changed, 59 insertions, 17 deletions
diff --git a/llvm/lib/Analysis/CodeMetrics.cpp b/llvm/lib/Analysis/CodeMetrics.cpp index 46a2c43b169..157a4bdd11c 100644 --- a/llvm/lib/Analysis/CodeMetrics.cpp +++ b/llvm/lib/Analysis/CodeMetrics.cpp @@ -155,6 +155,9 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB, if (isa<ExtractElementInst>(II) || II->getType()->isVectorTy()) ++NumVectorInsts; + if (II->getType()->isTokenTy() && II->isUsedOutsideOfBlock(BB)) + notDuplicatable = true; + if (const CallInst *CI = dyn_cast<CallInst>(II)) if (CI->cannotDuplicate()) notDuplicatable = true; diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index 1ad4fd893bc..3d30c3a06e2 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -220,6 +220,8 @@ bool Loop::isSafeToClone() const { if (CI->cannotDuplicate()) return false; } + if (BI->getType()->isTokenTy() && BI->isUsedOutsideOfBlock(*I)) + return false; } } return true; diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index be951f5c7d8..6d62584577a 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -691,6 +691,7 @@ lltok::Kind LLLexer::LexIdentifier() { TYPEKEYWORD("label", Type::getLabelTy(Context)); TYPEKEYWORD("metadata", Type::getMetadataTy(Context)); TYPEKEYWORD("x86_mmx", Type::getX86_MMXTy(Context)); + TYPEKEYWORD("token", Type::getTokenTy(Context)); #undef TYPEKEYWORD // Keywords for instructions. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 658c08f3646..06935f7ab1b 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1360,6 +1360,9 @@ std::error_code BitcodeReader::parseTypeTableBody() { case bitc::TYPE_CODE_X86_MMX: // X86_MMX ResultTy = Type::getX86_MMXTy(Context); break; + case bitc::TYPE_CODE_TOKEN: // TOKEN + ResultTy = Type::getTokenTy(Context); + break; case bitc::TYPE_CODE_INTEGER: { // INTEGER: [width] if (Record.size() < 1) return error("Invalid record"); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 0d1a2accc4f..03650ec37b7 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -405,6 +405,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break; case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break; case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break; + case Type::TokenTyID: Code = bitc::TYPE_CODE_TOKEN; break; case Type::IntegerTyID: // INTEGER: [width] Code = bitc::TYPE_CODE_INTEGER; diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 76b3b3103c1..9ce384825f4 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -467,6 +467,7 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) { case Type::LabelTyID: OS << "label"; return; case Type::MetadataTyID: OS << "metadata"; return; case Type::X86_MMXTyID: OS << "x86_mmx"; return; + case Type::TokenTyID: OS << "token"; return; case Type::IntegerTyID: OS << 'i' << cast<IntegerType>(Ty)->getBitWidth(); return; diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index a3768485fd5..2937a62f3b5 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -262,6 +262,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) { return LLVMVectorTypeKind; case Type::X86_MMXTyID: return LLVMX86_MMXTypeKind; + case Type::TokenTyID: + return LLVMTokenTypeKind; } llvm_unreachable("Unhandled TypeID."); } @@ -366,6 +368,9 @@ LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C) { LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C) { return (LLVMTypeRef) Type::getX86_MMXTy(*unwrap(C)); } +LLVMTypeRef LLVMTokenTypeInContext(LLVMContextRef C) { + return (LLVMTypeRef) Type::getTokenTy(*unwrap(C)); +} LLVMTypeRef LLVMHalfType(void) { return LLVMHalfTypeInContext(LLVMGetGlobalContext()); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 18f2f1385f4..79fb30e4734 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -62,7 +62,10 @@ UnaryInstruction::~UnaryInstruction() { const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) { if (Op1->getType() != Op2->getType()) return "both values to select must have same type"; - + + if (Op1->getType()->isTokenTy()) + return "select values cannot have token type"; + if (VectorType *VT = dyn_cast<VectorType>(Op0->getType())) { // Vector select. if (VT->getElementType() != Type::getInt1Ty(Op0->getContext())) diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index 0ce28712339..dc367fee884 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -27,6 +27,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) FloatTy(C, Type::FloatTyID), DoubleTy(C, Type::DoubleTyID), MetadataTy(C, Type::MetadataTyID), + TokenTy(C, Type::TokenTyID), X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID), PPC_FP128Ty(C, Type::PPC_FP128TyID), diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index f514beabd0d..cf0aa5c62ab 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -928,7 +928,7 @@ public: ConstantInt *TheFalseVal; // Basic type instances. - Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy; + Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy, TokenTy; Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy; IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty; diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index fbcd887ec68..c3c3f492b5b 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -35,6 +35,7 @@ Type *Type::getPrimitiveType(LLVMContext &C, TypeID IDNumber) { case LabelTyID : return getLabelTy(C); case MetadataTyID : return getMetadataTy(C); case X86_MMXTyID : return getX86_MMXTy(C); + case TokenTyID : return getTokenTy(C); default: return nullptr; } @@ -220,6 +221,7 @@ Type *Type::getHalfTy(LLVMContext &C) { return &C.pImpl->HalfTy; } Type *Type::getFloatTy(LLVMContext &C) { return &C.pImpl->FloatTy; } Type *Type::getDoubleTy(LLVMContext &C) { return &C.pImpl->DoubleTy; } Type *Type::getMetadataTy(LLVMContext &C) { return &C.pImpl->MetadataTy; } +Type *Type::getTokenTy(LLVMContext &C) { return &C.pImpl->TokenTy; } Type *Type::getX86_FP80Ty(LLVMContext &C) { return &C.pImpl->X86_FP80Ty; } Type *Type::getFP128Ty(LLVMContext &C) { return &C.pImpl->FP128Ty; } Type *Type::getPPC_FP128Ty(LLVMContext &C) { return &C.pImpl->PPC_FP128Ty; } @@ -595,7 +597,8 @@ void StructType::setBody(Type *type, ...) { bool StructType::isValidElementType(Type *ElemTy) { return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && - !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() && + !ElemTy->isTokenTy(); } /// isLayoutIdentical - Return true if this is layout identical to the @@ -690,7 +693,8 @@ ArrayType *ArrayType::get(Type *ElementType, uint64_t NumElements) { bool ArrayType::isValidElementType(Type *ElemTy) { return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && - !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy() && + !ElemTy->isTokenTy(); } //===----------------------------------------------------------------------===// @@ -758,7 +762,7 @@ PointerType *Type::getPointerTo(unsigned addrs) const { bool PointerType::isValidElementType(Type *ElemTy) { return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && - !ElemTy->isMetadataTy(); + !ElemTy->isMetadataTy() && !ElemTy->isTokenTy(); } bool PointerType::isLoadableOrStorableType(Type *ElemTy) { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 863ddc7e2dd..af1121e3c73 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1739,11 +1739,18 @@ void Verifier::visitFunction(const Function &F) { FT->getParamType(i)); Assert(I->getType()->isFirstClassType(), "Function arguments must have first-class types!", I); - if (!isLLVMdotName) + if (!isLLVMdotName) { Assert(!I->getType()->isMetadataTy(), "Function takes metadata but isn't an intrinsic", I, &F); + Assert(!I->getType()->isTokenTy(), + "Function takes token but isn't an intrinsic", I, &F); + } } + if (!isLLVMdotName) + Assert(!F.getReturnType()->isTokenTy(), + "Functions returns a token but isn't an intrinsic", &F); + // Get the function metadata attachments. SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; F.getAllMetadata(MDs); @@ -2190,6 +2197,9 @@ void Verifier::visitPHINode(PHINode &PN) { isa<PHINode>(--BasicBlock::iterator(&PN)), "PHI nodes not grouped at top of basic block!", &PN, PN.getParent()); + // Check that a PHI doesn't yield a Token. + Assert(!PN.getType()->isTokenTy(), "PHI nodes cannot have token type!"); + // Check that all of the values of the PHI node have the same type as the // result, and that the incoming blocks are really basic blocks. for (Value *IncValue : PN.incoming_values()) { @@ -2292,12 +2302,19 @@ void Verifier::VerifyCallSite(CallSite CS) { // Verify that there's no metadata unless it's a direct call to an intrinsic. if (CS.getCalledFunction() == nullptr || !CS.getCalledFunction()->getName().startswith("llvm.")) { - for (FunctionType::param_iterator PI = FTy->param_begin(), - PE = FTy->param_end(); PI != PE; ++PI) - Assert(!(*PI)->isMetadataTy(), + for (Type *ParamTy : FTy->params()) { + Assert(!ParamTy->isMetadataTy(), "Function has metadata parameter but isn't an intrinsic", I); + Assert(!ParamTy->isTokenTy(), + "Function has token parameter but isn't an intrinsic", I); + } } + // Verify that indirect calls don't return tokens. + if (CS.getCalledFunction() == nullptr) + Assert(!FTy->getReturnType()->isTokenTy(), + "Return type cannot be token for indirect call!"); + if (Function *F = CS.getCalledFunction()) if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) visitIntrinsicCallSite(ID, CS); diff --git a/llvm/lib/Target/CppBackend/CPPBackend.cpp b/llvm/lib/Target/CppBackend/CPPBackend.cpp index 272688edb8a..d9d2de42f3e 100644 --- a/llvm/lib/Target/CppBackend/CPPBackend.cpp +++ b/llvm/lib/Target/CppBackend/CPPBackend.cpp @@ -551,7 +551,8 @@ void CppWriter::printAttributes(const AttributeSet &PAL, void CppWriter::printType(Type* Ty) { // We don't print definitions for primitive types if (Ty->isFloatingPointTy() || Ty->isX86_MMXTy() || Ty->isIntegerTy() || - Ty->isLabelTy() || Ty->isMetadataTy() || Ty->isVoidTy()) + Ty->isLabelTy() || Ty->isMetadataTy() || Ty->isVoidTy() || + Ty->isTokenTy()) return; // If we already defined this type, we don't need to define it again. diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp index dba2d1bee60..13cdef90106 100644 --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -654,6 +654,7 @@ int FunctionComparator::cmpTypes(Type *TyL, Type *TyR) const { case Type::PPC_FP128TyID: case Type::LabelTyID: case Type::MetadataTyID: + case Type::TokenTyID: return 0; case Type::PointerTyID: { diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 6ad782f5089..b87f4766e8d 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -260,6 +260,11 @@ static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB, if (isa<BitCastInst>(I) && I->getType()->isPointerTy()) continue; + // Bail out if this instruction gives back a token type, it is not possible + // to duplicate it if it used outside this BB. + if (I->getType()->isTokenTy() && I->isUsedOutsideOfBlock(BB)) + return ~0U; + // All other instructions count for at least one unit. ++Size; diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index a7515bbf961..83dd1826c22 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -337,14 +337,8 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock, TPI->eraseFromParent(); UpdatePHINodes(BB); } - } else if (auto *CPI = dyn_cast<CleanupPadInst>(I)) { - if (CPI->getNumOperands() == 0) { - CleanupPadInst::Create(CPI->getType(), {UnwindDest}, CPI->getName(), - CPI); - CPI->eraseFromParent(); - } } else { - assert(isa<CatchPadInst>(I)); + assert(isa<CatchPadInst>(I) || isa<CleanupPadInst>(I)); } } |