aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2023-06-26 03:24:27 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2023-06-26 03:32:13 +0200
commit0f54a73b998b72f7c8452a63730ec3b16fc47854 (patch)
tree2f113149700b09803f07fdc72cd036a3cca0b1ef
parent016047f54713dc601c661ab57c78a26da3759608 (diff)
d: Suboptimal codegen for __builtin_expect(cond, false)vendors/ARM/release-12.3.rel1
Since PR96435, both boolean objects and expressions have been evaluated in the following way. (*(ubyte*)&obj_or_expr) & 1 It has been noted that sometimes this can cause the back-end to optimize in non-obvious ways - in particular with __builtin_expect. This @safe feature is now restricted to just when reading the value of a bool field that comes from a union. PR d/110359 gcc/d/ChangeLog: * d-convert.cc (convert_for_rvalue): Only apply the @safe boolean conversion to boolean fields of a union. (convert_for_condition): Call convert_for_rvalue in the default case. gcc/testsuite/ChangeLog: * gdc.dg/pr110359.d: New test. (cherry picked from commit ab98db1e8c1b997414539f41b7fb814019497d8d)
-rw-r--r--gcc/d/d-convert.cc31
-rw-r--r--gcc/testsuite/gdc.dg/pr110359.d22
2 files changed, 41 insertions, 12 deletions
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index ec5da6c10a6..2023245256b 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -620,7 +620,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
return result ? result : convert (build_ctype (totype), exp);
}
-/* Return a TREE represenwation of EXPR, whose type has been converted from
+/* Return a TREE representation of EXPR, whose type has been converted from
* ETYPE to TOTYPE, and is being used in an rvalue context. */
tree
@@ -635,20 +635,27 @@ convert_for_rvalue (tree expr, Type *etype, Type *totype)
{
/* If casting from bool, the result is either 0 or 1, any other value
violates @safe code, so enforce that it is never invalid. */
- if (CONSTANT_CLASS_P (expr))
- result = d_truthvalue_conversion (expr);
- else
+ for (tree ref = expr; TREE_CODE (ref) == COMPONENT_REF;
+ ref = TREE_OPERAND (ref, 0))
{
- /* Reinterpret the boolean as an integer and test the first bit.
- The generated code should end up being equivalent to:
+ /* If the expression is a field that's part of a union, reinterpret
+ the boolean as an integer and test the first bit. The generated
+ code should end up being equivalent to:
*cast(ubyte *)&expr & 1; */
- machine_mode bool_mode = TYPE_MODE (TREE_TYPE (expr));
- tree mtype = lang_hooks.types.type_for_mode (bool_mode, 1);
- result = fold_build2 (BIT_AND_EXPR, mtype,
- build_vconvert (mtype, expr),
- build_one_cst (mtype));
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == UNION_TYPE)
+ {
+ machine_mode bool_mode = TYPE_MODE (TREE_TYPE (expr));
+ tree mtype = lang_hooks.types.type_for_mode (bool_mode, 1);
+ result = fold_build2 (BIT_AND_EXPR, mtype,
+ build_vconvert (mtype, expr),
+ build_one_cst (mtype));
+ break;
+ }
}
+ if (result == NULL_TREE)
+ result = d_truthvalue_conversion (expr);
+
result = convert (build_ctype (tbtype), result);
}
@@ -845,7 +852,7 @@ convert_for_condition (tree expr, Type *type)
break;
default:
- result = expr;
+ result = convert_for_rvalue (expr, type, type);
break;
}
diff --git a/gcc/testsuite/gdc.dg/pr110359.d b/gcc/testsuite/gdc.dg/pr110359.d
new file mode 100644
index 00000000000..bf69201d9a5
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr110359.d
@@ -0,0 +1,22 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110359
+// { dg-do compile }
+// { dg-options "-fdump-tree-original" }
+double pow(in double x, in ulong p)
+{
+ import gcc.builtins : __builtin_expect;
+ if (__builtin_expect(p == 0, false))
+ return 1;
+ if (__builtin_expect(p == 1, false))
+ return x;
+
+ double s = x;
+ double v = 1;
+ for (ulong i = p; i > 1; i >>= 1)
+ {
+ v = (i & 0x1) ? s * v : v;
+ s = s * s;
+ }
+ return v * s;
+}
+// { dg-final { scan-tree-dump "if \\(__builtin_expect \\(p == 0, 0\\) != 0\\)" "original" } }
+// { dg-final { scan-tree-dump "if \\(__builtin_expect \\(p == 1, 0\\) != 0\\)" "original" } }