summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-25 16:00:12 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-25 16:00:12 +0000
commit188bbdeca8fa12ae04be9555c4679ba27f135681 (patch)
tree1d76677de125339268a0b5ae0da765fa4bc78cda
parent073ac520e104804cffaf4e48594685a549932f1d (diff)
downloadgcc-188bbdeca8fa12ae04be9555c4679ba27f135681.tar.gz
gcc/
PR target/53916 * config/mips/constraints.md (kl): New constraint. * config/mips/mips.md (divmod<mode>4, udivmod<mode>4): Delete. (divmod<mode>4_internal): Rename to divmod<mode>4. Use "kl" as the constraint for operand 0. Split after CSE for MIPS16. Emit a move from LO for MIPS16. (udivmod<mode>4_internal): Likewise udivmod<mode>4. gcc/testsuite/ PR target/53916 * gcc.target/mips/div-13.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199329 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/mips/constraints.md6
-rw-r--r--gcc/config/mips/mips.md70
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/mips/div-13.c17
5 files changed, 58 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 89936afd71d..e2879fc338f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2013-05-25 Richard Sandiford <rdsandiford@googlemail.com>
+ PR target/53916
+ * config/mips/constraints.md (kl): New constraint.
+ * config/mips/mips.md (divmod<mode>4, udivmod<mode>4): Delete.
+ (divmod<mode>4_internal): Rename to divmod<mode>4. Use "kl" as the
+ constraint for operand 0. Split after CSE for MIPS16. Emit a move
+ from LO for MIPS16.
+ (udivmod<mode>4_internal): Likewise udivmod<mode>4.
+
+2013-05-25 Richard Sandiford <rdsandiford@googlemail.com>
+
PR target/55777
* config/mips/mips.c (mips_can_inline_p): New function.
(TARGET_CAN_INLINE_P): Define.
diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md
index ddef8cc495d..1fe6119d075 100644
--- a/gcc/config/mips/constraints.md
+++ b/gcc/config/mips/constraints.md
@@ -92,6 +92,12 @@
;; but the DSP version allows any accumulator target.
(define_register_constraint "ka" "ISA_HAS_DSP_MULT ? ACC_REGS : MD_REGS")
+;; The register class to use for an allocatable division result.
+;; MIPS16 uses M16_REGS because LO is fixed.
+(define_register_constraint "kl"
+ "TARGET_MIPS16 ? M16_REGS : TARGET_BIG_ENDIAN ? MD1_REG : MD0_REG"
+ "@internal")
+
(define_constraint "kf"
"@internal"
(match_operand 0 "force_to_mem_operand"))
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 7284e5f3384..6f6484b0d8c 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2560,80 +2560,50 @@
;; VR4120 errata MD(A1): signed division instructions do not work correctly
;; with negative operands. We use special libgcc functions instead.
-(define_expand "divmod<mode>4"
- [(set (match_operand:GPR 0 "register_operand")
- (div:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))
- (set (match_operand:GPR 3 "register_operand")
- (mod:GPR (match_dup 1)
- (match_dup 2)))]
- "!TARGET_FIX_VR4120"
-{
- if (TARGET_MIPS16)
- {
- emit_insn (gen_divmod<mode>4_split (operands[3], operands[1],
- operands[2]));
- emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
- }
- else
- emit_insn (gen_divmod<mode>4_internal (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
-})
-
-(define_insn_and_split "divmod<mode>4_internal"
- [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
+;;
+;; Expand generates divmod instructions for individual division and modulus
+;; operations. We then rely on CSE to reuse earlier divmods where possible.
+;; This means that, when generating MIPS16 code, it is better not to expose
+;; the fixed LO register until after CSE has finished. However, it's still
+;; better to split before register allocation, so that we don't allocate
+;; one of the scarce MIPS16 registers to an unused result.
+(define_insn_and_split "divmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=kl")
(div:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))
(set (match_operand:GPR 3 "register_operand" "=d")
(mod:GPR (match_dup 1)
(match_dup 2)))]
- "!TARGET_FIX_VR4120 && !TARGET_MIPS16"
+ "!TARGET_FIX_VR4120"
"#"
- "&& reload_completed"
+ "&& ((TARGET_MIPS16 && cse_not_expected) || reload_completed)"
[(const_int 0)]
{
emit_insn (gen_divmod<mode>4_split (operands[3], operands[1], operands[2]));
+ if (TARGET_MIPS16)
+ emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
DONE;
}
[(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")
(set_attr "length" "8")])
-(define_expand "udivmod<mode>4"
- [(set (match_operand:GPR 0 "register_operand")
- (udiv:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "register_operand")))
- (set (match_operand:GPR 3 "register_operand")
- (umod:GPR (match_dup 1)
- (match_dup 2)))]
- ""
-{
- if (TARGET_MIPS16)
- {
- emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1],
- operands[2]));
- emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
- }
- else
- emit_insn (gen_udivmod<mode>4_internal (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
-})
-
-(define_insn_and_split "udivmod<mode>4_internal"
- [(set (match_operand:GPR 0 "muldiv_target_operand" "=l")
+;; See the comment above "divmod<mode>4" for the MIPS16 handling.
+(define_insn_and_split "udivmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=kl")
(udiv:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))
(set (match_operand:GPR 3 "register_operand" "=d")
(umod:GPR (match_dup 1)
(match_dup 2)))]
- "!TARGET_MIPS16"
+ ""
"#"
- "reload_completed"
+ "(TARGET_MIPS16 && cse_not_expected) || reload_completed"
[(const_int 0)]
{
emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1], operands[2]));
+ if (TARGET_MIPS16)
+ emit_move_insn (operands[0], gen_rtx_REG (<MODE>mode, LO_REGNUM));
DONE;
}
[(set_attr "type" "idiv")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fbc87164103..38985d6119a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2013-05-25 Richard Sandiford <rdsandiford@googlemail.com>
+ PR target/53916
+ * gcc.target/mips/div-13.c: New test.
+
+2013-05-25 Richard Sandiford <rdsandiford@googlemail.com>
+
PR target/55777
* gcc.target/mips/mips16-attributes-5.c,
* gcc.target/mips/mips16-attributes-6.c: New tests.
diff --git a/gcc/testsuite/gcc.target/mips/div-13.c b/gcc/testsuite/gcc.target/mips/div-13.c
new file mode 100644
index 00000000000..cf746a66306
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/div-13.c
@@ -0,0 +1,17 @@
+/* { dg-options "(-mips16) -mgp64" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+MIPS16 int32_t f1 (int32_t x, int32_t y) { return x / y + x % y; }
+MIPS16 uint32_t f2 (uint32_t x, uint32_t y) { return x / y + x % y; }
+MIPS16 int64_t f3 (int64_t x, int64_t y) { return x / y + x % y; }
+MIPS16 uint64_t f4 (uint64_t x, uint64_t y) { return x / y + x % y; }
+
+/* { dg-final { scan-assembler-times "\tdiv\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tdivu\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tddiv\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tddivu\t" 1 } } */