Message ID | 53AA7864.9020500@linaro.org |
---|---|
State | New |
Headers | show |
On Wed, Jun 25, 2014 at 05:21:08PM +1000, Kugan wrote: > The problem with SRP_POINTER 0, SRP_SIGNED 1, SRP_UNSIGNED 2, > SRP_SIGNED_AND_UNSIGNED 3 (as I understand) is that, it will be > incompatible with TYPE_UNSIGNED (tree) and defines of > POINTER_EXTEND_UNSIGNED values. We will have to then translate while > setting to SRP_* values . Also SUBREG_PROMOTED_SIGNED_P is now checked > in some cases for != 0 (meaning SRP_POINTER or SRP_UNSIGNED) and in some > cases > 0 (meaning SRP_UNSIGNED). > > Since our aim is to perform single bit checks, why don’t we just use > this representation internally (i.e. _rtx->unchanging = 1 if SRP_SIGNED > and _rtx->volatil = 1 if SRP_UNSIGNED). As for SUBREG_PROMOTED_SIGNED_P, > we still have to return -1 or 1 depending on SRP_POINTER or SRP_UNSIGNED. Why don't you make SUBREG_PROMOTED_UNSIGNED_P just return 0/1 (i.e. the single bit), and for places where it would like to match both SRP_UNSIGNED and SRP_POINTER use SUBREG_PROMOTED_GET () & SRP_UNSIGNED or so? > --- a/gcc/ifcvt.c > +++ b/gcc/ifcvt.c > @@ -1448,8 +1448,11 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, > || byte_vtrue != byte_vfalse > || (SUBREG_PROMOTED_VAR_P (vtrue) > != SUBREG_PROMOTED_VAR_P (vfalse)) > - || (SUBREG_PROMOTED_UNSIGNED_P (vtrue) > - != SUBREG_PROMOTED_UNSIGNED_P (vfalse))) > + || ((SUBREG_PROMOTED_UNSIGNED_P (vtrue) > + != SUBREG_PROMOTED_UNSIGNED_P (vfalse)) > + && (SUBREG_PROMOTED_SIGNED_P (vtrue) > + != SUBREG_PROMOTED_SIGNED_P (vfalse)))) Shouldn't this be SUBREG_PROMOTED_GET (vtrue) != SUBREG_PROMOTED_GET (vfalse) ? > +const unsigned int SRP_POINTER = -1; > +const unsigned int SRP_SIGNED = 0; Inconsistent whitespace, just use space instead of multiple spaces and/or tabs. > +const unsigned int SRP_UNSIGNED = 1; > +const unsigned int SRP_SIGNED_AND_UNSIGNED = 2; > +/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted > + for SIGNED type. */ > +#define SUBREG_PROMOTED_SIGNED_P(RTX) \ > + (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_SIGNED_P", (RTX), SUBREG)->unchanging == 1) Why the " == 1" ? > + > +/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted > + for UNSIGNED type. In case of SRP_POINTER, SUBREG_PROMOTED_UNSIGNED_P > + returns -1 as this is in most cases handled like unsigned extension, > + except for generating instructions where special code is emitted for > + (ptr_extend insns) on some architectures. */ > #define SUBREG_PROMOTED_UNSIGNED_P(RTX) \ > - ((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \ > - ? -1 : (int) (RTX)->unchanging) > + ((((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil)\ > + + (RTX)->unchanging) == 0) ? -1 : ((RTX)->volatil == 1)) > + > +/* Checks if RTX of SUBREG_PROMOTED_VAR_P() is promotd for given SIGN. */ > +#define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \ Use space rather than tab. Also, why do we need this macro? Can't you just use SUBREG_PROMOTED_GET () == sign ? I mean, sign in that case is typically just 0 or 1. Jakub
On 25/06/14 17:50, Jakub Jelinek wrote: > On Wed, Jun 25, 2014 at 05:21:08PM +1000, Kugan wrote: >> The problem with SRP_POINTER 0, SRP_SIGNED 1, SRP_UNSIGNED 2, >> SRP_SIGNED_AND_UNSIGNED 3 (as I understand) is that, it will be >> incompatible with TYPE_UNSIGNED (tree) and defines of >> POINTER_EXTEND_UNSIGNED values. We will have to then translate while >> setting to SRP_* values . Also SUBREG_PROMOTED_SIGNED_P is now checked >> in some cases for != 0 (meaning SRP_POINTER or SRP_UNSIGNED) and in some >> cases > 0 (meaning SRP_UNSIGNED). >> >> Since our aim is to perform single bit checks, why don’t we just use >> this representation internally (i.e. _rtx->unchanging = 1 if SRP_SIGNED >> and _rtx->volatil = 1 if SRP_UNSIGNED). As for SUBREG_PROMOTED_SIGNED_P, >> we still have to return -1 or 1 depending on SRP_POINTER or SRP_UNSIGNED. > > Why don't you make SUBREG_PROMOTED_UNSIGNED_P just return 0/1 (i.e. the > single bit), and for places where it would like to match both > SRP_UNSIGNED and SRP_POINTER use SUBREG_PROMOTED_GET () & SRP_UNSIGNED > or so? If we use SUBREG_PROMOTED_GET () & SRP_UNSIGNED, we will miss the case SRP_SIGNED_AND_UNSIGNED. Though this is not wrong, we might miss some optimization opportunities here. We can however use (SUBREG_PROMOTED_GET () != SRP_SIGNED) if you like this. Other option is to define another macro that explicilty says some think like SUBREG_PROMOTED_POINTER_OR_UNSIGNED_P. >> --- a/gcc/ifcvt.c >> +++ b/gcc/ifcvt.c >> @@ -1448,8 +1448,11 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, >> || byte_vtrue != byte_vfalse >> || (SUBREG_PROMOTED_VAR_P (vtrue) >> != SUBREG_PROMOTED_VAR_P (vfalse)) >> - || (SUBREG_PROMOTED_UNSIGNED_P (vtrue) >> - != SUBREG_PROMOTED_UNSIGNED_P (vfalse))) >> + || ((SUBREG_PROMOTED_UNSIGNED_P (vtrue) >> + != SUBREG_PROMOTED_UNSIGNED_P (vfalse)) >> + && (SUBREG_PROMOTED_SIGNED_P (vtrue) >> + != SUBREG_PROMOTED_SIGNED_P (vfalse)))) > > Shouldn't this be SUBREG_PROMOTED_GET (vtrue) != SUBREG_PROMOTED_GET (vfalse) ? The reason why I checked like this to cover one side with SRP_SIGNED_AND_UNSIGNED and other with SRP_SIGNED or SRP_UNSIGNED. If we check SUBREG_PROMOTED_GET (vtrue) != SUBREG_PROMOTED_GET (vfalse) we will miss that. >> + >> +/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted >> + for UNSIGNED type. In case of SRP_POINTER, SUBREG_PROMOTED_UNSIGNED_P >> + returns -1 as this is in most cases handled like unsigned extension, >> + except for generating instructions where special code is emitted for >> + (ptr_extend insns) on some architectures. */ >> #define SUBREG_PROMOTED_UNSIGNED_P(RTX) \ >> - ((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \ >> - ? -1 : (int) (RTX)->unchanging) >> + ((((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil)\ >> + + (RTX)->unchanging) == 0) ? -1 : ((RTX)->volatil == 1)) >> + >> +/* Checks if RTX of SUBREG_PROMOTED_VAR_P() is promotd for given SIGN. */ >> +#define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \ > > Use space rather than tab. Also, why do we need this macro? > Can't you just use SUBREG_PROMOTED_GET () == sign ? I mean, sign in that > case is typically just 0 or 1. Again I wanted to cover SRP_SIGNED_AND_UNSIGNED as well in this case. Thanks, Kugan
On Thu, Jun 26, 2014 at 11:06:26AM +1000, Kugan wrote: > >> Since our aim is to perform single bit checks, why don’t we just use > >> this representation internally (i.e. _rtx->unchanging = 1 if SRP_SIGNED > >> and _rtx->volatil = 1 if SRP_UNSIGNED). As for SUBREG_PROMOTED_SIGNED_P, > >> we still have to return -1 or 1 depending on SRP_POINTER or SRP_UNSIGNED. > > > > Why don't you make SUBREG_PROMOTED_UNSIGNED_P just return 0/1 (i.e. the > > single bit), and for places where it would like to match both > > SRP_UNSIGNED and SRP_POINTER use SUBREG_PROMOTED_GET () & SRP_UNSIGNED > > or so? > > If we use SUBREG_PROMOTED_GET () & SRP_UNSIGNED, we will miss > the case SRP_SIGNED_AND_UNSIGNED. Though this is not wrong, we might > miss some optimization opportunities here. We can however use > (SUBREG_PROMOTED_GET () != SRP_SIGNED) if you like this. Other option is > to define another macro that explicilty says some think like > SUBREG_PROMOTED_POINTER_OR_UNSIGNED_P. Ok, sure, if you want to make the test pass for SRP_UNSIGNED, SRP_POINTER and SRP_UNSIGNED_AND_SIGNED, then != SRP_SIGNED is the right thing. What I wanted is make SUBREG_PROMOTED_UNSIGNED_P be a 0/1 again. > >> --- a/gcc/ifcvt.c > >> +++ b/gcc/ifcvt.c > >> @@ -1448,8 +1448,11 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, > >> || byte_vtrue != byte_vfalse > >> || (SUBREG_PROMOTED_VAR_P (vtrue) > >> != SUBREG_PROMOTED_VAR_P (vfalse)) > >> - || (SUBREG_PROMOTED_UNSIGNED_P (vtrue) > >> - != SUBREG_PROMOTED_UNSIGNED_P (vfalse))) > >> + || ((SUBREG_PROMOTED_UNSIGNED_P (vtrue) > >> + != SUBREG_PROMOTED_UNSIGNED_P (vfalse)) > >> + && (SUBREG_PROMOTED_SIGNED_P (vtrue) > >> + != SUBREG_PROMOTED_SIGNED_P (vfalse)))) > > > > Shouldn't this be SUBREG_PROMOTED_GET (vtrue) != SUBREG_PROMOTED_GET (vfalse) ? > > The reason why I checked like this to cover one side with > SRP_SIGNED_AND_UNSIGNED and other with SRP_SIGNED or SRP_UNSIGNED. If > we check SUBREG_PROMOTED_GET (vtrue) != SUBREG_PROMOTED_GET (vfalse) we > will miss that. What you have above is just wrong though. Either you need to make sure the flags are the same (i.e. GET != GET), and keep the SET a few lines below as is, or you would allow (some?) mismatches of the promotion flags, but in that case you'd need to deal with it in the SET conservatively. Like, if one is SRP_SIGNED_AND_UNSIGNED and another one is just SRP_SIGNED or just SRP_UNSIGNED, you'd use the simpler one, if one is promoted and another one is not, you'd not make the SUBREG promoted at all, etc. Not worth it IMHO, at least not for now. > > >> + > >> +/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted > >> + for UNSIGNED type. In case of SRP_POINTER, SUBREG_PROMOTED_UNSIGNED_P > >> + returns -1 as this is in most cases handled like unsigned extension, > >> + except for generating instructions where special code is emitted for > >> + (ptr_extend insns) on some architectures. */ > >> #define SUBREG_PROMOTED_UNSIGNED_P(RTX) \ > >> - ((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \ > >> - ? -1 : (int) (RTX)->unchanging) > >> + ((((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil)\ > >> + + (RTX)->unchanging) == 0) ? -1 : ((RTX)->volatil == 1)) > >> + > >> +/* Checks if RTX of SUBREG_PROMOTED_VAR_P() is promotd for given SIGN. */ > >> +#define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \ > > > > Use space rather than tab. Also, why do we need this macro? > > Can't you just use SUBREG_PROMOTED_GET () == sign ? I mean, sign in that > > case is typically just 0 or 1. > > Again I wanted to cover SRP_SIGNED_AND_UNSIGNED as well in this case. Ah, ok. It is fine as is (with the whitespace change). Jakub
diff --git a/gcc/calls.c b/gcc/calls.c index 78fe7d8..a3e6faa 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1484,8 +1484,7 @@ precompute_arguments (int num_actuals, struct arg_data *args) args[i].initial_value = gen_lowpart_SUBREG (mode, args[i].value); SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value, - args[i].unsignedp); + SUBREG_PROMOTED_SET (args[i].initial_value, args[i].unsignedp); } } } @@ -3365,7 +3364,7 @@ expand_call (tree exp, rtx target, int ignore) target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset); SUBREG_PROMOTED_VAR_P (target) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp); + SUBREG_PROMOTED_SET (target, unsignedp); } /* If size of args is variable or this was a constructor call for a stack diff --git a/gcc/expr.c b/gcc/expr.c index 512c024..da02a06 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -329,7 +329,7 @@ convert_move (rtx to, rtx from, int unsignedp) if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from) && (GET_MODE_PRECISION (GET_MODE (SUBREG_REG (from))) >= GET_MODE_PRECISION (to_mode)) - && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp) + && SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp)) from = gen_lowpart (to_mode, from), from_mode = to_mode; gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to)); @@ -703,7 +703,7 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x) && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode) - && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp) + && SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp)) x = gen_lowpart (mode, SUBREG_REG (x)); if (GET_MODE (x) != VOIDmode) @@ -5202,8 +5202,8 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal) && GET_MODE_PRECISION (GET_MODE (target)) == TYPE_PRECISION (TREE_TYPE (exp))) { - if (TYPE_UNSIGNED (TREE_TYPE (exp)) - != SUBREG_PROMOTED_UNSIGNED_P (target)) + if (!SUBREG_CHECK_PROMOTED_SIGN (target, + TYPE_UNSIGNED (TREE_TYPE (exp)))) { /* Some types, e.g. Fortran's logical*4, won't have a signed version, so use the mode instead. */ @@ -9513,7 +9513,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, temp = gen_lowpart_SUBREG (mode, decl_rtl); SUBREG_PROMOTED_VAR_P (temp) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp); + SUBREG_PROMOTED_SET (temp, unsignedp); return temp; } diff --git a/gcc/function.c b/gcc/function.c index 441289e..9509622 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3093,7 +3093,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, /* The argument is already sign/zero extended, so note it into the subreg. */ SUBREG_PROMOTED_VAR_P (tempreg) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (tempreg, unsignedp); + SUBREG_PROMOTED_SET (tempreg, unsignedp); } /* TREE_USED gets set erroneously during expand_assignment. */ diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 816cdaa..b2a0574 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -1448,8 +1448,11 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, || byte_vtrue != byte_vfalse || (SUBREG_PROMOTED_VAR_P (vtrue) != SUBREG_PROMOTED_VAR_P (vfalse)) - || (SUBREG_PROMOTED_UNSIGNED_P (vtrue) - != SUBREG_PROMOTED_UNSIGNED_P (vfalse))) + || ((SUBREG_PROMOTED_UNSIGNED_P (vtrue) + != SUBREG_PROMOTED_UNSIGNED_P (vfalse)) + && (SUBREG_PROMOTED_SIGNED_P (vtrue) + != SUBREG_PROMOTED_SIGNED_P (vfalse)))) + return NULL_RTX; promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue)); @@ -1463,7 +1466,7 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue); SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue); - SUBREG_PROMOTED_UNSIGNED_SET (target, SUBREG_PROMOTED_UNSIGNED_P (vtrue)); + SUBREG_PROMOTED_SET (target, SUBREG_PROMOTED_GET (vtrue)); emit_move_insn (x, target); return x; } diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 78f59d6..4e0b964 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -584,12 +584,12 @@ ubsan_expand_si_overflow_mul_check (gimple stmt) if (GET_CODE (lopart0) == SUBREG) { SUBREG_PROMOTED_VAR_P (lopart0) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (lopart0, 0); + SUBREG_PROMOTED_SET (lopart0, 0); } if (GET_CODE (lopart1) == SUBREG) { SUBREG_PROMOTED_VAR_P (lopart1) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (lopart1, 0); + SUBREG_PROMOTED_SET (lopart1, 0); } tree halfstype = build_nonstandard_integer_type (hprec, 0); ops.op0 = make_tree (halfstype, lopart0); diff --git a/gcc/optabs.c b/gcc/optabs.c index ca1c194..a00b383 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -368,7 +368,7 @@ widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode, a promoted object differs from our extension. */ if (! no_extend || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op) - && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp)) + && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp))) return convert_modes (mode, oldmode, op, unsignedp); /* If MODE is no wider than a single word, we return a lowpart or paradoxical diff --git a/gcc/rtl.h b/gcc/rtl.h index 6ec91a8..edb449b 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1585,29 +1585,71 @@ get_full_set_src_cost (rtx x, struct full_rtx_costs *c) #define SUBREG_PROMOTED_VAR_P(RTX) \ (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED", (RTX), SUBREG)->in_struct) -#define SUBREG_PROMOTED_UNSIGNED_SET(RTX, VAL) \ -do { \ - rtx const _rtx = RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_SET", \ - (RTX), SUBREG); \ - if ((VAL) < 0) \ - _rtx->volatil = 1; \ - else { \ - _rtx->volatil = 0; \ - _rtx->unchanging = (VAL); \ - } \ -} while (0) - /* Valid for subregs which are SUBREG_PROMOTED_VAR_P(). In that case this gives the necessary extensions: - 0 - signed - 1 - normal unsigned + 0 - signed (SPR_SIGNED) + 1 - normal unsigned (SPR_UNSIGNED) + 2 - value is both sign and unsign extended for mode + (SPR_SIGNED_AND_UNSIGNED). -1 - pointer unsigned, which most often can be handled like unsigned extension, except for generating instructions where we need to - emit special code (ptr_extend insns) on some architectures. */ + emit special code (ptr_extend insns) on some architectures + (SPR_POINTER). */ + +const unsigned int SRP_POINTER = -1; +const unsigned int SRP_SIGNED = 0; +const unsigned int SRP_UNSIGNED = 1; +const unsigned int SRP_SIGNED_AND_UNSIGNED = 2; + +/* Sets promoted mode for SUBREG_PROMOTED_VAR_P(). */ +#define SUBREG_PROMOTED_SET(RTX, VAL) \ +do { \ + rtx const _rtx = RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_SET", \ + (RTX), SUBREG); \ + switch ((VAL)) \ + { \ + case SRP_POINTER: \ + _rtx->volatil = 0; \ + _rtx->unchanging = 0; \ + break; \ + case SRP_SIGNED: \ + _rtx->volatil = 0; \ + _rtx->unchanging = 1; \ + break; \ + case SRP_UNSIGNED: \ + _rtx->volatil = 1; \ + _rtx->unchanging = 0; \ + break; \ + case SRP_SIGNED_AND_UNSIGNED: \ + _rtx->volatil = 1; \ + _rtx->unchanging = 1; \ + break; \ + } \ +} while (0) +/* Gets promoted mode for SUBREG_PROMOTED_VAR_P(). */ +#define SUBREG_PROMOTED_GET(RTX) \ + (2 * (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_GET", (RTX), SUBREG)->volatil)\ + + (RTX)->unchanging - 1) + +/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted + for SIGNED type. */ +#define SUBREG_PROMOTED_SIGNED_P(RTX) \ + (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_SIGNED_P", (RTX), SUBREG)->unchanging == 1) + +/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted + for UNSIGNED type. In case of SRP_POINTER, SUBREG_PROMOTED_UNSIGNED_P + returns -1 as this is in most cases handled like unsigned extension, + except for generating instructions where special code is emitted for + (ptr_extend insns) on some architectures. */ #define SUBREG_PROMOTED_UNSIGNED_P(RTX) \ - ((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil) \ - ? -1 : (int) (RTX)->unchanging) + ((((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil)\ + + (RTX)->unchanging) == 0) ? -1 : ((RTX)->volatil == 1)) + +/* Checks if RTX of SUBREG_PROMOTED_VAR_P() is promotd for given SIGN. */ +#define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \ + ((SIGN) ? SUBREG_PROMOTED_UNSIGNED_P ((RTX)) \ + : SUBREG_PROMOTED_SIGNED_P ((RTX))) \ /* True if the subreg was generated by LRA for reload insns. Such subregs are valid only during LRA. */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 82cfc1bf..547bdbf 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -4619,7 +4619,7 @@ num_sign_bit_copies1 (const_rtx x, enum machine_mode mode, const_rtx known_x, and we are looking at it in a wider mode, we know that at least the high-order bits are known to be sign bit copies. */ - if (SUBREG_PROMOTED_VAR_P (x) && ! SUBREG_PROMOTED_UNSIGNED_P (x)) + if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_SIGNED_P (x)) { num0 = cached_num_sign_bit_copies (SUBREG_REG (x), mode, known_x, known_mode, known_ret); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 181b56f..81d196f 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -1352,7 +1352,7 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op) target mode is the same as the variable's promotion. */ if (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op) - && ! SUBREG_PROMOTED_UNSIGNED_P (op) + && SUBREG_PROMOTED_SIGNED_P (op) && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) { temp = rtl_hooks.gen_lowpart_no_emit (mode, op); @@ -5595,8 +5595,7 @@ simplify_subreg (enum machine_mode outermode, rtx op, && subreg_lowpart_p (newx)) { SUBREG_PROMOTED_VAR_P (newx) = 1; - SUBREG_PROMOTED_UNSIGNED_SET - (newx, SUBREG_PROMOTED_UNSIGNED_P (op)); + SUBREG_PROMOTED_SET (newx, SUBREG_PROMOTED_GET (op)); } return newx; }