aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2025-03-03 14:53:03 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2025-03-03 14:59:14 +0100
commitd05b64bdd048ffb7f72d97553888934a9bcd13fa (patch)
tree50bacb91ead5c3a7056df309afb177cb9aeb5c8e
parent758de6263dfc7ba8701965fa468691ac23cb7eb5 (diff)
downloadgcc-d05b64bdd048ffb7f72d97553888934a9bcd13fa.zip
gcc-d05b64bdd048ffb7f72d97553888934a9bcd13fa.tar.gz
gcc-d05b64bdd048ffb7f72d97553888934a9bcd13fa.tar.bz2
ipa-vr: Handle non-conversion unary ops separately from conversions (PR 118785)
Since we construct arithmetic jump functions even when there is a type conversion in between the operation encoded in the jump function and when it is passed in a call argument, the IPA propagation phase must also perform the operation and conversion in two steps. IPA-VR had actually been doing it even before for binary operations but, as PR 118756 exposes, not in the case on unary operations. This patch adds the necessary step to rectify that. Like in the scalar constant case, we depend on expr_type_first_operand_type_p to determine the type of the result of the arithmetic operation. On top this, the patch special-cases ABSU_EXPR because it looks useful an so that the PR testcase exercises the added code-path. This seems most appropriate for stage 4, long term we should probably stream the types, probably after also encoding them with a string of expr_eval_op rather than what we have today. A check for expr_type_first_operand_type_p was also missing in the handling of binary ops and the intermediate value_range was initialized with a wrong type, so I also fixed this. gcc/ChangeLog: 2025-02-24 Martin Jambor <mjambor@suse.cz> PR ipa/118785 * ipa-cp.cc (ipa_vr_intersect_with_arith_jfunc): Handle non-conversion unary operations separately before doing any conversions. Check expr_type_first_operand_type_p for non-unary operations too. Fix type of op_res. gcc/testsuite/ChangeLog: 2025-02-24 Martin Jambor <mjambor@suse.cz> PR ipa/118785 * g++.dg/lto/pr118785_0.C: New test.
-rw-r--r--gcc/ipa-cp.cc45
-rw-r--r--gcc/testsuite/g++.dg/lto/pr118785_0.C14
2 files changed, 56 insertions, 3 deletions
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 68959f2..3c994f2 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1720,8 +1720,45 @@ ipa_vr_intersect_with_arith_jfunc (vrange &vr,
enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
if (TREE_CODE_CLASS (operation) == tcc_unary)
{
+ value_range op_res;
+ const value_range *inter_vr;
+ if (operation != NOP_EXPR)
+ {
+ /* Since we construct arithmetic jump functions even when there is a
+ type conversion in between the operation encoded in the jump
+ function and when it is passed in a call argument, the IPA
+ propagation phase must also perform the operation and conversion
+ in two separate steps.
+
+ TODO: In order to remove the use of expr_type_first_operand_type_p
+ predicate we would need to stream the operation type, ideally
+ encoding the whole jump function as a series of expr_eval_op
+ structures. */
+
+ tree operation_type;
+ if (expr_type_first_operand_type_p (operation))
+ operation_type = src_type;
+ else if (operation == ABSU_EXPR)
+ operation_type = unsigned_type_for (src_type);
+ else
+ return;
+ op_res.set_varying (operation_type);
+ if (!ipa_vr_operation_and_type_effects (op_res, src_vr, operation,
+ operation_type, src_type))
+ return;
+ if (src_type == dst_type)
+ {
+ vr.intersect (op_res);
+ return;
+ }
+ inter_vr = &op_res;
+ src_type = operation_type;
+ }
+ else
+ inter_vr = &src_vr;
+
value_range tmp_res (dst_type);
- if (ipa_vr_operation_and_type_effects (tmp_res, src_vr, operation,
+ if (ipa_vr_operation_and_type_effects (tmp_res, *inter_vr, NOP_EXPR,
dst_type, src_type))
vr.intersect (tmp_res);
return;
@@ -1737,10 +1774,12 @@ ipa_vr_intersect_with_arith_jfunc (vrange &vr,
tree operation_type;
if (TREE_CODE_CLASS (operation) == tcc_comparison)
operation_type = boolean_type_node;
- else
+ else if (expr_type_first_operand_type_p (operation))
operation_type = src_type;
+ else
+ return;
- value_range op_res (dst_type);
+ value_range op_res (operation_type);
if (!ipa_vr_supported_type_p (operation_type)
|| !handler.operand_check_p (operation_type, src_type, op_vr.type ())
|| !handler.fold_range (op_res, operation_type, src_vr, op_vr))
diff --git a/gcc/testsuite/g++.dg/lto/pr118785_0.C b/gcc/testsuite/g++.dg/lto/pr118785_0.C
new file mode 100644
index 0000000..cdcc1dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr118785_0.C
@@ -0,0 +1,14 @@
+// { dg-lto-do link }
+// { dg-require-effective-target fpic }
+// { dg-lto-options { "-O3 -flto -fPIC" } }
+
+void WriteLiteral( unsigned long data, unsigned long bits) {}
+void WriteQIndexDelta( short qDelta)
+{
+ WriteLiteral(__builtin_abs(qDelta), 4);
+}
+__attribute((used))
+void ff(signed char *qIndexDeltaLumaDC) {
+ WriteQIndexDelta(*qIndexDeltaLumaDC);
+}
+int main(){}