[PATCH] Bug 14070 - Deeply nested struct types cause opt run time to explode
Oleg Ranevskyy
llvm.mail.list at gmail.com
Fri Aug 15 07:53:14 PDT 2014
Hi rafael, chandlerc,
**PROBLEM**
The problem appears on deeply nested structures due to the //getFoldedSizeOf// implementation (lib/IR/ConstantFold.cpp), which is very ineffective on such data types.
//getFoldedSizeOf// runs through the structure's fields to find out if all the fields are of the same size. If the function finds they are of different size, it calls //ConstantExpr::getSizeOf// with the structure type as an argument. //ConstantExpr::getSizeOf// internally leads to //getFoldedSizeOf// call that iterates the structure's fields again calculating structure size.
Since //getFoldedSizeOf// has recursive nature, the number of its calls grows immensely with structure nesting depth increase. E.g., for the attached structure having nesting depth=21 it is called 31719423 times.
**PROPOSED SOLUTION**
//getFoldedSizeOf// is doing the same work twice:
1) when iterating the structure's fields to compare field sizes;
2) when finally calling //ConstantExpr::getSizeOf// to calculate structure size.
The idea is to eliminate the 2nd step and calculate the whole size at the 1st step by summarizing sizes of separate fields.
This solution reduces //getFoldedSizeOf// calls from over 31M to about 80. The structure is processed in a fraction of a second.
Regression and performance tests show no regression.
http://reviews.llvm.org/D4928
Files:
lib/IR/ConstantFold.cpp
Index: lib/IR/ConstantFold.cpp
===================================================================
--- lib/IR/ConstantFold.cpp
+++ lib/IR/ConstantFold.cpp
@@ -349,19 +349,29 @@
if (NumElems == 0)
return ConstantExpr::getNullValue(DestTy);
// Check for a struct with all members having the same size.
- Constant *MemberSize =
+ Constant *FirstMemberSize =
getFoldedSizeOf(STy->getElementType(0), DestTy, true);
+ Constant *StructSize = FirstMemberSize;
+
bool AllSame = true;
- for (unsigned i = 1; i != NumElems; ++i)
- if (MemberSize !=
- getFoldedSizeOf(STy->getElementType(i), DestTy, true)) {
+ for (unsigned i = 1; i != NumElems; ++i){
+ Constant *MemberSize = getFoldedSizeOf(STy->getElementType(i), DestTy, true);
+ StructSize = ConstantExpr::getNUWAdd(StructSize, MemberSize);
+
+ if (FirstMemberSize != MemberSize){
+ if (!Folded)
+ return nullptr;
+
AllSame = false;
- break;
}
+ }
+
if (AllSame) {
Constant *N = ConstantInt::get(DestTy, NumElems);
- return ConstantExpr::getNUWMul(MemberSize, N);
+ return ConstantExpr::getNUWMul(FirstMemberSize, N);
}
+
+ return ConstantExpr::getCast(CastInst::getCastOpcode(StructSize, false, DestTy, false), StructSize, DestTy);
}
// Pointer size doesn't depend on the pointee type, so canonicalize them
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4928.12552.patch
Type: text/x-patch
Size: 1461 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140815/5df3d86a/attachment.bin>
More information about the llvm-commits
mailing list