BugFix of r22380 (fixes 176.gcc):
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 2 Oct 2008 11:18:31 +0000 (11:18 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 2 Oct 2008 11:18:31 +0000 (11:18 +0000)
 - smaller_mode() had the meaning "can be represented", restored
 - renamed new implemnetation into values_in_mode() with the meaning
   "can be converted into in back" which is different from smaller_mode()

[r22408]

include/libfirm/irmode.h
ir/ir/irmode.c
ir/ir/iropt.c

index d1b4e88..7f55e3c 100644 (file)
@@ -407,10 +407,26 @@ int mode_is_float_vector (const ir_mode *mode);
 int mode_is_int_vector (const ir_mode *mode);
 /*@}*/
 
-/** Returns true if sm can be converted to lm without loss
-   according to firm definition */
+/**
+ * Returns true if sm can be converted to lm without loss
+ * according to firm definition.
+ *
+ * Note that mode_Iu is NOT smaller than mode_Is here.
+ *
+ * @see values_in_mode()
+ */
 int smaller_mode(const ir_mode *sm, const ir_mode *lm);
 
+/**
+ * Returns true if a value of mode sm can be converted into mode lm
+ * and backwards without loss.
+ *
+ * Note that mode_Iu values CAN be converted in mode_Is and back.
+ *
+ * @see smaller_mode()
+ */
+int values_in_mode(const ir_mode *sm, const ir_mode *lm);
+
 /**
  * Returns a matching unsigned mode for a given integer signed mode.
  * Returns NULL if no matching mode exists.
index 71da96f..75b02bc 100644 (file)
@@ -523,6 +523,79 @@ int (mode_is_int_vector)(const ir_mode *mode) {
 /* Returns true if sm can be converted to lm without loss. */
 int smaller_mode(const ir_mode *sm, const ir_mode *lm) {
        int sm_bits, lm_bits;
+
+       assert(sm);
+       assert(lm);
+
+       if (sm == lm) return 1;
+
+       sm_bits = get_mode_size_bits(sm);
+       lm_bits = get_mode_size_bits(lm);
+
+       switch (get_mode_sort(sm)) {
+       case irms_int_number:
+               switch (get_mode_sort(lm)) {
+               case irms_int_number:
+                       if (get_mode_arithmetic(sm) != get_mode_arithmetic(lm))
+                               return 0;
+
+                       /* only two complement implemented */
+                       assert(get_mode_arithmetic(sm) == irma_twos_complement);
+
+                       /* integers are convertable if
+                        *   - both have the same sign and lm is the larger one
+                        *   - lm is the signed one and is at least two bits larger
+                        *     (one for the sign, one for the highest bit of sm)
+                        *   - sm & lm are two_complement and lm has greater or equal number of bits
+                        */
+                       if (mode_is_signed(sm)) {
+                               if (!mode_is_signed(lm))
+                                       return 0;
+                               return sm_bits <= lm_bits;
+                       } else {
+                               if (mode_is_signed(lm)) {
+                                       return sm_bits < lm_bits;
+                               }
+                               return sm_bits <= lm_bits;
+                       }
+                       break;
+
+               case irms_float_number:
+                       /* int to float works if the float is large enough */
+                       return 0;
+
+               default:
+                       break;
+               }
+               break;
+
+       case irms_float_number:
+               if (get_mode_arithmetic(sm) == get_mode_arithmetic(lm)) {
+                       if ( (get_mode_sort(lm) == irms_float_number)
+                               && (get_mode_size_bits(lm) >= get_mode_size_bits(sm)) )
+                               return 1;
+               }
+               break;
+
+       case irms_reference:
+               /* do exist machines out there with different pointer lenghts ?*/
+               return 0;
+
+       case irms_internal_boolean:
+               return mode_is_int(lm);
+
+       default:
+               break;
+       }
+
+       /* else */
+       return 0;
+}
+
+/* Returns true if a value of mode sm can be converted into mode lm
+   and backwards without loss. */
+int values_in_mode(const ir_mode *sm, const ir_mode *lm) {
+       int sm_bits, lm_bits;
        ir_mode_arithmetic arith;
 
        assert(sm);
index b7c6726..b77b15d 100644 (file)
@@ -1254,7 +1254,7 @@ restart:
                                        n = b; /* Convb(Conv*(xxxb(...))) == xxxb(...) */
                                        DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV);
                                } else if (get_mode_arithmetic(n_mode) == get_mode_arithmetic(a_mode)) {
-                                       if (smaller_mode(b_mode, a_mode)) {
+                                       if (values_in_mode(b_mode, a_mode)) {
                                                n = b;        /* ConvS(ConvL(xxxS(...))) == xxxS(...) */
                                                DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_CONV);
                                        }