Skip to content

Commit 7bf3172

Browse files
authored
Cranelift: simplify some side-effectful instructions in ISLE (#10524)
* Cranelift: simplify some side-effectful instructions in ISLE This commit adds a new top-level ISLE entrypoint specifically for instructions in the side-effectful skeleton: `simplify_skeleton`. While these rewrites are processed during the egraph pass, values from skeleton instructions still do not get inserted into the egraph. Indeed, `simplify_skeleton` operates on *instructions* rather than *values* because we do not represent side effects as values; values do not have side effects in CLIF, instructions do. Therefore, rather than doing a whole dynamic-programming style extraction of the best candidate simplification like we do with the egraph, we take an eager and greedy approach. Furthermore, `simplify_skeleton` is limited only to skeleton instructions that do not involve control-flow or terminators right now. This is because changing the control-flow graph can change whether a use is dominated by a def or not, and we do not currently have the machinery to track and fix up invalidated uses. Addressing this is left for future commits. * fix `MIN / -1` cprop and add negative tests for things simplify_skeleton cannot handle yet
1 parent b240d2c commit 7bf3172

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1002
-398
lines changed

cranelift/codegen/meta/src/gen_isle.rs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -208,25 +208,26 @@ fn gen_common_isle(
208208
";;;; Extracting Opcode, Operands, and Immediates from `InstructionData` ;;;;;;;;",
209209
);
210210
fmt.empty_line();
211-
let ret_ty = match isle_target {
212-
IsleTarget::Lower => "Inst",
213-
IsleTarget::Opt => "Value",
214-
};
215211
for inst in instructions {
216-
if isle_target == IsleTarget::Opt
217-
&& (inst.format.has_value_list || inst.value_results.len() != 1)
218-
{
219-
continue;
220-
}
212+
let results_len = inst.value_results.len();
213+
let is_var_args = inst.format.has_value_list;
214+
let has_side_effects = inst.can_trap || inst.other_side_effects;
215+
216+
let (ret_ty, ty_in_decl, make_inst_ctor, inst_data_etor) =
217+
match (isle_target, is_var_args, results_len, has_side_effects) {
218+
// The mid-end does not deal with instructions that have var-args right now.
219+
(IsleTarget::Opt, true, _, _) => continue,
220+
221+
(IsleTarget::Opt, _, 1, false) => ("Value", true, "make_inst", "inst_data_value"),
222+
(IsleTarget::Opt, _, _, _) => ("Inst", false, "make_skeleton_inst", "inst_data"),
223+
(IsleTarget::Lower, _, _, _) => ("Inst", false, "make_inst", "inst_data_value"),
224+
};
221225

222226
fmtln!(
223227
fmt,
224228
"(decl {} ({}{}) {})",
225229
inst.name,
226-
match isle_target {
227-
IsleTarget::Lower => "",
228-
IsleTarget::Opt => "Type ",
229-
},
230+
if ty_in_decl { "Type " } else { "" },
230231
inst.operands_in
231232
.iter()
232233
.map(|o| {
@@ -247,10 +248,7 @@ fn gen_common_isle(
247248
fmt,
248249
"({} {}{})",
249250
inst.name,
250-
match isle_target {
251-
IsleTarget::Lower => "",
252-
IsleTarget::Opt => "ty ",
253-
},
251+
if ty_in_decl { "ty " } else { "" },
254252
inst.operands_in
255253
.iter()
256254
.map(|o| { o.name })
@@ -259,11 +257,8 @@ fn gen_common_isle(
259257
);
260258

261259
let mut s = format!(
262-
"(inst_data{} (InstructionData.{} (Opcode.{})",
263-
match isle_target {
264-
IsleTarget::Lower => "",
265-
IsleTarget::Opt => " ty",
266-
},
260+
"({inst_data_etor} {}(InstructionData.{} (Opcode.{})",
261+
if ty_in_decl { "ty " } else { "" },
267262
inst.format.name,
268263
inst.camel_name
269264
);
@@ -367,8 +362,9 @@ fn gen_common_isle(
367362
if isle_target == IsleTarget::Opt {
368363
fmtln!(
369364
fmt,
370-
"(rule ({} ty {})",
365+
"(rule ({}{} {})",
371366
inst.name,
367+
if ty_in_decl { " ty" } else { "" },
372368
inst.operands_in
373369
.iter()
374370
.map(|o| o.name)
@@ -377,8 +373,10 @@ fn gen_common_isle(
377373
);
378374
fmt.indent(|fmt| {
379375
let mut s = format!(
380-
"(make_inst ty (InstructionData.{} (Opcode.{})",
381-
inst.format.name, inst.camel_name
376+
"({make_inst_ctor}{} (InstructionData.{} (Opcode.{})",
377+
if ty_in_decl { " ty" } else { "" },
378+
inst.format.name,
379+
inst.camel_name
382380
);
383381

384382
// Handle values. Note that we skip generating

cranelift/codegen/meta/src/isle.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub fn get_isle_compilations(
111111
src_opts.join("remat.isle"),
112112
src_opts.join("selects.isle"),
113113
src_opts.join("shifts.isle"),
114+
src_opts.join("skeleton.isle"),
114115
src_opts.join("spaceship.isle"),
115116
src_opts.join("spectre.isle"),
116117
src_opts.join("vector.isle"),

cranelift/codegen/src/cursor.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,17 @@ pub trait Cursor {
531531
inst
532532
}
533533

534+
/// Replace the instruction under the cursor with `new_inst`.
535+
///
536+
/// The cursor is left pointing at the new instruction.
537+
///
538+
/// The old instruction that was replaced is returned.
539+
fn replace_inst(&mut self, new_inst: ir::Inst) -> ir::Inst {
540+
let prev_inst = self.remove_inst();
541+
self.insert_inst(new_inst);
542+
prev_inst
543+
}
544+
534545
/// Insert a block at the current position and switch to it.
535546
///
536547
/// As far as possible, this method behaves as if the block header were an instruction inserted

0 commit comments

Comments
 (0)