This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

cse won't pull an expr out of a function call



While trying to speed up --enable-checking a bit I ran across an
limitation of CSE which I suspect hurts real code, not just debugging
macros.

Consider

 return (
     (decl->foo == BLAH ? decl : check_failed(decl, BLAH)
     )->bar->foo == BLUR
     ? (decl->foo == BLAH ? decl : check_failed(decl, BLAH)
       )->bar
     : check_failed(
	(decl->foo = BLAH ? decl : check_failed(decl, BLAH)
	)->bar,
	BLUR)
     )->baz;


check_failed is declared noreturn.  The expression 

(decl->foo == BLAH ? decl : check_failed(decl, BLAH))->bar

appears three times.  cse ought to be able to extract it entirely,
so we would get the equivalent of

 temp = (decl->foo == BLAH ? decl : check_failed(decl, BLAH))->bar;
 return (temp->foo == BLUR ? temp : check_failed(temp, BLUR))->baz;

This doesn't happen.  cse fails to extract the instance nested inside
a call to check_failed.  We get assembly equivalent to

 temp = (decl->foo == BLAH ? decl : check_failed(decl, BLAH))->bar;
 return (temp->foo == BLUR ? temp : check_failed(
		   (decl->foo == BLAH ? decl : check_failed(decl, BLAH))->bar
		   , BLUR))->baz;

The test case is appended.

zw

struct rtx_def;
enum tree_code { ERROR_MARK, IDENTIFIER_NODE, OP_IDENTIFIER, TREE_LIST,
TREE_VEC, BLOCK, VOID_TYPE, INTEGER_TYPE, REAL_TYPE, COMPLEX_TYPE,
ENUMERAL_TYPE, BOOLEAN_TYPE, CHAR_TYPE, POINTER_TYPE, OFFSET_TYPE,
REFERENCE_TYPE, METHOD_TYPE, FILE_TYPE, ARRAY_TYPE, SET_TYPE, RECORD_TYPE,
UNION_TYPE, QUAL_UNION_TYPE, FUNCTION_TYPE, LANG_TYPE, INTEGER_CST,
REAL_CST, COMPLEX_CST, STRING_CST, FUNCTION_DECL, LABEL_DECL, CONST_DECL,
TYPE_DECL, VAR_DECL, PARM_DECL, RESULT_DECL, FIELD_DECL, NAMESPACE_DECL,
COMPONENT_REF, BIT_FIELD_REF, INDIRECT_REF, BUFFER_REF, ARRAY_REF,
CONSTRUCTOR, COMPOUND_EXPR, MODIFY_EXPR, INIT_EXPR, TARGET_EXPR,
COND_EXPR, BIND_EXPR, CALL_EXPR, METHOD_CALL_EXPR, WITH_CLEANUP_EXPR,
CLEANUP_POINT_EXPR, PLACEHOLDER_EXPR, WITH_RECORD_EXPR, PLUS_EXPR,
MINUS_EXPR, MULT_EXPR, TRUNC_DIV_EXPR, CEIL_DIV_EXPR, FLOOR_DIV_EXPR,
ROUND_DIV_EXPR, TRUNC_MOD_EXPR, CEIL_MOD_EXPR, FLOOR_MOD_EXPR,
ROUND_MOD_EXPR, RDIV_EXPR, EXACT_DIV_EXPR, FIX_TRUNC_EXPR, FIX_CEIL_EXPR,
FIX_FLOOR_EXPR, FIX_ROUND_EXPR, FLOAT_EXPR, EXPON_EXPR, NEGATE_EXPR,
MIN_EXPR, MAX_EXPR, ABS_EXPR, FFS_EXPR, LSHIFT_EXPR, RSHIFT_EXPR,
LROTATE_EXPR, RROTATE_EXPR, BIT_IOR_EXPR, BIT_XOR_EXPR, BIT_AND_EXPR,
BIT_ANDTC_EXPR, BIT_NOT_EXPR, TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR,
TRUTH_AND_EXPR, TRUTH_OR_EXPR, TRUTH_XOR_EXPR, TRUTH_NOT_EXPR, LT_EXPR,
LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR, NE_EXPR, IN_EXPR, SET_LE_EXPR,
CARD_EXPR, RANGE_EXPR, CONVERT_EXPR, NOP_EXPR, NON_LVALUE_EXPR, SAVE_EXPR,
UNSAVE_EXPR, RTL_EXPR, ADDR_EXPR, REFERENCE_EXPR, ENTRY_VALUE_EXPR,
COMPLEX_EXPR, CONJ_EXPR, REALPART_EXPR, IMAGPART_EXPR, PREDECREMENT_EXPR,
PREINCREMENT_EXPR, POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, VA_ARG_EXPR,
TRY_CATCH_EXPR, TRY_FINALLY_EXPR, GOTO_SUBROUTINE_EXPR, POPDHC_EXPR,
POPDCC_EXPR, LABEL_EXPR, GOTO_EXPR, RETURN_EXPR, EXIT_EXPR, LOOP_EXPR,
LABELED_BLOCK_EXPR, EXIT_BLOCK_EXPR, EXPR_WITH_FILE_LOCATION, SWITCH_EXPR,
LAST_AND_UNUSED_TREE_CODE };

extern char tree_code_type[256];
extern int tree_code_length[256];
extern char *tree_code_name[256];
typedef union tree_node *tree;
struct tree_common
{
  union tree_node *chain;
  union tree_node *type;
  enum tree_code code : 8;
  unsigned side_effects_flag : 1;
  unsigned constant_flag : 1;
  unsigned permanent_flag : 1;
  unsigned addressable_flag : 1;
  unsigned volatile_flag : 1;
  unsigned readonly_flag : 1;
  unsigned unsigned_flag : 1;
  unsigned asm_written_flag: 1;
  unsigned used_flag : 1;
  unsigned raises_flag : 1;
  unsigned static_flag : 1;
  unsigned public_flag : 1;
  unsigned private_flag : 1;
  unsigned protected_flag : 1;
  unsigned lang_flag_0 : 1;
  unsigned lang_flag_1 : 1;
  unsigned lang_flag_2 : 1;
  unsigned lang_flag_3 : 1;
  unsigned lang_flag_4 : 1;
  unsigned lang_flag_5 : 1;
  unsigned lang_flag_6 : 1;
};
extern tree _tree_check_failed (const tree, enum tree_code)
    __attribute__ ((__noreturn__));
extern tree _tree_class_check_failed (const tree, char)
    __attribute__ ((__noreturn__));
struct tree_identifier
{
  char common[sizeof (struct tree_common)];
  int length;
  char *pointer;
};
struct tree_decl
{
  char common[sizeof (struct tree_common)];
  char *filename;
  int linenum;
  unsigned int uid;
  union tree_node *size;
  int mode : 8;
  unsigned external_flag : 1;
  unsigned nonlocal_flag : 1;
  unsigned regdecl_flag : 1;
  unsigned inline_flag : 1;
  unsigned bit_field_flag : 1;
  unsigned virtual_flag : 1;
  unsigned ignored_flag : 1;
  unsigned abstract_flag : 1;
  unsigned in_system_header_flag : 1;
  unsigned common_flag : 1;
  unsigned defer_output : 1;
  unsigned transparent_union : 1;
  unsigned static_ctor_flag : 1;
  unsigned static_dtor_flag : 1;
  unsigned artificial_flag : 1;
  unsigned weak_flag : 1;
  unsigned lang_flag_0 : 1;
  unsigned lang_flag_1 : 1;
  unsigned lang_flag_2 : 1;
  unsigned lang_flag_3 : 1;
  unsigned lang_flag_4 : 1;
  unsigned lang_flag_5 : 1;
  unsigned lang_flag_6 : 1;
  unsigned lang_flag_7 : 1;
  unsigned non_addr_const_p : 1;
  unsigned no_instrument_function_entry_exit : 1;
  unsigned no_check_memory_usage : 1;
  unsigned comdat_flag : 1;
  union {
    int i;
    unsigned int u;
  } frame_size;
  union tree_node *name;
  union tree_node *context;
  union tree_node *arguments;
  union tree_node *result;
  union tree_node *initial;
  union tree_node *abstract_origin;
  union tree_node *assembler_name;
  union tree_node *section_name;
  union tree_node *machine_attributes;
  struct rtx_def *rtl;	 
  struct rtx_def *live_range_rtl;
  union {
    struct rtx_def *r;
    int i;
  } saved_insns;
  union tree_node *vindex;
  int pointer_alias_set;
  struct lang_decl *lang_specific;
};
union tree_node
{
  struct tree_common common;
  struct tree_decl decl;
  struct tree_identifier identifier;
};
char *
decl_name(decl)
    tree decl;
{
 return (
     (tree_code_type[decl->common.code] == 'd'
      ? decl
      : _tree_class_check_failed(decl, 'd')
	 )->decl.name->common.code == IDENTIFIER_NODE
     ? (tree_code_type[decl->common.code] == 'd'
	? decl
	: _tree_class_check_failed(decl, 'd'))
     : _tree_check_failed(
	 (tree_code_type[decl->common.code] == 'd'
	  ? decl
	  : _tree_class_check_failed(decl, 'd')
	     )->decl.name,
	 IDENTIFIER_NODE)
     )->decl.name->identifier.pointer;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]