This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR middle-end/PR44706 II (wrong profile estimate)
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org, rguenther at suse dot de
- Date: Wed, 30 Jun 2010 19:20:07 +0200
- Subject: PR middle-end/PR44706 II (wrong profile estimate)
Hi,
this patch fixes the other problem. In the testcase there is call to throw () that ends
up predicted as likely. Noreturn call heruistic should make it predicted unlikely, but
this does not happen. It looks for control dependence block of the call and predict
edge as unlikely. However the block has only EH edge except for the one predicted
so the prediction has no effect.
This patch makes predict_paths_for_bb to check if there is another non-abnormal/fake/eh
edge out of the BB that leads to block not postominated by BB and drops prediction only
in that case. If this is not the case, it looks for control dependce of the new block
until something is found.
Bootstrapped/regtested x86_64-linux. Will hold the commit until after the merge unless
Richard tells me it is fine otherwise.
Honza
PR middle-end/44706
* g++.dg/tree-ssa/pr44706.C: New testcase.
* predict.c (predict_paths_for_bb): Handle case when control dependence
BB has only abnormal edges.
Index: testsuite/g++.dg/tree-ssa/pr44706.C
===================================================================
--- testsuite/g++.dg/tree-ssa/pr44706.C (revision 0)
+++ testsuite/g++.dg/tree-ssa/pr44706.C (revision 0)
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-fnsplit" } */
+class MemoryManager;
+class XMLExcepts {
+public :
+ enum Codes {
+ AttrList_BadIndex
+ };
+};
+class XMLException {
+public:
+ XMLException(const char* const srcFile, const unsigned int srcLine,
+MemoryManager* const memoryManager = 0);
+};
+class ArrayIndexOutOfBoundsException : public XMLException {
+public:
+ ArrayIndexOutOfBoundsException(const char* const srcFile , const unsigned
+int srcLine , const XMLExcepts::Codes toThrow , MemoryManager* memoryManager =
+0) : XMLException(srcFile, srcLine, memoryManager) {
+ }
+};
+class XMLAttDef {
+ bool fExternalAttribute;
+};
+class XMLAttDefList {
+public:
+ MemoryManager* getMemoryManager() const;
+};
+class DTDAttDef : public XMLAttDef {
+};
+class DTDAttDefList : public XMLAttDefList {
+ virtual const XMLAttDef &getAttDef(unsigned int index) const ;
+ DTDAttDef** fArray;
+ unsigned int fCount;
+};
+const XMLAttDef &DTDAttDefList::getAttDef(unsigned int index) const {
+ if(index >= fCount)
+ throw ArrayIndexOutOfBoundsException("foo.cpp", 0,
+XMLExcepts::AttrList_BadIndex, getMemoryManager());
+ return *(fArray[index]);
+}
+
+/* Mistake in branch prediction caused us to split away real body of the function keeping
+ only throw () invokation. This is bad idea. */
+/* { dg-final { scan-tree-dump-not "Splitting function" "fnsplit"} } */
+/* { dg-final { cleanup-tree-dump "fnsplit" } } */
Index: predict.c
===================================================================
--- predict.c (revision 161597)
+++ predict.c (working copy)
@@ -1786,8 +1786,33 @@ predict_paths_for_bb (basic_block cur, b
if (e->src->index >= NUM_FIXED_BLOCKS
&& !dominated_by_p (CDI_POST_DOMINATORS, e->src, bb))
{
+ edge e2;
+ edge_iterator ei2;
+ bool found = false;
+
+ /* Ignore abnormals, we predict them as not taken anyway. */
+ if (e->flags & (EDGE_EH | EDGE_FAKE | EDGE_ABNORMAL))
+ continue;
gcc_assert (bb == cur || dominated_by_p (CDI_POST_DOMINATORS, cur, bb));
- predict_edge_def (e, pred, taken);
+
+ /* See if there is how many edge from e->src that is not abnormal
+ and does not lead to BB. */
+ FOR_EACH_EDGE (e2, ei2, e->src->succs)
+ if (e2 != e
+ && !(e2->flags & (EDGE_EH | EDGE_FAKE | EDGE_ABNORMAL))
+ && !dominated_by_p (CDI_POST_DOMINATORS, e2->dest, bb))
+ {
+ found = true;
+ break;
+ }
+
+ /* If there is non-abnormal path leaving e->src, predict edge
+ using predictor. Otherwise we need to look for paths
+ leading to e->src. */
+ if (found)
+ predict_edge_def (e, pred, taken);
+ else
+ predict_paths_for_bb (e->src, e->src, pred, taken);
}
for (son = first_dom_son (CDI_POST_DOMINATORS, cur);
son;