cranelift_codegen/
opts.rs

1//! Optimization driver using ISLE rewrite rules on an egraph.
2
3use crate::egraph::{NewOrExistingInst, OptimizeCtx};
4use crate::ir::condcodes;
5pub use crate::ir::condcodes::{FloatCC, IntCC};
6use crate::ir::dfg::ValueDef;
7pub use crate::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32, Uimm64, Uimm8};
8pub use crate::ir::types::*;
9pub use crate::ir::{
10    dynamic_to_fixed, AtomicRmwOp, Block, BlockCall, Constant, DataFlowGraph, DynamicStackSlot,
11    FuncRef, GlobalValue, Immediate, InstructionData, JumpTable, MemFlags, Opcode, StackSlot,
12    Table, TrapCode, Type, Value,
13};
14use crate::isle_common_prelude_methods;
15use crate::machinst::isle::*;
16use crate::trace;
17use cranelift_entity::packed_option::ReservedValue;
18use smallvec::{smallvec, SmallVec};
19use std::marker::PhantomData;
20
21#[allow(dead_code)]
22pub type Unit = ();
23pub type Range = (usize, usize);
24pub type ValueArray2 = [Value; 2];
25pub type ValueArray3 = [Value; 3];
26
27pub type ConstructorVec<T> = SmallVec<[T; 8]>;
28
29pub(crate) mod generated_code;
30use generated_code::ContextIter;
31
32pub(crate) struct IsleContext<'a, 'b, 'c> {
33    pub(crate) ctx: &'a mut OptimizeCtx<'b, 'c>,
34}
35
36pub(crate) struct InstDataEtorIter<'a, 'b, 'c> {
37    stack: SmallVec<[Value; 8]>,
38    _phantom1: PhantomData<&'a ()>,
39    _phantom2: PhantomData<&'b ()>,
40    _phantom3: PhantomData<&'c ()>,
41}
42impl<'a, 'b, 'c> InstDataEtorIter<'a, 'b, 'c> {
43    fn new(root: Value) -> Self {
44        debug_assert_ne!(root, Value::reserved_value());
45        Self {
46            stack: smallvec![root],
47            _phantom1: PhantomData,
48            _phantom2: PhantomData,
49            _phantom3: PhantomData,
50        }
51    }
52}
53
54impl<'a, 'b, 'c> ContextIter for InstDataEtorIter<'a, 'b, 'c>
55where
56    'b: 'a,
57    'c: 'b,
58{
59    type Context = IsleContext<'a, 'b, 'c>;
60    type Output = (Type, InstructionData);
61
62    fn next(&mut self, ctx: &mut IsleContext<'a, 'b, 'c>) -> Option<Self::Output> {
63        while let Some(value) = self.stack.pop() {
64            debug_assert_ne!(value, Value::reserved_value());
65            let value = ctx.ctx.func.dfg.resolve_aliases(value);
66            trace!("iter: value {:?}", value);
67            match ctx.ctx.func.dfg.value_def(value) {
68                ValueDef::Union(x, y) => {
69                    debug_assert_ne!(x, Value::reserved_value());
70                    debug_assert_ne!(y, Value::reserved_value());
71                    trace!(" -> {}, {}", x, y);
72                    self.stack.push(x);
73                    self.stack.push(y);
74                    continue;
75                }
76                ValueDef::Result(inst, _) if ctx.ctx.func.dfg.inst_results(inst).len() == 1 => {
77                    let ty = ctx.ctx.func.dfg.value_type(value);
78                    trace!(" -> value of type {}", ty);
79                    return Some((ty, ctx.ctx.func.dfg.insts[inst].clone()));
80                }
81                _ => {}
82            }
83        }
84        None
85    }
86}
87
88impl<'a, 'b, 'c> generated_code::Context for IsleContext<'a, 'b, 'c> {
89    isle_common_prelude_methods!();
90
91    type inst_data_etor_iter = InstDataEtorIter<'a, 'b, 'c>;
92
93    fn inst_data_etor(&mut self, eclass: Value) -> InstDataEtorIter<'a, 'b, 'c> {
94        InstDataEtorIter::new(eclass)
95    }
96
97    fn make_inst_ctor(&mut self, ty: Type, op: &InstructionData) -> Value {
98        let value = self
99            .ctx
100            .insert_pure_enode(NewOrExistingInst::New(op.clone(), ty));
101        trace!("make_inst_ctor: {:?} -> {}", op, value);
102        value
103    }
104
105    fn value_array_2_ctor(&mut self, arg0: Value, arg1: Value) -> ValueArray2 {
106        [arg0, arg1]
107    }
108
109    fn value_array_3_ctor(&mut self, arg0: Value, arg1: Value, arg2: Value) -> ValueArray3 {
110        [arg0, arg1, arg2]
111    }
112
113    #[inline]
114    fn value_type(&mut self, val: Value) -> Type {
115        self.ctx.func.dfg.value_type(val)
116    }
117
118    fn remat(&mut self, value: Value) -> Value {
119        trace!("remat: {}", value);
120        self.ctx.remat_values.insert(value);
121        self.ctx.stats.remat += 1;
122        value
123    }
124
125    fn subsume(&mut self, value: Value) -> Value {
126        trace!("subsume: {}", value);
127        self.ctx.subsume_values.insert(value);
128        self.ctx.stats.subsume += 1;
129        value
130    }
131}