diff options
author | Daniel Dunbar <daniel@zuster.org> | 2013-03-15 20:55:27 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2013-03-15 20:55:27 +0000 |
commit | e738fc5145984235a8f084077791271c4d266236 (patch) | |
tree | 913ac747058266d19a5419a0aca03288268c620d /lib | |
parent | 1fd8d46d222fab7f17b91846e2c50bef640a60a0 (diff) |
[AST] Add a fast path to ConstantArrayType::getNumAddressingBits().
- This fast path is almost 100% effective on real code, and lets us avoid
multiple allocations of 128-bit APSInt objects in the common case.
- As with any overflow-check-skipping-code, I'd appreciate someone double
checking my logic.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177183 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/Type.cpp | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index cdd67fda4f..0c5636d840 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -76,16 +76,35 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) { unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements) { + uint64_t ElementSize = Context.getTypeSizeInChars(ElementType).getQuantity(); + + // Fast path the common cases so we can avoid the conservative computation + // below, which in common cases allocates "large" APSInt values, which are + // slow. + + // If the element size is a power of 2, we can directly compute the additional + // number of addressing bits beyond those required for the element count. + if (llvm::isPowerOf2_64(ElementSize)) { + return NumElements.getActiveBits() + llvm::Log2_64(ElementSize); + } + + // If both the element count and element size fit in 32-bits, we can do the + // computation directly in 64-bits. + if ((ElementSize >> 32) == 0 && NumElements.getBitWidth() <= 64 && + (NumElements.getZExtValue() >> 32) == 0) { + uint64_t TotalSize = NumElements.getZExtValue() * ElementSize; + return 64 - llvm::CountLeadingZeros_64(TotalSize); + } + + // Otherwise, use APSInt to handle arbitrary sized values. llvm::APSInt SizeExtended(NumElements, true); unsigned SizeTypeBits = Context.getTypeSize(Context.getSizeType()); SizeExtended = SizeExtended.extend(std::max(SizeTypeBits, SizeExtended.getBitWidth()) * 2); - uint64_t ElementSize - = Context.getTypeSizeInChars(ElementType).getQuantity(); llvm::APSInt TotalSize(llvm::APInt(SizeExtended.getBitWidth(), ElementSize)); TotalSize *= SizeExtended; - + return TotalSize.getActiveBits(); } |