diff --git a/docs/langref.rst b/docs/langref.rst index 7f8d3e038f..78953ed8b0 100644 --- a/docs/langref.rst +++ b/docs/langref.rst @@ -562,6 +562,7 @@ Constant materialization .. autoinst:: iconst .. autoinst:: f32const .. autoinst:: f64const +.. autoinst:: bconst Live range splitting -------------------- diff --git a/filetests/parser/tiny.cton b/filetests/parser/tiny.cton index ff3d386947..fff7ccd4c1 100644 --- a/filetests/parser/tiny.cton +++ b/filetests/parser/tiny.cton @@ -25,6 +25,23 @@ ebb0: ; nextln: $v2 = ishl $v0, $v1 ; nextln: } +; Create and use values. +; Polymorphic instructions with type suffix. +function %bvalues() { +ebb0: + v0 = bconst.b32 true + v1 = bconst.b8 false + v2 = bextend.b32 v1 + v3 = bxor v0, v2 +} +; sameln: function %bvalues() { +; nextln: ebb0: +; nextln: $v0 = bconst.b32 true +; nextln: $v1 = bconst.b8 false +; nextln: $v2 = bextend.b32 v1 +; nextln: $v3 = bxor v0, v2 +; nextln: } + ; Polymorphic istruction controlled by second operand. function %select() { ebb0(v90: i32, v91: i32, v92: b1): diff --git a/lib/cretonne/meta/base/formats.py b/lib/cretonne/meta/base/formats.py index 368fb13078..16732c1153 100644 --- a/lib/cretonne/meta/base/formats.py +++ b/lib/cretonne/meta/base/formats.py @@ -9,7 +9,7 @@ from __future__ import absolute_import from cdsl.formats import InstructionFormat from cdsl.operands import VALUE, VARIABLE_ARGS from .immediates import imm64, uimm8, ieee32, ieee64, offset32, uoffset32 -from .immediates import intcc, floatcc, memflags, regunit +from .immediates import boolean, intcc, floatcc, memflags, regunit from .entities import ebb, sig_ref, func_ref, jump_table, stack_slot Nullary = InstructionFormat() @@ -18,6 +18,7 @@ Unary = InstructionFormat(VALUE) UnaryImm = InstructionFormat(imm64) UnaryIeee32 = InstructionFormat(ieee32) UnaryIeee64 = InstructionFormat(ieee64) +UnaryBool = InstructionFormat(boolean) Binary = InstructionFormat(VALUE, VALUE) BinaryImm = InstructionFormat(VALUE, imm64) diff --git a/lib/cretonne/meta/base/immediates.py b/lib/cretonne/meta/base/immediates.py index 2458b76e70..5f64e73b80 100644 --- a/lib/cretonne/meta/base/immediates.py +++ b/lib/cretonne/meta/base/immediates.py @@ -45,6 +45,13 @@ ieee32 = ImmediateKind('ieee32', 'A 32-bit immediate floating point number.') #: IEEE 754-2008 binary64 interchange format. ieee64 = ImmediateKind('ieee64', 'A 64-bit immediate floating point number.') +#: An immediate boolean operand. +#: +#: This type of immediate boolean can interact with SSA values with any +#: :py:class:`cretonne.BoolType` type. +boolean = ImmediateKind('boolean', 'An immediate boolean.', + rust_type='bool') + #: A condition code for comparing integer values. #: #: This enumerated operand kind is used for the :cton:inst:`icmp` instruction diff --git a/lib/cretonne/meta/base/instructions.py b/lib/cretonne/meta/base/instructions.py index 2aa9027a45..8638e19368 100644 --- a/lib/cretonne/meta/base/instructions.py +++ b/lib/cretonne/meta/base/instructions.py @@ -10,7 +10,7 @@ from cdsl.typevar import TypeVar from cdsl.instructions import Instruction, InstructionGroup from base.types import f32, f64, b1 from base.immediates import imm64, uimm8, ieee32, ieee64, offset32, uoffset32 -from base.immediates import intcc, floatcc, memflags, regunit +from base.immediates import boolean, intcc, floatcc, memflags, regunit from base import entities from cdsl.ti import WiderOrEq import base.formats # noqa @@ -18,6 +18,8 @@ import base.formats # noqa GROUP = InstructionGroup("base", "Shared base instruction set") Int = TypeVar('Int', 'A scalar or vector integer type', ints=True, simd=True) +Bool = TypeVar('Bool', 'A scalar or vector boolean type', + bools=True, simd=True) iB = TypeVar('iB', 'A scalar integer type', ints=True) iAddr = TypeVar('iAddr', 'An integer address type', ints=(32, 64)) Testable = TypeVar( @@ -417,6 +419,17 @@ f64const = Instruction( """, ins=N, outs=a) +N = Operand('N', boolean) +a = Operand('a', Bool, doc='A constant boolean scalar or vector value') +bconst = Instruction( + 'bconst', r""" + Boolean constant. + + Create a scalar boolean SSA value with an immediate constant value, or + a boolean vector where all the lanes have the same value. + """, + ins=N, outs=a) + # # Generics. # diff --git a/lib/cretonne/src/ir/instructions.rs b/lib/cretonne/src/ir/instructions.rs index cf914b853a..808b7cc01a 100644 --- a/lib/cretonne/src/ir/instructions.rs +++ b/lib/cretonne/src/ir/instructions.rs @@ -107,6 +107,7 @@ pub enum InstructionData { UnaryImm { opcode: Opcode, imm: Imm64 }, UnaryIeee32 { opcode: Opcode, imm: Ieee32 }, UnaryIeee64 { opcode: Opcode, imm: Ieee64 }, + UnaryBool { opcode: Opcode, imm: bool }, Binary { opcode: Opcode, args: [Value; 2] }, BinaryImm { opcode: Opcode, diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 12b190e3da..164fa70289 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -273,6 +273,7 @@ impl<'a> Verifier<'a> { UnaryImm { .. } | UnaryIeee32 { .. } | UnaryIeee64 { .. } | + UnaryBool { .. } | Binary { .. } | BinaryImm { .. } | Ternary { .. } | diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index f015b7d6df..56a06a0c04 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -243,6 +243,7 @@ pub fn write_operands(w: &mut Write, UnaryImm { imm, .. } => write!(w, " {}", imm), UnaryIeee32 { imm, .. } => write!(w, " {}", imm), UnaryIeee64 { imm, .. } => write!(w, " {}", imm), + UnaryBool { imm, .. } => write!(w, " {}", imm), Binary { args, .. } => write!(w, " {}, {}", args[0], args[1]), BinaryImm { arg, imm, .. } => write!(w, " {}, {}", arg, imm), Ternary { args, .. } => write!(w, " {}, {}, {}", args[0], args[1], args[2]), diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index f698b1f54f..620d02ca2b 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -498,6 +498,20 @@ impl<'a> Parser<'a> { } } + // Match and consume a boolean immediate. + fn match_bool(&mut self, err_msg: &str) -> Result { + if let Some(Token::Identifier(text)) = self.token() { + self.consume(); + match text { + "true" => Ok(true), + "false" => Ok(false), + _ => err!(self.loc, err_msg), + } + } else { + err!(self.loc, err_msg) + } + } + // Match and consume an enumerated immediate, like one of the condition codes. fn match_enum(&mut self, err_msg: &str) -> Result { if let Some(Token::Identifier(text)) = self.token() { @@ -1483,6 +1497,12 @@ impl<'a> Parser<'a> { imm: self.match_ieee64("expected immediate 64-bit float operand")?, } } + InstructionFormat::UnaryBool => { + InstructionData::UnaryBool { + opcode, + imm: self.match_bool("expected immediate boolean operand")?, + } + } InstructionFormat::Binary => { let lhs = self.match_value("expected SSA value first operand")?; self.match_token(Token::Comma, "expected ',' between operands")?;