aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2013-03-15 20:55:27 +0000
committerDaniel Dunbar <daniel@zuster.org>2013-03-15 20:55:27 +0000
commite738fc5145984235a8f084077791271c4d266236 (patch)
tree913ac747058266d19a5419a0aca03288268c620d
parent1fd8d46d222fab7f17b91846e2c50bef640a60a0 (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
-rw-r--r--lib/AST/Type.cpp25
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();
}