Index: gcc/ira.h
===================================================================
--- gcc/ira.h	2012-09-30 12:56:14.344185269 +0100
+++ gcc/ira.h	2012-09-30 17:45:14.964463976 +0100
@@ -79,6 +79,10 @@ struct target_ira {
      class.  */
   int x_ira_class_hard_regs_num[N_REG_CLASSES];
 
+  /* If class CL has a single allocatable register of mode M,
+     index [CL][M] gives the number of that register, otherwise it is -1.  */
+  short x_ira_class_singleton[N_REG_CLASSES][MAX_MACHINE_MODE];
+
   /* Function specific hard registers can not be used for the register
      allocation.  */
   HARD_REG_SET x_ira_no_alloc_regs;
@@ -117,6 +121,8 @@ #define ira_class_hard_regs \
   (this_target_ira->x_ira_class_hard_regs)
 #define ira_class_hard_regs_num \
   (this_target_ira->x_ira_class_hard_regs_num)
+#define ira_class_singleton \
+  (this_target_ira->x_ira_class_singleton)
 #define ira_no_alloc_regs \
   (this_target_ira->x_ira_no_alloc_regs)
 
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2012-09-30 12:56:14.344185269 +0100
+++ gcc/ira.c	2012-09-30 19:20:32.555409864 +0100
@@ -1451,16 +1451,21 @@ setup_reg_class_nregs (void)
 
 
 
-/* Set up IRA_PROHIBITED_CLASS_MODE_REGS.  */
+/* Set up IRA_PROHIBITED_CLASS_MODE_REGS and IRA_CLASS_SINGLETON.
+   This function is called once IRA_CLASS_HARD_REGS has been initialized.  */
 static void
 setup_prohibited_class_mode_regs (void)
 {
-  int j, k, hard_regno, cl;
+  int j, k, hard_regno, cl, last_hard_regno, count;
 
   for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
     {
+      COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+      AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
       for (j = 0; j < NUM_MACHINE_MODES; j++)
 	{
+	  count = 0;
+	  last_hard_regno = -1;
 	  CLEAR_HARD_REG_SET (ira_prohibited_class_mode_regs[cl][j]);
 	  for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--)
 	    {
@@ -1468,7 +1473,14 @@ setup_prohibited_class_mode_regs (void)
 	      if (! HARD_REGNO_MODE_OK (hard_regno, (enum machine_mode) j))
 		SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
 				  hard_regno);
+	      else if (in_hard_reg_set_p (temp_hard_regset,
+					  (enum machine_mode) j, hard_regno))
+		{
+		  last_hard_regno = hard_regno;
+		  count++;
+		}
 	    }
+	  ira_class_singleton[cl][j] = (count == 1 ? last_hard_regno : -1);
 	}
     }
 }
Index: gcc/ira-build.c
===================================================================
--- gcc/ira-build.c	2012-09-30 12:56:14.344185269 +0100
+++ gcc/ira-build.c	2012-09-30 17:45:14.965463976 +0100
@@ -3047,11 +3047,10 @@ update_conflict_hard_reg_costs (void)
     {
       reg_class_t aclass = ALLOCNO_CLASS (a);
       reg_class_t pref = reg_preferred_class (ALLOCNO_REGNO (a));
-
-      if (reg_class_size[(int) pref] != 1)
+      int singleton = ira_class_singleton[pref][ALLOCNO_MODE (a)];
+      if (singleton < 0)
 	continue;
-      index = ira_class_hard_reg_index[(int) aclass]
-				      [ira_class_hard_regs[(int) pref][0]];
+      index = ira_class_hard_reg_index[(int) aclass][singleton];
       if (index < 0)
 	continue;
       if (ALLOCNO_CONFLICT_HARD_REG_COSTS (a) == NULL
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	2012-09-30 12:56:14.344185269 +0100
+++ gcc/ira-lives.c	2012-09-30 17:45:14.962463976 +0100
@@ -849,9 +849,10 @@ single_reg_class (const char *constraint
 	  next_cl = (c == 'r'
 		     ? GENERAL_REGS
 		     : REG_CLASS_FROM_CONSTRAINT (c, constraints));
-	  if ((cl != NO_REGS && next_cl != cl)
-	      || (ira_class_hard_regs_num[next_cl]
-		  > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
+	  if (cl == NO_REGS
+	      ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+	      : (ira_class_singleton[cl][GET_MODE (op)]
+		 != ira_class_singleton[next_cl][GET_MODE (op)]))
 	    return NO_REGS;
 	  cl = next_cl;
 	  break;
@@ -861,10 +862,10 @@ single_reg_class (const char *constraint
 	  next_cl
 	    = single_reg_class (recog_data.constraints[c - '0'],
 				recog_data.operand[c - '0'], NULL_RTX);
-	  if ((cl != NO_REGS && next_cl != cl)
-	      || next_cl == NO_REGS
-	      || (ira_class_hard_regs_num[next_cl]
-		  > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
+	  if (cl == NO_REGS
+	      ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+	      : (ira_class_singleton[cl][GET_MODE (op)]
+		 != ira_class_singleton[next_cl][GET_MODE (op)]))
 	    return NO_REGS;
 	  cl = next_cl;
 	  break;
@@ -939,13 +940,14 @@ ira_implicitly_set_insn_hard_regs (HARD_
 		  cl = (c == 'r'
 			? GENERAL_REGS
 			: REG_CLASS_FROM_CONSTRAINT (c, p));
-		  if (cl != NO_REGS
+		  if (cl != NO_REGS)
+		    {
 		      /* There is no register pressure problem if all of the
 			 regs in this class are fixed.  */
-		      && ira_class_hard_regs_num[cl] != 0
-		      && (ira_class_hard_regs_num[cl]
-			  <= ira_reg_class_max_nregs[cl][mode]))
-		    IOR_HARD_REG_SET (*set, reg_class_contents[cl]);
+		      int regno = ira_class_singleton[cl][mode];
+		      if (regno >= 0)
+			add_to_hard_reg_set (set, mode, regno);
+		    }
 		  break;
 		}
 	}
@@ -989,8 +991,7 @@ process_single_reg_class_operands (bool
 
 	  operand_a = ira_curr_regno_allocno_map[regno];
 	  aclass = ALLOCNO_CLASS (operand_a);
-	  if (ira_class_subset_p[cl][aclass]
-	      && ira_class_hard_regs_num[cl] != 0)
+	  if (ira_class_subset_p[cl][aclass])
 	    {
 	      /* View the desired allocation of OPERAND as:
 
@@ -1004,7 +1005,8 @@ process_single_reg_class_operands (bool
 	      HOST_WIDE_INT offset;
 
 	      xmode = recog_data.operand_mode[i];
-	      xregno = ira_class_hard_regs[cl][0];
+	      xregno = ira_class_singleton[cl][xmode];
+	      gcc_assert (xregno >= 0);
 	      ymode = ALLOCNO_MODE (operand_a);
 	      offset = subreg_lowpart_offset (ymode, xmode);
 	      yregno = simplify_subreg_regno (xregno, xmode, offset, ymode);
