Rollup merge of #121376 - Nadrieril:mir-half-ranges, r=pnkfelix
Skip unnecessary comparison with half-open range patterns This is the last remaining detail in the implementation of half-open range patterns. Until now, a half-open range pattern like `10..` was converted to `10..T::MAX` before lowering to MIR, which generated an extra pointless comparison. With this PR we don't generate it.
This commit is contained in:
commit
2e0a26a32a
2 changed files with 33 additions and 39 deletions
|
@ -291,33 +291,41 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
TestKind::Range(ref range) => {
|
||||
let lower_bound_success = self.cfg.start_new_block();
|
||||
|
||||
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
||||
// FIXME: skip useless comparison when the range is half-open.
|
||||
let lo = range.lo.to_const(range.ty, self.tcx);
|
||||
let hi = range.hi.to_const(range.ty, self.tcx);
|
||||
let lo = self.literal_operand(test.span, lo);
|
||||
let hi = self.literal_operand(test.span, hi);
|
||||
let val = Operand::Copy(place);
|
||||
|
||||
let [success, fail] = *target_blocks else {
|
||||
bug!("`TestKind::Range` should have two target blocks");
|
||||
};
|
||||
self.compare(
|
||||
block,
|
||||
lower_bound_success,
|
||||
fail,
|
||||
source_info,
|
||||
BinOp::Le,
|
||||
lo,
|
||||
val.clone(),
|
||||
);
|
||||
let op = match range.end {
|
||||
RangeEnd::Included => BinOp::Le,
|
||||
RangeEnd::Excluded => BinOp::Lt,
|
||||
// Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons.
|
||||
let val = Operand::Copy(place);
|
||||
|
||||
let intermediate_block = if !range.lo.is_finite() {
|
||||
block
|
||||
} else if !range.hi.is_finite() {
|
||||
success
|
||||
} else {
|
||||
self.cfg.start_new_block()
|
||||
};
|
||||
self.compare(lower_bound_success, success, fail, source_info, op, val, hi);
|
||||
|
||||
if let Some(lo) = range.lo.as_finite() {
|
||||
let lo = self.literal_operand(test.span, lo);
|
||||
self.compare(
|
||||
block,
|
||||
intermediate_block,
|
||||
fail,
|
||||
source_info,
|
||||
BinOp::Le,
|
||||
lo,
|
||||
val.clone(),
|
||||
);
|
||||
};
|
||||
|
||||
if let Some(hi) = range.hi.as_finite() {
|
||||
let hi = self.literal_operand(test.span, hi);
|
||||
let op = match range.end {
|
||||
RangeEnd::Included => BinOp::Le,
|
||||
RangeEnd::Excluded => BinOp::Lt,
|
||||
};
|
||||
self.compare(intermediate_block, success, fail, source_info, op, val, hi);
|
||||
}
|
||||
}
|
||||
|
||||
TestKind::Len { len, op } => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue