Skip to content

Commit 4078a54

Browse files
Stop generating assumes for validity ranges
Now that LLVM has implemented range attributes on arguments and returns, and now that we generate such attributes, we no longer need to use assumes to represent validity ranges.
1 parent e08b80c commit 4078a54

19 files changed

+59
-333
lines changed

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+4-65
Original file line numberDiff line numberDiff line change
@@ -240,13 +240,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
240240
if let OperandValueKind::Immediate(to_scalar) = cast_kind
241241
&& from_scalar.size(self.cx) == to_scalar.size(self.cx)
242242
{
243-
let from_backend_ty = bx.backend_type(operand.layout);
244243
let to_backend_ty = bx.backend_type(cast);
245244
Some(OperandValue::Immediate(self.transmute_immediate(
246245
bx,
247246
imm,
248247
from_scalar,
249-
from_backend_ty,
250248
to_scalar,
251249
to_backend_ty,
252250
)))
@@ -262,13 +260,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
262260
&& in_a.size(self.cx) == out_a.size(self.cx)
263261
&& in_b.size(self.cx) == out_b.size(self.cx)
264262
{
265-
let in_a_ibty = bx.scalar_pair_element_backend_type(operand.layout, 0, false);
266-
let in_b_ibty = bx.scalar_pair_element_backend_type(operand.layout, 1, false);
267263
let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false);
268264
let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false);
269265
Some(OperandValue::Pair(
270-
self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty),
271-
self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty),
266+
self.transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty),
267+
self.transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty),
272268
))
273269
} else {
274270
None
@@ -292,12 +288,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
292288
) -> Option<Bx::Value> {
293289
use abi::Primitive::*;
294290

295-
// When scalars are passed by value, there's no metadata recording their
296-
// valid ranges. For example, `char`s are passed as just `i32`, with no
297-
// way for LLVM to know that they're 0x10FFFF at most. Thus we assume
298-
// the range of the input value too, not just the output range.
299-
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
300-
301291
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
302292
(Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed),
303293
(Float(_), Float(_)) => {
@@ -339,21 +329,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
339329
bx: &mut Bx,
340330
mut imm: Bx::Value,
341331
from_scalar: abi::Scalar,
342-
from_backend_ty: Bx::Type,
343332
to_scalar: abi::Scalar,
344333
to_backend_ty: Bx::Type,
345334
) -> Bx::Value {
335+
use abi::Primitive::*;
336+
346337
assert_eq!(from_scalar.size(self.cx), to_scalar.size(self.cx));
347338

348-
use abi::Primitive::*;
349339
imm = bx.from_immediate(imm);
350340

351-
// When scalars are passed by value, there's no metadata recording their
352-
// valid ranges. For example, `char`s are passed as just `i32`, with no
353-
// way for LLVM to know that they're 0x10FFFF at most. Thus we assume
354-
// the range of the input value too, not just the output range.
355-
self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
356-
357341
imm = match (from_scalar.primitive(), to_scalar.primitive()) {
358342
(Int(..) | Float(_), Int(..) | Float(_)) => bx.bitcast(imm, to_backend_ty),
359343
(Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
@@ -368,55 +352,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
368352
bx.bitcast(int_imm, to_backend_ty)
369353
}
370354
};
371-
self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty);
372355
imm = bx.to_immediate_scalar(imm, to_scalar);
373356
imm
374357
}
375358

376-
fn assume_scalar_range(
377-
&self,
378-
bx: &mut Bx,
379-
imm: Bx::Value,
380-
scalar: abi::Scalar,
381-
backend_ty: Bx::Type,
382-
) {
383-
if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less)
384-
// For now, the critical niches are all over `Int`eger values.
385-
// Should floating-point values or pointers ever get more complex
386-
// niches, then this code will probably want to handle them too.
387-
|| !matches!(scalar.primitive(), abi::Primitive::Int(..))
388-
|| scalar.is_always_valid(self.cx)
389-
{
390-
return;
391-
}
392-
393-
let abi::WrappingRange { start, end } = scalar.valid_range(self.cx);
394-
395-
if start <= end {
396-
if start > 0 {
397-
let low = bx.const_uint_big(backend_ty, start);
398-
let cmp = bx.icmp(IntPredicate::IntUGE, imm, low);
399-
bx.assume(cmp);
400-
}
401-
402-
let type_max = scalar.size(self.cx).unsigned_int_max();
403-
if end < type_max {
404-
let high = bx.const_uint_big(backend_ty, end);
405-
let cmp = bx.icmp(IntPredicate::IntULE, imm, high);
406-
bx.assume(cmp);
407-
}
408-
} else {
409-
let low = bx.const_uint_big(backend_ty, start);
410-
let cmp_low = bx.icmp(IntPredicate::IntUGE, imm, low);
411-
412-
let high = bx.const_uint_big(backend_ty, end);
413-
let cmp_high = bx.icmp(IntPredicate::IntULE, imm, high);
414-
415-
let or = bx.or(cmp_low, cmp_high);
416-
bx.assume(or);
417-
}
418-
}
419-
420359
pub fn codegen_rvalue_unsized(
421360
&mut self,
422361
bx: &mut Bx,

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+2-74
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ use rustc_middle::mir::interpret::Scalar;
88
use rustc_middle::mir::*;
99
use rustc_middle::thir::*;
1010
use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
11-
use rustc_middle::ty::layout::IntegerExt;
1211
use rustc_middle::ty::util::IntTypeExt;
1312
use rustc_middle::ty::{self, Ty, UpvarArgs};
1413
use rustc_span::source_map::Spanned;
1514
use rustc_span::{Span, DUMMY_SP};
16-
use rustc_target::abi::{Abi, FieldIdx, Primitive};
15+
use rustc_target::abi::FieldIdx;
1716
use tracing::debug;
1817

1918
use crate::build::expr::as_place::PlaceBase;
@@ -201,85 +200,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
201200
{
202201
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
203202
let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
204-
let layout = this.tcx.layout_of(this.param_env.and(source_expr.ty));
205203
let discr = this.temp(discr_ty, source_expr.span);
206204
this.cfg.push_assign(
207205
block,
208206
source_info,
209207
discr,
210208
Rvalue::Discriminant(temp.into()),
211209
);
212-
let (op, ty) = (Operand::Move(discr), discr_ty);
213-
214-
if let Abi::Scalar(scalar) = layout.unwrap().abi
215-
&& !scalar.is_always_valid(&this.tcx)
216-
&& let Primitive::Int(int_width, _signed) = scalar.primitive()
217-
{
218-
let unsigned_ty = int_width.to_ty(this.tcx, false);
219-
let unsigned_place = this.temp(unsigned_ty, expr_span);
220-
this.cfg.push_assign(
221-
block,
222-
source_info,
223-
unsigned_place,
224-
Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr), unsigned_ty),
225-
);
226-
227-
let bool_ty = this.tcx.types.bool;
228-
let range = scalar.valid_range(&this.tcx);
229-
let merge_op =
230-
if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr };
231-
232-
let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
233-
let range_val = Const::from_bits(
234-
this.tcx,
235-
range,
236-
ty::ParamEnv::empty().and(unsigned_ty),
237-
);
238-
let lit_op = this.literal_operand(expr.span, range_val);
239-
let is_bin_op = this.temp(bool_ty, expr_span);
240-
this.cfg.push_assign(
241-
block,
242-
source_info,
243-
is_bin_op,
244-
Rvalue::BinaryOp(
245-
bin_op,
246-
Box::new((Operand::Copy(unsigned_place), lit_op)),
247-
),
248-
);
249-
is_bin_op
250-
};
251-
let assert_place = if range.start == 0 {
252-
comparer(range.end, BinOp::Le)
253-
} else {
254-
let start_place = comparer(range.start, BinOp::Ge);
255-
let end_place = comparer(range.end, BinOp::Le);
256-
let merge_place = this.temp(bool_ty, expr_span);
257-
this.cfg.push_assign(
258-
block,
259-
source_info,
260-
merge_place,
261-
Rvalue::BinaryOp(
262-
merge_op,
263-
Box::new((
264-
Operand::Move(start_place),
265-
Operand::Move(end_place),
266-
)),
267-
),
268-
);
269-
merge_place
270-
};
271-
this.cfg.push(
272-
block,
273-
Statement {
274-
source_info,
275-
kind: StatementKind::Intrinsic(Box::new(
276-
NonDivergingIntrinsic::Assume(Operand::Move(assert_place)),
277-
)),
278-
},
279-
);
280-
}
281-
282-
(op, ty)
210+
(Operand::Move(discr), discr_ty)
283211
} else {
284212
let ty = source_expr.ty;
285213
let source = unpack!(

src/tools/tidy/src/issues.txt

-1
Original file line numberDiff line numberDiff line change
@@ -3628,7 +3628,6 @@ ui/regions/issue-56537-closure-uses-region-from-container.rs
36283628
ui/regions/issue-6157.rs
36293629
ui/regions/issue-72051-member-region-hang.rs
36303630
ui/regions/issue-78262.rs
3631-
ui/repr/issue-83505-repr-simd.rs
36323631
ui/resolve/auxiliary/issue-112831-aux.rs
36333632
ui/resolve/auxiliary/issue-19452-aux.rs
36343633
ui/resolve/auxiliary/issue-21221-3.rs

tests/codegen/cast-optimized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//@ compile-flags: -O -Z merge-functions=disabled
2+
//@ min-llvm-version: 19
23
#![crate_type = "lib"]
34

45
// This tests that LLVM can optimize based on the niches in the source or

tests/codegen/enum/enum-bounds-check-derived-idx.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// This test checks an optimization that is not guaranteed to work. This test case should not block
22
// a future LLVM update.
33
//@ compile-flags: -O
4+
//@ min-llvm-version: 19
45

56
#![crate_type = "lib"]
67

tests/codegen/enum/enum-bounds-check-issue-13926.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// This test checks an optimization that is not guaranteed to work. This test case should not block
22
// a future LLVM update.
33
//@ compile-flags: -O
4+
//@ min-llvm-version: 19
45

56
#![crate_type = "lib"]
67

0 commit comments

Comments
 (0)