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?