On Wed, Nov 08, 2017 at 05:22:45PM +0100, Jakub Jelinek wrote: > Hi! > > Here is an attempt to fix these two PRs. The C++ FE already has an LVAL
Nice! > bool that it propagates through constexpr.c functions, or in > cp-gimplify.c through calling cp_fold_{maybe_,}rvalue where appropriate. > The C c_fully_fold was instead just calling > decl_constant_value_for_optimization > in some spots where we've previously called c_fully_fold{_internal,} on > some rvalue. > decl_constant_value_for_optimization wasn't doing anything when -O0, > so we got different behavior between -O0 and -O1+ on what is accepted > in static initializers. Furthermore, we needed the hack to ignore > vars with ARRAY_TYPE or BLKmode, so that we actually wouldn't fold lvalues > to rvalues. > > This patch adds LVAL to c_fully_fold{_internal,} and does what > decl_constant_value_for_optimization did inside of it (without the hacks, > furthermore, and additionally for -O0 when in initializers for consistency), > of course only if LVAL is false. Additionally, I've added folding of > "foo"[2] into 'o'. We have it in gimple-fold.c or so, so that one > isn't performed when not in_init. > > Not sure about the COND_EXPR/VEC_COND_EXPR cases, right now I'm passing > false as LVAL for the first operand (condition) and lval as LVAL for the > other two (i.e. if called with lval == true on the whole *_COND_EXPR > decl_constant_value_for_optimization etc. isn't performed on op1/op2, while > without it it is). Can one take address of the whole COND_EXPR, or > have it on LHS of anything in C? I don't think so, the ?: operator does not yield an lvalue. > @@ -218,12 +235,51 @@ c_fully_fold_internal (tree expr, bool i > op2 = TREE_OPERAND (expr, 2); > op3 = TREE_OPERAND (expr, 3); > op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, > - maybe_const_itself, for_int_const); > + maybe_const_itself, for_int_const, lval); > STRIP_TYPE_NOPS (op0); > op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, > - maybe_const_itself, for_int_const); > + maybe_const_itself, for_int_const, false); > STRIP_TYPE_NOPS (op1); > - op1 = decl_constant_value_for_optimization (op1); > + /* Fold "foo"[2] in initializers. */ > + if (!lval > + && in_init > + && TREE_CODE (op0) == STRING_CST > + && TREE_CODE (op1) == INTEGER_CST > + && TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE Does this also handle 2["foobar"]? > + && tree_fits_uhwi_p (op1)) > + { > + tree ary = op0; > + tree index = op1; > + unsigned len = 0; > + tree elem_type = TREE_TYPE (TREE_TYPE (ary)); > + unsigned elem_nchars = (TYPE_PRECISION (elem_type) > + / TYPE_PRECISION (char_type_node)); > + len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars; > + > + tree nelts = array_type_nelts (TREE_TYPE (ary)); > + bool dummy1 = true, dummy2 = true; > + nelts = c_fully_fold_internal (nelts, in_init, &dummy1, &dummy2, > + for_int_const, false); > + unsigned HOST_WIDE_INT i = tree_to_uhwi (index); > + if (tree_int_cst_le (index, nelts) > + && i < len > + && i + elem_nchars <= len) > + { > + tree type = TREE_TYPE (expr); > + if (elem_nchars == 1) > + ret = build_int_cst (type, > + TREE_STRING_POINTER (ary)[i]); > + else > + { > + const unsigned char *ptr > + = ((const unsigned char *)TREE_STRING_POINTER (ary) > + + i * elem_nchars); > + ret = native_interpret_expr (type, ptr, elem_nchars); > + } > + if (ret) > + goto out; > + } > + } So this code comes from gimple-fold.c? I would probably move it to a new function. Marek