The following testcase produces an ICE in subst_reloads, when compiled with "-march=z990 -O2 -ftracer":
----------------snip-------------------- extern int memcmp(const void *s1, const void *s2, unsigned long n); extern int printf (__const char *__restrict __format, ...); typedef struct { char tmp[4092]; char msglen[4]; char msgtype[2]; } TESTSTRUCT; void test_func(TESTSTRUCT *testtb) { if (testtb) printf("a"); if (memcmp(testtb->msgtype, "a", 2)) printf("a"); printf("b"); } ------------------snap-------------------- % ./gcc/cc1 -march=z990 -O2 -ftracer test.i test_func Analyzing compilation unitPerforming intraprocedural optimizations Assembling functions: test_func test.i: In function ‘test_func’: test.i:19: internal compiler error: in subst_reloads, at reload.c:6108 This already ICEs with the hammer branch, and I think is also still a latent problem in trunk. It's a combination of the tracer and CSE working hand in hand to produce an invalid MEM address. It goes like so: 1) Initially the memcmp() call is implemented by the cmpmem_short instruction of s390. Remember that with -march=z990 we have long displacements active. The instruction emitted for the memcmp() is: (insn 69 68 70 1 (parallel [ (set (reg:CCU 33 %cc) (compare:CCU (mem/s:BLK (reg/f:DI 46) [0 S2 A8]) (mem/s:BLK (plus:DI (reg/v/f:DI 43 [ testtb ]) (const_int 4096 [0x1000])) [0 <variable>.msgtype+0 S2 A8]))) (use (const_int 1 [0x1])) (use (const:BLK (unspec:BLK [ (const_int 0 [0x0]) ] 213))) (clobber (scratch:DI)) ]) 92 {*cmpmem_short} (nil) (expr_list:REG_EQUAL (compare:CCU (mem/s:BLK (symbol_ref/f:DI ("*.LC0") [flags 0x2] <string_cst 0x20000368b70>) [0 S2 A8]) (mem/s:BLK (plus:DI (reg/v/f:DI 43 [ testtb ]) (const_int 4096 [0x1000])) [0 <variable>.msgtype+0 S2 A8])) (nil))) So, everything fine, but note the (mem (plus (reg 43) (4096)) operand, which we are going to screw up soon. 2) Then -ftracer comes along an duplicates a trace through the whole function using the "if (testtb)" predicate. So we end up with two copies of the body, including the above instruction. One of them under the testtb==0 branch. 3) Now CSE2 comes into play, with it's path following feature. In the second version of the above insn it knows that testtb (== pseudo 43) is zero. Hence it happily changes the insn to read: (insn 24 23 25 3 (parallel [ (set (reg:CCU 33 %cc) (compare:CCU (mem/s:BLK (reg/f:DI 46) [0 S2 A8]) (mem/s:BLK (const_int 4096 [0x1000]) [0 <variable>.msgtype+0 S2 A8]))) (use (const_int 1 [0x1])) (use (const:BLK (unspec:BLK [ (const_int 0 [0x0]) ] 213))) (clobber (scratch:DI)) ]) 92 {*cmpmem_short} (nil) Note how the operand in question now is (mem (const_int 4096)). That is fine so far normally, as the compiler can't know that this is going to be in invalid address operand. It can't know that because all predicates say that it is valid. 4) reload comes over that insn, looks at the various operands and addresses and also determines that (mem (const_int 4096)) is valid because strict_memory_address_p returns true for it. 5) But then the constraints are checked too. And we use 'Q' constraints in the cmpmem_short insn: (define_insn "*cmpmem_short" [(set (reg:CCU CC_REGNUM) (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q") (match_operand:BLK 1 "memory_operand" "Q,Q,Q"))) (use (match_operand 2 "nonmemory_operand" "n,a,a")) (use (match_operand 3 "immediate_operand" "X,R,X")) (clobber (match_scratch 4 "=X,X,&a"))] ... And the 'Q' constraint forbids long displacements also on long disp machines. So we now have an inconsistent situation. As the constraints don't match we try to reload this address operand (const_int 4096): Reloads for insn # 24 Reload 0: reload_in (VOID) = (const_int 4096 [0x1000]) ADDR_REGS, RELOAD_FOR_INPUT (opnum = 1) reload_in_reg: (const_int 4096 [0x1000]) But this operand can't be reloaded easily, because the const_int has no mode, hence this whole reload has only VOIDmode, and no register can be found for it. Actually this situation should never happen (i.e. a modeless reload), that's why it isn't handled in push_reload and friends. All these invalid addresses should have been created a reload for much earlier than in the constraint checking. I unfortunately don't have a good idea how to fix this. I think these large displacements much somehow be forbidden already in the predicate, not only via the constraints, which would mean that one can't use "memory_operand" as predicate. Or cmpmem_short needs to accept also the 'S' constraint. Or some way would be found for reload to determine a mode for this reload despite it being only a const_int. Pmode would be natural. Alternatively strict_memory_address_p() (via legitimate_address_p() in s390.c) could reject addresses which only consist of a displacement larger than 4096. By that long displacement would still be accepted everywhere (when the machine has them) but only when connected with some register as base or index. That would ensure that a mode is available for the whole address which makes reloading possible. -- Summary: ICE in subst_reloads Product: gcc Version: 4.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: matz at gcc dot gnu dot org GCC host triplet: s390x-ibm-linux GCC target triplet: s390x-ibm-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27661