https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66984
Bug ID: 66984 Summary: ICE: fold_binary changes type of operand, causing failure in verify_gimple_assign_binary Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: gary at intrepid dot com Target Milestone: --- This problem was previously reported in bug #46679 and bug #56363. I'm logging it as new issue because it occurred as a recent regression in 6.0, though the changes made to 6.0 contributed only in that improved tree folding exposed this problem in our testing of UPC on the GUPC branch. As in the two bug reports mentioned above, we can't easily replicate the issue, because the UPC code generator uses FLOOR_DIV_EXPR, but "C" generally does not. The tree verify failure occurs using -m32 (x86), because on that target the size of 'int' equals the size of 'size_t' and they have the same mode. The test case fails as follows: timer_reduce.upc: In function ‘timers_reduce’: timer_reduce.upc:3:6: error: type mismatch in binary expression void timers_reduce(double *max_t, int j){ ^ int sizetype int D.1986 = D.1984 /[ex] THREADS.4; timer_reduce.upc:3:6: internal compiler error: verify_gimple failed 0xeb38bb verify_gimple_in_seq(gimple_statement_base*) /eng/upc/dev/gary/gupc-merge/src/gupc/gcc/tree-cfg.c:4805 0xbc91b6 gimplify_body(tree_node*, bool) /eng/upc/dev/gary/gupc-merge/src/gupc/gcc/gimplify.c:9260 0xbc960d gimplify_function_tree(tree_node*) /eng/upc/dev/gary/gupc-merge/src/gupc/gcc/gimplify.c:9349 [...] The operand type is changed here in fold-const.c: 10820 /* If arg0 is a multiple of arg1, then rewrite to the fastest div 10821 operation, EXACT_DIV_EXPR. 10822 10823 Note that only CEIL_DIV_EXPR and FLOOR_DIV_EXPR are rewritten now. 10824 At one time others generated faster code, it's not clear if they do 10825 after the last round to changes to the DIV code in expmed.c. */ 10826 if ((code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR) 10827 && multiple_of_p (type, arg0, arg1)) 10828 return fold_build2_loc (loc, EXACT_DIV_EXPR, type, arg0, arg1); (gdb) p code $24 = FLOOR_DIV_EXPR (gdb) p type $25 = (tree) 0x7ffff188c7e0 (gdb) pt warning: Expression is not an assignment (and might have no effect) <integer_type 0x7ffff188c7e0 int public SI size <integer_cst 0x7ffff1889ca8 type <integer_type 0x7ffff188c2a0 bitsizetype> constant 32> unit size <integer_cst 0x7ffff1889cc0 type <integer_type 0x7ffff188c1f8 sizetype> constant 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff188c7e0 precision 32 min <integer_cst 0x7ffff1889ee8 -2147483648> max <integer_cst 0x7ffff1889f00 2147483647> pointer_to_this <pointer_type 0x7ffff18a6a80>> 'op0' is the first operand, 'arg0' is 'op0' after applying STRIP_NOPS(). (gdb) p op0 $26 = (tree) 0x7ffff19e15c0 (gdb) pt warning: Expression is not an assignment (and might have no effect) <nop_expr 0x7ffff19e15c0 type <integer_type 0x7ffff188c7e0 int public SI size <integer_cst 0x7ffff1889ca8 constant 32> unit size <integer_cst 0x7ffff1889cc0 constant 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff188c7e0 precision 32 min <integer_cst 0x7ffff1889ee8 -2147483648> max <integer_cst 0x7ffff1889f00 2147483647> pointer_to_this <pointer_type 0x7ffff18a6a80>> side-effects arg 0 <save_expr 0x7ffff19abee0 type <integer_type 0x7ffff188c1f8 sizetype public unsigned SI size <integer_cst 0x7ffff1889ca8 32> unit size <integer_cst 0x7ffff1889cc0 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff188c1f8 precision 32 min <integer_cst 0x7ffff1889cd8 0> max <integer_cst 0x7ffff1889000 4294967295>> side-effects arg 0 <mult_expr 0x7ffff19de668 type <integer_type 0x7ffff188c1f8 sizetype> arg 0 <nop_expr 0x7ffff19abe00 type <integer_type 0x7ffff188c1f8 sizetype> arg 0 <parm_decl 0x7ffff19e0280 j>> arg 1 <nop_expr 0x7ffff19abde0 type <integer_type 0x7ffff188c1f8 sizetype> readonly arg 0 <var_decl 0x7ffff198d7e0 THREADS>>> timer_reduce.upc:4:19>> (gdb) p arg0 $27 = (tree) 0x7ffff19abee0 (gdb) pt warning: Expression is not an assignment (and might have no effect) <save_expr 0x7ffff19abee0 type <integer_type 0x7ffff188c1f8 sizetype public unsigned SI size <integer_cst 0x7ffff1889ca8 constant 32> unit size <integer_cst 0x7ffff1889cc0 constant 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff188c1f8 precision 32 min <integer_cst 0x7ffff1889cd8 0> max <integer_cst 0x7ffff1889000 4294967295>> side-effects arg 0 <mult_expr 0x7ffff19de668 type <integer_type 0x7ffff188c1f8 sizetype> arg 0 <nop_expr 0x7ffff19abe00 type <integer_type 0x7ffff188c1f8 sizetype> arg 0 <parm_decl 0x7ffff19e0280 j>> arg 1 <nop_expr 0x7ffff19abde0 type <integer_type 0x7ffff188c1f8 sizetype> readonly arg 0 <var_decl 0x7ffff198d7e0 THREADS>>> timer_reduce.upc:4:19> As shown, the type of arg0 is 'sizetype' and op0 is 'int'. After this rewrite is applied: fold_build2_loc (loc, EXACT_DIV_EXPR, type, arg0, arg1), the 'rhs1' type will be 'sizetype', but 'lhstype' and 'rhs2_type' will be 'int'. 3930 if (!useless_type_conversion_p (lhs_type, rhs1_type) 3931 || !useless_type_conversion_p (lhs_type, rhs2_type)) 3932 { 3933 error ("type mismatch in binary expression"); 3934 debug_generic_stmt (lhs_type); 3935 debug_generic_stmt (rhs1_type); 3936 debug_generic_stmt (rhs2_type); 3937 return true; 3938 } We need the type conversion encoded in op0: (gdb) p useless_type_conversion_p(type, TREE_TYPE(op0)) $28 = true (gdb) p useless_type_conversion_p(type, TREE_TYPE(arg0)) $29 = false useless_type_conversion_p() requires that the types agree in signedness and precesion. Perhaps this issue can be fixed by adding CEIL_DIV_EXPR and FLOOR_DIV_EXPR to the if statement at the beginning of fold_binary_loc(). Index: fold-const.c =================================================================== --- fold-const.c (revision 226135) +++ fold-const.c (working copy) @@ -9151,7 +9151,8 @@ fold_binary_loc (location_t loc, cases, the appropriate type conversions should be put back in the tree that will get out of the constant folder. */ - if (kind == tcc_comparison || code == MIN_EXPR || code == MAX_EXPR) + if (kind == tcc_comparison || code == MIN_EXPR || code == MAX_EXPR + code == CEIL_DIV_EXPR || code == FLOOR_DIV_EXPR) { STRIP_SIGN_NOPS (arg0); STRIP_SIGN_NOPS (arg1);