@@ -356,6 +356,49 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
356356 None
357357 }
358358
359+ /// If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
360+ #[instrument(level = "trace", skip(self))]
361+ fn process_constant(
362+ &mut self,
363+ bb: BasicBlock,
364+ lhs: PlaceIndex,
365+ constant: OpTy<'tcx>,
366+ state: &mut State<ConditionSet<'a>>,
367+ ) {
368+ self.map.for_each_projection_value(
369+ lhs,
370+ constant,
371+ &mut |elem, op| match elem {
372+ TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(),
373+ TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(),
374+ TrackElem::Discriminant => {
375+ let variant = self.ecx.read_discriminant(op).ok()?;
376+ let discr_value =
377+ self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?;
378+ Some(discr_value.into())
379+ }
380+ TrackElem::DerefLen => {
381+ let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into();
382+ let len_usize = op.len(&self.ecx).ok()?;
383+ let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
384+ Some(ImmTy::from_uint(len_usize, layout).into())
385+ }
386+ },
387+ &mut |place, op| {
388+ if let Some(conditions) = state.try_get_idx(place, self.map)
389+ && let Ok(imm) = self.ecx.read_immediate_raw(op)
390+ && let Some(imm) = imm.right()
391+ && let Immediate::Scalar(Scalar::Int(int)) = *imm
392+ {
393+ conditions.iter_matches(int).for_each(|c: Condition| {
394+ self.opportunities
395+ .push(ThreadingOpportunity { chain: vec![bb], target: c.target })
396+ })
397+ }
398+ },
399+ );
400+ }
401+
359402 #[instrument(level = "trace", skip(self))]
360403 fn process_operand(
361404 &mut self,
@@ -368,40 +411,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
368411 // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`.
369412 Operand::Constant(constant) => {
370413 let constant = self.ecx.eval_mir_constant(&constant.const_, None, None).ok()?;
371- self.map.for_each_projection_value(
372- lhs,
373- constant,
374- &mut |elem, op| match elem {
375- TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(),
376- TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(),
377- TrackElem::Discriminant => {
378- let variant = self.ecx.read_discriminant(op).ok()?;
379- let discr_value =
380- self.ecx.discriminant_for_variant(op.layout.ty, variant).ok()?;
381- Some(discr_value.into())
382- }
383- TrackElem::DerefLen => {
384- let op: OpTy<'_> = self.ecx.deref_pointer(op).ok()?.into();
385- let len_usize = op.len(&self.ecx).ok()?;
386- let layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
387- Some(ImmTy::from_uint(len_usize, layout).into())
388- }
389- },
390- &mut |place, op| {
391- if let Some(conditions) = state.try_get_idx(place, self.map)
392- && let Ok(imm) = self.ecx.read_immediate_raw(op)
393- && let Some(imm) = imm.right()
394- && let Immediate::Scalar(Scalar::Int(int)) = *imm
395- {
396- conditions.iter_matches(int).for_each(|c: Condition| {
397- self.opportunities.push(ThreadingOpportunity {
398- chain: vec![bb],
399- target: c.target,
400- })
401- })
402- }
403- },
404- );
414+ self.process_constant(bb, lhs, constant, state);
405415 }
406416 // Transfer the conditions on the copied rhs.
407417 Operand::Move(rhs) | Operand::Copy(rhs) => {
0 commit comments