please the find test case in the attachment. It shows the issue in google-4_6 branch
-c -O2 -fno-strict-aliasing ss.C -fdump-rtl-expand-all in the rtl-expand dump, trianglevertices and one the gtest_ar are in the same partition. the problem is found in arm compiler, but we manager to reproduce in x86. -Rong On Tue, Apr 24, 2012 at 3:02 PM, Andrew Pinski <pins...@gmail.com> wrote: > On Tue, Apr 24, 2012 at 2:57 PM, Rong Xu <x...@google.com> wrote: >> Hi, >> >> In split_function() (ipa-split.c), for the newly created call stmt, >> its block is set to the outermost scope, i.e. >> DECL_INITIAL(current_function_decl). When we inline this >> partially outlined function, we create the new block based on the >> block for the call stmt (in expand_call_inline()). >> So the new block for the inlined body is in >> parallel to the function top level scope. This bad block structure will >> late result in a bad stack layout. > > We do not depend on the block structure any more when dealing with > stack layout for variables in GCC 4.7.0 and above. I am not saying > your patch is incorrect or not needed. Just it will not have an > effect on variable stack layout. > > Did you have a testcase for the bad stack layout issue? Or was it too > hard to produce one because the size matters? > > >> >> This patch fixes the issue by setting the correct block number. It >> starts with the split_point entry bb to find the block stmt in the >> outlined region. The entry_bb maybe an empty BB so we need to follow >> the CFG until we find a non-empty bb. >> >> My early patch tried to use the block info from the first non-empty >> bb in the outlined regision. But that failed bootstrap as some of the >> stmts (assignment stmt) do not have the block info (bug?). So in this >> patch I traverse all the stmts in the bb until getting the block info. >> >> Tested with gcc bootstap. > > On which target? > > Thanks, > Andrew Pinski > >> >> Thanks, >> >> 2012-04-24 Rong Xu <x...@google.com> >> >> * ipa-split.c (split_function): set the correct block for the >> call statement. >> >> Index: ipa-split.c >> =================================================================== >> --- ipa-split.c (revision 186634) >> +++ ipa-split.c (working copy) >> @@ -948,7 +948,7 @@ >> int num = 0; >> struct cgraph_node *node, *cur_node = cgraph_node (current_function_decl); >> basic_block return_bb = find_return_bb (); >> - basic_block call_bb; >> + basic_block call_bb, bb; >> gimple_stmt_iterator gsi; >> gimple call; >> edge e; >> @@ -958,6 +958,7 @@ >> gimple last_stmt = NULL; >> unsigned int i; >> tree arg; >> + tree split_loc_block = NULL; >> >> if (dump_file) >> { >> @@ -1072,6 +1073,33 @@ >> } >> } >> >> + /* Find the block location of the split region. */ >> + bb = split_point->entry_bb; >> + do >> + { >> + bool found = false; >> + >> + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) >> + { >> + if (is_gimple_debug(gsi_stmt(gsi))) >> + continue; >> + if ((split_loc_block = gimple_block (gsi_stmt (gsi)))) >> + { >> + found = true; >> + break; >> + } >> + } >> + if (found) >> + break; >> + >> + /* If we reach here, this bb should be an empty unconditional >> + or fall-throuth branch. We continue with the succ bb. */ >> + bb = single_succ (bb); >> + } >> + while (bb && bitmap_bit_p (split_point->split_bbs, bb->index)); >> + >> + gcc_assert (split_loc_block); >> + >> /* Now create the actual clone. */ >> rebuild_cgraph_edges (); >> node = cgraph_function_versioning (cur_node, NULL, NULL, args_to_skip, >> @@ -1115,7 +1143,7 @@ >> VEC_replace (tree, args_to_pass, i, arg); >> } >> call = gimple_build_call_vec (node->decl, args_to_pass); >> - gimple_set_block (call, DECL_INITIAL (current_function_decl)); >> + gimple_set_block (call, split_loc_block); >> >> /* We avoid address being taken on any variable used by split part, >> so return slot optimization is always possible. Moreover this is >> >> -- >> This patch is available for review at http://codereview.appspot.com/6111050
namespace testing { class Test { virtual void TestBody() = 0; }; class AssertionResult { public: AssertionResult(const AssertionResult& other); operator bool() const { return success_; } private: bool success_; void operator=(AssertionResult const &); }; namespace internal { class TestFactoryBase { public: virtual ::testing::Test* CreateTest() = 0; }; template <class TestClass> class TestFactoryImpl : public TestFactoryBase { public: virtual ::testing::Test* CreateTest() { return new TestClass; } }; char* MakeAndRegisterTestInfo2( const char* test_case_name, TestFactoryBase* factory); AssertionResult CmpHelperEQ(const char* expected_expression, const char* actual_expression, long long expected, long long actual); AssertionResult CmpHelperNE( const char* expr, const char* expr2, long long val1, long long val2); template <bool lhs_is_null_literal> class EqHelper { public: template <typename T1, typename T2> static AssertionResult Compare(const char* expected_expression, const char* actual_expression, const T1& expected, const T2& actual) { return CmpHelperEQ(expected_expression, actual_expression, expected, actual); } static AssertionResult Compare(const char* expected_expression, const char* actual_expression, long long expected, long long actual) { return CmpHelperEQ(expected_expression, actual_expression, expected, actual); } }; class Secret; template<bool> struct EnableIf; template<> struct EnableIf<true> { typedef void type; }; template <bool bool_value> struct bool_constant { typedef bool_constant<bool_value> type; static const bool value = bool_value; }; template <bool bool_value> const bool bool_constant<bool_value>::value; typedef bool_constant<false> false_type; typedef bool_constant<true> true_type; template <typename T> struct is_pointer : public false_type {}; template <typename T> struct is_pointer<T*> : public true_type {}; template <> class EqHelper<true> { public: template <typename T1, typename T2> static AssertionResult Compare( const char* expected_expression, const char* actual_expression, const T1& expected, const T2& actual, typename EnableIf<!is_pointer<T2>::value>::type* = 0) { return CmpHelperEQ(expected_expression, actual_expression, expected, actual); } template <typename T> static AssertionResult Compare( const char* expected_expression, const char* actual_expression, Secret* , T* actual) { return CmpHelperEQ(expected_expression, actual_expression, static_cast<T*>(__null), actual); } }; char IsNullLiteralHelper(Secret* p); } } extern "C" { __attribute__((visibility("default"))) unsigned int glGetError(void); __attribute__((visibility("default"))) void glVertexAttribPointer( unsigned int indx, int size, unsigned int type, bool normalized, int stride, const void* ptr); } typedef unsigned int GLenum; class SGL : public ::testing::Test { protected: void drawTexture() { const float triangleVertices[] = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f }; glVertexAttribPointer(mPositionHandle, 2, 0x1406, 0, 0, triangleVertices); if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing::internal::IsNullLiteralHelper(GLenum(0))) == 1)>::Compare("GLenum(0)", "glGetError()", GLenum(0), glGetError()))) ; else return; if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing::internal::IsNullLiteralHelper(GLenum(0))) == 1)>::Compare("GLenum(0)", "glGetError()", GLenum(0), glGetError()))) ; else return; } int mPositionHandle; }; class SGL_1_Test : public SGL { private: virtual void TestBody() { drawTexture(); } }; class SGL_2_Test : public SGL { private: virtual void TestBody() { mPositionHandle = 12; drawTexture(); } static const char* test_info_; }; const char* SGL_2_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo2( "SGL_2_Test", new ::testing::internal::TestFactoryImpl<SGL_2_Test>);