diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2018-05-22 12:25:44 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2018-05-22 12:25:44 +0000 |
commit | 440ed9f839a068948c72441eda2ef3da515f4656 (patch) | |
tree | 54e8716f0c7fc3013557e980c5c8beb7ed532381 /gcc/internal-fn.c | |
parent | 81d5198d0093ab144c8a13b85c56ef496192f930 (diff) | |
download | gcc-440ed9f839a068948c72441eda2ef3da515f4656.zip gcc-440ed9f839a068948c72441eda2ef3da515f4656.tar.gz gcc-440ed9f839a068948c72441eda2ef3da515f4656.tar.bz2 |
Handle a null lhs in expand_direct_optab_fn (PR85862)
This PR showed that the normal function for expanding directly-mapped
internal functions didn't handle the case in which the call was only
being kept for its side-effects.
2018-05-22 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
PR middle-end/85862
* internal-fn.c (expand_direct_optab_fn): Cope with a null lhs.
gcc/testsuite/
PR middle-end/85862
* gcc.dg/torture/pr85862.c: New test.
From-SVN: r260504
Diffstat (limited to 'gcc/internal-fn.c')
-rw-r--r-- | gcc/internal-fn.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index b2c4a31..bb4404e 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -2891,14 +2891,15 @@ expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab, insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first)); tree lhs = gimple_call_lhs (stmt); - tree lhs_type = TREE_TYPE (lhs); - rtx lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); + rtx lhs_rtx = NULL_RTX; + if (lhs) + lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); /* Do not assign directly to a promoted subreg, since there is no guarantee that the instruction will leave the upper bits of the register in the state required by SUBREG_PROMOTED_SIGN. */ rtx dest = lhs_rtx; - if (GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest)) + if (dest && GET_CODE (dest) == SUBREG && SUBREG_PROMOTED_VAR_P (dest)) dest = NULL_RTX; create_output_operand (&ops[0], dest, insn_data[icode].operand[0].mode); @@ -2917,7 +2918,7 @@ expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab, } expand_insn (icode, nargs + 1, ops); - if (!rtx_equal_p (lhs_rtx, ops[0].value)) + if (lhs_rtx && !rtx_equal_p (lhs_rtx, ops[0].value)) { /* If the return value has an integral type, convert the instruction result to that type. This is useful for things that return an @@ -2931,7 +2932,7 @@ expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab, /* If this is a scalar in a register that is stored in a wider mode than the declared mode, compute the result into its declared mode and then convert to the wider mode. */ - gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type)); + gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs))); rtx tmp = convert_to_mode (GET_MODE (lhs_rtx), ops[0].value, 0); convert_move (SUBREG_REG (lhs_rtx), tmp, SUBREG_PROMOTED_SIGN (lhs_rtx)); @@ -2940,7 +2941,7 @@ expand_direct_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab, emit_move_insn (lhs_rtx, ops[0].value); else { - gcc_checking_assert (INTEGRAL_TYPE_P (lhs_type)); + gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (lhs))); convert_move (lhs_rtx, ops[0].value, 0); } } |