Skip to content

Commit 751ecb9

Browse files
committed
add an Rvalue for is_val_statically_known and use it in MIR optimization
1 parent 7ad23f4 commit 751ecb9

File tree

34 files changed

+189
-106
lines changed

34 files changed

+189
-106
lines changed

compiler/rustc_borrowck/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,7 +1535,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
15351535
| Rvalue::Repeat(operand, _)
15361536
| Rvalue::UnaryOp(_ /*un_op*/, operand)
15371537
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
1538-
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
1538+
| Rvalue::ShallowInitBox(operand, _ /*ty*/)
1539+
| Rvalue::StaticallyKnown(operand) => {
15391540
self.consume_operand(location, (operand, span), state)
15401541
}
15411542

compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
299299
| Rvalue::Repeat(operand, _)
300300
| Rvalue::UnaryOp(_ /*un_op*/, operand)
301301
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
302-
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
302+
| Rvalue::ShallowInitBox(operand, _ /*ty*/)
303+
| Rvalue::StaticallyKnown(operand) => self.consume_operand(location, operand),
303304

304305
&Rvalue::CopyForDeref(place) => {
305306
let op = &Operand::Copy(place);

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,7 +1633,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
16331633
| Rvalue::ThreadLocalRef(..)
16341634
| Rvalue::Len(..)
16351635
| Rvalue::Discriminant(..)
1636-
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
1636+
| Rvalue::NullaryOp(NullOp::OffsetOf(..), _)
1637+
| Rvalue::StaticallyKnown(_) => {}
16371638
}
16381639
}
16391640

@@ -2209,7 +2210,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22092210
| Rvalue::CopyForDeref(..)
22102211
| Rvalue::UnaryOp(..)
22112212
| Rvalue::Discriminant(..)
2212-
| Rvalue::WrapUnsafeBinder(..) => None,
2213+
| Rvalue::WrapUnsafeBinder(..)
2214+
| Rvalue::StaticallyKnown(..) => None,
22132215

22142216
Rvalue::Aggregate(aggregate, _) => match **aggregate {
22152217
AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,

compiler/rustc_codegen_gcc/src/builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
925925
self.gcc_checked_binop(oop, typ, lhs, rhs)
926926
}
927927

928+
fn is_constant(&mut self, val: Self::Value) -> Self::Value {
929+
let builtin = self.context.get_builtin_function("__builtin_constant_p");
930+
let res = self.context.new_call(None, builtin, &[val]);
931+
self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
932+
}
933+
928934
fn alloca(&mut self, size: Size, align: Align) -> RValue<'gcc> {
929935
let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes());
930936
// TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial.

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -381,12 +381,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
381381
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
382382
)
383383
}
384-
sym::is_val_statically_known => {
385-
let a = args[0].immediate();
386-
let builtin = self.context.get_builtin_function("__builtin_constant_p");
387-
let res = self.context.new_call(None, builtin, &[a]);
388-
self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
389-
}
390384
sym::catch_unwind => {
391385
try_intrinsic(
392386
self,

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11031103
Some(self.call_intrinsic(name, &[self.type_i8(), self.type_ix(size.bits())], &[lhs, rhs]))
11041104
}
11051105

1106+
fn is_constant(&mut self, val: Self::Value) -> Self::Value {
1107+
self.call_intrinsic("llvm.is.constant", &[self.cx.val_ty(val)], &[val])
1108+
}
1109+
11061110
/* Miscellaneous instructions */
11071111
fn memcpy(
11081112
&mut self,

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -198,17 +198,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
198198
codegen_autodiff(self, tcx, instance, args, result);
199199
return Ok(());
200200
}
201-
sym::is_val_statically_known => {
202-
if let OperandValue::Immediate(imm) = args[0].val {
203-
self.call_intrinsic(
204-
"llvm.is.constant",
205-
&[args[0].layout.immediate_llvm_type(self.cx)],
206-
&[imm],
207-
)
208-
} else {
209-
self.const_bool(false)
210-
}
211-
}
212201
sym::select_unpredictable => {
213202
let cond = args[0].immediate();
214203
assert_eq!(args[1].layout, args[2].layout);

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
737737
let layout = bx.cx().layout_of(binder_ty);
738738
OperandRef { val: operand.val, layout }
739739
}
740+
mir::Rvalue::StaticallyKnown(ref operand) => {
741+
let operand = self.codegen_operand(bx, operand);
742+
let val = match operand.val {
743+
// This would need to insert some loads for the type. That's
744+
// unlikely to be profitable, so just collapse to `false`.
745+
OperandValue::Ref(..) => bx.const_bool(false),
746+
OperandValue::Immediate(val) => bx.is_constant(val),
747+
OperandValue::Pair(lval, rval) => {
748+
let l = bx.is_constant(lval);
749+
let r = bx.is_constant(rval);
750+
bx.and(l, r)
751+
}
752+
// A zero-sized value is always constant, so the backend
753+
// knows everything there is to know about it.
754+
OperandValue::ZeroSized => bx.const_bool(true),
755+
};
756+
OperandRef {
757+
val: OperandValue::Immediate(val),
758+
layout: bx.cx().layout_of(bx.tcx().types.bool),
759+
}
760+
}
740761
}
741762
}
742763

compiler/rustc_codegen_ssa/src/traits/builder.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,15 @@ pub trait BuilderMethods<'a, 'tcx>:
293293
self.assume(is_null);
294294
}
295295

296+
/// Returns whether `val` has a value known at compile-time.
297+
///
298+
/// Defaults to always returning `false`, since returning `true` might trick
299+
/// the program into performing costly checks that only make sense at
300+
/// compile-time.
301+
fn is_constant(&mut self, _val: Self::Value) -> Self::Value {
302+
self.const_bool(false)
303+
}
304+
296305
fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
297306
fn nonnull_metadata(&mut self, load: Self::Value);
298307

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
708708
Rvalue::WrapUnsafeBinder(..) => {
709709
// Unsafe binders are always trivial to create.
710710
}
711+
712+
Rvalue::StaticallyKnown(..) => {
713+
// We can always choose a value for this.
714+
}
711715
}
712716
}
713717

0 commit comments

Comments
 (0)