]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
expand: Fix up expand_cond_expr_using_cmove [PR106030]
authorJakub Jelinek <jakub@redhat.com>
Tue, 21 Jun 2022 09:38:59 +0000 (11:38 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 21 Jun 2022 09:38:59 +0000 (11:38 +0200)
If expand_cond_expr_using_cmove can't find a cmove optab for a particular
mode, it tries to promote the mode and perform the cmove in the promoted
mode.

The testcase in the patch ICEs on arm because in that case we pass temp which
has the promoted mode (SImode) as target to expand_operands where the
operands have the non-promoted mode (QImode).
Later on the function uses paradoxical subregs:
  if (GET_MODE (op1) != mode)
    op1 = gen_lowpart (mode, op1);

  if (GET_MODE (op2) != mode)
    op2 = gen_lowpart (mode, op2);
to change the operand modes.

The following patch fixes it by passing NULL_RTX as target if it has
promoted mode.

2022-06-21  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/106030
* expr.cc (expand_cond_expr_using_cmove): Pass NULL_RTX instead of
temp to expand_operands if mode has been promoted.

* gcc.c-torture/compile/pr106030.c: New test.

gcc/expr.cc
gcc/testsuite/gcc.c-torture/compile/pr106030.c [new file with mode: 0644]

index 78c839ab425bdf81a7c9e506dddfd0cabb25fe8c..c90cde35006bf44b560cdb2ecb6cfc113bf3fb89 100644 (file)
@@ -8832,7 +8832,8 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
   expanding_cond_expr_using_cmove = true;
   start_sequence ();
   expand_operands (treeop1, treeop2,
-                  temp, &op1, &op2, EXPAND_NORMAL);
+                  mode == orig_mode ? temp : NULL_RTX, &op1, &op2,
+                  EXPAND_NORMAL);
 
   if (TREE_CODE (treeop0) == SSA_NAME
       && (srcstmt = get_def_for_expr_class (treeop0, tcc_comparison)))
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106030.c b/gcc/testsuite/gcc.c-torture/compile/pr106030.c
new file mode 100644 (file)
index 0000000..7514b34
--- /dev/null
@@ -0,0 +1,16 @@
+/* PR middle-end/106030 */
+
+int a, b, c;
+
+char
+foo (int x, int y)
+{
+  return x * y;
+}
+
+void
+bar (void)
+{
+  char d = (foo <= b) * a;
+  c = foo (2 != bar, d);
+}