GCC Wikia
Advertisement

このページを編集する際は,編集に関する方針に従ってください.[]

概要[]

引数[]

実装[]

 9936 /* Fold a ternary expression of code CODE and type TYPE with operands
 9937    OP0, OP1, and OP2.  Return the folded expression if folding is
 9938    successful.  Otherwise, return NULL_TREE.  */
9939 
9940 tree
9941 fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
9942 {
9943   tree tem;
9944   tree arg0 = NULL_TREE, arg1 = NULL_TREE;
9945   enum tree_code_class kind = TREE_CODE_CLASS (code);
9946 
9947   gcc_assert (IS_EXPR_CODE_CLASS (kind)
9948               && TREE_CODE_LENGTH (code) == 3);
9949 
 9950   /* Strip any conversions that don't change the mode.  This is safe
 9951      for every expression, except for a comparison expression because
 9952      its signedness is derived from its operands.  So, in the latter
 9953      case, only strip conversions that don't change the signedness.
 9954 
 9955      Note that this is done as an internal manipulation within the
 9956      constant folder, in order to find the simplest representation of
 9957      the arguments so that their form can be studied.  In any cases,
 9958      the appropriate type conversions should be put back in the tree
 9959      that will get out of the constant folder.  */
9960   if (op0)
9961     {
9962       arg0 = op0;
9963       STRIP_NOPS (arg0);
9964     }
9965 
9966   if (op1)
9967     {
9968       arg1 = op1;
9969       STRIP_NOPS (arg1);
9970     }
9971 

~
~

9972   switch (code)
9973     {
9974     case [[COMPONENT_REF>enum tree_code]]:
9975       if (TREE_CODE (arg0) == [[CONSTRUCTOR>enum tree_code]]
9976           && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
9977         {
9978           unsigned HOST_WIDE_INT idx;
9979           tree field, value;
9980           FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg0), idx, field, value)
9981             if (field == arg1)
9982               return value;
9983         }
9984       return NULL_TREE;
9985 

~

9986     case [[COND_EXPR>enum tree_code]]:
 9987       /* Pedantic ANSI C says that a conditional expression is never an lvalue,
 9988          so all simple results must be passed through pedantic_non_lvalue.  */
9989       if (TREE_CODE (arg0) == [[INTEGER_CST>enum tree_code]])
9990         {
9991           tree unused_op = integer_zerop (arg0) ? op1 : op2;
9992           tem = integer_zerop (arg0) ? op2 : op1;
 9993           /* Only optimize constant conditions when the selected branch
 9994              has the same type as the COND_EXPR.  This avoids optimizing
 9995              away "c ? x : throw", where the throw has a void type.
 9996              Avoid throwing away that operand which contains label.  */
9997           if ((!TREE_SIDE_EFFECTS (unused_op)
9998                || !contains_label_p (unused_op))
9999               && (! VOID_TYPE_P (TREE_TYPE (tem))
10000                   || VOID_TYPE_P (type)))
10001             return pedantic_non_lvalue (tem);
10002           return NULL_TREE;
10003         }
10004       if (operand_equal_p (arg1, op2, 0))
10005         return pedantic_omit_one_operand (type, arg1, arg0);
10006 
 10007       /* If we have A op B ? A : C, we may be able to convert this to a
 10008          simpler expression, depending on the operation and the values
 10009          of B and C.  Signed zeros prevent all of these transformations,
 10010          for reasons given above each one.
 10011 
 10012          Also try swapping the arguments and inverting the conditional.  */
10013       if (COMPARISON_CLASS_P (arg0)
10014           && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
10015                                              arg1, TREE_OPERAND (arg0, 1))
10016           && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
10017         {
10018           tem = fold_cond_expr_with_comparison (type, arg0, op1, op2);
10019           if (tem)
10020             return tem;
10021         }
10022 
10023       if (COMPARISON_CLASS_P (arg0)
10024           && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
10025                                              op2,
10026                                              TREE_OPERAND (arg0, 1))
10027           && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
10028         {
10029           tem = invert_truthvalue (arg0);
10030           if (COMPARISON_CLASS_P (tem))
10031             {
10032               tem = fold_cond_expr_with_comparison (type, tem, op2, op1);
10033               if (tem)
10034                 return tem;
10035             }
10036         }
10037 
 10038       /* If the second operand is simpler than the third, swap them
 10039          since that produces better jump optimization results.  */
10040       if (truth_value_p (TREE_CODE (arg0))
10041           && tree_swap_operands_p (op1, op2, false))
10042         {
 10043           /* See if this can be inverted.  If it can't, possibly because
 10044              it was a floating-point inequality comparison, don't do
 10045              anything.  */
10046           tem = invert_truthvalue (arg0);
10047 
10048           if (TREE_CODE (tem) != [[TRUTH_NOT_EXPR>enum tree_code]])
10049             return fold_build3 (code, type, tem, op2, op1);
10050         }
10051 
 10052       /* Convert A ? 1 : 0 to simply A.  */
10053       if (integer_onep (op1)
10054           && integer_zerop (op2)
 10055           /* If we try to convert OP0 to our type, the
 10056              call to fold will try to move the conversion inside
 10057              a COND, which will recurse.  In that case, the COND_EXPR
 10058              is probably the best choice, so leave it alone.  */
10059           && type == TREE_TYPE (arg0))
10060         return pedantic_non_lvalue (arg0);
10061 
 10062       /* Convert A ? 0 : 1 to !A.  This prefers the use of NOT_EXPR
 10063          over COND_EXPR in cases such as floating point comparisons.  */
10064       if (integer_zerop (op1)
10065           && integer_onep (op2)
10066           && truth_value_p (TREE_CODE (arg0)))
10067         return pedantic_non_lvalue (fold_convert (type,
10068                                                   invert_truthvalue (arg0)));
10069 
 10070       /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>).  */
10071       if (TREE_CODE (arg0) == [[LT_EXPR>enu tree_code]]
10072           && integer_zerop (TREE_OPERAND (arg0, 1))
10073           && integer_zerop (op2)
10074           && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
10075         return fold_convert (type, fold_build2 ([[BIT_AND_EXPR>enum tree_code]],
10076                                                 TREE_TYPE (tem), tem, arg1));
10077 
 10078       /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N).  A & 1 was
 10079          already handled above.  */
10080       if (TREE_CODE (arg0) == [[BIT_AND_EXPR>enum tree_code]]
10081           && integer_onep (TREE_OPERAND (arg0, 1))
10082           && integer_zerop (op2)
10083           && integer_pow2p (arg1))
10084         {
10085           tree tem = TREE_OPERAND (arg0, 0);
10086           STRIP_NOPS (tem);
10087           if (TREE_CODE (tem) == [[RSHIFT_EXPR>enum tree_code]]
10088               && TREE_CODE (TREE_OPERAND (tem, 1)) == [[INTEGER_CST>enum tree_code]]
10089               && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
10090                  TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
10091             return fold_build2 ([[BIT_AND_EXPR>enum tree_code]], type,
10092                                 TREE_OPERAND (tem, 0), arg1);
10093         }
10094 
 10095       /* A & N ? N : 0 is simply A & N if N is a power of two.  This
 10096          is probably obsolete because the first operand should be a
 10097          truth value (that's why we have the two cases above), but let's
 10098          leave it in until we can confirm this for all front-ends.  */
10099       if (integer_zerop (op2)
10100           && TREE_CODE (arg0) == [[NE_EXPR>enum tree_code]]
10101           && integer_zerop (TREE_OPERAND (arg0, 1))
10102           && integer_pow2p (arg1)
10103           && TREE_CODE (TREE_OPERAND (arg0, 0)) == [[BIT_AND_EXPR>enum tree_code]]
10104           && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
10105                               arg1, [[OEP_ONLY_CONST>enum tree_code]]))
10106         return pedantic_non_lvalue (fold_convert (type,
10107                                                   TREE_OPERAND (arg0, 0)));
10108 
 10109       /* Convert A ? B : 0 into A && B if A and B are truth values.  */
10110       if (integer_zerop (op2)
10111           && truth_value_p (TREE_CODE (arg0))
10112           && truth_value_p (TREE_CODE (arg1)))
10113         return fold_build2 ([[TRUTH_ANDIF_EXPR>enum tree_code]], type, arg0, arg1);
10114 
 10115       /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
10116       if (integer_onep (op2)
10117           && truth_value_p (TREE_CODE (arg0))
10118           && truth_value_p (TREE_CODE (arg1)))
10119         {
 10120           /* Only perform transformation if ARG0 is easily inverted.  */
10121           tem = invert_truthvalue (arg0);
10122           if (TREE_CODE (tem) != [[TRUTH_NOT_EXPR>enum tree_code]])
10123             return fold_build2 ([[TRUTH_ORIF_EXPR>enum tree_code]], type, tem, arg1);
10124         }
10125 
 10126       /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
10127       if (integer_zerop (arg1)
10128           && truth_value_p (TREE_CODE (arg0))
10129           && truth_value_p (TREE_CODE (op2)))
10130         {
 10131           /* Only perform transformation if ARG0 is easily inverted.  */
10132           tem = invert_truthvalue (arg0);
10133           if (TREE_CODE (tem) != [[TRUTH_NOT_EXPR>enum tree_code]])
10134             return fold_build2 ([[TRUTH_ANDIF_EXPR>enum tree_code]], type, tem, op2);
10135         }
10136 
 10137       /* Convert A ? 1 : B into A || B if A and B are truth values.  */
10138       if (integer_onep (arg1)
10139           && truth_value_p (TREE_CODE (arg0))
10140           && truth_value_p (TREE_CODE (op2)))
10141         return fold_build2 (TRUTH_ORIF_EXPR, type, arg0, op2);
10142 
10143       return NULL_TREE;
10144 

~

10145     case [[CALL_EXPR>enum tree_code]]:
 10146       /* Check for a built-in function.  */
10147       if (TREE_CODE (op0) == [[ADDR_EXPR>enum tree_code]]
10148           && TREE_CODE (TREE_OPERAND (op0, 0)) == [[FUNCTION_DECL>enum tree_code]]
10149           && DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
10150         return fold_builtin (TREE_OPERAND (op0, 0), op1, false);
10151       return NULL_TREE;
10152 

~

10153     case [[BIT_FIELD_REF>enum tree_code]]:
10154       if (TREE_CODE (arg0) == [[VECTOR_CST>enum tree_code]]
10155           && type == TREE_TYPE (TREE_TYPE (arg0))
10156           && host_integerp (arg1, 1)
10157           && host_integerp (op2, 1))
10158         {
10159           unsigned HOST_WIDE_INT width = tree_low_cst (arg1, 1);
10160           unsigned HOST_WIDE_INT idx = tree_low_cst (op2, 1);
10161 
10162           if (width != 0
10163               && simple_cst_equal (arg1, TYPE_SIZE (type)) == 1
10164               && (idx % width) == 0
10165               && (idx = idx / width)
10166                  < TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))
10167             {
10168               tree elements = TREE_VECTOR_CST_ELTS (arg0);
10169               while (idx-- > 0 && elements)
10170                 elements = TREE_CHAIN (elements);
10171               if (elements)
10172                 return TREE_VALUE (elements);
10173               else
10174                 return fold_convert (type, integer_zero_node);
10175             }
10176         }
10177       return NULL_TREE;
10178 

~

10179     default:
10180       return NULL_TREE;
10181     } /* switch (code) */
10182 }


リンク元

Advertisement