From fa9dada1439c818c5e633c1a4ded772c46514fa4 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Thu, 2 Oct 2008 11:18:31 +0000 Subject: [PATCH] BugFix of r22380 (fixes 176.gcc): - 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 | 20 +++++++++-- ir/ir/irmode.c | 73 ++++++++++++++++++++++++++++++++++++++++ ir/ir/iropt.c | 2 +- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/include/libfirm/irmode.h b/include/libfirm/irmode.h index d1b4e88c6..7f55e3ce7 100644 --- a/include/libfirm/irmode.h +++ b/include/libfirm/irmode.h @@ -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. diff --git a/ir/ir/irmode.c b/ir/ir/irmode.c index 71da96f3b..75b02bcb7 100644 --- a/ir/ir/irmode.c +++ b/ir/ir/irmode.c @@ -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); diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index b7c6726d4..b77b15d3f 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -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); } -- 2.20.1