From patchwork Fri May 31 21:28:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Segher Boessenkool X-Patchwork-Id: 248017 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id F24C22C007E for ; Sat, 1 Jun 2013 07:28:41 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=ClBolahgu1ws QycCm7WNU/Iy8sK8CktKKw/PAR3MUZooPOzB/WjgPXLp32eiAcEwGdhTA86vnucL dQ4mf3mGrxUvn1Bd4xdMBYgRC2cDfpSCCYrxygo49F5oglI0t7XON+mqY5/VIMyz DZORbS3GEak8nbBml7DwzSesPSZ5zfI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=BvbsAH7MEp3I1sEKh0 HYFc7kMyc=; b=k5liCiWHhlAop6y8rGlFw941rgF6A/7UKR2u86HoUj9EdKmZyb Axpau8o1hqw1EzgGT38V0cnfMPLDvXJSVswWTa35VDhxDQLw+Wk/C9OU/e6JN24l 2s5mNIRnIEitp5oVhlomIdZBaeTQEhd0z/u7UgyDnJxUQ2B+eFYgRLTGE= Received: (qmail 16371 invoked by alias); 31 May 2013 21:28:34 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 16361 invoked by uid 89); 31 May 2013 21:28:34 -0000 X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD autolearn=ham version=3.3.1 Received: from gcc1-power7.osuosl.org (HELO gcc1-power7.osuosl.org) (140.211.15.137) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 31 May 2013 21:28:31 +0000 Received: from gcc1-power7.osuosl.org (localhost [127.0.0.1]) by gcc1-power7.osuosl.org (8.14.6/8.14.6) with ESMTP id r4VLSIkG051090; Fri, 31 May 2013 14:28:18 -0700 Received: (from segher@localhost) by gcc1-power7.osuosl.org (8.14.6/8.14.6/Submit) id r4VLSGDV050636; Fri, 31 May 2013 14:28:16 -0700 From: Segher Boessenkool To: gcc-patches@gcc.gnu.org Cc: dje.gcc@gmail.com, Segher Boessenkool Subject: [PATCH 1/6] rs6000: Introducing define_dot_insn Date: Fri, 31 May 2013 14:28:06 -0700 Message-Id: <14577e1c6b530d6f4feda94ba84896983b05513b.1370028541.git.segher@kernel.crashing.org> This adds a program (mdm.pl) that does some processing on machine description files. It is careful to keep formatting and comments intact as much as possible, so that its output is well readable. The only transform it does so far is convert a "define_dot_insn" construct to three "define_insn"s and two "define_split"s, that together handle a PowerPC GPR instruction and its record-form ("dot") variant. The syntax of define_dot_insn is just like that of define_insn, with an extra condition string added after the normal one; the condition used for the record form variant is the conjunction of both those condition strings. The mdm.pl program is only used if the input file (*.mdm) has been touched, so users do not need Perl installed to build GCC unless they have changed the input file. The output file (*.md) is checked into SVN. I hope this is enough to guarantee the timestamps in generated tarballs will be later for the output file, too? This needs Perl 5.14, which is two years old. If that won't do I can rework some of it so it needs only 5.10, which is five years old. As an example this patch moves lshrdi3 over. This causes a minor regression that further patches will fix: no longer a different instruction type attribute is used for the dot form; instead, the "dot" attribute is set to "yes". Hopefully, with many fewer (and more descriptive) possible values for "type" the scheduling descriptions will be clearer and contain fewer silly bugs. Bootstrapped and tested on powerpc64-linux --enable-languages=c,c++,fortran --disable-libsanitizer, -m64,-m32,-m32/-mpowerpc64, no regressions. Comments, questions, flames? I'm wearing my asbestos suit... Segher 2013-05-31 Segher Boessenkool gcc/ * config/rs6000/rs6000.md (dot): New. (include "integer.md"): New. (lshrdi3_internal1, lshrdi3_internal2, lshrdi3_internal3): Delete. * config/rs6000/integer.mdm: New file. * config/rs6000/integer.md: New file, autogenerated. * config/rs6000/mdm.pl: New file. * config/rs6000/t-rs6000 (MD_INCLUDES): Add integer.md. (MDM): New. (%.md: %.mdm): New. --- gcc/config/rs6000/integer.md | 148 +++++++++++++ gcc/config/rs6000/integer.mdm | 67 ++++++ gcc/config/rs6000/mdm.pl | 470 ++++++++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/rs6000.md | 82 +------- gcc/config/rs6000/t-rs6000 | 6 + 5 files changed, 696 insertions(+), 77 deletions(-) create mode 100644 gcc/config/rs6000/integer.md create mode 100644 gcc/config/rs6000/integer.mdm create mode 100755 gcc/config/rs6000/mdm.pl diff --git a/gcc/config/rs6000/integer.md b/gcc/config/rs6000/integer.md new file mode 100644 index 0000000..0884e0f --- /dev/null +++ b/gcc/config/rs6000/integer.md @@ -0,0 +1,148 @@ +; Generated by mdm.pl; do not edit (edit the .mdm instead). +; vi:ro + + +; Copyright (C) 1990-2013 Free Software Foundation, Inc. +; +; This file is part of GCC. +; +; GCC is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published +; by the Free Software Foundation; either version 3, or (at your +; option) any later version. +; +; GCC is distributed in the hope that it will be useful, but WITHOUT +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +; License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GCC; see the file COPYING3. If not see +; . + + +; This file describes the integer (GPR-to-GPR) PowerPC instructions. +; Most of these have record-form ("dot") variants, and are described +; using define_dot_insn. + + +; -- Rotate and shift instructions: +; rlwinm[.], rlwnm[.], rldicl[.], rldicr[.], rldic[.], rldcl[.], rldcr[.] +; rlwimi[.], rldimi[.] +; slw[.], srw[.], srawi[.], sraw[.], sld[.], srd[.], sradi[.], srad[.] + + +(define_insn "lshrdi3" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i")))] + "TARGET_POWERPC64" + "@ + srd %0,%1,%2 + srdi %0,%1,%H2" + [(set_attr "type" "var_shift_rotate,shift") ; var_delayed_compare,delayed_compare +]) + +(define_insn "*lshrdi3_dot" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC + (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r,r,r,r"))] + "(TARGET_POWERPC64) + && (DImode == Pmode && rs6000_gen_cell_microcode)" + "@ + srd. %0,%1,%2 + srdi. %0,%1,%H2 + # + #" + [(set_attr "length" "4,4,8,8") + (set_attr "dot" "yes,yes,no,no") + (set_attr "type" "var_shift_rotate,shift,var_shift_rotate,shift") ; var_delayed_compare,delayed_compare +]) + +(define_split + [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "") + (compare:CC + (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_cint_operand" "")) + (const_int 0))) + (clobber (match_scratch:DI 0 ""))] + "((TARGET_POWERPC64) + && (DImode == Pmode && rs6000_gen_cell_microcode)) + && (reload_completed)" + [(set (match_dup 0) + (lshiftrt:DI (match_dup 1) + (match_dup 2))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + +(define_insn "*lshrdi3_dot2" + [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") + (compare:CC + (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") + (lshiftrt:DI (match_dup 1) + (match_dup 2)))] + "(TARGET_POWERPC64) + && (DImode == Pmode && rs6000_gen_cell_microcode)" + "@ + srd. %0,%1,%2 + srdi. %0,%1,%H2 + # + #" + [(set_attr "length" "4,4,8,8") + (set_attr "dot" "yes,yes,no,no") + (set_attr "type" "var_shift_rotate,shift,var_shift_rotate,shift") ; var_delayed_compare,delayed_compare +]) + +(define_split + [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "") + (compare:CC + (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "reg_or_cint_operand" "")) + (const_int 0))) + (set (match_operand:DI 0 "gpc_reg_operand" "") + (lshiftrt:DI (match_dup 1) + (match_dup 2)))] + "((TARGET_POWERPC64) + && (DImode == Pmode && rs6000_gen_cell_microcode)) + && (reload_completed)" + [(set (match_dup 0) + (lshiftrt:DI (match_dup 1) + (match_dup 2))) + (set (match_dup 3) + (compare:CC (match_dup 0) + (const_int 0)))] + "") + + +; -- Logical instructions: +; andi., andis., ori, oris, xori, xoris +; and[.], or[.], xor[.], nand[.], nor[.], eqv[.], andc[.], orc[.] +; extsb[.], extsh[.], extsw[.], cntlzw[.], cntlzd[.] + + +; -- Arithmetic instructions: +; addi, addis, add[.], subf[.], neg[.] +; addic[.], subfic, addc[.], subfc[.] +; adde[.], subfe[.], addme[.], subfme[.], addze[.], subfze[.] +; mulli, mullw[.], mulhw[.], mulhwu[.], mulld[.], mulhd[.], mulhdu[.] +; divw[.], divwu[.], divd[.], divdu[.] + + +; -- Compare instructions: +; cmpwi, cmpdi, cmpw, cmpd, cmplwi, cmpldi, cmplw, cmpld + + +; -- Trap instructions: +; twi, tw, tdi, td + + +; -- System register instructions: +; mtcrf, mfcr, mtocrf, mfocrf diff --git a/gcc/config/rs6000/integer.mdm b/gcc/config/rs6000/integer.mdm new file mode 100644 index 0000000..23ff8ca --- /dev/null +++ b/gcc/config/rs6000/integer.mdm @@ -0,0 +1,67 @@ +; Copyright (C) 1990-2013 Free Software Foundation, Inc. +; +; This file is part of GCC. +; +; GCC is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published +; by the Free Software Foundation; either version 3, or (at your +; option) any later version. +; +; GCC is distributed in the hope that it will be useful, but WITHOUT +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +; License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GCC; see the file COPYING3. If not see +; . + + +; This file describes the integer (GPR-to-GPR) PowerPC instructions. +; Most of these have record-form ("dot") variants, and are described +; using define_dot_insn. + + +; -- Rotate and shift instructions: +; rlwinm[.], rlwnm[.], rldicl[.], rldicr[.], rldic[.], rldcl[.], rldcr[.] +; rlwimi[.], rldimi[.] +; slw[.], srw[.], srawi[.], sraw[.], sld[.], srd[.], sradi[.], srad[.] + + +(define_dot_insn "lshrdi3" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") + (match_operand:SI 2 "reg_or_cint_operand" "r,i")))] + "TARGET_POWERPC64" + "DImode == Pmode && rs6000_gen_cell_microcode" + "@ + srd %0,%1,%2 + srdi %0,%1,%H2" + [(set_attr "type" "var_shift_rotate,shift") ; var_delayed_compare,delayed_compare +]) + + +; -- Logical instructions: +; andi., andis., ori, oris, xori, xoris +; and[.], or[.], xor[.], nand[.], nor[.], eqv[.], andc[.], orc[.] +; extsb[.], extsh[.], extsw[.], cntlzw[.], cntlzd[.] + + +; -- Arithmetic instructions: +; addi, addis, add[.], subf[.], neg[.] +; addic[.], subfic, addc[.], subfc[.] +; adde[.], subfe[.], addme[.], subfme[.], addze[.], subfze[.] +; mulli, mullw[.], mulhw[.], mulhwu[.], mulld[.], mulhd[.], mulhdu[.] +; divw[.], divwu[.], divd[.], divdu[.] + + +; -- Compare instructions: +; cmpwi, cmpdi, cmpw, cmpd, cmplwi, cmpldi, cmplw, cmpld + + +; -- Trap instructions: +; twi, tw, tdi, td + + +; -- System register instructions: +; mtcrf, mfcr, mtocrf, mfocrf diff --git a/gcc/config/rs6000/mdm.pl b/gcc/config/rs6000/mdm.pl new file mode 100755 index 0000000..607e9cc --- /dev/null +++ b/gcc/config/rs6000/mdm.pl @@ -0,0 +1,470 @@ +#!/usr/bin/perl + +# Copyright (C) 2013 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3, or (at your +# option) any later version. +# +# GCC is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + + +# Pre-process a machine description file as text. Preserve whitespace and +# comments as much as possible. +# +# Currently this just expands "define_dot_insn" constructs into three +# "define_insn"s and two "define_split"s, which handle integer PowerPC +# record form instructions. + + +use v5.14; # Needed for /r; otherwise, v5.10 for (?-1). +use strict; +use warnings; +use re "/s"; # Newlines are not usually significant in MD files. + + +# Interpolate arrays into strings without spaces between the elements. +$" = ""; + + +my $ws = qr/ + (?> + \s # whitespace char + | ;.*?\n # lisp comment + | \/\*.*?\*\/ # C comment + )+ + /x; + +my $string = qr/ + (?> + " + (?: \\. | [^\"] )* + " + ) + /x; + +my $block = qr/ + ((?> + \{ + (?: [^{}]++ | (?-1) )*+ + \} + )) + /x; + +# An "atom" is any RTL construct, followed by optional whitespace. +my $atom = qr/ + ((?> + \( $ws?+ (?: (?-1) )++ \) + | \[ $ws?+ (?: (?-1) )++ \] + | [-:<>\w]++ + | $string + | $block + )$ws?+) + /x; + + +# Split an atom into something that matches $head, a list of atoms, and +# finally something that matches $tail. No error checking is done or +# needed, that's the callers' job. +sub decompose { + my ($x, $head, $tail) = @_; + $x =~ /^(\Q$head\E$ws?+)/g; + $head = $1; + + my @body; + my $last = pos $x; + while ($x =~ /\G($atom)/g) { + push @body, $1; + $last = pos $x; + } + pos $x = $last; + + $x =~ /\G(\Q$tail\E$ws?+)/g; + $tail = $1; + + return ($head, @body, $tail); +} + +# Merge two conditions (double-quoted pieces of C code) into one. +sub join_cond { + my ($c1, $c2) = @_; + + return $c1 if $c2 =~ /^""/; + return $c2 if $c1 =~ /^""/; + + $c1 =~ s/^"([^"]*).*/"\($1\)\n /; + $c2 =~ s/^"([^"]*)"/ && \($1\)"/; + + return "$c1$c2"; +} + +# Double a constraint, e.g. "=r,i" becomes "=r,i,r,i". +sub double_constraint { + my $x = shift; + return $x =~ s/(\w[^"]*)/$1,$1/r; +} + +# Double all constraints in an atom. +sub double_constraints { + my $pattern = shift; + + if ($pattern =~ /^\(match_operand\b/) { + my ($head, @body) = decompose $pattern, "(", ")"; + $body[3] = double_constraint $body[3]; + return "$head@body"; + } + + if ($pattern =~ /^\(match_scratch\b/) { + my ($head, @body) = decompose $pattern, "(", ")"; + $body[2] = double_constraint $body[2]; + return "$head@body"; + } + + if ($pattern =~ /^[([]/) { + my $first = substr $pattern, 0, 1; + my $last = ($first eq "(") ? ")" : "]"; + my ($head, @body) = decompose $pattern, $first, $last; + my $tail = pop @body; + + @body = map { double_constraints($_) } @body; + + return "$head@body$tail"; + } + + return $pattern; +} + +# Remove a constraint, e.g. "=r,i" becomes "". +sub remove_constraint { + my $x = shift; + return $x =~ s/"[^"]*/"/r; +} + +# Remove all constraints in an atom. +sub remove_constraints { + my $pattern = shift; + + if ($pattern =~ /^\(match_operand\b/) { + my ($head, @body) = decompose $pattern, "(", ")"; + $body[3] = remove_constraint $body[3]; + return "$head@body"; + } + + if ($pattern =~ /^\(match_scratch\b/) { + my ($head, @body) = decompose $pattern, "(", ")"; + $body[2] = remove_constraint $body[2]; + return "$head@body"; + } + + if ($pattern =~ /^[([]/) { + my $first = substr $pattern, 0, 1; + my $last = ($first eq "(") ? ")" : "]"; + my ($head, @body) = decompose $pattern, $first, $last; + my $tail = pop @body; + + @body = map { remove_constraints($_) } @body; + + return "$head@body$tail"; + } + + return $pattern; +} + +# Change all "match_operand" and "match_scratch" to the equally numbered +# "match_dup" construct. +sub make_match_dups { + my $pattern = shift; + + if ($pattern =~ /^\(match_(?:operand|scratch)\b/) { + my ($head, @body) = decompose $pattern, "(", ")"; + my $tail = pop @body; + $body[1] =~ /(\d+)/; + return "${head}match_dup $1$tail"; + } + + if ($pattern =~ /^[([]/) { + my $first = substr $pattern, 0, 1; + my $last = ($first eq "(") ? ")" : "]"; + my ($head, @body) = decompose $pattern, $first, $last; + my $tail = pop @body; + + @body = map { make_match_dups($_) } @body; + + return "$head@body$tail"; + } + + return $pattern; +} + +# Find out the highest operand number used in a "match_". +sub max_op { + my $pattern = shift; + + if ($pattern =~ /^\(match_/) { + my ($head, @body) = decompose $pattern, "(", ")"; + return $body[1]; + } + + if ($pattern =~ /^[([]/) { + my $first = substr $pattern, 0, 1; + my $last = ($first eq "(") ? ")" : "]"; + my ($head, @body) = decompose $pattern, $first, $last; + pop @body; + + my $max = -1; + for (@body) { + my $x = max_op($_); + $max = $x if $x > $max; + } + return $max; + } + + return -1; +} + +# Find out the number of alternatives in this insn pattern. +sub num_alts { + my $pattern = shift; + + if ($pattern =~ /^\(match_operand/) { + my ($head, @body) = decompose $pattern, "(", ")"; + $body[3] =~ /"([^"]*)"/; + return 1 + $1 =~ tr/,//; + } + + if ($pattern =~ /^[([]/) { + my $first = substr $pattern, 0, 1; + my $last = ($first eq "(") ? ")" : "]"; + my ($head, @body) = decompose $pattern, $first, $last; + pop @body; + + my $max = 1; + for (@body) { + my $x = num_alts($_); + $max = $x if $x > $max; + } + return $max; + } + + return 1; +} + +# Make the various new patterns used in the two "define_insn"s and the +# two "define_split"s we manufacture: a "dot" pattern for the "compare +# the result of the insn to zero, and clobber" version; a "dot2" pattern +# for the "compare and set" version; and a "split" pattern for the result +# of the splitters. +# +# If the original pattern is a parallel, the set of the GPR that the dot +# compare uses has to be first. +sub make_dotpatterns { + my ($pattern, $n_ops, $n_alts) = @_; + + my ($head, @body) = decompose $pattern, "[", "]"; + my $tail = pop @body; + + my $first = shift @body; + my ($ihead, @ibody) = decompose $first, "(", ")"; + my $itail = pop @ibody; + die "$ARGV: insn not a valid SET in define_dot_insn pattern: $pattern\n" + if $ibody[0] !~ /^set\b/ or scalar @ibody != 3; + my ($set, $dst, $src) = @ibody; + + my $compare = "(compare:CC\n\t$src\n\t(const_int 0))"; + $compare = double_constraints $compare; + my $constraint = (",x" x $n_alts) . (",?y" x $n_alts); + $constraint =~ s/^,/=/; + + my $set_cc = "$set(match_operand:CC $n_ops " . + qq/"cc_reg_operand" "$constraint")\n /; + + my @double_body = map { double_constraints $_ } @body; + + my $dotset = "(clobber $dst" =~ s/\).*/))/r =~ s/operand/scratch/r; + $dotset =~ s/"[^"]*"$ws//; + $dotset = double_constraints $dotset; + my $dotpat = "$head$ihead$set_cc$compare)"; + $dotpat .= "\n @double_body" if scalar @body; + $dotpat .= "\n $dotset$tail"; + + my $src_dup = make_match_dups $src; + my $dot2set = double_constraints "$ihead$set$dst$src_dup$itail"; + my $dot2pat = "$head$ihead$set_cc$compare)\n $dot2set"; + $dot2pat .= "@double_body" if scalar @body; + $dot2pat .= $tail; + + my @dup_body = map { make_match_dups $_ } @body; + + my $dup = make_match_dups $first; + my @dd = decompose $dup, "(", ")"; + $dd[2] =~ s/\).*/)/; + my $comp = "(set (match_dup $n_ops)\n\t" . + "(compare:CC $dd[2]\n\t\t " . + "(const_int 0)))"; + my $splitpat = "$dup"; + $splitpat = "(parallel [\n $splitpat@dup_body])" if (scalar @body); + $splitpat = "$head$splitpat\n $comp$tail"; + + return ($dotpat, $dot2pat, $splitpat); +} + +# Construct an output template suitable for the dot instructions: change +# the mnemonics to include the ".", and add "#" alternatives for the split. +sub make_dottemplate { + my ($template, $n_alts) = @_; + + die "$ARGV: template not a string: $template\n" if $template !~ /^"/; + + $template =~ s/^"(?:\s*@\s*)?//; + $template =~ s/(^\s*+\S++)/$1./mg; + my $hashes = "\n #" x $n_alts; + $template =~ s/"/$hashes"/; + return qq/"@\n $template/; +} + +# Change a set_attr with multiple alternatives to have those alternatives +# twice, that is, for the split versions as well. +sub make_dotattr { + my $attr = shift; + + die "$ARGV: syntax error in attr: $attr\n" if $attr !~ /^\(/; + + my ($head, @body) = decompose $attr, "(", ")"; + + $body[2] =~ s/"([^"]*)"/"$1,$1"/ + if $body[0] =~ /^set_attr\b/ + and $body[2] =~ /,/; + + return "$head@body"; +} + +# Make an attribute vector for a dot insn: double all existing attributes, +# add a "length" attribute, add a "dot" attribute. +# +# This currently only supports single insns in the pattern. +sub make_dotattrs { + my ($attrs, $n_alts) = @_; + + $attrs ||= "[]"; + + my ($head, @body) = decompose $attrs, "[", "]"; + my $tail = pop @body; + + @body = map { make_dotattr($_) } @body; + + my $length_attr = (",4" x $n_alts) . (",8" x $n_alts); + $length_attr =~ s/^,//; + $length_attr = qq/(set_attr "length" "$length_attr")\n /; + + my $dot_attr = (",yes" x $n_alts) . (",no" x $n_alts); + $dot_attr =~ s/^,//; + $dot_attr = qq/(set_attr "dot" "$dot_attr")/; + $dot_attr .= "\n " unless $attrs eq "[]"; + + return "$head$length_attr$dot_attr@body$tail"; +} + +# Split a "define_dot_insn" into the appropriate three "define_insn"s and +# two "define_split"s. +sub handle_define_dot_insn { + my $x = shift; + my ($head, @body) = decompose $x, "(", ")"; + my $tail = pop @body; + + # TODO: check the atom types of @body here? This script might + # die a fiery death if the input file gets it wrong. + + my $define_dot_insn = shift @body; + my $name = shift @body; + my $pattern = shift @body; + my $cond = shift @body; + my $dotcond = shift @body; + my $template = shift @body; + my $attrs = shift @body; + + my $n_ops = 1 + max_op $pattern; + my $n_alts = num_alts $pattern; + + my $define_insn = $define_dot_insn =~ s/dot_//r; + my $define_split = $name =~ s/^"[^"]*"/define_split/r; + + my $name1 = $name =~ s/^"\*?([^"]*)/"*$1_dot/r; + my $name2 = $name =~ s/^"\*?([^"]*)/"*$1_dot2/r; + + my ($dotpat, $dot2pat, $splittedpat) = + make_dotpatterns $pattern, $n_ops, $n_alts; + + $dotcond = join_cond $cond, $dotcond; + + my $dottemplate = make_dottemplate $template, $n_alts; + + my $dotattrs = make_dotattrs $attrs, $n_alts; + + my $splitpat = remove_constraints $dotpat; + my $split2pat = remove_constraints $dot2pat; + $splitpat =~ s/cc_reg/cc_reg_not_cr0/; + $split2pat =~ s/cc_reg/cc_reg_not_cr0/; + + my $splitcond = join_cond $dotcond, qq/"reload_completed"\n /; + + my $prep = qq/""/; + + if (not defined $attrs) { + $attrs = ""; + $dottemplate .= "\n "; + } + + print $head; + print $define_insn, $name, $pattern, $cond, $template, $attrs; + print ")\n\n("; + print $define_insn, $name1, $dotpat, $dotcond, $dottemplate, $dotattrs; + print ")\n\n("; + print $define_split, $splitpat, $splitcond, $splittedpat, $prep; + print ")\n\n("; + print $define_insn, $name2, $dot2pat, $dotcond, $dottemplate, $dotattrs; + print ")\n\n("; + print $define_split, $split2pat, $splitcond, $splittedpat, $prep; + print $tail; +} + +sub handle_other { + print @_; +} + + +# Slurp the whole input file. +my $mdm; +{ + local $/; + $mdm = <>; +} + +print "; Generated by mdm.pl; do not edit (edit the .mdm instead).\n"; +print "; vi:ro\n\n\n"; + +# Handle leading whitespace. +$mdm =~ /^($ws?+)/g; +print $1; + +# Finally, handle the rest. +while ($mdm =~ /\G($atom|(?>.))/g) { + my $x = $1; + + $x =~ /^\((\w+)/ or die "$ARGV: bad toplevel construct:\n$x\n"; + + if ($1 eq "define_dot_insn") { + handle_define_dot_insn $x; + } else { + handle_other $x; + } +} diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6be05a4..7adde36 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -149,6 +149,9 @@ (define_c_enum "unspecv" (define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto" (const_string "integer")) +;; Is this instruction a "dot" (record) instruction or not? +(define_attr "dot" "no,yes" (const_string "no")) + ;; Define floating point instruction sub-types for use with Xfpu.md (define_attr "fp_type" "fp_default,fp_addsub_s,fp_addsub_d,fp_mul_s,fp_mul_d,fp_div_s,fp_div_d,fp_maddsub_s,fp_maddsub_d,fp_sqrt_s,fp_sqrt_d" (const_string "fp_default")) @@ -361,6 +364,8 @@ (define_mode_attr E500_CONVERT [(SF "!TARGET_FPRS") (define_mode_attr TARGET_FLOAT [(SF "TARGET_SINGLE_FLOAT") (DF "TARGET_DOUBLE_FLOAT")]) +(include "integer.md") + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -7671,83 +7676,6 @@ (define_split (const_int 0)))] "") -(define_expand "lshrdi3" - [(set (match_operand:DI 0 "gpc_reg_operand" "") - (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "reg_or_cint_operand" "")))] - "TARGET_POWERPC64" - "") - -(define_insn "*lshrdi3_internal1" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") - (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,i")))] - "TARGET_POWERPC64" - "@ - srd %0,%1,%2 - srdi %0,%1,%H2" - [(set_attr "type" "var_shift_rotate,shift")]) - -(define_insn "*lshrdi3_internal2" - [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y") - (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) - (const_int 0))) - (clobber (match_scratch:DI 3 "=r,r,r,r"))] - "TARGET_64BIT " - "@ - srd. %3,%1,%2 - srdi. %3,%1,%H2 - # - #" - [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") - (set_attr "length" "4,4,8,8")]) - -(define_split - [(set (match_operand:CC 0 "cc_reg_not_micro_cr0_operand" "") - (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "reg_or_cint_operand" "")) - (const_int 0))) - (clobber (match_scratch:DI 3 ""))] - "TARGET_POWERPC64 && reload_completed" - [(set (match_dup 3) - (lshiftrt:DI (match_dup 1) (match_dup 2))) - (set (match_dup 0) - (compare:CC (match_dup 3) - (const_int 0)))] - "") - -(define_insn "*lshrdi3_internal3" - [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y") - (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r") - (match_operand:SI 2 "reg_or_cint_operand" "r,i,r,i")) - (const_int 0))) - (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r") - (lshiftrt:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT" - "@ - srd. %0,%1,%2 - srdi. %0,%1,%H2 - # - #" - [(set_attr "type" "var_delayed_compare,delayed_compare,var_delayed_compare,delayed_compare") - (set_attr "length" "4,4,8,8")]) - -(define_split - [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") - (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "") - (match_operand:SI 2 "reg_or_cint_operand" "")) - (const_int 0))) - (set (match_operand:DI 0 "gpc_reg_operand" "") - (lshiftrt:DI (match_dup 1) (match_dup 2)))] - "TARGET_POWERPC64 && reload_completed" - [(set (match_dup 0) - (lshiftrt:DI (match_dup 1) (match_dup 2))) - (set (match_dup 3) - (compare:CC (match_dup 0) - (const_int 0)))] - "") - (define_expand "ashrdi3" [(set (match_operand:DI 0 "gpc_reg_operand" "") (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "") diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000 index ecfdf0e..5e1cf54 100644 --- a/gcc/config/rs6000/t-rs6000 +++ b/gcc/config/rs6000/t-rs6000 @@ -65,6 +65,7 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rs64.md \ $(srcdir)/config/rs6000/a2.md \ $(srcdir)/config/rs6000/predicates.md \ $(srcdir)/config/rs6000/constraints.md \ + $(srcdir)/config/rs6000/integer.md \ $(srcdir)/config/rs6000/darwin.md \ $(srcdir)/config/rs6000/sync.md \ $(srcdir)/config/rs6000/vector.md \ @@ -74,3 +75,8 @@ MD_INCLUDES = $(srcdir)/config/rs6000/rs64.md \ $(srcdir)/config/rs6000/spe.md \ $(srcdir)/config/rs6000/dfp.md \ $(srcdir)/config/rs6000/paired.md + +MDM := $(srcdir)/config/rs6000/mdm.pl + +$(srcdir)/config/rs6000/%.md: $(srcdir)/config/rs6000/%.mdm $(MDM) + $(MDM) $< > $@ || (rm $@ ; exit 1)