@@ -7,6 +7,7 @@ use gccjit::{
77 BinaryOp ,
88 Block ,
99 ComparisonOp ,
10+ Context ,
1011 Function ,
1112 LValue ,
1213 RValue ,
@@ -47,6 +48,7 @@ use rustc_target::spec::{HasTargetSpec, Target};
4748
4849use crate :: common:: { SignType , TypeReflection , type_is_pointer} ;
4950use crate :: context:: CodegenCx ;
51+ use crate :: intrinsic:: llvm;
5052use crate :: type_of:: LayoutGccExt ;
5153
5254// TODO(antoyo)
@@ -216,11 +218,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
216218 return Cow :: Borrowed ( args) ;
217219 }
218220
221+ let func_name = format ! ( "{:?}" , func_ptr) ;
222+
219223 let casted_args: Vec < _ > = param_types
220224 . into_iter ( )
221225 . zip ( args. iter ( ) )
222226 . enumerate ( )
223227 . map ( |( index, ( expected_ty, & actual_val) ) | {
228+ if llvm:: ignore_arg_cast ( & func_name, index, args. len ( ) ) {
229+ return actual_val;
230+ }
231+
224232 let actual_ty = actual_val. get_type ( ) ;
225233 if expected_ty != actual_ty {
226234 if !actual_ty. is_vector ( ) && !expected_ty. is_vector ( ) && actual_ty. is_integral ( ) && expected_ty. is_integral ( ) && actual_ty. get_size ( ) != expected_ty. get_size ( ) {
@@ -297,6 +305,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
297305 if return_type != void_type {
298306 unsafe { RETURN_VALUE_COUNT += 1 } ;
299307 let result = current_func. new_local ( None , return_type, & format ! ( "ptrReturnValue{}" , unsafe { RETURN_VALUE_COUNT } ) ) ;
308+ let func_name = format ! ( "{:?}" , func_ptr) ;
309+ let args = llvm:: adjust_intrinsic_arguments ( & self , gcc_func, args, & func_name) ;
300310 self . block . add_assignment ( None , result, self . cx . context . new_call_through_ptr ( None , func_ptr, & args) ) ;
301311 result. to_rvalue ( )
302312 }
@@ -1316,6 +1326,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
13161326 element_type
13171327 }
13181328 else {
1329+ #[ cfg( feature="master" ) ]
1330+ {
1331+ self . cx . type_ix ( element_type. get_size ( ) as u64 * 8 )
1332+ }
1333+ #[ cfg( not( feature="master" ) ) ]
13191334 self . int_type
13201335 } ;
13211336 for i in 0 ..mask_num_units {
@@ -1343,7 +1358,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
13431358 }
13441359 // TODO(antoyo): switch to using new_vector_access.
13451360 let array = self . context . new_bitcast ( None , v2, array_type) ;
1346- for i in 0 ..vec_num_units {
1361+ for i in 0 ..( mask_num_units - vec_num_units) {
13471362 elements. push ( self . context . new_array_access ( None , array, self . context . new_rvalue_from_int ( self . int_type , i as i32 ) ) . to_rvalue ( ) ) ;
13481363 }
13491364 let v1 = self . context . new_rvalue_from_vector ( None , result_type, & elements) ;
@@ -1380,6 +1395,98 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
13801395 pub fn shuffle_vector ( & mut self , _v1 : RValue < ' gcc > , _v2 : RValue < ' gcc > , _mask : RValue < ' gcc > ) -> RValue < ' gcc > {
13811396 unimplemented ! ( ) ;
13821397 }
1398+
1399+ #[ cfg( feature="master" ) ]
1400+ pub fn vector_reduce < F > ( & mut self , src : RValue < ' gcc > , op : F ) -> RValue < ' gcc >
1401+ where F : Fn ( RValue < ' gcc > , RValue < ' gcc > , & ' gcc Context < ' gcc > ) -> RValue < ' gcc >
1402+ {
1403+ let vector_type = src. get_type ( ) . unqualified ( ) . dyncast_vector ( ) . expect ( "vector type" ) ;
1404+ let element_count = vector_type. get_num_units ( ) ;
1405+ let mut vector_elements = vec ! [ ] ;
1406+ for i in 0 ..element_count {
1407+ vector_elements. push ( i) ;
1408+ }
1409+ let mask_type = self . context . new_vector_type ( self . int_type , element_count as u64 ) ;
1410+ let mut shift = 1 ;
1411+ let mut res = src;
1412+ while shift < element_count {
1413+ let vector_elements: Vec < _ > =
1414+ vector_elements. iter ( )
1415+ . map ( |i| self . context . new_rvalue_from_int ( self . int_type , ( ( i + shift) % element_count) as i32 ) )
1416+ . collect ( ) ;
1417+ let mask = self . context . new_rvalue_from_vector ( None , mask_type, & vector_elements) ;
1418+ let shifted = self . context . new_rvalue_vector_perm ( None , res, res, mask) ;
1419+ shift *= 2 ;
1420+ res = op ( res, shifted, & self . context ) ;
1421+ }
1422+ self . context . new_vector_access ( None , res, self . context . new_rvalue_zero ( self . int_type ) )
1423+ . to_rvalue ( )
1424+ }
1425+
1426+ #[ cfg( not( feature="master" ) ) ]
1427+ pub fn vector_reduce < F > ( & mut self , src : RValue < ' gcc > , op : F ) -> RValue < ' gcc >
1428+ where F : Fn ( RValue < ' gcc > , RValue < ' gcc > , & ' gcc Context < ' gcc > ) -> RValue < ' gcc >
1429+ {
1430+ unimplemented ! ( ) ;
1431+ }
1432+
1433+ pub fn vector_reduce_op ( & mut self , src : RValue < ' gcc > , op : BinaryOp ) -> RValue < ' gcc > {
1434+ self . vector_reduce ( src, |a, b, context| context. new_binary_op ( None , op, a. get_type ( ) , a, b) )
1435+ }
1436+
1437+ pub fn vector_reduce_fadd_fast ( & mut self , _acc : RValue < ' gcc > , _src : RValue < ' gcc > ) -> RValue < ' gcc > {
1438+ unimplemented ! ( ) ;
1439+ }
1440+
1441+ pub fn vector_reduce_fmul_fast ( & mut self , _acc : RValue < ' gcc > , _src : RValue < ' gcc > ) -> RValue < ' gcc > {
1442+ unimplemented ! ( ) ;
1443+ }
1444+
1445+ // Inspired by Hacker's Delight min implementation.
1446+ pub fn vector_reduce_min ( & mut self , src : RValue < ' gcc > ) -> RValue < ' gcc > {
1447+ self . vector_reduce ( src, |a, b, context| {
1448+ let differences_or_zeros = difference_or_zero ( a, b, context) ;
1449+ context. new_binary_op ( None , BinaryOp :: Minus , a. get_type ( ) , a, differences_or_zeros)
1450+ } )
1451+ }
1452+
1453+ // Inspired by Hacker's Delight max implementation.
1454+ pub fn vector_reduce_max ( & mut self , src : RValue < ' gcc > ) -> RValue < ' gcc > {
1455+ self . vector_reduce ( src, |a, b, context| {
1456+ let differences_or_zeros = difference_or_zero ( a, b, context) ;
1457+ context. new_binary_op ( None , BinaryOp :: Plus , b. get_type ( ) , b, differences_or_zeros)
1458+ } )
1459+ }
1460+
1461+ pub fn vector_select ( & mut self , cond : RValue < ' gcc > , then_val : RValue < ' gcc > , else_val : RValue < ' gcc > ) -> RValue < ' gcc > {
1462+ // cond is a vector of integers, not of bools.
1463+ let cond_type = cond. get_type ( ) ;
1464+ let vector_type = cond_type. unqualified ( ) . dyncast_vector ( ) . expect ( "vector type" ) ;
1465+ let num_units = vector_type. get_num_units ( ) ;
1466+ let element_type = vector_type. get_element_type ( ) ;
1467+ let zeros = vec ! [ self . context. new_rvalue_zero( element_type) ; num_units] ;
1468+ let zeros = self . context . new_rvalue_from_vector ( None , cond_type, & zeros) ;
1469+
1470+ let masks = self . context . new_comparison ( None , ComparisonOp :: NotEquals , cond, zeros) ;
1471+ let then_vals = masks & then_val;
1472+
1473+ let ones = vec ! [ self . context. new_rvalue_one( element_type) ; num_units] ;
1474+ let ones = self . context . new_rvalue_from_vector ( None , cond_type, & ones) ;
1475+ let inverted_masks = masks + ones;
1476+ // NOTE: sometimes, the type of else_val can be different than the type of then_val in
1477+ // libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND
1478+ // operation to work.
1479+ let else_val = self . context . new_bitcast ( None , else_val, then_val. get_type ( ) ) ;
1480+ let else_vals = inverted_masks & else_val;
1481+
1482+ then_vals | else_vals
1483+ }
1484+ }
1485+
1486+ fn difference_or_zero < ' gcc > ( a : RValue < ' gcc > , b : RValue < ' gcc > , context : & ' gcc Context < ' gcc > ) -> RValue < ' gcc > {
1487+ let difference = a - b;
1488+ let masks = context. new_comparison ( None , ComparisonOp :: GreaterThanEquals , b, a) ;
1489+ difference & masks
13831490}
13841491
13851492impl < ' a , ' gcc , ' tcx > StaticBuilderMethods for Builder < ' a , ' gcc , ' tcx > {
0 commit comments