OSDN Git Service

2007-08-04 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / optabs.c
index ef58aee..3741139 100644 (file)
@@ -7,7 +7,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 #include "config.h"
@@ -126,6 +125,10 @@ static rtx expand_parity (enum machine_mode, rtx, rtx);
 static enum rtx_code get_rtx_code (enum tree_code, bool);
 static rtx vector_compare_rtx (tree, bool, enum insn_code);
 
+/* Current libcall id.  It doesn't matter what these are, as long
+   as they are unique to each libcall that is emitted.  */
+static HOST_WIDE_INT libcall_id = 0;
+
 #ifndef HAVE_conditional_trap
 #define HAVE_conditional_trap 0
 #define gen_conditional_trap(a,b) (gcc_unreachable (), NULL_RTX)
@@ -340,12 +343,27 @@ optab_for_tree_code (enum tree_code code, tree type)
       return TYPE_UNSIGNED (type) ? 
        vec_unpacku_lo_optab : vec_unpacks_lo_optab;
 
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+      /* The signedness is determined from input operand.  */
+      return TYPE_UNSIGNED (type) ?
+       vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
+
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+      /* The signedness is determined from input operand.  */
+      return TYPE_UNSIGNED (type) ? 
+       vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
+
     case VEC_PACK_TRUNC_EXPR:
       return vec_pack_trunc_optab;
 
     case VEC_PACK_SAT_EXPR:
       return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
 
+    case VEC_PACK_FIX_TRUNC_EXPR:
+      /* The signedness is determined from output operand.  */
+      return TYPE_UNSIGNED (type) ?
+       vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
+
     default:
       break;
     }
@@ -353,6 +371,7 @@ optab_for_tree_code (enum tree_code code, tree type)
   trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
   switch (code)
     {
+    case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       return trapv ? addv_optab : add_optab;
 
@@ -1226,6 +1245,113 @@ swap_commutative_operands_with_target (rtx target, rtx op0, rtx op1)
 }
 
 
+/* Helper function for expand_binop: handle the case where there
+   is an insn that directly implements the indicated operation.
+   Returns null if this is not possible.  */
+static rtx
+expand_binop_directly (enum machine_mode mode, optab binoptab,
+                      rtx op0, rtx op1,
+                      rtx target, int unsignedp, enum optab_methods methods,
+                      int commutative_op, rtx last)
+{
+  int icode = (int) binoptab->handlers[(int) mode].insn_code;
+  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+  enum machine_mode tmp_mode;
+  rtx pat;
+  rtx xop0 = op0, xop1 = op1;
+  rtx temp;
+  
+  if (target)
+    temp = target;
+  else
+    temp = gen_reg_rtx (mode);
+  
+  /* If it is a commutative operator and the modes would match
+     if we would swap the operands, we can save the conversions.  */
+  if (commutative_op)
+    {
+      if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
+         && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
+       {
+         rtx tmp;
+         
+         tmp = op0; op0 = op1; op1 = tmp;
+         tmp = xop0; xop0 = xop1; xop1 = tmp;
+       }
+    }
+  
+  /* In case the insn wants input operands in modes different from
+     those of the actual operands, convert the operands.  It would
+     seem that we don't need to convert CONST_INTs, but we do, so
+     that they're properly zero-extended, sign-extended or truncated
+     for their mode.  */
+  
+  if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
+    xop0 = convert_modes (mode0,
+                         GET_MODE (op0) != VOIDmode
+                         ? GET_MODE (op0)
+                         : mode,
+                         xop0, unsignedp);
+  
+  if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
+    xop1 = convert_modes (mode1,
+                         GET_MODE (op1) != VOIDmode
+                         ? GET_MODE (op1)
+                         : mode,
+                         xop1, unsignedp);
+  
+  /* Now, if insn's predicates don't allow our operands, put them into
+     pseudo regs.  */
+  
+  if (!insn_data[icode].operand[1].predicate (xop0, mode0)
+      && mode0 != VOIDmode)
+    xop0 = copy_to_mode_reg (mode0, xop0);
+  
+  if (!insn_data[icode].operand[2].predicate (xop1, mode1)
+      && mode1 != VOIDmode)
+    xop1 = copy_to_mode_reg (mode1, xop1);
+  
+  if (binoptab == vec_pack_trunc_optab 
+      || binoptab == vec_pack_usat_optab
+      || binoptab == vec_pack_ssat_optab
+      || binoptab == vec_pack_ufix_trunc_optab
+      || binoptab == vec_pack_sfix_trunc_optab)
+    {
+      /* The mode of the result is different then the mode of the
+        arguments.  */
+      tmp_mode = insn_data[icode].operand[0].mode;
+      if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
+       return 0;
+    }
+  else
+    tmp_mode = mode;
+
+  if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
+    temp = gen_reg_rtx (tmp_mode);
+  
+  pat = GEN_FCN (icode) (temp, xop0, xop1);
+  if (pat)
+    {
+      /* If PAT is composed of more than one insn, try to add an appropriate
+        REG_EQUAL note to it.  If we can't because TEMP conflicts with an
+        operand, call expand_binop again, this time without a target.  */
+      if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
+         && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
+       {
+         delete_insns_since (last);
+         return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
+                              unsignedp, methods);
+       }
+      
+      emit_insn (pat);
+      return temp;
+    }
+
+  delete_insns_since (last);
+  return NULL_RTX;
+}
+
 /* Generate code to perform an operation specified by BINOPTAB
    on operands OP0 and OP1, with result having machine-mode MODE.
 
@@ -1255,7 +1381,6 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
                  || binoptab->code == ROTATERT);
   rtx entry_last = get_last_insn ();
   rtx last;
-  bool first_pass_p = true;
 
   class = GET_MODE_CLASS (mode);
 
@@ -1309,121 +1434,43 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
        }
     }
 
- retry:
-
   /* If we can do it with a three-operand insn, do so.  */
 
   if (methods != OPTAB_MUST_WIDEN
       && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
     {
-      int icode = (int) binoptab->handlers[(int) mode].insn_code;
-      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
-      enum machine_mode mode1 = insn_data[icode].operand[2].mode;
-      enum machine_mode tmp_mode;
-      rtx pat;
-      rtx xop0 = op0, xop1 = op1;
-
-      if (target)
-       temp = target;
-      else
-       temp = gen_reg_rtx (mode);
-
-      /* If it is a commutative operator and the modes would match
-        if we would swap the operands, we can save the conversions.  */
-      if (commutative_op)
-       {
-         if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
-             && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
-           {
-             rtx tmp;
-
-             tmp = op0; op0 = op1; op1 = tmp;
-             tmp = xop0; xop0 = xop1; xop1 = tmp;
-           }
-       }
-
-      /* In case the insn wants input operands in modes different from
-        those of the actual operands, convert the operands.  It would
-        seem that we don't need to convert CONST_INTs, but we do, so
-        that they're properly zero-extended, sign-extended or truncated
-        for their mode.  */
-
-      if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
-       xop0 = convert_modes (mode0,
-                             GET_MODE (op0) != VOIDmode
-                             ? GET_MODE (op0)
-                             : mode,
-                             xop0, unsignedp);
-
-      if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
-       xop1 = convert_modes (mode1,
-                             GET_MODE (op1) != VOIDmode
-                             ? GET_MODE (op1)
-                             : mode,
-                             xop1, unsignedp);
-
-      /* Now, if insn's predicates don't allow our operands, put them into
-        pseudo regs.  */
-
-      if (!insn_data[icode].operand[1].predicate (xop0, mode0)
-         && mode0 != VOIDmode)
-       xop0 = copy_to_mode_reg (mode0, xop0);
-
-      if (!insn_data[icode].operand[2].predicate (xop1, mode1)
-         && mode1 != VOIDmode)
-       xop1 = copy_to_mode_reg (mode1, xop1);
-
-      if (binoptab == vec_pack_trunc_optab 
-         || binoptab == vec_pack_usat_optab
-          || binoptab == vec_pack_ssat_optab)
-       {
-         /* The mode of the result is different then the mode of the
-            arguments.  */
-         tmp_mode = insn_data[icode].operand[0].mode;
-         if (GET_MODE_NUNITS (tmp_mode) != 2 * GET_MODE_NUNITS (mode))
-           return 0;
-       }
-      else
-        tmp_mode = mode;
-
-      if (!insn_data[icode].operand[0].predicate (temp, tmp_mode))
-       temp = gen_reg_rtx (tmp_mode);
-
-      pat = GEN_FCN (icode) (temp, xop0, xop1);
-      if (pat)
-       {
-         /* If PAT is composed of more than one insn, try to add an appropriate
-            REG_EQUAL note to it.  If we can't because TEMP conflicts with an
-            operand, call ourselves again, this time without a target.  */
-         if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
-             && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
-           {
-             delete_insns_since (last);
-             return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
-                                  unsignedp, methods);
-           }
-
-         emit_insn (pat);
-         return temp;
-       }
-      else
-       delete_insns_since (last);
+      temp = expand_binop_directly (mode, binoptab, op0, op1, target,
+                                   unsignedp, methods, commutative_op, last);
+      if (temp)
+       return temp;
     }
 
-  /* If we were trying to rotate by a constant value, and that didn't
-     work, try rotating the other direction before falling back to
-     shifts and bitwise-or.  */
-  if (first_pass_p
-      && (binoptab == rotl_optab || binoptab == rotr_optab)
-      && class == MODE_INT
-      && GET_CODE (op1) == CONST_INT
-      && INTVAL (op1) > 0
-      && (unsigned int) INTVAL (op1) < GET_MODE_BITSIZE (mode))
+  /* If we were trying to rotate, and that didn't work, try rotating
+     the other direction before falling back to shifts and bitwise-or.  */
+  if (((binoptab == rotl_optab
+       && rotr_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+       || (binoptab == rotr_optab
+          && rotl_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing))
+      && class == MODE_INT)
     {
-      first_pass_p = false;
-      op1 = GEN_INT (GET_MODE_BITSIZE (mode) - INTVAL (op1));
-      binoptab = binoptab == rotl_optab ? rotr_optab : rotl_optab;
-      goto retry;
+      optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab);
+      rtx newop1;
+      unsigned int bits = GET_MODE_BITSIZE (mode);
+
+      if (GET_CODE (op1) == CONST_INT)
+       newop1 = GEN_INT (bits - INTVAL (op1));
+      else if (targetm.shift_truncation_mask (mode) == bits - 1)
+       newop1 = negate_rtx (mode, op1);
+      else
+       newop1 = expand_binop (mode, sub_optab,
+                              GEN_INT (bits), op1,
+                              NULL_RTX, unsignedp, OPTAB_DIRECT);
+                                  
+      temp = expand_binop_directly (mode, otheroptab, op0, newop1,
+                                   target, unsignedp, methods,
+                                   commutative_op, last);
+      if (temp)
+       return temp;
     }
 
   /* If this is a multiply, see if we can do a widening operation that
@@ -1932,10 +1979,10 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
 
       if (shift_op)
        {
-         op1_mode = word_mode;
+         op1_mode = targetm.libgcc_shift_count_mode ();
          /* Specify unsigned here,
             since negative shift counts are meaningless.  */
-         op1x = convert_to_mode (word_mode, op1, 1);
+         op1x = convert_to_mode (op1_mode, op1, 1);
        }
 
       if (GET_MODE (op0) != VOIDmode
@@ -3064,63 +3111,79 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target,
                        int bitpos, bool op0_is_abs)
 {
   enum machine_mode imode;
-  HOST_WIDE_INT hi, lo;
-  int word;
-  rtx label;
+  int icode;
+  rtx sign, label;
 
   if (target == op1)
     target = NULL_RTX;
 
-  if (!op0_is_abs)
+  /* Check if the back end provides an insn that handles signbit for the
+     argument's mode. */
+  icode = (int) signbit_optab->handlers [(int) mode].insn_code;
+  if (icode != CODE_FOR_nothing)
     {
-      op0 = expand_unop (mode, abs_optab, op0, target, 0);
-      if (op0 == NULL)
-       return NULL_RTX;
-      target = op0;
+      imode = insn_data[icode].operand[0].mode;
+      sign = gen_reg_rtx (imode);
+      emit_unop_insn (icode, sign, op1, UNKNOWN);
     }
   else
     {
-      if (target == NULL_RTX)
-        target = copy_to_reg (op0);
+      HOST_WIDE_INT hi, lo;
+
+      if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
+       {
+         imode = int_mode_for_mode (mode);
+         if (imode == BLKmode)
+           return NULL_RTX;
+         op1 = gen_lowpart (imode, op1);
+       }
       else
-       emit_move_insn (target, op0);
-    }
+       {
+         int word;
 
-  if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
-    {
-      imode = int_mode_for_mode (mode);
-      if (imode == BLKmode)
-       return NULL_RTX;
-      op1 = gen_lowpart (imode, op1);
-    }
-  else
-    {
-      imode = word_mode;
-      if (FLOAT_WORDS_BIG_ENDIAN)
-       word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
+         imode = word_mode;
+         if (FLOAT_WORDS_BIG_ENDIAN)
+           word = (GET_MODE_BITSIZE (mode) - bitpos) / BITS_PER_WORD;
+         else
+           word = bitpos / BITS_PER_WORD;
+         bitpos = bitpos % BITS_PER_WORD;
+         op1 = operand_subword_force (op1, word, mode);
+       }
+
+      if (bitpos < HOST_BITS_PER_WIDE_INT)
+       {
+         hi = 0;
+         lo = (HOST_WIDE_INT) 1 << bitpos;
+       }
       else
-       word = bitpos / BITS_PER_WORD;
-      bitpos = bitpos % BITS_PER_WORD;
-      op1 = operand_subword_force (op1, word, mode);
+       {
+         hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
+         lo = 0;
+       }
+
+      sign = gen_reg_rtx (imode);
+      sign = expand_binop (imode, and_optab, op1,
+                          immed_double_const (lo, hi, imode),
+                          NULL_RTX, 1, OPTAB_LIB_WIDEN);
     }
 
-  if (bitpos < HOST_BITS_PER_WIDE_INT)
+  if (!op0_is_abs)
     {
-      hi = 0;
-      lo = (HOST_WIDE_INT) 1 << bitpos;
+      op0 = expand_unop (mode, abs_optab, op0, target, 0);
+      if (op0 == NULL)
+       return NULL_RTX;
+      target = op0;
     }
   else
     {
-      hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
-      lo = 0;
+      if (target == NULL_RTX)
+        target = copy_to_reg (op0);
+      else
+       emit_move_insn (target, op0);
     }
 
-  op1 = expand_binop (imode, and_optab, op1,
-                     immed_double_const (lo, hi, imode),
-                     NULL_RTX, 1, OPTAB_LIB_WIDEN);
-
   label = gen_label_rtx ();
-  emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, imode, 1, label);
+  emit_cmp_and_jump_insns (sign, const0_rtx, EQ, NULL_RTX, imode, 1, label);
 
   if (GET_CODE (op0) == CONST_DOUBLE)
     op0 = simplify_unary_operation (NEG, mode, op0, mode);
@@ -3332,7 +3395,7 @@ struct no_conflict_data
    in the list of insns that constitute the actual no_conflict block /
    libcall block.  */
 static void
-no_conflict_move_test (rtx dest, rtx set, void *p0)
+no_conflict_move_test (rtx dest, const_rtx set, void *p0)
 {
   struct no_conflict_data *p= p0;
 
@@ -3366,7 +3429,7 @@ no_conflict_move_test (rtx dest, rtx set, void *p0)
    logically equivalent to EQUIV, so it gets manipulated as a unit if it
    is possible to do so.  */
 
-static void
+void
 maybe_encapsulate_block (rtx first, rtx last, rtx equiv)
 {
   if (!flag_non_call_exceptions || !may_trap_p (equiv))
@@ -3390,6 +3453,12 @@ maybe_encapsulate_block (rtx first, rtx last, rtx equiv)
                                                 REG_NOTES (first));
          REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
                                                REG_NOTES (last));
+         next = NEXT_INSN (last);
+         for (insn = first; insn != next; insn = NEXT_INSN (insn))
+           REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LIBCALL_ID,
+                                                 GEN_INT (libcall_id),
+                                                 REG_NOTES (insn));
+         libcall_id++;
        }
     }
 }
@@ -3450,6 +3519,8 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
        remove_note (insn, note);
       if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
        remove_note (insn, note);
+      if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL)) != NULL)
+       remove_note (insn, note);
 
       data.target = target;
       data.first = insns;
@@ -3544,7 +3615,6 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
 
    Except for the first group of insns (the ones setting pseudos), the
    block is delimited by REG_RETVAL and REG_LIBCALL notes.  */
-
 void
 emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
 {
@@ -3603,6 +3673,8 @@ emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
        remove_note (insn, note);
       if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
        remove_note (insn, note);
+      if ((note = find_reg_note (insn, REG_LIBCALL_ID, NULL)) != NULL)
+       remove_note (insn, note);
 
       next = NEXT_INSN (insn);
 
@@ -3852,7 +3924,8 @@ prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
        libfunc = ucmp_optab->handlers[(int) mode].libfunc;
 
       result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
-                                       word_mode, 2, x, mode, y, mode);
+                                       targetm.libgcc_cmp_return_mode (),
+                                       2, x, mode, y, mode);
 
       /* There are two kinds of comparison routines. Biased routines
         return 0/1/2, and unbiased routines return -1/0/1. Other parts
@@ -3895,7 +3968,7 @@ prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
   if (!insn_data[icode].operand[opnum].predicate
       (x, insn_data[icode].operand[opnum].mode))
     {
-      if (no_new_pseudos)
+      if (reload_completed)
        return NULL_RTX;
       x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
     }
@@ -3996,9 +4069,11 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
   /* Swap operands and condition to ensure canonical RTL.  */
   if (swap_commutative_operands_p (x, y))
     {
-      /* If we're not emitting a branch, this means some caller
-         is out of sync.  */
-      gcc_assert (label);
+      /* If we're not emitting a branch, callers are required to pass
+        operands in an order conforming to canonical RTL.  We relax this
+        for commutative comparisons so callers using EQ don't need to do
+        swapping by hand.  */
+      gcc_assert (label || (comparison == swap_condition (comparison)));
 
       op0 = y, op1 = x;
       comparison = swap_condition (comparison);
@@ -5475,6 +5550,8 @@ init_optabs (void)
   movstrict_optab = init_optab (STRICT_LOW_PART);
   cmp_optab = init_optab (COMPARE);
 
+  storent_optab = init_optab (UNKNOWN);
+
   ucmp_optab = init_optab (UNKNOWN);
   tst_optab = init_optab (UNKNOWN);
 
@@ -5525,6 +5602,7 @@ init_optabs (void)
   tan_optab = init_optab (UNKNOWN);
   atan_optab = init_optab (UNKNOWN);
   copysign_optab = init_optab (UNKNOWN);
+  signbit_optab = init_optab (UNKNOWN);
 
   isinf_optab = init_optab (UNKNOWN);
 
@@ -5565,9 +5643,15 @@ init_optabs (void)
   vec_unpacks_lo_optab = init_optab (UNKNOWN);
   vec_unpacku_hi_optab = init_optab (UNKNOWN);
   vec_unpacku_lo_optab = init_optab (UNKNOWN);
+  vec_unpacks_float_hi_optab = init_optab (UNKNOWN);
+  vec_unpacks_float_lo_optab = init_optab (UNKNOWN);
+  vec_unpacku_float_hi_optab = init_optab (UNKNOWN);
+  vec_unpacku_float_lo_optab = init_optab (UNKNOWN);
   vec_pack_trunc_optab = init_optab (UNKNOWN);
   vec_pack_usat_optab = init_optab (UNKNOWN);
   vec_pack_ssat_optab = init_optab (UNKNOWN);
+  vec_pack_ufix_trunc_optab = init_optab (UNKNOWN);
+  vec_pack_sfix_trunc_optab = init_optab (UNKNOWN);
 
   powi_optab = init_optab (UNKNOWN);
 
@@ -5795,7 +5879,7 @@ debug_optab_libfuncs (void)
        h = &o->handlers[j];
        if (h->libfunc)
          {
-           gcc_assert (GET_CODE (h->libfunc) = SYMBOL_REF);
+           gcc_assert (GET_CODE (h->libfunc) == SYMBOL_REF);
            fprintf (stderr, "%s\t%s:\t%s\n",
                     GET_RTX_NAME (o->code),
                     GET_MODE_NAME (j),
@@ -5815,7 +5899,7 @@ debug_optab_libfuncs (void)
          h = &o->handlers[j][k];
          if (h->libfunc)
            {
-             gcc_assert (GET_CODE (h->libfunc) = SYMBOL_REF);
+             gcc_assert (GET_CODE (h->libfunc) == SYMBOL_REF);
              fprintf (stderr, "%s\t%s\t%s:\t%s\n",
                       GET_RTX_NAME (o->code),
                       GET_MODE_NAME (j),