Re: [PATCH][ARM] Add logical DImode expanders

2019-09-19 Thread Wilco Dijkstra
Hi Richard,

> Please reformat this as one mapping per line.  Over time I expect this 
> is only going to grow.

Sure, I've committed it reformatted as r275970.

Wilco






Re: [PATCH][ARM] Add logical DImode expanders

2019-09-19 Thread Richard Earnshaw (lists)

On 19/09/2019 15:26, Wilco Dijkstra wrote:

Hi Richard,


except we can do better than this...
(see below).  With that change, this just becomes di3

+(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])


These should just be added to the existing 'optab' attribute, there's no
need for an additional attribute.



+(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])


You don't need this, just use  where you want this substitution.


Yes we can avoid the new code attributes indeed and add to the existing
optab one. Here is what I did:

[PATCH][ARM] Simplify logical DImode iterators

Further simplify the logical DImode expander using code iterator and
obtab attributes.  This avoids adding unnecessary code_attr entries.

ChangeLog:
2019-09-19  Wilco Dijkstra  

* config/arm/arm.md (di3): Use  and .
* config/arm/iterators.md (optab): Add and, ior, xor entries.
(logical_op): Remove code attribute.
(logical_OP): Likewise.


OK, but...


--

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
d54082b13dd702aa55a1465c0fbfa87baa89149a..d607f88cb05ffa9cd8a47b8c8e0c53ea3a5ca411
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -2039,16 +2039,16 @@ (define_expand "divdf3"
  ; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
  ; So an explicit expander is needed to generate better code.
  
-(define_expand "di3"

+(define_expand "di3"
[(set (match_operand:DI   0 "s_register_operand")
(LOGICAL:DI (match_operand:DI 1 "s_register_operand")
-   (match_operand:DI 2 "arm_di_operand")))]
+   (match_operand:DI 2 "arm_di_operand")))]
"TARGET_32BIT"
{
-  rtx low  = simplify_gen_binary (, SImode,
+  rtx low  = simplify_gen_binary (, SImode,
  gen_lowpart (SImode, operands[1]),
  gen_lowpart (SImode, operands[2]));
-  rtx high = simplify_gen_binary (, SImode,
+  rtx high = simplify_gen_binary (, SImode,
  gen_highpart (SImode, operands[1]),
  gen_highpart_mode (SImode, DImode,
 operands[2]));
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 
5e3299e850813db2f3c0a25a6cde779d1d0d1d55..98ded4b22b2885e77e0ea0f1ce73ed12845115d3
 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -287,9 +287,6 @@ (define_code_attr cmp_type [(eq "i") (gt "s") (ge "s") (lt "s") (le 
"s")])
  
  (define_code_attr vfml_op [(plus "a") (minus "s")])
  
-(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])

-(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])
-
  ;;
  ;; Int iterators
  ;;
@@ -797,7 +794,7 @@ (define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin 
"u")
  (umax "u")])
  
  (define_code_attr cnb [(ltu "CC_C") (geu "CC")])

-(define_code_attr optab [(ltu "ltu") (geu "geu")])
+(define_code_attr optab [(ltu "ltu") (geu "geu") (and "and") (ior "ior") (xor 
"xor")])


Please reformat this as one mapping per line.  Over time I expect this 
is only going to grow.


R.

  
  ;; Assembler mnemonics for signedness of widening operations.

  (define_code_attr US [(sign_extend "s") (zero_extend "u")])





Re: [PATCH][ARM] Add logical DImode expanders

2019-09-19 Thread Wilco Dijkstra
Hi Richard,

> except we can do better than this...
> (see below).  With that change, this just becomes di3
>> +(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])
>
> These should just be added to the existing 'optab' attribute, there's no 
> need for an additional attribute.

>> +(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])
>
> You don't need this, just use  where you want this substitution.

Yes we can avoid the new code attributes indeed and add to the existing
optab one. Here is what I did:

[PATCH][ARM] Simplify logical DImode iterators

Further simplify the logical DImode expander using code iterator and
obtab attributes.  This avoids adding unnecessary code_attr entries.

ChangeLog:
2019-09-19  Wilco Dijkstra  

* config/arm/arm.md (di3): Use  and .
* config/arm/iterators.md (optab): Add and, ior, xor entries.
(logical_op): Remove code attribute.
(logical_OP): Likewise.
--

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
d54082b13dd702aa55a1465c0fbfa87baa89149a..d607f88cb05ffa9cd8a47b8c8e0c53ea3a5ca411
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -2039,16 +2039,16 @@ (define_expand "divdf3"
 ; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
 ; So an explicit expander is needed to generate better code.
 
-(define_expand "di3"
+(define_expand "di3"
   [(set (match_operand:DI0 "s_register_operand")
(LOGICAL:DI (match_operand:DI 1 "s_register_operand")
-   (match_operand:DI 2 "arm_di_operand")))]
+   (match_operand:DI 2 "arm_di_operand")))]
   "TARGET_32BIT"
   {
-  rtx low  = simplify_gen_binary (, SImode,
+  rtx low  = simplify_gen_binary (, SImode,
  gen_lowpart (SImode, operands[1]),
  gen_lowpart (SImode, operands[2]));
-  rtx high = simplify_gen_binary (, SImode,
+  rtx high = simplify_gen_binary (, SImode,
  gen_highpart (SImode, operands[1]),
  gen_highpart_mode (SImode, DImode,
 operands[2]));
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 
5e3299e850813db2f3c0a25a6cde779d1d0d1d55..98ded4b22b2885e77e0ea0f1ce73ed12845115d3
 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -287,9 +287,6 @@ (define_code_attr cmp_type [(eq "i") (gt "s") (ge "s") (lt 
"s") (le "s")])
 
 (define_code_attr vfml_op [(plus "a") (minus "s")])
 
-(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])
-(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])
-
 ;;
 ;; Int iterators
 ;;
@@ -797,7 +794,7 @@ (define_code_attr VQH_sign [(plus "i") (smin "s") (smax 
"s") (umin "u")
 (umax "u")])
 
 (define_code_attr cnb [(ltu "CC_C") (geu "CC")])
-(define_code_attr optab [(ltu "ltu") (geu "geu")])
+(define_code_attr optab [(ltu "ltu") (geu "geu") (and "and") (ior "ior") (xor 
"xor")])
 
 ;; Assembler mnemonics for signedness of widening operations.
 (define_code_attr US [(sign_extend "s") (zero_extend "u")])


Re: [PATCH][ARM] Add logical DImode expanders

2019-09-19 Thread Richard Earnshaw (lists)

On 18/09/2019 20:55, Wilco Dijkstra wrote:

Hi Kyrill,


We should be able to "compress" the above 3 patterns into one using code
iterators.


Good point, that makes sense. I've committed this:

ChangeLog:
2019-09-18  Wilco Dijkstra  

PR target/91738
* config/arm/arm.md (di3): Expand explicitly.
(one_cmpldi2): Likewise.
* config/arm/arm.c (const_ok_for_dimode_op): Return true if one
of the constant parts is simple.
* config/arm/iterators.md (LOGICAL): Add new code iterator.
(logical_op): Add new code attribute.
(logical_OP): Likewise.
* config/arm/predicates.md (arm_anddi_operand): Add predicate.
(arm_iordi_operand): Add predicate.
(arm_xordi_operand): Add predicate.


except we can do better than this...




--
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
173e6363682c35aa72a9fa36c14b6324b59e347b..1fc90c62798978ea5abddb11fbf1d7acbc8a8dc3
 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4273,8 +4273,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code 
code)
  case AND:
  case IOR:
  case XOR:
-  return (const_ok_for_op (hi_val, code) || hi_val == 0x)
-  && (const_ok_for_op (lo_val, code) || lo_val == 0x);
+  return const_ok_for_op (hi_val, code) || hi_val == 0x
+|| const_ok_for_op (lo_val, code) || lo_val == 0x;
  case PLUS:
return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
  
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md

index 
e23683114087f6cc9ee78376529da97cfe31d3a6..3943c4252b272d30f88f265e90ebc4cb88e3a615
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -2176,6 +2176,49 @@ (define_expand "divdf3"
"")
  
  
+; Expand logical operations.  The mid-end expander does not split off memory

+; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
+; So an explicit expander is needed to generate better code.
+
+(define_expand "di3"


(see below).  With that change, this just becomes di3


+  [(set (match_operand:DI0 "s_register_operand")
+   (LOGICAL:DI (match_operand:DI 1 "s_register_operand")
+   (match_operand:DI 2 "arm_di_operand")))]
+  "TARGET_32BIT"
+  {
+  rtx low  = simplify_gen_binary (, SImode,
+ gen_lowpart (SImode, operands[1]),
+ gen_lowpart (SImode, operands[2]));
+  rtx high = simplify_gen_binary (, SImode,
+ gen_highpart (SImode, operands[1]),
+ gen_highpart_mode (SImode, DImode,
+operands[2]));
+
+  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
+  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
+  DONE;
+  }
+)
+
+(define_expand "one_cmpldi2"
+  [(set (match_operand:DI 0 "s_register_operand")
+   (not:DI (match_operand:DI 1 "s_register_operand")))]
+  "TARGET_32BIT"
+  {
+  rtx low  = simplify_gen_unary (NOT, SImode,
+gen_lowpart (SImode, operands[1]),
+SImode);
+  rtx high = simplify_gen_unary (NOT, SImode,
+gen_highpart_mode (SImode, DImode,
+   operands[1]),
+SImode);
+
+  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
+  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
+  DONE;
+  }
+)
+
  ;; Split DImode and, ior, xor operations.  Simply perform the logical
  ;; operation on the upper and lower halves of the registers.
  ;; This is needed for atomic operations in arm_split_atomic_op.
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 
fa6f0c0529d5364b1e1df705cb1029868578e38c..20fd96cb0445fcdf821c7c72f2dd30bae8590d0c
 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -239,6 +239,8 @@ (define_code_iterator COMPARISONS [eq gt ge le lt])
  ;; A list of ...
  (define_code_iterator IOR_XOR [ior xor])
  
+(define_code_iterator LOGICAL [and ior xor])

+
  ;; Operations on two halves of a quadword vector.
  (define_code_iterator VQH_OPS [plus smin smax umin umax])
  
@@ -285,6 +287,9 @@ (define_code_attr cmp_type [(eq "i") (gt "s") (ge "s") (lt "s") (le "s")])
  
  (define_code_attr vfml_op [(plus "a") (minus "s")])
  
+(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])


These should just be added to the existing 'optab' attribute, there's no 
need for an additional attribute.



+(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])


You don't need this, just use  where you want this substitution.


+
  

Re: [PATCH][ARM] Add logical DImode expanders

2019-09-18 Thread Wilco Dijkstra
Hi Kyrill,

> We should be able to "compress" the above 3 patterns into one using code 
> iterators.

Good point, that makes sense. I've committed this:

ChangeLog:
2019-09-18  Wilco Dijkstra  

PR target/91738
* config/arm/arm.md (di3): Expand explicitly.
(one_cmpldi2): Likewise.
* config/arm/arm.c (const_ok_for_dimode_op): Return true if one
of the constant parts is simple.
* config/arm/iterators.md (LOGICAL): Add new code iterator.
(logical_op): Add new code attribute.
(logical_OP): Likewise.
* config/arm/predicates.md (arm_anddi_operand): Add predicate.
(arm_iordi_operand): Add predicate.
(arm_xordi_operand): Add predicate.

--
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
173e6363682c35aa72a9fa36c14b6324b59e347b..1fc90c62798978ea5abddb11fbf1d7acbc8a8dc3
 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -4273,8 +4273,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code 
code)
 case AND:
 case IOR:
 case XOR:
-  return (const_ok_for_op (hi_val, code) || hi_val == 0x)
-  && (const_ok_for_op (lo_val, code) || lo_val == 0x);
+  return const_ok_for_op (hi_val, code) || hi_val == 0x
+|| const_ok_for_op (lo_val, code) || lo_val == 0x;
 case PLUS:
   return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
 
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
e23683114087f6cc9ee78376529da97cfe31d3a6..3943c4252b272d30f88f265e90ebc4cb88e3a615
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -2176,6 +2176,49 @@ (define_expand "divdf3"
   "")
 
 
+; Expand logical operations.  The mid-end expander does not split off memory
+; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
+; So an explicit expander is needed to generate better code.
+
+(define_expand "di3"
+  [(set (match_operand:DI0 "s_register_operand")
+   (LOGICAL:DI (match_operand:DI 1 "s_register_operand")
+   (match_operand:DI 2 "arm_di_operand")))]
+  "TARGET_32BIT"
+  {
+  rtx low  = simplify_gen_binary (, SImode,
+ gen_lowpart (SImode, operands[1]),
+ gen_lowpart (SImode, operands[2]));
+  rtx high = simplify_gen_binary (, SImode,
+ gen_highpart (SImode, operands[1]),
+ gen_highpart_mode (SImode, DImode,
+operands[2]));
+
+  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
+  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
+  DONE;
+  }
+)
+
+(define_expand "one_cmpldi2"
+  [(set (match_operand:DI 0 "s_register_operand")
+   (not:DI (match_operand:DI 1 "s_register_operand")))]
+  "TARGET_32BIT"
+  {
+  rtx low  = simplify_gen_unary (NOT, SImode,
+gen_lowpart (SImode, operands[1]),
+SImode);
+  rtx high = simplify_gen_unary (NOT, SImode,
+gen_highpart_mode (SImode, DImode,
+   operands[1]),
+SImode);
+
+  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
+  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
+  DONE;
+  }
+)
+
 ;; Split DImode and, ior, xor operations.  Simply perform the logical
 ;; operation on the upper and lower halves of the registers.
 ;; This is needed for atomic operations in arm_split_atomic_op.
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 
fa6f0c0529d5364b1e1df705cb1029868578e38c..20fd96cb0445fcdf821c7c72f2dd30bae8590d0c
 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -239,6 +239,8 @@ (define_code_iterator COMPARISONS [eq gt ge le lt])
 ;; A list of ...
 (define_code_iterator IOR_XOR [ior xor])
 
+(define_code_iterator LOGICAL [and ior xor])
+
 ;; Operations on two halves of a quadword vector.
 (define_code_iterator VQH_OPS [plus smin smax umin umax])
 
@@ -285,6 +287,9 @@ (define_code_attr cmp_type [(eq "i") (gt "s") (ge "s") (lt 
"s") (le "s")])
 
 (define_code_attr vfml_op [(plus "a") (minus "s")])
 
+(define_code_attr logical_op [(ior "ior") (xor "xor") (and "and")])
+(define_code_attr logical_OP [(ior "IOR") (xor "XOR") (and "AND")])
+
 ;;
 ;; Int iterators
 ;;
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 
983faac8a72ef75e80cc34031c07c6435902c36f..8b36e7ee462235ad26e132f1ccf98d28c2487d67
 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ 

Re: [PATCH][ARM] Add logical DImode expanders

2019-09-18 Thread Kyrill Tkachov

Hi Wilco,

On 9/9/19 6:06 PM, Wilco Dijkstra wrote:

ping


We currently use default mid-end expanders for logical DImode operations.
 These split operations without first splitting off complex immediates or
 memory operands.  The resulting expansions are non-optimal and allow for
 fewer LDRD/STRD opportunities.  So add back explicit expanders which 
ensure

 memory operands and immediates are handled more efficiently.



Makes sense to me.



 Bootstrap OK on armhf, regress passes.

 ChangeLog:
 2019-08-29  Wilco Dijkstra  

 * config/arm/arm.md (anddi3): Expand explicitly.
 (iordi3): Likewise.
 (xordi3): Likewise.
 (one_cmpldi2): Likewise.
 * config/arm/arm.c (const_ok_for_dimode_op): Return true if one
 of the constant parts is simple.
 * config/arm/predicates.md (arm_anddi_operand): Add predicate.
 (arm_iordi_operand): Add predicate.
 (arm_xordi_operand): Add predicate.

 --

 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
 index 
fb57880fe0568be96a04aee1b7d230e77121e3f5..1fec00baa2a5e510ef2c02d9766432cc7cd0a17b 
100644

 --- a/gcc/config/arm/arm.c
 +++ b/gcc/config/arm/arm.c
 @@ -4273,8 +4273,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum 
rtx_code code)

  case AND:
  case IOR:
  case XOR:
 -  return (const_ok_for_op (hi_val, code) || hi_val == 0x)
 -  && (const_ok_for_op (lo_val, code) || lo_val == 
0x);

 +  return const_ok_for_op (hi_val, code) || hi_val == 0x
 +    || const_ok_for_op (lo_val, code) || lo_val == 0x;
  case PLUS:
    return arm_not_operand (hi, SImode) && arm_add_operand (lo, 
SImode);


 diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
 index 
ed49c4beda138633a84b58fe345cf5ba99103ab7..738d42fd164f117f1dec1108a824d984ccd70d09 
100644

 --- a/gcc/config/arm/arm.md
 +++ b/gcc/config/arm/arm.md
 @@ -2176,6 +2176,89 @@ (define_expand "divdf3"
    "")


 +; Expand logical operations.  The mid-end expander does not split 
off memory
 +; operands or complex immediates, which leads to fewer LDRD/STRD 
instructions.

 +; So an explicit expander is needed to generate better code.
 +
 +(define_expand "anddi3"
 +  [(set (match_operand:DI    0 "s_register_operand")
 +   (and:DI (match_operand:DI 1 "s_register_operand")
 +   (match_operand:DI 2 "arm_anddi_operand")))]
 +  "TARGET_32BIT"
 +  {
 +  rtx low  = simplify_gen_binary (AND, SImode,
 + gen_lowpart (SImode, operands[1]),
 + gen_lowpart (SImode, operands[2]));
 +  rtx high = simplify_gen_binary (AND, SImode,
 + gen_highpart (SImode, operands[1]),
 + gen_highpart_mode (SImode, DImode,
 +    operands[2]));
 +
 +  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
 +  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), 
high));

 +  DONE;
 +  }
 +)
 +
 +(define_expand "iordi3"
 +  [(set (match_operand:DI    0 "s_register_operand")
 +   (ior:DI (match_operand:DI 1 "s_register_operand")
 +   (match_operand:DI 2 "arm_iordi_operand")))]
 +  "TARGET_32BIT"
 +  {
 +  rtx low  = simplify_gen_binary (IOR, SImode,
 + gen_lowpart (SImode, operands[1]),
 + gen_lowpart (SImode, operands[2]));
 +  rtx high = simplify_gen_binary (IOR, SImode,
 + gen_highpart (SImode, operands[1]),
 + gen_highpart_mode (SImode, DImode,
 +    operands[2]));
 +
 +  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
 +  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), 
high));

 +  DONE;
 +  }
 +)
 +
 +(define_expand "xordi3"
 +  [(set (match_operand:DI    0 "s_register_operand")
 +   (xor:DI (match_operand:DI 1 "s_register_operand")
 +   (match_operand:DI 2 "arm_xordi_operand")))]
 +  "TARGET_32BIT"
 +  {
 +   rtx low  = simplify_gen_binary (XOR, SImode,
 +   gen_lowpart (SImode, 
operands[1]),
 +   gen_lowpart (SImode, 
operands[2]));

 +   rtx high = simplify_gen_binary (XOR, SImode,
 +   gen_highpart (SImode, 
operands[1]),

 + gen_highpart_mode (SImode, DImode,
 + operands[2]));
 +
 +   emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
 +   emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), 
high));

 +   DONE;
 +  }
 +)


We should be able to "compress" the above 3 patterns into one using code 
iterators.


Looks ok to me otherwise.

Thanks,

Kyrill


 +
 +(define_expand "one_cmpldi2"
 +  [(set (match_operand:DI 0 

Re: [PATCH][ARM] Add logical DImode expanders

2019-09-09 Thread Wilco Dijkstra
ping
   
 
We currently use default mid-end expanders for logical DImode operations.
 These split operations without first splitting off complex immediates or
 memory operands.  The resulting expansions are non-optimal and allow for
 fewer LDRD/STRD opportunities.  So add back explicit expanders which ensure
 memory operands and immediates are handled more efficiently.
 
 Bootstrap OK on armhf, regress passes.
 
 ChangeLog:
 2019-08-29  Wilco Dijkstra  
 
     * config/arm/arm.md (anddi3): Expand explicitly.
     (iordi3): Likewise.
     (xordi3): Likewise.
     (one_cmpldi2): Likewise.
     * config/arm/arm.c (const_ok_for_dimode_op): Return true if one
     of the constant parts is simple.
     * config/arm/predicates.md (arm_anddi_operand): Add predicate.
     (arm_iordi_operand): Add predicate.
     (arm_xordi_operand): Add predicate.
 
 --
 
 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
 index 
fb57880fe0568be96a04aee1b7d230e77121e3f5..1fec00baa2a5e510ef2c02d9766432cc7cd0a17b
 100644
 --- a/gcc/config/arm/arm.c
 +++ b/gcc/config/arm/arm.c
 @@ -4273,8 +4273,8 @@ const_ok_for_dimode_op (HOST_WIDE_INT i, enum rtx_code 
code)
  case AND:
  case IOR:
  case XOR:
 -  return (const_ok_for_op (hi_val, code) || hi_val == 0x)
 -  && (const_ok_for_op (lo_val, code) || lo_val == 0x);
 +  return const_ok_for_op (hi_val, code) || hi_val == 0x
 +    || const_ok_for_op (lo_val, code) || lo_val == 0x;
  case PLUS:
    return arm_not_operand (hi, SImode) && arm_add_operand (lo, SImode);
  
 diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
 index 
ed49c4beda138633a84b58fe345cf5ba99103ab7..738d42fd164f117f1dec1108a824d984ccd70d09
 100644
 --- a/gcc/config/arm/arm.md
 +++ b/gcc/config/arm/arm.md
 @@ -2176,6 +2176,89 @@ (define_expand "divdf3"
    "")
   
  
 +; Expand logical operations.  The mid-end expander does not split off memory
 +; operands or complex immediates, which leads to fewer LDRD/STRD instructions.
 +; So an explicit expander is needed to generate better code.
 +
 +(define_expand "anddi3"
 +  [(set (match_operand:DI    0 "s_register_operand")
 +   (and:DI (match_operand:DI 1 "s_register_operand")
 +   (match_operand:DI 2 "arm_anddi_operand")))]
 +  "TARGET_32BIT"
 +  {
 +  rtx low  = simplify_gen_binary (AND, SImode,
 + gen_lowpart (SImode, operands[1]),
 + gen_lowpart (SImode, operands[2]));
 +  rtx high = simplify_gen_binary (AND, SImode,
 + gen_highpart (SImode, operands[1]),
 + gen_highpart_mode (SImode, DImode,
 +    operands[2]));
 +
 +  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
 +  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
 +  DONE;
 +  }
 +)
 +
 +(define_expand "iordi3"
 +  [(set (match_operand:DI    0 "s_register_operand")
 +   (ior:DI (match_operand:DI 1 "s_register_operand")
 +   (match_operand:DI 2 "arm_iordi_operand")))]
 +  "TARGET_32BIT"
 +  {
 +  rtx low  = simplify_gen_binary (IOR, SImode,
 + gen_lowpart (SImode, operands[1]),
 + gen_lowpart (SImode, operands[2]));
 +  rtx high = simplify_gen_binary (IOR, SImode,
 + gen_highpart (SImode, operands[1]),
 + gen_highpart_mode (SImode, DImode,
 +    operands[2]));
 +
 +  emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
 +  emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
 +  DONE;
 +  }
 +)
 +
 +(define_expand "xordi3"
 +  [(set (match_operand:DI    0 "s_register_operand")
 +   (xor:DI (match_operand:DI 1 "s_register_operand")
 +   (match_operand:DI 2 "arm_xordi_operand")))]
 +  "TARGET_32BIT"
 +  {
 +   rtx low  = simplify_gen_binary (XOR, SImode,
 +   gen_lowpart (SImode, operands[1]),
 +   gen_lowpart (SImode, operands[2]));
 +   rtx high = simplify_gen_binary (XOR, SImode,
 +   gen_highpart (SImode, operands[1]),
 +   gen_highpart_mode (SImode, DImode,
 +  operands[2]));
 +
 +   emit_insn (gen_rtx_SET (gen_lowpart (SImode, operands[0]), low));
 +   emit_insn (gen_rtx_SET (gen_highpart (SImode, operands[0]), high));
 +   DONE;
 +  }
 +)
 +
 +(define_expand "one_cmpldi2"
 +  [(set (match_operand:DI 0 "s_register_operand")
 +   (not:DI (match_operand:DI 1 "s_register_operand")))]
 +  "TARGET_32BIT"
 +  {
 +  rtx low