https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104140
Roger Sayle <roger at nextmovesoftware dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2022-01-20 Assignee|unassigned at gcc dot gnu.org |roger at nextmovesoftware dot com --- Comment #1 from Roger Sayle <roger at nextmovesoftware dot com> --- Mine (perhaps?). To quote the review from my HIGHPART_MULT_EXPR patch: >+ if (optype != TREE_TYPE (mop2) > > I think mop1 and mop2 have to be compatible types (the tree-cfg.c > GIMPLE verification only tests for same precision it seems but tree.def > says they are of type T1). That said, I think optype != TREE_TYPE (mop2) > is superfluous and too conservative at it. It turns out that restoring this clause from the original patch submission resolves this ICE on a cross-compiler to riscv-unknown-linux-gnu. diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 1b6a57b..89a26dd 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -4600,7 +4600,8 @@ convert_mult_to_highpart (gassign *stmt, gimple_stmt_itera bool unsignedp = TYPE_UNSIGNED (optype); unsigned int prec = TYPE_PRECISION (optype); - if (unsignedp != TYPE_UNSIGNED (mtype) + if (optype != TREE_TYPE (mop2) + || unsignedp != TYPE_UNSIGNED (mtype) || TYPE_PRECISION (mtype) != 2 * prec) return false; It's odd that I'm unable to reproduce a similar failure on x86_64. Perhaps the above paranoid fix isn't the correct solution at all, as before/with it, I'm seeing: void g () { int x.0_2; unsigned int v.1_4; long long int _6; long long int _7; unsigned int _8; <bb 2> [local count: 1073741824]: x.0_2 = x; v.1_4 = v; _6 = x.0_2 w* v.1_4; _7 = _6 >> 32; _8 = (unsigned int) _7; u = _8; return; } Note the differing operand types to the widening multiplication. Perhaps the upstream widening multiplication perception is the true source of the problem, and just not being caught by verify_gimple like MULT_HIGHPART_EXPR is. More generally, "defensive programming", i.e. the use of seemingly superfluous tests that confirm assumed invariants isn't always a bad thing (in software as complex as GCC).