Skip to content

Commit

Permalink
cranelift: Sign extend immediates in instructions that embed them.
Browse files Browse the repository at this point in the history
  • Loading branch information
afonso360 committed Aug 4, 2022
1 parent 301be74 commit 2dd1d08
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 144 deletions.
184 changes: 40 additions & 144 deletions cranelift/codegen/src/legalizer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

use crate::cursor::{Cursor, FuncCursor};
use crate::flowgraph::ControlFlowGraph;
use crate::ir::types::I32;
use crate::ir::types::{I128, I64};
use crate::ir::{self, InstBuilder, InstructionData, MemFlags};
use crate::isa::TargetIsa;

Expand Down Expand Up @@ -157,160 +157,56 @@ pub fn simple_legalize(func: &mut ir::Function, cfg: &mut ControlFlowGraph, isa:
offset,
} => expand_table_addr(isa, inst, &mut pos.func, table, arg, offset),

// bitops
InstructionData::BinaryImm64 {
opcode: ir::Opcode::BandImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).band(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::BorImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).bor(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::BxorImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).bxor(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::IaddImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).iadd(arg, imm);
}

// bitshifting
InstructionData::BinaryImm64 {
opcode: ir::Opcode::IshlImm,
arg,
imm,
} => {
let imm = pos.ins().iconst(I32, imm);
pos.func.dfg.replace(inst).ishl(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::RotlImm,
arg,
imm,
} => {
let imm = pos.ins().iconst(I32, imm);
pos.func.dfg.replace(inst).rotl(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::RotrImm,
arg,
imm,
} => {
let imm = pos.ins().iconst(I32, imm);
pos.func.dfg.replace(inst).rotr(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::SshrImm,
arg,
imm,
} => {
let imm = pos.ins().iconst(I32, imm);
pos.func.dfg.replace(inst).sshr(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::UshrImm,
arg,
imm,
} => {
let imm = pos.ins().iconst(I32, imm);
pos.func.dfg.replace(inst).ushr(arg, imm);
}

// math
InstructionData::BinaryImm64 {
opcode: ir::Opcode::IrsubImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).isub(imm, arg); // note: arg order reversed
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::ImulImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).imul(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::SdivImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).sdiv(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::SremImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).srem(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::UdivImm,
arg,
imm,
} => {
InstructionData::BinaryImm64 { opcode, arg, imm } => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).udiv(arg, imm);
}
InstructionData::BinaryImm64 {
opcode: ir::Opcode::UremImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).urem(arg, imm);
let imm = if ty == I128 {
let imm = pos.ins().iconst(I64, imm);
pos.ins().sextend(I128, imm)
} else {
pos.ins().iconst(ty.lane_type(), imm)
};

let replace = pos.func.dfg.replace(inst);
match opcode {
// bitops
ir::Opcode::BandImm => replace.band(arg, imm),
ir::Opcode::BorImm => replace.bor(arg, imm),
ir::Opcode::BxorImm => replace.bxor(arg, imm),
// bitshifting
ir::Opcode::IshlImm => replace.ishl(arg, imm),
ir::Opcode::RotlImm => replace.rotl(arg, imm),
ir::Opcode::RotrImm => replace.rotr(arg, imm),
ir::Opcode::SshrImm => replace.sshr(arg, imm),
ir::Opcode::UshrImm => replace.ushr(arg, imm),
// math
ir::Opcode::IaddImm => replace.iadd(arg, imm),
ir::Opcode::IrsubImm => replace.isub(imm, arg), // note: arg order reversed
ir::Opcode::ImulImm => replace.imul(arg, imm),
ir::Opcode::SdivImm => replace.sdiv(arg, imm),
ir::Opcode::SremImm => replace.srem(arg, imm),
ir::Opcode::UdivImm => replace.udiv(arg, imm),
ir::Opcode::UremImm => replace.urem(arg, imm),
// comparisons
ir::Opcode::IfcmpImm => replace.ifcmp(arg, imm),
_ => unimplemented!(),
};
}

// comparisons
InstructionData::BinaryImm64 {
opcode: ir::Opcode::IfcmpImm,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
pos.func.dfg.replace(inst).ifcmp(arg, imm);
}
InstructionData::IntCompareImm {
opcode: ir::Opcode::IcmpImm,
cond,
arg,
imm,
} => {
let ty = pos.func.dfg.value_type(arg);
let imm = pos.ins().iconst(ty, imm);
let imm = if ty == I128 {
let imm = pos.ins().iconst(I64, imm);
pos.ins().sextend(I128, imm)
} else {
pos.ins().iconst(ty.lane_type(), imm)
};

pos.func.dfg.replace(inst).icmp(cond, arg, imm);
}

Expand Down
10 changes: 10 additions & 0 deletions cranelift/filetests/filetests/runtests/i128-arithmetic.clif
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,13 @@ block0(v0: i128,v1: i128):
; run: %mul_i128(13, 0x01010101_01010101_01010101_01010101) == 0x0D0D0D0D_0D0D0D0D_0D0D0D0D_0D0D0D0D
; run: %mul_i128(0x00000000_01234567_89ABCDEF_00000000, 0x00000000_FEDCBA98_76543210_00000000) == 0x2236D88F_E5618CF0_00000000_00000000
; run: %mul_i128(0xC0FFEEEE_C0FFEEEE_C0FFEEEE_C0FFEEEE, 0xDECAFFFF_DECAFFFF_DECAFFFF_DECAFFFF) == 0x5ECD38B5_9D1C2B7E_DB6B1E48_19BA1112


; Tests that imm's are sign extended on i128's
; See: https://github.com/bytecodealliance/wasmtime/issues/4568
function %iadd_imm_neg(i128) -> i128 {
block0(v0: i128):
v1 = iadd_imm.i128 v0, -1
return v1
}
; run: %iadd_imm_neg(1) == 0

0 comments on commit 2dd1d08

Please sign in to comment.