1use 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}