aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2014-01-25 20:16:14 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2014-01-25 20:16:14 +0000
commit317a951fc75f1afb5e4fc25810722cf9044da7ed (patch)
tree61e1e082d8cd475a243a3d27fe8660aefe81dfd5 /gcc/config
parent3abe9053ba83798e124f9efe9996e42a7d07a4e8 (diff)
downloadgcc-317a951fc75f1afb5e4fc25810722cf9044da7ed.zip
gcc-317a951fc75f1afb5e4fc25810722cf9044da7ed.tar.gz
gcc-317a951fc75f1afb5e4fc25810722cf9044da7ed.tar.bz2
constraints.md (kl): Delete.
gcc/ * config/mips/constraints.md (kl): Delete. * config/mips/mips.md (divmod<mode>4, udivmod<mode>4): Turn into define expands, using... (divmod<mode>4_mips16, udivmod<mode>4_mips16): ...these new instructions for MIPS16. (*divmod<mode>4, *udivmod<mode>4): New patterns, taken from the non-MIPS16 version of the old divmod<mode>4 and udivmod<mode>4. From-SVN: r207079
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/mips/constraints.md6
-rw-r--r--gcc/config/mips/mips.md107
2 files changed, 90 insertions, 23 deletions
diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md
index 196b3e1..49e4895 100644
--- a/gcc/config/mips/constraints.md
+++ b/gcc/config/mips/constraints.md
@@ -92,12 +92,6 @@
;; 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 fb47a89..4f64360 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2559,56 +2559,129 @@
;; 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"
+ [(parallel
+ [(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)))])]
+ "ISA_HAS_<D>DIV && !TARGET_FIX_VR4120"
+{
+ if (TARGET_MIPS16)
+ {
+ rtx lo = gen_rtx_REG (<MODE>mode, LO_REGNUM);
+ emit_insn (gen_divmod<mode>4_mips16 (operands[0], operands[1],
+ operands[2], operands[3], lo));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*divmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=l")
+ (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)))]
+ "ISA_HAS_<D>DIV && !TARGET_FIX_VR4120 && !TARGET_MIPS16"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ emit_insn (gen_divmod<mode>4_split (operands[3], operands[1], operands[2]));
+ DONE;
+}
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")
+ (set_attr "insn_count" "2")])
+
;; 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")
+(define_insn_and_split "divmod<mode>4_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
(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)))]
- "ISA_HAS_<D>DIV && !TARGET_FIX_VR4120"
+ (match_dup 2)))
+ (clobber (match_operand:GPR 4 "lo_operand" "=l"))]
+ "ISA_HAS_<D>DIV && !TARGET_FIX_VR4120 && TARGET_MIPS16"
"#"
- "&& ((TARGET_MIPS16 && cse_not_expected) || reload_completed)"
+ "&& cse_not_expected"
[(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));
+ emit_move_insn (operands[0], operands[4]);
DONE;
}
[(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")
- ;; Worst case for MIPS16.
(set_attr "insn_count" "3")])
-;; 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")
+(define_expand "udivmod<mode>4"
+ [(parallel
+ [(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)))])]
+ "ISA_HAS_<D>DIV && !TARGET_FIX_VR4120"
+{
+ if (TARGET_MIPS16)
+ {
+ rtx lo = gen_rtx_REG (<MODE>mode, LO_REGNUM);
+ emit_insn (gen_udivmod<mode>4_mips16 (operands[0], operands[1],
+ operands[2], operands[3], lo));
+ DONE;
+ }
+})
+
+(define_insn_and_split "*udivmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=l")
(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)))]
- "ISA_HAS_<D>DIV"
+ "ISA_HAS_<D>DIV && !TARGET_MIPS16"
"#"
- "(TARGET_MIPS16 && cse_not_expected) || reload_completed"
+ "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")
(set_attr "mode" "<MODE>")
- ;; Worst case for MIPS16.
+ (set_attr "insn_count" "2")])
+
+;; See the comment above "divmod<mode>4_mips16" for the split timing.
+(define_insn_and_split "udivmod<mode>4_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (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)))
+ (clobber (match_operand:GPR 4 "lo_operand" "=l"))]
+ "ISA_HAS_<D>DIV && TARGET_MIPS16"
+ "#"
+ "cse_not_expected"
+ [(const_int 0)]
+{
+ emit_insn (gen_udivmod<mode>4_split (operands[3], operands[1], operands[2]));
+ emit_move_insn (operands[0], operands[4]);
+ DONE;
+}
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")
(set_attr "insn_count" "3")])
(define_expand "<u>divmod<mode>4_split"