1 //! Data flow graph tracking Instructions, Values, and blocks. 2 3 use crate::entity::{self, PrimaryMap, SecondaryMap}; 4 use crate::ir; 5 use crate::ir::builder::ReplaceBuilder; 6 use crate::ir::dynamic_type::{DynamicTypeData, DynamicTypes}; 7 use crate::ir::instructions::{CallInfo, InstructionData}; 8 use crate::ir::pcc::Fact; 9 use crate::ir::{ 10 types, Block, BlockCall, ConstantData, ConstantPool, DynamicType, ExtFuncData, FuncRef, 11 Immediate, Inst, JumpTables, RelSourceLoc, SigRef, Signature, Type, Value, 12 ValueLabelAssignments, ValueList, ValueListPool, 13 }; 14 use crate::packed_option::ReservedValue; 15 use crate::write::write_operands; 16 use core::fmt; 17 use core::iter; 18 use core::mem; 19 use core::ops::{Index, IndexMut}; 20 use core::u16; 21 22 use alloc::collections::BTreeMap; 23 #[cfg(feature = "enable-serde")] 24 use serde_derive::{Deserialize, Serialize}; 25 use smallvec::SmallVec; 26 27 /// Storage for instructions within the DFG. 28 #[derive(Clone, PartialEq, Hash)] 29 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 30 pub struct Insts(PrimaryMap<Inst, InstructionData>); 31 32 /// Allow immutable access to instructions via indexing. 33 impl Index<Inst> for Insts { 34 type Output = InstructionData; 35 36 fn index(&self, inst: Inst) -> &InstructionData { 37 self.0.index(inst) 38 } 39 } 40 41 /// Allow mutable access to instructions via indexing. 42 impl IndexMut<Inst> for Insts { 43 fn index_mut(&mut self, inst: Inst) -> &mut InstructionData { 44 self.0.index_mut(inst) 45 } 46 } 47 48 /// Storage for basic blocks within the DFG. 49 #[derive(Clone, PartialEq, Hash)] 50 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 51 pub struct Blocks(PrimaryMap<Block, BlockData>); 52 53 impl Blocks { 54 /// Create a new basic block. 55 pub fn add(&mut self) -> Block { 56 self.0.push(BlockData::new()) 57 } 58 59 /// Get the total number of basic blocks created in this function, whether they are 60 /// currently inserted in the layout or not. 61 /// 62 /// This is intended for use with `SecondaryMap::with_capacity`. 63 pub fn len(&self) -> usize { 64 self.0.len() 65 } 66 67 /// Returns `true` if the given block reference is valid. 68 pub fn is_valid(&self, block: Block) -> bool { 69 self.0.is_valid(block) 70 } 71 } 72 73 impl Index<Block> for Blocks { 74 type Output = BlockData; 75 76 fn index(&self, block: Block) -> &BlockData { 77 &self.0[block] 78 } 79 } 80 81 impl IndexMut<Block> for Blocks { 82 fn index_mut(&mut self, block: Block) -> &mut BlockData { 83 &mut self.0[block] 84 } 85 } 86 87 /// A data flow graph defines all instructions and basic blocks in a function as well as 88 /// the data flow dependencies between them. The DFG also tracks values which can be either 89 /// instruction results or block parameters. 90 /// 91 /// The layout of blocks in the function and of instructions in each block is recorded by the 92 /// `Layout` data structure which forms the other half of the function representation. 93 /// 94 #[derive(Clone, PartialEq, Hash)] 95 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 96 pub struct DataFlowGraph { 97 /// Data about all of the instructions in the function, including opcodes and operands. 98 /// The instructions in this map are not in program order. That is tracked by `Layout`, along 99 /// with the block containing each instruction. 100 pub insts: Insts, 101 102 /// List of result values for each instruction. 103 /// 104 /// This map gets resized automatically by `make_inst()` so it is always in sync with the 105 /// primary `insts` map. 106 results: SecondaryMap<Inst, ValueList>, 107 108 /// basic blocks in the function and their parameters. 109 /// 110 /// This map is not in program order. That is handled by `Layout`, and so is the sequence of 111 /// instructions contained in each block. 112 pub blocks: Blocks, 113 114 /// Dynamic types created. 115 pub dynamic_types: DynamicTypes, 116 117 /// Memory pool of value lists. 118 /// 119 /// The `ValueList` references into this pool appear in many places: 120 /// 121 /// - Instructions in `insts` that don't have room for their entire argument list inline. 122 /// - Instruction result values in `results`. 123 /// - block parameters in `blocks`. 124 pub value_lists: ValueListPool, 125 126 /// Primary value table with entries for all values. 127 values: PrimaryMap<Value, ValueDataPacked>, 128 129 /// Facts: proof-carrying-code assertions about values. 130 pub facts: SecondaryMap<Value, Option<Fact>>, 131 132 /// Function signature table. These signatures are referenced by indirect call instructions as 133 /// well as the external function references. 134 pub signatures: PrimaryMap<SigRef, Signature>, 135 136 /// External function references. These are functions that can be called directly. 137 pub ext_funcs: PrimaryMap<FuncRef, ExtFuncData>, 138 139 /// Saves Value labels. 140 pub values_labels: Option<BTreeMap<Value, ValueLabelAssignments>>, 141 142 /// Constants used within the function. 143 pub constants: ConstantPool, 144 145 /// Stores large immediates that otherwise will not fit on InstructionData. 146 pub immediates: PrimaryMap<Immediate, ConstantData>, 147 148 /// Jump tables used in this function. 149 pub jump_tables: JumpTables, 150 } 151 152 impl DataFlowGraph { 153 /// Create a new empty `DataFlowGraph`. 154 pub fn new() -> Self { 155 Self { 156 insts: Insts(PrimaryMap::new()), 157 results: SecondaryMap::new(), 158 blocks: Blocks(PrimaryMap::new()), 159 dynamic_types: DynamicTypes::new(), 160 value_lists: ValueListPool::new(), 161 values: PrimaryMap::new(), 162 facts: SecondaryMap::new(), 163 signatures: PrimaryMap::new(), 164 ext_funcs: PrimaryMap::new(), 165 values_labels: None, 166 constants: ConstantPool::new(), 167 immediates: PrimaryMap::new(), 168 jump_tables: JumpTables::new(), 169 } 170 } 171 172 /// Clear everything. 173 pub fn clear(&mut self) { 174 self.insts.0.clear(); 175 self.results.clear(); 176 self.blocks.0.clear(); 177 self.dynamic_types.clear(); 178 self.value_lists.clear(); 179 self.values.clear(); 180 self.signatures.clear(); 181 self.ext_funcs.clear(); 182 self.values_labels = None; 183 self.constants.clear(); 184 self.immediates.clear(); 185 self.jump_tables.clear(); 186 self.facts.clear(); 187 } 188 189 /// Get the total number of instructions created in this function, whether they are currently 190 /// inserted in the layout or not. 191 /// 192 /// This is intended for use with `SecondaryMap::with_capacity`. 193 pub fn num_insts(&self) -> usize { 194 self.insts.0.len() 195 } 196 197 /// Returns `true` if the given instruction reference is valid. 198 pub fn inst_is_valid(&self, inst: Inst) -> bool { 199 self.insts.0.is_valid(inst) 200 } 201 202 /// Get the total number of basic blocks created in this function, whether they are 203 /// currently inserted in the layout or not. 204 /// 205 /// This is intended for use with `SecondaryMap::with_capacity`. 206 pub fn num_blocks(&self) -> usize { 207 self.blocks.len() 208 } 209 210 /// Returns `true` if the given block reference is valid. 211 pub fn block_is_valid(&self, block: Block) -> bool { 212 self.blocks.is_valid(block) 213 } 214 215 /// Make a BlockCall, bundling together the block and its arguments. 216 pub fn block_call(&mut self, block: Block, args: &[Value]) -> BlockCall { 217 BlockCall::new(block, args, &mut self.value_lists) 218 } 219 220 /// Get the total number of values. 221 pub fn num_values(&self) -> usize { 222 self.values.len() 223 } 224 225 /// Get an iterator over all values and their definitions. 226 pub fn values_and_defs(&self) -> impl Iterator<Item = (Value, ValueDef)> + '_ { 227 self.values().map(|value| (value, self.value_def(value))) 228 } 229 230 /// Starts collection of debug information. 231 pub fn collect_debug_info(&mut self) { 232 if self.values_labels.is_none() { 233 self.values_labels = Some(Default::default()); 234 } 235 } 236 237 /// Inserts a `ValueLabelAssignments::Alias` for `to_alias` if debug info 238 /// collection is enabled. 239 pub fn add_value_label_alias(&mut self, to_alias: Value, from: RelSourceLoc, value: Value) { 240 if let Some(values_labels) = self.values_labels.as_mut() { 241 values_labels.insert(to_alias, ir::ValueLabelAssignments::Alias { from, value }); 242 } 243 } 244 } 245 246 /// Resolve value aliases. 247 /// 248 /// Find the original SSA value that `value` aliases, or None if an 249 /// alias cycle is detected. 250 fn maybe_resolve_aliases( 251 values: &PrimaryMap<Value, ValueDataPacked>, 252 value: Value, 253 ) -> Option<Value> { 254 let mut v = value; 255 256 // Note that values may be empty here. 257 for _ in 0..=values.len() { 258 if let ValueData::Alias { original, .. } = ValueData::from(values[v]) { 259 v = original; 260 } else { 261 return Some(v); 262 } 263 } 264 265 None 266 } 267 268 /// Resolve value aliases. 269 /// 270 /// Find the original SSA value that `value` aliases. 271 fn resolve_aliases(values: &PrimaryMap<Value, ValueDataPacked>, value: Value) -> Value { 272 if let Some(v) = maybe_resolve_aliases(values, value) { 273 v 274 } else { 275 panic!("Value alias loop detected for {}", value); 276 } 277 } 278 279 /// Iterator over all Values in a DFG. 280 pub struct Values<'a> { 281 inner: entity::Iter<'a, Value, ValueDataPacked>, 282 } 283 284 /// Check for non-values. 285 fn valid_valuedata(data: ValueDataPacked) -> bool { 286 let data = ValueData::from(data); 287 if let ValueData::Alias { 288 ty: types::INVALID, 289 original, 290 } = ValueData::from(data) 291 { 292 if original == Value::reserved_value() { 293 return false; 294 } 295 } 296 true 297 } 298 299 impl<'a> Iterator for Values<'a> { 300 type Item = Value; 301 302 fn next(&mut self) -> Option<Self::Item> { 303 self.inner 304 .by_ref() 305 .find(|kv| valid_valuedata(*kv.1)) 306 .map(|kv| kv.0) 307 } 308 } 309 310 /// Handling values. 311 /// 312 /// Values are either block parameters or instruction results. 313 impl DataFlowGraph { 314 /// Allocate an extended value entry. 315 fn make_value(&mut self, data: ValueData) -> Value { 316 self.values.push(data.into()) 317 } 318 319 /// Get an iterator over all values. 320 pub fn values<'a>(&'a self) -> Values { 321 Values { 322 inner: self.values.iter(), 323 } 324 } 325 326 /// Check if a value reference is valid. 327 pub fn value_is_valid(&self, v: Value) -> bool { 328 self.values.is_valid(v) 329 } 330 331 /// Check whether a value is valid and not an alias. 332 pub fn value_is_real(&self, value: Value) -> bool { 333 // Deleted or unused values are also stored as aliases so this excludes 334 // those as well. 335 self.value_is_valid(value) && !matches!(self.values[value].into(), ValueData::Alias { .. }) 336 } 337 338 /// Get the type of a value. 339 pub fn value_type(&self, v: Value) -> Type { 340 self.values[v].ty() 341 } 342 343 /// Get the definition of a value. 344 /// 345 /// This is either the instruction that defined it or the Block that has the value as an 346 /// parameter. 347 pub fn value_def(&self, v: Value) -> ValueDef { 348 match ValueData::from(self.values[v]) { 349 ValueData::Inst { inst, num, .. } => ValueDef::Result(inst, num as usize), 350 ValueData::Param { block, num, .. } => ValueDef::Param(block, num as usize), 351 ValueData::Alias { original, .. } => { 352 // Make sure we only recurse one level. `resolve_aliases` has safeguards to 353 // detect alias loops without overrunning the stack. 354 self.value_def(self.resolve_aliases(original)) 355 } 356 ValueData::Union { x, y, .. } => ValueDef::Union(x, y), 357 } 358 } 359 360 /// Determine if `v` is an attached instruction result / block parameter. 361 /// 362 /// An attached value can't be attached to something else without first being detached. 363 /// 364 /// Value aliases are not considered to be attached to anything. Use `resolve_aliases()` to 365 /// determine if the original aliased value is attached. 366 pub fn value_is_attached(&self, v: Value) -> bool { 367 use self::ValueData::*; 368 match ValueData::from(self.values[v]) { 369 Inst { inst, num, .. } => Some(&v) == self.inst_results(inst).get(num as usize), 370 Param { block, num, .. } => Some(&v) == self.block_params(block).get(num as usize), 371 Alias { .. } => false, 372 Union { .. } => false, 373 } 374 } 375 376 /// Resolve value aliases. 377 /// 378 /// Find the original SSA value that `value` aliases. 379 pub fn resolve_aliases(&self, value: Value) -> Value { 380 resolve_aliases(&self.values, value) 381 } 382 383 /// Replace all uses of value aliases with their resolved values, and delete 384 /// the aliases. 385 pub fn resolve_all_aliases(&mut self) { 386 let invalid_value = ValueDataPacked::from(ValueData::Alias { 387 ty: types::INVALID, 388 original: Value::reserved_value(), 389 }); 390 391 // Rewrite each chain of aliases. Update every alias along the chain 392 // into an alias directly to the final value. Due to updating every 393 // alias that it looks at, this loop runs in time linear in the number 394 // of values. 395 for mut src in self.values.keys() { 396 let value_data = self.values[src]; 397 if value_data == invalid_value { 398 continue; 399 } 400 if let ValueData::Alias { mut original, .. } = value_data.into() { 401 // We don't use the type after this, we just need some place to 402 // store the resolved aliases temporarily. 403 let resolved = ValueDataPacked::from(ValueData::Alias { 404 ty: types::INVALID, 405 original: resolve_aliases(&self.values, original), 406 }); 407 // Walk the chain again, splatting the new alias everywhere. 408 // resolve_aliases panics if there's an alias cycle, so we don't 409 // need to guard against cycles here. 410 loop { 411 self.values[src] = resolved; 412 src = original; 413 if let ValueData::Alias { original: next, .. } = self.values[src].into() { 414 original = next; 415 } else { 416 break; 417 } 418 } 419 } 420 } 421 422 // Now aliases don't point to other aliases, so we can replace any use 423 // of an alias with the final value in constant time. 424 425 // Rewrite InstructionData in `self.insts`. 426 for inst in self.insts.0.values_mut() { 427 inst.map_values(&mut self.value_lists, &mut self.jump_tables, |arg| { 428 if let ValueData::Alias { original, .. } = self.values[arg].into() { 429 original 430 } else { 431 arg 432 } 433 }); 434 } 435 436 // - `results` and block-params in `blocks` are not aliases, by 437 // definition. 438 // - `dynamic_types` has no values. 439 // - `value_lists` can only be accessed via references from elsewhere. 440 // - `values` only has value references in aliases (which we've 441 // removed), and unions (but the egraph pass ensures there are no 442 // aliases before creating unions). 443 444 // Merge `facts` from any alias onto the aliased value. Note that if 445 // there was a chain of aliases, at this point every alias that was in 446 // the chain points to the same final value, so their facts will all be 447 // merged together. 448 for value in self.facts.keys() { 449 if let ValueData::Alias { original, .. } = self.values[value].into() { 450 if let Some(new_fact) = self.facts[value].take() { 451 match &mut self.facts[original] { 452 Some(old_fact) => *old_fact = Fact::intersect(old_fact, &new_fact), 453 old_fact => *old_fact = Some(new_fact), 454 } 455 } 456 } 457 } 458 459 // - `signatures` and `ext_funcs` have no values. 460 461 if let Some(values_labels) = &mut self.values_labels { 462 // Debug info is best-effort. If any is attached to value aliases, 463 // just discard it. 464 values_labels.retain(|&k, _| !matches!(self.values[k].into(), ValueData::Alias { .. })); 465 466 // If debug-info says a value should have the same labels as another 467 // value, then make sure that target is not a value alias. 468 for value_label in values_labels.values_mut() { 469 if let ValueLabelAssignments::Alias { value, .. } = value_label { 470 if let ValueData::Alias { original, .. } = self.values[*value].into() { 471 *value = original; 472 } 473 } 474 } 475 } 476 477 // - `constants` and `immediates` have no values. 478 // - `jump_tables` is updated together with instruction-data above. 479 480 // Delete all aliases now that there are no uses left. 481 for value in self.values.values_mut() { 482 if let ValueData::Alias { .. } = ValueData::from(*value) { 483 *value = invalid_value; 484 } 485 } 486 } 487 488 /// Turn a value into an alias of another. 489 /// 490 /// Change the `dest` value to behave as an alias of `src`. This means that all uses of `dest` 491 /// will behave as if they used that value `src`. 492 /// 493 /// The `dest` value can't be attached to an instruction or block. 494 pub fn change_to_alias(&mut self, dest: Value, src: Value) { 495 debug_assert!(!self.value_is_attached(dest)); 496 // Try to create short alias chains by finding the original source value. 497 // This also avoids the creation of loops. 498 let original = self.resolve_aliases(src); 499 debug_assert_ne!( 500 dest, original, 501 "Aliasing {} to {} would create a loop", 502 dest, src 503 ); 504 let ty = self.value_type(original); 505 debug_assert_eq!( 506 self.value_type(dest), 507 ty, 508 "Aliasing {} to {} would change its type {} to {}", 509 dest, 510 src, 511 self.value_type(dest), 512 ty 513 ); 514 debug_assert_ne!(ty, types::INVALID); 515 516 self.values[dest] = ValueData::Alias { ty, original }.into(); 517 } 518 519 /// Replace the results of one instruction with aliases to the results of another. 520 /// 521 /// Change all the results of `dest_inst` to behave as aliases of 522 /// corresponding results of `src_inst`, as if calling change_to_alias for 523 /// each. 524 /// 525 /// After calling this instruction, `dest_inst` will have had its results 526 /// cleared, so it likely needs to be removed from the graph. 527 /// 528 pub fn replace_with_aliases(&mut self, dest_inst: Inst, original_inst: Inst) { 529 debug_assert_ne!( 530 dest_inst, original_inst, 531 "Replacing {} with itself would create a loop", 532 dest_inst 533 ); 534 535 let dest_results = self.results[dest_inst].as_slice(&self.value_lists); 536 let original_results = self.results[original_inst].as_slice(&self.value_lists); 537 538 debug_assert_eq!( 539 dest_results.len(), 540 original_results.len(), 541 "Replacing {} with {} would produce a different number of results.", 542 dest_inst, 543 original_inst 544 ); 545 546 for (&dest, &original) in dest_results.iter().zip(original_results) { 547 let ty = self.value_type(original); 548 debug_assert_eq!( 549 self.value_type(dest), 550 ty, 551 "Aliasing {} to {} would change its type {} to {}", 552 dest, 553 original, 554 self.value_type(dest), 555 ty 556 ); 557 debug_assert_ne!(ty, types::INVALID); 558 559 self.values[dest] = ValueData::Alias { ty, original }.into(); 560 } 561 562 self.clear_results(dest_inst); 563 } 564 } 565 566 /// Where did a value come from? 567 #[derive(Clone, Copy, Debug, PartialEq, Eq)] 568 pub enum ValueDef { 569 /// Value is the n'th result of an instruction. 570 Result(Inst, usize), 571 /// Value is the n'th parameter to a block. 572 Param(Block, usize), 573 /// Value is a union of two other values. 574 Union(Value, Value), 575 } 576 577 impl ValueDef { 578 /// Unwrap the instruction where the value was defined, or panic. 579 pub fn unwrap_inst(&self) -> Inst { 580 self.inst().expect("Value is not an instruction result") 581 } 582 583 /// Get the instruction where the value was defined, if any. 584 pub fn inst(&self) -> Option<Inst> { 585 match *self { 586 Self::Result(inst, _) => Some(inst), 587 _ => None, 588 } 589 } 590 591 /// Unwrap the block there the parameter is defined, or panic. 592 pub fn unwrap_block(&self) -> Block { 593 match *self { 594 Self::Param(block, _) => block, 595 _ => panic!("Value is not a block parameter"), 596 } 597 } 598 599 /// Get the number component of this definition. 600 /// 601 /// When multiple values are defined at the same program point, this indicates the index of 602 /// this value. 603 pub fn num(self) -> usize { 604 match self { 605 Self::Result(_, n) | Self::Param(_, n) => n, 606 Self::Union(_, _) => 0, 607 } 608 } 609 } 610 611 /// Internal table storage for extended values. 612 #[derive(Clone, Debug, PartialEq, Hash)] 613 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 614 enum ValueData { 615 /// Value is defined by an instruction. 616 Inst { ty: Type, num: u16, inst: Inst }, 617 618 /// Value is a block parameter. 619 Param { ty: Type, num: u16, block: Block }, 620 621 /// Value is an alias of another value. 622 /// An alias value can't be linked as an instruction result or block parameter. It is used as a 623 /// placeholder when the original instruction or block has been rewritten or modified. 624 Alias { ty: Type, original: Value }, 625 626 /// Union is a "fork" in representation: the value can be 627 /// represented as either of the values named here. This is used 628 /// for aegraph (acyclic egraph) representation in the DFG. 629 Union { ty: Type, x: Value, y: Value }, 630 } 631 632 /// Bit-packed version of ValueData, for efficiency. 633 /// 634 /// Layout: 635 /// 636 /// ```plain 637 /// | tag:2 | type:14 | x:24 | y:24 | 638 /// 639 /// Inst 00 ty inst output inst index 640 /// Param 01 ty blockparam num block index 641 /// Alias 10 ty 0 value index 642 /// Union 11 ty first value second value 643 /// ``` 644 #[derive(Clone, Copy, Debug, PartialEq, Hash)] 645 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 646 struct ValueDataPacked(u64); 647 648 /// Encodes a value in 0..2^32 into 0..2^n, where n is less than 32 649 /// (and is implied by `mask`), by translating 2^32-1 (0xffffffff) 650 /// into 2^n-1 and panic'ing on 2^n..2^32-1. 651 fn encode_narrow_field(x: u32, bits: u8) -> u32 { 652 let max = (1 << bits) - 1; 653 if x == 0xffff_ffff { 654 max 655 } else { 656 debug_assert!( 657 x < max, 658 "{x} does not fit into {bits} bits (must be less than {max} to \ 659 allow for a 0xffffffff sentinal)" 660 ); 661 x 662 } 663 } 664 665 /// The inverse of the above `encode_narrow_field`: unpacks 2^n-1 into 666 /// 2^32-1. 667 fn decode_narrow_field(x: u32, bits: u8) -> u32 { 668 if x == (1 << bits) - 1 { 669 0xffff_ffff 670 } else { 671 x 672 } 673 } 674 675 impl ValueDataPacked { 676 const Y_SHIFT: u8 = 0; 677 const Y_BITS: u8 = 24; 678 const X_SHIFT: u8 = Self::Y_SHIFT + Self::Y_BITS; 679 const X_BITS: u8 = 24; 680 const TYPE_SHIFT: u8 = Self::X_SHIFT + Self::X_BITS; 681 const TYPE_BITS: u8 = 14; 682 const TAG_SHIFT: u8 = Self::TYPE_SHIFT + Self::TYPE_BITS; 683 const TAG_BITS: u8 = 2; 684 685 const TAG_INST: u64 = 0; 686 const TAG_PARAM: u64 = 1; 687 const TAG_ALIAS: u64 = 2; 688 const TAG_UNION: u64 = 3; 689 690 fn make(tag: u64, ty: Type, x: u32, y: u32) -> ValueDataPacked { 691 debug_assert!(tag < (1 << Self::TAG_BITS)); 692 debug_assert!(ty.repr() < (1 << Self::TYPE_BITS)); 693 694 let x = encode_narrow_field(x, Self::X_BITS); 695 let y = encode_narrow_field(y, Self::Y_BITS); 696 697 ValueDataPacked( 698 (tag << Self::TAG_SHIFT) 699 | ((ty.repr() as u64) << Self::TYPE_SHIFT) 700 | ((x as u64) << Self::X_SHIFT) 701 | ((y as u64) << Self::Y_SHIFT), 702 ) 703 } 704 705 #[inline(always)] 706 fn field(self, shift: u8, bits: u8) -> u64 { 707 (self.0 >> shift) & ((1 << bits) - 1) 708 } 709 710 #[inline(always)] 711 fn ty(self) -> Type { 712 let ty = self.field(ValueDataPacked::TYPE_SHIFT, ValueDataPacked::TYPE_BITS) as u16; 713 Type::from_repr(ty) 714 } 715 716 #[inline(always)] 717 fn set_type(&mut self, ty: Type) { 718 self.0 &= !(((1 << Self::TYPE_BITS) - 1) << Self::TYPE_SHIFT); 719 self.0 |= (ty.repr() as u64) << Self::TYPE_SHIFT; 720 } 721 } 722 723 impl From<ValueData> for ValueDataPacked { 724 fn from(data: ValueData) -> Self { 725 match data { 726 ValueData::Inst { ty, num, inst } => { 727 Self::make(Self::TAG_INST, ty, num.into(), inst.as_bits()) 728 } 729 ValueData::Param { ty, num, block } => { 730 Self::make(Self::TAG_PARAM, ty, num.into(), block.as_bits()) 731 } 732 ValueData::Alias { ty, original } => { 733 Self::make(Self::TAG_ALIAS, ty, 0, original.as_bits()) 734 } 735 ValueData::Union { ty, x, y } => { 736 Self::make(Self::TAG_UNION, ty, x.as_bits(), y.as_bits()) 737 } 738 } 739 } 740 } 741 742 impl From<ValueDataPacked> for ValueData { 743 fn from(data: ValueDataPacked) -> Self { 744 let tag = data.field(ValueDataPacked::TAG_SHIFT, ValueDataPacked::TAG_BITS); 745 let ty = u16::try_from(data.field(ValueDataPacked::TYPE_SHIFT, ValueDataPacked::TYPE_BITS)) 746 .expect("Mask should ensure result fits in a u16"); 747 let x = u32::try_from(data.field(ValueDataPacked::X_SHIFT, ValueDataPacked::X_BITS)) 748 .expect("Mask should ensure result fits in a u32"); 749 let y = u32::try_from(data.field(ValueDataPacked::Y_SHIFT, ValueDataPacked::Y_BITS)) 750 .expect("Mask should ensure result fits in a u32"); 751 752 let ty = Type::from_repr(ty); 753 match tag { 754 ValueDataPacked::TAG_INST => ValueData::Inst { 755 ty, 756 num: u16::try_from(x).expect("Inst result num should fit in u16"), 757 inst: Inst::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)), 758 }, 759 ValueDataPacked::TAG_PARAM => ValueData::Param { 760 ty, 761 num: u16::try_from(x).expect("Blockparam index should fit in u16"), 762 block: Block::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)), 763 }, 764 ValueDataPacked::TAG_ALIAS => ValueData::Alias { 765 ty, 766 original: Value::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)), 767 }, 768 ValueDataPacked::TAG_UNION => ValueData::Union { 769 ty, 770 x: Value::from_bits(decode_narrow_field(x, ValueDataPacked::X_BITS)), 771 y: Value::from_bits(decode_narrow_field(y, ValueDataPacked::Y_BITS)), 772 }, 773 _ => panic!("Invalid tag {} in ValueDataPacked 0x{:x}", tag, data.0), 774 } 775 } 776 } 777 778 /// Instructions. 779 /// 780 impl DataFlowGraph { 781 /// Create a new instruction. 782 /// 783 /// The type of the first result is indicated by `data.ty`. If the 784 /// instruction produces multiple results, also call 785 /// `make_inst_results` to allocate value table entries. (It is 786 /// always safe to call `make_inst_results`, regardless of how 787 /// many results the instruction has.) 788 pub fn make_inst(&mut self, data: InstructionData) -> Inst { 789 let n = self.num_insts() + 1; 790 self.results.resize(n); 791 self.insts.0.push(data) 792 } 793 794 /// Declares a dynamic vector type 795 pub fn make_dynamic_ty(&mut self, data: DynamicTypeData) -> DynamicType { 796 self.dynamic_types.push(data) 797 } 798 799 /// Returns an object that displays `inst`. 800 pub fn display_inst<'a>(&'a self, inst: Inst) -> DisplayInst<'a> { 801 DisplayInst(self, inst) 802 } 803 804 /// Returns an object that displays the given `value`'s defining instruction. 805 /// 806 /// Panics if the value is not defined by an instruction (i.e. it is a basic 807 /// block argument). 808 pub fn display_value_inst(&self, value: Value) -> DisplayInst<'_> { 809 match self.value_def(value) { 810 ir::ValueDef::Result(inst, _) => self.display_inst(inst), 811 ir::ValueDef::Param(_, _) => panic!("value is not defined by an instruction"), 812 ir::ValueDef::Union(_, _) => panic!("value is a union of two other values"), 813 } 814 } 815 816 /// Construct a read-only visitor context for the values of this instruction. 817 pub fn inst_values<'dfg>( 818 &'dfg self, 819 inst: Inst, 820 ) -> impl DoubleEndedIterator<Item = Value> + 'dfg { 821 self.inst_args(inst) 822 .iter() 823 .chain( 824 self.insts[inst] 825 .branch_destination(&self.jump_tables) 826 .into_iter() 827 .flat_map(|branch| branch.args_slice(&self.value_lists).iter()), 828 ) 829 .copied() 830 } 831 832 /// Map a function over the values of the instruction. 833 pub fn map_inst_values<F>(&mut self, inst: Inst, body: F) 834 where 835 F: FnMut(Value) -> Value, 836 { 837 self.insts[inst].map_values(&mut self.value_lists, &mut self.jump_tables, body); 838 } 839 840 /// Overwrite the instruction's value references with values from the iterator. 841 /// NOTE: the iterator provided is expected to yield at least as many values as the instruction 842 /// currently has. 843 pub fn overwrite_inst_values<I>(&mut self, inst: Inst, mut values: I) 844 where 845 I: Iterator<Item = Value>, 846 { 847 self.insts[inst].map_values(&mut self.value_lists, &mut self.jump_tables, |_| { 848 values.next().unwrap() 849 }); 850 } 851 852 /// Get all value arguments on `inst` as a slice. 853 pub fn inst_args(&self, inst: Inst) -> &[Value] { 854 self.insts[inst].arguments(&self.value_lists) 855 } 856 857 /// Get all value arguments on `inst` as a mutable slice. 858 pub fn inst_args_mut(&mut self, inst: Inst) -> &mut [Value] { 859 self.insts[inst].arguments_mut(&mut self.value_lists) 860 } 861 862 /// Get the fixed value arguments on `inst` as a slice. 863 pub fn inst_fixed_args(&self, inst: Inst) -> &[Value] { 864 let num_fixed_args = self.insts[inst] 865 .opcode() 866 .constraints() 867 .num_fixed_value_arguments(); 868 &self.inst_args(inst)[..num_fixed_args] 869 } 870 871 /// Get the fixed value arguments on `inst` as a mutable slice. 872 pub fn inst_fixed_args_mut(&mut self, inst: Inst) -> &mut [Value] { 873 let num_fixed_args = self.insts[inst] 874 .opcode() 875 .constraints() 876 .num_fixed_value_arguments(); 877 &mut self.inst_args_mut(inst)[..num_fixed_args] 878 } 879 880 /// Get the variable value arguments on `inst` as a slice. 881 pub fn inst_variable_args(&self, inst: Inst) -> &[Value] { 882 let num_fixed_args = self.insts[inst] 883 .opcode() 884 .constraints() 885 .num_fixed_value_arguments(); 886 &self.inst_args(inst)[num_fixed_args..] 887 } 888 889 /// Get the variable value arguments on `inst` as a mutable slice. 890 pub fn inst_variable_args_mut(&mut self, inst: Inst) -> &mut [Value] { 891 let num_fixed_args = self.insts[inst] 892 .opcode() 893 .constraints() 894 .num_fixed_value_arguments(); 895 &mut self.inst_args_mut(inst)[num_fixed_args..] 896 } 897 898 /// Create result values for an instruction that produces multiple results. 899 /// 900 /// Instructions that produce no result values only need to be created with `make_inst`, 901 /// otherwise call `make_inst_results` to allocate value table entries for the results. 902 /// 903 /// The result value types are determined from the instruction's value type constraints and the 904 /// provided `ctrl_typevar` type for polymorphic instructions. For non-polymorphic 905 /// instructions, `ctrl_typevar` is ignored, and `INVALID` can be used. 906 /// 907 /// The type of the first result value is also set, even if it was already set in the 908 /// `InstructionData` passed to `make_inst`. If this function is called with a single-result 909 /// instruction, that is the only effect. 910 pub fn make_inst_results(&mut self, inst: Inst, ctrl_typevar: Type) -> usize { 911 self.make_inst_results_reusing(inst, ctrl_typevar, iter::empty()) 912 } 913 914 /// Create result values for `inst`, reusing the provided detached values. 915 /// 916 /// Create a new set of result values for `inst` using `ctrl_typevar` to determine the result 917 /// types. Any values provided by `reuse` will be reused. When `reuse` is exhausted or when it 918 /// produces `None`, a new value is created. 919 pub fn make_inst_results_reusing<I>( 920 &mut self, 921 inst: Inst, 922 ctrl_typevar: Type, 923 reuse: I, 924 ) -> usize 925 where 926 I: Iterator<Item = Option<Value>>, 927 { 928 self.clear_results(inst); 929 930 let mut reuse = reuse.fuse(); 931 let result_tys: SmallVec<[_; 16]> = self.inst_result_types(inst, ctrl_typevar).collect(); 932 933 for (expected, &ty) in result_tys.iter().enumerate() { 934 let num = u16::try_from(expected).expect("Result value index should fit in u16"); 935 let value_data = ValueData::Inst { ty, num, inst }; 936 let v = if let Some(Some(v)) = reuse.next() { 937 debug_assert_eq!(self.value_type(v), ty, "Reused {} is wrong type", ty); 938 debug_assert!(!self.value_is_attached(v)); 939 self.values[v] = value_data.into(); 940 v 941 } else { 942 self.make_value(value_data) 943 }; 944 let actual = self.results[inst].push(v, &mut self.value_lists); 945 debug_assert_eq!(expected, actual); 946 } 947 948 result_tys.len() 949 } 950 951 /// Create a `ReplaceBuilder` that will replace `inst` with a new instruction in place. 952 pub fn replace(&mut self, inst: Inst) -> ReplaceBuilder { 953 ReplaceBuilder::new(self, inst) 954 } 955 956 /// Clear the list of result values from `inst`. 957 /// 958 /// This leaves `inst` without any result values. New result values can be created by calling 959 /// `make_inst_results` or by using a `replace(inst)` builder. 960 pub fn clear_results(&mut self, inst: Inst) { 961 self.results[inst].clear(&mut self.value_lists) 962 } 963 964 /// Replace an instruction result with a new value of type `new_type`. 965 /// 966 /// The `old_value` must be an attached instruction result. 967 /// 968 /// The old value is left detached, so it should probably be changed into something else. 969 /// 970 /// Returns the new value. 971 pub fn replace_result(&mut self, old_value: Value, new_type: Type) -> Value { 972 let (num, inst) = match ValueData::from(self.values[old_value]) { 973 ValueData::Inst { num, inst, .. } => (num, inst), 974 _ => panic!("{} is not an instruction result value", old_value), 975 }; 976 let new_value = self.make_value(ValueData::Inst { 977 ty: new_type, 978 num, 979 inst, 980 }); 981 let num = num as usize; 982 let attached = mem::replace( 983 self.results[inst] 984 .get_mut(num, &mut self.value_lists) 985 .expect("Replacing detached result"), 986 new_value, 987 ); 988 debug_assert_eq!( 989 attached, 990 old_value, 991 "{} wasn't detached from {}", 992 old_value, 993 self.display_inst(inst) 994 ); 995 new_value 996 } 997 998 /// Clone an instruction, attaching new result `Value`s and 999 /// returning them. 1000 pub fn clone_inst(&mut self, inst: Inst) -> Inst { 1001 // First, add a clone of the InstructionData. 1002 let inst_data = self.insts[inst].clone(); 1003 // If the `inst_data` has a reference to a ValueList, clone it 1004 // as well, because we can't share these (otherwise mutating 1005 // one would affect the other). 1006 let inst_data = inst_data.deep_clone(&mut self.value_lists); 1007 let new_inst = self.make_inst(inst_data); 1008 // Get the controlling type variable. 1009 let ctrl_typevar = self.ctrl_typevar(inst); 1010 // Create new result values. 1011 let num_results = self.make_inst_results(new_inst, ctrl_typevar); 1012 // Copy over PCC facts, if any. 1013 for i in 0..num_results { 1014 let old_result = self.inst_results(inst)[i]; 1015 let new_result = self.inst_results(new_inst)[i]; 1016 self.facts[new_result] = self.facts[old_result].clone(); 1017 } 1018 new_inst 1019 } 1020 1021 /// Get the first result of an instruction. 1022 /// 1023 /// This function panics if the instruction doesn't have any result. 1024 pub fn first_result(&self, inst: Inst) -> Value { 1025 self.results[inst] 1026 .first(&self.value_lists) 1027 .expect("Instruction has no results") 1028 } 1029 1030 /// Test if `inst` has any result values currently. 1031 pub fn has_results(&self, inst: Inst) -> bool { 1032 !self.results[inst].is_empty() 1033 } 1034 1035 /// Return all the results of an instruction. 1036 pub fn inst_results(&self, inst: Inst) -> &[Value] { 1037 self.results[inst].as_slice(&self.value_lists) 1038 } 1039 1040 /// Return all the results of an instruction as ValueList. 1041 pub fn inst_results_list(&self, inst: Inst) -> ValueList { 1042 self.results[inst] 1043 } 1044 1045 /// Create a union of two values. 1046 pub fn union(&mut self, x: Value, y: Value) -> Value { 1047 // Get the type. 1048 let ty = self.value_type(x); 1049 debug_assert_eq!(ty, self.value_type(y)); 1050 self.make_value(ValueData::Union { ty, x, y }) 1051 } 1052 1053 /// Get the call signature of a direct or indirect call instruction. 1054 /// Returns `None` if `inst` is not a call instruction. 1055 pub fn call_signature(&self, inst: Inst) -> Option<SigRef> { 1056 match self.insts[inst].analyze_call(&self.value_lists) { 1057 CallInfo::NotACall => None, 1058 CallInfo::Direct(f, _) => Some(self.ext_funcs[f].signature), 1059 CallInfo::Indirect(s, _) => Some(s), 1060 } 1061 } 1062 1063 /// Like `call_signature` but returns none for tail call instructions. 1064 fn non_tail_call_signature(&self, inst: Inst) -> Option<SigRef> { 1065 let sig = self.call_signature(inst)?; 1066 match self.insts[inst].opcode() { 1067 ir::Opcode::ReturnCall | ir::Opcode::ReturnCallIndirect => None, 1068 _ => Some(sig), 1069 } 1070 } 1071 1072 // Only for use by the verifier. Everyone else should just use 1073 // `dfg.inst_results(inst).len()`. 1074 pub(crate) fn num_expected_results_for_verifier(&self, inst: Inst) -> usize { 1075 match self.non_tail_call_signature(inst) { 1076 Some(sig) => self.signatures[sig].returns.len(), 1077 None => { 1078 let constraints = self.insts[inst].opcode().constraints(); 1079 constraints.num_fixed_results() 1080 } 1081 } 1082 } 1083 1084 /// Get the result types of the given instruction. 1085 pub fn inst_result_types<'a>( 1086 &'a self, 1087 inst: Inst, 1088 ctrl_typevar: Type, 1089 ) -> impl iter::ExactSizeIterator<Item = Type> + 'a { 1090 return match self.non_tail_call_signature(inst) { 1091 Some(sig) => InstResultTypes::Signature(self, sig, 0), 1092 None => { 1093 let constraints = self.insts[inst].opcode().constraints(); 1094 InstResultTypes::Constraints(constraints, ctrl_typevar, 0) 1095 } 1096 }; 1097 1098 enum InstResultTypes<'a> { 1099 Signature(&'a DataFlowGraph, SigRef, usize), 1100 Constraints(ir::instructions::OpcodeConstraints, Type, usize), 1101 } 1102 1103 impl Iterator for InstResultTypes<'_> { 1104 type Item = Type; 1105 1106 fn next(&mut self) -> Option<Type> { 1107 match self { 1108 InstResultTypes::Signature(dfg, sig, i) => { 1109 let param = dfg.signatures[*sig].returns.get(*i)?; 1110 *i += 1; 1111 Some(param.value_type) 1112 } 1113 InstResultTypes::Constraints(constraints, ctrl_ty, i) => { 1114 if *i < constraints.num_fixed_results() { 1115 let ty = constraints.result_type(*i, *ctrl_ty); 1116 *i += 1; 1117 Some(ty) 1118 } else { 1119 None 1120 } 1121 } 1122 } 1123 } 1124 1125 fn size_hint(&self) -> (usize, Option<usize>) { 1126 let len = match self { 1127 InstResultTypes::Signature(dfg, sig, i) => { 1128 dfg.signatures[*sig].returns.len() - *i 1129 } 1130 InstResultTypes::Constraints(constraints, _, i) => { 1131 constraints.num_fixed_results() - *i 1132 } 1133 }; 1134 (len, Some(len)) 1135 } 1136 } 1137 1138 impl ExactSizeIterator for InstResultTypes<'_> {} 1139 } 1140 1141 /// Compute the type of an instruction result from opcode constraints and call signatures. 1142 /// 1143 /// This computes the same sequence of result types that `make_inst_results()` above would 1144 /// assign to the created result values, but it does not depend on `make_inst_results()` being 1145 /// called first. 1146 /// 1147 /// Returns `None` if asked about a result index that is too large. 1148 pub fn compute_result_type( 1149 &self, 1150 inst: Inst, 1151 result_idx: usize, 1152 ctrl_typevar: Type, 1153 ) -> Option<Type> { 1154 self.inst_result_types(inst, ctrl_typevar).nth(result_idx) 1155 } 1156 1157 /// Get the controlling type variable, or `INVALID` if `inst` isn't polymorphic. 1158 pub fn ctrl_typevar(&self, inst: Inst) -> Type { 1159 let constraints = self.insts[inst].opcode().constraints(); 1160 1161 if !constraints.is_polymorphic() { 1162 types::INVALID 1163 } else if constraints.requires_typevar_operand() { 1164 // Not all instruction formats have a designated operand, but in that case 1165 // `requires_typevar_operand()` should never be true. 1166 self.value_type( 1167 self.insts[inst] 1168 .typevar_operand(&self.value_lists) 1169 .unwrap_or_else(|| { 1170 panic!( 1171 "Instruction format for {:?} doesn't have a designated operand", 1172 self.insts[inst] 1173 ) 1174 }), 1175 ) 1176 } else { 1177 self.value_type(self.first_result(inst)) 1178 } 1179 } 1180 } 1181 1182 /// basic blocks. 1183 impl DataFlowGraph { 1184 /// Create a new basic block. 1185 pub fn make_block(&mut self) -> Block { 1186 self.blocks.add() 1187 } 1188 1189 /// Get the number of parameters on `block`. 1190 pub fn num_block_params(&self, block: Block) -> usize { 1191 self.blocks[block].params(&self.value_lists).len() 1192 } 1193 1194 /// Get the parameters on `block`. 1195 pub fn block_params(&self, block: Block) -> &[Value] { 1196 self.blocks[block].params(&self.value_lists) 1197 } 1198 1199 /// Get the types of the parameters on `block`. 1200 pub fn block_param_types(&self, block: Block) -> impl Iterator<Item = Type> + '_ { 1201 self.block_params(block).iter().map(|&v| self.value_type(v)) 1202 } 1203 1204 /// Append a parameter with type `ty` to `block`. 1205 pub fn append_block_param(&mut self, block: Block, ty: Type) -> Value { 1206 let param = self.values.next_key(); 1207 let num = self.blocks[block].params.push(param, &mut self.value_lists); 1208 debug_assert!(num <= u16::MAX as usize, "Too many parameters on block"); 1209 self.make_value(ValueData::Param { 1210 ty, 1211 num: num as u16, 1212 block, 1213 }) 1214 } 1215 1216 /// Removes `val` from `block`'s parameters by swapping it with the last parameter on `block`. 1217 /// Returns the position of `val` before removal. 1218 /// 1219 /// *Important*: to ensure O(1) deletion, this method swaps the removed parameter with the 1220 /// last `block` parameter. This can disrupt all the branch instructions jumping to this 1221 /// `block` for which you have to change the branch argument order if necessary. 1222 /// 1223 /// Panics if `val` is not a block parameter. 1224 pub fn swap_remove_block_param(&mut self, val: Value) -> usize { 1225 let (block, num) = 1226 if let ValueData::Param { num, block, .. } = ValueData::from(self.values[val]) { 1227 (block, num) 1228 } else { 1229 panic!("{} must be a block parameter", val); 1230 }; 1231 self.blocks[block] 1232 .params 1233 .swap_remove(num as usize, &mut self.value_lists); 1234 if let Some(last_arg_val) = self.blocks[block] 1235 .params 1236 .get(num as usize, &self.value_lists) 1237 { 1238 // We update the position of the old last arg. 1239 let mut last_arg_data = ValueData::from(self.values[last_arg_val]); 1240 if let ValueData::Param { 1241 num: ref mut old_num, 1242 .. 1243 } = &mut last_arg_data 1244 { 1245 *old_num = num; 1246 self.values[last_arg_val] = last_arg_data.into(); 1247 } else { 1248 panic!("{} should be a Block parameter", last_arg_val); 1249 } 1250 } 1251 num as usize 1252 } 1253 1254 /// Removes `val` from `block`'s parameters by a standard linear time list removal which 1255 /// preserves ordering. Also updates the values' data. 1256 pub fn remove_block_param(&mut self, val: Value) { 1257 let (block, num) = 1258 if let ValueData::Param { num, block, .. } = ValueData::from(self.values[val]) { 1259 (block, num) 1260 } else { 1261 panic!("{} must be a block parameter", val); 1262 }; 1263 self.blocks[block] 1264 .params 1265 .remove(num as usize, &mut self.value_lists); 1266 for index in num..(self.num_block_params(block) as u16) { 1267 let packed = &mut self.values[self.blocks[block] 1268 .params 1269 .get(index as usize, &self.value_lists) 1270 .unwrap()]; 1271 let mut data = ValueData::from(*packed); 1272 match &mut data { 1273 ValueData::Param { ref mut num, .. } => { 1274 *num -= 1; 1275 *packed = data.into(); 1276 } 1277 _ => panic!( 1278 "{} must be a block parameter", 1279 self.blocks[block] 1280 .params 1281 .get(index as usize, &self.value_lists) 1282 .unwrap() 1283 ), 1284 } 1285 } 1286 } 1287 1288 /// Append an existing value to `block`'s parameters. 1289 /// 1290 /// The appended value can't already be attached to something else. 1291 /// 1292 /// In almost all cases, you should be using `append_block_param()` instead of this method. 1293 pub fn attach_block_param(&mut self, block: Block, param: Value) { 1294 debug_assert!(!self.value_is_attached(param)); 1295 let num = self.blocks[block].params.push(param, &mut self.value_lists); 1296 debug_assert!(num <= u16::MAX as usize, "Too many parameters on block"); 1297 let ty = self.value_type(param); 1298 self.values[param] = ValueData::Param { 1299 ty, 1300 num: num as u16, 1301 block, 1302 } 1303 .into(); 1304 } 1305 1306 /// Replace a block parameter with a new value of type `ty`. 1307 /// 1308 /// The `old_value` must be an attached block parameter. It is removed from its place in the list 1309 /// of parameters and replaced by a new value of type `new_type`. The new value gets the same 1310 /// position in the list, and other parameters are not disturbed. 1311 /// 1312 /// The old value is left detached, so it should probably be changed into something else. 1313 /// 1314 /// Returns the new value. 1315 pub fn replace_block_param(&mut self, old_value: Value, new_type: Type) -> Value { 1316 // Create new value identical to the old one except for the type. 1317 let (block, num) = 1318 if let ValueData::Param { num, block, .. } = ValueData::from(self.values[old_value]) { 1319 (block, num) 1320 } else { 1321 panic!("{} must be a block parameter", old_value); 1322 }; 1323 let new_arg = self.make_value(ValueData::Param { 1324 ty: new_type, 1325 num, 1326 block, 1327 }); 1328 1329 self.blocks[block] 1330 .params 1331 .as_mut_slice(&mut self.value_lists)[num as usize] = new_arg; 1332 new_arg 1333 } 1334 1335 /// Detach all the parameters from `block` and return them as a `ValueList`. 1336 /// 1337 /// This is a quite low-level operation. Sensible things to do with the detached block parameters 1338 /// is to put them back on the same block with `attach_block_param()` or change them into aliases 1339 /// with `change_to_alias()`. 1340 pub fn detach_block_params(&mut self, block: Block) -> ValueList { 1341 self.blocks[block].params.take() 1342 } 1343 1344 /// Merge the facts for two values. If both values have facts and 1345 /// they differ, both values get a special "conflict" fact that is 1346 /// never satisfied. 1347 pub fn merge_facts(&mut self, a: Value, b: Value) { 1348 let a = self.resolve_aliases(a); 1349 let b = self.resolve_aliases(b); 1350 match (&self.facts[a], &self.facts[b]) { 1351 (Some(a), Some(b)) if a == b => { /* nothing */ } 1352 (None, None) => { /* nothing */ } 1353 (Some(a), None) => { 1354 self.facts[b] = Some(a.clone()); 1355 } 1356 (None, Some(b)) => { 1357 self.facts[a] = Some(b.clone()); 1358 } 1359 (Some(a_fact), Some(b_fact)) => { 1360 assert_eq!(self.value_type(a), self.value_type(b)); 1361 let merged = Fact::intersect(a_fact, b_fact); 1362 crate::trace!( 1363 "facts merge on {} and {}: {:?}, {:?} -> {:?}", 1364 a, 1365 b, 1366 a_fact, 1367 b_fact, 1368 merged, 1369 ); 1370 self.facts[a] = Some(merged.clone()); 1371 self.facts[b] = Some(merged); 1372 } 1373 } 1374 } 1375 } 1376 1377 /// Contents of a basic block. 1378 /// 1379 /// Parameters on a basic block are values that dominate everything in the block. All 1380 /// branches to this block must provide matching arguments, and the arguments to the entry block must 1381 /// match the function arguments. 1382 #[derive(Clone, PartialEq, Hash)] 1383 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] 1384 pub struct BlockData { 1385 /// List of parameters to this block. 1386 params: ValueList, 1387 } 1388 1389 impl BlockData { 1390 fn new() -> Self { 1391 Self { 1392 params: ValueList::new(), 1393 } 1394 } 1395 1396 /// Get the parameters on `block`. 1397 pub fn params<'a>(&self, pool: &'a ValueListPool) -> &'a [Value] { 1398 self.params.as_slice(pool) 1399 } 1400 } 1401 1402 /// Object that can display an instruction. 1403 pub struct DisplayInst<'a>(&'a DataFlowGraph, Inst); 1404 1405 impl<'a> fmt::Display for DisplayInst<'a> { 1406 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1407 let dfg = self.0; 1408 let inst = self.1; 1409 1410 if let Some((first, rest)) = dfg.inst_results(inst).split_first() { 1411 write!(f, "{}", first)?; 1412 for v in rest { 1413 write!(f, ", {}", v)?; 1414 } 1415 write!(f, " = ")?; 1416 } 1417 1418 let typevar = dfg.ctrl_typevar(inst); 1419 if typevar.is_invalid() { 1420 write!(f, "{}", dfg.insts[inst].opcode())?; 1421 } else { 1422 write!(f, "{}.{}", dfg.insts[inst].opcode(), typevar)?; 1423 } 1424 write_operands(f, dfg, inst) 1425 } 1426 } 1427 1428 /// Parser routines. These routines should not be used outside the parser. 1429 impl DataFlowGraph { 1430 /// Set the type of a value. This is only for use in the parser, which needs 1431 /// to create invalid values for index padding which may be reassigned later. 1432 #[cold] 1433 fn set_value_type_for_parser(&mut self, v: Value, t: Type) { 1434 assert_eq!( 1435 self.value_type(v), 1436 types::INVALID, 1437 "this function is only for assigning types to previously invalid values" 1438 ); 1439 self.values[v].set_type(t); 1440 } 1441 1442 /// Check that the given concrete `Type` has been defined in the function. 1443 pub fn check_dynamic_type(&mut self, ty: Type) -> Option<Type> { 1444 debug_assert!(ty.is_dynamic_vector()); 1445 if self 1446 .dynamic_types 1447 .values() 1448 .any(|dyn_ty_data| dyn_ty_data.concrete().unwrap() == ty) 1449 { 1450 Some(ty) 1451 } else { 1452 None 1453 } 1454 } 1455 1456 /// Create result values for `inst`, reusing the provided detached values. 1457 /// This is similar to `make_inst_results_reusing` except it's only for use 1458 /// in the parser, which needs to reuse previously invalid values. 1459 #[cold] 1460 pub fn make_inst_results_for_parser( 1461 &mut self, 1462 inst: Inst, 1463 ctrl_typevar: Type, 1464 reuse: &[Value], 1465 ) -> usize { 1466 let mut reuse_iter = reuse.iter().copied(); 1467 let result_tys: SmallVec<[_; 16]> = self.inst_result_types(inst, ctrl_typevar).collect(); 1468 for ty in result_tys { 1469 if ty.is_dynamic_vector() { 1470 self.check_dynamic_type(ty) 1471 .unwrap_or_else(|| panic!("Use of undeclared dynamic type: {}", ty)); 1472 } 1473 if let Some(v) = reuse_iter.next() { 1474 self.set_value_type_for_parser(v, ty); 1475 } 1476 } 1477 1478 self.make_inst_results_reusing(inst, ctrl_typevar, reuse.iter().map(|x| Some(*x))) 1479 } 1480 1481 /// Similar to `append_block_param`, append a parameter with type `ty` to 1482 /// `block`, but using value `val`. This is only for use by the parser to 1483 /// create parameters with specific values. 1484 #[cold] 1485 pub fn append_block_param_for_parser(&mut self, block: Block, ty: Type, val: Value) { 1486 let num = self.blocks[block].params.push(val, &mut self.value_lists); 1487 assert!(num <= u16::MAX as usize, "Too many parameters on block"); 1488 self.values[val] = ValueData::Param { 1489 ty, 1490 num: num as u16, 1491 block, 1492 } 1493 .into(); 1494 } 1495 1496 /// Create a new value alias. This is only for use by the parser to create 1497 /// aliases with specific values, and the printer for testing. 1498 #[cold] 1499 pub fn make_value_alias_for_serialization(&mut self, src: Value, dest: Value) { 1500 assert_ne!(src, Value::reserved_value()); 1501 assert_ne!(dest, Value::reserved_value()); 1502 1503 let ty = if self.values.is_valid(src) { 1504 self.value_type(src) 1505 } else { 1506 // As a special case, if we can't resolve the aliasee yet, use INVALID 1507 // temporarily. It will be resolved later in parsing. 1508 types::INVALID 1509 }; 1510 let data = ValueData::Alias { ty, original: src }; 1511 self.values[dest] = data.into(); 1512 } 1513 1514 /// If `v` is already defined as an alias, return its destination value. 1515 /// Otherwise return None. This allows the parser to coalesce identical 1516 /// alias definitions, and the printer to identify an alias's immediate target. 1517 #[cold] 1518 pub fn value_alias_dest_for_serialization(&self, v: Value) -> Option<Value> { 1519 if let ValueData::Alias { original, .. } = ValueData::from(self.values[v]) { 1520 Some(original) 1521 } else { 1522 None 1523 } 1524 } 1525 1526 /// Compute the type of an alias. This is only for use in the parser. 1527 /// Returns false if an alias cycle was encountered. 1528 #[cold] 1529 pub fn set_alias_type_for_parser(&mut self, v: Value) -> bool { 1530 if let Some(resolved) = maybe_resolve_aliases(&self.values, v) { 1531 let old_ty = self.value_type(v); 1532 let new_ty = self.value_type(resolved); 1533 if old_ty == types::INVALID { 1534 self.set_value_type_for_parser(v, new_ty); 1535 } else { 1536 assert_eq!(old_ty, new_ty); 1537 } 1538 true 1539 } else { 1540 false 1541 } 1542 } 1543 1544 /// Create an invalid value, to pad the index space. This is only for use by 1545 /// the parser to pad out the value index space. 1546 #[cold] 1547 pub fn make_invalid_value_for_parser(&mut self) { 1548 let data = ValueData::Alias { 1549 ty: types::INVALID, 1550 original: Value::reserved_value(), 1551 }; 1552 self.make_value(data); 1553 } 1554 1555 /// Check if a value reference is valid, while being aware of aliases which 1556 /// may be unresolved while parsing. 1557 #[cold] 1558 pub fn value_is_valid_for_parser(&self, v: Value) -> bool { 1559 if !self.value_is_valid(v) { 1560 return false; 1561 } 1562 if let ValueData::Alias { ty, .. } = ValueData::from(self.values[v]) { 1563 ty != types::INVALID 1564 } else { 1565 true 1566 } 1567 } 1568 } 1569 1570 #[cfg(test)] 1571 mod tests { 1572 use super::*; 1573 use crate::cursor::{Cursor, FuncCursor}; 1574 use crate::ir::{Function, Opcode, TrapCode}; 1575 use alloc::string::ToString; 1576 1577 #[test] 1578 fn make_inst() { 1579 let mut dfg = DataFlowGraph::new(); 1580 1581 let idata = InstructionData::UnaryImm { 1582 opcode: Opcode::Iconst, 1583 imm: 0.into(), 1584 }; 1585 let inst = dfg.make_inst(idata); 1586 1587 dfg.make_inst_results(inst, types::I32); 1588 assert_eq!(inst.to_string(), "inst0"); 1589 assert_eq!(dfg.display_inst(inst).to_string(), "v0 = iconst.i32 0"); 1590 1591 // Immutable reference resolution. 1592 { 1593 let immdfg = &dfg; 1594 let ins = &immdfg.insts[inst]; 1595 assert_eq!(ins.opcode(), Opcode::Iconst); 1596 } 1597 1598 // Results. 1599 let val = dfg.first_result(inst); 1600 assert_eq!(dfg.inst_results(inst), &[val]); 1601 1602 assert_eq!(dfg.value_def(val), ValueDef::Result(inst, 0)); 1603 assert_eq!(dfg.value_type(val), types::I32); 1604 1605 // Replacing results. 1606 assert!(dfg.value_is_attached(val)); 1607 let v2 = dfg.replace_result(val, types::F64); 1608 assert!(!dfg.value_is_attached(val)); 1609 assert!(dfg.value_is_attached(v2)); 1610 assert_eq!(dfg.inst_results(inst), &[v2]); 1611 assert_eq!(dfg.value_def(v2), ValueDef::Result(inst, 0)); 1612 assert_eq!(dfg.value_type(v2), types::F64); 1613 } 1614 1615 #[test] 1616 fn no_results() { 1617 let mut dfg = DataFlowGraph::new(); 1618 1619 let idata = InstructionData::Trap { 1620 opcode: Opcode::Trap, 1621 code: TrapCode::User(0), 1622 }; 1623 let inst = dfg.make_inst(idata); 1624 assert_eq!(dfg.display_inst(inst).to_string(), "trap user0"); 1625 1626 // Result slice should be empty. 1627 assert_eq!(dfg.inst_results(inst), &[]); 1628 } 1629 1630 #[test] 1631 fn block() { 1632 let mut dfg = DataFlowGraph::new(); 1633 1634 let block = dfg.make_block(); 1635 assert_eq!(block.to_string(), "block0"); 1636 assert_eq!(dfg.num_block_params(block), 0); 1637 assert_eq!(dfg.block_params(block), &[]); 1638 assert!(dfg.detach_block_params(block).is_empty()); 1639 assert_eq!(dfg.num_block_params(block), 0); 1640 assert_eq!(dfg.block_params(block), &[]); 1641 1642 let arg1 = dfg.append_block_param(block, types::F32); 1643 assert_eq!(arg1.to_string(), "v0"); 1644 assert_eq!(dfg.num_block_params(block), 1); 1645 assert_eq!(dfg.block_params(block), &[arg1]); 1646 1647 let arg2 = dfg.append_block_param(block, types::I16); 1648 assert_eq!(arg2.to_string(), "v1"); 1649 assert_eq!(dfg.num_block_params(block), 2); 1650 assert_eq!(dfg.block_params(block), &[arg1, arg2]); 1651 1652 assert_eq!(dfg.value_def(arg1), ValueDef::Param(block, 0)); 1653 assert_eq!(dfg.value_def(arg2), ValueDef::Param(block, 1)); 1654 assert_eq!(dfg.value_type(arg1), types::F32); 1655 assert_eq!(dfg.value_type(arg2), types::I16); 1656 1657 // Swap the two block parameters. 1658 let vlist = dfg.detach_block_params(block); 1659 assert_eq!(dfg.num_block_params(block), 0); 1660 assert_eq!(dfg.block_params(block), &[]); 1661 assert_eq!(vlist.as_slice(&dfg.value_lists), &[arg1, arg2]); 1662 dfg.attach_block_param(block, arg2); 1663 let arg3 = dfg.append_block_param(block, types::I32); 1664 dfg.attach_block_param(block, arg1); 1665 assert_eq!(dfg.block_params(block), &[arg2, arg3, arg1]); 1666 } 1667 1668 #[test] 1669 fn replace_block_params() { 1670 let mut dfg = DataFlowGraph::new(); 1671 1672 let block = dfg.make_block(); 1673 let arg1 = dfg.append_block_param(block, types::F32); 1674 1675 let new1 = dfg.replace_block_param(arg1, types::I64); 1676 assert_eq!(dfg.value_type(arg1), types::F32); 1677 assert_eq!(dfg.value_type(new1), types::I64); 1678 assert_eq!(dfg.block_params(block), &[new1]); 1679 1680 dfg.attach_block_param(block, arg1); 1681 assert_eq!(dfg.block_params(block), &[new1, arg1]); 1682 1683 let new2 = dfg.replace_block_param(arg1, types::I8); 1684 assert_eq!(dfg.value_type(arg1), types::F32); 1685 assert_eq!(dfg.value_type(new2), types::I8); 1686 assert_eq!(dfg.block_params(block), &[new1, new2]); 1687 1688 dfg.attach_block_param(block, arg1); 1689 assert_eq!(dfg.block_params(block), &[new1, new2, arg1]); 1690 1691 let new3 = dfg.replace_block_param(new2, types::I16); 1692 assert_eq!(dfg.value_type(new1), types::I64); 1693 assert_eq!(dfg.value_type(new2), types::I8); 1694 assert_eq!(dfg.value_type(new3), types::I16); 1695 assert_eq!(dfg.block_params(block), &[new1, new3, arg1]); 1696 } 1697 1698 #[test] 1699 fn swap_remove_block_params() { 1700 let mut dfg = DataFlowGraph::new(); 1701 1702 let block = dfg.make_block(); 1703 let arg1 = dfg.append_block_param(block, types::F32); 1704 let arg2 = dfg.append_block_param(block, types::F32); 1705 let arg3 = dfg.append_block_param(block, types::F32); 1706 assert_eq!(dfg.block_params(block), &[arg1, arg2, arg3]); 1707 1708 dfg.swap_remove_block_param(arg1); 1709 assert_eq!(dfg.value_is_attached(arg1), false); 1710 assert_eq!(dfg.value_is_attached(arg2), true); 1711 assert_eq!(dfg.value_is_attached(arg3), true); 1712 assert_eq!(dfg.block_params(block), &[arg3, arg2]); 1713 dfg.swap_remove_block_param(arg2); 1714 assert_eq!(dfg.value_is_attached(arg2), false); 1715 assert_eq!(dfg.value_is_attached(arg3), true); 1716 assert_eq!(dfg.block_params(block), &[arg3]); 1717 dfg.swap_remove_block_param(arg3); 1718 assert_eq!(dfg.value_is_attached(arg3), false); 1719 assert_eq!(dfg.block_params(block), &[]); 1720 } 1721 1722 #[test] 1723 fn aliases() { 1724 use crate::ir::condcodes::IntCC; 1725 use crate::ir::InstBuilder; 1726 1727 let mut func = Function::new(); 1728 let block0 = func.dfg.make_block(); 1729 let mut pos = FuncCursor::new(&mut func); 1730 pos.insert_block(block0); 1731 1732 // Build a little test program. 1733 let v1 = pos.ins().iconst(types::I32, 42); 1734 1735 // Make sure we can resolve value aliases even when values is empty. 1736 assert_eq!(pos.func.dfg.resolve_aliases(v1), v1); 1737 1738 let arg0 = pos.func.dfg.append_block_param(block0, types::I32); 1739 let (s, c) = pos.ins().uadd_overflow(v1, arg0); 1740 let iadd = match pos.func.dfg.value_def(s) { 1741 ValueDef::Result(i, 0) => i, 1742 _ => panic!(), 1743 }; 1744 1745 // Remove `c` from the result list. 1746 pos.func.stencil.dfg.results[iadd].remove(1, &mut pos.func.stencil.dfg.value_lists); 1747 1748 // Replace `uadd_overflow` with a normal `iadd` and an `icmp`. 1749 pos.func.dfg.replace(iadd).iadd(v1, arg0); 1750 let c2 = pos.ins().icmp(IntCC::Equal, s, v1); 1751 pos.func.dfg.change_to_alias(c, c2); 1752 1753 assert_eq!(pos.func.dfg.resolve_aliases(c2), c2); 1754 assert_eq!(pos.func.dfg.resolve_aliases(c), c2); 1755 } 1756 1757 #[test] 1758 fn cloning() { 1759 use crate::ir::InstBuilder; 1760 1761 let mut func = Function::new(); 1762 let mut sig = Signature::new(crate::isa::CallConv::SystemV); 1763 sig.params.push(ir::AbiParam::new(types::I32)); 1764 let sig = func.import_signature(sig); 1765 let block0 = func.dfg.make_block(); 1766 let mut pos = FuncCursor::new(&mut func); 1767 pos.insert_block(block0); 1768 let v1 = pos.ins().iconst(types::I32, 0); 1769 let v2 = pos.ins().iconst(types::I32, 1); 1770 let call_inst = pos.ins().call_indirect(sig, v1, &[v1]); 1771 let func = pos.func; 1772 1773 let call_inst_dup = func.dfg.clone_inst(call_inst); 1774 func.dfg.inst_args_mut(call_inst)[0] = v2; 1775 assert_eq!(v1, func.dfg.inst_args(call_inst_dup)[0]); 1776 } 1777 } 1778