Fix PR target/53334
authorramana <ramana@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 May 2012 09:06:55 +0000 (09:06 +0000)
committerramana <ramana@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 May 2012 09:06:55 +0000 (09:06 +0000)
2012-05-22  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>

PR target/53334
* config/arm/arm-protos.h (arm_validize_comparison): Declare.
* config/arm/arm.c (arm_validize_comparison): Define.
* config/arm/arm.md ("cbranchsi4"): Cleanup expansion and use
arm_validize_comparison.
("cbranchdi4"): Likewise.
("cstoredi4"): Likewise.
("movsicc"): Likewise.
("movsfcc"): Likewise.
("movdfcc"): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187761 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.md

index 3ff410a..496bb5f 100644 (file)
@@ -1,7 +1,20 @@
+2012-05-22  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
+
+       PR target/53334
+       * config/arm/arm-protos.h (arm_validize_comparison): Declare.
+       * config/arm/arm.c (arm_validize_comparison): Define.
+       * config/arm/arm.md ("cbranchsi4"): Cleanup expansion and use
+       arm_validize_comparison.
+       ("cbranchdi4"): Likewise.
+       ("cstoredi4"): Likewise.
+       ("movsicc"): Likewise.
+       ("movsfcc"): Likewise.
+       ("movdfcc"): Likewise.
+
 2012-05-22  Dimitrios Apostolou  <jimis@gmx.net>
 
        * df-scan.c (df_scan_alloc): Round up allocation pools size, reduce
-       the mw_reg_pool size. 
+       the mw_reg_pool size.
 
 2012-05-22  Paolo Bonzini  <bonzini@gnu.org>
 
index b338470..4e6d7bb 100644 (file)
@@ -248,6 +248,7 @@ extern int vfp3_const_double_for_fract_bits (rtx);
 
 extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx,
                                           rtx);
+extern bool arm_validize_comparison (rtx *, rtx *, rtx *);
 #endif /* RTX_CODE */
 
 extern void arm_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
index 3ad4c75..7a98197 100644 (file)
@@ -26185,4 +26185,54 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in,
   #undef BRANCH
 }
 
+
+/* Returns true if a valid comparison operation and makes 
+   the operands in a form that is valid.  */
+bool
+arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2)
+{
+  enum rtx_code code = GET_CODE (*comparison);
+  enum rtx_code canonical_code;
+  enum machine_mode mode = (GET_MODE (*op1) == VOIDmode) 
+    ? GET_MODE (*op2) : GET_MODE (*op1);
+
+  gcc_assert (GET_MODE (*op1) != VOIDmode || GET_MODE (*op2) != VOIDmode);
+
+  if (code == UNEQ || code == LTGT)
+    return false;
+
+  canonical_code = arm_canonicalize_comparison (code, op1, op2);
+  PUT_CODE (*comparison, canonical_code);
+
+  switch (mode)
+    {
+    case SImode:
+      if (!arm_add_operand (*op1, mode))
+       *op1 = force_reg (mode, *op1);
+      if (!arm_add_operand (*op2, mode))
+       *op2 = force_reg (mode, *op2);
+      return true;
+
+    case DImode:
+      if (!cmpdi_operand (*op1, mode))
+       *op1 = force_reg (mode, *op1);
+      if (!cmpdi_operand (*op2, mode))
+       *op2 = force_reg (mode, *op2);
+      return true;
+      
+    case SFmode:
+    case DFmode:
+      if (!arm_float_compare_operand (*op1, mode))
+       *op1 = force_reg (mode, *op1);
+      if (!arm_float_compare_operand (*op2, mode))
+       *op2 = force_reg (mode, *op2);
+      return true;
+    default:
+      break;
+    }
+  
+  return false;
+
+}
+
 #include "gt-arm.h"
index bc97a4a..bbf6380 100644 (file)
                (match_operand:SI 2 "nonmemory_operand" "")])
              (label_ref (match_operand 3 "" ""))
              (pc)))]
-  "TARGET_THUMB1 || TARGET_32BIT"
+  "TARGET_EITHER"
   "
   if (!TARGET_THUMB1)
     {
-      if (!arm_add_operand (operands[2], SImode))
-       operands[2] = force_reg (SImode, operands[2]);
+      if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
+        FAIL;
       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
                                      operands[3]));
       DONE;
              (pc)))]
   "TARGET_32BIT"
   "{
-     rtx swap = NULL_RTX;
-     enum rtx_code code = GET_CODE (operands[0]);
-
      /* We should not have two constants.  */
      gcc_assert (GET_MODE (operands[1]) == DImode
                 || GET_MODE (operands[2]) == DImode);
 
-    /* Flip unimplemented DImode comparisons to a form that
-       arm_gen_compare_reg can handle.  */
-     switch (code)
-     {
-     case GT:
-       swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
-     case LE:
-       swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
-     case GTU:
-       swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
-     case LEU:
-       swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
-     default:
-       break;
-     }
-     if (swap)
-       emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
-                                       operands[3]));
-     else
-       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
+     if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))           
+       FAIL;
+     emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
                                       operands[3]));
      DONE;
    }"
          (match_operand:DI 3 "cmpdi_operand" "")]))]
   "TARGET_32BIT"
   "{
-     rtx swap = NULL_RTX;
-     enum rtx_code code = GET_CODE (operands[1]);
-
      /* We should not have two constants.  */
      gcc_assert (GET_MODE (operands[2]) == DImode
                 || GET_MODE (operands[3]) == DImode);
 
-    /* Flip unimplemented DImode comparisons to a form that
-       arm_gen_compare_reg can handle.  */
-     switch (code)
-     {
-     case GT:
-       swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
-     case LE:
-       swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
-     case GTU:
-       swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
-     case LEU:
-       swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
-     default:
-       break;
-     }
-     if (swap)
-       emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
-                                operands[2]));
-     else
-       emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
+     if (!arm_validize_comparison (&operands[1],
+                                  &operands[2],
+                                  &operands[3]))
+       FAIL;
+     emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
                                 operands[3]));
      DONE;
    }"
   "TARGET_32BIT"
   "
   {
-    enum rtx_code code = GET_CODE (operands[1]);
+    enum rtx_code code;
     rtx ccreg;
 
-    if (code == UNEQ || code == LTGT)
+    if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0), 
+                                         &XEXP (operands[1], 1)))
       FAIL;
-
+    
+    code = GET_CODE (operands[1]);
     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
                                 XEXP (operands[1], 1), NULL_RTX);
     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
   [(set (match_operand:SF 0 "s_register_operand" "")
        (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
                         (match_operand:SF 2 "s_register_operand" "")
-                        (match_operand:SF 3 "nonmemory_operand" "")))]
+                        (match_operand:SF 3 "arm_float_add_operand" "")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT"
   "
   {
     enum rtx_code code = GET_CODE (operands[1]);
     rtx ccreg;
 
-    if (code == UNEQ || code == LTGT)
-      FAIL;
-
-    /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
-       Otherwise, ensure it is a valid FP add operand */
-    if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
-        || (!arm_float_add_operand (operands[3], SFmode)))
-      operands[3] = force_reg (SFmode, operands[3]);
+    if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0), 
+                                         &XEXP (operands[1], 1)))
+       FAIL;
 
+    code = GET_CODE (operands[1]);
     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
                                 XEXP (operands[1], 1), NULL_RTX);
     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
     enum rtx_code code = GET_CODE (operands[1]);
     rtx ccreg;
 
-    if (code == UNEQ || code == LTGT)
-      FAIL;
-
+    if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0), 
+                                         &XEXP (operands[1], 1)))
+       FAIL;
+    code = GET_CODE (operands[1]);
     ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
                                 XEXP (operands[1], 1), NULL_RTX);
     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);