Re: [PATCH][ARM] Add logical DImode expanders
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
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
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
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
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
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
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