From 61f5eeee2fd9c9ed7aba21c0d1dc475681bc2d0d Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 21 Oct 2016 11:02:53 -0700 Subject: [PATCH] Properly infer result type for single-result instructions. Polymorphic single-result instructions don't always return the controlling type variable as their first result. They may use a derived type variable, as for example icmp does. --- lib/cretonne/meta/gen_instr.py | 16 +++++++++++++++- lib/cretonne/src/ir/builder.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index 21bd8bcd85..8a7e813223 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -474,7 +474,21 @@ def gen_inst_builder(inst, fmt): fmt.line( 'let ctrl_typevar = self.data_flow_graph().value_type({});' .format(inst.ins[inst.format.typevar_operand].name)) - args.append('ctrl_typevar') + if inst.format.multiple_results: + # The format constructor will resolve the result types from the + # type var. + args.append('ctrl_typevar') + elif inst.outs[inst.value_results[0]].typ == inst.ctrl_typevar: + # The format constructor expects a simple result type. + # No type transformation needed from the controlling type + # variable. + args.append('ctrl_typevar') + else: + # The format constructor expects a simple result type. + # TODO: This formula could be resolved ahead of time. + args.append( + 'Opcode::{}.constraints().result_type(0, ctrl_typevar)' + .format(inst.camel_name)) else: # This non-polymorphic instruction has a fixed result type. args.append( diff --git a/lib/cretonne/src/ir/builder.rs b/lib/cretonne/src/ir/builder.rs index 7df5a6aa3c..575d36cd0b 100644 --- a/lib/cretonne/src/ir/builder.rs +++ b/lib/cretonne/src/ir/builder.rs @@ -180,3 +180,32 @@ impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> { (self.inst, self.dfg) } } + +#[cfg(test)] +mod tests { + use ir::{Function, Cursor, InstBuilder}; + use ir::types::*; + use ir::condcodes::*; + + #[test] + fn types() { + let mut func = Function::new(); + let dfg = &mut func.dfg; + let ebb0 = dfg.make_ebb(); + let arg0 = dfg.append_ebb_arg(ebb0, I32); + let pos = &mut Cursor::new(&mut func.layout); + pos.insert_ebb(ebb0); + + // Explicit types. + let v0 = dfg.ins(pos).iconst(I32, 3); + assert_eq!(dfg.value_type(v0), I32); + + // Inferred from inputs. + let v1 = dfg.ins(pos).iadd(arg0, v0); + assert_eq!(dfg.value_type(v1), I32); + + // Formula. + let cmp = dfg.ins(pos).icmp(IntCC::Equal, arg0, v0); + assert_eq!(dfg.value_type(cmp), B1); + } +}