insv, extv and eztzv modify or read a field in a register or memory. The field always has a scalar integer mode, while the register or memory either has a scalar integer mode or BLKmode. The mode of the bit position is also a scalar integer.
This patch uses the type system to make that explicit. 2017-07-13 Richard Sandiford <richard.sandif...@linaro.org> Alan Hayward <alan.hayw...@arm.com> David Sherwood <david.sherw...@arm.com> gcc/ * optabs-query.h (extraction_insn::struct_mode): Change type to opt_scalar_int_mode and update comment. (extraction_insn::field_mode): Change type to scalar_int_mode. (extraction_insn::pos_mode): Likewise. * combine.c (make_extraction): Update accordingly. * optabs-query.c (get_traditional_extraction_insn): Likewise. (get_optab_extraction_insn): Likewise. * recog.c (simplify_while_replacing): Likewise. * expmed.c (narrow_bit_field_mem): Chane the type of the mode parameter to opt_scalar_int_mode. Index: gcc/optabs-query.h =================================================================== --- gcc/optabs-query.h 2017-02-23 19:54:15.000000000 +0000 +++ gcc/optabs-query.h 2017-07-13 09:18:42.162518990 +0100 @@ -141,16 +141,17 @@ struct extraction_insn enum insn_code icode; /* The mode that the structure operand should have. This is byte_mode - when using the legacy insv, extv and extzv patterns to access memory. */ - machine_mode struct_mode; + when using the legacy insv, extv and extzv patterns to access memory. + If no mode is given, the structure is a BLKmode memory. */ + opt_scalar_int_mode struct_mode; /* The mode of the field to be inserted or extracted, and by extension the mode of the insertion or extraction itself. */ - machine_mode field_mode; + scalar_int_mode field_mode; /* The mode of the field's bit position. This is only important when the position is variable rather than constant. */ - machine_mode pos_mode; + scalar_int_mode pos_mode; }; bool get_best_reg_extraction_insn (extraction_insn *, Index: gcc/combine.c =================================================================== --- gcc/combine.c 2017-07-13 09:18:39.584734236 +0100 +++ gcc/combine.c 2017-07-13 09:18:42.160519154 +0100 @@ -7632,7 +7632,7 @@ make_extraction (machine_mode mode, rtx if (get_best_reg_extraction_insn (&insn, pattern, GET_MODE_BITSIZE (inner_mode), mode)) { - wanted_inner_reg_mode = insn.struct_mode; + wanted_inner_reg_mode = *insn.struct_mode; pos_mode = insn.pos_mode; extraction_mode = insn.field_mode; } Index: gcc/optabs-query.c =================================================================== --- gcc/optabs-query.c 2017-07-13 09:18:30.902501597 +0100 +++ gcc/optabs-query.c 2017-07-13 09:18:42.161519072 +0100 @@ -100,9 +100,14 @@ get_traditional_extraction_insn (extract pos_mode = word_mode; insn->icode = icode; - insn->field_mode = field_mode; - insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode); - insn->pos_mode = pos_mode; + insn->field_mode = as_a <scalar_int_mode> (field_mode); + if (type == ET_unaligned_mem) + insn->struct_mode = byte_mode; + else if (struct_mode == BLKmode) + insn->struct_mode = opt_scalar_int_mode (); + else + insn->struct_mode = as_a <scalar_int_mode> (struct_mode); + insn->pos_mode = as_a <scalar_int_mode> (pos_mode); return true; } @@ -126,12 +131,17 @@ get_optab_extraction_insn (struct extrac const struct insn_data_d *data = &insn_data[icode]; + machine_mode pos_mode = data->operand[pos_op].mode; + if (pos_mode == VOIDmode) + pos_mode = word_mode; + insn->icode = icode; - insn->field_mode = mode; - insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode); - insn->pos_mode = data->operand[pos_op].mode; - if (insn->pos_mode == VOIDmode) - insn->pos_mode = word_mode; + insn->field_mode = as_a <scalar_int_mode> (mode); + if (type == ET_unaligned_mem) + insn->struct_mode = opt_scalar_int_mode (); + else + insn->struct_mode = insn->field_mode; + insn->pos_mode = as_a <scalar_int_mode> (pos_mode); return true; } Index: gcc/recog.c =================================================================== --- gcc/recog.c 2017-07-13 09:18:39.591733644 +0100 +++ gcc/recog.c 2017-07-13 09:18:42.162518990 +0100 @@ -663,25 +663,18 @@ simplify_while_replacing (rtx *loc, rtx MEM_ADDR_SPACE (XEXP (x, 0))) && !MEM_VOLATILE_P (XEXP (x, 0))) { - machine_mode wanted_mode = VOIDmode; int pos = INTVAL (XEXP (x, 2)); - + machine_mode new_mode = is_mode; if (GET_CODE (x) == ZERO_EXTRACT && targetm.have_extzv ()) - { - wanted_mode = insn_data[targetm.code_for_extzv].operand[1].mode; - if (wanted_mode == VOIDmode) - wanted_mode = word_mode; - } + new_mode = insn_data[targetm.code_for_extzv].operand[1].mode; else if (GET_CODE (x) == SIGN_EXTRACT && targetm.have_extv ()) - { - wanted_mode = insn_data[targetm.code_for_extv].operand[1].mode; - if (wanted_mode == VOIDmode) - wanted_mode = word_mode; - } + new_mode = insn_data[targetm.code_for_extv].operand[1].mode; + scalar_int_mode wanted_mode = (new_mode == VOIDmode + ? word_mode + : as_a <scalar_int_mode> (new_mode)); /* If we have a narrower mode, we can do something. */ - if (wanted_mode != VOIDmode - && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode)) + if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode)) { int offset = pos / BITS_PER_UNIT; rtx newmem; Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-07-13 09:18:41.678559010 +0100 +++ gcc/expmed.c 2017-07-13 09:18:42.161519072 +0100 @@ -409,31 +409,32 @@ flip_storage_order (machine_mode mode, r return result; } -/* Adjust bitfield memory MEM so that it points to the first unit of mode - MODE that contains a bitfield of size BITSIZE at bit position BITNUM. - If MODE is BLKmode, return a reference to every byte in the bitfield. - Set *NEW_BITNUM to the bit position of the field within the new memory. */ +/* If MODE is set, adjust bitfield memory MEM so that it points to the + first unit of mode MODE that contains a bitfield of size BITSIZE at + bit position BITNUM. If MODE is not set, return a BLKmode reference + to every byte in the bitfield. Set *NEW_BITNUM to the bit position + of the field within the new memory. */ static rtx -narrow_bit_field_mem (rtx mem, machine_mode mode, +narrow_bit_field_mem (rtx mem, opt_scalar_int_mode mode, unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT bitnum, unsigned HOST_WIDE_INT *new_bitnum) { - if (mode == BLKmode) + if (mode.exists ()) + { + unsigned int unit = GET_MODE_BITSIZE (*mode); + *new_bitnum = bitnum % unit; + HOST_WIDE_INT offset = (bitnum - *new_bitnum) / BITS_PER_UNIT; + return adjust_bitfield_address (mem, *mode, offset); + } + else { *new_bitnum = bitnum % BITS_PER_UNIT; HOST_WIDE_INT offset = bitnum / BITS_PER_UNIT; HOST_WIDE_INT size = ((*new_bitnum + bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT); - return adjust_bitfield_address_size (mem, mode, offset, size); - } - else - { - unsigned int unit = GET_MODE_BITSIZE (mode); - *new_bitnum = bitnum % unit; - HOST_WIDE_INT offset = (bitnum - *new_bitnum) / BITS_PER_UNIT; - return adjust_bitfield_address (mem, mode, offset); + return adjust_bitfield_address_size (mem, BLKmode, offset, size); } }