souper_ir/ast.rs
1//! Abstract syntax tree type definitions.
2
3pub use id_arena::{Arena, Id};
4
5/// An identifier for a value defined by an assignment.
6#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
7pub struct ValueId(
8 /// Always points to a `Statement::Assignment`, and references the value
9 /// defined by the assignment.
10 pub(crate) Id<Statement>,
11);
12
13impl From<ValueId> for Id<Statement> {
14 #[inline]
15 fn from(id: ValueId) -> Self {
16 id.0
17 }
18}
19
20/// An identifier for a defined block.
21#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
22pub struct BlockId(
23 /// Always points to an assignment where the RHS is `AssignmentRhs::Block`.
24 pub(crate) ValueId,
25);
26
27impl From<BlockId> for ValueId {
28 #[inline]
29 fn from(id: BlockId) -> Self {
30 id.0
31 }
32}
33
34impl From<BlockId> for Id<Statement> {
35 #[inline]
36 fn from(id: BlockId) -> Self {
37 (id.0).0
38 }
39}
40
41/// A complete optimization that replaces a left-hand side with a right-hand
42/// side.
43#[derive(Clone, Debug)]
44pub enum Replacement {
45 /// A replacement in the form of a left-hand side followed by a right-hand
46 /// side.
47 LhsRhs {
48 /// Statements that make up the expression DAGs for the left- and
49 /// right-hand sides.
50 statements: Arena<Statement>,
51 /// The left-hand side that is matched by the optimization.
52 lhs: Infer,
53 /// The right-hand side that replaces the left-hand side after applying
54 /// the optimization.
55 rhs: Operand,
56 },
57
58 /// A replacement in the form of an expression DAG followed by a `cand x y`
59 /// statement that declares that `y` is a candidate for replacing `x`.
60 Cand {
61 /// Statements that make up the expression DAG for both the
62 /// replacement's left- and right-hand sides.
63 statements: Arena<Statement>,
64 /// The candidate rewrite connecting the left- and right-hand sides of
65 /// this replacement within `statements`.
66 cand: Cand,
67 },
68}
69
70impl Replacement {
71 /// Get the assignment that defined the given value.
72 ///
73 /// # Panics
74 ///
75 /// May panic or produce incorrect results if given a `ValueId` from another
76 /// `Replacement`, `LeftHandSide`, or `RightHandSide`'s arena.
77 pub fn assignment(&self, id: ValueId) -> &Assignment {
78 match self {
79 Replacement::LhsRhs { statements, .. } | Replacement::Cand { statements, .. } => {
80 match &statements[id.into()] {
81 Statement::Assignment(a) => a,
82 _ => panic!("use of an `id` that is not from this `Replacement`'s arena"),
83 }
84 }
85 }
86 }
87}
88
89/// A builder for a [`Replacement`][crate::ast::Replacement].
90#[derive(Clone, Debug, Default)]
91pub struct ReplacementBuilder {
92 statements: Arena<Statement>,
93}
94
95impl ReplacementBuilder {
96 /// Create a new assignment statement.
97 ///
98 /// Returns the value defined by the assignment.
99 ///
100 /// # Panics
101 ///
102 /// Panics if `name` (when given) does not start with '%'.
103 pub fn assignment(
104 &mut self,
105 name: Option<String>,
106 r#type: Option<Type>,
107 value: impl Into<AssignmentRhs>,
108 attributes: Vec<Attribute>,
109 ) -> ValueId {
110 let name = name.unwrap_or_else(|| format!("%{}", self.statements.len()));
111 assert!(name.starts_with('%'));
112 ValueId(
113 self.statements.alloc(
114 Assignment {
115 name,
116 r#type,
117 value: value.into(),
118 attributes,
119 }
120 .into(),
121 ),
122 )
123 }
124
125 /// Create a new [basic block][crate::ast::Block].
126 ///
127 /// Declare that the block has `predecessors` number of incoming edges in
128 /// the control-flow graph.
129 ///
130 /// # Panics
131 ///
132 /// Panics if `name` (when given) does not start with '%'.
133 pub fn block(&mut self, name: Option<String>, predecessors: u32) -> BlockId {
134 BlockId(self.assignment(name, None, Block { predecessors }, vec![]))
135 }
136
137 /// Create a [path condition][crate::ast::Pc].
138 ///
139 /// Expresses the fact that `x` must equal `y` for the replacement to be
140 /// valid.
141 pub fn pc(&mut self, x: impl Into<Operand>, y: impl Into<Operand>) {
142 let x = x.into();
143 let y = y.into();
144 self.statements.alloc(Pc { x, y }.into());
145 }
146
147 /// Create a [block path condition][crate::ast::BlockPc].
148 ///
149 /// Expresses that `x` is equal to `y` on an incoming edge to `block` in the
150 /// control-flow graph.
151 ///
152 /// # Panics
153 ///
154 /// Panics if `predecessor` is greater than or equal to `block`'s number of
155 /// predecessors.
156 pub fn block_pc(
157 &mut self,
158 block: BlockId,
159 predecessor: u32,
160 x: impl Into<Operand>,
161 y: impl Into<Operand>,
162 ) {
163 let x = x.into();
164 let y = y.into();
165 self.statements.alloc(
166 BlockPc {
167 block,
168 predecessor,
169 x,
170 y,
171 }
172 .into(),
173 );
174 }
175
176 /// Finish building this replacement by providing the left- and right-hand
177 /// sides.
178 pub fn finish(
179 self,
180 lhs: ValueId,
181 rhs: impl Into<Operand>,
182 attributes: impl IntoIterator<Item = RootAttribute>,
183 ) -> Replacement {
184 Replacement::LhsRhs {
185 statements: self.statements,
186 lhs: Infer {
187 value: lhs,
188 attributes: attributes.into_iter().collect(),
189 },
190 rhs: rhs.into(),
191 }
192 }
193}
194
195/// A candidate rewrite.
196#[derive(Clone, Debug)]
197pub struct Cand {
198 /// The left-hand side expression that can be replaced by the right-hand
199 /// side.
200 pub lhs: Operand,
201
202 /// The right-hand side expression that can replace the left-hand side.
203 pub rhs: Operand,
204
205 /// Attributes for this rewrite.
206 pub attributes: Vec<RootAttribute>,
207}
208
209/// The left-hand side of a replacement.
210#[derive(Clone, Debug)]
211pub struct LeftHandSide {
212 /// Statements making up this LHS's expression DAG.
213 pub statements: Arena<Statement>,
214
215 /// The root of this LHS's expression DAG.
216 pub infer: Infer,
217}
218
219/// A builder for a [`LeftHandSide`][crate::ast::LeftHandSide].
220#[derive(Clone, Debug, Default)]
221pub struct LeftHandSideBuilder {
222 statements: Arena<Statement>,
223}
224
225impl LeftHandSideBuilder {
226 /// Create a new assignment statement.
227 ///
228 /// Returns the value defined by the assignment.
229 ///
230 /// # Panics
231 ///
232 /// Panics if `name` (when given) does not start with '%'.
233 pub fn assignment(
234 &mut self,
235 name: Option<String>,
236 r#type: Option<Type>,
237 value: impl Into<AssignmentRhs>,
238 attributes: Vec<Attribute>,
239 ) -> ValueId {
240 let name = name.unwrap_or_else(|| format!("%{}", self.statements.len()));
241 assert!(name.starts_with('%'));
242 ValueId(
243 self.statements.alloc(
244 Assignment {
245 name,
246 r#type,
247 value: value.into(),
248 attributes,
249 }
250 .into(),
251 ),
252 )
253 }
254
255 /// Create a new [basic block][crate::ast::Block].
256 ///
257 /// Declare that the block has `predecessors` number of incoming edges in
258 /// the control-flow graph.
259 ///
260 /// # Panics
261 ///
262 /// Panics if `name` (when given) does not start with '%'.
263 pub fn block(&mut self, name: Option<String>, predecessors: u32) -> BlockId {
264 BlockId(self.assignment(name, None, Block { predecessors }, vec![]))
265 }
266
267 /// Create a [path condition][crate::ast::Pc].
268 ///
269 /// Expresses the fact that `x` must equal `y` for the replacement to be
270 /// valid.
271 pub fn pc(&mut self, x: impl Into<Operand>, y: impl Into<Operand>) {
272 let x = x.into();
273 let y = y.into();
274 self.statements.alloc(Pc { x, y }.into());
275 }
276
277 /// Create a [block path condition][crate::ast::BlockPc].
278 ///
279 /// Expresses that `x` is equal to `y` on an incoming edge to `block` in the
280 /// control-flow graph.
281 ///
282 /// # Panics
283 ///
284 /// Panics if `predecessor` is greater than or equal to `block`'s number of
285 /// predecessors.
286 pub fn block_pc(
287 &mut self,
288 block: BlockId,
289 predecessor: u32,
290 x: impl Into<Operand>,
291 y: impl Into<Operand>,
292 ) {
293 let x = x.into();
294 let y = y.into();
295 self.statements.alloc(
296 BlockPc {
297 block,
298 predecessor,
299 x,
300 y,
301 }
302 .into(),
303 );
304 }
305
306 /// Finish building this `LeftHandSide`.
307 pub fn finish(
308 self,
309 lhs: ValueId,
310 attributes: impl IntoIterator<Item = RootAttribute>,
311 ) -> LeftHandSide {
312 LeftHandSide {
313 statements: self.statements,
314 infer: Infer {
315 value: lhs,
316 attributes: attributes.into_iter().collect(),
317 },
318 }
319 }
320
321 /// Get the assignment that created the given value.
322 ///
323 /// # Panics
324 ///
325 /// May panic when given a `ValudId` from a different LHS, RHS, or
326 /// replacement.
327 pub fn get_value(&self, id: ValueId) -> &Assignment {
328 match &self.statements[id.into()] {
329 Statement::Assignment(a) => a,
330 _ => panic!(),
331 }
332 }
333}
334
335/// The root of a left-hand side.
336#[derive(Clone, Debug)]
337pub struct Infer {
338 /// The value to be replaced by the right-hand side.
339 pub value: ValueId,
340
341 /// Attributes for this left-hand side.
342 pub attributes: Vec<RootAttribute>,
343}
344
345/// The right-hand side of a replacement.
346#[derive(Clone, Debug)]
347pub struct RightHandSide {
348 /// Statements making up this RHS's expression DAG.
349 pub statements: Arena<Statement>,
350
351 /// The root of this RHS's expression DAG.
352 pub result: Operand,
353}
354
355/// A statement in a LHS or RHS.
356#[derive(Clone, Debug)]
357pub enum Statement {
358 /// An assignment statement.
359 Assignment(Assignment),
360
361 /// A path condition statement.
362 Pc(Pc),
363
364 /// A block path condition statement.
365 BlockPc(BlockPc),
366}
367
368impl From<Assignment> for Statement {
369 fn from(a: Assignment) -> Self {
370 Statement::Assignment(a)
371 }
372}
373
374impl From<Pc> for Statement {
375 fn from(pc: Pc) -> Self {
376 Statement::Pc(pc)
377 }
378}
379
380impl From<BlockPc> for Statement {
381 fn from(bpc: BlockPc) -> Self {
382 Statement::BlockPc(bpc)
383 }
384}
385
386/// An assignment, defining a value.
387#[derive(Clone, Debug)]
388pub struct Assignment {
389 /// The name of the value being defined by this assignment.
390 pub name: String,
391
392 /// The ascribed type, if any.
393 pub r#type: Option<Type>,
394
395 /// The value being bound in this assignment.
396 pub value: AssignmentRhs,
397
398 /// Attributes describing data-flow facts known about this value.
399 pub attributes: Vec<Attribute>,
400}
401
402/// Any value that can be assigned to a name.
403#[derive(Clone, Debug)]
404pub enum AssignmentRhs {
405 /// An input variable.
406 Var,
407
408 /// A basic block.
409 Block(Block),
410
411 /// A phi node.
412 Phi(Phi),
413
414 /// A hole reserved for an as-of-yet-unknown instruction.
415 ReservedInst,
416
417 /// A hole reserved for an as-of-yet-unknown constant.
418 ReservedConst,
419
420 /// An instruction and its operands.
421 Instruction(Instruction),
422}
423
424impl From<Block> for AssignmentRhs {
425 fn from(b: Block) -> Self {
426 AssignmentRhs::Block(b)
427 }
428}
429
430impl From<Phi> for AssignmentRhs {
431 fn from(p: Phi) -> Self {
432 AssignmentRhs::Phi(p)
433 }
434}
435
436impl From<Instruction> for AssignmentRhs {
437 fn from(i: Instruction) -> Self {
438 AssignmentRhs::Instruction(i)
439 }
440}
441
442/// An input variable.
443#[derive(Clone, Debug)]
444pub struct Var {
445 /// Attributes describing dataflow facts known about this input variable.
446 pub attributes: Vec<Attribute>,
447}
448
449/// A basic block.
450#[derive(Clone, Debug)]
451pub struct Block {
452 /// The number of incoming predecessors that this basic block has in the
453 /// control-flow graph.
454 pub predecessors: u32,
455}
456
457/// A phi node.
458///
459/// If a phi's `block` has `n` predecessors, then the length of `values` must be
460/// `n`.
461///
462/// All phi nodes associated with a particular `block` will have their `i`th
463/// value selected when control flow comes from `block`'s `i`th predecessor. For
464/// example, given:
465///
466/// ```text
467/// %bb = block 3
468/// %a = phi %bb, 1, 2, 3
469/// %b = phi %bb, 4, 5, 6
470/// %c = phi %bb, 7, 8, 9
471/// ```
472///
473/// If the basic block `%bb` has three control-flow predecessors. If it is
474/// entered via its first predecessor, then `%a == 1`, `%b == 4`, and `%c ==
475/// 7`. If it is entered via its second predecessor, then `%a == 2`, `%b == 5`,
476/// and `%c == 8`. Finally, if it is entered via its third predecessor, then `%a
477/// == 3`, `%b == 6`, and `%c == 9`.
478#[derive(Clone, Debug)]
479pub struct Phi {
480 /// The basic block that this phi node is contained within.
481 pub block: BlockId,
482
483 /// The potential values for this phi node.
484 pub values: Vec<Operand>,
485}
486
487macro_rules! define_instructions {
488 (
489 $(
490 $( #[$attr:meta] )*
491 $token:literal => $inst:ident $( ( $($operand:ident),* ) )? ;
492 )*
493 ) => {
494 /// A Souper instruction.
495 #[derive(Copy, Clone, Debug)]
496 pub enum Instruction {
497 $(
498 $( #[$attr] )*
499 $inst $( { $(
500 #[allow(missing_docs)]
501 $operand: Operand
502 ),* } )? ,
503 )*
504 }
505
506 #[cfg(feature = "parse")]
507 impl crate::parse::Peek for Instruction {
508 fn peek<'a>(parser: &mut crate::parse::Parser<'a>) -> crate::parse::Result<bool> {
509 match parser.lookahead()? {
510 Some(crate::parse::Token::Ident(ident)) => Ok( false $( || ident == $token )* ),
511 _ => Ok(false),
512 }
513 }
514 }
515
516 #[cfg(feature = "parse")]
517 impl crate::parse::Parse for Instruction {
518 fn parse<'a>(parser: &mut crate::parse::Parser<'a>) -> crate::parse::Result<Self> {
519 let ident = parser.token()?;
520 match ident {
521 $(
522 #[allow(unused_assignments)]
523 crate::parse::Token::Ident($token) => {
524 $(
525 let mut first = true;
526 $(
527 if !first {
528 parser.comma()?;
529 }
530 let $operand = Operand::parse(parser)?;
531 first = false;
532 )*
533 )?
534 Ok(Instruction::$inst $( { $( $operand ),* } )? )
535 }
536 )*
537 _ => parser.error("expected instruction"),
538 }
539 }
540 }
541
542 #[cfg(feature = "stringify")]
543 impl Instruction {
544 pub(crate) fn value_ids(&self, mut f: impl FnMut(ValueId)) {
545 match self {
546 $(
547 Instruction::$inst $( { $( $operand ),* } )? => {
548 $(
549 $(
550 if let Operand::Value(v) = $operand {
551 f(*v);
552 }
553 )*
554 )?
555 }
556 )*
557 }
558 }
559
560 pub(crate) fn operands(&self, mut f: impl FnMut(Operand)) {
561 match self {
562 $(
563 Instruction::$inst $( { $( $operand ),* } )? => {
564 $(
565 $(
566 f(*$operand);
567 )*
568 )?
569 }
570 )*
571 }
572 }
573
574 pub(crate) fn instruction_name(&self) -> &'static str {
575 match self {
576 $(
577 Instruction::$inst $( { $( $operand: _),* } )? => $token,
578 )*
579 }
580 }
581 }
582 };
583}
584
585define_instructions! {
586 /// Wrapping integer addition.
587 "add" => Add(a, b);
588
589 /// Integer addition where signed overflow is undefined behavior.
590 "addnsw" => AddNsw(a, b);
591
592 /// Integer addition where unsigned overflow is undefined behavior.
593 "addnuw" => AddNuw(a, b);
594
595 /// Integer addition where any kind of overflow is undefined behavior.
596 "addnw" => AddNw(a, b);
597
598 /// Wrapping integer subtraction.
599 "sub" => Sub(a, b);
600
601 /// Integer subtraction where signed overflow is undefined behavior.
602 "subnsw" => SubNsw(a, b);
603
604 /// Integer subtraction where unsigned overflow is undefined behavior.
605 "subnuw" => SubNuw(a, b);
606
607 /// Integer subtraction where any kind of overflow is undefined behavior.
608 "subnw" => SubNw(a, b);
609
610 /// Wrapping integer multiplication.
611 "mul" => Mul(a, b);
612
613 /// Integer multiplication where signed overflow is undefined behavior.
614 "mulnsw" => MulNsw(a, b);
615
616 /// Integer multiplication where unsigned overflow is undefined behavior.
617 "mulnuw" => MulNuw(a, b);
618
619 /// Integer multiplication where any kind of overflow is undefined behavior.
620 "mulnw" => MulNw(a, b);
621
622 /// Unsigned integer division.
623 "udiv" => Udiv(a, b);
624
625 /// Signed integer division.
626 "sdiv" => Sdiv(a, b);
627
628 /// Unsigned division where `a` must be exactly divisible by `b`. If `a` is
629 /// not exactly divisible by `b`, then the result is undefined behavior.
630 "udivexact" => UdivExact(a, b);
631
632 /// Signed division where `a` must be exactly divisible by `b`. If `a` is
633 /// not exactly divisible by `b`, then the result is undefined behavior.
634 "sdivexact" => SdivExact(a, b);
635
636 /// Unsigned integer remainder.
637 "urem" => Urem(a, b);
638
639 /// Signed integer remainder.
640 "srem" => Srem(a, b);
641
642 /// Bit-wise and.
643 "and" => And(a, b);
644
645 /// Bit-wise or.
646 "or" => Or(a, b);
647
648 /// Bit-wise xor.
649 "xor" => Xor(a, b);
650
651 /// Bit shift left. Undefined behavior if `b` is greater than or equal to `bitwidth(a)`.
652 "shl" => Shl(a, b);
653
654 /// Bit shift left where shifting out any non-sign bits is undefined
655 /// behavior.
656 "shlnsw" => ShlNsw(a, b);
657
658 /// Bit shift left where shifting out any non-zero bits is undefined
659 /// behavior.
660 "shlnuw" => ShlNuw(a, b);
661
662 /// Bit shift left where shifting out any non-zero or non-sign bits is
663 /// undefined behavior.
664 "shlnw" => ShlNw(a, b);
665
666 /// Logical bit shift right (fills left `b` bits with zero). Undefined
667 /// behavior if `b` is greater than or equal to `bitwidth(a)`.
668 "lshr" => Lshr(a, b);
669
670 /// Logical bit shift right (fills left `b` bits with zero) where it is
671 /// undefined behavior if any bits shifted out are non-zero.
672 "lshrexact" => LshrExact(a, b);
673
674 /// Arithmetic bit shift right (sign extends the left `b` bits).
675 "ashr" => Ashr(a, b);
676
677 /// Arithmetic bit shift right (fills left `b` bits with zero) where it is
678 /// undefined behavior if any bits shifted out are non-zero.
679 "ashrexact" => AshrExact(a, b);
680
681 /// If `a` is 1, then evaluates to `b`, otherwise evaluates to `c`.
682 "select" => Select(a, b, c);
683
684 /// Zero extend `a`.
685 "zext" => Zext(a);
686
687 /// Sign extend `a`.
688 "sext" => Sext(a);
689
690 /// Truncate `a`.
691 "trunc" => Trunc(a);
692
693 /// `a == b`.
694 "eq" => Eq(a, b);
695
696 /// `a != b`
697 "ne" => Ne(a, b);
698
699 /// Unsigned less than.
700 "ult" => Ult(a, b);
701
702 /// Signed less than.
703 "slt" => Slt(a, b);
704
705 /// Unsigned less than or equal.
706 "ule" => Ule(a, b);
707
708 /// Signed less than or equal.
709 "sle" => Sle(a, b);
710
711 /// Count the number of 1 bits in `a`.
712 "ctpop" => Ctpop(a);
713
714 /// Swap bytes in `a`, e.g. `0xaabbccdd` becomes `0xddccbbaa`.
715 "bswap" => Bswap(a);
716
717 /// Reverse the bits in `a`.
718 "bitreverse" => BitReverse(a);
719
720 /// Count trailing zero bits in `a`.
721 "cttz" => Cttz(a);
722
723 /// Count leading one bits in `a`.
724 "ctlz" => Ctlz(a);
725
726 /// Left funnel shift.
727 "fshl" => Fshl(a, b, c);
728
729 /// Right funnel shift.
730 "fshr" => Fshr(a, b, c);
731
732 /// Wrapping signed integer addition of `a` and `b` where the result is
733 /// extended by one bit which indicates whether the addition overflowed.
734 "sadd.with.overflow" => SaddWithOverflow(a, b);
735
736 /// Wrapping unsigned integer addition of `a` and `b` where the result is
737 /// extended by one bit which indicates whether the addition overflowed.
738 "uadd.with.overflow" => UaddWithOverflow(a, b);
739
740 /// Wrapping signed integer subtraction of `a` and `b` where the result is
741 /// extended by one bit which indicates whether the subtraction overflowed.
742 "ssub.with.overflow" => SsubWithOverflow(a, b);
743
744 /// Wrapping unsigned integer subtraction of `a` and `b` where the result is
745 /// extended by one bit which indicates whether the subtraction overflowed.
746 "usub.with.overflow" => UsubWithOverflow(a, b);
747
748 /// Wrapping signed integer multiplication of `a` and `b` where the result
749 /// is extended by one bit which indicates whether the multiplication
750 /// overflowed.
751 "smul.with.overflow" => SmulWithOverflow(a, b);
752
753 /// Wrapping unsigned integer multiplication of `a` and `b` where the result
754 /// is extended by one bit which indicates whether the multiplication
755 /// overflowed.
756 "umul.with.overflow" => UmulWithOverflow(a, b);
757
758 /// Signed saturating integer addition.
759 "sadd.sat" => SaddSat(a, b);
760
761 /// Unsigned saturating integer addition.
762 "uadd.sat" => UaddSat(a, b);
763
764 /// Signed saturating integer subtraction.
765 "ssub.sat" => SsubSat(a, b);
766
767 /// Unsigned saturating integer subtraction.
768 "usub.sat" => UsubSat(a, b);
769
770 /// Extract the `b`th value from `a`.
771 "extractvalue" => ExtractValue(a, b);
772
773 /// A hole reserved for an unknown instruction or value.
774 "hole" => Hole;
775
776 /// If `a` is a poison or undef value, returns an arbitrary but fixed
777 /// value. Otherwise returns `a`.
778 "freeze" => Freeze(a);
779}
780
781/// An operand for an instruction or some other kind of operation.
782#[derive(Copy, Clone, Debug)]
783pub enum Operand {
784 /// The id of a value defined in an earlier statement.
785 Value(ValueId),
786
787 /// A literal constant value.
788 Constant(Constant),
789}
790
791impl From<Constant> for Operand {
792 fn from(c: Constant) -> Self {
793 Operand::Constant(c)
794 }
795}
796
797impl From<ValueId> for Operand {
798 fn from(v: ValueId) -> Self {
799 Operand::Value(v)
800 }
801}
802
803/// Attributes describing data-flow facts known about the root of a left- or
804/// right-hand side.
805#[derive(Clone, Debug)]
806pub enum RootAttribute {
807 /// Which bits of the resulting value are actually used.
808 ///
809 /// The vector must have a boolean for each bit in the result type, e.g. if
810 /// the result type is `i32`, then the vector's length must be 32.
811 ///
812 /// If the `n`th entry in the vector is `true`, then the `n`th bit of the
813 /// result is used. If it is `false`, then that bit is not used.
814 DemandedBits(Vec<bool>),
815
816 /// TODO
817 HarvestedFromUse,
818}
819
820/// Attributes describing data-flow facts known about a particular value or
821/// result of an instruction.
822#[derive(Clone, Debug)]
823pub enum Attribute {
824 /// Bits that are known to be set or unset.
825 ///
826 /// The vector must have an entry for each bit in the value, e.g. if the
827 /// value's type is `i32`, then the vector's length must be 32.
828 ///
829 /// If the `i`th bit is known to be set, then the `i`th entry should be
830 /// `Some(true)`. If the `i`th bit is known to be unset, then the `i`th
831 /// entry should be `Some(false)`. If it is unknown whether the `i`th bit is
832 /// set or unset, or it can sometimes be either, then the `i`th entry should
833 /// be `None`.
834 KnownBits(Vec<Option<bool>>),
835
836 /// The value is known to be a power of two.
837 PowerOfTwo,
838
839 /// The value is known to be negative.
840 Negative,
841
842 /// The value is known to be non-negative.
843 NonNegative,
844
845 /// The value is known to be non-zero.
846 NonZero,
847
848 /// The value is used by other expressions, not just this replacement's
849 /// expression DAG.
850 HasExternalUses,
851
852 /// It is known that there are `n` sign bits in this value.
853 SignBits(u8),
854
855 /// This value is within the range `.0` (inclusive) to `.1` (exclusive).
856 Range(i128, i128),
857}
858
859/// A path condition.
860///
861/// Expresses the fact that `x` must equal `y` for the replacement to be valid.
862#[derive(Clone, Debug)]
863pub struct Pc {
864 /// A value that must be equal to `y` for the replacement to be valid.
865 pub x: Operand,
866
867 /// A value that must be equal to `x` for the replacement to be valid.
868 pub y: Operand,
869}
870
871/// A block path condition.
872///
873/// Expresses that `x` is equal to `y` on an incoming predecessor to `block` in
874/// the control-flow graph.
875#[derive(Clone, Debug)]
876pub struct BlockPc {
877 /// The basic block in question.
878 pub block: BlockId,
879
880 /// The `i`th control-flow predecessor of `block`.
881 ///
882 /// Zero-indexed: must be less than `block`'s total number of predecessors.
883 pub predecessor: u32,
884
885 /// Must be equal to `y` if control-flow entered `block` via `predecessor`.
886 pub x: Operand,
887
888 /// Must be equal to `x` if control-flow entered `block` via `predecessor`.
889 pub y: Operand,
890}
891
892/// A constant value.
893///
894/// Optionally has an ascribed type.
895#[derive(Copy, Clone, Debug)]
896pub struct Constant {
897 /// The constant value.
898 pub value: i128,
899
900 /// The ascribed type, if any.
901 pub r#type: Option<Type>,
902}
903
904/// A type.
905///
906/// All Souper types are integers, they just have different bit widths.
907#[derive(Copy, Clone, Debug)]
908pub struct Type {
909 /// The bit width of this integer type.
910 pub width: u16,
911}