There's already rounding division, which is used in ConstantRange to
implement e.g. makeExactMulNUWRegion()/makeExactMulNUWRegion()
but there are no versions for right-shifts.
I'd like to try to extend ConstantRange::makeGuaranteedNoWrapRegion()
to deal with Instruction::Shl so i believe i need rounding right shifts.
The test coverage is confusing.
The existing RoundingSDiv() didn't actually pass - it never runs.
I've fixed that, and adjusted it to pass - i think we should be checking signed predicates?
Then i've added APIntOps::RoundingLShr(), APIntOps::RoundingAShr(),
standalone test coverage for them, and a cross-test to verify that
they produce identical output as compared to their div friends.
They do.
My understanding:
- LShr is "dividing" by positive 2^shamt, so it rounds down. Since the operation is unsigned it also rounds towards zero.
- (33 l>> 1) << 1 == 32
- (-31 l>> 1) << 1 == -32
Which means that if we want to round up, if there's remainder then we just need to always increment the quotent. - ((33 l>> 1) + 1) << 1 == 34
- ((-31 l>> 1) + 1) << 1 == -30
- AShr is "dividing" by positive 2^shamt, so it rounds down: (identical to LShr)
- (33 a>> 1) << 1 == 32
- (-31 a>> 1) << 1 == -32
Again, if we want to round up, if there's remainder then we just need to always increment the quotent. (identical to LShr) - ((33 a>> 1) + 1) << 1 == 34
- ((-31 a>> 1) + 1) << 1 == -30
However, if we want to round towards zero, the behavior is different. - Since it's default behavior is to round down, then for positive numbers rounds towards zero is also the default:
- (33 a>> 1) << 1 == 32
- But for negatives by default we'd go away from zero:
- (-31 l>> 1) << 1 == -32
while the expected answer is -30; which is the answer for rounding up: - ((-31 a>> 1) + 1) << 1 == -30
So if the value is negative then if quotent is non-zero - increment it, else do nothing.
- (-31 l>> 1) << 1 == -32
@sanjoy @timshen FIXME: that's the intended check, right?