[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