fold() can't fold simple expressions?

Aldy Hernandez aldyh@redhat.com
Wed Sep 14 13:25:00 GMT 2016


Hi folks.  I'm working on better range information with Macleod, and 
I've been playing with folding arbitrary range expressions, which I 
expect fold() to ahem...fold.

I'm surprised that even seemingly simple trees can't be folded after 
they've been built, because AFAICT, fold actually just works by 
recognizing patterns it recognizes at the top level, not by recursing 
down to the sub-trees.

For example, I was surprised at this:

#define INT(N) build_int_cst (integer_type_node, (N))
tree x = build2 (PLUS_EXPR, integer_type_node,
		 build2 (MULT_EXPR, integer_type_node, INT(20), INT(3)),
			 INT(10));

(gdb) call debug_generic_stmt(x)
20 * 3 + 10;

(gdb) call debug_generic_stmt(fold(x))
20 * 3 + 10;

I do know I can build everything with fold_buildN() and fold on the fly, 
but I can't because these are expressions that can have an SSA_NAME 
somewhere in there, and then after the fact, we substitute a constant in 
it.  So it is only after the fact that we realize we can reduce said 
expression to a constant.

Am I missing something?  Is there another entry point for a toplevel fold()?

For now I'm just refolding everything which does the trick, and may even 
work efficiently for small trees, but I'm hoping I'm not missing 
something completely obvious here.  For the record...the refolder:

static tree
refold (tree t)
{
   enum tree_code code = TREE_CODE (t);
   enum tree_code_class kind = TREE_CODE_CLASS (code);
   if (IS_EXPR_CODE_CLASS (kind))
     {
       tree type = TREE_TYPE (t);
       tree op0, op1, op2;

       switch (TREE_CODE_LENGTH (code))
	{
	case 1:
	  op0 = TREE_OPERAND (t, 0);
	  if (TREE_CODE (op0) != INTEGER_CST)
	    op0 = refold (op0);
	  return fold_build1 (code, type, op0);
	case 2:
	  op0 = TREE_OPERAND (t, 0);
	  op1 = TREE_OPERAND (t, 1);
	  if (TREE_CODE (op0) != INTEGER_CST)
	    op0 = refold (op0);
	  if (TREE_CODE (op1) != INTEGER_CST)
	    op1 = refold (op1);
	  return fold_build2 (code, type, op0, op1);
	case 3:
	  op0 = TREE_OPERAND (t, 0);
	  op1 = TREE_OPERAND (t, 1);
	  op2 = TREE_OPERAND (t, 2);
	  if (TREE_CODE (op0) != INTEGER_CST)
	    op0 = refold (op0);
	  if (TREE_CODE (op1) != INTEGER_CST)
	    op1 = refold (op1);
	  if (TREE_CODE (op2) != INTEGER_CST)
	    op1 = refold (op2);
	  return fold_build3 (code, type, op0, op1, op2);
	default:
	  return t;
	}
     }
   return t;
}

Thanks.
Aldy



More information about the Gcc mailing list