s390.c (pool_stop_uid, [...]): Delete.
authorUlrich Weigand <uweigand@de.ibm.com>
Fri, 15 Feb 2002 23:30:03 +0000 (23:30 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Fri, 15 Feb 2002 23:30:03 +0000 (23:30 +0000)
* config/s390/s390.c (pool_stop_uid, other_chunk, far_away,
check_and_change_labels, s390_final_chunkify): Delete.
(s390_split_branches, s390_chunkify_pool): New functions.
(s390_function_prologue): Call them.

* config/s390/s390.h (S390_REL_MAX): Delete.
(S390_CHUNK_MAX, S390_CHUNK_OV): Adjust values.

* config/s390/s390.md (cjump, icjump, jump): Fix length
attribute calculation.

From-SVN: r49797

gcc/ChangeLog
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md

index 682ed307d94132b56aed7c0520d1aeb10a35058f..73f2033975ac6c675fcc355270f83016aa1b737b 100644 (file)
@@ -1,3 +1,17 @@
+2002-02-16  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.c (pool_stop_uid, other_chunk, far_away, 
+       check_and_change_labels, s390_final_chunkify): Delete.
+       (s390_split_branches, s390_chunkify_pool): New functions.
+       (s390_function_prologue): Call them.
+       
+       * config/s390/s390.h (S390_REL_MAX): Delete.
+       (S390_CHUNK_MAX, S390_CHUNK_OV): Adjust values.
+
+       * config/s390/s390.md (cjump, icjump, jump): Fix length 
+       attribute calculation.
+
+
 2002-02-15  David Edelsohn  <edelsohn@gnu.org>
 
        * config/rs6000/linux64.h (STRIP_NAME_ENCODING): Delete.
index 178b32ef2336d3b8e7ed3299a81916648b5c00c5..0f6a9db10c7304b34a8f25250faec8982297d12c 100644 (file)
@@ -129,10 +129,8 @@ static int general_s_operand PARAMS ((rtx, enum machine_mode, int));
 static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
 static int reg_used_in_mem_p PARAMS ((int, rtx));
 static int addr_generation_dependency_p PARAMS ((rtx, rtx));
-static int other_chunk PARAMS ((int *, int, int));
-static int far_away PARAMS ((int, int));
-static rtx check_and_change_labels PARAMS ((rtx, int *));
-static void s390_final_chunkify PARAMS ((int));
+static void s390_split_branches PARAMS ((void));
+static void s390_chunkify_pool PARAMS ((void));
 static int save_fprs_p PARAMS ((void));
 static int find_unused_clobbered_reg PARAMS ((void));
 static void s390_frame_info PARAMS ((struct s390_frame *));
@@ -2341,10 +2339,6 @@ int s390_pool_count = -1;
    processed.  */
 rtx s390_pool_start_insn = NULL_RTX;
 
-/* UID of last insn using the constant pool chunk that is currently 
-   being processed.  */
-static int pool_stop_uid;
-
 /* Called from the ASM_OUTPUT_POOL_PROLOGUE macro to 
    prepare for printing a literal pool chunk to stdio stream FILE.  
 
@@ -2382,312 +2376,206 @@ s390_asm_output_pool_prologue (file, fname, fndecl, size)
     function_section (fndecl);
 }
 
-/* Return true if OTHER_ADDR is in different chunk than MY_ADDR.
-   LTORG points to a list of all literal pools inserted
-   into the current function.  */
+/* Split all branches that exceed the maximum distance.  */
 
-static int
-other_chunk (ltorg, my_addr, other_addr)
-     int *ltorg;
-     int my_addr;
-     int other_addr;
+static void 
+s390_split_branches (void)
 {
-  int ad, i=0, j=0;
-
-  while ((ad = ltorg[i++])) {
-    if (INSN_ADDRESSES (ad) >= my_addr)
-      break;
-  }
-
-  while ((ad = ltorg[j++])) {
-    if (INSN_ADDRESSES (ad) > other_addr)
-      break;
-  }
-  
-  if (i==j)
-    return 0;
-
-  return 1;
-}
+  rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
+  rtx insn, pat, label, target, jump, tmp;
 
-/* Return true if OTHER_ADDR is too far away from MY_ADDR
-   to use a relative branch instruction.  */
+  /* In 64-bit mode we can jump +- 4GB.  */
 
-static int 
-far_away (my_addr, other_addr)
-     int my_addr;
-     int other_addr;
-{
-  /* In 64 bit mode we can jump +- 4GB.  */
   if (TARGET_64BIT)
-    return 0;
-  if (abs (my_addr - other_addr) > S390_REL_MAX)
-    return 1;
-  return 0;
-}
+    return;
 
-/* Go through all insns in the current function (starting
-   at INSN), replacing branch insn if necessary.  A branch
-   needs to be modified if either the distance to the 
-   target is too far to use a relative branch, or if the
-   target uses a different literal pool than the origin.
-   LTORG_UIDS points to a list of all literal pool insns
-   that have been inserted.  */
+  /* Find all branches that exceed 64KB, and split them.  */
 
-static rtx 
-check_and_change_labels (insn, ltorg_uids)
-     rtx insn;
-     int *ltorg_uids;
-{
-  rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
-  rtx target, jump, cjump;
-  rtx pattern, tmp, body, label1;
-  int addr0, addr1;
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    {
+      if (GET_CODE (insn) != JUMP_INSN)
+       continue;
 
-  if (GET_CODE (insn) != JUMP_INSN) 
-    return insn;
+      pat = PATTERN (insn);
+      if (GET_CODE (pat) != SET)
+       continue;
 
-  pattern = PATTERN (insn);
-  
-  addr0 = INSN_ADDRESSES (INSN_UID (insn));
-  if (GET_CODE (pattern) == SET) 
-    {
-      body = XEXP (pattern, 1);
-      if (GET_CODE (body) == LABEL_REF) 
+      if (GET_CODE (SET_SRC (pat)) == LABEL_REF) 
        {
-         addr1 = INSN_ADDRESSES (INSN_UID (XEXP (body, 0)));
-         
-         if (other_chunk (ltorg_uids, addr0, addr1)) 
-           {
-             SYMBOL_REF_USED (XEXP (body, 0)) = 1;
-           } 
-         if (far_away (addr0, addr1)) 
-           {
-             if (flag_pic) 
-               {
-                 target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, body), 100);
-                 target = gen_rtx_CONST (SImode, target);
-                 target = force_const_mem (SImode, target);
-                 jump = gen_rtx_REG (Pmode, BASE_REGISTER);
-                 jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
-               } 
-             else 
-               {
-                 target = force_const_mem (Pmode, body);
-                 jump = temp_reg;
-               }
-             
-             emit_insn_before (gen_movsi (temp_reg, target), insn);
-             tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
-             remove_insn (insn);
-             INSN_ADDRESSES_NEW (tmp, -1);
-             return tmp;
-           }
+         label = SET_SRC (pat);
        } 
-      else if (GET_CODE (body) == IF_THEN_ELSE) 
+      else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE) 
        {
-         if (GET_CODE (XEXP (body, 1)) == LABEL_REF) 
-           {
-             addr1 = INSN_ADDRESSES (INSN_UID (XEXP (XEXP (body, 1), 0)));
-             
-             if (other_chunk (ltorg_uids, addr0, addr1)) 
-               {
-                 SYMBOL_REF_USED (XEXP (XEXP (body, 1), 0)) = 1;
-               } 
-             
-             if (far_away (addr0, addr1)) 
-               {
-                 if (flag_pic) 
-                   {
-                     target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, XEXP (body, 1)), 100);
-                     target = gen_rtx_CONST (SImode, target);
-                     target = force_const_mem (SImode, target);
-                     jump = gen_rtx_REG (Pmode, BASE_REGISTER);
-                     jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
-                   } 
-                 else 
-                   {
-                     target = force_const_mem (Pmode, XEXP (body, 1));
-                     jump = temp_reg;
-                   }
-                 
-                 label1 = gen_label_rtx ();
-                 cjump = gen_rtx_LABEL_REF (VOIDmode, label1);
-                 cjump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (body, 0), pc_rtx, cjump);
-                 cjump = gen_rtx_SET (VOIDmode, pc_rtx, cjump);
-                 emit_jump_insn_before (cjump, insn);
-                 emit_insn_before (gen_movsi (temp_reg, target), insn);
-                 tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
-                 INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
-                 remove_insn (insn);
-                 return tmp;
-               }
-           }
-         else if (GET_CODE (XEXP (body, 2)) == LABEL_REF) 
-           {
-             addr1 = INSN_ADDRESSES (INSN_UID (XEXP (XEXP (body, 2), 0)));
-             
-             if (other_chunk (ltorg_uids, addr0, addr1)) 
-               {
-                 SYMBOL_REF_USED (XEXP (XEXP (body, 2), 0)) = 1;
-               } 
-             
-             if (far_away (addr0, addr1)) 
-               {
-                 if (flag_pic) 
-                   {
-                     target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, XEXP (body, 2)), 100);
-                     target = gen_rtx_CONST (SImode, target);
-                     target = force_const_mem (SImode, target);
-                     jump = gen_rtx_REG (Pmode, BASE_REGISTER);
-                     jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
-                   } 
-                 else 
-                   {
-                     target = force_const_mem (Pmode, XEXP (body, 2));
-                     jump = temp_reg;
-                   }
-                 
-                 label1 = gen_label_rtx ();
-                 cjump = gen_rtx_LABEL_REF (VOIDmode, label1);
-                 cjump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (body, 0), cjump, pc_rtx);
-                 cjump = gen_rtx_SET (VOIDmode, pc_rtx, cjump);
-                 emit_jump_insn_before (cjump, insn);
-                 emit_insn_before (gen_movsi (temp_reg, target), insn);
-                 tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
-                 INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
-                 remove_insn (insn);
-                 return tmp;
-               }
-           }
+         if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF) 
+           label = XEXP (SET_SRC (pat), 1);
+          else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF) 
+            label = XEXP (SET_SRC (pat), 2);
+         else
+           continue;
+        }
+      else
+       continue;
+
+      if (get_attr_length (insn) == 4)
+       continue;
+
+      if (flag_pic)
+       {
+         target = gen_rtx_UNSPEC (SImode, gen_rtvec (1, label), 100);
+         target = gen_rtx_CONST (SImode, target);
+         target = force_const_mem (SImode, target);
+         jump = gen_rtx_REG (Pmode, BASE_REGISTER);
+         jump = gen_rtx_PLUS (Pmode, jump, temp_reg);
        }
-    } 
-  else if (GET_CODE (pattern) == ADDR_VEC || 
-          GET_CODE (pattern) == ADDR_DIFF_VEC) 
-    {
-      int i, diff_vec_p = GET_CODE (pattern) == ADDR_DIFF_VEC;
-      int len = XVECLEN (pattern, diff_vec_p);
-      
-      for (i = 0; i < len; i++) 
+      else
        {
-         addr1 = INSN_ADDRESSES (INSN_UID (XEXP (XVECEXP (pattern, diff_vec_p, i), 0)));
-         if (other_chunk (ltorg_uids, addr0, addr1)) 
-           {
-             SYMBOL_REF_USED (XEXP (XVECEXP (pattern, diff_vec_p, i), 0)) = 1;
-           } 
+         target = force_const_mem (Pmode, label);
+         jump = temp_reg;
+       }
+
+      if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
+       {
+         if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
+           jump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (SET_SRC (pat), 0),
+                                        jump, pc_rtx);
+         else
+           jump = gen_rtx_IF_THEN_ELSE (VOIDmode, XEXP (SET_SRC (pat), 0),
+                                        pc_rtx, jump);
        }
+
+      tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
+      INSN_ADDRESSES_NEW (tmp, -1);
+
+      tmp = emit_jump_insn_before (gen_rtx_SET (VOIDmode, pc_rtx, jump), insn);
+      INSN_ADDRESSES_NEW (tmp, -1);
+
+      remove_insn (insn);
+      insn = tmp;
     }
-  return insn;
 }
 
-/* Called from s390_function_prologue to make final adjustments
-   before outputting code.  CHUNKIFY specifies whether we need
-   to use multiple literal pools (because the total size of the
-   literals exceeds 4K).  */
+/* Chunkify the literal pool if required.  */
 
-static void
-s390_final_chunkify (chunkify)
-     int chunkify;
+static void 
+s390_chunkify_pool (void)
 {
-  rtx insn, ninsn, tmp;
-  int addr, naddr = 0, uids;
-  int chunk_max = 0;
+  int *ltorg_uids, max_ltorg, chunk, last_addr;
+  rtx insn;
 
-  int size = insn_current_address;
+  /* Do we need to chunkify the literal pool?  */
 
-  int *ltorg_uids;
-  int max_ltorg=0;
+  if (get_pool_size () <= S390_POOL_MAX)
+    return;
 
-  ltorg_uids = alloca (size / 1024 + 1024);
-  memset (ltorg_uids, 0, size / 1024 + 1024);
+  /* Find all insns where a literal pool chunk must be inserted.  */
 
-  if (chunkify == 1) 
-    {
-      chunk_max = size * 2048 / get_pool_size ();
-      chunk_max = chunk_max > S390_CHUNK_MAX 
-       ? S390_CHUNK_MAX : chunk_max;
-    } 
-  
-  for (insn=get_insns (); insn;insn = next_real_insn (insn)) 
+  ltorg_uids = alloca (insn_current_address / 1024 + 1024);
+  max_ltorg = 0;
+
+  last_addr = 0;
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
-      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+      if (INSN_ADDRESSES (INSN_UID (insn)) - last_addr < S390_CHUNK_MAX)
        continue;
-      
-      addr = INSN_ADDRESSES (INSN_UID (insn));
-      if ((ninsn = next_real_insn (insn))) 
+      if (INSN_ADDRESSES (INSN_UID (insn)) - last_addr > S390_CHUNK_OV)
+       abort ();
+
+      if (GET_CODE (insn) == CODE_LABEL
+         && !(GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
+              && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
+                  || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC)))
        {
-         naddr = INSN_ADDRESSES (INSN_UID (ninsn));
+         ltorg_uids[max_ltorg++] = INSN_UID (prev_real_insn (insn));
+         last_addr = INSN_ADDRESSES (ltorg_uids[max_ltorg-1]);
+         continue;
        }
-      
-      if (chunkify && (addr / chunk_max != naddr / chunk_max)) 
+
+      if (GET_CODE (insn) == CALL_INSN)
        {
-         for (tmp = insn; tmp; tmp = NEXT_INSN (tmp)) 
-           {
-             if (GET_CODE (tmp) == CODE_LABEL && 
-                 GET_CODE (NEXT_INSN (tmp)) != JUMP_INSN) 
-               {
-                 ltorg_uids[max_ltorg++] = INSN_UID (prev_real_insn (tmp));
-                 break;
-               } 
-             if (GET_CODE (tmp) == CALL_INSN) 
-               {
-                 ltorg_uids[max_ltorg++] = INSN_UID (tmp);
-                 break;
-               } 
-             if (INSN_ADDRESSES (INSN_UID (tmp)) - naddr > S390_CHUNK_OV) 
-               {
-                 debug_rtx (insn);
-                 debug_rtx (tmp);
-                 fprintf (stderr, "s390 multiple literalpool support:\n No code label between this insn %X %X",
-                          naddr, INSN_ADDRESSES (INSN_UID (tmp)));
-                 abort ();
-               }
-           }
-         if (tmp == NULL) 
-           {
-             warning ("no code label found");
-           }
-       } 
+         ltorg_uids[max_ltorg++] = INSN_UID (insn);
+         last_addr = INSN_ADDRESSES (ltorg_uids[max_ltorg-1]);
+         continue;
+       }
     }
-  ltorg_uids[max_ltorg] = 0;
 
-  if (max_ltorg > 0)
-    {
-      for (insn = get_insns (), uids = 0; insn; insn = next_real_insn (insn)) 
-        if (INSN_UID (insn) == ltorg_uids[uids]) 
-         {
-           INSN_ADDRESSES_NEW (emit_insn_after (gen_ltorg (
-                               gen_rtx_CONST_INT (Pmode, ltorg_uids[++uids])),
-                                              insn), -1);
-         } 
+  ltorg_uids[max_ltorg] = insn_current_address + 1;
 
-      init_insn_lengths ();
-      shorten_branches (get_insns ());
-    }
+  /* Find and mark all labels that are branched into 
+     from an insn belonging to a different chunk.  */
 
-  for (insn = get_insns (); insn; insn = next_real_insn (insn)) 
+  chunk = last_addr = 0;
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
-      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
-       continue;
       if (GET_CODE (insn) == JUMP_INSN) 
-       insn = check_and_change_labels (insn, ltorg_uids);
+       {
+          rtx pat = PATTERN (insn);
+          if (GET_CODE (pat) == SET) 
+            {
+             rtx label = 0;
+
+              if (GET_CODE (SET_SRC (pat)) == LABEL_REF) 
+               {
+                 label = XEXP (SET_SRC (pat), 0);
+               } 
+              else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE) 
+               {
+                 if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF) 
+                   label = XEXP (XEXP (SET_SRC (pat), 1), 0);
+                 else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF) 
+                   label = XEXP (XEXP (SET_SRC (pat), 2), 0);
+               }
+
+             if (label)
+               {
+                 if (INSN_ADDRESSES (INSN_UID (label)) <= last_addr
+                     || INSN_ADDRESSES (INSN_UID (label)) > ltorg_uids[chunk])
+                   SYMBOL_REF_USED (label) = 1;
+               }
+            } 
+          else if (GET_CODE (pat) == ADDR_VEC
+                  || GET_CODE (pat) == ADDR_DIFF_VEC)
+            {
+             int i, diff_p = GET_CODE (pat) == ADDR_DIFF_VEC;
+
+              for (i = 0; i < XVECLEN (pat, diff_p); i++) 
+               {
+                 rtx label = XEXP (XVECEXP (pat, diff_p, i), 0);
+
+                 if (INSN_ADDRESSES (INSN_UID (label)) <= last_addr
+                     || INSN_ADDRESSES (INSN_UID (label)) > ltorg_uids[chunk])
+                   SYMBOL_REF_USED (label) = 1;
+               }
+            }
+        }
+
+      if (INSN_UID (insn) == ltorg_uids[chunk]) 
+        {
+         last_addr = ltorg_uids[chunk++];
+        }
     }
 
-  if (chunkify) 
+  /* Insert literal pools and base register reload insns.  */
+
+  chunk = 0;
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     {
-    for (insn=get_insns (); insn;insn = next_insn (insn)) 
-      {
-      if (GET_CODE (insn) == CODE_LABEL) 
+      if (INSN_UID (insn) == ltorg_uids[chunk]) 
+        {
+         rtx new_insn = gen_ltorg (GEN_INT (chunk++));
+         INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
+        }
+
+      if (GET_CODE (insn) == CODE_LABEL && SYMBOL_REF_USED (insn))
        {
-       if (SYMBOL_REF_USED (insn)) 
-         {
-           INSN_ADDRESSES_NEW (emit_insn_after (gen_reload_base (
-                                                                 gen_rtx_LABEL_REF (Pmode, XEXP (insn, 0))), insn), -1);
-         }
+         rtx new_insn = gen_reload_base (insn);
+         INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
        }
-      }
     }
-  pool_stop_uid = ltorg_uids[0];
+
+  /* Recompute insn addresses.  */
+
+  init_insn_lengths ();
+  shorten_branches (get_insns ());
 }
 
 /* Return true if INSN is a 'ltorg' insn.  */
@@ -2719,7 +2607,6 @@ s390_dump_literal_pool (act_insn, stop)
      rtx stop;
 {
   s390_pool_start_insn = act_insn;
-  pool_stop_uid = INTVAL (stop);
   s390_pool_count++;
   output_constant_pool (current_function_name, current_function_decl);
   function_section (current_function_decl);
@@ -2927,10 +2814,8 @@ s390_function_prologue (file, lsize)
      FILE *file ATTRIBUTE_UNUSED;
      HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
 {
-  if (get_pool_size () > S390_POOL_MAX)
-    s390_final_chunkify (1);
-  else
-    s390_final_chunkify (0);
+  s390_chunkify_pool ();
+  s390_split_branches ();
 }
 
 /* Output the function epilogue assembly code to the 
index 9bba974fd3defb66a060e7910629876aae0b3af2..6756e6099ef4ba935df6bcd2ea1f1dc137f00efe 100644 (file)
@@ -1330,9 +1330,8 @@ extern int s390_nr_constants;
 /* Function is splitted in chunk, if literal pool could overflow
    Value need to be lowered, if problems with displacement overflow.  */
 
-#define S390_REL_MAX 55000
-#define S390_CHUNK_MAX 0x2000
-#define S390_CHUNK_OV 0x8000
+#define S390_CHUNK_MAX 0xe00
+#define S390_CHUNK_OV 0x1000
 #define S390_POOL_MAX 0xe00
 
 #define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, fndecl, size)                  \
index 112116a2c2a414fbda3b121d248758e9138159c9..1ec96849b36c639dd8bc8457a72432384b1d68bb 100644 (file)
   ""
   "*
 {
-  if (get_attr_length (insn) == 4 || !TARGET_64BIT)
-     return \"j%C1\\t%l0\";
+  if (get_attr_length (insn) == 4)
+    return \"j%C1\\t%l0\";
+  else if (TARGET_64BIT)
+    return \"jg%C1\\t%l0\";
   else
-     return \"jg%C1\\t%l0\";
+    abort ();
 }"
   [(set_attr "op_type" "RI")
-   (set (attr "length") (if_then_else
-      (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
-      (const_int 4) (const_int 6)))])
+   (set (attr "length")
+        (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+                (const_int 4)
+               (ne (symbol_ref "TARGET_64BIT") (const_int 0))
+                 (const_int 6)
+               (eq (symbol_ref "flag_pic") (const_int 0))
+                 (const_int 6)] (const_int 8)))])
 
 (define_insn "*cjump_long"
  [(set (pc)
   ""
   "*
 {  
-  if (get_attr_length (insn) == 4 || !TARGET_64BIT)
-     return \"j%D1\\t%l0\";
+  if (get_attr_length (insn) == 4)
+    return \"j%D1\\t%l0\";
+  else if (TARGET_64BIT)
+    return \"jg%D1\\t%l0\";
   else
-     return \"jg%D1\\t%l0\";
+    abort ();
 }"
   [(set_attr "op_type" "RI")
-   (set (attr "length") (if_then_else
-     (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
-     (const_int 4) (const_int 6)))])
+   (set (attr "length")
+        (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+                (const_int 4)
+               (ne (symbol_ref "TARGET_64BIT") (const_int 0))
+                 (const_int 6)
+               (eq (symbol_ref "flag_pic") (const_int 0))
+                 (const_int 6)] (const_int 8)))])
 
 (define_insn "*icjump_long"
  [(set (pc)
   ""
   "*
 {
-  if (get_attr_length (insn) == 4 || !TARGET_64BIT)
-     return \"j\\t%l0\";
+  if (get_attr_length (insn) == 4)
+    return \"j\\t%l0\";
+  else if (TARGET_64BIT)
+    return \"jg\\t%l0\";
   else
-     return \"jg\\t%l0\";
+    abort ();
 }"
   [(set_attr "op_type" "RI")
-   (set (attr "length") (if_then_else
-     (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
-     (const_int 4) (const_int 6)))])
+   (set (attr "length")
+        (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+                (const_int 4)
+               (ne (symbol_ref "TARGET_64BIT") (const_int 0))
+                 (const_int 6)
+               (eq (symbol_ref "flag_pic") (const_int 0))
+                 (const_int 6)] (const_int 8)))])
 
 ;
 ; indirect-jump instruction pattern(s).