1#![allow(non_snake_case)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4use super::SSATransformer::SSATransformer;
5use rustc_abi::FieldIdx;
6use rustc_hir::def_id::DefIdMap;
7use rustc_index::IndexVec;
8use rustc_middle::ty::TyCtxt;
9use rustc_middle::{mir::*, ty::GenericArgs};
10use rustc_span::sym::new;
11use std::collections::{HashMap, HashSet, VecDeque};
12pub struct Replacer<'tcx> {
18 pub(crate) tcx: TyCtxt<'tcx>,
19 pub(crate) ssatransformer: super::SSATransformer::SSATransformer<'tcx>,
20 pub(crate) new_local_collection: HashSet<Local>,
21 pub(crate) new_locals_to_declare: HashMap<Local, Local>,
22}
23impl<'tcx> Replacer<'tcx> {
24 pub fn insert_phi_statment(&mut self, body: &mut Body<'tcx>) {
25 for (block_index, blockdata) in body.basic_blocks.iter_enumerated() {}
26 let mut phi_functions: HashMap<BasicBlock, HashSet<Local>> = HashMap::new();
27 for bb in body.basic_blocks.indices() {
28 phi_functions.insert(bb, HashSet::new());
29 }
30 let variables: Vec<Local> = self
31 .ssatransformer
32 .local_assign_blocks
33 .iter()
34 .filter(|(_, blocks)| blocks.len() >= 2)
35 .map(|(&local, _)| local)
36 .collect();
37 for var in &variables {
38 if let Some(def_blocks) = self.ssatransformer.local_assign_blocks.get(var) {
39 let mut worklist: VecDeque<BasicBlock> = def_blocks.iter().cloned().collect();
40 let mut processed: HashSet<BasicBlock> = HashSet::new();
41 while let Some(block) = worklist.pop_front() {
42 if let Some(df_blocks) = self.ssatransformer.df.get(&block) {
43 for &df_block in df_blocks {
44 if !processed.contains(&df_block) {
45 phi_functions.get_mut(&df_block).unwrap().insert(*var);
46 processed.insert(df_block);
47
48 worklist.push_back(df_block);
49 }
50 }
51 }
52 }
53 }
68 }
69
70 for (block, vars) in phi_functions {
71 for var in vars.clone() {
72 let decl = body.local_decls[var].clone();
73 let predecessors = body.basic_blocks.predecessors()[block].clone();
77
78 let mut operands = IndexVec::with_capacity(predecessors.len());
79 for _ in 0..predecessors.len() {
80 operands.push(Operand::Copy(Place::from(var)));
81 }
82 let phi_stmt: Statement<'_> = Statement::new(
83 SourceInfo::outermost(body.span),
84 StatementKind::Assign(Box::new((
85 Place::from(var),
86 Rvalue::Aggregate(
87 Box::new(AggregateKind::Adt(
88 self.ssatransformer.phi_def_id.clone(),
89 rustc_abi::VariantIdx::from_u32(0),
90 GenericArgs::empty(),
91 None,
92 None,
93 )),
94 operands,
95 ),
96 ))),
97 );
98 body.basic_blocks_mut()[block]
106 .statements
107 .insert(0, phi_stmt);
108 }
109 }
110 }
111 pub fn insert_essa_statement(&mut self, body: &mut Body<'tcx>) {
112 let order = SSATransformer::depth_first_search_preorder(
113 &self.ssatransformer.dom_tree,
114 body.basic_blocks.indices().next().unwrap(),
115 );
116
117 for &bb in &order {
118 self.essa_process_basic_block(bb, body);
119 }
120 }
121
122 fn essa_process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
123 let switch_block_data = body.basic_blocks[bb].clone();
124
125 if let Some(terminator) = &switch_block_data.terminator {
126 if let TerminatorKind::SwitchInt { discr, targets, .. } = &terminator.kind {
127 if targets.iter().count() == 1 {
128 let (value, target) = targets.iter().next().unwrap();
129 self.essa_assign_statement(&target, &bb, value, discr, body);
130
131 let otherwise = targets.otherwise();
132 self.essa_assign_statement(&otherwise, &bb, 1, discr, body);
133 }
134 }
135 }
136 }
137
138 fn extract_condition(
139 &self,
140 place: &Place<'tcx>,
141 switch_block: &BasicBlockData<'tcx>,
142 ) -> Option<(Operand<'tcx>, Operand<'tcx>, BinOp)> {
143 for stmt in &switch_block.statements {
144 if let StatementKind::Assign(box (lhs, Rvalue::BinaryOp(bin_op, box (op1, op2)))) =
145 &stmt.kind
146 {
147 if lhs == place {
148 let return_op1: &Operand<'tcx> = &op1;
149 let return_op2: &Operand<'tcx> = &op2;
150
151 return Some((return_op1.clone(), return_op2.clone(), *bin_op));
152 }
153 }
154 }
155 None
156 }
157 fn make_const_operand(&self, val: u64) -> Operand<'tcx> {
158 Operand::Constant(Box::new(ConstOperand {
159 span: rustc_span::DUMMY_SP,
160 user_ty: None,
161 const_: Const::from_usize(self.tcx, val),
162 }))
163 }
164
165 fn op_to_code(op: BinOp) -> u64 {
166 match op {
167 BinOp::Lt => 1,
168 BinOp::Le => 2,
169 BinOp::Ge => 3,
170 BinOp::Gt => 4,
171 BinOp::Eq => 5,
172 BinOp::Ne => 6,
173 _ => 7,
174 }
175 }
176 fn trace_operand_source(
177 &self,
178 body: &Body<'tcx>,
179 mut current_block: BasicBlock,
180 target_place: Place<'tcx>,
181 ) -> Operand<'tcx> {
182 let mut visited = HashSet::new();
183 let current_place = target_place;
184
185 while visited.insert(current_block) {
186 let data = &body.basic_blocks[current_block];
187 for stmt in data.statements.iter().rev() {
188 if let StatementKind::Assign(box (lhs, rvalue)) = &stmt.kind {
189 if *lhs == current_place {
190 match rvalue {
191 Rvalue::Use(op) => return op.clone(),
192 _ => return Operand::Copy(current_place),
193 }
194 }
195 }
196 }
197
198 let preds = &body.basic_blocks.predecessors()[current_block];
199 if preds.len() == 1 {
200 current_block = preds[0];
201 } else {
202 break;
203 }
204 }
205
206 Operand::Copy(current_place)
207 }
208 fn essa_assign_statement(
212 &mut self,
213 bb: &BasicBlock,
214 switch_block: &BasicBlock,
215 value: u128,
216 discr: &Operand<'tcx>,
217 body: &mut Body<'tcx>,
218 ) {
219 let switch_block_data = &body.basic_blocks[*switch_block];
220
221 let magic_number_operand = self.make_const_operand(switch_block.as_usize() as u64);
222
223 if let Operand::Copy(switch_place) | Operand::Move(switch_place) = discr {
225 if let Some((op1, op2, cmp_op)) =
227 self.extract_condition(switch_place, switch_block_data)
228 {
229 let op1 = if let Some(p1) = op1.place() {
230 self.trace_operand_source(body, *switch_block, p1)
231 } else {
232 op1
233 };
234
235 let op2 = if let Some(p2) = op2.place() {
236 self.trace_operand_source(body, *switch_block, p2)
237 } else {
238 op2
239 };
240 rap_debug!(
241 "essa trace_operand_source op1:{:?} op2:{:?} cmp_op:{:?} value:{:?}\n",
242 op1,
243 op2,
244 cmp_op,
245 value
246 );
247 let block_data: &mut BasicBlockData<'tcx> = &mut body.basic_blocks.as_mut()[*bb];
248
249 let const_op1: Option<&ConstOperand<'_>> = op1.constant();
250 let const_op2: Option<&ConstOperand<'_>> = op2.constant();
251
252 let cmp_operand = self.make_const_operand(Self::op_to_code(cmp_op));
254 let flip_cmp_operand =
255 self.make_const_operand(Self::op_to_code(Self::flip(cmp_op)));
256 let reverse_cmp_operand =
257 self.make_const_operand(Self::op_to_code(Self::reverse(cmp_op)));
258 let flip_reverse_cmp_operand =
259 self.make_const_operand(Self::op_to_code(Self::flip(Self::reverse(cmp_op))));
260
261 match (const_op1, const_op2) {
262 (None, None) => {
264 match (op1, op2) {
265 (
266 Operand::Copy(p1) | Operand::Move(p1),
267 Operand::Copy(p2) | Operand::Move(p2),
268 ) => {
269 let adt_kind = AggregateKind::Adt(
270 self.ssatransformer.essa_def_id.clone(),
271 rustc_abi::VariantIdx::from_u32(0),
272 GenericArgs::empty(),
273 None,
274 None,
275 );
276 let place1 = Place::from(p1);
277 let place2 = Place::from(p2);
278 let rvalue1;
279 let rvalue2;
280 let mut operand1: IndexVec<_, _> = IndexVec::with_capacity(4);
281 let mut operand2: IndexVec<_, _> = IndexVec::with_capacity(4);
282
283 if value == 0 {
285 operand1.push(Operand::Copy(Place::from(p1)));
288 operand1.push(Operand::Copy(Place::from(p2)));
289 operand1.push(flip_cmp_operand.clone());
290 operand1.push(magic_number_operand.clone());
291
292 operand2.push(Operand::Copy(Place::from(p2)));
294 operand2.push(Operand::Copy(Place::from(p1)));
295 operand2.push(flip_reverse_cmp_operand.clone());
296 operand2.push(magic_number_operand.clone());
297
298 rvalue1 =
299 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand1);
300 rvalue2 =
301 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand2);
302 } else {
303 operand1.push(Operand::Copy(Place::from(p1)));
306 operand1.push(Operand::Copy(Place::from(p2)));
307 operand1.push(cmp_operand.clone());
308 operand1.push(magic_number_operand.clone());
309
310 operand2.push(Operand::Copy(Place::from(p2)));
312 operand2.push(Operand::Copy(Place::from(p1)));
313 operand2.push(reverse_cmp_operand.clone());
314 operand2.push(magic_number_operand.clone());
315
316 rvalue1 =
317 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand1);
318 rvalue2 =
319 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand2);
320 }
321
322 let assign_stmt1 = Statement::new(
323 SourceInfo::outermost(body.span),
324 StatementKind::Assign(Box::new((place1, rvalue1))),
325 );
326 let assign_stmt2 = Statement::new(
327 SourceInfo::outermost(body.span),
328 StatementKind::Assign(Box::new((place2, rvalue2))),
329 );
330
331 let mut insert_index = 0;
332 for (i, stmt) in block_data.statements.iter().enumerate() {
333 if !SSATransformer::is_essa_statement(
334 &self.ssatransformer,
335 stmt,
336 ) {
337 break;
338 }
339 insert_index = i + 1;
340 }
341
342 block_data.statements.insert(insert_index, assign_stmt1);
343 block_data.statements.insert(insert_index + 1, assign_stmt2);
344
345 for i in insert_index..insert_index + 2 {
346 let essa_in_body = block_data.statements.get_mut(i).unwrap();
347 rap_trace!(
348 "Inserted eSSA statement {:?} in block {:?}",
349 essa_in_body,
350 magic_number_operand
351 );
352 }
353 }
354 _ => panic!("Expected a place"),
355 };
356 }
357
358 (None, Some(_)) | (Some(_), None) => {
360 let mut operand: IndexVec<_, _> = IndexVec::with_capacity(3);
361 let place;
362
363 if op1.constant().is_none() {
371 place = match op1 {
372 Operand::Copy(p) | Operand::Move(p) => Place::from(p),
373 _ => panic!("Expected a place"),
374 };
375 operand.push(op1.clone());
376 operand.push(op2.clone());
377 } else {
378 place = match op2 {
379 Operand::Copy(p) | Operand::Move(p) => Place::from(p),
380 _ => panic!("Expected a place"),
381 };
382 operand.push(op2.clone());
383 operand.push(op1.clone());
384 }
385
386 let rvalue;
387 if value == 0 {
388 operand.push(flip_cmp_operand.clone());
389 } else {
390 operand.push(cmp_operand.clone());
391 }
392 operand.push(magic_number_operand.clone());
393 let adt_kind = AggregateKind::Adt(
394 self.ssatransformer.essa_def_id.clone(),
395 rustc_abi::VariantIdx::from_u32(0),
396 GenericArgs::empty(),
397 None,
398 None,
399 );
400 rvalue = Rvalue::Aggregate(Box::new(adt_kind.clone()), operand);
401
402 let assign_stmt = Statement::new(
403 SourceInfo::outermost(body.span),
404 StatementKind::Assign(Box::new((place, rvalue))),
405 );
406 let mut insert_index = 0;
407 for (i, stmt) in block_data.statements.iter().enumerate() {
408 if !SSATransformer::is_essa_statement(&self.ssatransformer, stmt) {
409 break;
410 }
411 insert_index = i + 1;
412 }
413
414 block_data.statements.insert(insert_index, assign_stmt);
415
416 let essa_in_body = block_data.statements.get_mut(insert_index).unwrap();
417 let essa_ptr = essa_in_body as *const _;
418
419 rap_trace!(
420 "Inserted eSSA statement {:?} in block {:?}",
421 essa_in_body,
422 magic_number_operand
423 );
424 }
425
426 (Some(_), Some(_)) => {}
427 }
428 };
429 }
430
431 }
433 pub fn flip(binOp: BinOp) -> BinOp {
434 match binOp {
435 BinOp::Lt => BinOp::Ge,
436 BinOp::Le => BinOp::Gt,
437 BinOp::Gt => BinOp::Le,
438 BinOp::Ge => BinOp::Lt,
439 BinOp::Eq => BinOp::Ne,
440 BinOp::Ne => BinOp::Eq,
441 _ => panic!("flip() called on non-comparison operator"),
442 }
443 }
444 pub fn reverse(binOp: BinOp) -> BinOp {
445 match binOp {
446 BinOp::Lt => BinOp::Gt,
447 BinOp::Le => BinOp::Ge,
448 BinOp::Gt => BinOp::Lt,
449 BinOp::Ge => BinOp::Le,
450 BinOp::Eq => BinOp::Ne,
451 BinOp::Ne => BinOp::Eq,
452 _ => panic!("flip() called on non-comparison operator"),
453 }
454 }
455 pub fn rename_variables(&mut self, body: &mut Body<'tcx>) {
456 for local in body.local_decls.indices() {
457 self.ssatransformer.reaching_def.insert(local, None);
458 }
459 let order = SSATransformer::depth_first_search_preorder(
462 &self.ssatransformer.dom_tree,
463 body.basic_blocks.indices().next().unwrap().clone(),
464 );
465 for bb in order {
466 self.process_basic_block(bb, body);
467 }
468
469 rap_debug!("new_locals_to_declare {:?}", self.new_locals_to_declare);
470
471 let mut locals_to_add: Vec<_> = self.new_locals_to_declare.iter().collect();
472 locals_to_add.sort_by_key(|(new_local, _)| new_local.index());
473 rap_debug!("locals_to_add {:?}", locals_to_add);
474 for (new_local, original_local) in locals_to_add {
475 let original_decl = &body.local_decls[*original_local];
476
477 let new_decl = original_decl.clone();
478
479 let pushed_index = body.local_decls.push(new_decl);
480 rap_debug!("Ok with {:?} {:?}", pushed_index, *new_local);
481 assert_eq!(pushed_index, *new_local);
482 }
483 }
484
485 fn process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
486 self.rename_statement(bb, body);
487 self.rename_terminator(bb, body);
488 let terminator = body.basic_blocks[bb].terminator();
489 let successors: Vec<_> = terminator.successors().collect();
490 if let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind {
491 if targets.iter().count() == 1 {
492 for succ_bb in successors.clone() {
493 self.rename_essa_statments(succ_bb, body, bb);
494 }
495 }
496 }
497
498 for succ_bb in successors {
499 self.rename_phi_functions(succ_bb, body, bb);
500 }
501 }
502 fn rename_essa_statments(
503 &mut self,
504 succ_bb: BasicBlock,
505 body: &mut Body<'tcx>,
506 do_bb: BasicBlock,
507 ) {
508 for statement in body.basic_blocks.as_mut()[succ_bb].statements.iter_mut() {
510 if self.ssatransformer.is_essa_statement(statement) {
512 if let Some(pred_block) = self.ssatransformer.get_essa_source_block(statement) {
515 if pred_block != do_bb {
518 continue;
519 }
520
521 if let StatementKind::Assign(box (_, rvalue)) = &mut statement.kind {
523 if let Rvalue::Aggregate(_, operands) = rvalue {
524 let index = 0;
526 if index < operands.len() {
527 self.replace_operand(
529 &mut operands[FieldIdx::from_usize(index)],
530 &do_bb,
531 );
532 }
533 }
534 }
535 }
536 }
537 }
538 }
539
540 fn rename_phi_functions(
541 &mut self,
542 succ_bb: BasicBlock,
543 body: &mut Body<'tcx>,
544 do_bb: BasicBlock,
545 ) {
546 for (stmt_idx, statement) in body.basic_blocks.as_mut()[succ_bb]
547 .statements
548 .iter_mut()
549 .enumerate()
550 {
551 let location = Location {
552 block: succ_bb,
553 statement_index: stmt_idx,
554 };
555
556 if SSATransformer::is_phi_statement(&self.ssatransformer, statement) {
557 if let StatementKind::Assign(box (_, rvalue)) = &mut statement.kind {
558 if let Rvalue::Aggregate(_, operands) = rvalue {
559 let operand_count = operands.len();
560 let index = *self.ssatransformer.phi_index.entry(location).or_insert(0);
561
562 if index < operand_count {
563 match &mut operands[FieldIdx::from_usize(index)] {
564 Operand::Copy(place) | Operand::Move(place) => {
565 self.replace_place(place, &do_bb);
566 }
567 _ => {}
568 }
569 *self.ssatransformer.phi_index.entry(location).or_insert(0) += 1;
570 }
571 }
572 }
573 }
574 }
575 }
576 pub fn rename_statement(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
577 for statement in body.basic_blocks.as_mut()[bb].statements.iter_mut() {
578 let is_phi = SSATransformer::is_phi_statement(&self.ssatransformer, statement);
580 let is_essa = SSATransformer::is_essa_statement(&self.ssatransformer, statement);
581 rap_trace!(
582 "IS in statement at block {:?}: {:?}, is_phi: {}, is_essa: {}",
583 bb,
584 statement.clone(),
585 is_phi,
586 is_essa
587 );
588 match &mut statement.kind {
589 StatementKind::Assign(box (place, rvalue)) => {
590 if !is_phi {
591 if !is_essa {
592 rap_trace!(
593 "Renaming in statement at block {:?}: {:?}",
594 bb,
595 rvalue.clone()
596 );
597 self.replace_rvalue(rvalue, &bb);
598 self.rename_local_def(place, &bb, true);
599 } else {
600 self.ssa_rename_local_def(place, &bb, true);
601 }
602 } else {
603 self.ssa_rename_local_def(place, &bb, false);
604 }
605 }
606 StatementKind::StorageLive(local) => {
608 }
610 StatementKind::StorageDead(local) => {
611 }
613 _ => {}
614 }
615 }
616 }
617
618 fn rename_terminator(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
619 let terminator: &mut Terminator<'tcx> = body.basic_blocks.as_mut()[bb].terminator_mut();
620 match &mut terminator.kind {
621 TerminatorKind::Call {
622 args, destination, ..
623 } => {
624 for op in args.iter_mut() {
625 match &mut op.node {
626 Operand::Copy(place) | Operand::Move(place) => {
627 self.replace_place(place, &bb);
628 }
629 Operand::Constant(const_operand) => {}
630 }
631 }
632 self.rename_local_def(destination, &bb, true);
633 }
634 TerminatorKind::Assert { cond, .. } => {
635 self.replace_operand(cond, &bb);
636 }
637 TerminatorKind::Drop { place, .. } => {
638 self.replace_place(place, &bb);
639 }
640 TerminatorKind::SwitchInt { discr, .. } => {
641 self.replace_operand(discr, &bb);
642 }
643 _ => {}
644 }
645 }
646
647 fn replace_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, bb: &BasicBlock) {
648 match rvalue {
649 Rvalue::Use(operand)
650 | Rvalue::Repeat(operand, _)
651 | Rvalue::UnaryOp(_, operand)
652 | Rvalue::Cast(_, operand, _)
653 | Rvalue::ShallowInitBox(operand, _) => {
654 self.replace_operand(operand, &bb);
655 }
656 Rvalue::BinaryOp(_, box (lhs, rhs)) => {
657 self.replace_operand(lhs, &bb);
658 self.replace_operand(rhs, &bb);
659 }
660 Rvalue::Aggregate(_, operands) => {
661 for operand in operands {
662 self.replace_operand(operand, &bb);
663 }
664 }
665 _ => {}
666 }
667 }
668
669 fn replace_operand(&mut self, operand: &mut Operand<'tcx>, bb: &BasicBlock) {
670 match operand {
671 Operand::Copy(place) | Operand::Move(place) => {
672 self.replace_place(place, bb);
673 }
675 _ => {}
676 }
677 }
678
679 fn replace_place(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock) {
680 self.update_reachinf_def(&place.local, &bb);
682
683 if let Some(Some(reaching_local)) = self.ssatransformer.reaching_def.get(&place.local) {
684 let local = reaching_local.clone();
685 let mut new_place: Place<'_> = Place::from(local);
686 new_place.projection = place.projection;
687
688 *place = new_place;
689 } else {
690 }
691 }
692
693 fn ssa_rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
694 self.update_reachinf_def(&place.local, &bb);
696 let Place {
697 local: old_local,
698 projection: _,
699 } = place.clone();
700 let old_place = place.clone();
701 if old_local.as_u32() == 0 {
702 return;
703 }
704 let new_local = Local::from_usize(self.ssatransformer.local_index);
705 self.ssatransformer.local_index += 1;
706 let new_place: Place<'_> = Place::from(new_local);
707 *place = new_place.clone();
708 self.new_locals_to_declare.insert(new_local, old_local);
709
710 let _old_local = old_local.clone();
711 self.ssatransformer
712 .ssa_locals_map
713 .entry(old_place)
714 .or_insert_with(HashSet::new)
715 .insert(new_place);
716
717 self.ssatransformer
718 .local_defination_block
719 .insert(new_local.clone(), bb.clone());
720 let old_local_reaching = self
721 .ssatransformer
722 .reaching_def
723 .get(&_old_local.clone())
724 .unwrap();
725
726 self.ssatransformer
727 .reaching_def
728 .insert(new_local.clone(), *old_local_reaching);
729 self.ssatransformer
730 .reaching_def
731 .insert(_old_local.clone(), Some(new_local.clone()));
732
733 }
738 fn rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
739 self.update_reachinf_def(&place.local, &bb);
741 let Place {
742 local: old_local,
743 projection: _,
744 } = place.clone();
745 let old_place = place.clone();
746 if old_local.as_u32() == 0 {
747 return;
748 }
749
750 if self.ssatransformer.skipped.contains(&old_local.as_usize()) && not_phi {
751 self.ssatransformer.skipped.remove(&old_local.as_usize());
752 self.ssatransformer
753 .reaching_def
754 .insert(old_local, Some(old_local));
755 self.ssatransformer
756 .places_map
757 .entry(old_place)
758 .or_insert_with(HashSet::new)
759 .insert(old_place);
760 return;
761 }
762 let new_local = Local::from_usize(self.ssatransformer.local_index);
763 let mut new_place: Place<'_> = Place::from(new_local);
764 self.new_locals_to_declare.insert(new_local, old_local);
765
766 new_place.projection = place.projection;
767 *place = new_place.clone();
768
769 if old_local.as_u32() == 0 {
771 return;
772 }
773
774 self.ssatransformer.local_index += 1;
775 self.ssatransformer
776 .places_map
777 .entry(old_place)
778 .or_insert_with(HashSet::new)
779 .insert(new_place);
780
781 let _old_local = old_local.clone();
782 self.ssatransformer
783 .local_defination_block
784 .insert(new_local.clone(), bb.clone());
785 let old_local_reaching = self
786 .ssatransformer
787 .reaching_def
788 .get(&_old_local.clone())
789 .unwrap();
790
791 self.ssatransformer
792 .reaching_def
793 .insert(new_local.clone(), *old_local_reaching);
794 self.ssatransformer
795 .reaching_def
796 .insert(_old_local.clone(), Some(new_local.clone()));
797
798 }
803
804 pub fn dominates_(&self, def_bb: &BasicBlock, bb: &BasicBlock) -> bool {
805 let mut visited = HashSet::new();
806
807 let mut stack = self.ssatransformer.dom_tree.get(def_bb).unwrap().clone();
808 while let Some(block) = stack.pop() {
809 if !visited.insert(block) {
810 continue;
811 }
812
813 if block == *bb {
814 return true;
815 }
816
817 if let Some(children) = self.ssatransformer.dom_tree.get(&block) {
818 stack.extend(children);
819 }
820 }
821
822 false
823 }
824 fn update_reachinf_def(&mut self, local: &Local, bb: &BasicBlock) {
825 let mut r = self.ssatransformer.reaching_def[local];
829 let mut dominate_bool = true;
830 if r != None {
831 let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
832 }
833
834 while !(r == None || dominate_bool) {
835 r = self.ssatransformer.reaching_def[&r.unwrap()];
836 if r != None {
837 let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
838
839 dominate_bool = self.dominates_(&def_bb, bb);
840 }
841 }
842
843 if let Some(entry) = self.ssatransformer.reaching_def.get_mut(local) {
844 *entry = r.clone();
845 }
846 }
847}
848
849