Add general legalization for the select instruction.
This commit is contained in:
@@ -68,3 +68,13 @@ ebb0:
|
||||
; check: $v1 = bitcast.f64 $tmp
|
||||
return v1
|
||||
}
|
||||
|
||||
function %select_f64(f64, f64, i32) -> f64 {
|
||||
ebb0(v0: f64, v1: f64, v2: i32):
|
||||
v3 = select v2, v0, v1
|
||||
; check: brnz v2, $(new=$EBB)($v0)
|
||||
; nextln: jump $new($v1)
|
||||
; check: $new($v3: f64):
|
||||
; nextln: return $v3
|
||||
return v3
|
||||
}
|
||||
|
||||
32
cranelift/filetests/wasm/select.cton
Normal file
32
cranelift/filetests/wasm/select.cton
Normal file
@@ -0,0 +1,32 @@
|
||||
; Test basic code generation for the select WebAssembly instruction.
|
||||
test compile
|
||||
|
||||
set is_64bit=0
|
||||
isa intel haswell
|
||||
|
||||
set is_64bit=1
|
||||
isa intel haswell
|
||||
|
||||
function %select_i32(i32, i32, i32) -> i32 {
|
||||
ebb0(v0: i32, v1: i32, v2: i32):
|
||||
v3 = select v2, v0, v1
|
||||
return v3
|
||||
}
|
||||
|
||||
function %select_i64(i64, i64, i32) -> i64 {
|
||||
ebb0(v0: i64, v1: i64, v2: i32):
|
||||
v3 = select v2, v0, v1
|
||||
return v3
|
||||
}
|
||||
|
||||
function %select_f32(f32, f32, i32) -> f32 {
|
||||
ebb0(v0: f32, v1: f32, v2: i32):
|
||||
v3 = select v2, v0, v1
|
||||
return v3
|
||||
}
|
||||
|
||||
function %select_f64(f64, f64, i32) -> f64 {
|
||||
ebb0(v0: f64, v1: f64, v2: i32):
|
||||
v3 = select v2, v0, v1
|
||||
return v3
|
||||
}
|
||||
@@ -16,7 +16,7 @@ from .instructions import imul, imul_imm
|
||||
from .instructions import band, bor, bxor, isplit, iconcat
|
||||
from .instructions import bnot, band_not, bor_not, bxor_not
|
||||
from .instructions import icmp, icmp_imm
|
||||
from .instructions import iconst, bint
|
||||
from .instructions import iconst, bint, select
|
||||
from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm
|
||||
from .instructions import rotl, rotl_imm, rotr, rotr_imm
|
||||
from .instructions import f32const, f64const
|
||||
@@ -56,6 +56,7 @@ expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
||||
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
||||
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
|
||||
expand.custom_legalize(insts.br_table, 'expand_br_table')
|
||||
expand.custom_legalize(insts.select, 'expand_select')
|
||||
|
||||
# Custom expansions for floating point constants.
|
||||
# These expansions require bit-casting or creating constant pool entries.
|
||||
@@ -116,6 +117,16 @@ for bitop in [band, bor, bxor]:
|
||||
a << iconcat(al, ah)
|
||||
))
|
||||
|
||||
narrow.legalize(
|
||||
a << select(c, x, y),
|
||||
Rtl(
|
||||
(xl, xh) << isplit(x),
|
||||
(yl, yh) << isplit(y),
|
||||
al << select(c, xl, yl),
|
||||
ah << select(c, xh, yh),
|
||||
a << iconcat(al, ah)
|
||||
))
|
||||
|
||||
# Expand integer operations with carry for RISC architectures that don't have
|
||||
# the flags.
|
||||
expand.legalize(
|
||||
|
||||
@@ -179,6 +179,41 @@ fn expand_br_table(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlo
|
||||
cfg.recompute_ebb(pos.func, ebb);
|
||||
}
|
||||
|
||||
/// Expand the select instruction.
|
||||
///
|
||||
/// Conditional moves are available in some ISAs for some register classes. The remaining selects
|
||||
/// are handled by a branch.
|
||||
fn expand_select(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlowGraph) {
|
||||
let (ctrl, tval, fval) = match func.dfg[inst] {
|
||||
ir::InstructionData::Ternary {
|
||||
opcode: ir::Opcode::Select,
|
||||
args,
|
||||
} => (args[0], args[1], args[2]),
|
||||
_ => panic!("Expected select: {}", func.dfg.display_inst(inst, None)),
|
||||
};
|
||||
|
||||
// Replace `result = select ctrl, tval, fval` with:
|
||||
//
|
||||
// brnz ctrl, new_ebb(tval)
|
||||
// jump new_ebb(fval)
|
||||
// new_ebb(result):
|
||||
let old_ebb = func.layout.pp_ebb(inst);
|
||||
let result = func.dfg.first_result(inst);
|
||||
func.dfg.clear_results(inst);
|
||||
let new_ebb = func.dfg.make_ebb();
|
||||
func.dfg.attach_ebb_arg(new_ebb, result);
|
||||
|
||||
func.dfg.replace(inst).brnz(ctrl, new_ebb, &[tval]);
|
||||
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||
pos.use_srcloc(inst);
|
||||
pos.ins().jump(new_ebb, &[fval]);
|
||||
pos.insert_ebb(new_ebb);
|
||||
|
||||
cfg.recompute_ebb(pos.func, new_ebb);
|
||||
cfg.recompute_ebb(pos.func, old_ebb);
|
||||
}
|
||||
|
||||
|
||||
/// Expand illegal `f32const` and `f64const` instructions.
|
||||
fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) {
|
||||
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||
|
||||
Reference in New Issue
Block a user