https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94261
Bug ID: 94261 Summary: [10 Regression] ICE in vect_get_vec_def_for_operand_1 for 3-element condition reduction Product: gcc Version: unknown Status: UNCONFIRMED Keywords: ice-on-valid-code Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: rsandifo at gcc dot gnu.org CC: rguenth at gcc dot gnu.org Target Milestone: --- Target: aarch64*-*-* The following test ICEs when compiled with -O3 -ffinite-math-only -march=armv8.2-a+sve on aarch64: void f (float *x, float *y, float z) { float res0 = 0, res1 = 1, res2 = 2; for (int i = 0; i < 100; ++i) { res0 = 100 <= y[i * 3] ? res0 : z; res1 = 101 <= y[i * 3 + 1] ? res1 : z; res2 = y[i * 3 + 2] < 102 ? z : res2; } x[0] = res0; x[1] = res1; x[2] = res2; } The ICE is: b.c:2:1: internal compiler error: in vect_get_vec_def_for_operand_1, at tree-vect-stmts.c:1555 2 | f (float *x, float *y, float z) | ^ 0x10a86c3 vect_get_vec_def_for_operand_1(_stmt_vec_info*, vect_def_type) gcc/tree-vect-stmts.c:1555 0x10af8e1 vect_get_vec_def_for_operand(tree_node*, _stmt_vec_info*, tree_node*) gcc/tree-vect-stmts.c:1617 0x10b258f vectorizable_condition gcc/tree-vect-stmts.c:10213 0x10d01ea vect_transform_stmt(_stmt_vec_info*, gimple_stmt_iterator*, _slp_tree*, _slp_instance*) gcc/tree-vect-stmts.c:11012 0x10d4226 vect_transform_loop_stmt gcc/tree-vect-loop.c:8307 0x10ec31a vect_transform_loop(_loop_vec_info*, gimple*) gcc/tree-vect-loop.c:8707 0x110f797 try_vectorize_loop_1 gcc/tree-vectorizer.c:990 0x1110319 vectorize_loops() gcc/tree-vectorizer.c:1126 The problem comes from trying both SVE and Advanced SIMD and eventually picking SVE. The SVE version can't treat the loop as a single 3-element SLP reduction because we don't yet support loading { 100, 101, 102 } repeating for variable-length vectors. We therefore fail the SLP build before doing anything about the awkward comparison arrangement. With this version, each ?: is a separate reduction and each one has its own, correct, STMT_VINFO_REDUC_IDX. But then we try the Advanced SIMD version. This doesn't have a problem with loading the constants, so we get as far as dealing with mismatched comparisons: /* Swap. */ if (*swap == 1) { swap_ssa_operands (stmt, &TREE_OPERAND (cond, 0), &TREE_OPERAND (cond, 1)); TREE_SET_CODE (cond, swap_tree_comparison (code)); } /* Invert. */ else { swap_ssa_operands (stmt, gimple_assign_rhs2_ptr (stmt), gimple_assign_rhs3_ptr (stmt)); if (STMT_VINFO_REDUC_IDX (stmt_info) == 1) STMT_VINFO_REDUC_IDX (stmt_info) = 2; else if (STMT_VINFO_REDUC_IDX (stmt_info) == 2) STMT_VINFO_REDUC_IDX (stmt_info) = 1; bool honor_nans = HONOR_NANS (TREE_OPERAND (cond, 0)); code = invert_tree_comparison (TREE_CODE (cond), honor_nans); gcc_assert (code != ERROR_MARK); TREE_SET_CODE (cond, code); } But these changes to the gimple stmt persist even if the SLP build fails later, or if the SLP build succeeds and we decide not to vectorise that way. That doesn't matter too much for the current loop_vinfo, because the STMT_VINFO_REDUC_IDXs are still consistent with the gimple stmt. But it means that the STMT_VINFO_REDUC_IDXs for the older SVE loop_vinfo are now no longer correct. The ICE triggers when we go back to the SVE loop_vinfo as the cheapest implementation and try to code-generate the reduction. The testcase is reduced from 481.wrf compiled with LTO.