tree-optimization/123040 - handle nary -> ifn simplification in VN

The following handles (by rejecting) simplifications that end up
turning a VN NARY operation into a call which would be a VN REFERENCE
and is unexpected and not handled.

	PR tree-optimization/123040
	* tree-ssa-sccvn.cc (vn_nary_build_or_lookup_1): Only insert
	nary results.

	* g++.dg/torture/pr123040.C: New testcase.
This commit is contained in:
Richard Biener
2025-12-08 11:06:54 +01:00
committed by Richard Biener
parent 09bece00d0
commit 5a6d911ca2
2 changed files with 65 additions and 1 deletions

View File

@@ -0,0 +1,61 @@
// { dg-do compile }
template <int kBytes, typename From, typename To>
void CopyBytes(From from, To to) {
__builtin_memcpy(to, from, kBytes);
}
template <typename From, typename To> void CopySameSize(From *from, To to) {
CopyBytes<sizeof(From)>(from, to);
}
template <typename> using MakeUnsigned = char;
template <typename Lane, int N> struct Simd {
using T = Lane;
static constexpr int kPrivateLanes = N;
template <typename NewT> using Rebind = Simd<NewT, 0>;
};
template <class D> using TFromD = D::T;
template <class T, class D> using Rebind = D::template Rebind<T>;
template <class D> using RebindToUnsigned = Rebind<MakeUnsigned<D>, D>;
template <typename T, int> struct Vec128 {
using PrivateT = T;
static constexpr int kPrivateN = 6;
T raw[16];
};
template <class V> using DFromV = Simd<typename V::PrivateT, V::kPrivateN>;
template <class D> Vec128<TFromD<D>, D::kPrivateLanes> Zero(D);
template <class D> using VFromD = decltype(Zero(D()));
template <class D, class VFrom> VFromD<D> BitCast(D, VFrom v) {
VFromD<D> to;
CopySameSize(&v, to.raw);
return to;
}
template <int N> Vec128<signed char, N> And(Vec128<signed char, N> b) {
Vec128<signed char, N> a;
DFromV<decltype(a)> d;
RebindToUnsigned<decltype(d)> du;
auto au(a);
auto bu = BitCast(du, b);
for (int i = 0; i < N; ++i)
au.raw[i] &= bu.raw[i];
return au;
}
void Or(Vec128<signed char, 16>);
template <int N> void IfVecThenElse(Vec128<signed char, N> yes) {
Vec128 __trans_tmp_2 = And(yes);
Or(__trans_tmp_2);
}
template <int N> void IfThenElseZero(Vec128<signed char, N> yes) {
IfVecThenElse(yes);
}
Vec128<signed char, 16> Abs_a;
char MaskedAbs___trans_tmp_5;
void MaskedAbs() {
Vec128<signed char, 16> __trans_tmp_4;
for (int i = 0; i < 16; ++i) {
MaskedAbs___trans_tmp_5 = Abs_a.raw[i] ? -Abs_a.raw[i] : 0;
Abs_a.raw[i] = MaskedAbs___trans_tmp_5;
}
__trans_tmp_4 = Abs_a;
Vec128 __trans_tmp_3 = __trans_tmp_4;
IfThenElseZero(__trans_tmp_3);
}

View File

@@ -2527,7 +2527,10 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert,
else
{
tree val = vn_lookup_simplify_result (res_op);
if (!val && insert)
/* ??? In weird cases we can end up with internal-fn calls,
but this isn't expected so throw the result away. See
PR123040 for an example. */
if (!val && insert && res_op->code.is_tree_code ())
{
gimple_seq stmts = NULL;
result = maybe_push_res_to_seq (res_op, &stmts);