#175959 - sverx - Thu Mar 10, 2011 5:26 pm
I guess I'm asking one of these things that they teach in high school but either I was sleeping or the school wasn't as good as I'd want it to be... BTW:
Do the integer divisions (and modulus) operations between a variable (the dividend) and a constant value, power of 2 [2^n] (the divisor) generate different ARM ASM code when the variable is unsigned vs. signed? And are the operations on the former faster?
Thanks :)
#175960 - Dwedit - Thu Mar 10, 2011 11:47 pm
Right shift is different depending on whether it's signed or not, so that the sign bit is preserved. Otherwise, they are the same. Doesn't matter whether you write x >> 4 or x/16, it's the same asm.
_________________
"We are merely sprites that dance at the beck and call of our button pressing overlord."
#175961 - Ruben - Fri Mar 11, 2011 5:48 am
Dividing by a signed power of two needs a bit more baggage (cmp, addmi) to round the number to zero (ASR rounds to -infinity).
Read TONC ;D
#175962 - sverx - Fri Mar 11, 2011 9:55 am
Thank you both. If I understand correctly, if there's no real reason to use a signed, then it's better to use an unsigned, right? :)
#175963 - Ruben - Fri Mar 11, 2011 10:07 am
Mhm.
Here's the article at Cearn's site (turns out it wasn't TONC afterall =P): Linky
Quote: |
... There are some other consequences besides the obvious difference in results. First, there's how compilers deal with it. Compilers are very well aware that a bit-shift is faster than division and one of the optimizations they perform is replacing divisions by shifts where appropriate. For unsigned numerals the division will be replaced by a single shift. However, for signed variables some extra instructions have to added to correct the difference in rounding. |
#175964 - sverx - Fri Mar 11, 2011 10:44 am
I went to run a test. For the work I needed to be done, the time required went from 22 scanlines down to 18 scanlines, after I changed my short ints with unsigned short ints. It's 18% faster :)
(Since I needed to store values from 0 to 4095 plus a 'null' value that I defined as '-1' I had to change that 'null' to 0xFFFF but anyway I see it was a good choice :) )
#175965 - Ruben - Fri Mar 11, 2011 10:50 am
Usually, you'll want to use 'signed int' or 'unsigned int' for types unless you ABSOLUTELY have to, but even then there's work arounds.
For example:
Code: |
//! When doing addition/subtraction/storing
//! You truncate only if you need to use multiplication/division
0x6382 + 0xFF28 = 0x162AA [truncated to 16-bit, this is still correct]
0x6382 - 0xFF28 = 0xF645A [ditto]
//! When multiplying/dividing
val <<= 16; //! get rid of carry area
val >>= 16; //! shift back to 16-bit
|
#175980 - sverx - Mon Mar 14, 2011 12:50 pm
Thanks, I'll follow your advices :)