Add general legalization for the select instruction.

This commit is contained in:
Jakob Stoklund Olesen
2017-09-26 13:38:06 -07:00
parent ce767be703
commit 6ff681a90d
4 changed files with 89 additions and 1 deletions

View File

@@ -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
}

View 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
}

View File

@@ -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(

View File

@@ -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));