aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/expmed.cc8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr110717-2.c20
2 files changed, 26 insertions, 2 deletions
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index fbd4ce2..b294eabb 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -1631,6 +1631,7 @@ extract_bit_field_as_subreg (machine_mode mode, rtx op0,
}
/* A subroutine of extract_bit_field, with the same arguments.
+ If UNSIGNEDP is -1, the result need not be sign or zero extended.
If FALLBACK_P is true, fall back to extract_fixed_bit_field
if we can find no other means of implementing the operation.
if FALLBACK_P is false, return NULL instead. */
@@ -1933,7 +1934,8 @@ extract_integral_bit_field (rtx op0, opt_scalar_int_mode op0_mode,
rtx result_part
= extract_bit_field_1 (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
- bitnum + bit_offset, 1, target_part,
+ bitnum + bit_offset,
+ (unsignedp ? 1 : -1), target_part,
mode, word_mode, reverse, fallback_p, NULL);
gcc_assert (target_part);
@@ -2187,6 +2189,7 @@ extract_fixed_bit_field (machine_mode tmode, rtx op0,
/* Helper function for extract_fixed_bit_field, extracts
the bit field always using MODE, which is the mode of OP0.
+ If UNSIGNEDP is -1, the result need not be sign or zero extended.
The other arguments are as for extract_fixed_bit_field. */
static rtx
@@ -2231,7 +2234,8 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0, scalar_int_mode mode,
/* Unless the msb of the field used to be the msb when we shifted,
mask out the upper bits. */
- if (GET_MODE_BITSIZE (mode) != bitnum + bitsize)
+ if (GET_MODE_BITSIZE (mode) != bitnum + bitsize
+ && unsignedp != -1)
return expand_binop (new_mode, and_optab, op0,
mask_rtx (new_mode, 0, bitsize, 0),
target, 1, OPTAB_LIB_WIDEN);
diff --git a/gcc/testsuite/gcc.target/i386/pr110717-2.c b/gcc/testsuite/gcc.target/i386/pr110717-2.c
new file mode 100644
index 0000000..a3cb568
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr110717-2.c
@@ -0,0 +1,20 @@
+/* PR target/110717 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#ifdef __SIZEOF_INT128__
+#define type __int128
+#define N 59
+#else
+#define type long long
+#define N 27
+#endif
+
+struct S { type a : sizeof (type) * __CHAR_BIT__ - N; };
+
+unsigned type bar (struct S *p)
+{
+ return p->a;
+}
+
+/* { dg-final { scan-assembler-not "andl" } } */