[pypy-commit] pypy libgccjit-backend: Start supporting floats (requires GCC_JIT_UNARY_OP_ABS)

dmalcolm noreply at buildbot.pypy.org
Wed Dec 17 17:48:41 CET 2014


Author: David Malcolm <dmalcolm at redhat.com>
Branch: libgccjit-backend
Changeset: r74986:6ed15f284d0e
Date: 2014-12-17 10:46 -0500
http://bitbucket.org/pypy/pypy/changeset/6ed15f284d0e/

Log:	Start supporting floats (requires GCC_JIT_UNARY_OP_ABS)

	Convert arg-handling to use a union. Implement some float
	operations.

	Requires new GCC_JIT_UNARY_OP_ABS (not yet in upstream gcc repo)

diff --git a/rpython/jit/backend/libgccjit/assembler.py b/rpython/jit/backend/libgccjit/assembler.py
--- a/rpython/jit/backend/libgccjit/assembler.py
+++ b/rpython/jit/backend/libgccjit/assembler.py
@@ -4,7 +4,7 @@
 from rpython.jit.backend.llsupport.regalloc import FrameManager
 from rpython.jit.backend.model import CompiledLoopToken
 from rpython.jit.backend.libgccjit.rffi_bindings import make_eci, Library, make_param_array, make_field_array, Context, Type
-from rpython.jit.metainterp.history import BoxInt, ConstInt
+from rpython.jit.metainterp.history import BoxInt, ConstInt, BoxFloat, ConstFloat
 from rpython.jit.metainterp.resoperation import *
 from rpython.rtyper.annlowlevel import llhelper, cast_instance_to_gcref, cast_object_to_ptr
 from rpython.rtyper.lltypesystem.rffi import *
@@ -90,9 +90,15 @@
         self.make_context()
         self.t_Signed = self.ctxt.get_int_type(r_int(self.sizeof_signed),
                                                r_int(1))
+        self.t_float = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_DOUBLE) # FIXME                                          
         self.t_bool = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_BOOL)
         self.t_void_ptr = self.ctxt.get_type(self.lib.GCC_JIT_TYPE_VOID_PTR)
 
+        self.u_signed = self.ctxt.new_field(self.t_Signed, "u_signed")
+        self.u_float = self.ctxt.new_field(self.t_float, "u_float")
+        self.t_any = self.ctxt.new_union_type ("any",
+                                               [self.u_signed,
+                                                self.u_float])
         self.lvalue_for_box = {}
 
         print(jitframe.JITFRAME)
@@ -154,7 +160,7 @@
         self.field_for_arg_idx = {}
         for idx in range(max_args):
             self.field_for_arg_idx[idx] = make_field("arg%i" % idx,
-                                                     self.t_Signed)
+                                                     self.t_any)
             initial_locs.append(idx * self.sizeof_signed) # hack!
 
         struct_jit_frame.set_fields (fields)
@@ -197,9 +203,21 @@
         # Get initial values from input args:
         for idx, arg in enumerate(inputargs):
             self.b_current.add_comment("inputargs[%i]: %s" % (idx, arg))
+            # (gdb) p *(double*)&jitframe->arg0
+            # $7 = 10.5
+            # (gdb) p *(double*)&jitframe->arg1
+            # $8 = -2.25
+            #src_ptr_rvalue = self.get_arg_as_lvalue(idx).get_address()
+            #src_ptr_rvalue = self.ctxt.new_cast(src_ptr_rvalue, self.t_float.get_pointer())
+            #src_rvalue = self.ctxt.new_dereference(src_ptr_rvalue)
+            # or do it as a union
+            field = self.get_union_field_for_box(arg)
+            src_rvalue = self.get_arg_as_lvalue(idx).access_field(field).as_rvalue()
+            # FIXME: this may need a cast:
+            #src_rvalue = self.ctxt.new_cast(src_rvalue, self.t_float)
             self.b_current.add_assignment(
                 self.get_box_as_lvalue(arg),
-                self.get_arg_as_lvalue(idx).as_rvalue())
+                src_rvalue)
 
         for op in operations:
             print(op)
@@ -243,19 +261,25 @@
         print(' %s' % expr.__dict__)
         """
 
-        if isinstance(expr, BoxInt):
+        if isinstance(expr, (BoxInt, BoxFloat)):
             return self.get_box_as_lvalue(expr).as_rvalue()
         elif isinstance(expr, ConstInt):
             #print('value: %r' % expr.value)
             #print('type(value): %r' % type(expr.value))
             return self.ctxt.new_rvalue_from_long(self.t_Signed,
                                                   r_long(expr.value))
-        raise ValueError('unhandled expr: %s' % expr)
+        elif isinstance(expr, ConstFloat):
+            #print('value: %r' % expr.value)
+            #print('type(value): %r' % type(expr.value))
+            return self.ctxt.new_rvalue_from_double(self.t_float,
+                                                    expr.value)#r_double(expr.value))
+        raise ValueError('unhandled expr: %s %s' % (expr, type(expr)))
 
     def get_box_as_lvalue(self, box):
         if box not in self.lvalue_for_box:
-            self.lvalue_for_box[box] = self.fn.new_local(self.t_Signed,
-                                                         str(box))
+            self.lvalue_for_box[box] = (
+                self.fn.new_local(self.get_type_for_box(box),
+                                  str(box)))
         return self.lvalue_for_box[box]
 
     def get_arg_as_lvalue(self, idx):
@@ -271,17 +295,34 @@
         print(' %s' % dir(expr))
         print(' %s' % expr.__dict__)
         """
-        if isinstance(expr, BoxInt):
+        if isinstance(expr, (BoxInt, BoxFloat)):
             return self.get_box_as_lvalue(expr)
+            
         raise ValueError('unhandled expr: %s' % expr)
 
+    def get_type_for_box(self, box):
+        if isinstance(box, BoxInt):
+            return self.t_Signed;
+        elif isinstance(box, BoxFloat):
+            return self.t_float;
+        else:
+            raise ValueError('unhandled box: %s %s' % (box, type(box)))
+
+    def get_union_field_for_box(self, box):
+        if isinstance(box, BoxInt):
+            return self.u_signed;
+        elif isinstance(box, BoxFloat):
+            return self.u_float;
+        else:
+            raise ValueError('unhandled box: %s %s' % (box, type(box)))        
+
     # Handling of specific ResOperation subclasses
 
+    # Binary operations on "int":
     def impl_int_binop(self, resop, gcc_jit_binary_op):
         rval0 = self.expr_to_rvalue(resop._arg0)
         rval1 = self.expr_to_rvalue(resop._arg1)
         lvalres = self.expr_to_lvalue(resop.result)
-
         binop_expr = self.ctxt.new_binary_op(gcc_jit_binary_op,
                                              self.t_Signed,
                                              rval0, rval1)
@@ -289,34 +330,58 @@
 
     def emit_int_add(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_PLUS)
-
     def emit_int_sub(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_MINUS)
-
     def emit_int_mul(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_MULT)
-
     def emit_int_floordiv(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_DIVIDE)
-
     def emit_int_mod(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_MODULO)
-
     def emit_int_and(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_BITWISE_AND)
-
     def emit_int_or(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_BITWISE_OR)
-
     def emit_int_xor(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_BITWISE_XOR)
-
     def emit_int_rshift(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_RSHIFT)
-
     def emit_int_lshift(self, resop):
         self.impl_int_binop(resop, self.lib.GCC_JIT_BINARY_OP_LSHIFT)
 
+    # "FLOAT" binary ops:
+    def impl_float_binop(self, resop, gcc_jit_binary_op):
+        rval0 = self.expr_to_rvalue(resop._arg0)
+        rval1 = self.expr_to_rvalue(resop._arg1)
+        lvalres = self.expr_to_lvalue(resop.result)
+        binop_expr = self.ctxt.new_binary_op(gcc_jit_binary_op,
+                                             self.t_float,
+                                             rval0, rval1)
+        self.b_current.add_assignment(lvalres, binop_expr)
+
+    def emit_float_add(self, resop):
+        self.impl_float_binop(resop, self.lib.GCC_JIT_BINARY_OP_PLUS)
+    def emit_float_sub(self, resop):
+        self.impl_float_binop(resop, self.lib.GCC_JIT_BINARY_OP_MINUS)
+    def emit_float_mul(self, resop):
+        self.impl_float_binop(resop, self.lib.GCC_JIT_BINARY_OP_MULT)
+    def emit_float_truediv(self, resop):
+        self.impl_float_binop(resop, self.lib.GCC_JIT_BINARY_OP_DIVIDE)
+
+    # "FLOAT" unary ops:
+    def _impl_float_unaryop(self, resop, gcc_jit_unary_op):
+        rvalue = self.expr_to_rvalue(resop._arg0)
+        lvalres = self.expr_to_lvalue(resop.result)
+        unaryop_expr = self.ctxt.new_unary_op(gcc_jit_unary_op,
+                                            self.t_float,
+                                            rvalue)
+        self.b_current.add_assignment(lvalres, unaryop_expr)
+
+    def emit_float_neg(self, resop):
+        self._impl_float_unaryop(resop, self.lib.GCC_JIT_UNARY_OP_MINUS)
+    def emit_float_abs(self, resop):
+        self._impl_float_unaryop(resop, self.lib.GCC_JIT_UNARY_OP_ABS)
+
     def emit_label(self, resop):
         print(resop)
         print(resop.__dict__)
@@ -358,6 +423,7 @@
             
         self.b_current.end_with_jump(self.block_for_label_descr[jumpop.getdescr()])
 
+    # "INT" comparisons:
     def impl_int_cmp(self, resop, gcc_jit_comparison):
         rval0 = self.expr_to_rvalue(resop._arg0)
         rval1 = self.expr_to_rvalue(resop._arg1)
@@ -370,16 +436,50 @@
             )
         self.b_current.add_assignment(lvalres,
                                       resop_cmp)
-
+    def emit_int_lt(self, resop):
+        self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_LT)
+    def emit_int_le(self, resop):
+        self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_LE)
     def emit_int_eq(self, resop):
         self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_EQ)
-
-    def emit_int_le(self, resop):
-        self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_LE)
-
+    def emit_int_ne(self, resop):
+        self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_NE)
+    def emit_int_gt(self, resop):
+        self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_GT)
     def emit_int_ge(self, resop):
         self.impl_int_cmp(resop, self.lib.GCC_JIT_COMPARISON_GE)
 
+    # "UINT" comparisons:
+
+    # (TODO)
+
+    # "FLOAT" comparisons:
+    def impl_float_cmp(self, resop, gcc_jit_comparison):
+        rval0 = self.expr_to_rvalue(resop._arg0)
+        rval1 = self.expr_to_rvalue(resop._arg1)
+        lvalres = self.expr_to_lvalue(resop.result)
+        resop_cmp = (
+            self.ctxt.new_cast(
+                self.ctxt.new_comparison(gcc_jit_comparison,
+                                         rval0, rval1),
+                self.t_Signed)
+            )
+        self.b_current.add_assignment(lvalres,
+                                      resop_cmp)
+
+    def emit_float_lt(self, resop):
+        self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_LT)
+    def emit_float_le(self, resop):
+        self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_LE)
+    def emit_float_eq(self, resop):
+        self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_EQ)
+    def emit_float_ne(self, resop):
+        self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_NE)
+    def emit_float_gt(self, resop):
+        self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_GT)
+    def emit_float_ge(self, resop):
+        self.impl_float_cmp(resop, self.lib.GCC_JIT_COMPARISON_GE)
+
     def impl_guard(self, resop, istrue):
         print(resop)
         print(resop.__dict__)
@@ -417,9 +517,10 @@
         # Write outputs back:
         for idx, arg in enumerate(args):
             if arg is not None:
-                self.b_current.add_assignment(
-                    self.get_arg_as_lvalue(idx),
-                    self.get_box_as_lvalue(arg).as_rvalue())
+                src_rvalue = self.get_box_as_lvalue(arg).as_rvalue()
+                field = self.get_union_field_for_box(arg)
+                dst_lvalue = self.get_arg_as_lvalue(idx).access_field(field)
+                self.b_current.add_assignment(dst_lvalue, src_rvalue)
             else:
                 # FIXME: see test_compile_with_holes_in_fail_args
                 raise ValueError("how to handle holes in fail args?")
diff --git a/rpython/jit/backend/libgccjit/rffi_bindings.py b/rpython/jit/backend/libgccjit/rffi_bindings.py
--- a/rpython/jit/backend/libgccjit/rffi_bindings.py
+++ b/rpython/jit/backend/libgccjit/rffi_bindings.py
@@ -161,6 +161,13 @@
                                                INT,
                                                self.FIELD_P_P]),
 
+                (self.GCC_JIT_TYPE_P,
+                 'gcc_jit_context_new_union_type', [self.GCC_JIT_CONTEXT_P,
+                                                    self.GCC_JIT_LOCATION_P,
+                                                    CCHARP,
+                                                    INT,
+                                                    self.FIELD_P_P]),
+
                 ############################################################
                 # Constructing functions.
                 ############################################################
@@ -214,13 +221,23 @@
                 (self.GCC_JIT_RVALUE_P,
                  'gcc_jit_context_one', [self.GCC_JIT_CONTEXT_P,
                                          self.GCC_JIT_TYPE_P]),
-
+                (self.GCC_JIT_RVALUE_P,
+                 'gcc_jit_context_new_rvalue_from_double', [self.GCC_JIT_CONTEXT_P,
+                                                            self.GCC_JIT_TYPE_P,
+                                                            DOUBLE]),
                 (self.GCC_JIT_RVALUE_P,
                  'gcc_jit_context_new_rvalue_from_ptr', [self.GCC_JIT_CONTEXT_P,
                                                          self.GCC_JIT_TYPE_P,
                                                          VOIDP]),
 
                 (self.GCC_JIT_RVALUE_P,
+                 'gcc_jit_context_new_unary_op', [self.GCC_JIT_CONTEXT_P,
+                                                  self.GCC_JIT_LOCATION_P,
+                                                  INT, # enum gcc_jit_unary_op op,
+                                                  self.GCC_JIT_TYPE_P,
+                                                  self.GCC_JIT_RVALUE_P]),
+
+                (self.GCC_JIT_RVALUE_P,
                  'gcc_jit_context_new_binary_op', [self.GCC_JIT_CONTEXT_P,
                                                    self.GCC_JIT_LOCATION_P,
                                                    INT, # enum gcc_jit_binary_op op,
@@ -231,7 +248,7 @@
                 (self.GCC_JIT_RVALUE_P,
                  'gcc_jit_context_new_comparison', [self.GCC_JIT_CONTEXT_P,
                                                     self.GCC_JIT_LOCATION_P,
-                                                    INT, # enum gcc_jit_binary_op op,
+                                                    INT, # enum gcc_jit_comparison op,
                                                     self.GCC_JIT_RVALUE_P,
                                                     self.GCC_JIT_RVALUE_P]),
 
@@ -242,6 +259,11 @@
                                               self.GCC_JIT_TYPE_P]),
 
                 (self.GCC_JIT_LVALUE_P,
+                 'gcc_jit_lvalue_access_field', [self.GCC_JIT_LVALUE_P,
+                                                 self.GCC_JIT_LOCATION_P,
+                                                 self.GCC_JIT_FIELD_P]),
+
+                (self.GCC_JIT_LVALUE_P,
                  'gcc_jit_rvalue_dereference_field', [self.GCC_JIT_RVALUE_P,
                                                       self.GCC_JIT_LOCATION_P,
                                                       self.GCC_JIT_FIELD_P]),
@@ -321,6 +343,14 @@
 
         self.make_enum_values(
             """
+            GCC_JIT_UNARY_OP_MINUS,
+            GCC_JIT_UNARY_OP_BITWISE_NEGATE,
+            GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
+            GCC_JIT_UNARY_OP_ABS
+            """)
+
+        self.make_enum_values(
+            """
             GCC_JIT_BINARY_OP_PLUS,
             GCC_JIT_BINARY_OP_MINUS,
             GCC_JIT_BINARY_OP_MULT,
@@ -446,6 +476,23 @@
         free_charp(name_charp)
         return Struct(self.lib, inner_struct)
 
+    def new_union_type(self, name, fields):
+        name_charp = str2charp(name)
+        field_array = lltype.malloc(self.lib.FIELD_P_P.TO,
+                                    len(fields),
+                                    flavor='raw') # of maybe gc?
+        for i in range(len(fields)):
+            field_array[i] = fields[i].inner_field
+        inner_type = (
+            self.lib.gcc_jit_context_new_union_type(self.inner_ctxt,
+                                                    self.lib.null_location_ptr,
+                                                    name_charp,
+                                                    r_int(len(fields)),
+                                                    field_array))
+        lltype.free(field_array, flavor='raw')
+        free_charp(name_charp)
+        return Type(self.lib, inner_type)
+
     def new_rvalue_from_int(self, type_, llvalue):
         return RValue(self.lib,
                       self.lib.gcc_jit_context_new_rvalue_from_int(self.inner_ctxt,
@@ -458,12 +505,26 @@
                                                                     type_.inner_type,
                                                                     llvalue))
 
+    def new_rvalue_from_double(self, type_, llvalue):
+        return RValue(self.lib,
+                      self.lib.gcc_jit_context_new_rvalue_from_double(self.inner_ctxt,
+                                                                      type_.inner_type,
+                                                                      llvalue))
+
     def new_rvalue_from_ptr(self, type_, llvalue):
         return RValue(self.lib,
                       self.lib.gcc_jit_context_new_rvalue_from_ptr(self.inner_ctxt,
                                                                    type_.inner_type,
                                                                    llvalue))
 
+    def new_unary_op(self, op, type_, rvalue):
+        return RValue(self.lib,
+                      self.lib.gcc_jit_context_new_unary_op(self.inner_ctxt,
+                                                            self.lib.null_location_ptr,
+                                                            op,
+                                                            type_.inner_type,
+                                                             rvalue.inner_rvalue))
+
     def new_binary_op(self, op, type_, a, b):
         return RValue(self.lib,
                       self.lib.gcc_jit_context_new_binary_op(self.inner_ctxt,
@@ -572,6 +633,12 @@
         return RValue(self.lib,
                       self.lib.gcc_jit_lvalue_as_rvalue(self.inner_lvalue))
 
+    def access_field(self, field):
+        return LValue(self.lib,
+                      self.lib.gcc_jit_lvalue_access_field (self.inner_lvalue,
+                                                            self.lib.null_location_ptr,
+                                                            field.inner_field))
+
 class Param(Wrapper):
     def __init__(self, lib, inner_param):
         Wrapper.__init__(self, lib)
diff --git a/rpython/jit/backend/libgccjit/runner.py b/rpython/jit/backend/libgccjit/runner.py
--- a/rpython/jit/backend/libgccjit/runner.py
+++ b/rpython/jit/backend/libgccjit/runner.py
@@ -4,6 +4,9 @@
 
 #class CPU(model.AbstractCPU):
 class CPU(AbstractLLCPU):
+
+    supports_floats = True
+
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                  gcdescr=None):
         AbstractLLCPU.__init__(self, rtyper, stats, opts,


More information about the pypy-commit mailing list