On 28/06/11 17:37, Michael Matz wrote: >> What I want (and I'm not totally clear on what this actually means) is >> > to be able to optimize all the cases where the end result will be the >> > same as the compiler produces now (using multiple multiply, shift, and >> > add operations). > Okay, then you really want to look through value-preserving conversions. > >> > Ok, so that's an obvious statement, but the point is that, right now, >> > the compiler does nothing special when you cast from int -> unsigned >> > int, or vice-versa, and I want to capture that somehow. There are some >> > exceptions, I'm sure, but what are they? > Same-sized signed<-> unsigned conversions aren't value preserving: > unsigned char c = 255; (signed char)c == -1; 255 != -1 > unsigned -> larger sized signed is value preserving > unsigned char c = 255; (signed short)c == 255; > signed -> unsigned never is value preserving
OK, so I've tried implementing this, and I find I hit against a problem: Given this test case: unsigned long long foo (unsigned long long a, signed char *b, signed char *c) { return a + *b * *c; } Those rules say that it should not be suitable for optimization because there's an implicit cast from signed int to unsigned long long. Without any widening multiplications allowed, GCC gives this code (for ARM): ldrsb r2, [r2, #0] ldrsb r3, [r3, #0] mul r2, r2, r3 adds r0, r0, r2 adc r1, r1, r2, asr #31 This is exactly what a signed widening multiply-and-accumulate with smlalbb would have done! OK, so the types in the testcase are a bit contrived, but my point is that I want to be able to use the widening-mult instructions everywhere that they would produce the same output and gcc would otherwise, and gcc just doesn't seem that interested in signed<->unsigned conversions. So, I'm happy to put in checks to ensure that truncations are not ignore, but I'm really not sure what's the right thing to do with the extends and signedness switches. Any suggestions? Andrew