Basic-block: Insert regmove instructions in new blocks dedicated to hold the diversions.

This commit is contained in:
Nicolas B. Pierron
2019-09-05 14:55:35 +02:00
committed by GitHub
parent 0f4101a509
commit 7e398af999
8 changed files with 264 additions and 22 deletions

View File

@@ -212,7 +212,7 @@ impl Context {
/// Run the locations verifier on the function. /// Run the locations verifier on the function.
pub fn verify_locations(&self, isa: &dyn TargetIsa) -> VerifierResult<()> { pub fn verify_locations(&self, isa: &dyn TargetIsa) -> VerifierResult<()> {
let mut errors = VerifierErrors::default(); let mut errors = VerifierErrors::default();
let _ = verify_locations(isa, &self.func, None, &mut errors); let _ = verify_locations(isa, &self.func, &self.cfg, None, &mut errors);
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())

View File

@@ -44,18 +44,19 @@
use crate::cursor::{Cursor, EncCursor}; use crate::cursor::{Cursor, EncCursor};
use crate::dominator_tree::DominatorTree; use crate::dominator_tree::DominatorTree;
use crate::flowgraph::ControlFlowGraph;
use crate::ir::{ArgumentLoc, InstBuilder, ValueDef}; use crate::ir::{ArgumentLoc, InstBuilder, ValueDef};
use crate::ir::{Ebb, Function, Inst, InstructionData, Layout, Opcode, SigRef, Value, ValueLoc}; use crate::ir::{Ebb, Function, Inst, InstructionData, Layout, Opcode, SigRef, Value, ValueLoc};
use crate::isa::{regs_overlap, RegClass, RegInfo, RegUnit}; use crate::isa::{regs_overlap, RegClass, RegInfo, RegUnit};
use crate::isa::{ConstraintKind, EncInfo, OperandConstraint, RecipeConstraints, TargetIsa}; use crate::isa::{ConstraintKind, EncInfo, OperandConstraint, RecipeConstraints, TargetIsa};
use crate::packed_option::PackedOption; use crate::packed_option::PackedOption;
use crate::regalloc::affinity::Affinity; use crate::regalloc::affinity::Affinity;
use crate::regalloc::diversion::RegDiversions;
use crate::regalloc::live_value_tracker::{LiveValue, LiveValueTracker}; use crate::regalloc::live_value_tracker::{LiveValue, LiveValueTracker};
use crate::regalloc::liveness::Liveness; use crate::regalloc::liveness::Liveness;
use crate::regalloc::liverange::{LiveRange, LiveRangeContext}; use crate::regalloc::liverange::{LiveRange, LiveRangeContext};
use crate::regalloc::register_set::RegisterSet; use crate::regalloc::register_set::RegisterSet;
use crate::regalloc::solver::{Solver, SolverError}; use crate::regalloc::solver::{Solver, SolverError};
use crate::regalloc::RegDiversions;
use crate::timing; use crate::timing;
use core::mem; use core::mem;
use log::debug; use log::debug;
@@ -92,6 +93,7 @@ struct Context<'a> {
encinfo: EncInfo, encinfo: EncInfo,
// References to contextual data structures we need. // References to contextual data structures we need.
cfg: &'a ControlFlowGraph,
domtree: &'a DominatorTree, domtree: &'a DominatorTree,
liveness: &'a mut Liveness, liveness: &'a mut Liveness,
@@ -126,6 +128,7 @@ impl Coloring {
&mut self, &mut self,
isa: &dyn TargetIsa, isa: &dyn TargetIsa,
func: &mut Function, func: &mut Function,
cfg: &ControlFlowGraph,
domtree: &DominatorTree, domtree: &DominatorTree,
liveness: &mut Liveness, liveness: &mut Liveness,
tracker: &mut LiveValueTracker, tracker: &mut LiveValueTracker,
@@ -137,6 +140,7 @@ impl Coloring {
cur: EncCursor::new(func, isa), cur: EncCursor::new(func, isa),
reginfo: isa.register_info(), reginfo: isa.register_info(),
encinfo: isa.encoding_info(), encinfo: isa.encoding_info(),
cfg,
domtree, domtree,
liveness, liveness,
divert: &mut self.divert, divert: &mut self.divert,
@@ -166,13 +170,13 @@ impl<'a> Context<'a> {
debug!("Coloring {}:", ebb); debug!("Coloring {}:", ebb);
let mut regs = self.visit_ebb_header(ebb, tracker); let mut regs = self.visit_ebb_header(ebb, tracker);
tracker.drop_dead_params(); tracker.drop_dead_params();
self.divert.clear();
// Now go through the instructions in `ebb` and color the values they define. // Now go through the instructions in `ebb` and color the values they define.
self.cur.goto_top(ebb); self.cur.goto_top(ebb);
while let Some(inst) = self.cur.next_inst() { while let Some(inst) = self.cur.next_inst() {
self.cur.use_srcloc(inst); self.cur.use_srcloc(inst);
if !self.cur.func.dfg[inst].opcode().is_ghost() { let opcode = self.cur.func.dfg[inst].opcode();
if !opcode.is_ghost() {
// This is an instruction which either has an encoding or carries ABI-related // This is an instruction which either has an encoding or carries ABI-related
// register allocation constraints. // register allocation constraints.
let enc = self.cur.func.encodings[inst]; let enc = self.cur.func.encodings[inst];
@@ -189,6 +193,54 @@ impl<'a> Context<'a> {
self.process_ghost_kills(kills, &mut regs); self.process_ghost_kills(kills, &mut regs);
} }
tracker.drop_dead(inst); tracker.drop_dead(inst);
// We are not able to insert any regmove for diversion or un-diversion after the first
// branch. Instead, we record the diversion to be restored at the entry of the next EBB,
// which should have a single predecessor.
if opcode.is_branch() && cfg!(feature = "basic-blocks") {
// The next instruction is necessarily an unconditional branch.
if let Some(branch) = self.cur.next_inst() {
debug!(
"Skip coloring {}\n from {}\n with diversions {}",
self.cur.display_inst(branch),
regs.input.display(&self.reginfo),
self.divert.display(&self.reginfo)
);
use crate::ir::instructions::BranchInfo::*;
let target = match self.cur.func.dfg.analyze_branch(branch) {
NotABranch | Table(_, _) => panic!(
"unexpected instruction {} after a conditional branch",
self.cur.display_inst(branch)
),
SingleDest(ebb, _) => ebb,
};
// We have a single branch with a single target, and an EBB with a single
// predecessor. Thus we can forward the diversion set to the next EBB.
if self.cfg.pred_iter(target).count() == 1 {
// Transfer the diversion to the next EBB.
self.divert
.save_for_ebb(&mut self.cur.func.entry_diversions, target);
debug!(
"Set entry-diversion for {} to\n {}",
target,
self.divert.display(&self.reginfo)
);
} else {
debug_assert!(
self.divert.is_empty(),
"Divert set is non-empty after the terminator."
);
}
assert_eq!(
self.cur.next_inst(),
None,
"Unexpected instruction after a branch group."
);
} else {
assert!(opcode.is_terminator());
}
}
} }
} }
@@ -205,7 +257,15 @@ impl<'a> Context<'a> {
self.domtree, self.domtree,
); );
// Copy the content of the registered diversions to be reused at the
// entry of this basic block.
self.divert.at_ebb(&self.cur.func.entry_diversions, ebb); self.divert.at_ebb(&self.cur.func.entry_diversions, ebb);
debug!(
"Start {} with entry-diversion set to\n {}",
ebb,
self.divert.display(&self.reginfo)
);
if self.cur.func.layout.entry_block() == Some(ebb) { if self.cur.func.layout.entry_block() == Some(ebb) {
// Parameters on the entry block have ABI constraints. // Parameters on the entry block have ABI constraints.
self.color_entry_params(tracker.live()) self.color_entry_params(tracker.live())
@@ -231,17 +291,35 @@ impl<'a> Context<'a> {
"Live-in: {}:{} in {}", "Live-in: {}:{} in {}",
lv.value, lv.value,
lv.affinity.display(&self.reginfo), lv.affinity.display(&self.reginfo),
self.cur.func.locations[lv.value].display(&self.reginfo) self.divert
.get(lv.value, &self.cur.func.locations)
.display(&self.reginfo)
); );
if let Affinity::Reg(rci) = lv.affinity { if let Affinity::Reg(rci) = lv.affinity {
let rc = self.reginfo.rc(rci); let rc = self.reginfo.rc(rci);
let loc = self.cur.func.locations[lv.value]; let loc = self.cur.func.locations[lv.value];
match loc { let reg = match loc {
ValueLoc::Reg(reg) => regs.take(rc, reg, lv.is_local), ValueLoc::Reg(reg) => reg,
ValueLoc::Unassigned => panic!("Live-in {} wasn't assigned", lv.value), ValueLoc::Unassigned => panic!("Live-in {} wasn't assigned", lv.value),
ValueLoc::Stack(ss) => { ValueLoc::Stack(ss) => {
panic!("Live-in {} is in {}, should be register", lv.value, ss) panic!("Live-in {} is in {}, should be register", lv.value, ss)
} }
};
if lv.is_local {
regs.take(rc, reg, lv.is_local);
} else {
let loc = self.divert.get(lv.value, &self.cur.func.locations);
let reg_divert = match loc {
ValueLoc::Reg(reg) => reg,
ValueLoc::Unassigned => {
panic!("Diversion: Live-in {} wasn't assigned", lv.value)
}
ValueLoc::Stack(ss) => panic!(
"Diversion: Live-in {} is in {}, should be register",
lv.value, ss
),
};
regs.take_divert(rc, reg, reg_divert);
} }
} }
} }
@@ -1155,4 +1233,10 @@ impl AvailableRegs {
self.global.take(rc, reg); self.global.take(rc, reg);
} }
} }
/// Take a diverted register from both sets for a non-local allocation.
pub fn take_divert(&mut self, rc: RegClass, reg: RegUnit, reg_divert: RegUnit) {
self.input.take(rc, reg_divert);
self.global.take(rc, reg);
}
} }

View File

@@ -198,8 +198,14 @@ impl Context {
} }
// Pass: Coloring. // Pass: Coloring.
self.coloring self.coloring.run(
.run(isa, func, domtree, &mut self.liveness, &mut self.tracker); isa,
func,
cfg,
domtree,
&mut self.liveness,
&mut self.tracker,
);
// This function runs after register allocation has taken // This function runs after register allocation has taken
// place, meaning values have locations assigned already. // place, meaning values have locations assigned already.
@@ -218,7 +224,7 @@ impl Context {
if isa.flags().enable_verifier() { if isa.flags().enable_verifier() {
let ok = verify_context(func, cfg, domtree, isa, &mut errors).is_ok() let ok = verify_context(func, cfg, domtree, isa, &mut errors).is_ok()
&& verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok() && verify_liveness(isa, func, cfg, &self.liveness, &mut errors).is_ok()
&& verify_locations(isa, func, Some(&self.liveness), &mut errors).is_ok() && verify_locations(isa, func, cfg, Some(&self.liveness), &mut errors).is_ok()
&& verify_cssa( && verify_cssa(
func, func,
cfg, cfg,

View File

@@ -1,5 +1,6 @@
//! Verify value locations. //! Verify value locations.
use crate::flowgraph::ControlFlowGraph;
use crate::ir; use crate::ir;
use crate::isa; use crate::isa;
use crate::regalloc::liveness::Liveness; use crate::regalloc::liveness::Liveness;
@@ -21,6 +22,7 @@ use crate::verifier::{VerifierErrors, VerifierStepResult};
pub fn verify_locations( pub fn verify_locations(
isa: &dyn isa::TargetIsa, isa: &dyn isa::TargetIsa,
func: &ir::Function, func: &ir::Function,
cfg: &ControlFlowGraph,
liveness: Option<&Liveness>, liveness: Option<&Liveness>,
errors: &mut VerifierErrors, errors: &mut VerifierErrors,
) -> VerifierStepResult<()> { ) -> VerifierStepResult<()> {
@@ -30,6 +32,7 @@ pub fn verify_locations(
func, func,
reginfo: isa.register_info(), reginfo: isa.register_info(),
encinfo: isa.encoding_info(), encinfo: isa.encoding_info(),
cfg,
liveness, liveness,
}; };
verifier.check_constraints(errors)?; verifier.check_constraints(errors)?;
@@ -41,6 +44,7 @@ struct LocationVerifier<'a> {
func: &'a ir::Function, func: &'a ir::Function,
reginfo: isa::RegInfo, reginfo: isa::RegInfo,
encinfo: isa::EncInfo, encinfo: isa::EncInfo,
cfg: &'a ControlFlowGraph,
liveness: Option<&'a Liveness>, liveness: Option<&'a Liveness>,
} }
@@ -53,6 +57,7 @@ impl<'a> LocationVerifier<'a> {
for ebb in self.func.layout.ebbs() { for ebb in self.func.layout.ebbs() {
divert.at_ebb(&self.func.entry_diversions, ebb); divert.at_ebb(&self.func.entry_diversions, ebb);
let mut is_after_branch = false;
for inst in self.func.layout.ebb_insts(ebb) { for inst in self.func.layout.ebb_insts(ebb) {
let enc = self.func.encodings[inst]; let enc = self.func.encodings[inst];
@@ -70,10 +75,11 @@ impl<'a> LocationVerifier<'a> {
if opcode.is_return() { if opcode.is_return() {
self.check_return_abi(inst, &divert, errors)?; self.check_return_abi(inst, &divert, errors)?;
} else if opcode.is_branch() && !divert.is_empty() { } else if opcode.is_branch() && !divert.is_empty() {
self.check_cfg_edges(inst, &divert, errors)?; self.check_cfg_edges(inst, &mut divert, is_after_branch, errors)?;
} }
self.update_diversions(inst, &mut divert, errors)?; self.update_diversions(inst, &mut divert, errors)?;
is_after_branch = opcode.is_branch();
} }
} }
@@ -284,8 +290,9 @@ impl<'a> LocationVerifier<'a> {
return fatal!( return fatal!(
errors, errors,
inst, inst,
"inconsistent with global location {}", "inconsistent with global location {} ({})",
self.func.locations[arg].display(&self.reginfo) self.func.locations[arg].display(&self.reginfo),
self.func.dfg.display_inst(inst, None)
); );
} }
@@ -299,37 +306,52 @@ impl<'a> LocationVerifier<'a> {
fn check_cfg_edges( fn check_cfg_edges(
&self, &self,
inst: ir::Inst, inst: ir::Inst,
divert: &RegDiversions, divert: &mut RegDiversions,
is_after_branch: bool,
errors: &mut VerifierErrors, errors: &mut VerifierErrors,
) -> VerifierStepResult<()> { ) -> VerifierStepResult<()> {
use crate::ir::instructions::BranchInfo::*; use crate::ir::instructions::BranchInfo::*;
let dfg = &self.func.dfg;
let branch_kind = dfg.analyze_branch(inst);
// We can only check CFG edges if we have a liveness analysis. // We can only check CFG edges if we have a liveness analysis.
let liveness = match self.liveness { let liveness = match self.liveness {
Some(l) => l, Some(l) => l,
None => return Ok(()), None => return Ok(()),
}; };
let dfg = &self.func.dfg;
match dfg.analyze_branch(inst) { match branch_kind {
NotABranch => panic!( NotABranch => panic!(
"No branch information for {}", "No branch information for {}",
dfg.display_inst(inst, self.isa) dfg.display_inst(inst, self.isa)
), ),
SingleDest(ebb, _) => { SingleDest(ebb, _) => {
let unique_predecessor = self.cfg.pred_iter(ebb).count() == 1;
let mut val_to_remove = vec![];
for (&value, d) in divert.iter() { for (&value, d) in divert.iter() {
let lr = &liveness[value]; let lr = &liveness[value];
if lr.is_livein(ebb, liveness.context(&self.func.layout)) { if is_after_branch && unique_predecessor {
// Forward diversions based on the targeted branch.
if !lr.is_livein(ebb, liveness.context(&self.func.layout)) {
val_to_remove.push(value)
}
} else if lr.is_livein(ebb, liveness.context(&self.func.layout)) {
return fatal!( return fatal!(
errors, errors,
inst, inst,
"{} is diverted to {} and live in to {}", "SingleDest: {} is diverted to {} and live in to {}",
value, value,
d.to.display(&self.reginfo), d.to.display(&self.reginfo),
ebb ebb
); );
} }
} }
if is_after_branch && unique_predecessor {
for val in val_to_remove.into_iter() {
divert.remove(val);
}
debug_assert!(divert.check_ebb_entry(&self.func.entry_diversions, ebb));
}
} }
Table(jt, ebb) => { Table(jt, ebb) => {
for (&value, d) in divert.iter() { for (&value, d) in divert.iter() {
@@ -339,7 +361,7 @@ impl<'a> LocationVerifier<'a> {
return fatal!( return fatal!(
errors, errors,
inst, inst,
"{} is diverted to {} and live in to {}", "Table.default: {} is diverted to {} and live in to {}",
value, value,
d.to.display(&self.reginfo), d.to.display(&self.reginfo),
ebb ebb
@@ -351,7 +373,7 @@ impl<'a> LocationVerifier<'a> {
return fatal!( return fatal!(
errors, errors,
inst, inst,
"{} is diverted to {} and live in to {}", "Table.case: {} is diverted to {} and live in to {}",
value, value,
d.to.display(&self.reginfo), d.to.display(&self.reginfo),
ebb ebb

View File

@@ -1,6 +1,7 @@
test compile test compile
target x86_64 target x86_64
feature !"basic-blocks"
; regex: V=v\d+ ; regex: V=v\d+
; regex: EBB=ebb\d+ ; regex: EBB=ebb\d+

View File

@@ -1,7 +1,7 @@
test safepoint test safepoint
set enable_safepoints=true set enable_safepoints=true
target x86_64 target x86_64
feature !"basic-blocks"
function %test(i32, r64, r64) -> r64 { function %test(i32, r64, r64) -> r64 {
ebb0(v0: i32, v1:r64, v2:r64): ebb0(v0: i32, v1:r64, v2:r64):

View File

@@ -1,7 +1,7 @@
test safepoint test safepoint
set enable_safepoints=true set enable_safepoints=true
target x86_64 target x86_64
feature !"basic-blocks"
function %direct() -> r64 { function %direct() -> r64 {
fn0 = %none() fn0 = %none()

View File

@@ -554,6 +554,9 @@ ebb18:
v196 = load.i8 v195 v196 = load.i8 v195
v197 = uextend.i32 v196 v197 = uextend.i32 v196
brz v197, ebb19 brz v197, ebb19
jump ebb164
ebb164:
v198 = global_value.i64 gv12 v198 = global_value.i64 gv12
trap user0 trap user0
@@ -572,6 +575,9 @@ ebb19:
v209 = load.i8 v208 v209 = load.i8 v208
v210 = uextend.i32 v209 v210 = uextend.i32 v209
brz v210, ebb20 brz v210, ebb20
jump ebb163
ebb163:
v211 = global_value.i64 gv13 v211 = global_value.i64 gv13
trap user0 trap user0
@@ -605,6 +611,9 @@ ebb22:
v233 = load.i8 v232 v233 = load.i8 v232
v234 = uextend.i32 v233 v234 = uextend.i32 v233
brz v234, ebb23 brz v234, ebb23
jump ebb162
ebb162:
v235 = global_value.i64 gv16 v235 = global_value.i64 gv16
trap user0 trap user0
@@ -630,6 +639,9 @@ ebb24:
v252 = load.i8 v251 v252 = load.i8 v251
v253 = uextend.i32 v252 v253 = uextend.i32 v252
brz v253, ebb25 brz v253, ebb25
jump ebb161
ebb161:
v254 = global_value.i64 gv17 v254 = global_value.i64 gv17
trap user0 trap user0
@@ -666,6 +678,9 @@ ebb27:
v278 = load.i8 v277 v278 = load.i8 v277
v279 = uextend.i32 v278 v279 = uextend.i32 v278
brz v279, ebb28 brz v279, ebb28
jump ebb160
ebb160:
v280 = global_value.i64 gv18 v280 = global_value.i64 gv18
trap user0 trap user0
@@ -681,6 +696,9 @@ ebb28:
v289 = load.i8 v288 v289 = load.i8 v288
v290 = uextend.i32 v289 v290 = uextend.i32 v289
brz v290, ebb29 brz v290, ebb29
jump ebb159
ebb159:
v291 = global_value.i64 gv19 v291 = global_value.i64 gv19
trap user0 trap user0
@@ -699,6 +717,9 @@ ebb29:
v302 = load.i8 v301 v302 = load.i8 v301
v303 = uextend.i32 v302 v303 = uextend.i32 v302
brz v303, ebb30 brz v303, ebb30
jump ebb158
ebb158:
v304 = global_value.i64 gv20 v304 = global_value.i64 gv20
trap user0 trap user0
@@ -714,6 +735,9 @@ ebb30:
v313 = load.i8 v312 v313 = load.i8 v312
v314 = uextend.i32 v313 v314 = uextend.i32 v313
brz v314, ebb31 brz v314, ebb31
jump ebb157
ebb157:
v315 = global_value.i64 gv21 v315 = global_value.i64 gv21
trap user0 trap user0
@@ -887,6 +911,9 @@ ebb49(v1006: i16):
v411 = load.i8 v410 v411 = load.i8 v410
v412 = uextend.i32 v411 v412 = uextend.i32 v411
brz v412, ebb50 brz v412, ebb50
jump ebb156
ebb156:
v413 = global_value.i64 gv28 v413 = global_value.i64 gv28
trap user0 trap user0
@@ -908,6 +935,9 @@ ebb50:
v424 = load.i8 v423 v424 = load.i8 v423
v425 = uextend.i32 v424 v425 = uextend.i32 v424
brz v425, ebb51 brz v425, ebb51
jump ebb155
ebb155:
v426 = global_value.i64 gv29 v426 = global_value.i64 gv29
trap user0 trap user0
@@ -922,6 +952,9 @@ ebb51:
v432 = bint.i8 v431 v432 = bint.i8 v431
v433 = uextend.i32 v432 v433 = uextend.i32 v432
brz v433, ebb52 brz v433, ebb52
jump ebb154
ebb154:
v434 = global_value.i64 gv30 v434 = global_value.i64 gv30
trap user0 trap user0
@@ -941,6 +974,9 @@ ebb52:
v447 = load.i8 v446 v447 = load.i8 v446
v448 = uextend.i32 v447 v448 = uextend.i32 v447
brz v448, ebb53 brz v448, ebb53
jump ebb153
ebb153:
v449 = global_value.i64 gv31 v449 = global_value.i64 gv31
trap user0 trap user0
@@ -960,6 +996,9 @@ ebb53:
v462 = load.i8 v461 v462 = load.i8 v461
v463 = uextend.i32 v462 v463 = uextend.i32 v462
brz v463, ebb54 brz v463, ebb54
jump ebb152
ebb152:
v464 = global_value.i64 gv32 v464 = global_value.i64 gv32
trap user0 trap user0
@@ -976,6 +1015,9 @@ ebb54:
v474 = load.i8 v473 v474 = load.i8 v473
v475 = uextend.i32 v474 v475 = uextend.i32 v474
brz v475, ebb55 brz v475, ebb55
jump ebb151
ebb151:
v476 = global_value.i64 gv33 v476 = global_value.i64 gv33
trap user0 trap user0
@@ -1002,6 +1044,9 @@ ebb56:
v493 = load.i8 v492 v493 = load.i8 v492
v494 = uextend.i32 v493 v494 = uextend.i32 v493
brz v494, ebb57 brz v494, ebb57
jump ebb150
ebb150:
v495 = global_value.i64 gv34 v495 = global_value.i64 gv34
trap user0 trap user0
@@ -1017,6 +1062,9 @@ ebb57:
v504 = load.i8 v503 v504 = load.i8 v503
v505 = uextend.i32 v504 v505 = uextend.i32 v504
brz v505, ebb58 brz v505, ebb58
jump ebb149
ebb149:
v506 = global_value.i64 gv35 v506 = global_value.i64 gv35
trap user0 trap user0
@@ -1032,6 +1080,9 @@ ebb58:
v517 = load.i8 v516 v517 = load.i8 v516
v518 = uextend.i32 v517 v518 = uextend.i32 v517
brz v518, ebb59 brz v518, ebb59
jump ebb148
ebb148:
v519 = global_value.i64 gv36 v519 = global_value.i64 gv36
trap user0 trap user0
@@ -1049,6 +1100,9 @@ ebb59:
v530 = load.i8 v529 v530 = load.i8 v529
v531 = uextend.i32 v530 v531 = uextend.i32 v530
brz v531, ebb60 brz v531, ebb60
jump ebb147
ebb147:
v532 = global_value.i64 gv37 v532 = global_value.i64 gv37
trap user0 trap user0
@@ -1065,6 +1119,9 @@ ebb60:
v542 = load.i8 v541 v542 = load.i8 v541
v543 = uextend.i32 v542 v543 = uextend.i32 v542
brz v543, ebb61 brz v543, ebb61
jump ebb146
ebb146:
v544 = global_value.i64 gv38 v544 = global_value.i64 gv38
trap user0 trap user0
@@ -1118,6 +1175,9 @@ ebb62(v552: i32, v1009: i64, v1013: i64, v1016: i64, v1019: i64, v1022: i16, v10
v556 = bint.i8 v555 v556 = bint.i8 v555
v557 = uextend.i32 v556 v557 = uextend.i32 v556
brz v557, ebb63 brz v557, ebb63
jump ebb145
ebb145:
v558 = global_value.i64 gv39 v558 = global_value.i64 gv39
trap user0 trap user0
@@ -1131,6 +1191,9 @@ ebb63:
v566 = bint.i8 v565 v566 = bint.i8 v565
v567 = uextend.i32 v566 v567 = uextend.i32 v566
brz v567, ebb64 brz v567, ebb64
jump ebb144
ebb144:
v568 = global_value.i64 gv40 v568 = global_value.i64 gv40
trap user0 trap user0
@@ -1175,6 +1238,9 @@ ebb68(v584: i32):
v593 = load.i8 v592 v593 = load.i8 v592
v594 = uextend.i32 v593 v594 = uextend.i32 v593
brz v594, ebb69 brz v594, ebb69
jump ebb143
ebb143:
v595 = global_value.i64 gv43 v595 = global_value.i64 gv43
trap user0 trap user0
@@ -1185,6 +1251,9 @@ ebb69:
v600 = bint.i8 v599 v600 = bint.i8 v599
v601 = uextend.i32 v600 v601 = uextend.i32 v600
brnz v601, ebb70 brnz v601, ebb70
jump ebb142
ebb142:
v602 = global_value.i64 gv44 v602 = global_value.i64 gv44
trap user0 trap user0
@@ -1205,6 +1274,9 @@ ebb70:
v618 = load.i8 v617 v618 = load.i8 v617
v619 = uextend.i32 v618 v619 = uextend.i32 v618
brz v619, ebb71 brz v619, ebb71
jump ebb141
ebb141:
v620 = global_value.i64 gv45 v620 = global_value.i64 gv45
trap user0 trap user0
@@ -1225,6 +1297,9 @@ ebb71:
v632 = load.i8 v631 v632 = load.i8 v631
v633 = uextend.i32 v632 v633 = uextend.i32 v632
brz v633, ebb72 brz v633, ebb72
jump ebb140
ebb140:
v634 = global_value.i64 gv46 v634 = global_value.i64 gv46
trap user0 trap user0
@@ -1240,6 +1315,9 @@ ebb72:
v644 = load.i8 v643 v644 = load.i8 v643
v645 = uextend.i32 v644 v645 = uextend.i32 v644
brz v645, ebb73 brz v645, ebb73
jump ebb139
ebb139:
v646 = global_value.i64 gv47 v646 = global_value.i64 gv47
trap user0 trap user0
@@ -1266,6 +1344,9 @@ ebb74:
v662 = load.i8 v661 v662 = load.i8 v661
v663 = uextend.i32 v662 v663 = uextend.i32 v662
brz v663, ebb75 brz v663, ebb75
jump ebb138
ebb138:
v664 = global_value.i64 gv48 v664 = global_value.i64 gv48
trap user0 trap user0
@@ -1294,6 +1375,9 @@ ebb76:
v686 = load.i8 v685 v686 = load.i8 v685
v687 = uextend.i32 v686 v687 = uextend.i32 v686
brz v687, ebb77 brz v687, ebb77
jump ebb137
ebb137:
v688 = global_value.i64 gv49 v688 = global_value.i64 gv49
trap user0 trap user0
@@ -1465,6 +1549,9 @@ ebb96:
v790 = load.i8 v789 v790 = load.i8 v789
v791 = uextend.i32 v790 v791 = uextend.i32 v790
brz v791, ebb97 brz v791, ebb97
jump ebb136
ebb136:
v792 = global_value.i64 gv58 v792 = global_value.i64 gv58
trap user0 trap user0
@@ -1476,6 +1563,9 @@ ebb97:
v797 = bint.i8 v796 v797 = bint.i8 v796
v798 = uextend.i32 v797 v798 = uextend.i32 v797
brz v798, ebb98 brz v798, ebb98
jump ebb135
ebb135:
v799 = global_value.i64 gv59 v799 = global_value.i64 gv59
trap user0 trap user0
@@ -1515,6 +1605,9 @@ ebb99(v804: i64, v1035: i64, v1037: i64, v1039: i64, v1044: i64, v1052: i16, v10
v813 = load.i8 v812 v813 = load.i8 v812
v814 = uextend.i32 v813 v814 = uextend.i32 v813
brz v814, ebb100 brz v814, ebb100
jump ebb134
ebb134:
v815 = global_value.i64 gv60 v815 = global_value.i64 gv60
trap user0 trap user0
@@ -1534,6 +1627,9 @@ ebb100:
v826 = load.i8 v825 v826 = load.i8 v825
v827 = uextend.i32 v826 v827 = uextend.i32 v826
brz v827, ebb101 brz v827, ebb101
jump ebb133
ebb133:
v828 = global_value.i64 gv61 v828 = global_value.i64 gv61
trap user0 trap user0
@@ -1555,6 +1651,9 @@ ebb101:
v839 = load.i8 v838 v839 = load.i8 v838
v840 = uextend.i32 v839 v840 = uextend.i32 v839
brz v840, ebb102 brz v840, ebb102
jump ebb132
ebb132:
v841 = global_value.i64 gv62 v841 = global_value.i64 gv62
trap user0 trap user0
@@ -1574,6 +1673,9 @@ ebb102:
v852 = load.i8 v851 v852 = load.i8 v851
v853 = uextend.i32 v852 v853 = uextend.i32 v852
brz v853, ebb103 brz v853, ebb103
jump ebb131
ebb131:
v854 = global_value.i64 gv63 v854 = global_value.i64 gv63
trap user0 trap user0
@@ -1591,6 +1693,9 @@ ebb103:
v866 = load.i8 v865 v866 = load.i8 v865
v867 = uextend.i32 v866 v867 = uextend.i32 v866
brz v867, ebb104 brz v867, ebb104
jump ebb130
ebb130:
v868 = global_value.i64 gv64 v868 = global_value.i64 gv64
trap user0 trap user0
@@ -1607,6 +1712,9 @@ ebb104:
v878 = load.i8 v877 v878 = load.i8 v877
v879 = uextend.i32 v878 v879 = uextend.i32 v878
brz v879, ebb105 brz v879, ebb105
jump ebb129
ebb129:
v880 = global_value.i64 gv65 v880 = global_value.i64 gv65
trap user0 trap user0
@@ -1654,6 +1762,9 @@ ebb109(v896: i64):
v905 = load.i8 v904 v905 = load.i8 v904
v906 = uextend.i32 v905 v906 = uextend.i32 v905
brz v906, ebb110 brz v906, ebb110
jump ebb128
ebb128:
v907 = global_value.i64 gv68 v907 = global_value.i64 gv68
trap user0 trap user0
@@ -1664,6 +1775,9 @@ ebb110:
v912 = bint.i8 v911 v912 = bint.i8 v911
v913 = uextend.i32 v912 v913 = uextend.i32 v912
brnz v913, ebb111 brnz v913, ebb111
jump ebb127
ebb127:
v914 = global_value.i64 gv69 v914 = global_value.i64 gv69
trap user0 trap user0
@@ -1684,6 +1798,9 @@ ebb111:
v930 = load.i8 v929 v930 = load.i8 v929
v931 = uextend.i32 v930 v931 = uextend.i32 v930
brz v931, ebb112 brz v931, ebb112
jump ebb126
ebb126:
v932 = global_value.i64 gv70 v932 = global_value.i64 gv70
trap user0 trap user0
@@ -1709,6 +1826,9 @@ ebb113:
v948 = load.i8 v947 v948 = load.i8 v947
v949 = uextend.i32 v948 v949 = uextend.i32 v948
brz v949, ebb114 brz v949, ebb114
jump ebb125
ebb125:
v950 = global_value.i64 gv71 v950 = global_value.i64 gv71
trap user0 trap user0
@@ -1737,6 +1857,9 @@ ebb115:
v972 = load.i8 v971 v972 = load.i8 v971
v973 = uextend.i32 v972 v973 = uextend.i32 v972
brz v973, ebb116 brz v973, ebb116
jump ebb123
ebb123:
v974 = global_value.i64 gv72 v974 = global_value.i64 gv72
trap user0 trap user0
@@ -1752,6 +1875,9 @@ ebb116:
v984 = load.i8 v983 v984 = load.i8 v983
v985 = uextend.i32 v984 v985 = uextend.i32 v984
brz v985, ebb117 brz v985, ebb117
jump ebb122
ebb122:
v986 = global_value.i64 gv73 v986 = global_value.i64 gv73
trap user0 trap user0
@@ -1775,6 +1901,9 @@ ebb119:
v1001 = load.i8 v1000 v1001 = load.i8 v1000
v1002 = uextend.i32 v1001 v1002 = uextend.i32 v1001
brz v1002, ebb120 brz v1002, ebb120
jump ebb121
ebb121:
v1003 = global_value.i64 gv74 v1003 = global_value.i64 gv74
trap user0 trap user0