Hi, By investigating the conditional expression handling I found some causes, why TRUTH operations AND, ANDIF, OR, XOR, and ORIF are appearing withing conditional folding during gimplification. The reason for this can be that the truth expression is simply used as result of an assignment or return statement, which then leads to the issue that expression has lhs type. By this reason it is still necessary to have in TRUTH operations type-cast after boolifying it for later operation, if type isn't of kind boolean. Therefore it is necessary for conditional to check if their arms might be TRUTH results and therefore doing boolification of the arms, too.
2011-05-11 Kai Tietz * gimplify.c (gimple_boolify): Handle COND_EXPR and make sure that even if type is BOOLEAN for TRUTH-opcodes the operands getting boolified. (gimple_has_cond_boolean_arms): Helper function to detect if condition is a TRUTH operation in arms. (gimple_is_truth_op): Checks if operand is of BOOLEAN kind. (gimplify_expr): Boolify operand condition for COND_EXPR and try to see if condition might be an TRUTH operation. Boolify truth opcodes AND, ANDIF, OR, ORIF, and XOR. Additional take care that we keep expression's type. Tested on x86_64-w64-mingw32 and x86_64-pc-linux-gnu. Ok for apply? Regards, Kai
Index: gcc/gcc/gimplify.c =================================================================== --- gcc.orig/gcc/gimplify.c 2011-05-10 18:31:40.000000000 +0200 +++ gcc/gcc/gimplify.c 2011-05-11 10:20:30.413964700 +0200 @@ -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;