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 std::collections::{HashMap, HashSet, VecDeque};
11pub struct Replacer<'tcx> {
17 pub(crate) tcx: TyCtxt<'tcx>,
18 pub(crate) ssatransformer: super::SSATransformer::SSATransformer<'tcx>,
19 pub(crate) new_local_collection: HashSet<Local>,
20}
21impl<'tcx> Replacer<'tcx> {
22 pub fn insert_phi_statment(&mut self, body: &mut Body<'tcx>) {
23 for (block_index, blockdata) in body.basic_blocks.iter_enumerated() {}
24 let mut phi_functions: HashMap<BasicBlock, HashSet<Local>> = HashMap::new();
25 for bb in body.basic_blocks.indices() {
26 phi_functions.insert(bb, HashSet::new());
27 }
28 let variables: Vec<Local> = self
29 .ssatransformer
30 .local_assign_blocks
31 .iter()
32 .filter(|(_, blocks)| blocks.len() >= 2)
33 .map(|(&local, _)| local)
34 .collect();
35 for var in &variables {
36 if let Some(def_blocks) = self.ssatransformer.local_assign_blocks.get(var) {
37 let mut worklist: VecDeque<BasicBlock> = def_blocks.iter().cloned().collect();
38 let mut processed: HashSet<BasicBlock> = HashSet::new();
39
40 while let Some(block) = worklist.pop_front() {
41 if let Some(df_blocks) = self.ssatransformer.df.get(&block) {
42 for &df_block in df_blocks {
43 if !processed.contains(&df_block) {
44 phi_functions.get_mut(&df_block).unwrap().insert(*var);
45 processed.insert(df_block);
46 if self.ssatransformer.local_assign_blocks[var].contains(&df_block)
47 {
48 worklist.push_back(df_block);
49 }
50 }
51 }
52 }
53 }
54 }
55 }
56
57 for (block, vars) in phi_functions {
58 for var in vars.clone() {
59 let decl = body.local_decls[var].clone();
60 let predecessors = body.basic_blocks.predecessors()[block].clone();
64
65 let mut operands = IndexVec::with_capacity(predecessors.len());
66 for _ in 0..predecessors.len() {
67 operands.push(Operand::Copy(Place::from(var)));
68 }
69 let phi_stmt: Statement<'_> = Statement {
70 source_info: SourceInfo::outermost(body.span),
71 kind: StatementKind::Assign(Box::new((
72 Place::from(var),
73 Rvalue::Aggregate(
74 Box::new(AggregateKind::Adt(
75 self.ssatransformer.phi_def_id.clone(),
76 rustc_abi::VariantIdx::from_u32(0),
77 GenericArgs::empty(),
78 None,
79 None,
80 )),
81 operands,
82 ),
83 ))),
84 };
85 body.basic_blocks_mut()[block]
93 .statements
94 .insert(0, phi_stmt);
95 }
96
97 for i in 0..vars.len() {
98 let phi_in_body = body.basic_blocks.as_mut()[block]
99 .statements
100 .get_mut(i)
101 .unwrap();
102 let phi_ptr = phi_in_body as *const _;
103 self.ssatransformer.phi_statements.insert(phi_ptr, true);
104 }
105 }
106 }
107 pub fn insert_essa_statement(&mut self, body: &mut Body<'tcx>) {
108 let order = SSATransformer::depth_first_search_preorder(
109 &self.ssatransformer.dom_tree,
110 body.basic_blocks.indices().next().unwrap(),
111 );
112
113 for &bb in &order {
114 self.essa_process_basic_block(bb, body);
115 }
116 }
117
118 fn essa_process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
119 let switch_block_data = body.basic_blocks[bb].clone();
120
121 if let Some(terminator) = &switch_block_data.terminator {
122 if let TerminatorKind::SwitchInt { discr, targets, .. } = &terminator.kind {
123 {
124 for (value, target) in targets.iter() {
125 self.essa_assign_statement(&target, &bb, value, discr, body);
126 }
127 let otherwise = targets.otherwise();
128
129 self.essa_assign_statement(&otherwise, &bb, 1, discr, body);
130 }
131 }
132 }
133 }
134 fn extract_condition(
135 &self,
136 place: &Place<'tcx>,
137 switch_block: &BasicBlockData<'tcx>,
138 ) -> Option<(Operand<'tcx>, Operand<'tcx>, BinOp)> {
139 for stmt in &switch_block.statements {
140 if let StatementKind::Assign(box (lhs, Rvalue::BinaryOp(bin_op, box (op1, op2)))) =
141 &stmt.kind
142 {
143 if lhs == place {
144 let mut return_op1: &Operand<'tcx> = &op1;
145 let mut return_op2: &Operand<'tcx> = &op2;
146 for stmt_original in &switch_block.statements {
147 if let StatementKind::Assign(box (lhs, Rvalue::Use(OP1))) =
148 &stmt_original.kind
149 {
150 if lhs.clone() == op1.place().unwrap() {
151 return_op1 = OP1;
152 }
153 }
154 }
155 if op2.constant().is_none() {
156 for stmt_original in &switch_block.statements {
157 if let StatementKind::Assign(box (lhs, Rvalue::Use(OP2))) =
158 &stmt_original.kind
159 {
160 if lhs.clone() == op2.place().unwrap() {
161 return_op2 = OP2;
162 }
163 }
164 }
165 }
166 return Some((return_op1.clone(), return_op2.clone(), *bin_op));
167 }
168 }
169 }
170 None
171 }
172 fn essa_assign_statement(
174 &mut self,
175 bb: &BasicBlock,
176 switch_block: &BasicBlock,
177 value: u128,
178 discr: &Operand<'tcx>,
179 body: &mut Body<'tcx>,
180 ) {
181 let switch_block_data = &body.basic_blocks[*switch_block];
182
183 let magic_number = 213134123 as u64;
185 let magic_number_operand = Operand::Constant(Box::new(ConstOperand {
186 span: rustc_span::DUMMY_SP,
187 user_ty: None,
188 const_: Const::from_usize(self.tcx, magic_number),
189 }));
190 let Lt_operand = Operand::Constant(Box::new(ConstOperand {
191 span: rustc_span::DUMMY_SP,
192 user_ty: None,
193 const_: Const::from_usize(self.tcx, 1),
194 }));
195 let Le_operand = Operand::Constant(Box::new(ConstOperand {
196 span: rustc_span::DUMMY_SP,
197 user_ty: None,
198 const_: Const::from_usize(self.tcx, 2),
199 }));
200 let Ge_operand = Operand::Constant(Box::new(ConstOperand {
201 span: rustc_span::DUMMY_SP,
202 user_ty: None,
203 const_: Const::from_usize(self.tcx, 3),
204 }));
205 let Gt_operand = Operand::Constant(Box::new(ConstOperand {
206 span: rustc_span::DUMMY_SP,
207 user_ty: None,
208 const_: Const::from_usize(self.tcx, 4),
209 }));
210 let Eq_operand = Operand::Constant(Box::new(ConstOperand {
211 span: rustc_span::DUMMY_SP,
212 user_ty: None,
213 const_: Const::from_usize(self.tcx, 5),
214 }));
215 let Ne_operand = Operand::Constant(Box::new(ConstOperand {
216 span: rustc_span::DUMMY_SP,
217 user_ty: None,
218 const_: Const::from_usize(self.tcx, 6),
219 }));
220 let other_operand = Operand::Constant(Box::new(ConstOperand {
221 span: rustc_span::DUMMY_SP,
222 user_ty: None,
223 const_: Const::from_usize(self.tcx, 7),
224 }));
225 if let Operand::Copy(switch_place) | Operand::Move(switch_place) = discr {
226 if let Some((op1, op2, cmp_op)) =
227 self.extract_condition(switch_place, switch_block_data)
228 {
229 let block_data: &mut BasicBlockData<'tcx> = &mut body.basic_blocks.as_mut()[*bb];
230
231 let const_op1: Option<&ConstOperand<'_>> = op1.constant();
232 let const_op2: Option<&ConstOperand<'_>> = op2.constant();
233 let cmp_operand: Operand<'_> = match cmp_op.clone() {
234 BinOp::Lt => Lt_operand.clone(),
235 BinOp::Le => Le_operand.clone(),
236 BinOp::Gt => Gt_operand.clone(),
237 BinOp::Ge => Ge_operand.clone(),
238 BinOp::Ne => Ne_operand.clone(),
239 BinOp::Eq => Eq_operand.clone(),
240
241 _ => other_operand.clone(),
242 };
243
244 let flip_cmp_operand: Operand<'_> = match Self::flip(cmp_op) {
245 BinOp::Lt => Lt_operand.clone(),
246 BinOp::Le => Le_operand.clone(),
247 BinOp::Gt => Gt_operand.clone(),
248 BinOp::Ge => Ge_operand.clone(),
249 BinOp::Eq => Ne_operand.clone(),
250 BinOp::Ne => Eq_operand.clone(),
251
252 _ => other_operand.clone(),
253 };
254 let reverse_cmp_operand: Operand<'_> = match Self::reverse(cmp_op) {
255 BinOp::Lt => Lt_operand.clone(),
256 BinOp::Le => Le_operand.clone(),
257 BinOp::Gt => Gt_operand.clone(),
258 BinOp::Ge => Ge_operand.clone(),
259 BinOp::Ne => Ne_operand.clone(),
260 BinOp::Eq => Eq_operand.clone(),
261
262 _ => other_operand.clone(),
263 };
264 let flip_reverse_cmp_operand: Operand<'_> = match Self::flip(Self::reverse(cmp_op))
265 {
266 BinOp::Lt => Lt_operand.clone(),
267 BinOp::Le => Le_operand.clone(),
268 BinOp::Gt => Gt_operand.clone(),
269 BinOp::Ge => Ge_operand.clone(),
270 BinOp::Eq => Ne_operand.clone(),
271 BinOp::Ne => Eq_operand.clone(),
272
273 _ => other_operand.clone(),
274 };
275 match (const_op1, const_op2) {
276 (None, None) => {
277 match (op1, op2) {
278 (
279 Operand::Copy(p1) | Operand::Move(p1),
280 Operand::Copy(p2) | Operand::Move(p2),
281 ) => {
282 let ADT = AggregateKind::Adt(
283 self.ssatransformer.essa_def_id.clone(),
284 rustc_abi::VariantIdx::from_u32(0),
285 GenericArgs::empty(),
286 None,
287 None,
288 );
289 let place1 = Place::from(p1);
290 let place2 = Place::from(p2);
291 let rvalue1;
292 let rvalue2;
293 let mut operand1: IndexVec<_, _> = IndexVec::with_capacity(4);
294 let mut operand2: IndexVec<_, _> = IndexVec::with_capacity(4);
295
296 if value == 0 {
297 operand1.push(Operand::Copy(Place::from(p1)));
298 operand1.push(Operand::Copy(Place::from(p2)));
299 operand1.push(flip_cmp_operand.clone());
300 operand1.push(magic_number_operand.clone());
301
302 operand2.push(Operand::Copy(Place::from(p2)));
303 operand2.push(Operand::Copy(Place::from(p1)));
304 operand2.push(flip_reverse_cmp_operand.clone());
305 operand2.push(magic_number_operand.clone());
306 rvalue1 = Rvalue::Aggregate(Box::new(ADT.clone()), operand1);
311 rvalue2 = Rvalue::Aggregate(Box::new(ADT.clone()), operand2);
312 } else {
313 operand1.push(Operand::Copy(Place::from(p1)));
314 operand1.push(Operand::Copy(Place::from(p2)));
315 operand1.push(cmp_operand.clone());
316 operand1.push(magic_number_operand.clone());
317
318 operand2.push(Operand::Copy(Place::from(p2)));
319 operand2.push(Operand::Copy(Place::from(p1)));
320 operand2.push(reverse_cmp_operand.clone());
321 operand2.push(magic_number_operand.clone());
322 rvalue1 = Rvalue::Aggregate(Box::new(ADT.clone()), operand1);
327 rvalue2 = Rvalue::Aggregate(Box::new(ADT.clone()), operand2);
328 }
329
330 let assign_stmt1 = Statement {
331 source_info: SourceInfo::outermost(body.span),
332 kind: StatementKind::Assign(Box::new((place1, rvalue1))),
333 };
334 let assign_stmt2 = Statement {
335 source_info: SourceInfo::outermost(body.span),
336 kind: StatementKind::Assign(Box::new((place2, rvalue2))),
337 };
338 block_data.statements.insert(0, assign_stmt2);
339 block_data.statements.insert(0, assign_stmt1);
340
341 for i in 0..2 {
342 let essa_in_body = block_data.statements.get_mut(i).unwrap();
343 let essa_ptr = essa_in_body as *const _;
344 self.ssatransformer.essa_statements.insert(essa_ptr, true);
345 }
346 }
347 _ => panic!("Expected a place"),
348 };
349 }
350 (None, Some(_)) | (Some(_), None) => {
351 let mut operand: IndexVec<_, _> = IndexVec::with_capacity(3);
352
353 let place = match op1 {
354 Operand::Copy(p) | Operand::Move(p) => Place::from(p),
355 _ => panic!("Expected a place"),
356 };
357 operand.push(op1.clone());
358 operand.push(op2.clone());
359 let rvalue;
360 if value == 0 {
361 operand.push(flip_cmp_operand.clone());
362 } else {
363 operand.push(cmp_operand.clone());
364 }
365 let ADT = AggregateKind::Adt(
366 self.ssatransformer.essa_def_id.clone(),
367 rustc_abi::VariantIdx::from_u32(0),
368 GenericArgs::empty(),
369 None,
370 None,
371 );
372 rvalue = Rvalue::Aggregate(Box::new(ADT.clone()), operand);
373 let assign_stmt = Statement {
374 source_info: SourceInfo::outermost(body.span),
375 kind: StatementKind::Assign(Box::new((place, rvalue))),
376 };
377 block_data.statements.insert(0, assign_stmt);
378
379 for i in 0..1 {
380 let essa_in_body = block_data.statements.get_mut(i).unwrap();
381 let essa_ptr = essa_in_body as *const _;
382 self.ssatransformer.essa_statements.insert(essa_ptr, true);
383 }
384 }
385
386 (Some(_), Some(_)) => {}
387 }
388 };
389 }
390
391 }
393 pub fn flip(binOp: BinOp) -> BinOp {
394 match binOp {
395 BinOp::Lt => BinOp::Ge,
396 BinOp::Le => BinOp::Gt,
397 BinOp::Gt => BinOp::Le,
398 BinOp::Ge => BinOp::Lt,
399 BinOp::Eq => BinOp::Ne,
400 BinOp::Ne => BinOp::Eq,
401 _ => panic!("flip() called on non-comparison operator"),
402 }
403 }
404 pub fn reverse(binOp: BinOp) -> BinOp {
405 match binOp {
406 BinOp::Lt => BinOp::Gt,
407 BinOp::Le => BinOp::Ge,
408 BinOp::Gt => BinOp::Lt,
409 BinOp::Ge => BinOp::Le,
410 BinOp::Eq => BinOp::Ne,
411 BinOp::Ne => BinOp::Eq,
412 _ => panic!("flip() called on non-comparison operator"),
413 }
414 }
415 pub fn rename_variables(&mut self, body: &mut Body<'tcx>) {
416 for local in body.local_decls.indices() {
417 self.ssatransformer.reaching_def.insert(local, None);
418 }
419 let order = SSATransformer::depth_first_search_preorder(
422 &self.ssatransformer.dom_tree,
423 body.basic_blocks.indices().next().unwrap().clone(),
424 );
425 for bb in order {
426 self.process_basic_block(bb, body);
427 }
428 }
429
430 fn process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
431 self.rename_statement(bb, body);
432 self.rename_terminator(bb, body);
433 let terminator = body.basic_blocks[bb].terminator();
434 let successors: Vec<_> = terminator.successors().collect();
435 if let TerminatorKind::SwitchInt { .. } = &terminator.kind {
436 for succ_bb in successors.clone() {
437 self.process_essa_statments(succ_bb, body, bb);
438 }
439 }
440
441 for succ_bb in successors {
442 self.process_phi_functions(succ_bb, body, bb);
443 }
444 }
445 pub fn process_essa_statments(
446 &mut self,
447 succ_bb: BasicBlock,
448 body: &mut Body<'tcx>,
449 switch_bb: BasicBlock,
450 ) {
451 let switch_block_data = &body.basic_blocks[switch_bb];
452 if let Some(terminator) = &switch_block_data.terminator {
453 if let TerminatorKind::SwitchInt { discr, .. } = &terminator.kind {
454 if let Operand::Copy(switch_place) | Operand::Move(switch_place) = discr {
455 if let Some((op1, op2, cmp_op)) =
456 self.extract_condition(switch_place, switch_block_data)
457 {
458 if op2.constant().is_none() {
459 let essa_statement = body.basic_blocks.as_mut()[succ_bb]
460 .statements
461 .get_mut(0)
462 .unwrap();
463 match &mut essa_statement.kind {
464 StatementKind::Assign(box (place, rvalue)) => {
465 if let Rvalue::Aggregate(_, operands) = rvalue {
466 let loc_1: usize = 0;
467 let loc_2: usize = 1;
468
469 operands[FieldIdx::from_usize(loc_1)] = op1.clone();
470 operands[FieldIdx::from_usize(loc_2)] = op2.clone();
471 }
472 }
473 _ => {}
474 }
475 let essa_statement = body.basic_blocks.as_mut()[succ_bb]
476 .statements
477 .get_mut(1)
478 .unwrap();
479 match &mut essa_statement.kind {
480 StatementKind::Assign(box (place, rvalue)) => {
481 if let Rvalue::Aggregate(_, operands) = rvalue {
482 let loc_1: usize = 0;
483 let loc_2: usize = 1;
484 operands[FieldIdx::from_usize(loc_1)] = op2.clone();
485 operands[FieldIdx::from_usize(loc_2)] = op1.clone();
486 }
487 }
488 _ => {}
489 }
490 } else {
491 let essa_statement = body.basic_blocks.as_mut()[succ_bb]
492 .statements
493 .get_mut(0)
494 .unwrap();
495 match &mut essa_statement.kind {
496 StatementKind::Assign(box (place, rvalue)) => {
497 if let Rvalue::Aggregate(_, operands) = rvalue {
498 let loc: usize = 0;
499 operands[FieldIdx::from_usize(loc)] = op1.clone();
500 }
501 }
502 _ => {}
503 }
504 }
505 }
506 }
507 }
508 }
509 }
510
511 fn process_phi_functions(
512 &mut self,
513 succ_bb: BasicBlock,
514 body: &mut Body<'tcx>,
515 do_bb: BasicBlock,
516 ) {
517 for statement in body.basic_blocks.as_mut()[succ_bb].statements.iter_mut() {
518 let phi_stmt = statement as *const _;
519
520 if SSATransformer::is_phi_statement(&self.ssatransformer, statement) {
521 if let StatementKind::Assign(box (_, rvalue)) = &mut statement.kind {
522 if let Rvalue::Aggregate(_, operands) = rvalue {
523 let operand_count = operands.len();
524 let index = self
525 .ssatransformer
526 .phi_index
527 .entry(phi_stmt)
528 .or_insert(0)
529 .clone();
530
531 if index < operand_count {
532 match &mut operands[FieldIdx::from_usize(index)] {
534 Operand::Copy(place) | Operand::Move(place) => {
535 self.replace_place(place, &do_bb);
536 }
537 _ => {}
538 }
539 *self.ssatransformer.phi_index.entry(phi_stmt).or_insert(0) += 1;
540 }
544 }
545 }
546 }
547 }
548 }
549
550 pub fn rename_statement(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
551 for statement in body.basic_blocks.as_mut()[bb].statements.iter_mut() {
552 let is_phi = SSATransformer::is_phi_statement(&self.ssatransformer, statement);
554 let is_essa = SSATransformer::is_essa_statement(&self.ssatransformer, statement);
555 match &mut statement.kind {
556 StatementKind::Assign(box (place, rvalue)) => {
557 if !is_phi {
558 if !is_essa {
559 self.replace_rvalue(rvalue, &bb);
560 self.rename_local_def(place, &bb, true);
561 } else {
562 self.ssa_rename_local_def(place, &bb, true);
563 }
564 } else {
565 self.ssa_rename_local_def(place, &bb, false);
566 }
567 }
568 StatementKind::Deinit(place) | StatementKind::SetDiscriminant { place, .. } => {
570 }
574 StatementKind::StorageLive(local) => {
575 }
577 StatementKind::StorageDead(local) => {
578 }
580 _ => {}
581 }
582 }
583 }
584
585 fn rename_terminator(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
586 let terminator: &mut Terminator<'tcx> = body.basic_blocks.as_mut()[bb].terminator_mut();
587 match &mut terminator.kind {
588 TerminatorKind::Call {
589 args, destination, ..
590 } => {
591 for op in args.iter_mut() {
592 match &mut op.node {
593 Operand::Copy(place) | Operand::Move(place) => {
594 self.replace_place(place, &bb);
595 }
596 Operand::Constant(const_operand) => {}
597 }
598 }
599 self.rename_local_def(destination, &bb, true);
600 }
601 TerminatorKind::Assert { cond, .. } => {
602 self.replace_operand(cond, &bb);
603 }
604 TerminatorKind::Drop { place, .. } => {
605 self.replace_place(place, &bb);
606 }
607 TerminatorKind::SwitchInt { discr, .. } => {
608 self.replace_operand(discr, &bb);
609 }
610 _ => {}
611 }
612 }
613
614 fn replace_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, bb: &BasicBlock) {
615 match rvalue {
616 Rvalue::Use(operand)
617 | Rvalue::Repeat(operand, _)
618 | Rvalue::UnaryOp(_, operand)
619 | Rvalue::Cast(_, operand, _)
620 | Rvalue::ShallowInitBox(operand, _) => {
621 self.replace_operand(operand, &bb);
622 }
623 Rvalue::BinaryOp(_, box (lhs, rhs)) => {
624 self.replace_operand(lhs, &bb);
625 self.replace_operand(rhs, &bb);
626 }
627 Rvalue::Aggregate(_, operands) => {
628 for operand in operands {
629 self.replace_operand(operand, &bb);
630 }
631 }
632 _ => {}
633 }
634 }
635
636 fn replace_operand(&mut self, operand: &mut Operand<'tcx>, bb: &BasicBlock) {
637 match operand {
638 Operand::Copy(place) | Operand::Move(place) => {
639 self.replace_place(place, bb);
640 }
642 _ => {}
643 }
644 }
645
646 fn replace_place(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock) {
647 self.update_reachinf_def(&place.local, &bb);
649
650 if let Some(Some(reaching_local)) = self.ssatransformer.reaching_def.get(&place.local) {
651 let local = reaching_local.clone();
652 *place = Place::from(local);
653 } else {
654 }
655 }
656
657 fn ssa_rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
658 self.update_reachinf_def(&place.local, &bb);
660 let Place {
661 local: old_local,
662 projection: _,
663 } = place.clone();
664 let old_place = place.clone();
665 if old_local.as_u32() == 0 {
666 return;
667 }
668 let new_local = Local::from_usize(self.ssatransformer.local_index);
669 self.ssatransformer.local_index += 1;
670 let new_place: Place<'_> = Place::from(new_local);
671 *place = new_place.clone();
672
673 let _old_local = old_local.clone();
674 self.ssatransformer
675 .ssa_locals_map
676 .entry(old_place)
677 .or_insert_with(HashSet::new)
678 .insert(new_place);
679
680 self.ssatransformer
681 .local_defination_block
682 .insert(new_local.clone(), bb.clone());
683 let old_local_reaching = self
684 .ssatransformer
685 .reaching_def
686 .get(&_old_local.clone())
687 .unwrap();
688
689 self.ssatransformer
690 .reaching_def
691 .insert(new_local.clone(), *old_local_reaching);
692 self.ssatransformer
693 .reaching_def
694 .insert(_old_local.clone(), Some(new_local.clone()));
695
696 }
701 fn rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
702 self.update_reachinf_def(&place.local, &bb);
704 let Place {
705 local: old_local,
706 projection: _,
707 } = place.clone();
708 let old_place = place.clone();
709 if old_local.as_u32() == 0 {
710 return;
711 }
712 if self.ssatransformer.skipped.contains(&old_local.as_usize()) && not_phi {
713 self.ssatransformer.skipped.remove(&old_local.as_usize());
714 self.ssatransformer
715 .reaching_def
716 .insert(old_local, Some(old_local));
717 self.ssatransformer
718 .places_map
719 .entry(old_place)
720 .or_insert_with(HashSet::new)
721 .insert(old_place);
722 return;
723 }
724 let new_local = Local::from_usize(self.ssatransformer.local_index);
725 let new_place: Place<'_> = Place::from(new_local);
726
727 *place = new_place.clone();
728
729 if old_local.as_u32() == 0 {
731 return;
732 }
733
734 self.ssatransformer.local_index += 1;
735 self.ssatransformer
736 .places_map
737 .entry(old_place)
738 .or_insert_with(HashSet::new)
739 .insert(new_place);
740
741 let _old_local = old_local.clone();
742 self.ssatransformer
743 .local_defination_block
744 .insert(new_local.clone(), bb.clone());
745 let old_local_reaching = self
746 .ssatransformer
747 .reaching_def
748 .get(&_old_local.clone())
749 .unwrap();
750
751 self.ssatransformer
752 .reaching_def
753 .insert(new_local.clone(), *old_local_reaching);
754 self.ssatransformer
755 .reaching_def
756 .insert(_old_local.clone(), Some(new_local.clone()));
757
758 }
763
764 pub fn dominates_(&self, def_bb: &BasicBlock, bb: &BasicBlock) -> bool {
765 let mut visited = HashSet::new();
766
767 let mut stack = self.ssatransformer.dom_tree.get(def_bb).unwrap().clone();
768 while let Some(block) = stack.pop() {
769 if !visited.insert(block) {
770 continue;
771 }
772
773 if block == *bb {
774 return true;
775 }
776
777 if let Some(children) = self.ssatransformer.dom_tree.get(&block) {
778 stack.extend(children);
779 }
780 }
781
782 false
783 }
784 fn update_reachinf_def(&mut self, local: &Local, bb: &BasicBlock) {
785 let mut r = self.ssatransformer.reaching_def[local];
789 let mut dominate_bool = true;
790 if r != None {
791 let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
792 }
793
794 while !(r == None || dominate_bool) {
795 r = self.ssatransformer.reaching_def[&r.unwrap()];
796 if r != None {
797 let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
798
799 dominate_bool = self.dominates_(&def_bb, bb);
800 }
801 }
802
803 if let Some(entry) = self.ssatransformer.reaching_def.get_mut(local) {
804 *entry = r.clone();
805 }
806 }
807}
808
809