diff mbox

[AArch64] Fix PR target/77822: Use tighter predicates for zero_extract patterns

Message ID 5804F919.3020407@foss.arm.com
State New
Headers show

Commit Message

Kyrill Tkachov Oct. 17, 2016, 4:15 p.m. UTC
Hi all,

For the attached testcase the code ends up trying to extract bits outside the range of the normal register
widths. The aarch64 patterns for ubfz and tbnz end up accepting such operands and emitting invalid assembly
such as 'ubfx x18,x2,192,32'

The solution is to add proper predicates and guards to the operands of the zero_extract operations that are going on.
I had a look at all the other patterns in aarch64 that generate/use zero_extract and they all have guards on their
operands in one form or another to avoid them accessing an area that is out of range.

With this patch the testcase compiles and assembles fine.

Bootstrapped and tested on aarch64-none-linux-gnu.

Ok for trunk?

Thanks,
Kyrill

2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR target/77822
     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
     aarch64_simd_shift_imm_<mode> predicate for operand 1.
     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
     to restrict them to an appropriate range and add FAIL check if the
     region they specify is out of range.  Delete useless constraint
     strings.
     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
     2 and 3 to restrict their range and add pattern predicate.

2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR target/77822

Comments

Kyrill Tkachov Oct. 24, 2016, 11:29 a.m. UTC | #1
Ping.
https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01321.html

Thanks,
Kyrill

On 17/10/16 17:15, Kyrill Tkachov wrote:
> Hi all,
>
> For the attached testcase the code ends up trying to extract bits outside the range of the normal register
> widths. The aarch64 patterns for ubfz and tbnz end up accepting such operands and emitting invalid assembly
> such as 'ubfx x18,x2,192,32'
>
> The solution is to add proper predicates and guards to the operands of the zero_extract operations that are going on.
> I had a look at all the other patterns in aarch64 that generate/use zero_extract and they all have guards on their
> operands in one form or another to avoid them accessing an area that is out of range.
>
> With this patch the testcase compiles and assembles fine.
>
> Bootstrapped and tested on aarch64-none-linux-gnu.
>
> Ok for trunk?
>
> Thanks,
> Kyrill
>
> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     PR target/77822
>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>     to restrict them to an appropriate range and add FAIL check if the
>     region they specify is out of range.  Delete useless constraint
>     strings.
>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>     2 and 3 to restrict their range and add pattern predicate.
>
> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     PR target/77822
Kyrill Tkachov Oct. 24, 2016, 1:12 p.m. UTC | #2
On 24/10/16 12:29, Kyrill Tkachov wrote:
> Ping.
> https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01321.html
>

I just noticed my original ChangeLog entry was truncated.
It is
2016-10-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR target/77822
     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
     aarch64_simd_shift_imm_<mode> predicate for operand 1.
     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
     to restrict them to an appropriate range and add FAIL check if the
     region they specify is out of range.  Delete useless constraint
     strings.
     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
     2 and 3 to restrict their range and add pattern predicate.

2016-10-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR target/77822
     * g++.dg/torture/pr77822.C: New test.

Kyrill

>
> On 17/10/16 17:15, Kyrill Tkachov wrote:
>> Hi all,
>>
>> For the attached testcase the code ends up trying to extract bits outside the range of the normal register
>> widths. The aarch64 patterns for ubfz and tbnz end up accepting such operands and emitting invalid assembly
>> such as 'ubfx x18,x2,192,32'
>>
>> The solution is to add proper predicates and guards to the operands of the zero_extract operations that are going on.
>> I had a look at all the other patterns in aarch64 that generate/use zero_extract and they all have guards on their
>> operands in one form or another to avoid them accessing an area that is out of range.
>>
>> With this patch the testcase compiles and assembles fine.
>>
>> Bootstrapped and tested on aarch64-none-linux-gnu.
>>
>> Ok for trunk?
>>
>> Thanks,
>> Kyrill
>>
>> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>
>>     PR target/77822
>>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>>     to restrict them to an appropriate range and add FAIL check if the
>>     region they specify is out of range.  Delete useless constraint
>>     strings.
>>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>>     2 and 3 to restrict their range and add pattern predicate.
>>
>> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>
>>     PR target/77822
>
Kyrill Tkachov Oct. 31, 2016, 12:10 p.m. UTC | #3
Ping.

Thanks,
Kyrill

On 24/10/16 14:12, Kyrill Tkachov wrote:
>
> On 24/10/16 12:29, Kyrill Tkachov wrote:
>> Ping.
>> https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01321.html
>>
>
> I just noticed my original ChangeLog entry was truncated.
> It is
> 2016-10-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     PR target/77822
>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>     to restrict them to an appropriate range and add FAIL check if the
>     region they specify is out of range.  Delete useless constraint
>     strings.
>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>     2 and 3 to restrict their range and add pattern predicate.
>
> 2016-10-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>     PR target/77822
>     * g++.dg/torture/pr77822.C: New test.
>
> Kyrill
>
>>
>> On 17/10/16 17:15, Kyrill Tkachov wrote:
>>> Hi all,
>>>
>>> For the attached testcase the code ends up trying to extract bits outside the range of the normal register
>>> widths. The aarch64 patterns for ubfz and tbnz end up accepting such operands and emitting invalid assembly
>>> such as 'ubfx x18,x2,192,32'
>>>
>>> The solution is to add proper predicates and guards to the operands of the zero_extract operations that are going on.
>>> I had a look at all the other patterns in aarch64 that generate/use zero_extract and they all have guards on their
>>> operands in one form or another to avoid them accessing an area that is out of range.
>>>
>>> With this patch the testcase compiles and assembles fine.
>>>
>>> Bootstrapped and tested on aarch64-none-linux-gnu.
>>>
>>> Ok for trunk?
>>>
>>> Thanks,
>>> Kyrill
>>>
>>> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>
>>>     PR target/77822
>>>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>>>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>>>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>>>     to restrict them to an appropriate range and add FAIL check if the
>>>     region they specify is out of range.  Delete useless constraint
>>>     strings.
>>>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>>>     2 and 3 to restrict their range and add pattern predicate.
>>>
>>> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>
>>>     PR target/77822
>>
>
Kyrill Tkachov Nov. 7, 2016, 11:33 a.m. UTC | #4
Ping.

Thanks,
Kyrill

On 31/10/16 12:10, Kyrill Tkachov wrote:
> Ping.
>
> Thanks,
> Kyrill
>
> On 24/10/16 14:12, Kyrill Tkachov wrote:
>>
>> On 24/10/16 12:29, Kyrill Tkachov wrote:
>>> Ping.
>>> https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01321.html
>>>
>>
>> I just noticed my original ChangeLog entry was truncated.
>> It is
>> 2016-10-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>
>>     PR target/77822
>>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>>     to restrict them to an appropriate range and add FAIL check if the
>>     region they specify is out of range.  Delete useless constraint
>>     strings.
>>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>>     2 and 3 to restrict their range and add pattern predicate.
>>
>> 2016-10-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>
>>     PR target/77822
>>     * g++.dg/torture/pr77822.C: New test.
>>
>> Kyrill
>>
>>>
>>> On 17/10/16 17:15, Kyrill Tkachov wrote:
>>>> Hi all,
>>>>
>>>> For the attached testcase the code ends up trying to extract bits outside the range of the normal register
>>>> widths. The aarch64 patterns for ubfz and tbnz end up accepting such operands and emitting invalid assembly
>>>> such as 'ubfx x18,x2,192,32'
>>>>
>>>> The solution is to add proper predicates and guards to the operands of the zero_extract operations that are going on.
>>>> I had a look at all the other patterns in aarch64 that generate/use zero_extract and they all have guards on their
>>>> operands in one form or another to avoid them accessing an area that is out of range.
>>>>
>>>> With this patch the testcase compiles and assembles fine.
>>>>
>>>> Bootstrapped and tested on aarch64-none-linux-gnu.
>>>>
>>>> Ok for trunk?
>>>>
>>>> Thanks,
>>>> Kyrill
>>>>
>>>> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>
>>>>     PR target/77822
>>>>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>>>>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>>>>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>>>>     to restrict them to an appropriate range and add FAIL check if the
>>>>     region they specify is out of range.  Delete useless constraint
>>>>     strings.
>>>>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>>>>     2 and 3 to restrict their range and add pattern predicate.
>>>>
>>>> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>>
>>>>     PR target/77822
>>>
>>
>
James Greenhalgh Nov. 7, 2016, 11:37 a.m. UTC | #5
On Mon, Oct 17, 2016 at 05:15:21PM +0100, Kyrill Tkachov wrote:
> Hi all,
> 
> For the attached testcase the code ends up trying to extract bits outside the
> range of the normal register widths. The aarch64 patterns for ubfz and tbnz
> end up accepting such operands and emitting invalid assembly
> such as 'ubfx x18,x2,192,32'
> 
> The solution is to add proper predicates and guards to the operands of the
> zero_extract operations that are going on.  I had a look at all the other
> patterns in aarch64 that generate/use zero_extract and they all have guards
> on their
> operands in one form or another to avoid them accessing an area that is out
> of range.
> 
> With this patch the testcase compiles and assembles fine.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu.
> 
> Ok for trunk?

Ok, sorry for the delay on review.

Thanks,
James

> 2016-10-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>     PR target/77822
>     * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
>     aarch64_simd_shift_imm_<mode> predicate for operand 1.
>     (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
>     to restrict them to an appropriate range and add FAIL check if the
>     region they specify is out of range.  Delete useless constraint
>     strings.
>     (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
>     2 and 3 to restrict their range and add pattern predicate.
>
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 50cfdee909aa717afc097c74ab744c36137352ad..83d45931a28fc7b3442aa0a59b9e7315ef46c0e5 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -639,7 +639,8 @@  (define_insn "*tb<optab><mode>1"
   [(set (pc) (if_then_else
 	      (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
 				    (const_int 1)
-				    (match_operand 1 "const_int_operand" "n"))
+				    (match_operand 1
+				      "aarch64_simd_shift_imm_<mode>" "n"))
 		   (const_int 0))
 	     (label_ref (match_operand 2 "" ""))
 	     (pc)))
@@ -4301,19 +4302,28 @@  (define_insn "*extend<GPI:mode>_ashr<SHORT:mode>"
 
 (define_expand "<optab>"
   [(set (match_operand:DI 0 "register_operand" "=r")
-	(ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
-			(match_operand 2 "const_int_operand" "n")
-			(match_operand 3 "const_int_operand" "n")))]
-  ""
+	(ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
+			(match_operand 2
+			  "aarch64_simd_shift_imm_offset_di")
+			(match_operand 3 "aarch64_simd_shift_imm_di")))]
   ""
+  {
+    if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+		   1, GET_MODE_BITSIZE (DImode) - 1))
+     FAIL;
+  }
 )
 
+
 (define_insn "*<optab><mode>"
   [(set (match_operand:GPI 0 "register_operand" "=r")
 	(ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
-			 (match_operand 2 "const_int_operand" "n")
-			 (match_operand 3 "const_int_operand" "n")))]
-  ""
+			 (match_operand 2
+			   "aarch64_simd_shift_imm_offset_<mode>" "n")
+			 (match_operand 3
+			   "aarch64_simd_shift_imm_<mode>" "n")))]
+  "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+	     1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
   "<su>bfx\\t%<w>0, %<w>1, %3, %2"
   [(set_attr "type" "bfm")]
 )
diff --git a/gcc/testsuite/g++.dg/torture/pr77822.C b/gcc/testsuite/g++.dg/torture/pr77822.C
new file mode 100644
index 0000000000000000000000000000000000000000..4dc428b63eee981bda04e1faa29bb97e3986dca9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr77822.C
@@ -0,0 +1,30 @@ 
+// PR target/77822
+// { dg-do compile }
+
+using UINT8 = char;
+using UINT32 = int;
+using UINT64 = long;
+class A
+{
+  void m_fn1 ();
+  struct B
+  {
+    UINT32 m_multiplier;
+  };
+  UINT8 m_datawidth;
+  UINT8 m_subunits;
+  B m_subunit_infos[];
+};
+int a;
+UINT64 b;
+void
+A::m_fn1 ()
+{
+  int c = 32, d = m_datawidth / c;
+  for (int e = 0; e < d; e++)
+    {
+      UINT32 f = e * 32;
+      if (b >> f & 1)
+	m_subunit_infos[m_subunits].m_multiplier = a;
+    }
+}