Hi, this is updated patch I am going to commit. As discussed, we also need to match non-empty CONSTRUCTOR of vectors, but those should never be having CONSTANT flags set, so they need care in the other path trhough operand_equal_p, so I will post separate patch for that.
I updated the comment per Richard's comment and added a testcase. Vuriously enoug we fold "val? (struct a){} : (struct a){}" only in PRE (tailmerging). W/o the patch even .optimized dump has the test and we fold it away only after lowering to RTL: ret (int val) { struct a D.1764; <bb 2>: if (val_2(D) != 0) goto <bb 3>; else goto <bb 4>; <bb 3>: D.1764 = {}; goto <bb 5>; <bb 4>: D.1764 = {}; <bb 5>: return D.1764; } ret: .LFB0: .cfi_startproc xorl %eax, %eax ret .cfi_endproc With the patch we get: ret (int val) { struct a D.1764; <bb 2>: D.1764 = {}; return D.1764; } Honza * fold-const.c (operand_equal_p): Add code matching empty constructors. * gcc.dg/tree-ssa/operand-equal-1.c: Verify that empty constructors are matched. Index: fold-const.c =================================================================== --- fold-const.c (revision 229133) +++ fold-const.c (working copy) @@ -2892,6 +2892,11 @@ operand_equal_p (const_tree arg0, const_ return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), flags | OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF); + case CONSTRUCTOR: + /* In GIMPLE empty constructors are allowed in initializers of + aggregates. */ + return (!vec_safe_length (CONSTRUCTOR_ELTS (arg0)) + && !vec_safe_length (CONSTRUCTOR_ELTS (arg1))); default: break; } Index: testsuite/gcc.dg/tree-ssa/operand-equal-1.c =================================================================== --- testsuite/gcc.dg/tree-ssa/operand-equal-1.c (revision 0) +++ testsuite/gcc.dg/tree-ssa/operand-equal-1.c (revision 0) @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre" } */ +struct a {int a,b;}; +struct a ret(int val) +{ + return val? (struct a){} : (struct a){}; +} +/* { dg-final { scan-tree-dump-not "if " "pre"} } */