Bug 17965 - ice in expand_call
Summary: ice in expand_call
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.1.0
Assignee: Not yet assigned to anyone
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2004-10-13 02:34 UTC by Andrew Pinski
Modified: 2005-06-26 14:36 UTC (History)
1 user (show)

See Also:
Host:
Target: powerpc-darwin
Build:
Known to work:
Known to fail: 4.0.0 3.3.2
Last reconfirmed: 2005-05-07 22:48:16


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2004-10-13 02:34:08 UTC
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
 
 
template < typename atom, int n > struct StrassenMatrix { 
    atom data[n][n]; 
 
    StrassenMatrix < atom, n / 2 > operator() (int a, int b) { 
        StrassenMatrix < atom, n / 2 > result; 
        int offs_i = a * n / 2; 
        int offs_j = b * n / 2; 
        for (int i = 0; i < n / 2; i++) 
            for (int j = 0; j < n / 2; j++) 
                 result.data[i][j] = data[i + offs_i][j + offs_j]; 
         return result; 
    }  
     
    StrassenMatrix operator+(StrassenMatrix m) { 
        StrassenMatrix result; 
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < n; j++) 
                result.data[i][j] = data[i][j] + m.data[i][j]; 
        return result; 
    } 
 
    StrassenMatrix operator-(StrassenMatrix m) { 
        StrassenMatrix result; 
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < n; j++) 
                result.data[i][j] = data[i][j] - m.data[i][j]; 
        return result; 
    } 
 
    StrassenMatrix operator*(StrassenMatrix m2) { 
        StrassenMatrix result; 
        StrassenMatrix < atom, n / 2 > p1, p2, p3, p4, p5, p6, p7; 
        StrassenMatrix m1 = *this; 
        p1 = (m1(0, 1) - m1(1, 1)) * (m2(1, 0) + m2(1, 1)); 
        p2 = (m1(0, 0) + m1(1, 1)) * (m2(0, 0) + m2(1, 1)); 
        p3 = (m1(0, 0) - m1(1, 0)) * (m2(0, 0) + m2(0, 1)); 
        p4 = (m1(0, 0) + m1(0, 1)) * m2(1, 1); 
        p5 = m1(0, 0) * (m2(0, 1) - m2(1, 1)); 
        p6 = m1(1, 1) * (m2(1, 0) - m2(0, 0)); 
        p7 = (m1(1, 0) + m1(1, 1)) * m2(0, 0); 
        int nhalf = n / 2; 
        for (int i = 0; i < nhalf; i++) { 
            for (int j = 0; j < nhalf; j++) { 
                result.data[i][j] =  
                    p1.data[i][j] + p2.data[i][j] - p4.data[i][j] +  
                    p6.data[i][j]; 
                result.data[i][j + nhalf] =  
                    p4.data[i][j] + p5.data[i][j]; 
                result.data[i + nhalf][j] =  
                    p6.data[i][j] + p7.data[i][j]; 
                result.data[i + nhalf][j + nhalf] = 
                    p2.data[i][j] - p3.data[i][j] + p5.data[i][j] - 
                    p7.data[i][j]; 
            } 
        } 
        return result; 
    } 
 
    atom* elem(int i, int j) { 
        return &data[i][j]; 
    } 
}; 
 
template < typename atom > struct StrassenMatrix <atom, 1 > { 
    atom data[1][1]; 
 
    StrassenMatrix operator+(StrassenMatrix m) { 
        StrassenMatrix result; 
         result.data[0][0] = data[0][0] + m.data[0][0]; 
         return result; 
    }  
     
    StrassenMatrix operator-(StrassenMatrix m) { 
        StrassenMatrix result; 
        result.data[0][0] = data[0][0] - m.data[0][0]; 
        return result; 
    } 
 
    StrassenMatrix operator*(StrassenMatrix m) { 
        StrassenMatrix result; 
        result.data[0][0] = data[0][0] * m.data[0][0]; 
        return result; 
    } 
 
    atom* elem(int i, int j) { 
        return &data[i][j]; 
    } 
}; 
 
 
#define NUMTYPE double 
 
template<int dim> 
void test() { 
    // Initialisierung 
    StrassenMatrix < NUMTYPE, dim > strassen1, strassen2, strassenResult; 
    for (int i = 0; i < dim; i++) 
        for (int j = 0; j < dim; j++) { 
            *strassen1.elem(i,j) = 
                (NUMTYPE) (10.0 * rand() / (RAND_MAX + 1.0)); 
            *strassen2.elem(i,j) = 
                (NUMTYPE) (10.0 * rand() / (RAND_MAX + 1.0)); 
        } 
    // 5. Feld: Zeit fuer StrassenMatrix 
    strassenResult = strassen1 * strassen2; 
} 
 
int main(int argc, char **argv) 
{ 
    srand(0); 
    for (int i = 0; i < 5; i++) test<64>(); 
    for (int i = 0; i < 5; i++) test<128>(); 
    for (int i = 0; i < 5; i++) test<256>(); 
    for (int i = 0; i < 5; i++) test<512>(); 
    // ---*** HERE ***--- 
    // As soon as I uncomment the following line, g++ will seg fault.  
//    for (int i = 0; i < 5; i++) test<1024>(); 
    return 0; 
} 

--------------------------------------------
Confirmed, this is a middle-end problem on the mainline:
#0  0x003f13ec in expand_call (exp=0x42901a00, target=0xf15798, ignore=0) at /Users/pinskia/src/
local1/gcc/gcc/calls.c:2351
#1  0x004f3874 in expand_expr_real_1 (exp=0x42901a00, target=0xf15798, tmode=BLKmode, 
modifier=EXPAND_NORMAL, alt_rtl=0xbfffef94) at /Users/pinskia/src/local1/gcc/gcc/expr.c:7242
#2  0x004ec518 in expand_expr_real (exp=0x42901a00, target=0xf15798, tmode=BLKmode, 
modifier=EXPAND_NORMAL, alt_rtl=0xbfffef94) at /Users/pinskia/src/local1/gcc/gcc/expr.c:6314
#3  0x004dd2b8 in store_expr (exp=0x42901a00, target=0xf15798, want_value=0) at /Users/pinskia/
src/local1/gcc/gcc/expr.c:3933
#4  0x004dbfd4 in expand_assignment (to=0xb967c0, from=0x42901a00, want_value=0) at /Users/
pinskia/src/local1/gcc/gcc/expr.c:3746
#5  0x00500338 in expand_expr_real_1 (exp=0xb94480, target=0x0, tmode=VOIDmode, 
modifier=EXPAND_NORMAL, alt_rtl=0x0) at /Users/pinskia/src/local1/gcc/gcc/expr.c:8112
#6  0x004ec518 in expand_expr_real (exp=0xb94480, target=0x4280d300, tmode=VOIDmode, 
modifier=EXPAND_NORMAL, alt_rtl=0x0) at /Users/pinskia/src/local1/gcc/gcc/expr.c:6314
#7  0x007a5764 in expand_expr (exp=0xb94480, target=0x4280d300, mode=VOIDmode, 
modifier=EXPAND_NORMAL) at /Users/pinskia/src/local1/gcc/gcc/expr.h:493
#8  0x0079c4c4 in expand_expr_stmt (exp=0xb94480) at /Users/pinskia/src/local1/gcc/gcc/stmt.c:
1354
#9  0x00823a74 in expand_gimple_basic_block (bb=0xc25b24, dump_file=0x0) at /Users/pinskia/src/
local1/gcc/gcc/cfgexpand.c:1126
#10 0x008243b4 in tree_expand_cfg () at /Users/pinskia/src/local1/gcc/gcc/cfgexpand.c:1299
#11 0x002bb75c in execute_one_pass (pass=0xac30f4) at /Users/pinskia/src/local1/gcc/gcc/tree-
optimize.c:503
#12 0x002bb8a8 in execute_pass_list (pass=0xac30f4) at /Users/pinskia/src/local1/gcc/gcc/tree-
optimize.c:538
#13 0x002bbcac in tree_rest_of_compilation (fndecl=0x42905f04) at /Users/pinskia/src/local1/gcc/
gcc/tree-optimize.c:633
#14 0x001b4e9c in expand_body (fn=0x42905f04) at /Users/pinskia/src/local1/gcc/gcc/cp/
semantics.c:2912
#15 0x00864ff0 in cgraph_expand_function (node=0x42906000) at /Users/pinskia/src/local1/gcc/
gcc/cgraphunit.c:1046
#16 0x0086aaa0 in cgraph_expand_all_functions () at /Users/pinskia/src/local1/gcc/gcc/cgraphunit.c:
2728
#17 0x0086b048 in cgraph_optimize () at /Users/pinskia/src/local1/gcc/gcc/cgraphunit.c:2839
#18 0x001121d8 in cp_finish_file () at /Users/pinskia/src/local1/gcc/gcc/cp/decl2.c:3067
#19 0x00002764 in finish_file () at /Users/pinskia/src/local1/gcc/gcc/cp/cp-lang.c:136
#20 0x00266c28 in c_common_parse_file (set_yydebug=0) at /Users/pinskia/src/local1/gcc/gcc/c-
opts.c:1096
#21 0x007b8f9c in compile_file () at /Users/pinskia/src/local1/gcc/gcc/toplev.c:985
#22 0x007bbc3c in do_compile () at /Users/pinskia/src/local1/gcc/gcc/toplev.c:2069
#23 0x007bbcd8 in toplev_main (argc=2, argv=0xbffffd90) at /Users/pinskia/src/local1/gcc/gcc/
toplev.c:2101
#24 0x0027e094 in main (argc=2, argv=0xbffffd90) at /Users/pinskia/src/local1/gcc/gcc/main.c:35


                  stack_usage_map = alloca (highest_outgoing_arg_in_use);


highest_outgoing_arg_in_use is 8388624, maybe it is time to allocate it on the heap instead of the 
stack.
Comment 1 Andrew Pinski 2004-10-13 02:35:07 UTC
Confirmed (I can do this because this was basically PR 16578).
Comment 2 Giovanni Bajo 2004-10-13 02:43:52 UTC
You need -mtune=k8 or -mtune=pentiumpro to reproduce this on x86.
Comment 3 Wolfgang Bangerth 2004-10-13 03:07:01 UTC
Can you post the complete command line? I can't reproduce with Giovanni's 
options as well as -O2 with a snapshot from 20040930. 
 
W. 
Comment 4 Andrew Pinski 2004-10-13 03:17:22 UTC
I had forgot to uncomment the needed line in the given source:
//    for (int i = 0; i < 5; i++) test<1024>(); 

The comment in the source says it all though:
    // As soon as I uncomment the following line, g++ will seg fault.  
Comment 5 Wolfgang Bangerth 2004-10-13 13:29:51 UTC
I still can't reproduce with a snapshot from an hour ago. This is 
my command line: 
  /home/bangerth/bin/gcc-4.0-pre/bin/c++ -mtune=k8 -c x.cc -O2 
W. 
Comment 6 Andrew Pinski 2004-10-23 23:45:52 UTC
This 4.0 regression at least on powerpc-darwin.  It used to work in 3.3.
Comment 7 Andrew Pinski 2004-11-25 18:44:11 UTC
The problem is that we don't mark structs which are passed by reference really by reference so it adds 
it to the size of the arguments which is wrong.
Simple example:
struct a
{
  int a2[1024][1024];
  int a1[1024][1024];
};
void f(struct a a2){}
struct a a1;
void g()
{
  f(a1);
}
Comment 8 Alan Modra 2004-11-28 10:25:42 UTC
If I recollect correctly, stack_usage_map is only relevant for libcalls that
might be executed when evaluating arguments for a call.  ie. There's no need to
cater for arbitrary user function calls.  This suggests that the right fix for
this particular problem is to limit the size of stack_usage_map to something
that covers all possible libcall arguments.
Comment 9 Andrew Pinski 2005-06-22 12:07:36 UTC
Patch was posted here: <http://gcc.gnu.org/ml/gcc-patches/2005-06/msg01764.html>
Comment 10 CVS Commits 2005-06-26 05:27:24 UTC
Subject: Bug 17965

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	jakub@gcc.gnu.org	2005-06-26 05:27:15

Modified files:
	gcc            : ChangeLog calls.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/gcc.c-torture/compile: 20050622-1.c 

Log message:
	PR middle-end/17965
	* calls.c (expand_call, emit_library_call_value_1): Use xmalloc/free
	instead of alloca for really big argument sizes.
	
	* gcc.c-torture/compile/20050622-1.c: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.9231&r2=2.9232
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/calls.c.diff?cvsroot=gcc&r1=1.391&r2=1.392
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5687&r2=1.5688
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/compile/20050622-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 11 Andrew Pinski 2005-06-26 14:36:05 UTC
Fixed.
Comment 12 Jakub Jelinek 2005-11-21 09:41:45 UTC
Subject: Bug 17965

Author: jakub
Date: Mon Nov 21 09:41:42 2005
New Revision: 107289

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=107289
Log:
	PR middle-end/17965
	* calls.c (expand_call, emit_library_call_value_1): Use xmalloc/free
	instead of alloca for really big argument sizes.

	* gcc.c-torture/compile/20050622-1.c: New test.

Added:
    branches/gcc-4_0-rhl-branch/gcc/testsuite/gcc.c-torture/compile/20050622-1.c
Modified:
    branches/gcc-4_0-rhl-branch/gcc/ChangeLog
    branches/gcc-4_0-rhl-branch/gcc/calls.c
    branches/gcc-4_0-rhl-branch/gcc/testsuite/ChangeLog