From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32476 invoked by alias); 16 Apr 2010 22:34:32 -0000 Received: (qmail 32376 invoked by uid 48); 16 Apr 2010 22:34:07 -0000 Date: Fri, 16 Apr 2010 22:34:00 -0000 Message-ID: <20100416223407.32375.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug target/43744] SH: Error: pcrel too far In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "kkojima at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2010-04/txt/msg01615.txt.bz2 ------- Comment #7 from kkojima at gcc dot gnu dot org 2010-04-16 22:34 ------- Created an attachment (id=20404) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=20404&action=view) A bit reduced test case It seems that we see a yet another corner case for find_barrier. Also it looks latent on the trunk and 4.5. Here is what is going on, I guess. For PIC, sh.c:fixup_mova replaces casesi_worker_1 insn with casesi_worker_2 insn and a constant table entry is added to a constant pool. In the problematic case, find_barrier inserts this constant pool in the middle of insns for casesi_worker_2. Then the constant pool including the above constant table entry is put before some of those insns. This results a code sequence like mov.l .L94,r0 ! insn for casesi_worker_2 ... CP: .long bar ... .L94: .long .L24-.L86 .align 5 .L87: add r0,r1 ! insn for casesi_worker_2 mova .L86,r0 ! insn for casesi_worker_2 mov.b @(r0,r1),r1 ! insn for casesi_worker_2 ... .L24: .byte .L22-.L25 .byte .L23-.L25 ... otherCP: .L86: which looks unexpected to the range computation in find_barrier. It seems that the constant entry .long .L24-.L86 was assumed to be put after the label .L86. The patch below is an experimental one to avoid the issue, though there would be better ways. --- ORIG/gcc-4_4-branch/gcc/config/sh/sh.c 2010-04-15 19:59:21.000000000 +0900 +++ gcc-4_4-branch/gcc/config/sh/sh.c 2010-04-16 19:46:26.000000000 +0900 @@ -3884,6 +3884,7 @@ find_barrier (int num_mova, rtx mova, rt int si_limit; int hi_limit; rtx orig = from; + rtx last_symoff = NULL_RTX; /* For HImode: range is 510, add 4 because pc counts from address of second instruction after this one, subtract 2 for the jump instruction @@ -4013,8 +4014,17 @@ find_barrier (int num_mova, rtx mova, rt if (mova_p (from)) { + rtx src; + switch (untangle_mova (&num_mova, &mova, from)) { + case 1: + src = SET_SRC (PATTERN (from)); + if (GET_CODE (src) == CONST + && GET_CODE (XEXP (src, 0)) == UNSPEC + && XINT (XEXP (src, 0), 1) == UNSPEC_SYMOFF) + last_symoff = from; + break; case 0: return find_barrier (0, 0, mova); case 2: { @@ -4120,6 +4130,9 @@ find_barrier (int num_mova, rtx mova, rt so we'll make one. */ rtx label = gen_label_rtx (); + if (last_symoff) + from = last_symoff; + /* If we exceeded the range, then we must back up over the last instruction we looked at. Otherwise, we just need to undo the NEXT_INSN at the end of the loop. */ -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43744