[Bug c/31734] New: optimizer looses ops for with aliasing
ajrobb at bigfoot dot com
gcc-bugzilla@gcc.gnu.org
Sat Apr 28 15:36:00 GMT 2007
The following routine generates takes a value (promoted from float or double to
long double) and generates a two-part mantissa (integer and fraction parts).
With optimisation above -O, the last multiply and addition are not performed. I
can fix this by abusing a union (change #if 0 to #if 1).
typedef struct Double {
int exponent;
unsigned mantissa; /**< 100,000,000..999,999,999 */
unsigned fraction; /**< 0.1 <= fraction < 1 */
} Double;
void scale(Double * out, long double value) {
typedef struct {
long double a;
long double b;
int scale;
} Scale;
static const Scale e3[] =
{ { 1e100L, 1e-100L, 100 }
, { 1e200L, 1e-200L, 200 }
, { 1e300L, 1e-300L, 300 }
};
static const Scale e2[] =
{ { 1e10L, 1e-10L, 10 }
, { 1e20L, 1e-20L, 20 }
, { 1e30L, 1e-30L, 30 }
, { 1e40L, 1e-40L, 40 }
, { 1e50L, 1e-50L, 50 }
, { 1e60L, 1e-60L, 60 }
, { 1e70L, 1e-70L, 70 }
, { 1e80L, 1e-80L, 80 }
, { 1e90L, 1e-90L, 90 }
};
static const Scale e1[] =
{ { 1e1L, 1e-1L, 1 }
, { 1e2L, 1e-2L, 2 }
, { 1e3L, 1e-3L, 3 }
, { 1e4L, 1e-4L, 4 }
, { 1e5L, 1e-5L, 5 }
, { 1e6L, 1e-6L, 6 }
, { 1e7L, 1e-7L, 7 }
, { 1e8L, 1e-8L, 8 }
, { 1e9L, 1e-9L, 9 }
};
typedef struct {
const Scale * scale;
const int n;
} Scales;
static const Scales scales[] = { { e3, 3 }, { e2, 10 }, { e1, 9 } };
union {
unsigned array[3];
long double value;
} result = {0,0,0};
int scale = 0;
int i;
if (value < 0) value = -value;
/* scale 0.1 <= value < 1 */
if (value != 0) for (i = 0; i < 3; ++i) {
if (value >= scales[i].scale[0].a) {
int j = scales[i].n;
while (--j >= 0) {
if (value >= scales[i].scale[j].a) {
value *= scales[i].scale[j].b;
scale += scales[i].scale[j].scale;
break;
}
}
}
else if (value < scales[i].scale[0].b) {
int j = scales[i].n;
while (--j >= 0) {
if (value < scales[i].scale[j].b) {
value *= scales[i].scale[j].a;
scale -= scales[i].scale[j].scale;
break;
}
}
}
}
if (value >= 1) {
value *= 1e-1L;
scale += 1;
}
else if (value < 0.1) {
value *= 10;
scale -= 1;
}
/* float values for 1e9 and 1u<<31 are exact */
printf("%.19f\t", (double)value);
value *= 1e9; /* 1e9 <= value < 1e10 */
/* fix the position of the decimal point to between words
* (it also does a good job of rounding)
*/
value += 2147483648.0f;
#if 0
/* abuse union to cast (long double) to int[] - but it works */
result.value = value;
out->fraction = result.array[0];
out->mantissa = result.array[1] & 0x7fffffff;
#else
/* this is odd, using ((int*)&value)[0] fools the optimizer
* and it omits the previous 2 ops on value!
*/
out->fraction = ((int*)&value)[0];
out->mantissa = ((int*)&value)[1] & 0x7fffffff;
#endif
out->exponent = scale;
}
It appears that because 'value' is not used directly after the last multiply
and add, these operations are dropped by the optimizer. Fails on cygwin, SuSE 8
and SuSE 10.2
gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)
gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
gcc version 3.3.3 (SuSE Linux)
--
Summary: optimizer looses ops for with aliasing
Product: gcc
Version: 4.1.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: ajrobb at bigfoot dot com
GCC build triplet: i586-suse-linux
GCC host triplet: i586-suse-linux
GCC target triplet: i586-suse-linux
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31734
More information about the Gcc-bugs
mailing list