From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19340 invoked by alias); 7 Aug 2006 09:09:47 -0000 Received: (qmail 19270 invoked by uid 48); 7 Aug 2006 09:09:37 -0000 Date: Mon, 07 Aug 2006 09:09:00 -0000 Message-ID: <20060807090937.19269.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug rtl-optimization/21299] [4.0/4.1/4.2 Regression] internal error on invalid asm statement In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "hubicka at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2006-08/txt/msg00468.txt.bz2 List-Id: ------- Comment #5 from hubicka at gcc dot gnu dot org 2006-08-07 09:09 ------- The IA-64 problem shall be fixed by my patch for PR target/26655. The x86 problem is trickier. Reload is decided to merge all classes mentioned in given alternative, so "ad" is equivalent to "A", while recog.c is working the oposite way. The best way to fix it I can think of is to make reload ignore the classes that are too small to fit the register themselves. It does not fix the problem quite in general but at least deals with the x86 cases. (in general one can have multiple register mode, join together two multiple reg classes but reload might place the result just on the boundary still making recog unhappy.) Better ideas? Honza Index: reload.c =================================================================== -cp -L reload.c (revision 115987) -L reload.c (working copy) .svn/text-base/reload.c.svn-base reload.c *** reload.c (revision 115987) --- reload.c (working copy) *************** find_reloads (rtx insn, int replace, int *** 2913,2918 **** --- 2913,2919 ---- operand. */ int constmemok = 0; int earlyclobber = 0; + enum reg_class class = NO_REGS; /* If the predicate accepts a unary operator, it means that we need to reload the operand, but do not do this for *************** find_reloads (rtx insn, int replace, int *** 3309,3314 **** --- 3310,3316 ---- /* Drop through into 'r' case. */ case 'r': + class = GENERAL_REGS; this_alternative[i] = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS]; goto reg; *************** find_reloads (rtx insn, int replace, int *** 3368,3384 **** break; } this_alternative[i] = (int) (reg_class_subunion [this_alternative[i]] ! [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]); reg: if (GET_MODE (operand) == BLKmode) break; winreg = 1; if (REG_P (operand) ! && reg_fits_class_p (operand, this_alternative[i], ! offset, GET_MODE (recog_data.operand[i]))) win = 1; break; } --- 3370,3409 ---- break; } + class = REG_CLASS_FROM_CONSTRAINT (c, p); + /* When class is too tiny to hold the operand, ignore it. + See PR21299. First quickly test if things looks slopy + and if they does try to look if register is really + available. */ + if (CLASS_MAX_NREGS (class, GET_MODE (recog_data.operand[i])) + > (int)reg_class_size [class]) + { + int regno; + enum machine_mode mode; + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if (TEST_HARD_REG_BIT (reg_class_contents[class], regno) + && HARD_REGNO_MODE_OK (regno, mode) + && (regno + hard_regno_nregs[regno][mode] + < FIRST_PSEUDO_REGISTER) + && TEST_HARD_REG_BIT + (reg_class_contents[class], + regno + hard_regno_nregs[regno][mode])) + break; + if (regno == FIRST_PSEUDO_REGISTER) + break; + } this_alternative[i] = (int) (reg_class_subunion [this_alternative[i]] ! [(int) class]); reg: if (GET_MODE (operand) == BLKmode) break; winreg = 1; if (REG_P (operand) ! && reg_fits_class_p (operand, class, ! offset, ! GET_MODE (recog_data.operand[i]))) win = 1; break; } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21299