<s> static bool expand_vselect ( rtx target , rtx op0 , const unsigned char * perm , unsigned nelt , bool testing_p ) { unsigned int i ; rtx x , save_vconcat ; int icode ; if ( vselect_insn == NULL_RTX ) init_vselect_insn ( ) ; x = XEXP ( SET_SRC ( PATTERN ( vselect_insn ) ) , 1 ) ; PUT_NUM_ELEM ( XVEC ( x , 0 ) , nelt ) ; for ( i = 0 ; i < nelt ; ++ i ) XVECEXP ( x , 0 , i ) = GEN_INT ( perm [ i ] ) ; save_vconcat = XEXP ( SET_SRC ( PATTERN ( vselect_insn ) ) , 0 ) ; XEXP ( SET_SRC ( PATTERN ( vselect_insn ) ) , 0 ) = op0 ; PUT_MODE ( SET_SRC ( PATTERN ( vselect_insn ) ) , GET_MODE ( target ) ) ; SET_DEST ( PATTERN ( vselect_insn ) ) = target ; icode = recog_memoized ( vselect_insn ) ; if ( icode >= 0 && ! testing_p ) emit_insn ( copy_rtx ( PATTERN ( vselect_insn ) ) ) ; SET_DEST ( PATTERN ( vselect_insn ) ) = const0_rtx ; XEXP ( SET_SRC ( PATTERN ( vselect_insn ) ) , 0 ) = save_vconcat ; INSN_CODE ( vselect_insn ) = - 1 ; return icode >= 0 ; } </s>

Construct ( set target ( vec_select op0 ( parallel perm ) ) ) and return true if that 's a valid instruction in the active ISA .


<s> static bool expand_vselect_vconcat ( rtx target , rtx op0 , rtx op1 , const unsigned char * perm , unsigned nelt , bool testing_p ) { machine_mode v2mode ; rtx x ; bool ok ; if ( vselect_insn == NULL_RTX ) init_vselect_insn ( ) ; if ( ! GET_MODE_2XWIDER_MODE ( GET_MODE ( op0 ) ) . exists ( & v2mode ) ) return false ; x = XEXP ( SET_SRC ( PATTERN ( vselect_insn ) ) , 0 ) ; PUT_MODE ( x , v2mode ) ; XEXP ( x , 0 ) = op0 ; XEXP ( x , 1 ) = op1 ; ok = expand_vselect ( target , x , perm , nelt , testing_p ) ; XEXP ( x , 0 ) = const0_rtx ; XEXP ( x , 1 ) = const0_rtx ; return ok ; } </s>

Similar , but generate a vec_concat from op0 and op1 as well .


<s> static bool find_nearest_reg_def ( rtx_insn * insn , int regno1 , int regno2 ) { rtx_insn * prev = insn ; rtx_insn * start = BB_HEAD ( BLOCK_FOR_INSN ( insn ) ) ; if ( insn == start ) return false ; while ( prev && prev != start ) { if ( ! INSN_P ( prev ) || ! NONDEBUG_INSN_P ( prev ) ) { prev = PREV_INSN ( prev ) ; continue ; } if ( insn_defines_reg ( regno1 , INVALID_REGNUM , prev ) ) return true ; else if ( insn_defines_reg ( regno2 , INVALID_REGNUM , prev ) ) return false ; prev = PREV_INSN ( prev ) ; } return false ; } </s>

Return true if regno1 def is nearest to the insn .


<s> static rtx fixup_modeless_constant ( rtx x , machine_mode mode ) { if ( GET_MODE ( x ) == VOIDmode ) x = convert_to_mode ( mode , x , 1 ) ; return x ; } </s>

Fixup modeless constants to fit required mode .


"selector must be an integer constant in the range "

Return the integer constant in ARG . Constrain it to be in the range of the subparts of VEC_TYPE ; issue an error if not .


<s> static machine_mode get_mode_wider_vector ( machine_mode o ) { machine_mode n = GET_MODE_WIDER_MODE ( o ) . require ( ) ; gcc_assert ( GET_MODE_NUNITS ( o ) == GET_MODE_NUNITS ( n ) * 2 ) ; gcc_assert ( GET_MODE_SIZE ( o ) == GET_MODE_SIZE ( n ) ) ; return n ; } </s>

Get a vector mode of the same size as the original but with elements twice as wide . This is only guaranteed to apply to integral vectors .


<s> static void init_vselect_insn ( void ) { unsigned i ; rtx x ; x = gen_rtx_PARALLEL ( VOIDmode , rtvec_alloc ( MAX_VECT_LEN ) ) ; for ( i = 0 ; i < MAX_VECT_LEN ; ++ i ) XVECEXP ( x , 0 , i ) = const0_rtx ; x = gen_rtx_VEC_SELECT ( V2DFmode , gen_rtx_VEC_CONCAT ( V4DFmode , const0_rtx , const0_rtx ) , x ) ; x = gen_rtx_SET ( const0_rtx , x ) ; start_sequence ( ) ; vselect_insn = emit_insn ( x ) ; end_sequence ( ) ; } </s>


<s> static void ix86_adjust_counter ( rtx countreg , HOST_WIDE_INT value ) { emit_insn ( gen_add2_insn ( countreg , GEN_INT ( - value ) ) ) ; } </s>


<s> static void ix86_avx256_split_vector_move_misalign ( rtx op0 , rtx op1 ) { rtx m ; rtx ( * extract ) ( rtx , rtx , rtx ) ; machine_mode mode ; if ( ( MEM_P ( op1 ) && ! TARGET_AVX256_SPLIT_UNALIGNED_LOAD ) || ( MEM_P ( op0 ) && ! TARGET_AVX256_SPLIT_UNALIGNED_STORE ) ) { emit_insn ( gen_rtx_SET ( op0 , op1 ) ) ; return ; } rtx orig_op0 = NULL_RTX ; mode = GET_MODE ( op0 ) ; switch ( GET_MODE_CLASS ( mode ) ) { case MODE_VECTOR_INT : case MODE_INT : if ( mode != V32QImode ) { if ( ! MEM_P ( op0 ) ) { orig_op0 = op0 ; op0 = gen_reg_rtx ( V32QImode ) ; } else op0 = gen_lowpart ( V32QImode , op0 ) ; op1 = gen_lowpart ( V32QImode , op1 ) ; mode = V32QImode ; } break ; case MODE_VECTOR_FLOAT : break ; default : gcc_unreachable ( ) ; } switch ( mode ) { default : gcc_unreachable ( ) ; case E_V32QImode : extract = gen_avx_vextractf128v32qi ; mode = V16QImode ; break ; case E_V16HFmode : extract = gen_avx_vextractf128v16hf ; mode = V8HFmode ; break ; case E_V8SFmode : extract = gen_avx_vextractf128v8sf ; mode = V4SFmode ; break ; case E_V4DFmode : extract = gen_avx_vextractf128v4df ; mode = V2DFmode ; break ; } if ( MEM_P ( op1 ) ) { rtx r = gen_reg_rtx ( mode ) ; m = adjust_address ( op1 , mode , 0 ) ; emit_move_insn ( r , m ) ; m = adjust_address ( op1 , mode , 16 ) ; r = gen_rtx_VEC_CONCAT ( GET_MODE ( op0 ) , r , m ) ; emit_move_insn ( op0 , r ) ; } else if ( MEM_P ( op0 ) ) { m = adjust_address ( op0 , mode , 0 ) ; emit_insn ( extract ( m , op1 , const0_rtx ) ) ; m = adjust_address ( op0 , mode , 16 ) ; emit_insn ( extract ( m , copy_rtx ( op1 ) , const1_rtx ) ) ; } else gcc_unreachable ( ) ; if ( orig_op0 ) emit_move_insn ( orig_op0 , gen_lowpart ( GET_MODE ( orig_op0 ) , op0 ) ) ; } </s>

Split 32-byte AVX unaligned load and store if needed .


<s> bool ix86_binary_operator_ok ( enum rtx_code code , machine_mode mode , rtx operands [ 3 ] ) { rtx dst = operands [ 0 ] ; rtx src1 = operands [ 1 ] ; rtx src2 = operands [ 2 ] ; if ( ( MEM_P ( src1 ) || bcst_mem_operand ( src1 , mode ) ) && ( MEM_P ( src2 ) || bcst_mem_operand ( src2 , mode ) ) ) return false ; if ( ix86_swap_binary_operands_p ( code , mode , operands ) ) std :: swap ( src1 , src2 ) ; if ( MEM_P ( dst ) && ! rtx_equal_p ( dst , src1 ) ) return false ; if ( CONSTANT_P ( src1 ) ) return false ; if ( MEM_P ( src1 ) && ! rtx_equal_p ( dst , src1 ) ) return ( code == AND && ( mode == HImode || mode == SImode || ( TARGET_64BIT && mode == DImode ) ) && satisfies_constraint_L ( src2 ) ) ; return true ; } </s>

Return TRUE or FALSE depending on whether the binary operator meets the appropriate constraints .


<s> static bool ix86_broadcast ( HOST_WIDE_INT v , unsigned int width , HOST_WIDE_INT & val_broadcast ) { wide_int val = wi :: uhwi ( v , HOST_BITS_PER_WIDE_INT ) ; val_broadcast = wi :: extract_uhwi ( val , 0 , width ) ; for ( unsigned int i = width ; i < HOST_BITS_PER_WIDE_INT ; i += width ) { HOST_WIDE_INT each = wi :: extract_uhwi ( val , i , width ) ; if ( val_broadcast != each ) return false ; } val_broadcast = sext_hwi ( val_broadcast , width ) ; return true ; } </s>

Return true if V can be broadcasted from an integer of WIDTH bits which is returned in VAL_BROADCAST . Otherwise , return false .


<s> static rtx ix86_broadcast_from_constant ( machine_mode mode , rtx op ) { int nunits = GET_MODE_NUNITS ( mode ) ; if ( nunits < 2 ) return nullptr ; if ( ! TARGET_INTER_UNIT_MOVES_TO_VEC && INTEGRAL_MODE_P ( mode ) ) return nullptr ; if ( ! ( TARGET_AVX2 || ( TARGET_AVX && ( GET_MODE_INNER ( mode ) == SImode || GET_MODE_INNER ( mode ) == DImode ) ) || FLOAT_MODE_P ( mode ) ) || standard_sse_constant_p ( op , mode ) ) return nullptr ; if ( GET_MODE_INNER ( mode ) == DImode && ! TARGET_64BIT && ( ! TARGET_AVX512F || ( GET_MODE_SIZE ( mode ) < 64 && ! TARGET_AVX512VL ) ) ) return nullptr ; if ( GET_MODE_INNER ( mode ) == TImode ) return nullptr ; rtx constant = get_pool_constant ( XEXP ( op , 0 ) ) ; if ( GET_CODE ( constant ) != CONST_VECTOR ) return nullptr ; if ( GET_MODE ( constant ) != mode ) { constant = simplify_subreg ( mode , constant , GET_MODE ( constant ) , 0 ) ; if ( constant == nullptr || GET_CODE ( constant ) != CONST_VECTOR ) return nullptr ; } rtx first = XVECEXP ( constant , 0 , 0 ) ; for ( int i = 1 ; i < nunits ; ++ i ) { rtx tmp = XVECEXP ( constant , 0 , i ) ; if ( ! rtx_equal_p ( tmp , first ) ) return nullptr ; } return first ; } </s>

OP is a memref of CONST_VECTOR , return scalar constant mem if CONST_VECTOR is a vec_duplicate , else return NULL .


<s> bool ix86_check_builtin_isa_match ( unsigned int fcode , HOST_WIDE_INT * pbisa , HOST_WIDE_INT * pbisa2 ) { HOST_WIDE_INT isa = ix86_isa_flags ; HOST_WIDE_INT isa2 = ix86_isa_flags2 ; HOST_WIDE_INT bisa = ix86_builtins_isa [ fcode ] . isa ; HOST_WIDE_INT bisa2 = ix86_builtins_isa [ fcode ] . isa2 ; if ( ( ( bisa & ( OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A ) ) == ( OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A ) ) && ( isa & ( OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A ) ) != 0 ) isa |= ( OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_3DNOW_A ) ; if ( ( ( bisa & ( OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32 ) ) == ( OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32 ) ) && ( isa & ( OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32 ) ) != 0 ) isa |= ( OPTION_MASK_ISA_SSE4_2 | OPTION_MASK_ISA_CRC32 ) ; if ( ( ( bisa & ( OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4 ) ) == ( OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4 ) ) && ( isa & ( OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4 ) ) != 0 ) isa |= ( OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4 ) ; if ( ( ( ( bisa & ( OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL ) ) == ( OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL ) ) || ( bisa2 & OPTION_MASK_ISA2_AVXVNNI ) != 0 ) && ( ( ( isa & ( OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL ) ) == ( OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL ) ) || ( isa2 & OPTION_MASK_ISA2_AVXVNNI ) != 0 ) ) { isa |= OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VL ; isa2 |= OPTION_MASK_ISA2_AVXVNNI ; } if ( ( bisa & OPTION_MASK_ISA_MMX ) && ! TARGET_MMX && TARGET_MMX_WITH_SSE && fcode != IX86_BUILTIN_MASKMOVQ ) { bisa &= ~ OPTION_MASK_ISA_MMX ; bisa |= OPTION_MASK_ISA_SSE2 ; } if ( pbisa ) * pbisa = bisa ; if ( pbisa2 ) * pbisa2 = bisa2 ; return ( bisa & isa ) == bisa && ( bisa2 & isa2 ) == bisa2 ; } </s>

Return true if the necessary isa options for this builtin exist , else false . fcode = DECL_MD_FUNCTION_CODE ( fndecl ) ;


<s> static int ix86_cmp_code_to_pcmp_immediate ( enum rtx_code code , machine_mode mode ) { if ( FLOAT_MODE_P ( mode ) ) return ix86_fp_cmp_code_to_pcmp_immediate ( code ) ; return ix86_int_cmp_code_to_pcmp_immediate ( code ) ; } </s>

Return immediate value to be used in UNSPEC_PCMP for comparison CODE in MODE .


Convert the CONST_WIDE_INT operand OP to broadcast in MODE .


<s> static rtx ix86_copy_addr_to_reg ( rtx addr ) { rtx reg ; if ( GET_MODE ( addr ) == Pmode || GET_MODE ( addr ) == VOIDmode ) { reg = copy_addr_to_reg ( addr ) ; REG_POINTER ( reg ) = 1 ; return reg ; } else { gcc_assert ( GET_MODE ( addr ) == DImode && Pmode == SImode ) ; reg = copy_to_mode_reg ( DImode , addr ) ; REG_POINTER ( reg ) = 1 ; return gen_rtx_SUBREG ( SImode , reg , 0 ) ; } } </s>

Copy the address to a Pmode register . This is used for x32 to truncate DImode TLS address to a SImode register .


<s> void ix86_emit_binop ( enum rtx_code code , machine_mode mode , rtx dst , rtx src ) { rtx op , clob ; op = gen_rtx_SET ( dst , gen_rtx_fmt_ee ( code , mode , dst , src ) ) ; clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , op , clob ) ) ) ; } </s>

Emit x86 binary operand CODE in mode MODE , where the first operand matches destination . RTX includes clobber of FLAGS_REG .


<s> void ix86_emit_fp_unordered_jump ( rtx label ) { rtx reg = gen_reg_rtx ( HImode ) ; rtx_insn * insn ; rtx temp ; emit_insn ( gen_x86_fnstsw_1 ( reg ) ) ; if ( TARGET_SAHF && ( TARGET_USE_SAHF || optimize_insn_for_size_p ( ) ) ) { emit_insn ( gen_x86_sahf_1 ( reg ) ) ; temp = gen_rtx_REG ( CCmode , FLAGS_REG ) ; temp = gen_rtx_UNORDERED ( VOIDmode , temp , const0_rtx ) ; } else { emit_insn ( gen_testqi_ext_1_ccno ( reg , GEN_INT ( 0x04 ) ) ) ; temp = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; temp = gen_rtx_NE ( VOIDmode , temp , const0_rtx ) ; } temp = gen_rtx_IF_THEN_ELSE ( VOIDmode , temp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; insn = emit_jump_insn ( gen_rtx_SET ( pc_rtx , temp ) ) ; predict_jump ( REG_BR_PROB_BASE * 10 / 100 ) ; JUMP_LABEL ( insn ) = label ; } </s>

Output code to perform a conditional jump to LABEL , if C2 flag in FP status register is set .


Output code to perform an acosh XFmode calculation .


<s> void ix86_emit_i387_asinh ( rtx op0 , rtx op1 ) { rtx e1 = gen_reg_rtx ( XFmode ) ; rtx e2 = gen_reg_rtx ( XFmode ) ; rtx scratch = gen_reg_rtx ( HImode ) ; rtx flags = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; rtx cst1 , tmp ; rtx_code_label * jump_label = gen_label_rtx ( ) ; rtx_insn * insn ; emit_insn ( gen_mulxf3 ( e1 , op1 , op1 ) ) ; cst1 = force_reg ( XFmode , CONST1_RTX ( XFmode ) ) ; emit_insn ( gen_addxf3 ( e2 , e1 , cst1 ) ) ; emit_insn ( gen_sqrtxf2 ( e2 , e2 ) ) ; emit_insn ( gen_addxf3 ( e2 , e2 , cst1 ) ) ; emit_insn ( gen_divxf3 ( e1 , e1 , e2 ) ) ; emit_insn ( gen_fxamxf2_i387 ( scratch , op1 ) ) ; emit_insn ( gen_absxf2 ( e2 , op1 ) ) ; emit_insn ( gen_addxf3 ( e1 , e1 , e2 ) ) ; ix86_emit_i387_log1p ( e2 , e1 ) ; emit_insn ( gen_testqi_ext_1_ccno ( scratch , GEN_INT ( 0x02 ) ) ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , gen_rtx_EQ ( VOIDmode , flags , const0_rtx ) , gen_rtx_LABEL_REF ( VOIDmode , jump_label ) , pc_rtx ) ; insn = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; predict_jump ( REG_BR_PROB_BASE * 50 / 100 ) ; JUMP_LABEL ( insn ) = jump_label ; emit_insn ( gen_negxf2 ( e2 , e2 ) ) ; emit_label ( jump_label ) ; LABEL_NUSES ( jump_label ) = 1 ; emit_move_insn ( op0 , e2 ) ; } </s>

Output code to perform an asinh XFmode calculation .


<s> void ix86_emit_i387_atanh ( rtx op0 , rtx op1 ) { rtx e1 = gen_reg_rtx ( XFmode ) ; rtx e2 = gen_reg_rtx ( XFmode ) ; rtx scratch = gen_reg_rtx ( HImode ) ; rtx flags = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; rtx half = const_double_from_real_value ( dconsthalf , XFmode ) ; rtx cst1 , tmp ; rtx_code_label * jump_label = gen_label_rtx ( ) ; rtx_insn * insn ; emit_insn ( gen_fxamxf2_i387 ( scratch , op1 ) ) ; emit_insn ( gen_absxf2 ( e2 , op1 ) ) ; cst1 = force_reg ( XFmode , CONST1_RTX ( XFmode ) ) ; emit_insn ( gen_addxf3 ( e1 , e2 , cst1 ) ) ; emit_insn ( gen_addxf3 ( e2 , e2 , e2 ) ) ; emit_insn ( gen_negxf2 ( e2 , e2 ) ) ; emit_insn ( gen_divxf3 ( e1 , e2 , e1 ) ) ; ix86_emit_i387_log1p ( e2 , e1 ) ; emit_insn ( gen_testqi_ext_1_ccno ( scratch , GEN_INT ( 0x02 ) ) ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , gen_rtx_NE ( VOIDmode , flags , const0_rtx ) , gen_rtx_LABEL_REF ( VOIDmode , jump_label ) , pc_rtx ) ; insn = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; predict_jump ( REG_BR_PROB_BASE * 50 / 100 ) ; JUMP_LABEL ( insn ) = jump_label ; emit_insn ( gen_negxf2 ( e2 , e2 ) ) ; emit_label ( jump_label ) ; LABEL_NUSES ( jump_label ) = 1 ; half = force_reg ( XFmode , half ) ; emit_insn ( gen_mulxf3 ( op0 , e2 , half ) ) ; } </s>

Output code to perform an atanh XFmode calculation .


<s> void ix86_emit_i387_cosh ( rtx op0 , rtx op1 ) { rtx e1 = gen_reg_rtx ( XFmode ) ; rtx e2 = gen_reg_rtx ( XFmode ) ; rtx half = const_double_from_real_value ( dconsthalf , XFmode ) ; rtx cst1 ; emit_insn ( gen_expxf2 ( e1 , op1 ) ) ; cst1 = force_reg ( XFmode , CONST1_RTX ( XFmode ) ) ; emit_insn ( gen_divxf3 ( e2 , cst1 , e1 ) ) ; emit_insn ( gen_addxf3 ( e2 , e1 , e2 ) ) ; half = force_reg ( XFmode , half ) ; emit_insn ( gen_mulxf3 ( op0 , e2 , half ) ) ; } </s>

Output code to perform an cosh XFmode calculation .


<s> void ix86_emit_i387_log1p ( rtx op0 , rtx op1 ) { rtx_code_label * label1 = gen_label_rtx ( ) ; rtx_code_label * label2 = gen_label_rtx ( ) ; rtx tmp = gen_reg_rtx ( XFmode ) ; rtx res = gen_reg_rtx ( XFmode ) ; rtx cst , cstln2 , cst1 ; rtx_insn * insn ; do_pending_stack_adjust ( ) ; cst = const_double_from_real_value ( REAL_VALUE_ATOF ( "0.29289321881345247561810596348408353" , XFmode ) , XFmode ) ; cstln2 = force_reg ( XFmode , standard_80387_constant_rtx ( 4 ) ) ; emit_insn ( gen_absxf2 ( tmp , op1 ) ) ; cst = force_reg ( XFmode , cst ) ; ix86_expand_branch ( GE , tmp , cst , label1 ) ; predict_jump ( REG_BR_PROB_BASE * 10 / 100 ) ; insn = get_last_insn ( ) ; JUMP_LABEL ( insn ) = label1 ; emit_insn ( gen_fyl2xp1xf3_i387 ( res , op1 , cstln2 ) ) ; emit_jump ( label2 ) ; emit_label ( label1 ) ; LABEL_NUSES ( label1 ) = 1 ; cst1 = force_reg ( XFmode , CONST1_RTX ( XFmode ) ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_PLUS ( XFmode , op1 , cst1 ) ) ) ; emit_insn ( gen_fyl2xxf3_i387 ( res , tmp , cstln2 ) ) ; emit_label ( label2 ) ; LABEL_NUSES ( label2 ) = 1 ; emit_move_insn ( op0 , res ) ; } </s>

Output code to perform a log1p XFmode calculation .


<s> void ix86_emit_i387_round ( rtx op0 , rtx op1 ) { machine_mode inmode = GET_MODE ( op1 ) ; machine_mode outmode = GET_MODE ( op0 ) ; rtx e1 = gen_reg_rtx ( XFmode ) ; rtx e2 = gen_reg_rtx ( XFmode ) ; rtx scratch = gen_reg_rtx ( HImode ) ; rtx flags = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; rtx half = const_double_from_real_value ( dconsthalf , XFmode ) ; rtx res = gen_reg_rtx ( outmode ) ; rtx_code_label * jump_label = gen_label_rtx ( ) ; rtx ( * floor_insn ) ( rtx , rtx ) ; rtx ( * neg_insn ) ( rtx , rtx ) ; rtx_insn * insn ; rtx tmp ; switch ( inmode ) { case E_SFmode : case E_DFmode : tmp = gen_reg_rtx ( XFmode ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_FLOAT_EXTEND ( XFmode , op1 ) ) ) ; op1 = tmp ; break ; case E_XFmode : break ; default : gcc_unreachable ( ) ; } switch ( outmode ) { case E_SFmode : floor_insn = gen_frndintxf2_floor ; neg_insn = gen_negsf2 ; break ; case E_DFmode : floor_insn = gen_frndintxf2_floor ; neg_insn = gen_negdf2 ; break ; case E_XFmode : floor_insn = gen_frndintxf2_floor ; neg_insn = gen_negxf2 ; break ; case E_HImode : floor_insn = gen_lfloorxfhi2 ; neg_insn = gen_neghi2 ; break ; case E_SImode : floor_insn = gen_lfloorxfsi2 ; neg_insn = gen_negsi2 ; break ; case E_DImode : floor_insn = gen_lfloorxfdi2 ; neg_insn = gen_negdi2 ; break ; default : gcc_unreachable ( ) ; } emit_insn ( gen_fxamxf2_i387 ( scratch , op1 ) ) ; emit_insn ( gen_absxf2 ( e1 , op1 ) ) ; half = force_reg ( XFmode , half ) ; emit_insn ( gen_rtx_SET ( e2 , gen_rtx_PLUS ( XFmode , e1 , half ) ) ) ; switch ( outmode ) { case E_SFmode : case E_DFmode : { tmp = gen_reg_rtx ( XFmode ) ; emit_insn ( floor_insn ( tmp , e2 ) ) ; emit_insn ( gen_rtx_SET ( res , gen_rtx_UNSPEC ( outmode , gen_rtvec ( 1 , tmp ) , UNSPEC_TRUNC_NOOP ) ) ) ; } break ; default : emit_insn ( floor_insn ( res , e2 ) ) ; } emit_insn ( gen_testqi_ext_1_ccno ( scratch , GEN_INT ( 0x02 ) ) ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , gen_rtx_EQ ( VOIDmode , flags , const0_rtx ) , gen_rtx_LABEL_REF ( VOIDmode , jump_label ) , pc_rtx ) ; insn = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; predict_jump ( REG_BR_PROB_BASE * 50 / 100 ) ; JUMP_LABEL ( insn ) = jump_label ; emit_insn ( neg_insn ( res , res ) ) ; emit_label ( jump_label ) ; LABEL_NUSES ( jump_label ) = 1 ; emit_move_insn ( op0 , res ) ; } </s>


<s> void ix86_emit_i387_sinh ( rtx op0 , rtx op1 ) { rtx e1 = gen_reg_rtx ( XFmode ) ; rtx e2 = gen_reg_rtx ( XFmode ) ; rtx scratch = gen_reg_rtx ( HImode ) ; rtx flags = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; rtx half = const_double_from_real_value ( dconsthalf , XFmode ) ; rtx cst1 , tmp ; rtx_code_label * jump_label = gen_label_rtx ( ) ; rtx_insn * insn ; emit_insn ( gen_fxamxf2_i387 ( scratch , op1 ) ) ; emit_insn ( gen_absxf2 ( e2 , op1 ) ) ; emit_insn ( gen_expm1xf2 ( e1 , e2 ) ) ; cst1 = force_reg ( XFmode , CONST1_RTX ( XFmode ) ) ; emit_insn ( gen_addxf3 ( e2 , e1 , cst1 ) ) ; emit_insn ( gen_divxf3 ( e2 , e1 , e2 ) ) ; emit_insn ( gen_addxf3 ( e2 , e2 , e1 ) ) ; emit_insn ( gen_testqi_ext_1_ccno ( scratch , GEN_INT ( 0x02 ) ) ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , gen_rtx_EQ ( VOIDmode , flags , const0_rtx ) , gen_rtx_LABEL_REF ( VOIDmode , jump_label ) , pc_rtx ) ; insn = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; predict_jump ( REG_BR_PROB_BASE * 50 / 100 ) ; JUMP_LABEL ( insn ) = jump_label ; emit_insn ( gen_negxf2 ( e2 , e2 ) ) ; emit_label ( jump_label ) ; LABEL_NUSES ( jump_label ) = 1 ; half = force_reg ( XFmode , half ) ; emit_insn ( gen_mulxf3 ( op0 , e2 , half ) ) ; } </s>

Output code to perform an sinh XFmode calculation .


<s> void ix86_emit_i387_tanh ( rtx op0 , rtx op1 ) { rtx e1 = gen_reg_rtx ( XFmode ) ; rtx e2 = gen_reg_rtx ( XFmode ) ; rtx scratch = gen_reg_rtx ( HImode ) ; rtx flags = gen_rtx_REG ( CCNOmode , FLAGS_REG ) ; rtx cst2 , tmp ; rtx_code_label * jump_label = gen_label_rtx ( ) ; rtx_insn * insn ; emit_insn ( gen_fxamxf2_i387 ( scratch , op1 ) ) ; emit_insn ( gen_addxf3 ( e2 , op1 , op1 ) ) ; emit_insn ( gen_absxf2 ( e2 , e2 ) ) ; emit_insn ( gen_negxf2 ( e2 , e2 ) ) ; emit_insn ( gen_expm1xf2 ( e1 , e2 ) ) ; cst2 = force_reg ( XFmode , CONST2_RTX ( XFmode ) ) ; emit_insn ( gen_addxf3 ( e2 , e1 , cst2 ) ) ; emit_insn ( gen_divxf3 ( e2 , e1 , e2 ) ) ; emit_insn ( gen_testqi_ext_1_ccno ( scratch , GEN_INT ( 0x02 ) ) ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , gen_rtx_NE ( VOIDmode , flags , const0_rtx ) , gen_rtx_LABEL_REF ( VOIDmode , jump_label ) , pc_rtx ) ; insn = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; predict_jump ( REG_BR_PROB_BASE * 50 / 100 ) ; JUMP_LABEL ( insn ) = jump_label ; emit_insn ( gen_negxf2 ( e2 , e2 ) ) ; emit_label ( jump_label ) ; LABEL_NUSES ( jump_label ) = 1 ; emit_move_insn ( op0 , e2 ) ; } </s>

Output code to perform an tanh XFmode calculation .


<s> void ix86_emit_swdivsf ( rtx res , rtx a , rtx b , machine_mode mode ) { rtx x0 , x1 , e0 , e1 ; x0 = gen_reg_rtx ( mode ) ; e0 = gen_reg_rtx ( mode ) ; e1 = gen_reg_rtx ( mode ) ; x1 = gen_reg_rtx ( mode ) ; b = force_reg ( mode , b ) ; if ( mode == V16SFmode || mode == V8DFmode ) { if ( TARGET_AVX512ER ) { emit_insn ( gen_rtx_SET ( x0 , gen_rtx_UNSPEC ( mode , gen_rtvec ( 1 , b ) , UNSPEC_RCP28 ) ) ) ; emit_insn ( gen_rtx_SET ( res , gen_rtx_MULT ( mode , a , x0 ) ) ) ; return ; } else emit_insn ( gen_rtx_SET ( x0 , gen_rtx_UNSPEC ( mode , gen_rtvec ( 1 , b ) , UNSPEC_RCP14 ) ) ) ; } else emit_insn ( gen_rtx_SET ( x0 , gen_rtx_UNSPEC ( mode , gen_rtvec ( 1 , b ) , UNSPEC_RCP ) ) ) ; emit_insn ( gen_rtx_SET ( e0 , gen_rtx_MULT ( mode , x0 , b ) ) ) ; emit_insn ( gen_rtx_SET ( e0 , gen_rtx_MULT ( mode , x0 , e0 ) ) ) ; emit_insn ( gen_rtx_SET ( e1 , gen_rtx_PLUS ( mode , x0 , x0 ) ) ) ; emit_insn ( gen_rtx_SET ( x1 , gen_rtx_MINUS ( mode , e1 , e0 ) ) ) ; emit_insn ( gen_rtx_SET ( res , gen_rtx_MULT ( mode , a , x1 ) ) ) ; } </s>


<s> static void ix86_emit_vec_binop ( enum rtx_code code , machine_mode mode , rtx dst , rtx src1 , rtx src2 ) { rtx tmp ; tmp = gen_rtx_SET ( dst , gen_rtx_fmt_ee ( code , mode , src1 , src2 ) ) ; if ( GET_MODE_SIZE ( mode ) <= GET_MODE_SIZE ( SImode ) && GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) { rtx clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; tmp = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , tmp , clob ) ) ; } emit_insn ( tmp ) ; } </s>

Emit x86 binary operand CODE in mode MODE for SSE vector instructions that can be performed using GP registers .


<s> static rtx ix86_erase_embedded_rounding ( rtx pat ) { if ( GET_CODE ( pat ) == INSN ) pat = PATTERN ( pat ) ; gcc_assert ( GET_CODE ( pat ) == SET ) ; rtx src = SET_SRC ( pat ) ; gcc_assert ( XVECLEN ( src , 0 ) == 2 ) ; rtx p0 = XVECEXP ( src , 0 , 0 ) ; gcc_assert ( GET_CODE ( src ) == UNSPEC && XINT ( src , 1 ) == UNSPEC_EMBEDDED_ROUNDING ) ; rtx res = gen_rtx_SET ( SET_DEST ( pat ) , p0 ) ; return res ; } </s>

Transform pattern of following layout : ( parallel [ set ( A B ) ( unspec [ C ] UNSPEC_EMBEDDED_ROUNDING ) ] ) ] ) into : ( set ( A B ) ) Or : ( parallel [ A B ... ( unspec [ C ] UNSPEC_EMBEDDED_ROUNDING ) ... ] ) into : ( parallel [ A B ... ] )


<s> rtx ix86_expand_adjust_ufix_to_sfix_si ( rtx val , rtx * xorp ) { REAL_VALUE_TYPE TWO31r ; rtx two31r , tmp [ 4 ] ; machine_mode mode = GET_MODE ( val ) ; machine_mode scalarmode = GET_MODE_INNER ( mode ) ; machine_mode intmode = GET_MODE_SIZE ( mode ) == 32 ? V8SImode : V4SImode ; rtx ( * cmp ) ( rtx , rtx , rtx , rtx ) ; int i ; for ( i = 0 ; i < 3 ; i ++ ) tmp [ i ] = gen_reg_rtx ( mode ) ; real_ldexp ( & TWO31r , & dconst1 , 31 ) ; two31r = const_double_from_real_value ( TWO31r , scalarmode ) ; two31r = ix86_build_const_vector ( mode , 1 , two31r ) ; two31r = force_reg ( mode , two31r ) ; switch ( mode ) { case E_V8SFmode : cmp = gen_avx_maskcmpv8sf3 ; break ; case E_V4SFmode : cmp = gen_sse_maskcmpv4sf3 ; break ; case E_V4DFmode : cmp = gen_avx_maskcmpv4df3 ; break ; case E_V2DFmode : cmp = gen_sse2_maskcmpv2df3 ; break ; default : gcc_unreachable ( ) ; } tmp [ 3 ] = gen_rtx_LE ( mode , two31r , val ) ; emit_insn ( cmp ( tmp [ 0 ] , two31r , val , tmp [ 3 ] ) ) ; tmp [ 1 ] = expand_simple_binop ( mode , AND , tmp [ 0 ] , two31r , tmp [ 1 ] , 0 , OPTAB_DIRECT ) ; if ( intmode == V4SImode || TARGET_AVX2 ) * xorp = expand_simple_binop ( intmode , ASHIFT , gen_lowpart ( intmode , tmp [ 0 ] ) , GEN_INT ( 31 ) , NULL_RTX , 0 , OPTAB_DIRECT ) ; else { rtx two31 = gen_int_mode ( HOST_WIDE_INT_1U << 31 , SImode ) ; two31 = ix86_build_const_vector ( intmode , 1 , two31 ) ; * xorp = expand_simple_binop ( intmode , AND , gen_lowpart ( intmode , tmp [ 0 ] ) , two31 , NULL_RTX , 0 , OPTAB_DIRECT ) ; } return expand_simple_binop ( mode , MINUS , val , tmp [ 1 ] , tmp [ 2 ] , 0 , OPTAB_DIRECT ) ; } </s>

Adjust a V * SFmode/V * DFmode value VAL so that * sfix_trunc * resp . fix_trunc * pattern can be used on it instead of fixuns_trunc * . This is done by doing just signed conversion if < 0x1p31 , and otherwise by subtracting 0x1p31 first and xoring in 0x80000000 from * XORP afterwards .


<s> static rtx_code_label * ix86_expand_aligntest ( rtx variable , int value , bool epilogue ) { rtx_code_label * label = gen_label_rtx ( ) ; rtx tmpcount = gen_reg_rtx ( GET_MODE ( variable ) ) ; if ( GET_MODE ( variable ) == DImode ) emit_insn ( gen_anddi3 ( tmpcount , variable , GEN_INT ( value ) ) ) ; else emit_insn ( gen_andsi3 ( tmpcount , variable , GEN_INT ( value ) ) ) ; emit_cmp_and_jump_insns ( tmpcount , const0_rtx , EQ , 0 , GET_MODE ( variable ) , 1 , label ) ; if ( epilogue ) predict_jump ( REG_BR_PROB_BASE * 50 / 100 ) ; else predict_jump ( REG_BR_PROB_BASE * 90 / 100 ) ; return label ; } </s>

Helper function for the string operations below . Dest VARIABLE whether it is aligned to VALUE bytes . If true , jump to the label .


<s> static void ix86_expand_ashl_const ( rtx operand , int count , machine_mode mode ) { if ( count == 1 || ( count * ix86_cost -> add <= ix86_cost -> shift_const && ! optimize_insn_for_size_p ( ) ) ) { while ( count -- > 0 ) emit_insn ( gen_add2_insn ( operand , operand ) ) ; } else { rtx ( * insn ) ( rtx , rtx , rtx ) ; insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3 ; emit_insn ( insn ( operand , operand , GEN_INT ( count ) ) ) ; } } </s>

Helper function of ix86_split_ashl used to generate an SImode/DImode left shift by a constant , either using a single shift or a sequence of add instructions .


<s> void ix86_expand_binary_operator ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { rtx src1 , src2 , dst , op , clob ; dst = ix86_fixup_binary_operands ( code , mode , operands ) ; src1 = operands [ 1 ] ; src2 = operands [ 2 ] ; op = gen_rtx_SET ( dst , gen_rtx_fmt_ee ( code , mode , src1 , src2 ) ) ; if ( reload_completed && code == PLUS && ! rtx_equal_p ( dst , src1 ) ) { emit_insn ( op ) ; } else { clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , op , clob ) ) ) ; } if ( dst != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , dst ) ; } </s>

Attempt to expand a binary operator . Make the expansion closer to the actual machine , then just general_operand , which will allow 3 separate memory references ( one output , two input ) in a single insn .


<s> static rtx ix86_expand_binop_builtin ( enum insn_code icode , tree exp , rtx target ) { rtx pat ; tree arg0 = CALL_EXPR_ARG ( exp , 0 ) ; tree arg1 = CALL_EXPR_ARG ( exp , 1 ) ; rtx op0 = expand_normal ( arg0 ) ; rtx op1 = expand_normal ( arg1 ) ; machine_mode tmode = insn_data [ icode ] . operand [ 0 ] . mode ; machine_mode mode0 = insn_data [ icode ] . operand [ 1 ] . mode ; machine_mode mode1 = insn_data [ icode ] . operand [ 2 ] . mode ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( VECTOR_MODE_P ( mode1 ) ) op1 = safe_vector_operand ( op1 , mode1 ) ; if ( optimize || ! target || GET_MODE ( target ) != tmode || ! insn_data [ icode ] . operand [ 0 ] . predicate ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; if ( GET_MODE ( op1 ) == SImode && mode1 == TImode ) { rtx x = gen_reg_rtx ( V4SImode ) ; emit_insn ( gen_sse2_loadd ( x , op1 ) ) ; op1 = gen_lowpart ( TImode , x ) ; } if ( ! insn_data [ icode ] . operand [ 1 ] . predicate ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; if ( ! insn_data [ icode ] . operand [ 2 ] . predicate ( op1 , mode1 ) ) op1 = copy_to_mode_reg ( mode1 , op1 ) ; pat = GEN_FCN ( icode ) ( target , op0 , op1 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of ix86_expand_builtin to take care of binop insns .


<s> void ix86_expand_clear ( rtx dest ) { rtx tmp ; gcc_assert ( reload_completed ) ; if ( GET_MODE_SIZE ( GET_MODE ( dest ) ) < 4 ) dest = gen_rtx_REG ( SImode , REGNO ( dest ) ) ; tmp = gen_rtx_SET ( dest , const0_rtx ) ; if ( ! TARGET_USE_MOV0 || optimize_insn_for_size_p ( ) ) { rtx clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; tmp = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , tmp , clob ) ) ; } emit_insn ( tmp ) ; } </s>

Generate either `` mov $ 0 , reg '' or `` xor reg , reg '' , as appropriate for the target .


<s> bool ix86_expand_cmpstrn_or_cmpmem ( rtx result , rtx src1 , rtx src2 , rtx length , rtx align , bool is_cmpstrn ) { if ( ! TARGET_INLINE_ALL_STRINGOPS ) return false ; if ( fixed_regs [ CX_REG ] || fixed_regs [ SI_REG ] || fixed_regs [ DI_REG ] ) return false ; if ( is_cmpstrn ) { tree t1 = MEM_EXPR ( src1 ) ; tree t2 = MEM_EXPR ( src2 ) ; if ( ! ( ( t1 && TREE_CODE ( t1 ) == MEM_REF && TREE_CODE ( TREE_OPERAND ( t1 , 0 ) ) == ADDR_EXPR && ( TREE_CODE ( TREE_OPERAND ( TREE_OPERAND ( t1 , 0 ) , 0 ) ) == STRING_CST ) ) || ( t2 && TREE_CODE ( t2 ) == MEM_REF && TREE_CODE ( TREE_OPERAND ( t2 , 0 ) ) == ADDR_EXPR && ( TREE_CODE ( TREE_OPERAND ( TREE_OPERAND ( t2 , 0 ) , 0 ) ) == STRING_CST ) ) ) ) return false ; } rtx addr1 = copy_addr_to_reg ( XEXP ( src1 , 0 ) ) ; rtx addr2 = copy_addr_to_reg ( XEXP ( src2 , 0 ) ) ; if ( addr1 != XEXP ( src1 , 0 ) ) src1 = replace_equiv_address_nv ( src1 , addr1 ) ; if ( addr2 != XEXP ( src2 , 0 ) ) src2 = replace_equiv_address_nv ( src2 , addr2 ) ; length = ix86_zero_extend_to_Pmode ( length ) ; rtx lengthreg = gen_reg_rtx ( Pmode ) ; emit_move_insn ( lengthreg , length ) ; if ( CONST_INT_P ( length ) ) { if ( length == const0_rtx ) { emit_move_insn ( result , const0_rtx ) ; return true ; } emit_insn ( gen_cmpstrnqi_nz_1 ( addr1 , addr2 , lengthreg , align , src1 , src2 ) ) ; } else { emit_insn ( gen_cmp_1 ( Pmode , lengthreg , lengthreg ) ) ; emit_insn ( gen_cmpstrnqi_1 ( addr1 , addr2 , lengthreg , align , src1 , src2 ) ) ; } rtx out = gen_lowpart ( QImode , result ) ; emit_insn ( gen_cmpintqi ( out ) ) ; emit_move_insn ( result , gen_rtx_SIGN_EXTEND ( SImode , out ) ) ; return true ; } </s>


<s> void ix86_expand_convert_sign_didf_sse ( rtx target , rtx input ) { REAL_VALUE_TYPE TWO32r ; rtx fp_lo , fp_hi , x ; fp_lo = gen_reg_rtx ( DFmode ) ; fp_hi = gen_reg_rtx ( DFmode ) ; emit_insn ( gen_floatsidf2 ( fp_hi , gen_highpart ( SImode , input ) ) ) ; real_ldexp ( & TWO32r , & dconst1 , 32 ) ; x = const_double_from_real_value ( TWO32r , DFmode ) ; fp_hi = expand_simple_binop ( DFmode , MULT , fp_hi , x , fp_hi , 0 , OPTAB_DIRECT ) ; ix86_expand_convert_uns_sidf_sse ( fp_lo , gen_lowpart ( SImode , input ) ) ; x = expand_simple_binop ( DFmode , PLUS , fp_hi , fp_lo , target , 0 , OPTAB_DIRECT ) ; if ( x != target ) emit_move_insn ( target , x ) ; } </s>

Convert a signed DImode value into a DFmode . Only used for SSE in 32-bit mode ; otherwise we have a direct convert instruction .


<s> void ix86_expand_convert_uns_didf_sse ( rtx target , rtx input ) { REAL_VALUE_TYPE bias_lo_rvt , bias_hi_rvt ; rtx int_xmm , fp_xmm ; rtx biases , exponents ; rtx x ; int_xmm = gen_reg_rtx ( V4SImode ) ; if ( TARGET_INTER_UNIT_MOVES_TO_VEC ) emit_insn ( gen_movdi_to_sse ( int_xmm , input ) ) ; else if ( TARGET_SSE_SPLIT_REGS ) { emit_clobber ( int_xmm ) ; emit_move_insn ( gen_lowpart ( DImode , int_xmm ) , input ) ; } else { x = gen_reg_rtx ( V2DImode ) ; ix86_expand_vector_init_one_nonzero ( false , V2DImode , x , input , 0 ) ; emit_move_insn ( int_xmm , gen_lowpart ( V4SImode , x ) ) ; } x = gen_rtx_CONST_VECTOR ( V4SImode , gen_rtvec ( 4 , GEN_INT ( 0x43300000UL ) , GEN_INT ( 0x45300000UL ) , const0_rtx , const0_rtx ) ) ; exponents = validize_mem ( force_const_mem ( V4SImode , x ) ) ; emit_insn ( gen_vec_interleave_lowv4si ( int_xmm , int_xmm , exponents ) ) ; fp_xmm = copy_to_mode_reg ( V2DFmode , gen_lowpart ( V2DFmode , int_xmm ) ) ; real_ldexp ( & bias_lo_rvt , & dconst1 , 52 ) ; real_ldexp ( & bias_hi_rvt , & dconst1 , 84 ) ; biases = const_double_from_real_value ( bias_lo_rvt , DFmode ) ; x = const_double_from_real_value ( bias_hi_rvt , DFmode ) ; biases = gen_rtx_CONST_VECTOR ( V2DFmode , gen_rtvec ( 2 , biases , x ) ) ; biases = validize_mem ( force_const_mem ( V2DFmode , biases ) ) ; emit_insn ( gen_subv2df3 ( fp_xmm , fp_xmm , biases ) ) ; if ( TARGET_SSE3 ) emit_insn ( gen_sse3_haddv2df3 ( fp_xmm , fp_xmm , fp_xmm ) ) ; else { x = copy_to_mode_reg ( V2DFmode , fp_xmm ) ; emit_insn ( gen_vec_interleave_highv2df ( fp_xmm , fp_xmm , fp_xmm ) ) ; emit_insn ( gen_addv2df3 ( fp_xmm , fp_xmm , x ) ) ; } ix86_expand_vector_extract ( false , target , fp_xmm , 0 ) ; } </s>

Convert an unsigned DImode value into a DFmode , using only SSE . Expects the 64-bit DImode to be supplied in a pair of integral registers . Requires SSE2 ; will use SSE3 if available . For x86_32 , -mfpmath=sse , ! optimize_size only .


<s> void ix86_expand_convert_uns_sidf_sse ( rtx target , rtx input ) { REAL_VALUE_TYPE TWO31r ; rtx x , fp ; x = expand_simple_binop ( SImode , PLUS , input , GEN_INT ( - 2147483647 - 1 ) , NULL , 1 , OPTAB_DIRECT ) ; fp = gen_reg_rtx ( DFmode ) ; emit_insn ( gen_floatsidf2 ( fp , x ) ) ; real_ldexp ( & TWO31r , & dconst1 , 31 ) ; x = const_double_from_real_value ( TWO31r , DFmode ) ; x = expand_simple_binop ( DFmode , PLUS , fp , x , target , 0 , OPTAB_DIRECT ) ; if ( HONOR_SIGNED_ZEROS ( DFmode ) && flag_rounding_math ) x = ix86_expand_sse_fabs ( x , NULL ) ; if ( x != target ) emit_move_insn ( target , x ) ; } </s>

Convert an unsigned SImode value into a DFmode . Only currently used for SSE , but applicable anywhere .


<s> void ix86_expand_convert_uns_sisf_sse ( rtx target , rtx input ) { REAL_VALUE_TYPE ONE16r ; rtx fp_hi , fp_lo , int_hi , int_lo , x ; real_ldexp ( & ONE16r , & dconst1 , 16 ) ; x = const_double_from_real_value ( ONE16r , SFmode ) ; int_lo = expand_simple_binop ( SImode , AND , input , GEN_INT ( 0xffff ) , NULL , 0 , OPTAB_DIRECT ) ; int_hi = expand_simple_binop ( SImode , LSHIFTRT , input , GEN_INT ( 16 ) , NULL , 0 , OPTAB_DIRECT ) ; fp_hi = gen_reg_rtx ( SFmode ) ; fp_lo = gen_reg_rtx ( SFmode ) ; emit_insn ( gen_floatsisf2 ( fp_hi , int_hi ) ) ; emit_insn ( gen_floatsisf2 ( fp_lo , int_lo ) ) ; if ( TARGET_FMA ) { x = validize_mem ( force_const_mem ( SFmode , x ) ) ; fp_hi = gen_rtx_FMA ( SFmode , fp_hi , x , fp_lo ) ; emit_move_insn ( target , fp_hi ) ; } else { fp_hi = expand_simple_binop ( SFmode , MULT , fp_hi , x , fp_hi , 0 , OPTAB_DIRECT ) ; fp_hi = expand_simple_binop ( SFmode , PLUS , fp_hi , fp_lo , target , 0 , OPTAB_DIRECT ) ; if ( ! rtx_equal_p ( target , fp_hi ) ) emit_move_insn ( target , fp_hi ) ; } } </s>

Convert an unsigned SImode value into a SFmode , using only SSE . For x86_32 , -mfpmath=sse , ! optimize_size only .


<s> void ix86_expand_convert_uns_sixf_sse ( rtx , rtx ) { gcc_unreachable ( ) ; } </s>

Not used , but eases macroization of patterns .


<s> void ix86_expand_copysign ( rtx operands [ ] ) { machine_mode mode , vmode ; rtx dest , vdest , op0 , op1 , mask , op2 , op3 ; mode = GET_MODE ( operands [ 0 ] ) ; if ( mode == HFmode ) vmode = V8HFmode ; else if ( mode == SFmode ) vmode = V4SFmode ; else if ( mode == DFmode ) vmode = V2DFmode ; else if ( mode == TFmode ) vmode = mode ; else gcc_unreachable ( ) ; if ( rtx_equal_p ( operands [ 1 ] , operands [ 2 ] ) ) { emit_move_insn ( operands [ 0 ] , operands [ 1 ] ) ; return ; } dest = operands [ 0 ] ; vdest = lowpart_subreg ( vmode , dest , mode ) ; if ( vdest == NULL_RTX ) vdest = gen_reg_rtx ( vmode ) ; else dest = NULL_RTX ; op1 = lowpart_subreg ( vmode , force_reg ( mode , operands [ 2 ] ) , mode ) ; mask = ix86_build_signbit_mask ( vmode , 0 , 0 ) ; if ( CONST_DOUBLE_P ( operands [ 1 ] ) ) { op0 = simplify_unary_operation ( ABS , mode , operands [ 1 ] , mode ) ; if ( op0 == CONST0_RTX ( mode ) ) { emit_move_insn ( vdest , gen_rtx_AND ( vmode , mask , op1 ) ) ; if ( dest ) emit_move_insn ( dest , lowpart_subreg ( mode , vdest , vmode ) ) ; return ; } if ( GET_MODE_SIZE ( mode ) < 16 ) op0 = ix86_build_const_vector ( vmode , false , op0 ) ; op0 = force_reg ( vmode , op0 ) ; } else op0 = lowpart_subreg ( vmode , force_reg ( mode , operands [ 1 ] ) , mode ) ; op2 = gen_reg_rtx ( vmode ) ; op3 = gen_reg_rtx ( vmode ) ; emit_move_insn ( op2 , gen_rtx_AND ( vmode , gen_rtx_NOT ( vmode , mask ) , op0 ) ) ; emit_move_insn ( op3 , gen_rtx_AND ( vmode , mask , op1 ) ) ; emit_move_insn ( vdest , gen_rtx_IOR ( vmode , op2 , op3 ) ) ; if ( dest ) emit_move_insn ( dest , lowpart_subreg ( mode , vdest , vmode ) ) ; } </s>

Expand a copysign operation . Special case operand 0 being a constant .


<s> void ix86_expand_divmod_libfunc ( rtx libfunc , machine_mode mode , rtx op0 , rtx op1 , rtx * quot_p , rtx * rem_p ) { rtx rem = assign_386_stack_local ( mode , SLOT_TEMP ) ; rtx quot = emit_library_call_value ( libfunc , NULL_RTX , LCT_NORMAL , mode , op0 , mode , op1 , mode , XEXP ( rem , 0 ) , Pmode ) ; * quot_p = quot ; * rem_p = rem ; } </s>


<s> void ix86_expand_floorceil ( rtx operand0 , rtx operand1 , bool do_floor ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , xi , TWO52 , tmp , one , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = copy_to_reg ( operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xi = gen_reg_rtx ( int_mode_for_mode ( mode ) . require ( ) ) ; expand_fix ( xi , res , 0 ) ; expand_float ( xa , xi , 0 ) ; one = force_reg ( mode , const_double_from_real_value ( dconst1 , mode ) ) ; tmp = ix86_expand_sse_compare_mask ( UNGT , xa , res , ! do_floor ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , one , tmp ) ) ) ; tmp = expand_simple_binop ( mode , do_floor ? MINUS : PLUS , xa , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; if ( HONOR_SIGNED_ZEROS ( mode ) ) { if ( do_floor && flag_rounding_math ) tmp = ix86_expand_sse_fabs ( tmp , NULL ) ; ix86_sse_copysign_to_positive ( tmp , tmp , res , mask ) ; } emit_move_insn ( res , tmp ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand SSE2 sequence for computing floor or ceil from OPERAND1 storing into OPERAND0 .


<s> void ix86_expand_floorceildf_32 ( rtx operand0 , rtx operand1 , bool do_floor ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , TWO52 , tmp , one , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = copy_to_reg ( operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xa = expand_simple_binop ( mode , PLUS , xa , TWO52 , NULL_RTX , 0 , OPTAB_DIRECT ) ; xa = expand_simple_binop ( mode , MINUS , xa , TWO52 , xa , 0 , OPTAB_DIRECT ) ; ix86_sse_copysign_to_positive ( xa , xa , res , mask ) ; one = force_reg ( mode , const_double_from_real_value ( dconst1 , mode ) ) ; tmp = ix86_expand_sse_compare_mask ( UNGT , xa , res , ! do_floor ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , one , tmp ) ) ) ; tmp = expand_simple_binop ( mode , do_floor ? MINUS : PLUS , xa , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; if ( HONOR_SIGNED_ZEROS ( mode ) ) { if ( do_floor && flag_rounding_math ) tmp = ix86_expand_sse_fabs ( tmp , NULL ) ; ix86_sse_copysign_to_positive ( tmp , tmp , res , mask ) ; } emit_move_insn ( res , tmp ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>


<s> void ix86_expand_fp_absneg_operator ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { rtx set , dst , src ; bool use_sse = false ; bool vector_mode = VECTOR_MODE_P ( mode ) ; machine_mode vmode = mode ; rtvec par ; if ( vector_mode || mode == TFmode || mode == HFmode ) { use_sse = true ; if ( mode == HFmode ) vmode = V8HFmode ; } else if ( TARGET_SSE_MATH ) { use_sse = SSE_FLOAT_MODE_P ( mode ) ; if ( mode == SFmode ) vmode = V4SFmode ; else if ( mode == DFmode ) vmode = V2DFmode ; } dst = operands [ 0 ] ; src = operands [ 1 ] ; set = gen_rtx_fmt_e ( code , mode , src ) ; set = gen_rtx_SET ( dst , set ) ; if ( use_sse ) { rtx mask , use , clob ; mask = ix86_build_signbit_mask ( vmode , vector_mode , code == ABS ) ; use = gen_rtx_USE ( VOIDmode , mask ) ; if ( vector_mode || mode == TFmode ) par = gen_rtvec ( 2 , set , use ) ; else { clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; par = gen_rtvec ( 3 , set , use , clob ) ; } } else { rtx clob ; clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; par = gen_rtvec ( 2 , set , clob ) ; } emit_insn ( gen_rtx_PARALLEL ( VOIDmode , par ) ) ; } </s>

Generate code for floating point ABS or NEG .


<s> bool ix86_expand_fp_movcc ( rtx operands [ ] ) { machine_mode mode = GET_MODE ( operands [ 0 ] ) ; enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx tmp , compare_op ; rtx op0 = XEXP ( operands [ 1 ] , 0 ) ; rtx op1 = XEXP ( operands [ 1 ] , 1 ) ; if ( SSE_FLOAT_MODE_SSEMATH_OR_HF_P ( mode ) ) { machine_mode cmode ; cmode = GET_MODE ( op0 ) ; if ( cmode == VOIDmode ) cmode = GET_MODE ( op1 ) ; if ( cmode != mode ) return false ; code = ix86_prepare_sse_fp_compare_args ( operands [ 0 ] , code , & op0 , & op1 ) ; if ( code == UNKNOWN ) return false ; if ( ix86_expand_sse_fp_minmax ( operands [ 0 ] , code , op0 , op1 , operands [ 2 ] , operands [ 3 ] ) ) return true ; tmp = ix86_expand_sse_cmp ( operands [ 0 ] , code , op0 , op1 , operands [ 2 ] , operands [ 3 ] ) ; ix86_expand_sse_movcc ( operands [ 0 ] , tmp , operands [ 2 ] , operands [ 3 ] ) ; return true ; } if ( GET_MODE ( op0 ) == TImode || ( GET_MODE ( op0 ) == DImode && ! TARGET_64BIT ) ) return false ; compare_op = ix86_expand_compare ( code , op0 , op1 ) ; if ( ! fcmov_comparison_operator ( compare_op , VOIDmode ) ) { tmp = gen_reg_rtx ( QImode ) ; ix86_expand_setcc ( tmp , code , op0 , op1 ) ; compare_op = ix86_expand_compare ( NE , tmp , const0_rtx ) ; } emit_insn ( gen_rtx_SET ( operands [ 0 ] , gen_rtx_IF_THEN_ELSE ( mode , compare_op , operands [ 2 ] , operands [ 3 ] ) ) ) ; return true ; } </s>

Expand a floating-point conditional move . Return true if successful .


<s> bool ix86_expand_fp_vcond ( rtx operands [ ] ) { enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; rtx cmp ; code = ix86_prepare_sse_fp_compare_args ( operands [ 0 ] , code , & operands [ 4 ] , & operands [ 5 ] ) ; if ( code == UNKNOWN ) { rtx temp ; switch ( GET_CODE ( operands [ 3 ] ) ) { case LTGT : temp = ix86_expand_sse_cmp ( operands [ 0 ] , ORDERED , operands [ 4 ] , operands [ 5 ] , operands [ 0 ] , operands [ 0 ] ) ; cmp = ix86_expand_sse_cmp ( operands [ 0 ] , NE , operands [ 4 ] , operands [ 5 ] , operands [ 1 ] , operands [ 2 ] ) ; code = AND ; break ; case UNEQ : temp = ix86_expand_sse_cmp ( operands [ 0 ] , UNORDERED , operands [ 4 ] , operands [ 5 ] , operands [ 0 ] , operands [ 0 ] ) ; cmp = ix86_expand_sse_cmp ( operands [ 0 ] , EQ , operands [ 4 ] , operands [ 5 ] , operands [ 1 ] , operands [ 2 ] ) ; code = IOR ; break ; default : gcc_unreachable ( ) ; } cmp = expand_simple_binop ( GET_MODE ( cmp ) , code , temp , cmp , cmp , 1 , OPTAB_DIRECT ) ; ix86_expand_sse_movcc ( operands [ 0 ] , cmp , operands [ 1 ] , operands [ 2 ] ) ; return true ; } if ( ix86_expand_sse_fp_minmax ( operands [ 0 ] , code , operands [ 4 ] , operands [ 5 ] , operands [ 1 ] , operands [ 2 ] ) ) return true ; cmp = ix86_expand_sse_cmp ( operands [ 0 ] , code , operands [ 4 ] , operands [ 5 ] , operands [ 1 ] , operands [ 2 ] ) ; ix86_expand_sse_movcc ( operands [ 0 ] , cmp , operands [ 1 ] , operands [ 2 ] ) ; return true ; } </s>

Expand a floating-point vector conditional move ; a vcond operation rather than a movcc operation .


<s> bool ix86_expand_fp_vec_cmp ( rtx operands [ ] ) { enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx cmp ; code = ix86_prepare_sse_fp_compare_args ( operands [ 0 ] , code , & operands [ 2 ] , & operands [ 3 ] ) ; if ( code == UNKNOWN ) { rtx temp ; switch ( GET_CODE ( operands [ 1 ] ) ) { case LTGT : temp = ix86_expand_sse_cmp ( operands [ 0 ] , ORDERED , operands [ 2 ] , operands [ 3 ] , NULL , NULL ) ; cmp = ix86_expand_sse_cmp ( operands [ 0 ] , NE , operands [ 2 ] , operands [ 3 ] , NULL , NULL ) ; code = AND ; break ; case UNEQ : temp = ix86_expand_sse_cmp ( operands [ 0 ] , UNORDERED , operands [ 2 ] , operands [ 3 ] , NULL , NULL ) ; cmp = ix86_expand_sse_cmp ( operands [ 0 ] , EQ , operands [ 2 ] , operands [ 3 ] , NULL , NULL ) ; code = IOR ; break ; default : gcc_unreachable ( ) ; } cmp = expand_simple_binop ( GET_MODE ( cmp ) , code , temp , cmp , cmp , 1 , OPTAB_DIRECT ) ; } else cmp = ix86_expand_sse_cmp ( operands [ 0 ] , code , operands [ 2 ] , operands [ 3 ] , NULL , NULL ) ; if ( operands [ 0 ] != cmp ) emit_move_insn ( operands [ 0 ] , cmp ) ; return true ; } </s>


<s> bool ix86_expand_int_addcc ( rtx operands [ ] ) { enum rtx_code code = GET_CODE ( operands [ 1 ] ) ; rtx flags ; rtx ( * insn ) ( machine_mode , rtx , rtx , rtx , rtx , rtx ) ; rtx compare_op ; rtx val = const0_rtx ; bool fpcmp = false ; machine_mode mode ; rtx op0 = XEXP ( operands [ 1 ] , 0 ) ; rtx op1 = XEXP ( operands [ 1 ] , 1 ) ; if ( operands [ 3 ] != const1_rtx && operands [ 3 ] != constm1_rtx ) return false ; if ( ! ix86_expand_carry_flag_compare ( code , op0 , op1 , & compare_op ) ) return false ; code = GET_CODE ( compare_op ) ; flags = XEXP ( compare_op , 0 ) ; if ( GET_MODE ( flags ) == CCFPmode ) { fpcmp = true ; code = ix86_fp_compare_code_to_integer ( code ) ; } if ( code != LTU ) { val = constm1_rtx ; if ( fpcmp ) PUT_CODE ( compare_op , reverse_condition_maybe_unordered ( GET_CODE ( compare_op ) ) ) ; else PUT_CODE ( compare_op , reverse_condition ( GET_CODE ( compare_op ) ) ) ; } mode = GET_MODE ( operands [ 0 ] ) ; if ( ( code == LTU ) == ( operands [ 3 ] == constm1_rtx ) ) insn = gen_sub3_carry ; else insn = gen_add3_carry ; emit_insn ( insn ( mode , operands [ 0 ] , operands [ 2 ] , val , flags , compare_op ) ) ; return true ; } </s>

Expand conditional increment or decrement using adb/sbb instructions . The default case using setcc followed by the conditional move can be done by generic code .


<s> static rtx ix86_expand_int_compare ( enum rtx_code code , rtx op0 , rtx op1 ) { machine_mode cmpmode ; rtx tmp , flags ; if ( ( code == GTU || code == LEU ) && nonimmediate_operand ( op1 , VOIDmode ) ) { std :: swap ( op0 , op1 ) ; code = swap_condition ( code ) ; } cmpmode = SELECT_CC_MODE ( code , op0 , op1 ) ; flags = gen_rtx_REG ( cmpmode , FLAGS_REG ) ; tmp = gen_rtx_COMPARE ( cmpmode , op0 , op1 ) ; emit_insn ( gen_rtx_SET ( flags , tmp ) ) ; return gen_rtx_fmt_ee ( code , VOIDmode , flags , const0_rtx ) ; } </s>

Generate insn patterns to do an integer compare of OPERANDS .


<s> bool ix86_expand_int_vcond ( rtx operands [ ] ) { machine_mode data_mode = GET_MODE ( operands [ 0 ] ) ; machine_mode mode = GET_MODE ( operands [ 4 ] ) ; enum rtx_code code = GET_CODE ( operands [ 3 ] ) ; bool negate = false ; rtx x , cop0 , cop1 ; cop0 = operands [ 4 ] ; cop1 = operands [ 5 ] ; if ( ( code == LT || code == GE ) && data_mode == mode && cop1 == CONST0_RTX ( mode ) && operands [ 1 + ( code == LT ) ] == CONST0_RTX ( data_mode ) && GET_MODE_UNIT_SIZE ( data_mode ) > 1 && GET_MODE_UNIT_SIZE ( data_mode ) <= 8 && ( GET_MODE_SIZE ( data_mode ) == 16 || ( TARGET_AVX2 && GET_MODE_SIZE ( data_mode ) == 32 ) ) ) { rtx negop = operands [ 2 - ( code == LT ) ] ; int shift = GET_MODE_UNIT_BITSIZE ( data_mode ) - 1 ; if ( negop == CONST1_RTX ( data_mode ) ) { rtx res = expand_simple_binop ( mode , LSHIFTRT , cop0 , GEN_INT ( shift ) , operands [ 0 ] , 1 , OPTAB_DIRECT ) ; if ( res != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , res ) ; return true ; } else if ( GET_MODE_INNER ( data_mode ) != DImode && vector_all_ones_operand ( negop , data_mode ) ) { rtx res = expand_simple_binop ( mode , ASHIFTRT , cop0 , GEN_INT ( shift ) , operands [ 0 ] , 0 , OPTAB_DIRECT ) ; if ( res != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , res ) ; return true ; } } if ( ! nonimmediate_operand ( cop1 , mode ) ) cop1 = force_reg ( mode , cop1 ) ; if ( ! general_operand ( operands [ 1 ] , data_mode ) ) operands [ 1 ] = force_reg ( data_mode , operands [ 1 ] ) ; if ( ! general_operand ( operands [ 2 ] , data_mode ) ) operands [ 2 ] = force_reg ( data_mode , operands [ 2 ] ) ; x = ix86_expand_int_sse_cmp ( operands [ 0 ] , code , cop0 , cop1 , operands [ 1 ] , operands [ 2 ] , & negate ) ; if ( ! x ) return false ; ix86_expand_sse_movcc ( operands [ 0 ] , x , operands [ 1 + negate ] , operands [ 2 - negate ] ) ; return true ; } </s>

Expand a signed integral vector conditional move .


<s> bool ix86_expand_int_vec_cmp ( rtx operands [ ] ) { rtx_code code = GET_CODE ( operands [ 1 ] ) ; bool negate = false ; rtx cmp = ix86_expand_int_sse_cmp ( operands [ 0 ] , code , operands [ 2 ] , operands [ 3 ] , NULL , NULL , & negate ) ; if ( ! cmp ) return false ; if ( negate ) cmp = ix86_expand_int_sse_cmp ( operands [ 0 ] , EQ , cmp , CONST0_RTX ( GET_MODE ( cmp ) ) , NULL , NULL , & negate ) ; gcc_assert ( ! negate ) ; if ( operands [ 0 ] != cmp ) emit_move_insn ( operands [ 0 ] , cmp ) ; return true ; } </s>


<s> void ix86_expand_lfloorceil ( rtx op0 , rtx op1 , bool do_floor ) { machine_mode fmode = GET_MODE ( op1 ) ; machine_mode imode = GET_MODE ( op0 ) ; rtx ireg , freg , tmp ; rtx_code_label * label ; ireg = gen_reg_rtx ( imode ) ; expand_fix ( ireg , op1 , 0 ) ; freg = gen_reg_rtx ( fmode ) ; expand_float ( freg , ireg , 0 ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , freg , op1 , ! do_floor ) ; tmp = expand_simple_binop ( imode , do_floor ? MINUS : PLUS , ireg , const1_rtx , NULL_RTX , 0 , OPTAB_DIRECT ) ; emit_move_insn ( ireg , tmp ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( op0 , ireg ) ; } </s>

Expand SSE2 sequence for computing lround from OPERAND1 storing into OPERAND0 .


<s> void ix86_expand_lround ( rtx op0 , rtx op1 ) { machine_mode mode = GET_MODE ( op1 ) ; const struct real_format * fmt ; REAL_VALUE_TYPE pred_half , half_minus_pred_half ; rtx adj ; fmt = REAL_MODE_FORMAT ( mode ) ; real_2expN ( & half_minus_pred_half , - ( fmt -> p ) - 1 , mode ) ; real_arithmetic ( & pred_half , MINUS_EXPR , & dconsthalf , & half_minus_pred_half ) ; adj = force_reg ( mode , const_double_from_real_value ( pred_half , mode ) ) ; ix86_sse_copysign_to_positive ( adj , adj , force_reg ( mode , op1 ) , NULL_RTX ) ; adj = expand_simple_binop ( mode , PLUS , adj , op1 , NULL_RTX , 0 , OPTAB_DIRECT ) ; expand_fix ( op0 , adj , 0 ) ; } </s>

Expand SSE sequence for computing lround from OP1 storing into OP0 .


<s> bool ix86_expand_mask_vec_cmp ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 ) { machine_mode mask_mode = GET_MODE ( dest ) ; machine_mode cmp_mode = GET_MODE ( cmp_op0 ) ; rtx imm = GEN_INT ( ix86_cmp_code_to_pcmp_immediate ( code , cmp_mode ) ) ; int unspec_code ; rtx unspec ; switch ( code ) { case LEU : case GTU : case GEU : case LTU : unspec_code = UNSPEC_UNSIGNED_PCMP ; break ; default : unspec_code = UNSPEC_PCMP ; } unspec = gen_rtx_UNSPEC ( mask_mode , gen_rtvec ( 3 , cmp_op0 , cmp_op1 , imm ) , unspec_code ) ; emit_insn ( gen_rtx_SET ( dest , unspec ) ) ; return true ; } </s>


<s> bool ix86_expand_pextr ( rtx * operands ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 1 ] ; unsigned int size = INTVAL ( operands [ 2 ] ) ; unsigned int pos = INTVAL ( operands [ 3 ] ) ; if ( SUBREG_P ( dst ) ) { if ( SUBREG_BYTE ( dst ) > 0 ) return false ; dst = SUBREG_REG ( dst ) ; } if ( SUBREG_P ( src ) ) { pos += SUBREG_BYTE ( src ) * BITS_PER_UNIT ; src = SUBREG_REG ( src ) ; } switch ( GET_MODE ( src ) ) { case E_V16QImode : case E_V8HImode : case E_V4SImode : case E_V2DImode : case E_V1TImode : { machine_mode srcmode , dstmode ; rtx d , pat ; if ( ! int_mode_for_size ( size , 0 ) . exists ( & dstmode ) ) return false ; switch ( dstmode ) { case E_QImode : if ( ! TARGET_SSE4_1 ) return false ; srcmode = V16QImode ; break ; case E_HImode : if ( ! TARGET_SSE2 ) return false ; srcmode = V8HImode ; break ; case E_SImode : if ( ! TARGET_SSE4_1 ) return false ; srcmode = V4SImode ; break ; case E_DImode : gcc_assert ( TARGET_64BIT ) ; if ( ! TARGET_SSE4_1 ) return false ; srcmode = V2DImode ; break ; default : return false ; } if ( pos & ( size - 1 ) ) return false ; if ( GET_MODE ( dst ) == dstmode ) d = dst ; else d = gen_reg_rtx ( dstmode ) ; pat = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 1 , GEN_INT ( pos / size ) ) ) ; pat = gen_rtx_VEC_SELECT ( dstmode , gen_lowpart ( srcmode , src ) , pat ) ; if ( dstmode == QImode || dstmode == HImode ) { pat = gen_rtx_ZERO_EXTEND ( SImode , pat ) ; d = gen_lowpart ( SImode , d ) ; } emit_insn ( gen_rtx_SET ( d , pat ) ) ; if ( d != dst ) emit_move_insn ( dst , gen_lowpart ( GET_MODE ( dst ) , d ) ) ; return true ; } default : return false ; } } </s>

Expand an extract from a vector register through pextr insn . Return true if successful .


<s> bool ix86_expand_pinsr ( rtx * operands ) { rtx dst = operands [ 0 ] ; rtx src = operands [ 3 ] ; unsigned int size = INTVAL ( operands [ 1 ] ) ; unsigned int pos = INTVAL ( operands [ 2 ] ) ; if ( SUBREG_P ( dst ) ) { pos += SUBREG_BYTE ( dst ) * BITS_PER_UNIT ; dst = SUBREG_REG ( dst ) ; } switch ( GET_MODE ( dst ) ) { case E_V16QImode : case E_V8HImode : case E_V4SImode : case E_V2DImode : case E_V1TImode : { machine_mode srcmode , dstmode ; rtx ( * pinsr ) ( rtx , rtx , rtx , rtx ) ; rtx d ; if ( ! int_mode_for_size ( size , 0 ) . exists ( & srcmode ) ) return false ; switch ( srcmode ) { case E_QImode : if ( ! TARGET_SSE4_1 ) return false ; dstmode = V16QImode ; pinsr = gen_sse4_1_pinsrb ; break ; case E_HImode : if ( ! TARGET_SSE2 ) return false ; dstmode = V8HImode ; pinsr = gen_sse2_pinsrw ; break ; case E_SImode : if ( ! TARGET_SSE4_1 ) return false ; dstmode = V4SImode ; pinsr = gen_sse4_1_pinsrd ; break ; case E_DImode : gcc_assert ( TARGET_64BIT ) ; if ( ! TARGET_SSE4_1 ) return false ; dstmode = V2DImode ; pinsr = gen_sse4_1_pinsrq ; break ; default : return false ; } if ( pos & ( size - 1 ) ) return false ; if ( SUBREG_P ( src ) ) { unsigned int srcpos = SUBREG_BYTE ( src ) ; if ( srcpos > 0 ) { rtx extr_ops [ 4 ] ; extr_ops [ 0 ] = gen_reg_rtx ( srcmode ) ; extr_ops [ 1 ] = gen_lowpart ( srcmode , SUBREG_REG ( src ) ) ; extr_ops [ 2 ] = GEN_INT ( size ) ; extr_ops [ 3 ] = GEN_INT ( srcpos * BITS_PER_UNIT ) ; if ( ! ix86_expand_pextr ( extr_ops ) ) return false ; src = extr_ops [ 0 ] ; } else src = gen_lowpart ( srcmode , SUBREG_REG ( src ) ) ; } if ( GET_MODE ( dst ) == dstmode ) d = dst ; else d = gen_reg_rtx ( dstmode ) ; emit_insn ( pinsr ( d , gen_lowpart ( dstmode , dst ) , gen_lowpart ( srcmode , src ) , GEN_INT ( 1 << ( pos / size ) ) ) ) ; if ( d != dst ) emit_move_insn ( dst , gen_lowpart ( GET_MODE ( dst ) , d ) ) ; return true ; } default : return false ; } } </s>

Expand an insert into a vector register through pinsr insn . Return true if successful .


<s> void ix86_expand_reduc ( rtx ( * fn ) ( rtx , rtx , rtx ) , rtx dest , rtx in ) { rtx half , dst , vec = in ; machine_mode mode = GET_MODE ( in ) ; int i ; if ( TARGET_SSE4_1 && mode == V8HImode && fn == gen_uminv8hi3 ) { emit_insn ( gen_sse4_1_phminposuw ( dest , in ) ) ; return ; } for ( i = GET_MODE_BITSIZE ( mode ) ; i > GET_MODE_UNIT_BITSIZE ( mode ) ; i >>= 1 ) { half = gen_reg_rtx ( mode ) ; emit_reduc_half ( half , vec , i ) ; if ( i == GET_MODE_UNIT_BITSIZE ( mode ) * 2 ) dst = dest ; else dst = gen_reg_rtx ( mode ) ; emit_insn ( fn ( dst , half , vec ) ) ; vec = dst ; } } </s>

Expand a vector reduction . FN is the binary pattern to reduce ; DEST is the destination ; IN is the input vector .


<s> void ix86_expand_rint ( rtx operand0 , rtx operand1 ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx res , xa , TWO52 , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = copy_to_reg ( operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; if ( flag_rounding_math ) { ix86_sse_copysign_to_positive ( TWO52 , TWO52 , res , mask ) ; xa = res ; } xa = expand_simple_binop ( mode , PLUS , xa , TWO52 , NULL_RTX , 0 , OPTAB_DIRECT ) ; xa = expand_simple_binop ( mode , MINUS , xa , TWO52 , xa , 0 , OPTAB_DIRECT ) ; if ( HONOR_SIGNED_ZEROS ( mode ) && flag_rounding_math ) xa = ix86_expand_sse_fabs ( xa , NULL ) ; ix86_sse_copysign_to_positive ( res , xa , res , mask ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand rint ( IEEE round to nearest ) rounding OPERAND1 and storing the result in OPERAND0 .


<s> void ix86_expand_round ( rtx operand0 , rtx operand1 ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx res , TWO52 , xa , xi , half , mask ; rtx_code_label * label ; const struct real_format * fmt ; REAL_VALUE_TYPE pred_half , half_minus_pred_half ; res = copy_to_reg ( operand1 ) ; TWO52 = ix86_gen_TWO52 ( mode ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; fmt = REAL_MODE_FORMAT ( mode ) ; real_2expN ( & half_minus_pred_half , - ( fmt -> p ) - 1 , mode ) ; real_arithmetic ( & pred_half , MINUS_EXPR , & dconsthalf , & half_minus_pred_half ) ; half = force_reg ( mode , const_double_from_real_value ( pred_half , mode ) ) ; xa = expand_simple_binop ( mode , PLUS , xa , half , NULL_RTX , 0 , OPTAB_DIRECT ) ; xi = gen_reg_rtx ( int_mode_for_mode ( mode ) . require ( ) ) ; expand_fix ( xi , xa , 0 ) ; expand_float ( xa , xi , 0 ) ; ix86_sse_copysign_to_positive ( res , xa , res , mask ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand SSE sequence for computing round from OPERAND1 storing into OPERAND0 .


<s> void ix86_expand_rounddf_32 ( rtx operand0 , rtx operand1 ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , xa2 , dxa , TWO52 , tmp , half , mhalf , one , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = copy_to_reg ( operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xa2 = expand_simple_binop ( mode , PLUS , xa , TWO52 , NULL_RTX , 0 , OPTAB_DIRECT ) ; xa2 = expand_simple_binop ( mode , MINUS , xa2 , TWO52 , xa2 , 0 , OPTAB_DIRECT ) ; dxa = expand_simple_binop ( mode , MINUS , xa2 , xa , NULL_RTX , 0 , OPTAB_DIRECT ) ; half = force_reg ( mode , const_double_from_real_value ( dconsthalf , mode ) ) ; one = expand_simple_binop ( mode , PLUS , half , half , NULL_RTX , 0 , OPTAB_DIRECT ) ; mhalf = expand_simple_binop ( mode , MINUS , half , one , NULL_RTX , 0 , OPTAB_DIRECT ) ; tmp = ix86_expand_sse_compare_mask ( UNGT , dxa , half , false ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , tmp , one ) ) ) ; xa2 = expand_simple_binop ( mode , MINUS , xa2 , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; tmp = ix86_expand_sse_compare_mask ( UNGE , mhalf , dxa , false ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , tmp , one ) ) ) ; xa2 = expand_simple_binop ( mode , PLUS , xa2 , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; ix86_sse_copysign_to_positive ( res , xa2 , res , mask ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand SSE sequence for computing round from OPERAND1 storing into OPERAND0 . Sequence that works without relying on DImode truncation via cvttsd2siq that is only available on 64bit targets .


<s> void ix86_expand_round_sse4 ( rtx op0 , rtx op1 ) { machine_mode mode = GET_MODE ( op0 ) ; rtx e1 , e2 , res , half ; const struct real_format * fmt ; REAL_VALUE_TYPE pred_half , half_minus_pred_half ; rtx ( * gen_copysign ) ( rtx , rtx , rtx ) ; rtx ( * gen_round ) ( rtx , rtx , rtx ) ; switch ( mode ) { case E_SFmode : gen_copysign = gen_copysignsf3 ; gen_round = gen_sse4_1_roundsf2 ; break ; case E_DFmode : gen_copysign = gen_copysigndf3 ; gen_round = gen_sse4_1_rounddf2 ; break ; default : gcc_unreachable ( ) ; } fmt = REAL_MODE_FORMAT ( mode ) ; real_2expN ( & half_minus_pred_half , - ( fmt -> p ) - 1 , mode ) ; real_arithmetic ( & pred_half , MINUS_EXPR , & dconsthalf , & half_minus_pred_half ) ; half = const_double_from_real_value ( pred_half , mode ) ; e1 = gen_reg_rtx ( mode ) ; emit_insn ( gen_copysign ( e1 , half , op1 ) ) ; e2 = expand_simple_binop ( mode , PLUS , op1 , e1 , NULL_RTX , 0 , OPTAB_DIRECT ) ; res = gen_reg_rtx ( mode ) ; emit_insn ( gen_round ( res , e2 , GEN_INT ( ROUND_TRUNC ) ) ) ; emit_move_insn ( op0 , res ) ; } </s>

Expand SSE sequence for computing round from OP1 storing into OP0 using sse4 round insn .


<s> void ix86_expand_sse2_abs ( rtx target , rtx input ) { machine_mode mode = GET_MODE ( target ) ; rtx tmp0 , tmp1 , x ; switch ( mode ) { case E_V2DImode : case E_V4DImode : if ( TARGET_SSE4_2 ) { tmp0 = gen_reg_rtx ( mode ) ; tmp1 = gen_reg_rtx ( mode ) ; emit_move_insn ( tmp1 , CONST0_RTX ( mode ) ) ; if ( mode == E_V2DImode ) emit_insn ( gen_sse4_2_gtv2di3 ( tmp0 , tmp1 , input ) ) ; else emit_insn ( gen_avx2_gtv4di3 ( tmp0 , tmp1 , input ) ) ; } else { tmp0 = expand_simple_binop ( mode , LSHIFTRT , input , GEN_INT ( GET_MODE_UNIT_BITSIZE ( mode ) - 1 ) , NULL , 0 , OPTAB_DIRECT ) ; tmp0 = expand_simple_unop ( mode , NEG , tmp0 , NULL , false ) ; } tmp1 = expand_simple_binop ( mode , XOR , tmp0 , input , NULL , 0 , OPTAB_DIRECT ) ; x = expand_simple_binop ( mode , MINUS , tmp1 , tmp0 , target , 0 , OPTAB_DIRECT ) ; break ; case E_V4SImode : tmp0 = expand_simple_binop ( mode , ASHIFTRT , input , GEN_INT ( GET_MODE_UNIT_BITSIZE ( mode ) - 1 ) , NULL , 0 , OPTAB_DIRECT ) ; tmp1 = expand_simple_binop ( mode , XOR , tmp0 , input , NULL , 0 , OPTAB_DIRECT ) ; x = expand_simple_binop ( mode , MINUS , tmp1 , tmp0 , target , 0 , OPTAB_DIRECT ) ; break ; case E_V8HImode : tmp0 = expand_unop ( mode , neg_optab , input , NULL_RTX , 0 ) ; x = expand_simple_binop ( mode , SMAX , tmp0 , input , target , 0 , OPTAB_DIRECT ) ; break ; case E_V16QImode : tmp0 = expand_unop ( mode , neg_optab , input , NULL_RTX , 0 ) ; x = expand_simple_binop ( V16QImode , UMIN , tmp0 , input , target , 0 , OPTAB_DIRECT ) ; break ; default : gcc_unreachable ( ) ; } if ( x != target ) emit_move_insn ( target , x ) ; } </s>

Calculate integer abs ( ) using only SSE2 instructions .


<s> static rtx ix86_expand_sse_cmp ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 , rtx op_true , rtx op_false ) { machine_mode mode = GET_MODE ( dest ) ; machine_mode cmp_ops_mode = GET_MODE ( cmp_op0 ) ; machine_mode cmp_mode ; bool maskcmp = false ; rtx x ; if ( ix86_use_mask_cmp_p ( mode , cmp_ops_mode , op_true , op_false ) ) { unsigned int nbits = GET_MODE_NUNITS ( cmp_ops_mode ) ; maskcmp = true ; cmp_mode = nbits > 8 ? int_mode_for_size ( nbits , 0 ) . require ( ) : E_QImode ; } else cmp_mode = cmp_ops_mode ; cmp_op0 = force_reg ( cmp_ops_mode , cmp_op0 ) ; bool ( * op1_predicate ) ( rtx , machine_mode ) = VECTOR_MODE_P ( cmp_ops_mode ) ? vector_operand : nonimmediate_operand ; if ( ! op1_predicate ( cmp_op1 , cmp_ops_mode ) ) cmp_op1 = force_reg ( cmp_ops_mode , cmp_op1 ) ; if ( optimize || ( maskcmp && cmp_mode != mode ) || ( op_true && reg_overlap_mentioned_p ( dest , op_true ) ) || ( op_false && reg_overlap_mentioned_p ( dest , op_false ) ) ) dest = gen_reg_rtx ( maskcmp ? cmp_mode : mode ) ; if ( maskcmp ) { bool ok = ix86_expand_mask_vec_cmp ( dest , code , cmp_op0 , cmp_op1 ) ; gcc_assert ( ok ) ; return dest ; } x = gen_rtx_fmt_ee ( code , cmp_mode , cmp_op0 , cmp_op1 ) ; if ( cmp_mode != mode ) { x = force_reg ( cmp_ops_mode , x ) ; convert_move ( dest , x , false ) ; } else emit_insn ( gen_rtx_SET ( dest , x ) ) ; return dest ; } </s>

Expand an sse vector comparison . Return the register with the result .


<s> static rtx ix86_expand_sse_comi ( const struct builtin_description * d , tree exp , rtx target ) { rtx pat ; tree arg0 = CALL_EXPR_ARG ( exp , 0 ) ; tree arg1 = CALL_EXPR_ARG ( exp , 1 ) ; rtx op0 = expand_normal ( arg0 ) ; rtx op1 = expand_normal ( arg1 ) ; machine_mode mode0 = insn_data [ d -> icode ] . operand [ 0 ] . mode ; machine_mode mode1 = insn_data [ d -> icode ] . operand [ 1 ] . mode ; enum rtx_code comparison = d -> comparison ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( VECTOR_MODE_P ( mode1 ) ) op1 = safe_vector_operand ( op1 , mode1 ) ; target = gen_reg_rtx ( SImode ) ; emit_move_insn ( target , const0_rtx ) ; target = gen_rtx_SUBREG ( QImode , target , 0 ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! insn_data [ d -> icode ] . operand [ 0 ] . predicate ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; if ( ( optimize && ! register_operand ( op1 , mode1 ) ) || ! insn_data [ d -> icode ] . operand [ 1 ] . predicate ( op1 , mode1 ) ) op1 = copy_to_mode_reg ( mode1 , op1 ) ; pat = GEN_FCN ( d -> icode ) ( op0 , op1 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; emit_insn ( gen_rtx_SET ( gen_rtx_STRICT_LOW_PART ( VOIDmode , target ) , gen_rtx_fmt_ee ( comparison , QImode , SET_DEST ( pat ) , const0_rtx ) ) ) ; return SUBREG_REG ( target ) ; } </s>

Subroutine of ix86_expand_builtin to take care of comi insns .


<s> static rtx ix86_expand_sse_compare ( const struct builtin_description * d , tree exp , rtx target , bool swap ) { rtx pat ; tree arg0 = CALL_EXPR_ARG ( exp , 0 ) ; tree arg1 = CALL_EXPR_ARG ( exp , 1 ) ; rtx op0 = expand_normal ( arg0 ) ; rtx op1 = expand_normal ( arg1 ) ; rtx op2 ; machine_mode tmode = insn_data [ d -> icode ] . operand [ 0 ] . mode ; machine_mode mode0 = insn_data [ d -> icode ] . operand [ 1 ] . mode ; machine_mode mode1 = insn_data [ d -> icode ] . operand [ 2 ] . mode ; enum rtx_code comparison = d -> comparison ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( VECTOR_MODE_P ( mode1 ) ) op1 = safe_vector_operand ( op1 , mode1 ) ; if ( swap ) std :: swap ( op0 , op1 ) ; if ( optimize || ! target || GET_MODE ( target ) != tmode || ! insn_data [ d -> icode ] . operand [ 0 ] . predicate ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! insn_data [ d -> icode ] . operand [ 1 ] . predicate ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; if ( ( optimize && ! register_operand ( op1 , mode1 ) ) || ! insn_data [ d -> icode ] . operand [ 2 ] . predicate ( op1 , mode1 ) ) op1 = copy_to_mode_reg ( mode1 , op1 ) ; op2 = gen_rtx_fmt_ee ( comparison , mode0 , op0 , op1 ) ; pat = GEN_FCN ( d -> icode ) ( target , op0 , op1 , op2 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of ix86_expand_builtin to take care of comparison insns .


<s> static rtx_code_label * ix86_expand_sse_compare_and_jump ( enum rtx_code code , rtx op0 , rtx op1 , bool swap_operands ) { bool unordered_compare = ix86_unordered_fp_compare ( code ) ; rtx_code_label * label ; rtx tmp , reg ; if ( swap_operands ) std :: swap ( op0 , op1 ) ; label = gen_label_rtx ( ) ; tmp = gen_rtx_COMPARE ( CCFPmode , op0 , op1 ) ; if ( unordered_compare ) tmp = gen_rtx_UNSPEC ( CCFPmode , gen_rtvec ( 1 , tmp ) , UNSPEC_NOTRAP ) ; reg = gen_rtx_REG ( CCFPmode , FLAGS_REG ) ; emit_insn ( gen_rtx_SET ( reg , tmp ) ) ; tmp = gen_rtx_fmt_ee ( code , VOIDmode , reg , const0_rtx ) ; tmp = gen_rtx_IF_THEN_ELSE ( VOIDmode , tmp , gen_rtx_LABEL_REF ( VOIDmode , label ) , pc_rtx ) ; tmp = emit_jump_insn ( gen_rtx_SET ( pc_rtx , tmp ) ) ; JUMP_LABEL ( tmp ) = label ; return label ; } </s>

Expands a comparison of OP0 with OP1 using comparison code CODE , swapping the operands if SWAP_OPERANDS is true . The expanded code is a forward jump to a newly created label in case the comparison is true . The generated label rtx is returned .


<s> static rtx ix86_expand_sse_compare_mask ( enum rtx_code code , rtx op0 , rtx op1 , bool swap_operands ) { rtx ( * insn ) ( rtx , rtx , rtx , rtx ) ; machine_mode mode = GET_MODE ( op0 ) ; rtx mask = gen_reg_rtx ( mode ) ; if ( swap_operands ) std :: swap ( op0 , op1 ) ; insn = mode == DFmode ? gen_setcc_df_sse : gen_setcc_sf_sse ; emit_insn ( insn ( mask , op0 , op1 , gen_rtx_fmt_ee ( code , mode , op0 , op1 ) ) ) ; return mask ; } </s>

Expand a mask generating SSE comparison instruction comparing OP0 with OP1 using comparison code CODE . Operands are swapped for the comparison if SWAP_OPERANDS is true . Returns a rtx for the generated mask .


<s> static rtx ix86_expand_sse_fabs ( rtx op0 , rtx * smask ) { machine_mode vmode , mode = GET_MODE ( op0 ) ; rtx xa , mask ; xa = gen_reg_rtx ( mode ) ; if ( mode == SFmode ) vmode = V4SFmode ; else if ( mode == DFmode ) vmode = V2DFmode ; else vmode = mode ; mask = ix86_build_signbit_mask ( vmode , VECTOR_MODE_P ( mode ) , true ) ; if ( ! VECTOR_MODE_P ( mode ) ) { rtx tmp = gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 1 , const0_rtx ) ) ; tmp = gen_rtx_VEC_SELECT ( mode , mask , tmp ) ; mask = gen_reg_rtx ( mode ) ; emit_insn ( gen_rtx_SET ( mask , tmp ) ) ; } emit_insn ( gen_rtx_SET ( xa , gen_rtx_AND ( mode , op0 , mask ) ) ) ; if ( smask ) * smask = mask ; return xa ; } </s>

Expand fabs ( OP0 ) and return a new rtx that holds the result . The mask for masking out the sign-bit is stored in * SMASK , if that is non-null .


<s> static bool ix86_expand_sse_fp_minmax ( rtx dest , enum rtx_code code , rtx cmp_op0 , rtx cmp_op1 , rtx if_true , rtx if_false ) { machine_mode mode ; bool is_min ; rtx tmp ; if ( code == LT ) ; else if ( code == UNGE ) std :: swap ( if_true , if_false ) ; else return false ; if ( rtx_equal_p ( cmp_op0 , if_true ) && rtx_equal_p ( cmp_op1 , if_false ) ) is_min = true ; else if ( rtx_equal_p ( cmp_op1 , if_true ) && rtx_equal_p ( cmp_op0 , if_false ) ) is_min = false ; else return false ; mode = GET_MODE ( dest ) ; if ( ! flag_finite_math_only || flag_signed_zeros ) { int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX ; rtvec v ; if_true = force_reg ( mode , if_true ) ; v = gen_rtvec ( 2 , if_true , if_false ) ; tmp = gen_rtx_UNSPEC ( mode , v , u ) ; } else { code = is_min ? SMIN : SMAX ; if ( MEM_P ( if_true ) && MEM_P ( if_false ) ) if_true = force_reg ( mode , if_true ) ; tmp = gen_rtx_fmt_ee ( code , mode , if_true , if_false ) ; } emit_insn ( gen_rtx_SET ( dest , tmp ) ) ; return true ; } </s>

Detect conditional moves that exactly match min/max operational semantics . Note that this is IEEE safe , as long as we do n't interchange the operands . Returns FALSE if this conditional move does n't match a MIN/MAX , and TRUE if the operation is successful and instructions are emitted .


<s> static rtx ix86_expand_sse_ptest ( const struct builtin_description * d , tree exp , rtx target ) { rtx pat ; tree arg0 = CALL_EXPR_ARG ( exp , 0 ) ; tree arg1 = CALL_EXPR_ARG ( exp , 1 ) ; rtx op0 = expand_normal ( arg0 ) ; rtx op1 = expand_normal ( arg1 ) ; machine_mode mode0 = insn_data [ d -> icode ] . operand [ 0 ] . mode ; machine_mode mode1 = insn_data [ d -> icode ] . operand [ 1 ] . mode ; enum rtx_code comparison = d -> comparison ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( VECTOR_MODE_P ( mode1 ) ) op1 = safe_vector_operand ( op1 , mode1 ) ; target = gen_reg_rtx ( SImode ) ; emit_move_insn ( target , const0_rtx ) ; target = gen_rtx_SUBREG ( QImode , target , 0 ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! insn_data [ d -> icode ] . operand [ 0 ] . predicate ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; if ( ( optimize && ! register_operand ( op1 , mode1 ) ) || ! insn_data [ d -> icode ] . operand [ 1 ] . predicate ( op1 , mode1 ) ) op1 = copy_to_mode_reg ( mode1 , op1 ) ; pat = GEN_FCN ( d -> icode ) ( op0 , op1 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; emit_insn ( gen_rtx_SET ( gen_rtx_STRICT_LOW_PART ( VOIDmode , target ) , gen_rtx_fmt_ee ( comparison , QImode , SET_DEST ( pat ) , const0_rtx ) ) ) ; return SUBREG_REG ( target ) ; } </s>

Subroutine of ix86_expand_builtin to take care of ptest insns .


<s> static rtx ix86_expand_sse_round ( const struct builtin_description * d , tree exp , rtx target ) { rtx pat ; tree arg0 = CALL_EXPR_ARG ( exp , 0 ) ; rtx op1 , op0 = expand_normal ( arg0 ) ; machine_mode tmode = insn_data [ d -> icode ] . operand [ 0 ] . mode ; machine_mode mode0 = insn_data [ d -> icode ] . operand [ 1 ] . mode ; if ( optimize || target == 0 || GET_MODE ( target ) != tmode || ! insn_data [ d -> icode ] . operand [ 0 ] . predicate ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! insn_data [ d -> icode ] . operand [ 0 ] . predicate ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; op1 = GEN_INT ( d -> comparison ) ; pat = GEN_FCN ( d -> icode ) ( target , op0 , op1 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; return target ; } </s>

Subroutines of ix86_expand_args_builtin to take care of round insns .


<s> bool ix86_expand_strlen ( rtx out , rtx src , rtx eoschar , rtx align ) { if ( TARGET_UNROLL_STRLEN && TARGET_INLINE_ALL_STRINGOPS && eoschar == const0_rtx && optimize > 1 ) { rtx addr = force_reg ( Pmode , XEXP ( src , 0 ) ) ; emit_move_insn ( out , addr ) ; ix86_expand_strlensi_unroll_1 ( out , src , align ) ; emit_insn ( gen_sub2_insn ( out , addr ) ) ; return true ; } else return false ; } </s>


<s> static rtx ix86_expand_ti_to_v1ti ( rtx x ) { if ( TARGET_SSE2 ) { rtx lo = gen_lowpart ( DImode , x ) ; rtx hi = gen_highpart ( DImode , x ) ; rtx tmp = gen_reg_rtx ( V2DImode ) ; emit_insn ( gen_vec_concatv2di ( tmp , lo , hi ) ) ; return force_reg ( V1TImode , gen_lowpart ( V1TImode , tmp ) ) ; } return force_reg ( V1TImode , gen_lowpart ( V1TImode , x ) ) ; } </s>

Expand move of TI mode register X to a new V1TI mode register .


<s> void ix86_expand_trunc ( rtx operand0 , rtx operand1 ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , xi , TWO52 , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = copy_to_reg ( operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xi = gen_reg_rtx ( int_mode_for_mode ( mode ) . require ( ) ) ; expand_fix ( xi , res , 0 ) ; expand_float ( xa , xi , 0 ) ; if ( HONOR_SIGNED_ZEROS ( mode ) ) ix86_sse_copysign_to_positive ( xa , xa , res , mask ) ; emit_move_insn ( res , xa ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>

Expand SSE sequence for computing trunc from OPERAND1 storing into OPERAND0 .


<s> void ix86_expand_truncdf_32 ( rtx operand0 , rtx operand1 ) { machine_mode mode = GET_MODE ( operand0 ) ; rtx xa , xa2 , TWO52 , tmp , one , res , mask ; rtx_code_label * label ; TWO52 = ix86_gen_TWO52 ( mode ) ; res = copy_to_reg ( operand1 ) ; xa = ix86_expand_sse_fabs ( res , & mask ) ; label = ix86_expand_sse_compare_and_jump ( UNLE , TWO52 , xa , false ) ; xa2 = expand_simple_binop ( mode , PLUS , xa , TWO52 , NULL_RTX , 0 , OPTAB_DIRECT ) ; xa2 = expand_simple_binop ( mode , MINUS , xa2 , TWO52 , xa2 , 0 , OPTAB_DIRECT ) ; one = force_reg ( mode , const_double_from_real_value ( dconst1 , mode ) ) ; tmp = ix86_expand_sse_compare_mask ( UNGT , xa2 , xa , false ) ; emit_insn ( gen_rtx_SET ( tmp , gen_rtx_AND ( mode , one , tmp ) ) ) ; tmp = expand_simple_binop ( mode , MINUS , xa2 , tmp , NULL_RTX , 0 , OPTAB_DIRECT ) ; if ( HONOR_SIGNED_ZEROS ( mode ) && flag_rounding_math ) tmp = ix86_expand_sse_fabs ( tmp , NULL ) ; ix86_sse_copysign_to_positive ( res , tmp , res , mask ) ; emit_label ( label ) ; LABEL_NUSES ( label ) = 1 ; emit_move_insn ( operand0 , res ) ; } </s>


<s> void ix86_expand_unary_operator ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { bool matching_memory = false ; rtx src , dst , op , clob ; dst = operands [ 0 ] ; src = operands [ 1 ] ; if ( MEM_P ( dst ) ) { if ( rtx_equal_p ( dst , src ) ) matching_memory = true ; else dst = gen_reg_rtx ( mode ) ; } if ( MEM_P ( src ) && ! matching_memory ) src = force_reg ( mode , src ) ; op = gen_rtx_SET ( dst , gen_rtx_fmt_e ( code , mode , src ) ) ; if ( code == NOT ) emit_insn ( op ) ; else { clob = gen_rtx_CLOBBER ( VOIDmode , gen_rtx_REG ( CCmode , FLAGS_REG ) ) ; emit_insn ( gen_rtx_PARALLEL ( VOIDmode , gen_rtvec ( 2 , op , clob ) ) ) ; } if ( dst != operands [ 0 ] ) emit_move_insn ( operands [ 0 ] , dst ) ; } </s>

Attempt to expand a unary operator . Make the expansion closer to the actual machine , then just general_operand , which will allow 2 separate memory references ( one output , one input ) in a single insn .


<s> static rtx ix86_expand_unop_vec_merge_builtin ( enum insn_code icode , tree exp , rtx target ) { rtx pat ; tree arg0 = CALL_EXPR_ARG ( exp , 0 ) ; rtx op1 , op0 = expand_normal ( arg0 ) ; machine_mode tmode = insn_data [ icode ] . operand [ 0 ] . mode ; machine_mode mode0 = insn_data [ icode ] . operand [ 1 ] . mode ; if ( optimize || ! target || GET_MODE ( target ) != tmode || ! insn_data [ icode ] . operand [ 0 ] . predicate ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; if ( VECTOR_MODE_P ( mode0 ) ) op0 = safe_vector_operand ( op0 , mode0 ) ; if ( ( optimize && ! register_operand ( op0 , mode0 ) ) || ! insn_data [ icode ] . operand [ 1 ] . predicate ( op0 , mode0 ) ) op0 = copy_to_mode_reg ( mode0 , op0 ) ; op1 = op0 ; if ( ! insn_data [ icode ] . operand [ 2 ] . predicate ( op1 , mode0 ) ) op1 = copy_to_mode_reg ( mode0 , op1 ) ; pat = GEN_FCN ( icode ) ( target , op0 , op1 ) ; if ( ! pat ) return 0 ; emit_insn ( pat ) ; return target ; } </s>

Subroutine of ix86_expand_args_builtin to take care of scalar unop insns with vec_merge .


<s> void ix86_expand_v1ti_shift ( enum rtx_code code , rtx operands [ ] ) { rtx op1 = force_reg ( V1TImode , operands [ 1 ] ) ; if ( ! CONST_INT_P ( operands [ 2 ] ) ) { rtx tmp1 = ix86_expand_v1ti_to_ti ( op1 ) ; rtx tmp2 = gen_reg_rtx ( TImode ) ; rtx ( * shift ) ( rtx , rtx , rtx ) = ( code == ASHIFT ) ? gen_ashlti3 : gen_lshrti3 ; emit_insn ( shift ( tmp2 , tmp1 , operands [ 2 ] ) ) ; rtx tmp3 = ix86_expand_ti_to_v1ti ( tmp2 ) ; emit_move_insn ( operands [ 0 ] , tmp3 ) ; return ; } HOST_WIDE_INT bits = INTVAL ( operands [ 2 ] ) & 127 ; if ( bits == 0 ) { emit_move_insn ( operands [ 0 ] , op1 ) ; return ; } if ( ( bits & 7 ) == 0 ) { rtx tmp = gen_reg_rtx ( V1TImode ) ; if ( code == ASHIFT ) emit_insn ( gen_sse2_ashlv1ti3 ( tmp , op1 , GEN_INT ( bits ) ) ) ; else emit_insn ( gen_sse2_lshrv1ti3 ( tmp , op1 , GEN_INT ( bits ) ) ) ; emit_move_insn ( operands [ 0 ] , tmp ) ; return ; } rtx tmp1 = gen_reg_rtx ( V1TImode ) ; if ( code == ASHIFT ) emit_insn ( gen_sse2_ashlv1ti3 ( tmp1 , op1 , GEN_INT ( 64 ) ) ) ; else emit_insn ( gen_sse2_lshrv1ti3 ( tmp1 , op1 , GEN_INT ( 64 ) ) ) ; rtx tmp2 = force_reg ( V2DImode , gen_lowpart ( V2DImode , tmp1 ) ) ; rtx tmp3 = gen_reg_rtx ( V2DImode ) ; if ( bits > 64 ) { if ( code == ASHIFT ) emit_insn ( gen_ashlv2di3 ( tmp3 , tmp2 , GEN_INT ( bits - 64 ) ) ) ; else emit_insn ( gen_lshrv2di3 ( tmp3 , tmp2 , GEN_INT ( bits - 64 ) ) ) ; } else { rtx tmp4 = force_reg ( V2DImode , gen_lowpart ( V2DImode , op1 ) ) ; rtx tmp5 = gen_reg_rtx ( V2DImode ) ; if ( code == ASHIFT ) emit_insn ( gen_ashlv2di3 ( tmp5 , tmp4 , GEN_INT ( bits ) ) ) ; else emit_insn ( gen_lshrv2di3 ( tmp5 , tmp4 , GEN_INT ( bits ) ) ) ; rtx tmp6 = gen_reg_rtx ( V2DImode ) ; if ( code == ASHIFT ) emit_insn ( gen_lshrv2di3 ( tmp6 , tmp2 , GEN_INT ( 64 - bits ) ) ) ; else emit_insn ( gen_ashlv2di3 ( tmp6 , tmp2 , GEN_INT ( 64 - bits ) ) ) ; emit_insn ( gen_iorv2di3 ( tmp3 , tmp5 , tmp6 ) ) ; } rtx tmp7 = force_reg ( V1TImode , gen_lowpart ( V1TImode , tmp3 ) ) ; emit_move_insn ( operands [ 0 ] , tmp7 ) ; } </s>

Expand V1TI mode shift ( of rtx_code CODE ) by constant .


<s> static rtx ix86_expand_v1ti_to_ti ( rtx x ) { rtx result = gen_reg_rtx ( TImode ) ; if ( TARGET_SSE2 ) { rtx temp = force_reg ( V2DImode , gen_lowpart ( V2DImode , x ) ) ; rtx lo = gen_lowpart ( DImode , result ) ; emit_insn ( gen_vec_extractv2didi ( lo , temp , const0_rtx ) ) ; rtx hi = gen_highpart ( DImode , result ) ; emit_insn ( gen_vec_extractv2didi ( hi , temp , const1_rtx ) ) ; } else emit_move_insn ( result , gen_lowpart ( TImode , x ) ) ; return result ; } </s>

Expand move of V1TI mode register X to a new TI mode register .


<s> static bool ix86_expand_vecop_qihi2 ( enum rtx_code code , rtx dest , rtx op1 , rtx op2 ) { machine_mode himode , qimode = GET_MODE ( dest ) ; rtx hop1 , hop2 , hdest ; rtx ( * gen_extend ) ( rtx , rtx ) ; rtx ( * gen_truncate ) ( rtx , rtx ) ; bool uns_p = ( code == ASHIFTRT ) ? false : true ; if ( qimode == E_V64QImode ) return false ; if ( ! TARGET_AVX512BW ) return false ; if ( ( qimode == V8QImode || qimode == V16QImode ) && ! TARGET_AVX512VL ) return false ; if ( qimode == V32QImode && ( TARGET_PREFER_AVX128 || TARGET_PREFER_AVX256 ) ) return false ; switch ( qimode ) { case E_V8QImode : himode = V8HImode ; gen_extend = uns_p ? gen_zero_extendv8qiv8hi2 : gen_extendv8qiv8hi2 ; gen_truncate = gen_truncv8hiv8qi2 ; break ; case E_V16QImode : himode = V16HImode ; gen_extend = uns_p ? gen_zero_extendv16qiv16hi2 : gen_extendv16qiv16hi2 ; gen_truncate = gen_truncv16hiv16qi2 ; break ; case E_V32QImode : himode = V32HImode ; gen_extend = uns_p ? gen_zero_extendv32qiv32hi2 : gen_extendv32qiv32hi2 ; gen_truncate = gen_truncv32hiv32qi2 ; break ; default : gcc_unreachable ( ) ; } hop1 = gen_reg_rtx ( himode ) ; hop2 = gen_reg_rtx ( himode ) ; hdest = gen_reg_rtx ( himode ) ; emit_insn ( gen_extend ( hop1 , op1 ) ) ; emit_insn ( gen_extend ( hop2 , op2 ) ) ; emit_insn ( gen_rtx_SET ( hdest , simplify_gen_binary ( code , himode , hop1 , hop2 ) ) ) ; emit_insn ( gen_truncate ( dest , hdest ) ) ; return true ; } </s>

This function is similar as ix86_expand_vecop_qihi , but optimized under AVX512BW by using vpmovwb . For example , optimize vector MUL generation like vpmovzxbw ymm2 , xmm0 vpmovzxbw ymm3 , xmm1 vpmullw ymm4 , ymm2 , ymm3 vpmovwb xmm0 , ymm4 it would take less instructions than ix86_expand_vecop_qihi . Return true if success .


<s> void ix86_expand_vector_convert_uns_vsivsf ( rtx target , rtx val ) { rtx tmp [ 8 ] ; REAL_VALUE_TYPE TWO16r ; machine_mode intmode = GET_MODE ( val ) ; machine_mode fltmode = GET_MODE ( target ) ; rtx ( * cvt ) ( rtx , rtx ) ; if ( intmode == V4SImode ) cvt = gen_floatv4siv4sf2 ; else cvt = gen_floatv8siv8sf2 ; tmp [ 0 ] = ix86_build_const_vector ( intmode , 1 , GEN_INT ( 0xffff ) ) ; tmp [ 0 ] = force_reg ( intmode , tmp [ 0 ] ) ; tmp [ 1 ] = expand_simple_binop ( intmode , AND , val , tmp [ 0 ] , NULL_RTX , 1 , OPTAB_DIRECT ) ; tmp [ 2 ] = expand_simple_binop ( intmode , LSHIFTRT , val , GEN_INT ( 16 ) , NULL_RTX , 1 , OPTAB_DIRECT ) ; tmp [ 3 ] = gen_reg_rtx ( fltmode ) ; emit_insn ( cvt ( tmp [ 3 ] , tmp [ 1 ] ) ) ; tmp [ 4 ] = gen_reg_rtx ( fltmode ) ; emit_insn ( cvt ( tmp [ 4 ] , tmp [ 2 ] ) ) ; real_ldexp ( & TWO16r , & dconst1 , 16 ) ; tmp [ 5 ] = const_double_from_real_value ( TWO16r , SFmode ) ; tmp [ 5 ] = force_reg ( fltmode , ix86_build_const_vector ( fltmode , 1 , tmp [ 5 ] ) ) ; if ( TARGET_FMA ) { tmp [ 6 ] = gen_rtx_FMA ( fltmode , tmp [ 4 ] , tmp [ 5 ] , tmp [ 3 ] ) ; emit_move_insn ( target , tmp [ 6 ] ) ; } else { tmp [ 6 ] = expand_simple_binop ( fltmode , MULT , tmp [ 4 ] , tmp [ 5 ] , NULL_RTX , 1 , OPTAB_DIRECT ) ; tmp [ 7 ] = expand_simple_binop ( fltmode , PLUS , tmp [ 3 ] , tmp [ 6 ] , target , 1 , OPTAB_DIRECT ) ; if ( tmp [ 7 ] != target ) emit_move_insn ( target , tmp [ 7 ] ) ; } } </s>

floatunsv { 4,8 } siv { 4,8 } sf2 expander . Expand code to convert a vector of unsigned ints VAL to vector of floats TARGET .


<s> void ix86_expand_vector_init ( bool mmx_ok , rtx target , rtx vals ) { machine_mode mode = GET_MODE ( target ) ; machine_mode inner_mode = GET_MODE_INNER ( mode ) ; int n_elts = GET_MODE_NUNITS ( mode ) ; int n_var = 0 , one_var = - 1 ; bool all_same = true , all_const_zero = true ; int i ; rtx x ; if ( n_elts != XVECLEN ( vals , 0 ) ) { rtx subtarget = target ; x = XVECEXP ( vals , 0 , 0 ) ; gcc_assert ( GET_MODE_INNER ( GET_MODE ( x ) ) == inner_mode ) ; if ( GET_MODE_NUNITS ( GET_MODE ( x ) ) * 2 == n_elts ) { rtx ops [ 2 ] = { XVECEXP ( vals , 0 , 0 ) , XVECEXP ( vals , 0 , 1 ) } ; if ( inner_mode == QImode || inner_mode == HImode || inner_mode == TImode || inner_mode == HFmode ) { unsigned int n_bits = n_elts * GET_MODE_SIZE ( inner_mode ) ; scalar_mode elt_mode = inner_mode == TImode ? DImode : SImode ; n_bits /= GET_MODE_SIZE ( elt_mode ) ; mode = mode_for_vector ( elt_mode , n_bits ) . require ( ) ; inner_mode = mode_for_vector ( elt_mode , n_bits / 2 ) . require ( ) ; ops [ 0 ] = gen_lowpart ( inner_mode , ops [ 0 ] ) ; ops [ 1 ] = gen_lowpart ( inner_mode , ops [ 1 ] ) ; subtarget = gen_reg_rtx ( mode ) ; } ix86_expand_vector_init_concat ( mode , subtarget , ops , 2 ) ; if ( subtarget != target ) emit_move_insn ( target , gen_lowpart ( GET_MODE ( target ) , subtarget ) ) ; return ; } gcc_unreachable ( ) ; } for ( i = 0 ; i < n_elts ; ++ i ) { x = XVECEXP ( vals , 0 , i ) ; if ( ! ( CONST_SCALAR_INT_P ( x ) || CONST_DOUBLE_P ( x ) || CONST_FIXED_P ( x ) ) ) n_var ++ , one_var = i ; else if ( x != CONST0_RTX ( inner_mode ) ) all_const_zero = false ; if ( i > 0 && ! rtx_equal_p ( x , XVECEXP ( vals , 0 , 0 ) ) ) all_same = false ; } if ( n_var == 0 ) { emit_move_insn ( target , gen_rtx_CONST_VECTOR ( mode , XVEC ( vals , 0 ) ) ) ; return ; } if ( all_same && ix86_expand_vector_init_duplicate ( mmx_ok , mode , target , XVECEXP ( vals , 0 , 0 ) ) ) return ; if ( n_var == 1 ) { if ( all_const_zero && ix86_expand_vector_init_one_nonzero ( mmx_ok , mode , target , XVECEXP ( vals , 0 , one_var ) , one_var ) ) return ; if ( ix86_expand_vector_init_one_var ( mmx_ok , mode , target , vals , one_var ) ) return ; } ix86_expand_vector_init_general ( mmx_ok , mode , target , vals ) ; } </s>

Initialize vector TARGET via VALS . Suppress the use of MMX instructions unless MMX_OK is true .


<s> static bool ix86_expand_vector_init_one_var ( bool mmx_ok , machine_mode mode , rtx target , rtx vals , int one_var ) { rtx var = XVECEXP ( vals , 0 , one_var ) ; machine_mode wmode ; rtx const_vec , x ; const_vec = copy_rtx ( vals ) ; XVECEXP ( const_vec , 0 , one_var ) = CONST0_RTX ( GET_MODE_INNER ( mode ) ) ; const_vec = gen_rtx_CONST_VECTOR ( mode , XVEC ( const_vec , 0 ) ) ; switch ( mode ) { case E_V2DFmode : case E_V2DImode : case E_V2SFmode : case E_V2SImode : return false ; case E_V4DImode : if ( ! TARGET_64BIT ) return false ; case E_V8HFmode : case E_V16HFmode : case E_V4DFmode : case E_V8SFmode : case E_V8SImode : case E_V16HImode : case E_V32QImode : case E_V4SFmode : case E_V4SImode : case E_V8HImode : case E_V4HImode : break ; case E_V16QImode : if ( TARGET_SSE4_1 ) break ; wmode = V8HImode ; goto widen ; case E_V8QImode : if ( TARGET_MMX_WITH_SSE && TARGET_SSE4_1 ) break ; wmode = V4HImode ; goto widen ; case E_V4QImode : if ( TARGET_SSE4_1 ) break ; wmode = V2HImode ; widen : x = XVECEXP ( vals , 0 , one_var ^ 1 ) ; if ( one_var & 1 ) { var = convert_modes ( HImode , QImode , var , true ) ; var = expand_simple_binop ( HImode , ASHIFT , var , GEN_INT ( 8 ) , NULL_RTX , 1 , OPTAB_LIB_WIDEN ) ; x = GEN_INT ( INTVAL ( x ) & 0xff ) ; } else { var = convert_modes ( HImode , QImode , var , true ) ; x = gen_int_mode ( UINTVAL ( x ) << 8 , HImode ) ; } if ( x != const0_rtx ) var = expand_simple_binop ( HImode , IOR , var , x , var , 1 , OPTAB_LIB_WIDEN ) ; x = gen_reg_rtx ( wmode ) ; emit_move_insn ( x , gen_lowpart ( wmode , const_vec ) ) ; ix86_expand_vector_set ( mmx_ok , x , var , one_var >> 1 ) ; emit_move_insn ( target , gen_lowpart ( mode , x ) ) ; return true ; default : return false ; } emit_move_insn ( target , const_vec ) ; ix86_expand_vector_set ( mmx_ok , target , var , one_var ) ; return true ; } </s>

A subroutine of ix86_expand_vector_init . Store into TARGET a vector consisting of the values in VALS . It is known that all elements except ONE_VAR are constants . Return true if successful .


<s> void ix86_expand_vector_logical_operator ( enum rtx_code code , machine_mode mode , rtx operands [ ] ) { rtx op1 = NULL_RTX , op2 = NULL_RTX ; if ( SUBREG_P ( operands [ 1 ] ) ) { op1 = operands [ 1 ] ; op2 = operands [ 2 ] ; } else if ( SUBREG_P ( operands [ 2 ] ) ) { op1 = operands [ 2 ] ; op2 = operands [ 1 ] ; } if ( op1 && ! TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL && ( SUBREG_P ( op2 ) || GET_CODE ( op2 ) == CONST_VECTOR ) && GET_MODE_CLASS ( GET_MODE ( SUBREG_REG ( op1 ) ) ) == MODE_VECTOR_FLOAT && GET_MODE_SIZE ( GET_MODE ( SUBREG_REG ( op1 ) ) ) == GET_MODE_SIZE ( mode ) && SUBREG_BYTE ( op1 ) == 0 && ( GET_CODE ( op2 ) == CONST_VECTOR || ( GET_MODE ( SUBREG_REG ( op1 ) ) == GET_MODE ( SUBREG_REG ( op2 ) ) && SUBREG_BYTE ( op2 ) == 0 ) ) && can_create_pseudo_p ( ) ) { rtx dst ; switch ( GET_MODE ( SUBREG_REG ( op1 ) ) ) { case E_V4SFmode : case E_V8SFmode : case E_V16SFmode : case E_V2DFmode : case E_V4DFmode : case E_V8DFmode : dst = gen_reg_rtx ( GET_MODE ( SUBREG_REG ( op1 ) ) ) ; if ( GET_CODE ( op2 ) == CONST_VECTOR ) { op2 = gen_lowpart ( GET_MODE ( dst ) , op2 ) ; op2 = force_reg ( GET_MODE ( dst ) , op2 ) ; } else { op1 = operands [ 1 ] ; op2 = SUBREG_REG ( operands [ 2 ] ) ; if ( ! vector_operand ( op2 , GET_MODE ( dst ) ) ) op2 = force_reg ( GET_MODE ( dst ) , op2 ) ; } op1 = SUBREG_REG ( op1 ) ; if ( ! vector_operand ( op1 , GET_MODE ( dst ) ) ) op1 = force_reg ( GET_MODE ( dst ) , op1 ) ; emit_insn ( gen_rtx_SET ( dst , gen_rtx_fmt_ee ( code , GET_MODE ( dst ) , op1 , op2 ) ) ) ; emit_move_insn ( operands [ 0 ] , gen_lowpart ( mode , dst ) ) ; return ; default : break ; } } if ( ! vector_operand ( operands [ 1 ] , mode ) ) operands [ 1 ] = force_reg ( mode , operands [ 1 ] ) ; if ( ! vector_operand ( operands [ 2 ] , mode ) ) operands [ 2 ] = force_reg ( mode , operands [ 2 ] ) ; ix86_fixup_binary_operands_no_copy ( code , mode , operands ) ; emit_insn ( gen_rtx_SET ( operands [ 0 ] , gen_rtx_fmt_ee ( code , mode , operands [ 1 ] , operands [ 2 ] ) ) ) ; } </s>

Expand vector logical operation CODE ( AND , IOR , XOR ) in MODE with the given OPERANDS .


<s> void ix86_expand_vector_move_misalign ( machine_mode mode , rtx operands [ ] ) { rtx op0 , op1 , m ; op0 = operands [ 0 ] ; op1 = operands [ 1 ] ; if ( GET_MODE_SIZE ( mode ) == 64 || optimize_insn_for_size_p ( ) ) { emit_insn ( gen_rtx_SET ( op0 , op1 ) ) ; return ; } if ( TARGET_AVX ) { if ( GET_MODE_SIZE ( mode ) == 32 ) ix86_avx256_split_vector_move_misalign ( op0 , op1 ) ; else emit_insn ( gen_rtx_SET ( op0 , op1 ) ) ; return ; } if ( TARGET_SSE_UNALIGNED_LOAD_OPTIMAL || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL ) { emit_insn ( gen_rtx_SET ( op0 , op1 ) ) ; return ; } if ( TARGET_SSE2 && GET_MODE_CLASS ( mode ) == MODE_VECTOR_INT ) { emit_insn ( gen_rtx_SET ( op0 , op1 ) ) ; return ; } if ( MEM_P ( op1 ) ) { if ( TARGET_SSE2 && mode == V2DFmode ) { rtx zero ; if ( TARGET_SSE_SPLIT_REGS ) { emit_clobber ( op0 ) ; zero = op0 ; } else { zero = CONST0_RTX ( V2DFmode ) ; } m = adjust_address ( op1 , DFmode , 0 ) ; emit_insn ( gen_sse2_loadlpd ( op0 , zero , m ) ) ; m = adjust_address ( op1 , DFmode , 8 ) ; emit_insn ( gen_sse2_loadhpd ( op0 , op0 , m ) ) ; } else { rtx t ; if ( mode != V4SFmode ) t = gen_reg_rtx ( V4SFmode ) ; else t = op0 ; if ( TARGET_SSE_PARTIAL_REG_DEPENDENCY ) emit_move_insn ( t , CONST0_RTX ( V4SFmode ) ) ; else emit_clobber ( t ) ; m = adjust_address ( op1 , V2SFmode , 0 ) ; emit_insn ( gen_sse_loadlps ( t , t , m ) ) ; m = adjust_address ( op1 , V2SFmode , 8 ) ; emit_insn ( gen_sse_loadhps ( t , t , m ) ) ; if ( mode != V4SFmode ) emit_move_insn ( op0 , gen_lowpart ( mode , t ) ) ; } } else if ( MEM_P ( op0 ) ) { if ( TARGET_SSE2 && mode == V2DFmode ) { m = adjust_address ( op0 , DFmode , 0 ) ; emit_insn ( gen_sse2_storelpd ( m , op1 ) ) ; m = adjust_address ( op0 , DFmode , 8 ) ; emit_insn ( gen_sse2_storehpd ( m , op1 ) ) ; } else { if ( mode != V4SFmode ) op1 = gen_lowpart ( V4SFmode , op1 ) ; m = adjust_address ( op0 , V2SFmode , 0 ) ; emit_insn ( gen_sse_storelps ( m , op1 ) ) ; m = adjust_address ( op0 , V2SFmode , 8 ) ; emit_insn ( gen_sse_storehps ( m , copy_rtx ( op1 ) ) ) ; } } else gcc_unreachable ( ) ; } </s>

Implement the movmisalign patterns for SSE . Non-SSE modes go straight to ix86_expand_vector_move .


<s> static rtx ix86_expand_vec_ext_builtin ( tree exp , rtx target ) { machine_mode tmode , mode0 ; tree arg0 , arg1 ; int elt ; rtx op0 ; arg0 = CALL_EXPR_ARG ( exp , 0 ) ; arg1 = CALL_EXPR_ARG ( exp , 1 ) ; op0 = expand_normal ( arg0 ) ; elt = get_element_number ( TREE_TYPE ( arg0 ) , arg1 ) ; tmode = TYPE_MODE ( TREE_TYPE ( TREE_TYPE ( arg0 ) ) ) ; mode0 = TYPE_MODE ( TREE_TYPE ( arg0 ) ) ; gcc_assert ( VECTOR_MODE_P ( mode0 ) ) ; op0 = force_reg ( mode0 , op0 ) ; if ( optimize || ! target || ! register_operand ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; ix86_expand_vector_extract ( true , target , op0 , elt ) ; return target ; } </s>

A subroutine of ix86_expand_builtin . These builtins are a wrapper around ix86_expand_vector_extract . They would be redundant ( for non-MMX ) if we had a language-level syntax for referencing vector elements .


<s> static rtx ix86_expand_vec_init_builtin ( tree type , tree exp , rtx target ) { machine_mode tmode = TYPE_MODE ( type ) ; machine_mode inner_mode = GET_MODE_INNER ( tmode ) ; int i , n_elt = GET_MODE_NUNITS ( tmode ) ; rtvec v = rtvec_alloc ( n_elt ) ; gcc_assert ( VECTOR_MODE_P ( tmode ) ) ; gcc_assert ( call_expr_nargs ( exp ) == n_elt ) ; for ( i = 0 ; i < n_elt ; ++ i ) { rtx x = expand_normal ( CALL_EXPR_ARG ( exp , i ) ) ; RTVEC_ELT ( v , i ) = gen_lowpart ( inner_mode , x ) ; } if ( ! target || ! register_operand ( target , tmode ) ) target = gen_reg_rtx ( tmode ) ; ix86_expand_vector_init ( true , target , gen_rtx_PARALLEL ( tmode , v ) ) ; return target ; } </s>

A subroutine of ix86_expand_builtin . These builtins are a wrapper around ix86_expand_vector_init . We DO have language-level syntax for this , in the form of ( type ) { init-list } . Except that since we ca n't place emms instructions from inside the compiler , we ca n't allow the use of MMX registers unless the user explicitly asks for it . So we do * not * define vec_set/vec_extract/vec_init patterns for MMX modes in mmx.md . Instead we have builtins invoked by mmintrin.h that gives us license to emit these sorts of instructions .


<s> static bool ix86_expand_vec_one_operand_perm_avx512 ( struct expand_vec_perm_d * d ) { machine_mode mode = GET_MODE ( d -> op0 ) ; machine_mode maskmode = mode ; unsigned inner_size = GET_MODE_SIZE ( GET_MODE_INNER ( mode ) ) ; rtx ( * gen ) ( rtx , rtx , rtx ) = NULL ; rtx target , op0 , mask ; rtx vec [ 64 ] ; if ( ! rtx_equal_p ( d -> op0 , d -> op1 ) ) return false ; if ( ! TARGET_AVX512F ) return false ; if ( ! TARGET_AVX512VL && GET_MODE_SIZE ( mode ) < 64 ) return false ; if ( ! TARGET_AVX512BW && inner_size == 2 ) return false ; if ( ! TARGET_AVX512VBMI && inner_size == 1 ) return false ; switch ( mode ) { case E_V16SImode : gen = gen_avx512f_permvarv16si ; break ; case E_V16SFmode : gen = gen_avx512f_permvarv16sf ; maskmode = V16SImode ; break ; case E_V8DImode : gen = gen_avx512f_permvarv8di ; break ; case E_V8DFmode : gen = gen_avx512f_permvarv8df ; maskmode = V8DImode ; break ; case E_V32HImode : gen = gen_avx512bw_permvarv32hi ; break ; case E_V16HImode : gen = gen_avx512vl_permvarv16hi ; break ; case E_V8HImode : gen = gen_avx512vl_permvarv8hi ; break ; case E_V64QImode : gen = gen_avx512bw_permvarv64qi ; break ; case E_V32QImode : gen = gen_avx512vl_permvarv32qi ; break ; case E_V16QImode : gen = gen_avx512vl_permvarv16qi ; break ; default : return false ; } if ( d -> testing_p ) return true ; target = d -> target ; op0 = d -> op0 ; for ( int i = 0 ; i < d -> nelt ; ++ i ) vec [ i ] = GEN_INT ( d -> perm [ i ] ) ; mask = gen_rtx_CONST_VECTOR ( maskmode , gen_rtvec_v ( d -> nelt , vec ) ) ; emit_insn ( gen ( target , op0 , force_reg ( maskmode , mask ) ) ) ; return true ; } </s>

Try to expand one-operand permutation with constant mask .


The guts of ix86_expand_vec_perm_const , also used by the ok hook . With all of the interface bits taken care of , perform the expansion in D and return true on success .


<s> static rtx ix86_expand_vec_set_builtin ( tree exp ) { machine_mode tmode , mode1 ; tree arg0 , arg1 , arg2 ; int elt ; rtx op0 , op1 , target ; arg0 = CALL_EXPR_ARG ( exp , 0 ) ; arg1 = CALL_EXPR_ARG ( exp , 1 ) ; arg2 = CALL_EXPR_ARG ( exp , 2 ) ; tmode = TYPE_MODE ( TREE_TYPE ( arg0 ) ) ; mode1 = TYPE_MODE ( TREE_TYPE ( TREE_TYPE ( arg0 ) ) ) ; gcc_assert ( VECTOR_MODE_P ( tmode ) ) ; op0 = expand_expr ( arg0 , NULL_RTX , tmode , EXPAND_NORMAL ) ; op1 = expand_expr ( arg1 , NULL_RTX , mode1 , EXPAND_NORMAL ) ; elt = get_element_number ( TREE_TYPE ( arg0 ) , arg2 ) ; if ( GET_MODE ( op1 ) != mode1 && GET_MODE ( op1 ) != VOIDmode ) op1 = convert_modes ( mode1 , GET_MODE ( op1 ) , op1 , true ) ; op0 = force_reg ( tmode , op0 ) ; op1 = force_reg ( mode1 , op1 ) ; target = gen_reg_rtx ( tmode ) ; emit_move_insn ( target , op0 ) ; ix86_expand_vector_set ( true , target , op1 , elt ) ; return target ; } </s>

A subroutine of ix86_expand_builtin . These builtins are a wrapper around ix86_expand_vector_set . They would be redundant ( for non-MMX ) if we had a language-level syntax for referencing vector elements .