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}