Skip to content

Commit fe0fa2b

Browse files
Shreya MunnangiJeffreyALaw
authored andcommitted
[RISC-V][SH][PR rtl-optimization/67731] Improve logical IOR of single bit bitfields
This is Shreya's work except for the SH testcase which I added after realizing her work would also fix the testcases for that port. I bootstrapped and regression tested this on sh4-linux-gnu, x86_64 & risc-v. It also was tested across all the embedded targets in my tester without regressions. -- We are extracting two single-bit bitfields from a structure and determining whether they both have the value 0 or if at least one bit is set. This has been generating poor code: > lw a5,0(a0) > bexti a0,a5,1 > bexti a5,a5,2 > or a0,a0,a5 > ret We address this as a simplification problem and optimize this using an andi of the original value and a mask with just the desired bits set, followed by a snez. This results in a 1 if any of those bits are set or 0 if none. For cases where we want to extract three or more single-bit bitfields, we build on the previous case. We take the result of the 2-bitfield case, extract the mask, update it to include the new single-bit bitfield, and again perform an andi + snez. In our new testfile, we scan to ensure we do not see a bexti or an or instruction, and that we have the correct assembly for both two and three single-bit bitfield cases: lw + andi + snez + ret. PR target/67731 gcc/ * simplify-rtx.cc (simplify_context::simplify_binary_operation_1): Handle IOR of single bit bitfields from the same object. gcc/testsuite/ * gcc.target/riscv/pr67731.c: New test. * gcc.target/sh/pr67731.c: New test.
1 parent 6363288 commit fe0fa2b

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

gcc/simplify-rtx.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3673,6 +3673,63 @@ simplify_context::simplify_binary_operation_1 (rtx_code code,
36733673
&& GET_MODE_CLASS (mode) != MODE_CC)
36743674
return CONSTM1_RTX (mode);
36753675

3676+
/* IOR of two single bit bitfields extracted from the same object.
3677+
Bitfields are represented as an AND based extraction */
3678+
if (GET_CODE (op0) == AND
3679+
&& GET_CODE (op1) == AND
3680+
/* Verify both AND operands are logical right shifts. */
3681+
&& GET_CODE (XEXP (op0, 0)) == LSHIFTRT
3682+
&& GET_CODE (XEXP (op1, 0)) == LSHIFTRT
3683+
/* Verify both bitfields are extracted from the same object. */
3684+
&& XEXP (XEXP (op0, 0), 0) == XEXP (XEXP (op1, 0), 0)
3685+
/* Verify both fields are a single bit (could be generalized). */
3686+
&& XEXP (op0, 1) == CONST1_RTX (mode)
3687+
&& XEXP (op1, 1) == CONST1_RTX (mode)
3688+
/* Verify bit positions (for cases with variable bit position). */
3689+
&& CONST_INT_P (XEXP (op0, 1))
3690+
&& CONST_INT_P (XEXP (op1, 1)))
3691+
{
3692+
unsigned HOST_WIDE_INT bitpos1 = INTVAL (XEXP (XEXP (op0, 0), 1));
3693+
unsigned HOST_WIDE_INT bitpos2 = INTVAL (XEXP (XEXP (op1, 0), 1));
3694+
unsigned HOST_WIDE_INT mask
3695+
= (HOST_WIDE_INT_1U << bitpos1) | (HOST_WIDE_INT_1U << bitpos2);
3696+
3697+
rtx m = GEN_INT (mask);
3698+
rtx t = gen_rtx_AND (mode, XEXP (XEXP (op0, 0), 0), m);
3699+
t = gen_rtx_NE (mode, t, CONST0_RTX (mode));
3700+
return t;
3701+
}
3702+
3703+
/* IOR of multiple single bit bitfields extracted from the same object
3704+
(building on previous case).
3705+
First bitfield is represented as an AND based extraction, as done
3706+
above. Second represented as NE based extraction, from
3707+
output above. */
3708+
if (GET_CODE (op0) == AND
3709+
&& GET_CODE (op1) == NE
3710+
/* Verify AND operand is logical right shift. */
3711+
&& GET_CODE (XEXP (op0, 0)) == LSHIFTRT
3712+
/* Verify NE operand is an AND (based on output above). */
3713+
&& GET_CODE (XEXP (op1, 0)) == AND
3714+
/* Verify both bitfields are extracted from the same object. */
3715+
&& XEXP (XEXP (op0, 0), 0) == XEXP (XEXP (op1, 0), 0)
3716+
/* Verify masking is with a single bit and that we have a NE 0
3717+
comparison for the other operand. */
3718+
&& XEXP (op0, 1) == CONST1_RTX (mode)
3719+
&& XEXP (op1, 1) == CONST0_RTX (mode)
3720+
/* Verify bit position. */
3721+
&& CONST_INT_P (XEXP (op0, 1)))
3722+
{
3723+
unsigned HOST_WIDE_INT bitpos1 = INTVAL (XEXP (XEXP (op0, 0), 1));
3724+
unsigned HOST_WIDE_INT mask
3725+
= (HOST_WIDE_INT_1U << bitpos1) | INTVAL (XEXP (XEXP (op1, 0), 1));
3726+
3727+
rtx m = GEN_INT (mask);
3728+
rtx t = gen_rtx_AND (mode, XEXP (XEXP (op0, 0), 0), m);
3729+
t = gen_rtx_NE (mode, t, CONST0_RTX (mode));
3730+
return t;
3731+
}
3732+
36763733
/* Convert (ior (plus (A - 1)) (neg A)) to -1. */
36773734
if (match_plus_neg_pattern (op0, op1, mode))
36783735
return CONSTM1_RTX (mode);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* { dg-do compile } */
2+
/* { dg-options "-O2 -march=rv64gcbv -mabi=lp64d" { target { rv64 } } } */
3+
/* { dg-options "-O2 -march=rv32gcbv -mabi=ilp32" { target { rv32 } } } */
4+
5+
typedef struct
6+
{
7+
_Bool a : 1;
8+
_Bool b : 1;
9+
_Bool c : 1;
10+
_Bool d : 1;
11+
unsigned int e : 4;
12+
} S;
13+
14+
_Bool test_00 (S* s)
15+
{
16+
return s->b | s->c;
17+
}
18+
19+
_Bool test_01 (S* s)
20+
{
21+
return s->b | s->c | s->d;
22+
}
23+
/* { dg-final { scan-assembler-times {\tlw\ta0,0\(a0\).*?\n\tandi\ta0,a0,\d+.*?\n\tsnez\ta0,a0.*?\n\tret} 2 } } */
24+
/* { dg-final { scan-assembler-not {\tor} } } */
25+
/* { dg-final { scan-assembler-not {\tbexti} } } */
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* { dg-do compile } */
2+
/* { dg-options "-O2 -m4 -ml" } */
3+
4+
typedef struct
5+
{
6+
_Bool a : 1;
7+
_Bool b : 1;
8+
_Bool c : 1;
9+
_Bool d : 1;
10+
unsigned int e : 4;
11+
} S;
12+
13+
_Bool test_00 (S* s)
14+
{
15+
return s->b | s->c;
16+
}
17+
18+
_Bool test_01 (S* s)
19+
{
20+
return s->b | s->c | s->d;
21+
}
22+
23+
/* { dg-final { scan-assembler-times {\ttst} 2 } } */
24+
/* { dg-final { scan-assembler-times {\tnegc} 2 } } */
25+
/* { dg-final { scan-assembler-not {\tor} } } */

0 commit comments

Comments
 (0)