===================================================================
@@ -102,6 +102,7 @@ typedef struct gimple_temp_hash_elt
/* Forward declaration. */
static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
+static bool gimple_has_cond_boolean_arms (tree);
/* Mark X addressable. Unlike the langhook we expect X to be in gimple
form and we don't do any syntax checking. */
@@ -2824,11 +2825,26 @@ gimple_boolify (tree expr)
}
}
- if (TREE_CODE (type) == BOOLEAN_TYPE)
- return expr;
-
switch (TREE_CODE (expr))
{
+ case COND_EXPR:
+ /* If we have a conditional expression, which shall be
+ boolean, take care we boolify also their left and right arm. */
+ if (TREE_OPERAND (expr, 2) != NULL_TREE && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 2))))
+ TREE_OPERAND (expr, 2) = gimple_boolify (TREE_OPERAND (expr, 2));
+ if (TREE_OPERAND (expr, 1) != NULL_TREE && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
+ TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
+ TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ return expr;
+ if (!VOID_TYPE_P (TREE_TYPE (expr)))
+ {
+ /* These expressions always produce boolean results. */
+ TREE_TYPE (expr) = boolean_type_node;
+ }
+ else
+ return fold_convert_loc (loc, boolean_type_node, expr);
+
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
@@ -2851,6 +2867,8 @@ gimple_boolify (tree expr)
default:
/* Other expressions that get here must have boolean values, but
might need to be converted to the appropriate mode. */
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ return expr;
return fold_convert_loc (loc, boolean_type_node, expr);
}
}
@@ -2909,6 +2927,66 @@ generic_expr_could_trap_p (tree expr)
return false;
}
+/* This function checks if OP is of TRUTH kind expression. It special-case
+ COND_EXPR, as here we need to look on results, too. See function
+ gimple_has_cond_boolean_arms () for more details.
+ If OP is of possible kind TRUTH expression, TRUE is returned,
+ otherwise FALSE is returned.
+ This functions assumes that all TRUTH operations, COND_EXPR with
+ boolean arms, INTEGER_CST with value of one or zero, and any
+ comparision has boolean result. */
+
+static bool
+gimple_is_truth_op (tree op)
+{
+ if (VOID_TYPE_P (TREE_TYPE (op)))
+ return false;
+ if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE)
+ return true;
+ switch (TREE_CODE (op))
+ {
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_NOT_EXPR:
+ return true;
+ case COND_EXPR:
+ return gimple_has_cond_boolean_arms (op);
+ case INTEGER_CST:
+ if (integer_zerop (op) || integer_onep (op))
+ return true;
+ return false;
+ default:
+ if (TREE_CODE_CLASS (TREE_CODE (op)) == tcc_comparison)
+ return true;
+ break;
+ }
+ return false;
+}
+
+/* This function checks if all arms of the condition expression EXPR
+ are of kind TRUTH. If so, it returns TRUE, otherwise FALSE. */
+
+static bool
+gimple_has_cond_boolean_arms (tree expr)
+{
+ tree type = TREE_TYPE (expr);
+ tree arm1 = TREE_OPERAND (expr, 0);
+ tree arm2 = TREE_OPERAND (expr, 1);
+
+ if (VOID_TYPE_P (type))
+ return false;
+ if (!arm1 && !arm2)
+ return false;
+ if (arm1 && !gimple_is_truth_op (arm1))
+ return false;
+ if (arm2 && !gimple_is_truth_op (arm2))
+ return false;
+ return true;
+}
+
/* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
into
@@ -6714,7 +6792,25 @@ gimplify_expr (tree *expr_p, gimple_seq
break;
case COND_EXPR:
- ret = gimplify_cond_expr (expr_p, pre_p, fallback);
+ {
+ tree type = TREE_TYPE (*expr_p);
+ tree nexpr = NULL_TREE;
+ if (TREE_CODE (type) == BOOLEAN_TYPE
+ || !gimple_has_cond_boolean_arms (*expr_p))
+ type = NULL;
+ if (type)
+ nexpr = gimple_boolify (*expr_p);
+
+ TREE_OPERAND (*expr_p, 0) = gimple_boolify (TREE_OPERAND (*expr_p, 0));
+
+ ret = gimplify_cond_expr (expr_p, pre_p, fallback);
+
+ if (nexpr)
+ {
+ *expr_p = fold_convert (type, *expr_p);
+ ret = GS_OK;
+ }
+ }
/* C99 code may assign to an array in a structure value of a
conditional expression, and this has undefined behavior
@@ -6762,6 +6858,18 @@ gimplify_expr (tree *expr_p, gimple_seq
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
+ /* This shouldn't happen, but due fold-const (and here especially
+ fold_truth_not_expr) happily uses operand type and doesn't
+ automatically uses boolean_type as result, this happens. */
+ if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
+ {
+ tree type = TREE_TYPE (*expr_p);
+
+ *expr_p = fold_convert (type, gimple_boolify (*expr_p));
+ ret = GS_OK;
+ break;
+ }
+ *expr_p = gimple_boolify (*expr_p);
/* Pass the source location of the outer expression. */
ret = gimplify_boolean_expr (expr_p, saved_location);
break;
@@ -7203,6 +7311,17 @@ gimplify_expr (tree *expr_p, gimple_seq
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_XOR_EXPR:
+ /* This shouldn't happen, but due fold-const (and here especially
+ fold_truth_not_expr) happily uses operand type and doesn't
+ automatically uses boolean_type as result, this happens. */
+ if (TREE_CODE (TREE_TYPE (*expr_p)) != BOOLEAN_TYPE)
+ {
+ tree type = TREE_TYPE (*expr_p);
+ *expr_p = fold_convert (type, gimple_boolify (*expr_p));
+ ret = GS_OK;
+ break;
+ }
+ *expr_p = gimple_boolify (*expr_p);
/* Classified as tcc_expression. */
goto expr_2;