[llvm-commits] [llvm-gcc-4.2] r54208 - in /llvm-gcc-4.2/trunk/gcc: config/i386/i386.c cse.c dwarf2out.c global.c ifcvt.c recog.c

Bill Wendling isanbard at gmail.com
Wed Jul 30 01:02:53 PDT 2008


Author: void
Date: Wed Jul 30 03:02:52 2008
New Revision: 54208

URL: http://llvm.org/viewvc/llvm-project?rev=54208&view=rev
Log:
Merges from Apple's GCC 4.2 r148430

Modified:
    llvm-gcc-4.2/trunk/gcc/config/i386/i386.c
    llvm-gcc-4.2/trunk/gcc/cse.c
    llvm-gcc-4.2/trunk/gcc/dwarf2out.c
    llvm-gcc-4.2/trunk/gcc/global.c
    llvm-gcc-4.2/trunk/gcc/ifcvt.c
    llvm-gcc-4.2/trunk/gcc/recog.c

Modified: llvm-gcc-4.2/trunk/gcc/config/i386/i386.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/i386.c?rev=54208&r1=54207&r2=54208&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/i386/i386.c (original)
+++ llvm-gcc-4.2/trunk/gcc/config/i386/i386.c Wed Jul 30 03:02:52 2008
@@ -1134,8 +1134,12 @@
 int x86_prefetch_sse;
 
 /* ix86_regparm_string as a number */
-/* LLVM local */
+/* LLVM LOCAL begin */
+#ifndef ENABLE_LLVM
+static
+#endif
 int ix86_regparm;
+/* LLVM LOCAL end */
 
 /* APPLE LOCAL begin 5612787 mainline sse4 */
 /* True if SSE population count insn supported. */
@@ -1241,8 +1245,11 @@
 static bool ix86_function_ok_for_sibcall (tree, tree);
 static tree ix86_handle_cconv_attribute (tree *, tree, tree, int, bool *);
 static int ix86_value_regno (enum machine_mode, tree, tree);
-/* LLVM LOCAL make global */
-/*static bool contains_128bit_aligned_vector_p (tree);*/
+/* LLVM LOCAL - begin make global */
+#ifndef ENABLE_LLVM
+static bool contains_128bit_aligned_vector_p (tree);
+#endif
+/* LLVM LOCAL - end make global */
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
 static tree ix86_handle_struct_attribute (tree *, tree, tree, int, bool *);
@@ -4109,8 +4116,12 @@
 
 /* Return true when TYPE should be 128bit aligned for 32bit argument passing
    ABI.  Only called if TARGET_SSE.  */
-/* LLVM LOCAL make global */
+/* LLVM LOCAL - begin make global */
+#ifndef ENABLE_LLVM
+static
+#endif
 bool
+/* LLVM LOCAL - end make global */
 contains_128bit_aligned_vector_p (tree type)
 {
   enum machine_mode mode = TYPE_MODE (type);

Modified: llvm-gcc-4.2/trunk/gcc/cse.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/cse.c?rev=54208&r1=54207&r2=54208&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/cse.c (original)
+++ llvm-gcc-4.2/trunk/gcc/cse.c Wed Jul 30 03:02:52 2008
@@ -1533,6 +1533,16 @@
   elt->mode = mode;
   elt->is_const = (CONSTANT_P (x) || fixed_base_plus_p (x));
 
+/* APPLE LOCAL begin ARM propagate stack addresses better */
+#ifdef TARGET_ARM
+  /* Adjust cost of SP+const addresses lower; generally, we want to propagate the addition
+     rather than use a register if these are equally cheap.  This attempts to compensate
+     for forcing the cost of a reg to 0. */
+  if (fixed_base_plus_p (x))
+    elt->cost -= 2 * COSTS_N_INSNS (1);
+#endif
+/* APPLE LOCAL end ARM propagate stack addresses better */
+
   if (table[hash])
     table[hash]->prev_same_hash = elt;
   table[hash] = elt;
@@ -2927,6 +2937,8 @@
 	  int best_addr_cost = address_cost (*loc, mode);
 	  int best_rtx_cost = (elt->cost + 1) >> 1;
 	  int exp_cost;
+	  /* APPLE LOCAL ARM propagate stack addresses better */
+	  bool best_fixed_base_plus_p = fixed_base_plus_p (elt->exp);
 	  struct table_elt *best_elt = elt;
 
 	  found_better = 0;
@@ -2937,11 +2949,25 @@
 		     || exp_equiv_p (p->exp, p->exp, 1, false))
 		    && ((exp_cost = address_cost (p->exp, mode)) < best_addr_cost
 			|| (exp_cost == best_addr_cost
-			    && ((p->cost + 1) >> 1) > best_rtx_cost)))
+/* APPLE LOCAL begin ARM propagate stack addresses better */
+#ifdef TARGET_ARM
+			    /* Prefer a stack address if possible.  Thus, prefer a new
+			       stack address to an old non-stack address, and do not replace
+			       an old stack address with a new non-stack address. */
+			    && ((!best_fixed_base_plus_p && fixed_base_plus_p (p->exp))
+				|| (!(best_fixed_base_plus_p && !fixed_base_plus_p (p->exp))
+				    && ((p->cost + 1) >> 1) > best_rtx_cost))
+#else
+			    && ((p->cost + 1) >> 1) > best_rtx_cost
+#endif
+		    )))
+/* APPLE LOCAL end ARM propagate stack addresses better */
 		  {
 		    found_better = 1;
 		    best_addr_cost = exp_cost;
 		    best_rtx_cost = (p->cost + 1) >> 1;
+		    /* APPLE LOCAL ARM propagate stack addresses better */
+		    best_fixed_base_plus_p = fixed_base_plus_p (p->exp);
 		    best_elt = p;
 		  }
 	      }

Modified: llvm-gcc-4.2/trunk/gcc/dwarf2out.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/dwarf2out.c?rev=54208&r1=54207&r2=54208&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/dwarf2out.c (original)
+++ llvm-gcc-4.2/trunk/gcc/dwarf2out.c Wed Jul 30 03:02:52 2008
@@ -69,6 +69,9 @@
 #include "hashtab.h"
 #include "cgraph.h"
 #include "input.h"
+/* APPLE LOCAL radar 5811943 - Fix type of pointers to Blocks  */
+/* APPLE LOCAL Radar 5741731, typedefs used in '@try' blocks    */ 
+#include "c-common.h"
 
 #ifdef DWARF2_DEBUGGING_INFO
 static void dwarf2out_source_line (unsigned int, const char *);
@@ -418,6 +421,13 @@
 #ifndef DWARF_FRAME_REGNUM
 #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
 #endif
+
+/* APPLE LOCAL begin differentiate between arm & thumb.  */
+#define DW_ISA_UNKNOWN         0
+#define DW_ISA_ARM_thumb       1
+#define DW_ISA_ARM_arm         2
+#define DW_ISA_USE_STMT_LIST  -1
+/* APPLE LOCAL end differentiate between arm & thumb.  */
 
 /* Hook used by __throw.  */
 
@@ -4026,6 +4036,11 @@
    within the current function.  */
 static HOST_WIDE_INT frame_pointer_fb_offset;
 
+/* APPLE LOCAL begin ARM prefer SP to FP */
+/* Which register was used to calculate the frame_pointer_fb_offset.  */
+static rtx frame_pointer_fb_offset_from;
+/* APPLE LOCAL end ARM prefer SP to FP */
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (rtx);
@@ -4776,7 +4791,15 @@
     case DW_AT_APPLE_optimized:
       return "DW_AT_APPLE_optimized";
     /* APPLE LOCAL end radar 2338865 optimization notification  */
-
+    /* APPLE LOCAL begin differentiate between arm & thumb.  */
+    case DW_AT_APPLE_isa:
+      return "DW_AT_APPLE_isa";
+    /* APPLE LOCAL end differentiate between arm & thumb.  */
+     
+    /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks  */
+    case DW_AT_APPLE_block:
+      return "DW_AT_APPLE_block";
+    /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks  */
     default:
       return "DW_AT_<unknown>";
     }
@@ -8590,6 +8613,17 @@
   if (code == ERROR_MARK)
     return NULL;
 
+  /* APPLE LOCAL begin Radar 5741731, typedefs used in '@try' blocks    */ 
+  if (is_volatile_type
+      && c_dialect_objc ()
+      && lookup_attribute ("objc_volatilized", TYPE_ATTRIBUTES (type)))
+    {
+      is_volatile_type = 0;
+      if (TYPE_NAME (type) && TREE_TYPE (TYPE_NAME (type)))
+	type = TREE_TYPE (TYPE_NAME (type));
+    }
+  /* APPLE LOCAL end Radar 5741731, typedefs used in '@try' blocks    */ 
+
   /* See if we already have the appropriately qualified variant of
      this type.  */
   qualified_type
@@ -8955,8 +8989,10 @@
 	      offset += INTVAL (XEXP (elim, 1));
 	      elim = XEXP (elim, 0);
 	    }
-	  gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
-		      : stack_pointer_rtx));
+	  /* APPLE LOCAL begin ARM prefer SP to FP */
+	  /* Make sure we are using the same base register.  */
+	  gcc_assert (elim == frame_pointer_fb_offset_from);
+	  /* APPLE LOCAL end ARM prefer SP to FP */
           offset += frame_pointer_fb_offset;
 
           return new_loc_descr (DW_OP_fbreg, offset, 0);
@@ -10846,9 +10882,10 @@
       offset += INTVAL (XEXP (elim, 1));
       elim = XEXP (elim, 0);
     }
-  gcc_assert (elim == (frame_pointer_needed ? hard_frame_pointer_rtx
-		       : stack_pointer_rtx));
+  /* APPLE LOCAL begin ARM prefer SP to FP */
 
+  frame_pointer_fb_offset_from = elim;
+  /* APPLE LOCAL end ARM prefer SP to FP */
   frame_pointer_fb_offset = -offset;
 }
 
@@ -11145,8 +11182,12 @@
 static inline void
 add_prototyped_attribute (dw_die_ref die, tree func_type)
 {
-  if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89
+  /* APPLE LOCAL begin radar 5344182 */
+  unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
+  
+  if ((lang == DW_LANG_C89 || lang == DW_LANG_ObjC)
       && TYPE_ARG_TYPES (func_type) != NULL)
+   /* APPLE LOCAL end radar 5344182 */
     add_AT_flag (die, DW_AT_prototyped, 1);
 }
 
@@ -11430,6 +11471,15 @@
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
 
+  /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to blocks  */
+  if (code == BLOCK_POINTER_TYPE)
+    {
+      gcc_assert (invoke_impl_ptr_type);
+      type = invoke_impl_ptr_type;
+      code = TREE_CODE (type);
+    }
+  /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks  */
+
   /* ??? If this type is an unnamed subrange type of an integral or
      floating-point type, use the inner type.  This is because we have no
      support for unnamed types in base_type_die.  This can happen if this is
@@ -12318,13 +12368,394 @@
   if (optimize > 0)
     add_AT_flag (subr_die, DW_AT_APPLE_optimized, 1);
   /* APPLE LOCAL end radar 2338865 optimization notification  */
+  /* APPLE LOCAL begin differentiate between arm & thumb.  */
+#ifdef TARGET_ARM
+  if (TARGET_THUMB)
+    add_AT_int (subr_die, DW_AT_APPLE_isa, DW_ISA_ARM_thumb);
+  else if (TARGET_ARM)
+    add_AT_int  (subr_die, DW_AT_APPLE_isa, DW_ISA_ARM_arm);
+#endif
+  /* APPLE LOCAL end differentiate between arm & thumb.  */
+  /* APPLE LOCAL confused diff */
+}
+/* APPLE LOCAL begin radar 6048397 handle block byref variables  */
+
+/* Byref variables, in blocks, are declared by the programmer as
+   "SomeType VarName;", but the compiler creates a
+   __Block_byref_x_VarName struct, and gives the variable VarName
+   either the struct, or a pointer to the struct, as its type.  This
+   is necessary for various behind-the-scenes things the compiler
+   needs to do with by-reference variables in blocks.
+
+   However, as far as the original *programmer* is concerned, the
+   variable should still have type 'SomeType', as originally declared.
+
+   The following function dives into the __Block_byref_x_VarName
+   struct to find the original type of the variable.  This will be
+   passed back to the code generating the type for the Debug
+   Information Entry for the variable 'VarName'.  'VarName' will then
+   have the original type 'SomeType' in its debug information.
+
+   The original type 'SomeType' will be the type of the field named
+   'VarName' inside the __Block_byref_x_VarName struct.
+
+   NOTE: In order for this to not completely fail on the debugger
+   side, the Debug Information Entry for the variable VarName needs to
+   have a DW_AT_location that tells the debugger how to unwind through
+   the pointers and __Block_byref_x_VarName struct to find the actual
+   value of the variable.  The function
+   add_block_byref_var_location_attribute does this.  */
+
+static tree
+find_block_byref_var_real_type (tree decl)
+{
+  tree block_struct = TREE_TYPE (decl);
+  const char *var_name ;
+  tree var_field;
+  bool found = false;
+  tree ret_type = NULL_TREE;
+
+
+  if ((! (DECL_NAME (decl)))
+      || (! IDENTIFIER_POINTER (DECL_NAME (decl))))
+    return ret_type;
+
+  if (!block_struct)
+    return ret_type;
+
+  /* Get the name of the variable whose real type we are trying to find.  */
+
+  var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
+
+  /* If the type for the variable was pointer to __Block_byref_etc, then
+     dereference the pointer type to get the structure __Block_byref_etc.  */
+
+  if (TREE_CODE (block_struct) == POINTER_TYPE)
+    block_struct = TREE_TYPE (block_struct);
+
+  /* If block_struct is NOT a __Block_byref_etc record, then something is
+     wrong, so we should bail out here.  */
+
+  if (TREE_CODE (block_struct) != RECORD_TYPE)
+    return ret_type;
+
+  if ((! TYPE_NAME (block_struct))
+      || (! IDENTIFIER_POINTER (TYPE_NAME (block_struct)))
+      || (strncmp (IDENTIFIER_POINTER (TYPE_NAME (block_struct)),
+		   "__Block_byref_", 14) != 0))
+    return ret_type;
+
+  /* We've got the record for a __Byref_block_etc; go through the fields
+     looking for one with the same name as the var_decl.  */
+
+  var_field = TYPE_FIELDS (block_struct);
+
+  while (var_field && !found)
+    {
+      if (TREE_CODE (var_field) != FIELD_DECL)
+	return ret_type;
+      if (DECL_NAME (var_field)
+	  && IDENTIFIER_POINTER (DECL_NAME (var_field))
+	  && strcmp (IDENTIFIER_POINTER (DECL_NAME (var_field)), var_name) == 0)
+	{
+	  /* We've found the right field.  Return its type.  */
+	  ret_type = TREE_TYPE (var_field);
+	  found = 1;
+	}
+      else
+	var_field = TREE_CHAIN (var_field);
+    }
+
+  return ret_type;
+}
+
+/* This function is a helper function for the function below,
+   add_block_byref_var_location_attribute.  See comments there
+   for full description.  */
+
+static void
+build_byref_var_location_expression (dw_loc_descr_ref *main_descr,
+				     bool is_pointer,
+				     int forwarding_field_offset,
+				     int var_field_offset)
+{
+  dw_loc_descr_ref temp_descr;
+
+  /* If we started with a pointer to the __Block_byref... struct, then
+     the first thing we need to do is dereference the pointer
+     (DW_OP_deref).  */
+
+  if (is_pointer)
+    {
+      temp_descr = new_loc_descr (DW_OP_deref, 0, 0);
+      add_loc_descr (main_descr, temp_descr);
+    }
+
+  /* Next add the offset for the 'forwarding' field:
+     DW_OP_plus_uconst forwarding_field_offset
+     Note, there's no point in adding it if the offset is 0.  */
+
+  if (forwarding_field_offset != 0)
+    {
+      temp_descr = new_loc_descr (DW_OP_plus_uconst, forwarding_field_offset,
+				  0);
+      add_loc_descr (main_descr, temp_descr);
+    }
+
+  /* Follow that pointer to find the *real* __Block_byref struct:
+     DW_OP_deref  */
+
+  temp_descr = new_loc_descr (DW_OP_deref, 0, 0);
+  add_loc_descr (main_descr, temp_descr);
+
+  /* Now we've got the real __Block_byref struct, add the offset for
+     the variable's field to get the location of the actual variable:
+     DW_OP_plus_uconst var_field_offset
+     Again, there's no point in adding the offset if it is 0.  */
+
+  if (var_field_offset != 0)
+    {
+      temp_descr = new_loc_descr (DW_OP_plus_uconst, var_field_offset, 0);
+      add_loc_descr (main_descr, temp_descr);
+    }
 }
 
+/* Byref variables, in blocks, are declared by the programmer as
+   "SomeType VarName;", but the compiler creates a
+   __Block_byref_x_VarName struct, and gives the variable VarName
+   either the struct, or a pointer to the struct, as its type.  This
+   is necessary for various behind-the-scenes things the compiler
+   needs to do with by-reference variables in blocks.
+
+   However, as far as the original *programmer* is concerned, the
+   variable should still have type 'SomeType', as originally declared.
+
+   The function find_block_byref_var_real_type dives into the
+   __Block_byref_x_VarName struct to find the original type of the
+   variable, which is then assigned to the variable's Debug
+   Information Entry as its real type.  So far, so good.  However now
+   the debugger will expect the variable VarName to have the type
+   SomeType.  So we need the location attribute for the variable to be
+   an expression that explains to the debugger how to navigate through
+   the pointers and struct to find the actual variable of type
+   SomeType.
+
+   The following function does just that.  We start by getting
+   the "normal" location for the variable. This will be the location
+   of either the struct __Block_byref_x_VarName or the pointer to the
+   struct __Block_byref_x_VarName.
+
+   The struct will look something like:
+
+   struct __Block_byref_x_VarName {
+     struct __Block_byref_x_VarName *forwarding;
+     ... <various irrelevant fields>
+     SomeType VarName;
+   };
+
+   If we are given the struct directly (as our starting point) we
+   need to tell the debugger to:
+
+   1).  Add the offset of the forwarding field (do NOT assume the field
+   will always be as position 0).
+
+   2).  Follow that pointer to get the the real __Block_byref_x_VarName
+   struct to use (the real one may have been copied onto the heap).
+
+   3).  Add the offset for the field VarName, to find the actual variable.
+
+   If we started with a pointer to the struct, then we need to
+   derefernce (follow) that pointer first, before the other steps.
+   Translating this into DWARF ops, we will need to append the following
+   to the current location description for the variable:
+
+   DW_OP_deref                    -- optional, if we start with a pointer
+   DW_OP_plus_uconst <forward_fld_offset>
+   DW_OP_deref
+   DW_OP_plus_uconst <varName_fld_offset>
+
+   This function returns a boolean indicating whether or not it was
+   able to successfully create and add the location description.  */
+
+static bool
+add_block_byref_var_location_attribute (dw_die_ref var_die, tree decl)
+{
+  tree block_struct = TREE_TYPE (decl);
+  const char *var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
+  tree var_field = NULL;
+  tree forwarding_field = NULL;
+  tree temp_field;
+  unsigned int forwarding_field_offset = 0;
+  unsigned int var_field_offset = 0;
+  bool is_pointer = false;
+  dw_loc_descr_ref descr;
+  var_loc_list *loc_list;
+
+  if (!block_struct)
+    return false;
+
+  if ((! DECL_NAME (decl))
+      || (! IDENTIFIER_POINTER (DECL_NAME (decl))))
+    return false;
+
+  /* Get the name of the variable whose location we are decoding.  */
+
+  var_name = IDENTIFIER_POINTER (DECL_NAME (decl));
+
+  if (TREE_CODE (block_struct) == POINTER_TYPE)
+    block_struct = TREE_TYPE (block_struct);
+
+  /* Verify that we have a record that is a __Block_byref_...  */
+
+  if (TREE_CODE (block_struct) != RECORD_TYPE)
+    return false;
+
+  if ((! TYPE_NAME (block_struct))
+      || (! IDENTIFIER_POINTER (TYPE_NAME (block_struct)))
+      || strncmp (IDENTIFIER_POINTER (TYPE_NAME (block_struct)),
+		  "__Block_byref_", 14) != 0)
+    return false;
+
+  /* Find the forwarding field and the variable field within
+     the struct.  */
+
+  temp_field = TYPE_FIELDS (block_struct);
+
+  while (temp_field
+	 && (!var_field || !forwarding_field))
+    {
+      if (TREE_CODE (temp_field) != FIELD_DECL)
+	return false;
+      if (DECL_NAME (temp_field)
+	  && IDENTIFIER_POINTER (DECL_NAME (temp_field)))
+	{
+	  if (strcmp (IDENTIFIER_POINTER (DECL_NAME (temp_field)),
+		      var_name) == 0)
+	    var_field = temp_field;
+	  else if (strcmp (IDENTIFIER_POINTER (DECL_NAME (temp_field)),
+			   "forwarding") == 0)
+	    forwarding_field = temp_field;
+	}
+
+      temp_field = TREE_CHAIN (temp_field);
+    }
+
+  /* If we didn't find both fields, we can't continue.  */
+
+  if (!var_field || !forwarding_field)
+    return false;
+
+  /* Get the offsets of the fields within the struct.  */
+
+  if (var_field)
+    var_field_offset = field_byte_offset (var_field);
+  if (forwarding_field)
+    forwarding_field_offset = field_byte_offset (forwarding_field);
+
+  /* Check to see if we start with a pointer we need to dereference,
+     or not.  */
+
+  if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
+    is_pointer = true;
+
+  /* See if we possible have multiple locations for this variable.  */
+  loc_list = lookup_decl_loc (decl);
+
+  /* If it truly has multiple locations, the first and last node will
+     differ.  */
+  if (loc_list && loc_list->first != loc_list->last)
+    {
+      struct var_loc_node *node;
+      rtx varloc;
+      dw_loc_list_ref list;
+      const char *endname, *secname;
+
+      /* Build the first entry for the location list.  */
+
+      node = loc_list->first;
+      varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+      secname = secname_for_decl (decl);
+
+      descr = loc_descriptor (varloc, STATUS_INITIALIZED);
+      build_byref_var_location_expression (&descr, is_pointer,
+					   forwarding_field_offset,
+					   var_field_offset);
+      list = new_loc_list (descr, node->label, node->next->label, secname, 1);
+      node = node->next;
+
+      for (; node->next; node = node->next)
+
+	/* Build the other entries for the location list, except the last.  */
+
+	if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+	  {
+	    varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+	    descr = loc_descriptor (varloc, STATUS_INITIALIZED);
+	    build_byref_var_location_expression (&descr, is_pointer,
+						 forwarding_field_offset,
+						 var_field_offset);
+	    add_loc_descr_to_loc_list (&list, descr, node->label,
+				       node->next->label, secname);
+	  }
+      if (NOTE_VAR_LOCATION_LOC (node->var_loc_note) != NULL_RTX)
+	{
+	  char label_id[MAX_ARTIFICIAL_LABEL_BYTES];
+
+	  /* Build the last entry for the location list.  */
+
+	  varloc = NOTE_VAR_LOCATION (node->var_loc_note);
+	  if (!current_function_decl)
+	    endname = text_end_label;
+	  else
+	    {
+	      ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL,
+					   current_function_funcdef_no);
+	      endname = ggc_strdup (label_id);
+	    }
+	  descr = loc_descriptor (varloc, STATUS_INITIALIZED);
+	  build_byref_var_location_expression (&descr, is_pointer,
+					       forwarding_field_offset,
+					       var_field_offset);
+	  add_loc_descr_to_loc_list (&list, descr, node->label, endname,
+				     secname);
+	}
+      add_AT_loc_list (var_die, DW_AT_location, list);
+    }
+  else
+    {
+      /* We are not dealing with a location list so...  */
+
+      /* 'descr' starts with the base location of the __Block_byref_... struct,
+	 or the pointer to the __Block_byref_... struct.  */
+
+      descr = loc_descriptor_from_tree (decl);
+      if (!descr)
+	return false;
+
+      build_byref_var_location_expression (&descr, is_pointer,
+					   forwarding_field_offset,
+					   var_field_offset);
+
+      /* Finally, now that we've built up the location description to find the
+	 actual value of the variable, add the location description to the
+	 variable's die.  */
+
+      add_AT_location_description (var_die, DW_AT_location, descr);
+    }
+
+  return true;
+}
+/* APPLE LOCAL end radar 6048397 handle block byref variables  */
+
 /* Generate a DIE to represent a declared data object.  */
 
 static void
 gen_variable_die (tree decl, dw_die_ref context_die)
 {
+  /* APPLE LOCAL begin radar 6048397 handle block byref variables  */
+  bool is_block_byref_var = false;
+  tree decl_type = TREE_TYPE (decl);
+  /* APPLE LOCAL end radar 6048397 handle block byref variables  */
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl);
 
@@ -12351,6 +12782,24 @@
 			 && DECL_COMDAT (decl) && !TREE_ASM_WRITTEN (decl))
 		     || class_or_namespace_scope_p (context_die));
 
+  /* APPLE LOCAL begin radar 6048397 handle block byref variables  */
+  /* Check to see if this variable is for a block passed-by-refernce
+     variable, in which case we need to do some special stuff for its
+     type and location.  */
+  if (decl_type)
+    {
+      if (TREE_CODE (decl_type) == POINTER_TYPE)
+	decl_type = TREE_TYPE (decl_type);
+      if (decl_type
+	  && TREE_CODE (decl_type) == RECORD_TYPE
+	  && TYPE_NAME (decl_type)
+	  && TREE_CODE (TYPE_NAME (decl_type)) == IDENTIFIER_NODE
+	  && IDENTIFIER_POINTER (TYPE_NAME (decl_type))
+	  && (strncmp (IDENTIFIER_POINTER (TYPE_NAME (decl_type)), 
+		       "__Block_byref_", 14) == 0))
+	  is_block_byref_var = true;
+    }
+  /* APPLE LOCAL end radar 6048397 handle block byref variables  */
   if (origin != NULL)
     add_abstract_origin_attribute (var_die, origin);
 
@@ -12388,8 +12837,24 @@
   else
     {
       add_name_and_src_coords_attributes (var_die, decl);
-      add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
-			  TREE_THIS_VOLATILE (decl), context_die);
+      /* APPLE LOCAL begin radar 6048397 handle block byref variables  */
+      if (is_block_byref_var)
+	{
+	  /* Try to find the real type for the variable; if we can't find
+	     it, fall back on the old behavior.  */
+	  tree real_type = NULL_TREE;
+	  real_type = find_block_byref_var_real_type (decl);
+	  if (real_type)
+	    add_type_attribute (var_die, real_type, TREE_READONLY (decl),
+				TREE_THIS_VOLATILE (decl), context_die);
+	  else
+	    add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
+				TREE_THIS_VOLATILE (decl), context_die);
+	}
+      else
+	add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
+			    TREE_THIS_VOLATILE (decl), context_die);
+      /* APPLE LOCAL end radar 6048397 handle block byref variables  */
 
       if (TREE_PUBLIC (decl))
 	add_AT_flag (var_die, DW_AT_external, 1);
@@ -12411,7 +12876,16 @@
 
   if (! declaration && ! DECL_ABSTRACT (decl))
     {
-      add_location_or_const_value_attribute (var_die, decl, DW_AT_location);
+      /* APPLE LOCAL begin radar 6048397 handle block byref variables  */
+      /* Try to build and add the location info for navigating through
+	 a __Block_byref_... struct to find the real variable.  If that
+	 fails, fall back on the old behavior.  */
+      bool loc_added = false;
+      if (is_block_byref_var)
+	loc_added = add_block_byref_var_location_attribute (var_die, decl);
+      if (!loc_added)
+	add_location_or_const_value_attribute (var_die, decl, DW_AT_location);
+      /* APPLE LOCAL end radar 6048397 handle block byref variables  */
       add_pubname (decl, var_die);
     }
   else
@@ -12827,6 +13301,11 @@
 	add_AT_specification (type_die, old_die);
       else
 	add_name_attribute (type_die, type_tag (type));
+
+      /* APPLE LOCAL begin radar 5811943 - Fix type of pointers to Blocks  */
+      if (TYPE_BLOCK_IMPL_STRUCT (type))
+	add_AT_flag (type_die, DW_AT_APPLE_block, 1);
+      /* APPLE LOCAL end radar 5811943 - Fix type of pointers to Blocks  */
     }
   else
     remove_AT (type_die, DW_AT_declaration);
@@ -13799,6 +14278,8 @@
 	 a plain function, this will be fixed up in decls_for_scope.  If
 	 we're a method, it will be ignored, since we already have a DIE.  */
       if (decl_function_context (decl)
+	  /* APPLE LOCAL blocks 5811952 */
+	  && (! BLOCK_HELPER_FUNC (decl))
 	  /* But if we're in terse mode, we don't care about scope.  */
 	  && debug_info_level > DINFO_LEVEL_TERSE)
 	context_die = NULL;

Modified: llvm-gcc-4.2/trunk/gcc/global.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/global.c?rev=54208&r1=54207&r2=54208&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/global.c (original)
+++ llvm-gcc-4.2/trunk/gcc/global.c Wed Jul 30 03:02:52 2008
@@ -51,6 +51,11 @@
 #define REWRITE_WEIGHT_COMPUTATION
 #endif
 /* APPLE LOCAL end rewrite weight computation */
+/* APPLE LOCAL begin 5831562 ARM pseudo-pseudo tying*/
+#ifndef TIE_PSEUDOS
+#define TIE_PSEUDOS 0
+#endif
+/* APPLE LOCAL end 5831562 ARM pseudo-pseudo tying*/
 
 /* This pass of the compiler performs global register allocation.
    It assigns hard register numbers to all the pseudo registers
@@ -308,6 +313,13 @@
 
 static int local_reg_n_refs[FIRST_PSEUDO_REGISTER];
 
+/* APPLE LOCAL begin 5831562 ARM pseudo-pseudo tying*/
+/* Set with no registers.  This is not declared const to avoid a warning at the point
+   of use; but it is const.  */
+
+static HARD_REG_SET empty_reg_set;
+/* APPLE LOCAL end 5831562 ARM pseudo-pseudo tying*/
+
 /* APPLE LOCAL begin rewrite weight computation */
 #ifdef REWRITE_WEIGHT_COMPUTATION
 /* Overall weight of each hard reg, as used by local alloc.
@@ -1538,6 +1550,12 @@
 #else
 	  int regno = i;
 #endif
+/* APPLE LOCAL begin 5831562 add DIMODE_REG_ALLOC_ORDER */
+#ifdef DIMODE_REG_ALLOC_ORDER
+	  if (mode == DImode)
+	    regno = dimode_reg_alloc_order[i];
+#endif
+/* APPLE LOCAL end 5831562 add DIMODE_REG_ALLOC_ORDER */
 	  if (! TEST_HARD_REG_BIT (used, regno)
 	      && HARD_REGNO_MODE_OK (regno, mode)
 	      && (allocno[num].calls_crossed == 0
@@ -1837,8 +1855,24 @@
 	});
 
       /* APPLE LOCAL begin 4321079 */
+      /* APPLE LOCAL begin 5831562 ARM pseudo-pseudo tying*/
       {
 	int k, l;
+	/* If this reg is not live over calls, remove any ties to pseudo-regs
+	   that are live over calls; they cannot use this reg. */
+	if (call_used_regs[best_reg])
+	  {
+	    EXECUTE_IF_SET_IN_ALLOCNO_SET (
+	      pseudo_preferences + num * allocno_row_words, k,
+	      {
+		if (allocno[k].calls_crossed != 0)
+		  {
+		    CLEAR_PSEUDO_PREF (num, k);
+		    CLEAR_PSEUDO_PREF (k, num);
+		  }
+	      });
+	  }
+
 	/* Mark tied pseudo-regs that have not yet been assigned a reg
 	   and do not already have a hard reg preference
 	   and do not conflict as preferring this reg.  Mark pseudo-regs
@@ -1848,9 +1882,19 @@
 	  pseudo_preferences + num * allocno_row_words, k,
 	  {
 	    if (!CONFLICTP (num, k) && reg_renumber[allocno[k].reg] < 0)
-	      SET_REGBIT (hard_reg_copy_preferences, k, best_reg);
+	      {
+	       /* go-if-equal is not exactly what we want, ugh */
+		GO_IF_HARD_REG_EQUAL (allocno[k].hard_reg_copy_preferences, 
+				      empty_reg_set, none_yet);
+		goto skip;
+		none_yet:;
+		  SET_REGBIT (hard_reg_copy_preferences, k, best_reg);
+		skip:;
+	      }
 
-	    if (num != k && !CONFLICTP (num, k))
+	    if (num != k && !CONFLICTP (num, k) && 
+		(reg_renumber[allocno[k].reg] < 0 ||
+		 reg_renumber[allocno[k].reg] == best_reg))
 	      EXECUTE_IF_SET_IN_ALLOCNO_SET (
 		conflicts + k * allocno_row_words, l,
 		{
@@ -1858,21 +1902,28 @@
 		    SET_REGBIT (regs_someone_prefers, l, best_reg);
 		});
 	  });
-	/* Mark pseudo-regs tied to conflicting regs and not yet assigned a
-	   reg as not preferring this reg.  */
+	/* Mark pseudo-regs tied to {conflicting allocnos which have either
+	   not yet been assigned a reg, or assigned best_reg}, but are not
+	   tied to this allocno, and not yet assigned a reg, as not preferring
+	   this reg, provided they are not already marked as preferring
+	   this reg.  Got that?  */
 	EXECUTE_IF_SET_IN_ALLOCNO_SET (
 	  conflicts + num * allocno_row_words, k,
 	  {
-	    if (num != k)
+	    if (num != k 
+		&& (reg_renumber[allocno[k].reg] < 0
+		    || reg_renumber[allocno[k].reg] == best_reg))
 	      EXECUTE_IF_SET_IN_ALLOCNO_SET (
 		pseudo_preferences + k * allocno_row_words, l, 
 		{
-		  if (k != l && !CONFLICTP (k, l) 
+		  if (k != l && !CONFLICTP (k, l) && !TEST_PSEUDO_PREF (l, num)
+		      && !TEST_HARD_REG_BIT(allocno[l].hard_reg_preferences, best_reg)
 		      && reg_renumber[allocno[l].reg] < 0)
 		    SET_REGBIT (regs_someone_prefers, l, best_reg);
 		});
 	  });
       }	    
+      /* APPLE LOCAL end 5831562 ARM pseudo-pseudo tying*/
       /* APPLE LOCAL end 4321079 */
     }
 }
@@ -2191,11 +2242,19 @@
   int copy = 1;
 
   /* APPLE LOCAL begin 4321079 */
-  /* Look under SUBREG for vectors; vector-to-vector SUBREGs are NOPs. */
+  /* APPLE LOCAL begin 5831562 ARM pseudo-pseudo tying*/
+  /* Look under SUBREG for vectors; vector-to-vector SUBREGs are NOPs.
+     This code formerly did less testing, which was OK on PPC and x86
+     as vector-to-nonvector SUBREGs did not occur; but they do on ARM. */
 
   if (GET_RTX_FORMAT (GET_CODE (src))[0] == 'e'
-      && ! (GET_CODE (src) == SUBREG && VECTOR_MODE_P (GET_MODE (dest))))
+      && ! (GET_CODE (src) == SUBREG 
+           && REG_P (SUBREG_REG (src))
+           && VECTOR_MODE_P (GET_MODE (src))
+           && VECTOR_MODE_P (GET_MODE (SUBREG_REG (src)))
+           && VECTOR_MODE_P (GET_MODE (dest))))
     src = XEXP (src, 0), copy = 0;
+  /* APPLE LOCAL end 5831562 ARM pseudo-pseudo tying*/
   /* APPLE LOCAL end 4321079 */
 
   /* Get the reg number for both SRC and DEST.
@@ -2305,11 +2364,13 @@
      marked as tied here; the data is only used for pseudos that do not
      conflict. */
 
+  /* APPLE LOCAL begin 5831562 ARM pseudo-pseudo tying*/
   if (src_regno >= FIRST_PSEUDO_REGISTER && reg_allocno[src_regno] >= 0
-      && VECTOR_MODE_P (GET_MODE (src_reg))
+      && (VECTOR_MODE_P (GET_MODE (src_reg)) || TIE_PSEUDOS)
       && dest_regno >= FIRST_PSEUDO_REGISTER && reg_allocno[dest_regno] >= 0
-      && VECTOR_MODE_P (GET_MODE (dest_reg))
+      && (VECTOR_MODE_P (GET_MODE (dest_reg)) || TIE_PSEUDOS)
       && copy)
+  /* APPLE LOCAL end 5831562 ARM pseudo-pseudo tying*/
     {
       src_regno += offset;
       SET_PSEUDO_PREF (reg_allocno[dest_regno], reg_allocno[src_regno]);

Modified: llvm-gcc-4.2/trunk/gcc/ifcvt.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/ifcvt.c?rev=54208&r1=54207&r2=54208&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/ifcvt.c (original)
+++ llvm-gcc-4.2/trunk/gcc/ifcvt.c Wed Jul 30 03:02:52 2008
@@ -284,6 +284,22 @@
 	  goto insn_done;
 	}
 
+      /* APPLE LOCAL begin ARM enhance conditional insn generation */
+#ifdef TARGET_ARM
+      /* If we've got a comparison in the block, we can continue to merge
+	 provided all following insns are COND_EXEC with a condition identical
+	 to TEST.  The existing instruction is just fine in this case, no
+	 modifications needed.  Misleading name of "must_be_last" retained to
+	 minimize changes.  */
+      /* This probably won't work on some other targets.  */
+
+      if (must_be_last
+	  && GET_CODE (PATTERN (insn)) == COND_EXEC
+	  && rtx_equal_p (COND_EXEC_TEST (PATTERN (insn)), test))
+	goto insn_done;
+#endif
+      /* APPLE LOCAL end ARM enhance conditional insn generation */
+
       /* Last insn wasn't last?  */
       if (must_be_last)
 	return FALSE;
@@ -295,6 +311,13 @@
 	  must_be_last = TRUE;
 	}
 
+      /* APPLE LOCAL begin 5831528 make calls predicable */
+      /* Calls with NORETURN notes cannot easily be conditionally executed,
+	 since all insns following such calls have been removed as dead. */
+      if (CALL_P (insn) && find_reg_note (insn, REG_NORETURN,  NULL_RTX))
+	return FALSE;
+      /* APPLE LOCAL end 5831528 make calls predicable */
+
       /* Now build the conditional form of the instruction.  */
       pattern = PATTERN (insn);
       xtest = copy_rtx (test);
@@ -366,9 +389,33 @@
   return cond;
 }
 
+/* APPLE LOCAL begin ARM enhance conditional insn generation */
+/* Test whether two conditional branches have the same destination.  We've
+   checked elsewhere that the conditions are compatible; if one is
+   reversed, so must the other be.  */
+static bool
+cond_exec_branch_targets_equiv (rtx insn1, rtx insn2)
+{
+  rtx cond1, cond2;
+  if (!any_condjump_p (insn1) || !any_condjump_p (insn2))
+    return false;
+  cond1 = SET_SRC (pc_set (insn1));
+  cond2 = SET_SRC (pc_set (insn2));
+  if (rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))
+      && rtx_equal_p (XEXP (cond1, 2), XEXP (cond2, 2)))
+    return true;
+  return false;
+}
+
 /* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
    to conditional execution.  Return TRUE if we were successful at
    converting the block.  */
+/* In addition to the above, we're locally handling the case where multiple
+   && or || blocks precede the THEN, but we cannot convert the THEN block
+   for some reason (e.g. it has multiple successors, or THEN and ELSE do
+   not join.)  We can still convert and merge the && or || blocks.
+   This case is indicated by ce_info->then_bb==NULL.  Heavy modifications 
+   in this routine.  */
 
 static int
 cond_exec_process_if_block (ce_if_block_t * ce_info,
@@ -378,8 +425,8 @@
   basic_block then_bb = ce_info->then_bb;	/* THEN */
   basic_block else_bb = ce_info->else_bb;	/* ELSE or NULL */
   rtx test_expr;		/* expression in IF_THEN_ELSE that is tested */
-  rtx then_start;		/* first insn in THEN block */
-  rtx then_end;			/* last insn + 1 in THEN block */
+  rtx then_start = NULL_RTX;	/* first insn in THEN block */
+  rtx then_end = NULL_RTX;	/* last insn + 1 in THEN block */
   rtx else_start = NULL_RTX;	/* first insn in ELSE block or NULL */
   rtx else_end = NULL_RTX;	/* last insn + 1 in ELSE block */
   int max;			/* max # of insns to convert.  */
@@ -388,7 +435,7 @@
   rtx false_expr;		/* test for then block insns */
   rtx true_prob_val;		/* probability of else block */
   rtx false_prob_val;		/* probability of then block */
-  int n_insns;
+  int n_insns = 0;
   enum rtx_code false_code;
 
   /* If test is comprised of && or || elements, and we've failed at handling
@@ -419,21 +466,24 @@
   /* Collect the bounds of where we're to search, skipping any labels, jumps
      and notes at the beginning and end of the block.  Then count the total
      number of insns and see if it is small enough to convert.  */
-  then_start = first_active_insn (then_bb);
-  then_end = last_active_insn (then_bb, TRUE);
-  n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
-  max = MAX_CONDITIONAL_EXECUTE;
-
-  if (else_bb)
+  if (then_bb)
     {
-      max *= 2;
-      else_start = first_active_insn (else_bb);
-      else_end = last_active_insn (else_bb, TRUE);
-      n_insns += ce_info->num_else_insns = count_bb_insns (else_bb);
-    }
+      then_start = first_active_insn (then_bb);
+      then_end = last_active_insn (then_bb, TRUE);
+      n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
+      max = MAX_CONDITIONAL_EXECUTE;
 
-  if (n_insns > max)
-    return FALSE;
+      if (else_bb)
+	{
+	  max *= 2;
+	  else_start = first_active_insn (else_bb);
+	  else_end = last_active_insn (else_bb, TRUE);
+	  n_insns += ce_info->num_else_insns = count_bb_insns (else_bb);
+	}
+
+      if (n_insns > max)
+	return FALSE;
+    }
 
   /* Map test_expr/test_jump into the appropriate MD tests to use on
      the conditionally executed code.  */
@@ -472,6 +522,7 @@
     {
       basic_block bb = test_bb;
       basic_block last_test_bb = ce_info->last_test_bb;
+      int mod_ok = 0;
 
       if (! false_expr)
 	goto fail;
@@ -485,9 +536,19 @@
 	  bb = block_fallthru (bb);
 	  start = first_active_insn (bb);
 	  end = last_active_insn (bb, TRUE);
+
+	  /* If the condition at the next block is same as this one, and they
+	     share a target, we can conditionally redefine CC within the block.
+	     This should work on targets with a single CC register and conditional
+	     compares. */
+	  t = cond_exec_get_condition (BB_END (bb));
+	  if (t && rtx_equal_p (t, true_expr)
+		&& cond_exec_branch_targets_equiv (BB_END (bb), BB_END (test_bb)))
+	    mod_ok = 1;
+
 	  if (start
 	      && ! cond_exec_process_insns (ce_info, start, end, false_expr,
-					    false_prob_val, FALSE))
+					    false_prob_val, mod_ok))
 	    goto fail;
 
 	  /* If the conditional jump is more than just a conditional jump, then
@@ -505,15 +566,44 @@
 	    goto fail;
 
 	  f = gen_rtx_fmt_ee (f_code, GET_MODE (t), XEXP (t, 0), XEXP (t, 1));
+	  /* The conditions in the following code are corrected from
+	     mainline.  The true_expr is the condition that means the
+	     'then' block is executed, i.e. the branch is taken.  Voila
+	     some simple diagrams for && and || blocks -- in these all
+	     control flows downward (and outward) and when control
+	     splits, the right angle/horizontal line is the 'then'
+	     clause (i.e., true) and the vertical line is the 'else'
+	     clause (i.e., false).
+
+	     and_and:                          or_or:
+	            +-----+                             +-----+
+	            | BB1 |                             | BB1 |
+	            +-----+                             +-----+
+	               |                                   |
+	               +---------+                  +------+
+	     false_expr|         |                  |      |false_expr
+	            +-----+      |                  |   +-----+
+	            | BB2 |      |                  |   | BB2 |
+	            +-----+      |                  |   +-----+
+	               |         |                  |      |    
+	               +-------+ |                  +---+  +-------+
+	               |f     t| |true_expr    true_expr|  |f      |t
+	            +-----+   +-----+                  +-----+  +-----+
+	            | BB3 |   | BB4 |                  | BB3 |  | BB4 |
+	            +-----+   +-----+                  +-----+  +-----+
+
+	     We're calculating 'f', which is the condition necessary to
+	     reach BB3 in the above diagrams, and 't' which is the
+	     condition necessary to reach BB4.  */
 	  if (ce_info->and_and_p)
 	    {
-	      t = gen_rtx_AND (GET_MODE (t), true_expr, t);
-	      f = gen_rtx_IOR (GET_MODE (t), false_expr, f);
+	      t = gen_rtx_IOR (GET_MODE (t), true_expr, t);
+	      f = gen_rtx_AND (GET_MODE (t), false_expr, f);
 	    }
 	  else
 	    {
-	      t = gen_rtx_IOR (GET_MODE (t), true_expr, t);
-	      f = gen_rtx_AND (GET_MODE (t), false_expr, f);
+	      f = gen_rtx_IOR (GET_MODE (t), true_expr, f);
+	      t = gen_rtx_AND (GET_MODE (t), false_expr, t);
 	    }
 
 	  /* If the machine description needs to modify the tests, such as
@@ -531,6 +621,13 @@
 	  false_expr = f;
 	}
       while (bb != last_test_bb);
+      /* If tests from several blocks were merged, change the last branch to use the
+	 merged tests, which may of course be invalid.  We need do this only in the
+	 &&-only case, as the branch will be removed if we have a then block. */
+      if (!then_bb && !rtx_equal_p (true_expr, test_expr))
+	if (any_condjump_p (BB_END (bb)))
+	    validate_change (BB_END (bb), &XEXP (SET_SRC (pc_set (BB_END (bb))), 0), 
+			 true_expr, 1);
     }
 
   /* For IF-THEN-ELSE blocks, we don't allow modifications of the test
@@ -540,7 +637,7 @@
   /* Go through the THEN and ELSE blocks converting the insns if possible
      to conditional execution.  */
 
-  if (then_end
+  if (then_bb && then_end
       && (! false_expr
 	  || ! cond_exec_process_insns (ce_info, then_start, then_end,
 					false_expr, false_prob_val,
@@ -587,6 +684,7 @@
   cancel_changes (0);
   return FALSE;
 }
+/* APPLE LOCAL end ARM enhance conditional insn generation */
 
 /* Used by noce_process_if_block to communicate with its subroutines.
 
@@ -2661,7 +2759,10 @@
       if (cond_exec_process_if_block (ce_info, TRUE))
 	return TRUE;
 
-      if (ce_info->num_multiple_test_blocks)
+      /* APPLE LOCAL begin ARM enhance conditional insn generation */
+      /* The &&-only case can't do anything useful here, so don't try. */
+      if (ce_info->num_multiple_test_blocks && ce_info->then_bb)
+      /* APPLE LOCAL end ARM enhance conditional insn generation */
 	{
 	  cancel_changes (0);
 
@@ -3009,22 +3110,23 @@
 	}
     }
 
+  /* APPLE LOCAL begin ARM enhance conditional insn generation */
   /* The THEN block of an IF-THEN combo must have exactly one predecessor,
      other than any || blocks which jump to the THEN block.  */
   if ((EDGE_COUNT (then_bb->preds) - ce_info->num_or_or_blocks) != 1)
-    return FALSE;
+    goto combine_and_and_only;
     
   /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
   FOR_EACH_EDGE (cur_edge, ei, then_bb->preds)
     {
       if (cur_edge->flags & EDGE_COMPLEX)
-	return FALSE;
+	goto combine_and_and_only;
     }
 
   FOR_EACH_EDGE (cur_edge, ei, else_bb->preds)
     {
       if (cur_edge->flags & EDGE_COMPLEX)
-	return FALSE;
+	goto combine_and_and_only;
     }
 
   /* The THEN block of an IF-THEN combo must have zero or one successors.  */
@@ -3032,7 +3134,7 @@
       && (!single_succ_p (then_bb)
           || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
 	  || (flow2_completed && tablejump_p (BB_END (then_bb), NULL, NULL))))
-    return FALSE;
+    goto combine_and_and_only;
 
   /* If the THEN block has no successors, conditional execution can still
      make a conditional call.  Don't do this unless the ELSE block has
@@ -3054,13 +3156,13 @@
 	  if (last_insn
 	      && JUMP_P (last_insn)
 	      && ! simplejump_p (last_insn))
-	    return FALSE;
+	    goto combine_and_and_only;
 
 	  join_bb = else_bb;
 	  else_bb = NULL_BLOCK;
 	}
       else
-	return FALSE;
+	goto combine_and_and_only;
     }
 
   /* If the THEN block's successor is the other edge out of the TEST block,
@@ -3081,30 +3183,51 @@
 	   && ! (flow2_completed && tablejump_p (BB_END (else_bb), NULL, NULL)))
     join_bb = single_succ (else_bb);
 
-  /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
+  /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
+  else
+    goto combine_and_and_only;
+ 
+  /* Fallthrough means one of the recognized cases above matched. */
+  goto if_block_found;
+
+  /* This is not a recognizable if-then-else for some reason.  If we have multiple 
+     && blocks, we can still try to combine them.  This case is indicated by marking
+     everything else null.  */
+combine_and_and_only:;
+  if (ce_info->num_and_and_blocks || ce_info->num_or_or_blocks)
+    {
+      join_bb = else_bb = NULL_BLOCK;
+      then_bb = ce_info->then_bb = NULL_BLOCK;
+    }
   else
     return FALSE;
 
+if_block_found:;
   num_possible_if_blocks++;
 
   if (dump_file)
     {
       fprintf (dump_file,
-	       "\nIF-THEN%s block found, pass %d, start block %d "
-	       "[insn %d], then %d [%d]",
+	       "\nIF%s%s block found, pass %d, start block %d "
+	       "[insn %d]",
+	       (then_bb) ? "-THEN" : "",
 	       (else_bb) ? "-ELSE" : "",
 	       ce_info->pass,
 	       test_bb->index,
-	       BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
-	       then_bb->index,
-	       BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
+	       BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1);
+
+      if (then_bb)
+	fprintf (dump_file, ", then %d [%d]",
+		 then_bb->index,
+		 BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
 
       if (else_bb)
 	fprintf (dump_file, ", else %d [%d]",
 		 else_bb->index,
 		 BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
 
-      fprintf (dump_file, ", join %d [%d]",
+      if (join_bb)
+	fprintf (dump_file, ", join %d [%d]",
 	       join_bb->index,
 	       BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
 
@@ -3125,20 +3248,25 @@
      first condition for free, since we've already asserted that there's a
      fallthru edge from IF to THEN.  Likewise for the && and || blocks, since
      we checked the FALLTHRU flag, those are already adjacent to the last IF
-     block.  */
+     block.  (When then_bb is null, we are only looking at the && blocks, which
+     were already verified.)  */
   /* ??? As an enhancement, move the ELSE block.  Have to deal with
      BLOCK notes, if by no other means than backing out the merge if they
      exist.  Sticky enough I don't want to think about it now.  */
-  next = then_bb;
-  if (else_bb && (next = next->next_bb) != else_bb)
-    return FALSE;
-  if ((next = next->next_bb) != join_bb && join_bb != EXIT_BLOCK_PTR)
+  if (then_bb)
     {
-      if (else_bb)
-	join_bb = NULL;
-      else
+      next = then_bb;
+      if (else_bb && (next = next->next_bb) != else_bb)
 	return FALSE;
+      if ((next = next->next_bb) != join_bb && join_bb != EXIT_BLOCK_PTR)
+	{
+	  if (else_bb)
+	    join_bb = NULL;
+	  else
+	    return FALSE;
+	}
     }
+  /* APPLE LOCAL end ARM enhance conditional insn generation */
 
   /* Do the real work.  */
   ce_info->else_bb = else_bb;

Modified: llvm-gcc-4.2/trunk/gcc/recog.c
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/recog.c?rev=54208&r1=54207&r2=54208&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/recog.c (original)
+++ llvm-gcc-4.2/trunk/gcc/recog.c Wed Jul 30 03:02:52 2008
@@ -3005,7 +3005,12 @@
 #else
       regno = raw_regno;
 #endif
-
+/* APPLE LOCAL begin 5831562 add DIMODE_REG_ALLOC_ORDER */
+#ifdef DIMODE_REG_ALLOC_ORDER
+      if (mode == DImode)
+	regno = dimode_reg_alloc_order[raw_regno];
+#endif
+/* APPLE LOCAL end 5831562 add DIMODE_REG_ALLOC_ORDER */
       /* Don't allocate fixed registers.  */
       if (fixed_regs[regno])
 	continue;





More information about the llvm-commits mailing list