From 29c449f117c32fc7bd042dd056e87ceb6e77a128 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 27 Sep 2016 16:22:32 -0700 Subject: [PATCH] Add legalization helper instructions. The isplit_lohi instruction breaks an integer into two halves. This will typically be used to get the two halves of an `i64` value on 32-bit CPUs. The iconcat_lohi is the reverse operation. It reconstructs the `i64` from the low and high bits. --- docs/langref.rst | 8 +++++++ meta/cretonne/base.py | 38 ++++++++++++++++++++++++++++++ meta/cretonne/formats.py | 1 + src/libcretonne/ir/instructions.rs | 6 +++++ src/libcretonne/write.rs | 1 + src/libreader/parser.rs | 9 +++++++ 6 files changed, 63 insertions(+) diff --git a/docs/langref.rst b/docs/langref.rst index e42d82ecf4..e4d2d9dbd3 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -823,6 +823,14 @@ Conversion operations .. autoinst:: fcvt_from_uint .. autoinst:: fcvt_from_sint +Legalization operations +----------------------- + +These instructions are used as helpers when legalizing types and operations for +the target ISA. + +.. autoinst:: isplit_lohi +.. autoinst:: iconcat_lohi Base instruction group ====================== diff --git a/meta/cretonne/base.py b/meta/cretonne/base.py index fdca2484f9..fc8de5d78f 100644 --- a/meta/cretonne/base.py +++ b/meta/cretonne/base.py @@ -1105,4 +1105,42 @@ fcvt_from_sint = Instruction( """, ins=x, outs=a) +# +# Legalization helper instructions. +# + +WideInt = TypeVar( + 'WideInt', 'A scalar integer type from `i16` upwards', + ints=(16, 64)) +x = Operand('x', WideInt) +lo = Operand( + 'lo', WideInt.half_width(), 'The low bits of `x`') +hi = Operand( + 'hi', WideInt.half_width(), 'The high bits of `x`') + +isplit_lohi = Instruction( + 'isplit_lohi', r""" + Split a scalar integer into low and high parts. + + Returns the low half of `x` and the high half of `x` as two independent + values. + """, + ins=x, outs=(lo, hi)) + + +NarrowInt = TypeVar( + 'NarrowInt', 'A scalar integer type up to `i32`', + ints=(8, 32)) +lo = Operand('lo', NarrowInt) +hi = Operand('hi', NarrowInt) +a = Operand( + 'a', NarrowInt.double_width(), + doc='The concatenation of `lo` and `hi`') + +iconcat_lohi = Instruction( + 'iconcat_lohi', r""" + Concatenate low and high bits to form a larger integer type. + """, + ins=(lo, hi), outs=a) + instructions.close() diff --git a/meta/cretonne/formats.py b/meta/cretonne/formats.py index 48b9d978af..df0019bff4 100644 --- a/meta/cretonne/formats.py +++ b/meta/cretonne/formats.py @@ -17,6 +17,7 @@ UnaryImm = InstructionFormat(imm64) UnaryIeee32 = InstructionFormat(ieee32) UnaryIeee64 = InstructionFormat(ieee64) UnaryImmVector = InstructionFormat(immvector) +UnarySplit = InstructionFormat(value, multiple_results=True) Binary = InstructionFormat(value, value) BinaryImm = InstructionFormat(value, imm64) diff --git a/src/libcretonne/ir/instructions.rs b/src/libcretonne/ir/instructions.rs index 9e259273cc..fd7fd5f25b 100644 --- a/src/libcretonne/ir/instructions.rs +++ b/src/libcretonne/ir/instructions.rs @@ -120,6 +120,12 @@ pub enum InstructionData { opcode: Opcode, ty: Type, // TBD: imm: Box }, + UnarySplit { + opcode: Opcode, + ty: Type, + second_result: Value, + arg: Value, + }, Binary { opcode: Opcode, ty: Type, diff --git a/src/libcretonne/write.rs b/src/libcretonne/write.rs index ea73d18666..8f7acde772 100644 --- a/src/libcretonne/write.rs +++ b/src/libcretonne/write.rs @@ -185,6 +185,7 @@ fn write_instruction(w: &mut Write, UnaryIeee32 { imm, .. } => writeln!(w, " {}", imm), UnaryIeee64 { imm, .. } => writeln!(w, " {}", imm), UnaryImmVector { .. } => writeln!(w, " [...]"), + UnarySplit { arg, .. } => writeln!(w, " {}", arg), Binary { args, .. } => writeln!(w, " {}, {}", args[0], args[1]), BinaryImm { arg, imm, .. } => writeln!(w, " {}, {}", arg, imm), BinaryImmRev { imm, arg, .. } => writeln!(w, " {}, {}", imm, arg), diff --git a/src/libreader/parser.rs b/src/libreader/parser.rs index 723cfb1951..258f920b81 100644 --- a/src/libreader/parser.rs +++ b/src/libreader/parser.rs @@ -119,6 +119,7 @@ impl Context { InstructionData::UnaryImmVector { .. } => {} InstructionData::Unary { ref mut arg, .. } | + InstructionData::UnarySplit { ref mut arg, .. } | InstructionData::BinaryImm { ref mut arg, .. } | InstructionData::BinaryImmRev { ref mut arg, .. } | InstructionData::ExtractLane { ref mut arg, .. } | @@ -1013,6 +1014,14 @@ impl<'a> Parser<'a> { InstructionFormat::UnaryImmVector => { unimplemented!(); } + InstructionFormat::UnarySplit => { + InstructionData::UnarySplit { + opcode: opcode, + ty: VOID, + second_result: NO_VALUE, + arg: try!(self.match_value("expected SSA value operand")), + } + } InstructionFormat::Binary => { let lhs = try!(self.match_value("expected SSA value first operand")); try!(self.match_token(Token::Comma, "expected ',' between operands"));