From lattner at cs.uiuc.edu Mon Sep 12 00:29:54 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 00:29:54 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/FileParser.y Message-ID: <200509120529.AAA30826@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: FileParser.y updated: 1.35 -> 1.36 --- Log message: Rearrange two rules, which apparently makes some versions of bison happier. --- Diffs of the changes: (+15 -15) FileParser.y | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) Index: llvm/utils/TableGen/FileParser.y diff -u llvm/utils/TableGen/FileParser.y:1.35 llvm/utils/TableGen/FileParser.y:1.36 --- llvm/utils/TableGen/FileParser.y:1.35 Thu Sep 8 13:48:23 2005 +++ llvm/utils/TableGen/FileParser.y Mon Sep 12 00:29:43 2005 @@ -276,21 +276,6 @@ } $$ = Init; delete $2; - } | ID { - if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) { - $$ = new VarInit(*$1, RV->getType()); - } else if (CurRec && CurRec->isTemplateArg(CurRec->getName()+":"+*$1)) { - const RecordVal *RV = CurRec->getValue(CurRec->getName()+":"+*$1); - assert(RV && "Template arg doesn't exist??"); - $$ = new VarInit(CurRec->getName()+":"+*$1, RV->getType()); - } else if (Record *D = Records.getDef(*$1)) { - $$ = new DefInit(D); - } else { - err() << "Variable not defined: '" << *$1 << "'!\n"; - exit(1); - } - - delete $1; } | ID '<' ValueListNE '>' { // This is a CLASS expression. This is supposed to synthesize // a new anonymous definition, deriving from CLASS with no @@ -319,6 +304,21 @@ // Restore the old CurRec CurRec = OldRec; + } | ID { + if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) { + $$ = new VarInit(*$1, RV->getType()); + } else if (CurRec && CurRec->isTemplateArg(CurRec->getName()+":"+*$1)) { + const RecordVal *RV = CurRec->getValue(CurRec->getName()+":"+*$1); + assert(RV && "Template arg doesn't exist??"); + $$ = new VarInit(CurRec->getName()+":"+*$1, RV->getType()); + } else if (Record *D = Records.getDef(*$1)) { + $$ = new DefInit(D); + } else { + err() << "Variable not defined: '" << *$1 << "'!\n"; + exit(1); + } + + delete $1; } | Value '{' BitList '}' { $$ = $1->convertInitializerBitRange(*$3); if ($$ == 0) { From lattner at cs.uiuc.edu Mon Sep 12 00:30:18 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 00:30:18 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/FileLexer.cpp FileParser.cpp FileParser.h Message-ID: <200509120530.AAA31156@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: FileLexer.cpp updated: 1.2 -> 1.3 FileParser.cpp updated: 1.4 -> 1.5 FileParser.h updated: 1.2 -> 1.3 --- Log message: Regenerate --- Diffs of the changes: (+1642 -1193) FileLexer.cpp | 86 - FileParser.cpp | 2629 ++++++++++++++++++++++++++++++++------------------------- FileParser.h | 111 +- 3 files changed, 1642 insertions(+), 1184 deletions(-) Index: llvm/utils/TableGen/FileLexer.cpp diff -u llvm/utils/TableGen/FileLexer.cpp:1.2 llvm/utils/TableGen/FileLexer.cpp:1.3 --- llvm/utils/TableGen/FileLexer.cpp:1.2 Tue Sep 6 16:23:27 2005 +++ llvm/utils/TableGen/FileLexer.cpp Mon Sep 12 00:30:06 2005 @@ -21,7 +21,7 @@ /* A lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header: /home/vadve/shared/PublicCVS/llvm/utils/TableGen/FileLexer.cpp,v 1.2 2005/09/06 21:23:27 lattner Exp $ + * $Header: /home/vadve/shared/PublicCVS/llvm/utils/TableGen/FileLexer.cpp,v 1.3 2005/09/12 05:30:06 lattner Exp $ */ #define FLEX_SCANNER @@ -29,6 +29,7 @@ #define YY_FLEX_MINOR_VERSION 5 #include +#include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ @@ -42,7 +43,6 @@ #ifdef __cplusplus #include -#include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS @@ -489,7 +489,7 @@ #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 1 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" #define INITIAL 0 /*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===// // @@ -507,7 +507,7 @@ #define YY_NEVER_INTERACTIVE 1 #define comment 1 -#line 30 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 30 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" #include "Record.h" typedef std::pair*> SubClassRefTy; #include "FileParser.h" @@ -792,10 +792,10 @@ YY_DECL { register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; + register char *yy_cp = NULL, *yy_bp = NULL; register int yy_act; -#line 176 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 176 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" #line 802 "Lexer.cpp" @@ -891,165 +891,165 @@ { /* beginning of action switch */ case 1: YY_RULE_SETUP -#line 178 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 178 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { /* Ignore comments */ } YY_BREAK case 2: YY_RULE_SETUP -#line 180 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 180 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { HandleInclude(yytext); } YY_BREAK case 3: YY_RULE_SETUP -#line 181 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 181 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2); return CODEFRAGMENT; } YY_BREAK case 4: YY_RULE_SETUP -#line 184 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 184 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return INT; } YY_BREAK case 5: YY_RULE_SETUP -#line 185 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 185 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return BIT; } YY_BREAK case 6: YY_RULE_SETUP -#line 186 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 186 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return BITS; } YY_BREAK case 7: YY_RULE_SETUP -#line 187 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 187 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return STRING; } YY_BREAK case 8: YY_RULE_SETUP -#line 188 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 188 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return LIST; } YY_BREAK case 9: YY_RULE_SETUP -#line 189 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 189 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return CODE; } YY_BREAK case 10: YY_RULE_SETUP -#line 190 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 190 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return DAG; } YY_BREAK case 11: YY_RULE_SETUP -#line 192 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 192 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return CLASS; } YY_BREAK case 12: YY_RULE_SETUP -#line 193 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 193 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return DEF; } YY_BREAK case 13: YY_RULE_SETUP -#line 194 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 194 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return FIELD; } YY_BREAK case 14: YY_RULE_SETUP -#line 195 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 195 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return LET; } YY_BREAK case 15: YY_RULE_SETUP -#line 196 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 196 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return IN; } YY_BREAK case 16: YY_RULE_SETUP -#line 198 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 198 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return SRATOK; } YY_BREAK case 17: YY_RULE_SETUP -#line 199 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 199 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return SRLTOK; } YY_BREAK case 18: YY_RULE_SETUP -#line 200 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 200 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return SHLTOK; } YY_BREAK case 19: YY_RULE_SETUP -#line 203 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 203 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { Filelval.StrVal = new std::string(yytext, yytext+yyleng); return ID; } YY_BREAK case 20: YY_RULE_SETUP -#line 205 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 205 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng); return VARNAME; } YY_BREAK case 21: YY_RULE_SETUP -#line 208 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 208 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1); return STRVAL; } YY_BREAK case 22: YY_RULE_SETUP -#line 211 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 211 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { Filelval.IntVal = ParseInt(Filetext); return INTVAL; } YY_BREAK case 23: YY_RULE_SETUP -#line 213 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 213 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { /* Ignore whitespace */ } YY_BREAK case 24: YY_RULE_SETUP -#line 216 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 216 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { BEGIN(comment); CommentDepth++; } YY_BREAK case 25: YY_RULE_SETUP -#line 217 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 217 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" {} /* eat anything that's not a '*' or '/' */ YY_BREAK case 26: YY_RULE_SETUP -#line 218 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 218 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" {} /* eat up '*'s not followed by '/'s */ YY_BREAK case 27: YY_RULE_SETUP -#line 219 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 219 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { ++CommentDepth; } YY_BREAK case 28: YY_RULE_SETUP -#line 220 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 220 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" {} /* eat up /'s not followed by *'s */ YY_BREAK case 29: YY_RULE_SETUP -#line 221 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 221 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { if (!--CommentDepth) { BEGIN(INITIAL); } } YY_BREAK case YY_STATE_EOF(comment): -#line 222 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 222 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { err() << "Unterminated comment!\n"; exit(1); } YY_BREAK case 30: YY_RULE_SETUP -#line 224 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 224 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" { return Filetext[0]; } YY_BREAK case 31: YY_RULE_SETUP -#line 226 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 226 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK #line 1056 "Lexer.cpp" @@ -1430,6 +1430,7 @@ #endif /* ifndef YY_NO_UNPUT */ +#ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput() #else @@ -1503,7 +1504,7 @@ return c; } - +#endif /* YY_NO_INPUT */ #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) @@ -1614,11 +1615,6 @@ } -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -extern int isatty YY_PROTO(( int )); -#endif -#endif #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) @@ -1936,5 +1932,5 @@ return 0; } #endif -#line 226 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileLexer.l" +#line 226 "/home/vadve/lattner/llvm/utils/TableGen/FileLexer.l" Index: llvm/utils/TableGen/FileParser.cpp diff -u llvm/utils/TableGen/FileParser.cpp:1.4 llvm/utils/TableGen/FileParser.cpp:1.5 --- llvm/utils/TableGen/FileParser.cpp:1.4 Thu Sep 8 14:47:28 2005 +++ llvm/utils/TableGen/FileParser.cpp Mon Sep 12 00:30:06 2005 @@ -1,38 +1,115 @@ +/* A Bison parser, made by GNU Bison 1.875. */ -/* A Bison parser, made from /Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y - by GNU Bison version 1.28 */ +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. -#define YYBISON 1 /* Identify Bison output. */ + This program 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 2, or (at your option) + any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ #define yyparse Fileparse -#define yylex Filelex +#define yylex Filelex #define yyerror Fileerror -#define yylval Filelval -#define yychar Filechar +#define yylval Filelval +#define yychar Filechar #define yydebug Filedebug #define yynerrs Filenerrs -#define INT 257 -#define BIT 258 -#define STRING 259 -#define BITS 260 -#define LIST 261 -#define CODE 262 -#define DAG 263 -#define CLASS 264 -#define DEF 265 -#define FIELD 266 -#define LET 267 -#define IN 268 -#define SHLTOK 269 -#define SRATOK 270 -#define SRLTOK 271 -#define INTVAL 272 -#define ID 273 -#define VARNAME 274 -#define STRVAL 275 -#define CODEFRAGMENT 276 -#line 14 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + INT = 258, + BIT = 259, + STRING = 260, + BITS = 261, + LIST = 262, + CODE = 263, + DAG = 264, + CLASS = 265, + DEF = 266, + FIELD = 267, + LET = 268, + IN = 269, + SHLTOK = 270, + SRATOK = 271, + SRLTOK = 272, + INTVAL = 273, + ID = 274, + VARNAME = 275, + STRVAL = 276, + CODEFRAGMENT = 277 + }; +#endif +#define INT 258 +#define BIT 259 +#define STRING 260 +#define BITS 261 +#define LIST 262 +#define CODE 263 +#define DAG 264 +#define CLASS 265 +#define DEF 266 +#define FIELD 267 +#define LET 268 +#define IN 269 +#define SHLTOK 270 +#define SRATOK 271 +#define SRLTOK 272 +#define INTVAL 273 +#define ID 274 +#define VARNAME 275 +#define STRVAL 276 +#define CODEFRAGMENT 277 + + + + +/* Copy the first part of user declarations. */ +#line 14 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" #include "Record.h" #include "llvm/ADT/StringExtras.h" @@ -207,8 +284,23 @@ using namespace llvm; -#line 189 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -typedef union { + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 189 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" +typedef union YYSTYPE { std::string* StrVal; int IntVal; llvm::RecTy* Ty; @@ -220,537 +312,831 @@ std::vector* SubClassList; std::vector >* DagValueList; } YYSTYPE; -#include +/* Line 191 of yacc.c. */ +#line 316 "FileParser.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 214 of yacc.c. */ +#line 328 "FileParser.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) -#ifndef __cplusplus -#ifndef __STDC__ -#define const -#endif #endif +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif - -#define YYFINAL 155 -#define YYFLAG -32768 -#define YYNTBASE 38 - -#define YYTRANSLATE(x) ((unsigned)(x) <= 276 ? yytranslate[x] : 74) - -static const char yytranslate[] = { 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, - 33, 2, 2, 34, 36, 31, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 35, 37, 23, - 25, 24, 26, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 29, 2, 30, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 27, 2, 28, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22 +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 18 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 153 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 38 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 37 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 85 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 155 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 277 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 32, 33, 2, 2, 34, 36, 31, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 35, 37, + 23, 25, 24, 26, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 29, 2, 30, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 27, 2, 28, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22 }; -#if YYDEBUG != 0 -static const short yyprhs[] = { 0, - 0, 2, 4, 6, 11, 13, 18, 20, 22, 24, - 25, 27, 28, 31, 33, 35, 37, 39, 43, 45, - 50, 55, 59, 63, 68, 73, 80, 87, 94, 95, - 98, 101, 106, 107, 109, 111, 115, 118, 122, 128, - 133, 135, 136, 140, 141, 143, 145, 149, 154, 157, - 164, 165, 168, 170, 174, 176, 181, 183, 187, 188, - 191, 193, 197, 201, 202, 204, 206, 207, 208, 209, - 216, 219, 222, 224, 226, 231, 233, 237, 238, 243, - 248, 251, 253, 256 +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short yyprhs[] = +{ + 0, 0, 3, 5, 7, 9, 14, 16, 21, 23, + 25, 27, 28, 30, 31, 34, 36, 38, 40, 42, + 46, 51, 53, 58, 62, 66, 71, 76, 83, 90, + 97, 98, 101, 104, 109, 110, 112, 114, 118, 121, + 125, 131, 136, 138, 139, 143, 144, 146, 148, 152, + 157, 160, 167, 168, 171, 173, 177, 179, 184, 186, + 190, 191, 194, 196, 200, 204, 205, 207, 209, 210, + 211, 212, 219, 222, 225, 227, 229, 234, 236, 240, + 241, 246, 251, 254, 256, 259 }; -static const short yyrhs[] = { 19, - 0, 5, 0, 4, 0, 6, 23, 18, 24, 0, - 3, 0, 7, 23, 39, 24, 0, 8, 0, 9, - 0, 38, 0, 0, 12, 0, 0, 25, 42, 0, - 18, 0, 21, 0, 22, 0, 26, 0, 27, 49, - 28, 0, 19, 0, 19, 23, 50, 24, 0, 42, - 27, 47, 28, 0, 29, 49, 30, 0, 42, 31, - 19, 0, 32, 19, 45, 33, 0, 42, 29, 47, - 30, 0, 15, 32, 42, 34, 42, 33, 0, 16, - 32, 42, 34, 42, 33, 0, 17, 32, 42, 34, - 42, 33, 0, 0, 35, 20, 0, 42, 43, 0, - 44, 34, 42, 43, 0, 0, 44, 0, 18, 0, - 18, 36, 18, 0, 18, 18, 0, 46, 34, 18, - 0, 46, 34, 18, 36, 18, 0, 46, 34, 18, - 18, 0, 46, 0, 0, 27, 47, 28, 0, 0, - 50, 0, 42, 0, 50, 34, 42, 0, 40, 39, - 19, 41, 0, 51, 37, 0, 13, 19, 48, 25, - 42, 37, 0, 0, 53, 52, 0, 37, 0, 27, - 53, 28, 0, 38, 0, 38, 23, 50, 24, 0, - 55, 0, 56, 34, 55, 0, 0, 35, 56, 0, - 51, 0, 58, 34, 51, 0, 23, 58, 24, 0, - 0, 59, 0, 19, 0, 0, 0, 0, 61, 63, - 60, 57, 64, 54, 0, 10, 62, 0, 11, 62, - 0, 65, 0, 66, 0, 19, 48, 25, 42, 0, - 68, 0, 69, 34, 68, 0, 0, 13, 71, 69, - 14, 0, 70, 27, 72, 28, 0, 70, 67, 0, - 67, 0, 72, 67, 0, 72, 0 +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 74, 0, -1, 19, -1, 5, -1, 4, -1, 6, + 23, 18, 24, -1, 3, -1, 7, 23, 40, 24, + -1, 8, -1, 9, -1, 39, -1, -1, 12, -1, + -1, 25, 43, -1, 18, -1, 21, -1, 22, -1, + 26, -1, 27, 50, 28, -1, 19, 23, 51, 24, + -1, 19, -1, 43, 27, 48, 28, -1, 29, 50, + 30, -1, 43, 31, 19, -1, 32, 19, 46, 33, + -1, 43, 29, 48, 30, -1, 15, 32, 43, 34, + 43, 33, -1, 16, 32, 43, 34, 43, 33, -1, + 17, 32, 43, 34, 43, 33, -1, -1, 35, 20, + -1, 43, 44, -1, 45, 34, 43, 44, -1, -1, + 45, -1, 18, -1, 18, 36, 18, -1, 18, 18, + -1, 47, 34, 18, -1, 47, 34, 18, 36, 18, + -1, 47, 34, 18, 18, -1, 47, -1, -1, 27, + 48, 28, -1, -1, 51, -1, 43, -1, 51, 34, + 43, -1, 41, 40, 19, 42, -1, 52, 37, -1, + 13, 19, 49, 25, 43, 37, -1, -1, 54, 53, + -1, 37, -1, 27, 54, 28, -1, 39, -1, 39, + 23, 51, 24, -1, 56, -1, 57, 34, 56, -1, + -1, 35, 57, -1, 52, -1, 59, 34, 52, -1, + 23, 59, 24, -1, -1, 60, -1, 19, -1, -1, + -1, -1, 62, 64, 61, 58, 65, 55, -1, 10, + 63, -1, 11, 63, -1, 66, -1, 67, -1, 19, + 49, 25, 43, -1, 69, -1, 70, 34, 69, -1, + -1, 13, 72, 70, 14, -1, 71, 27, 73, 28, + -1, 71, 68, -1, 68, -1, 73, 68, -1, 73, + -1 }; -#endif - -#if YYDEBUG != 0 -static const short yyrline[] = { 0, - 223, 234, 236, 238, 240, 242, 244, 246, 248, 252, - 252, 254, 254, 256, 258, 261, 264, 266, 279, 294, - 322, 329, 332, 339, 347, 355, 361, 367, 375, 378, - 382, 387, 393, 396, 399, 402, 415, 429, 431, 444, - 460, 462, 462, 466, 468, 472, 475, 479, 489, 491, - 497, 497, 498, 498, 500, 502, 506, 511, 516, 519, - 523, 526, 531, 532, 532, 534, 534, 536, 543, 558, - 563, 571, 589, 589, 591, 596, 596, 599, 599, 602, - 605, 609, 609, 611 +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short yyrline[] = +{ + 0, 223, 223, 234, 236, 238, 240, 242, 244, 246, + 248, 252, 252, 254, 254, 256, 258, 261, 264, 266, + 279, 307, 322, 329, 332, 339, 347, 355, 361, 367, + 375, 378, 382, 387, 393, 396, 399, 402, 415, 429, + 431, 444, 460, 462, 462, 466, 468, 472, 475, 479, + 489, 491, 497, 497, 498, 498, 500, 502, 506, 511, + 516, 519, 523, 526, 531, 532, 532, 534, 534, 536, + 543, 536, 563, 571, 589, 589, 591, 596, 596, 599, + 599, 602, 605, 609, 609, 611 }; #endif - -#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) - -static const char * const yytname[] = { "$","error","$undefined.","INT","BIT", -"STRING","BITS","LIST","CODE","DAG","CLASS","DEF","FIELD","LET","IN","SHLTOK", -"SRATOK","SRLTOK","INTVAL","ID","VARNAME","STRVAL","CODEFRAGMENT","'<'","'>'", -"'='","'?'","'{'","'}'","'['","']'","'.'","'('","')'","','","':'","'-'","';'", -"ClassID","Type","OptPrefix","OptValue","Value","OptVarName","DagArgListNE", -"DagArgList","RBitList","BitList","OptBitList","ValueList","ValueListNE","Declaration", -"BodyItem","BodyList","Body","SubClassRef","ClassListNE","ClassList","DeclListNE", -"TemplateArgList","OptTemplateArgList","OptID","ObjectBody","@1","@2","ClassInst", -"DefInst","Object","LETItem","LETList","LETCommand","@3","ObjectList","File", NULL +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "INT", "BIT", "STRING", "BITS", "LIST", + "CODE", "DAG", "CLASS", "DEF", "FIELD", "LET", "IN", "SHLTOK", "SRATOK", + "SRLTOK", "INTVAL", "ID", "VARNAME", "STRVAL", "CODEFRAGMENT", "'<'", + "'>'", "'='", "'?'", "'{'", "'}'", "'['", "']'", "'.'", "'('", "')'", + "','", "':'", "'-'", "';'", "$accept", "ClassID", "Type", "OptPrefix", + "OptValue", "Value", "OptVarName", "DagArgListNE", "DagArgList", + "RBitList", "BitList", "OptBitList", "ValueList", "ValueListNE", + "Declaration", "BodyItem", "BodyList", "Body", "SubClassRef", + "ClassListNE", "ClassList", "DeclListNE", "TemplateArgList", + "OptTemplateArgList", "OptID", "ObjectBody", "@1", "@2", "ClassInst", + "DefInst", "Object", "LETItem", "LETList", "LETCommand", "@3", + "ObjectList", "File", 0 }; #endif -static const short yyr1[] = { 0, - 38, 39, 39, 39, 39, 39, 39, 39, 39, 40, - 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, - 44, 44, 45, 45, 46, 46, 46, 46, 46, 46, - 47, 48, 48, 49, 49, 50, 50, 51, 52, 52, - 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, - 58, 58, 59, 60, 60, 61, 61, 63, 64, 62, - 65, 66, 67, 67, 68, 69, 69, 71, 70, 67, - 67, 72, 72, 73 +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 60, 62, 61, 63, 123, 125, 91, + 93, 46, 40, 41, 44, 58, 45, 59 }; +# endif -static const short yyr2[] = { 0, - 1, 1, 1, 4, 1, 4, 1, 1, 1, 0, - 1, 0, 2, 1, 1, 1, 1, 3, 1, 4, - 4, 3, 3, 4, 4, 6, 6, 6, 0, 2, - 2, 4, 0, 1, 1, 3, 2, 3, 5, 4, - 1, 0, 3, 0, 1, 1, 3, 4, 2, 6, - 0, 2, 1, 3, 1, 4, 1, 3, 0, 2, - 1, 3, 3, 0, 1, 1, 0, 0, 0, 6, - 2, 2, 1, 1, 4, 1, 3, 0, 4, 4, - 2, 1, 2, 1 +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 38, 39, 40, 40, 40, 40, 40, 40, 40, + 40, 41, 41, 42, 42, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 44, 44, 45, 45, 46, 46, 47, 47, 47, 47, + 47, 47, 48, 49, 49, 50, 50, 51, 51, 52, + 53, 53, 54, 54, 55, 55, 56, 56, 57, 57, + 58, 58, 59, 59, 60, 61, 61, 62, 62, 64, + 65, 63, 66, 67, 68, 68, 69, 70, 70, 72, + 71, 68, 68, 73, 73, 74 }; -static const short yydefact[] = { 0, - 67, 67, 78, 73, 74, 82, 0, 84, 66, 68, - 71, 72, 0, 0, 81, 83, 64, 42, 76, 0, - 0, 10, 65, 59, 0, 0, 79, 0, 80, 11, - 0, 61, 0, 0, 69, 35, 41, 0, 0, 77, - 5, 3, 2, 0, 0, 7, 8, 1, 9, 0, - 63, 10, 55, 57, 60, 0, 37, 0, 0, 43, - 0, 0, 0, 14, 19, 15, 16, 17, 44, 44, - 0, 75, 0, 0, 12, 62, 0, 0, 51, 53, - 70, 36, 38, 0, 0, 0, 0, 46, 0, 45, - 0, 33, 0, 0, 0, 0, 0, 0, 48, 0, - 58, 10, 40, 0, 0, 0, 0, 0, 18, 0, - 22, 29, 34, 0, 0, 0, 23, 4, 6, 13, - 56, 0, 54, 0, 52, 39, 0, 0, 0, 20, - 47, 0, 31, 0, 24, 21, 25, 42, 49, 0, - 0, 0, 30, 29, 0, 26, 27, 28, 32, 0, - 0, 50, 0, 0, 0 +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 1, 1, 4, 1, 4, 1, 1, + 1, 0, 1, 0, 2, 1, 1, 1, 1, 3, + 4, 1, 4, 3, 3, 4, 4, 6, 6, 6, + 0, 2, 2, 4, 0, 1, 1, 3, 2, 3, + 5, 4, 1, 0, 3, 0, 1, 1, 3, 4, + 2, 6, 0, 2, 1, 3, 1, 4, 1, 3, + 0, 2, 1, 3, 3, 0, 1, 1, 0, 0, + 0, 6, 2, 2, 1, 1, 4, 1, 3, 0, + 4, 4, 2, 1, 2, 1 }; -static const short yydefgoto[] = { 49, - 50, 31, 99, 88, 133, 113, 114, 37, 38, 26, - 89, 90, 32, 125, 102, 81, 54, 55, 35, 33, - 23, 24, 10, 11, 17, 56, 4, 5, 6, 19, - 20, 7, 13, 8, 153 +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 68, 68, 79, 74, 75, 83, 0, 85, 0, + 67, 69, 72, 73, 0, 0, 82, 84, 1, 65, + 43, 77, 0, 0, 11, 66, 60, 0, 0, 80, + 0, 81, 12, 0, 62, 0, 0, 70, 36, 42, + 0, 0, 78, 6, 4, 3, 0, 0, 8, 9, + 2, 10, 0, 64, 11, 56, 58, 61, 0, 38, + 0, 0, 44, 0, 0, 0, 15, 21, 16, 17, + 18, 45, 45, 0, 76, 0, 0, 13, 63, 0, + 0, 52, 54, 71, 37, 39, 0, 0, 0, 0, + 47, 0, 46, 0, 34, 0, 0, 0, 0, 0, + 0, 49, 0, 59, 11, 41, 0, 0, 0, 0, + 0, 19, 0, 23, 30, 35, 0, 0, 0, 24, + 5, 7, 14, 57, 0, 55, 0, 53, 40, 0, + 0, 0, 20, 48, 0, 32, 0, 25, 22, 26, + 43, 50, 0, 0, 0, 31, 30, 0, 27, 28, + 29, 33, 0, 0, 51 }; -static const short yypact[] = { 45, - -10, -10,-32768,-32768,-32768,-32768, 4, 45,-32768,-32768, --32768,-32768, -3, 45,-32768,-32768, 12, -7,-32768, -12, - -5, 24,-32768, 39, 23, 25,-32768, -3,-32768,-32768, - 57,-32768, 15, 64,-32768, -15, 51, 58, 11,-32768, --32768,-32768,-32768, 68, 70,-32768,-32768,-32768,-32768, 78, --32768, 24, 80,-32768, 67, 17,-32768, 89, 91,-32768, - 94, 95, 96,-32768, 98,-32768,-32768,-32768, 11, 11, - 104, 93, 107, 57, 105,-32768, 11, 64,-32768,-32768, --32768,-32768, -11, 11, 11, 11, 11, 93, 101, 97, - 102, 11, 23, 23, 114, 110, 111, 11,-32768, 18, --32768, 6,-32768, 118, 53, 65, 71, 33,-32768, 11, --32768, 46, 103, 106, 112, 108,-32768,-32768,-32768, 93, --32768, 122,-32768, 109,-32768,-32768, 11, 11, 11,-32768, - 93, 123,-32768, 11,-32768,-32768,-32768, -7,-32768, 77, - 85, 86,-32768, 46, 117,-32768,-32768,-32768,-32768, 11, - 41,-32768, 144, 145,-32768 +/* YYDEFGOTO[NTERM-NUM]. */ +static const short yydefgoto[] = +{ + -1, 51, 52, 33, 101, 90, 135, 115, 116, 39, + 40, 28, 91, 92, 34, 127, 104, 83, 56, 57, + 37, 35, 25, 26, 11, 12, 19, 58, 4, 5, + 6, 21, 22, 7, 14, 8, 9 }; -static const short yypgoto[] = { -30, - 73,-32768,-32768, -39, 5,-32768,-32768,-32768, -81, 10, - 81, -8, -51,-32768,-32768,-32768, 72,-32768,-32768,-32768, --32768,-32768,-32768, 150,-32768,-32768,-32768,-32768, 3, 125, --32768,-32768,-32768, 140,-32768 +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -61 +static const yysigned_char yypact[] = +{ + 45, -7, -7, -61, -61, -61, -61, 4, 45, 24, + -61, -61, -61, -61, 31, 45, -61, -61, -61, 29, + 46, -61, -12, -5, 62, -61, 40, 63, 68, -61, + 31, -61, -61, 57, -61, -14, 78, -61, -15, 67, + 75, 11, -61, -61, -61, -61, 84, 96, -61, -61, + -61, -61, 90, -61, 62, 97, -61, 87, 12, -61, + 104, 105, -61, 92, 93, 94, -61, 106, -61, -61, + -61, 11, 11, 108, 86, 110, 57, 107, -61, 11, + 78, -61, -61, -61, -61, -11, 11, 11, 11, 11, + 86, 102, 99, 101, 11, 63, 63, 115, 111, 112, + 11, -61, 20, -61, 6, -61, 119, -18, 65, 71, + 43, -61, 11, -61, 56, 109, 113, 114, 117, -61, + -61, -61, 86, -61, 120, -61, 103, -61, -61, 11, + 11, 11, -61, 86, 118, -61, 11, -61, -61, -61, + 46, -61, 53, 77, 85, -61, 56, 116, -61, -61, + -61, -61, 11, 41, -61 }; - -#define YYLAST 154 - - -static const short yytable[] = { 72, - 76, 27, 57, 53, 1, 2, 103, 3, 9, 15, - 16, 115, 116, 1, 2, 18, 3, 30, 122, 25, - 58, 28, 29, 16, 104, 61, 62, 63, 64, 65, - 14, 66, 67, 123, 22, 30, 68, 69, 51, 70, - 36, 121, 71, 79, 105, 106, 107, 53, 52, 39, - 124, 110, 112, 80, 1, 2, 130, 3, 120, 41, - 42, 43, 44, 45, 46, 47, 110, 93, 100, 94, - 131, 95, 93, 34, 94, 48, 95, 152, 108, 93, - 132, 94, 48, 95, 59, 60, 127, 140, 141, 142, - 73, 93, 74, 94, 144, 95, 75, 93, 128, 94, - 78, 95, 77, 93, 129, 94, 82, 95, 83, 146, - 151, 93, 93, 94, 94, 95, 95, 147, 148, 93, - 87, 94, 92, 95, 96, 84, 85, 86, 109, 98, - 110, 111, 117, 118, 119, 126, 134, 137, 135, 136, - 138, 150, 143, 154, 155, 139, 97, 145, 149, 101, - 91, 12, 40, 21 +/* YYPGOTO[NTERM-NUM]. */ +static const short yypgoto[] = +{ + -61, -32, 69, -61, -61, -41, -2, -61, -61, -61, + -60, 8, 79, -10, -53, -61, -61, -61, 70, -61, + -61, -61, -61, -61, -61, 147, -61, -61, -61, -61, + 34, 122, -61, -61, -61, 138, -61 }; -static const short yycheck[] = { 39, - 52, 14, 18, 34, 10, 11, 18, 13, 19, 7, - 8, 93, 94, 10, 11, 19, 13, 12, 13, 27, - 36, 34, 28, 21, 36, 15, 16, 17, 18, 19, - 27, 21, 22, 28, 23, 12, 26, 27, 24, 29, - 18, 24, 32, 27, 84, 85, 86, 78, 34, 25, - 102, 34, 92, 37, 10, 11, 24, 13, 98, 3, - 4, 5, 6, 7, 8, 9, 34, 27, 77, 29, - 110, 31, 27, 35, 29, 19, 31, 37, 87, 27, - 35, 29, 19, 31, 34, 28, 34, 127, 128, 129, - 23, 27, 23, 29, 134, 31, 19, 27, 34, 29, - 34, 31, 23, 27, 34, 29, 18, 31, 18, 33, - 150, 27, 27, 29, 29, 31, 31, 33, 33, 27, - 23, 29, 19, 31, 18, 32, 32, 32, 28, 25, - 34, 30, 19, 24, 24, 18, 34, 30, 33, 28, - 19, 25, 20, 0, 0, 37, 74, 138, 144, 78, - 70, 2, 28, 14 +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 74, 78, 29, 59, 55, 1, 2, 105, 3, 95, + 53, 96, 10, 97, 1, 2, 129, 3, 32, 124, + 54, 60, 30, 31, 18, 106, 63, 64, 65, 66, + 67, 15, 68, 69, 125, 117, 118, 70, 71, 81, + 72, 16, 17, 73, 123, 107, 108, 109, 55, 82, + 20, 126, 24, 114, 112, 1, 2, 17, 3, 122, + 43, 44, 45, 46, 47, 48, 49, 132, 95, 102, + 96, 133, 97, 27, 32, 36, 50, 112, 154, 110, + 95, 38, 96, 95, 97, 96, 148, 97, 142, 143, + 144, 134, 95, 41, 96, 146, 97, 50, 95, 130, + 96, 61, 97, 62, 95, 131, 96, 75, 97, 77, + 149, 153, 95, 95, 96, 96, 97, 97, 150, 76, + 79, 80, 84, 85, 86, 87, 88, 94, 98, 89, + 111, 113, 100, 112, 119, 120, 121, 128, 145, 140, + 141, 152, 138, 136, 151, 99, 137, 139, 147, 13, + 103, 93, 42, 23 }; -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/share/bison.simple" -/* This file comes from bison-1.28. */ -/* Skeleton output parser for bison, - Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. - - This program 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 2, or (at your option) - any later version. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ +static const unsigned char yycheck[] = +{ + 41, 54, 14, 18, 36, 10, 11, 18, 13, 27, + 24, 29, 19, 31, 10, 11, 34, 13, 12, 13, + 34, 36, 34, 28, 0, 36, 15, 16, 17, 18, + 19, 27, 21, 22, 28, 95, 96, 26, 27, 27, + 29, 7, 8, 32, 24, 86, 87, 88, 80, 37, + 19, 104, 23, 94, 34, 10, 11, 23, 13, 100, + 3, 4, 5, 6, 7, 8, 9, 24, 27, 79, + 29, 112, 31, 27, 12, 35, 19, 34, 37, 89, + 27, 18, 29, 27, 31, 29, 33, 31, 129, 130, + 131, 35, 27, 25, 29, 136, 31, 19, 27, 34, + 29, 34, 31, 28, 27, 34, 29, 23, 31, 19, + 33, 152, 27, 27, 29, 29, 31, 31, 33, 23, + 23, 34, 18, 18, 32, 32, 32, 19, 18, 23, + 28, 30, 25, 34, 19, 24, 24, 18, 20, 19, + 37, 25, 28, 34, 146, 76, 33, 30, 140, 2, + 80, 72, 30, 15 +}; -/* This is the parser code that is written into each bison parser - when the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -#ifndef YYSTACK_USE_ALLOCA -#ifdef alloca -#define YYSTACK_USE_ALLOCA -#else /* alloca not defined */ -#ifdef __GNUC__ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#else /* not GNU C. */ -#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) -#define YYSTACK_USE_ALLOCA -#include -#else /* not sparc */ -/* We think this test detects Watcom and Microsoft C. */ -/* This used to test MSDOS, but that is a bad idea - since that symbol is in the user namespace. */ -#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) -#if 0 /* No need for malloc.h, which pollutes the namespace; - instead, just don't use alloca. */ -#include -#endif -#else /* not MSDOS, or __TURBOC__ */ -#if defined(_AIX) -/* I don't know what this was needed for, but it pollutes the namespace. - So I turned it off. rms, 2 May 1997. */ -/* #include */ - #pragma alloca -#define YYSTACK_USE_ALLOCA -#else /* not MSDOS, or __TURBOC__, or _AIX */ -#if 0 -#ifdef __hpux /* haible at ilog.fr says this works for HPUX 9.05 and up, - and on HPUX 10. Eventually we can turn this on. */ -#define YYSTACK_USE_ALLOCA -#define alloca __builtin_alloca -#endif /* __hpux */ -#endif -#endif /* not _AIX */ -#endif /* not MSDOS, or __TURBOC__ */ -#endif /* not sparc */ -#endif /* not GNU C */ -#endif /* alloca not defined */ -#endif /* YYSTACK_USE_ALLOCA not defined */ +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 10, 11, 13, 66, 67, 68, 71, 73, 74, + 19, 62, 63, 63, 72, 27, 68, 68, 0, 64, + 19, 69, 70, 73, 23, 60, 61, 27, 49, 14, + 34, 28, 12, 41, 52, 59, 35, 58, 18, 47, + 48, 25, 69, 3, 4, 5, 6, 7, 8, 9, + 19, 39, 40, 24, 34, 39, 56, 57, 65, 18, + 36, 34, 28, 15, 16, 17, 18, 19, 21, 22, + 26, 27, 29, 32, 43, 23, 23, 19, 52, 23, + 34, 27, 37, 55, 18, 18, 32, 32, 32, 23, + 43, 50, 51, 50, 19, 27, 29, 31, 18, 40, + 25, 42, 51, 56, 54, 18, 36, 43, 43, 43, + 51, 28, 34, 30, 43, 45, 46, 48, 48, 19, + 24, 24, 43, 24, 13, 28, 52, 53, 18, 34, + 34, 34, 24, 43, 35, 44, 34, 33, 28, 30, + 19, 37, 43, 43, 43, 20, 43, 49, 33, 33, + 33, 44, 25, 43, 37 +}; -#ifdef YYSTACK_USE_ALLOCA -#define YYSTACK_ALLOC alloca -#else -#define YYSTACK_ALLOC malloc +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int #endif - -/* Note: there must be only one dollar sign in this file. - It is replaced by the list of actions, each action - as one case of the switch. */ #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 +#define YYEMPTY (-2) #define YYEOF 0 + #define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab +#define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. - This remains here temporarily to ease the - transition to the new meaning of YYERROR, for GCC. + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ + #define YYFAIL goto yyerrlab + #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(token, value) \ + +#define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ - { yychar = (token), yylval = (value); \ - yychar1 = YYTRANSLATE (yychar); \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ - { yyerror ("syntax error: cannot back up"); YYERROR; } \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 -#ifndef YYPURE -#define YYLEX yylex() -#endif +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ -#ifdef YYPURE -#ifdef YYLSP_NEEDED -#ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) -#else -#define YYLEX yylex(&yylval, &yylloc) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; #endif -#else /* not YYLSP_NEEDED */ + +/* YYLEX -- calling `yylex' with the right arguments. */ + #ifdef YYLEX_PARAM -#define YYLEX yylex(&yylval, YYLEX_PARAM) +# define YYLEX yylex (YYLEX_PARAM) #else -#define YYLEX yylex(&yylval) -#endif -#endif /* not YYLSP_NEEDED */ +# define YYLEX yylex () #endif -/* If nonreentrant, generate the variables here */ +/* Enable debugging if requested. */ +#if YYDEBUG -#ifndef YYPURE +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) -int yychar; /* the lookahead symbol */ -YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded). | +`------------------------------------------------------------------*/ -#ifdef YYLSP_NEEDED -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; #endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) -int yynerrs; /* number of parse errors so far */ -#endif /* not YYPURE */ -#if YYDEBUG != 0 -int yydebug; /* nonzero means print parse trace */ -/* Since this is uninitialized, it does not stop multiple parsers - from coexisting. */ +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; #endif +{ + int yyi; + unsigned int yylineno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylineno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ -/* YYINITDEPTH indicates the initial size of the parser's stacks */ +/* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH -#define YYINITDEPTH 200 +# define YYINITDEPTH 200 #endif -/* YYMAXDEPTH is the maximum size the stacks can grow to - (effective only if the built-in stack extension method is used). */ +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ #if YYMAXDEPTH == 0 -#undef YYMAXDEPTH +# undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH -#define YYMAXDEPTH 10000 +# define YYMAXDEPTH 10000 #endif + -/* Define __yy_memcpy. Note that the size argument - should be passed with type unsigned int, because that is what the non-GCC - definitions require. With GCC, __builtin_memcpy takes an arg - of type size_t, but it can handle unsigned int. */ - -#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ -#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) -#else /* not GNU C or C++ */ -#ifndef __cplusplus -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ -static void -__yy_memcpy (to, from, count) - char *to; - char *from; - unsigned int count; -{ - register char *f = from; - register char *t = to; - register int i = count; +#if YYERROR_VERBOSE - while (i-- > 0) - *t++ = *f++; +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; } +# endif +# endif -#else /* __cplusplus */ +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif -/* This is the most reliable way to avoid incompatibilities - in available built-in functions on various systems. */ +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) static void -__yy_memcpy (char *to, char *from, unsigned int count) +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif { - register char *t = to; - register char *f = from; - register int i = count; + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; - while (i-- > 0) - *t++ = *f++; + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); } +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; #endif -#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} -#line 217 "/usr/share/bison.simple" -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ +/* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM -#ifdef __cplusplus -#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -#define YYPARSE_PARAM_DECL -#else /* not __cplusplus */ -#define YYPARSE_PARAM_ARG YYPARSE_PARAM -#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -#endif /* not __cplusplus */ -#else /* not YYPARSE_PARAM */ -#define YYPARSE_PARAM_ARG -#define YYPARSE_PARAM_DECL -#endif /* not YYPARSE_PARAM */ +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ #ifdef YYPARSE_PARAM -int yyparse (void *); +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) #else -int yyparse (void); +int +yyparse () + #endif #endif - -int -yyparse(YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL { + register int yystate; register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; register short *yyssp; - register YYSTYPE *yyvsp; - int yyerrstatus; /* number of tokens to shift before error messages enabled */ - int yychar1 = 0; /* lookahead token as an internal (translated) token number */ - short yyssa[YYINITDEPTH]; /* the state stack */ - YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; - short *yyss = yyssa; /* refer to the stacks thru separate pointers */ - YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ -#ifdef YYLSP_NEEDED - YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; -#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else #define YYPOPSTACK (yyvsp--, yyssp--) -#endif - int yystacksize = YYINITDEPTH; - int yyfree_stacks = 0; + YYSIZE_T yystacksize = YYINITDEPTH; -#ifdef YYPURE - int yychar; - YYSTYPE yylval; - int yynerrs; -#ifdef YYLSP_NEEDED - YYLTYPE yylloc; -#endif -#endif + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; - YYSTYPE yyval; /* the variable used to return */ - /* semantic values from the action */ - /* routines */ + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ int yylen; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Starting parse\n"); -#endif + YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; @@ -762,110 +1148,96 @@ so that they stay on the same level as the state stack. The wasted elements are never initialized. */ - yyssp = yyss - 1; + yyssp = yyss; yyvsp = yyvs; -#ifdef YYLSP_NEEDED - yylsp = yyls; -#endif -/* Push a new state, which is found in yystate . */ -/* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. */ -yynewstate: + goto yysetstate; - *++yyssp = yystate; +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; - if (yyssp >= yyss + yystacksize - 1) - { - /* Give user a chance to reallocate the stack */ - /* Use copies of these so that the &'s don't force the real ones into memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; -#ifdef YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; -#endif + yysetstate: + *yyssp = yystate; + if (yyss + yystacksize - 1 <= yyssp) + { /* Get the current used size of the three stacks, in elements. */ - int size = yyssp - yyss + 1; + YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow - /* Each stack pointer address is followed by the size of - the data in use in that stack, in bytes. */ -#ifdef YYLSP_NEEDED - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yyls1, size * sizeof (*yylsp), - &yystacksize); -#else - yyoverflow("parser stack overflow", - &yyss1, size * sizeof (*yyssp), - &yyvs1, size * sizeof (*yyvsp), - &yystacksize); -#endif + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), - yyss = yyss1; yyvs = yyvs1; -#ifdef YYLSP_NEEDED - yyls = yyls1; -#endif + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } #else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - { - yyerror("parser stack overflow"); - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 2; - } + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) + if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; -#ifndef YYSTACK_USE_ALLOCA - yyfree_stacks = 1; -#endif - yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); - __yy_memcpy ((char *)yyss, (char *)yyss1, - size * (unsigned int) sizeof (*yyssp)); - yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); - __yy_memcpy ((char *)yyvs, (char *)yyvs1, - size * (unsigned int) sizeof (*yyvsp)); -#ifdef YYLSP_NEEDED - yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); - __yy_memcpy ((char *)yyls, (char *)yyls1, - size * (unsigned int) sizeof (*yylsp)); -#endif + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif #endif /* no yyoverflow */ - yyssp = yyss + size - 1; - yyvsp = yyvs + size - 1; -#ifdef YYLSP_NEEDED - yylsp = yyls + size - 1; -#endif + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Stack size increased to %d\n", yystacksize); -#endif - if (yyssp >= yyss + yystacksize - 1) + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) YYABORT; } -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Entering state %d\n", yystate); -#endif + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; - yybackup: + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ @@ -874,236 +1246,217 @@ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYFLAG) + if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ - + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Reading a token: "); -#endif + YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } - /* Convert token to internal form (in yychar1) for indexing tables with */ - - if (yychar <= 0) /* This means end of input. */ + if (yychar <= YYEOF) { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Now at end of input.\n"); -#endif + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); } else { - yychar1 = YYTRANSLATE(yychar); - -#if YYDEBUG != 0 - if (yydebug) - { - fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise meaning - of a token, for further debugging info. */ -#ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -#endif - fprintf (stderr, ")\n"); - } -#endif + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; - yyn = yytable[yyn]; - - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ - - if (yyn < 0) + if (yyn <= 0) { - if (yyn == YYFLAG) + if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } - else if (yyn == 0) - goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); -#endif + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif - /* count tokens shifted since error; after three, turn off error status. */ - if (yyerrstatus) yyerrstatus--; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; yystate = yyn; goto yynewstate; -/* Do the default action for the current state. */ -yydefault: +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; + goto yyreduce; + -/* Do a reduction. yyn is the number of a rule to reduce with. */ +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ yyreduce: + /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; - if (yylen > 0) - yyval = yyvsp[1-yylen]; /* implement default value of the action */ -#if YYDEBUG != 0 - if (yydebug) - { - int i; + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. - fprintf (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); - - /* Print the symbols being reduced, and their result. */ - for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) - fprintf (stderr, "%s ", yytname[yyrhs[i]]); - fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); - } -#endif + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; - switch (yyn) { - -case 1: -#line 223 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 223 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Rec = Records.getClass(*yyvsp[0].StrVal); if (yyval.Rec == 0) { err() << "Couldn't find class '" << *yyvsp[0].StrVal << "'!\n"; exit(1); } delete yyvsp[0].StrVal; - ; - break;} -case 2: -#line 234 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // string type + ;} + break; + + case 3: +#line 234 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // string type yyval.Ty = new StringRecTy(); - ; - break;} -case 3: -#line 236 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // bit type + ;} + break; + + case 4: +#line 236 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // bit type yyval.Ty = new BitRecTy(); - ; - break;} -case 4: -#line 238 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // bits type + ;} + break; + + case 5: +#line 238 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // bits type yyval.Ty = new BitsRecTy(yyvsp[-1].IntVal); - ; - break;} -case 5: -#line 240 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // int type + ;} + break; + + case 6: +#line 240 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // int type yyval.Ty = new IntRecTy(); - ; - break;} -case 6: -#line 242 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // list type + ;} + break; + + case 7: +#line 242 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // list type yyval.Ty = new ListRecTy(yyvsp[-1].Ty); - ; - break;} -case 7: -#line 244 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // code type + ;} + break; + + case 8: +#line 244 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // code type yyval.Ty = new CodeRecTy(); - ; - break;} -case 8: -#line 246 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // dag type + ;} + break; + + case 9: +#line 246 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // dag type yyval.Ty = new DagRecTy(); - ; - break;} -case 9: -#line 248 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ // Record Type + ;} + break; + + case 10: +#line 248 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // Record Type yyval.Ty = new RecordRecTy(yyvsp[0].Rec); - ; - break;} -case 10: -#line 252 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.IntVal = 0; ; - break;} -case 11: -#line 252 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.IntVal = 1; ; - break;} -case 12: -#line 254 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.Initializer = 0; ; - break;} -case 13: -#line 254 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.Initializer = yyvsp[0].Initializer; ; - break;} -case 14: -#line 256 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 11: +#line 252 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.IntVal = 0; ;} + break; + + case 12: +#line 252 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.IntVal = 1; ;} + break; + + case 13: +#line 254 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = 0; ;} + break; + + case 14: +#line 254 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = yyvsp[0].Initializer; ;} + break; + + case 15: +#line 256 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = new IntInit(yyvsp[0].IntVal); - ; - break;} -case 15: -#line 258 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 16: +#line 258 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = new StringInit(*yyvsp[0].StrVal); delete yyvsp[0].StrVal; - ; - break;} -case 16: -#line 261 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 17: +#line 261 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = new CodeInit(*yyvsp[0].StrVal); delete yyvsp[0].StrVal; - ; - break;} -case 17: -#line 264 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 18: +#line 264 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = new UnsetInit(); - ; - break;} -case 18: -#line 266 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 19: +#line 266 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { BitsInit *Init = new BitsInit(yyvsp[-1].FieldList->size()); for (unsigned i = 0, e = yyvsp[-1].FieldList->size(); i != e; ++i) { struct Init *Bit = (*yyvsp[-1].FieldList)[i]->convertInitializerTo(new BitRecTy()); @@ -1116,30 +1469,12 @@ } yyval.Initializer = Init; delete yyvsp[-1].FieldList; - ; - break;} -case 19: -#line 279 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ - if (const RecordVal *RV = (CurRec ? CurRec->getValue(*yyvsp[0].StrVal) : 0)) { - yyval.Initializer = new VarInit(*yyvsp[0].StrVal, RV->getType()); - } else if (CurRec && CurRec->isTemplateArg(CurRec->getName()+":"+*yyvsp[0].StrVal)) { - const RecordVal *RV = CurRec->getValue(CurRec->getName()+":"+*yyvsp[0].StrVal); - assert(RV && "Template arg doesn't exist??"); - yyval.Initializer = new VarInit(CurRec->getName()+":"+*yyvsp[0].StrVal, RV->getType()); - } else if (Record *D = Records.getDef(*yyvsp[0].StrVal)) { - yyval.Initializer = new DefInit(D); - } else { - err() << "Variable not defined: '" << *yyvsp[0].StrVal << "'!\n"; - exit(1); - } - - delete yyvsp[0].StrVal; - ; - break;} -case 20: -#line 294 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 20: +#line 279 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { // This is a CLASS expression. This is supposed to synthesize // a new anonymous definition, deriving from CLASS with no // body. @@ -1167,40 +1502,64 @@ // Restore the old CurRec CurRec = OldRec; - ; - break;} -case 21: -#line 322 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 21: +#line 307 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { + if (const RecordVal *RV = (CurRec ? CurRec->getValue(*yyvsp[0].StrVal) : 0)) { + yyval.Initializer = new VarInit(*yyvsp[0].StrVal, RV->getType()); + } else if (CurRec && CurRec->isTemplateArg(CurRec->getName()+":"+*yyvsp[0].StrVal)) { + const RecordVal *RV = CurRec->getValue(CurRec->getName()+":"+*yyvsp[0].StrVal); + assert(RV && "Template arg doesn't exist??"); + yyval.Initializer = new VarInit(CurRec->getName()+":"+*yyvsp[0].StrVal, RV->getType()); + } else if (Record *D = Records.getDef(*yyvsp[0].StrVal)) { + yyval.Initializer = new DefInit(D); + } else { + err() << "Variable not defined: '" << *yyvsp[0].StrVal << "'!\n"; + exit(1); + } + + delete yyvsp[0].StrVal; + ;} + break; + + case 22: +#line 322 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = yyvsp[-3].Initializer->convertInitializerBitRange(*yyvsp[-1].BitList); if (yyval.Initializer == 0) { err() << "Invalid bit range for value '" << *yyvsp[-3].Initializer << "'!\n"; exit(1); } delete yyvsp[-1].BitList; - ; - break;} -case 22: -#line 329 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 23: +#line 329 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = new ListInit(*yyvsp[-1].FieldList); delete yyvsp[-1].FieldList; - ; - break;} -case 23: -#line 332 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 24: +#line 332 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { if (!yyvsp[-2].Initializer->getFieldType(*yyvsp[0].StrVal)) { err() << "Cannot access field '" << *yyvsp[0].StrVal << "' of value '" << *yyvsp[-2].Initializer << "!\n"; exit(1); } yyval.Initializer = new FieldInit(yyvsp[-2].Initializer, *yyvsp[0].StrVal); delete yyvsp[0].StrVal; - ; - break;} -case 24: -#line 339 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 25: +#line 339 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { Record *D = Records.getDef(*yyvsp[-2].StrVal); if (D == 0) { err() << "Invalid def '" << *yyvsp[-2].StrVal << "'!\n"; @@ -1208,11 +1567,12 @@ } yyval.Initializer = new DagInit(D, *yyvsp[-1].DagValueList); delete yyvsp[-2].StrVal; delete yyvsp[-1].DagValueList; - ; - break;} -case 25: -#line 347 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 26: +#line 347 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { std::reverse(yyvsp[-1].BitList->begin(), yyvsp[-1].BitList->end()); yyval.Initializer = yyvsp[-3].Initializer->convertInitListSlice(*yyvsp[-1].BitList); if (yyval.Initializer == 0) { @@ -1220,86 +1580,97 @@ exit(1); } delete yyvsp[-1].BitList; - ; - break;} -case 26: -#line 355 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 27: +#line 355 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = yyvsp[-3].Initializer->getBinaryOp(Init::SHL, yyvsp[-1].Initializer); if (yyval.Initializer == 0) { err() << "Cannot shift values '" << *yyvsp[-3].Initializer << "' and '" << *yyvsp[-1].Initializer << "'!\n"; exit(1); } - ; - break;} -case 27: -#line 361 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 28: +#line 361 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = yyvsp[-3].Initializer->getBinaryOp(Init::SRA, yyvsp[-1].Initializer); if (yyval.Initializer == 0) { err() << "Cannot shift values '" << *yyvsp[-3].Initializer << "' and '" << *yyvsp[-1].Initializer << "'!\n"; exit(1); } - ; - break;} -case 28: -#line 367 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 29: +#line 367 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Initializer = yyvsp[-3].Initializer->getBinaryOp(Init::SRL, yyvsp[-1].Initializer); if (yyval.Initializer == 0) { err() << "Cannot shift values '" << *yyvsp[-3].Initializer << "' and '" << *yyvsp[-1].Initializer << "'!\n"; exit(1); } - ; - break;} -case 29: -#line 375 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 30: +#line 375 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.StrVal = new std::string(); - ; - break;} -case 30: -#line 378 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 31: +#line 378 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.StrVal = yyvsp[0].StrVal; - ; - break;} -case 31: -#line 382 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 32: +#line 382 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.DagValueList = new std::vector >(); yyval.DagValueList->push_back(std::make_pair(yyvsp[-1].Initializer, *yyvsp[0].StrVal)); delete yyvsp[0].StrVal; - ; - break;} -case 32: -#line 387 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 33: +#line 387 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyvsp[-3].DagValueList->push_back(std::make_pair(yyvsp[-1].Initializer, *yyvsp[0].StrVal)); delete yyvsp[0].StrVal; yyval.DagValueList = yyvsp[-3].DagValueList; - ; - break;} -case 33: -#line 393 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 34: +#line 393 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.DagValueList = new std::vector >(); - ; - break;} -case 34: -#line 396 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.DagValueList = yyvsp[0].DagValueList; ; - break;} -case 35: -#line 399 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 35: +#line 396 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.DagValueList = yyvsp[0].DagValueList; ;} + break; + + case 36: +#line 399 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.BitList = new std::vector(); yyval.BitList->push_back(yyvsp[0].IntVal); - ; - break;} -case 36: -#line 402 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 37: +#line 402 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { if (yyvsp[-2].IntVal < 0 || yyvsp[0].IntVal < 0) { err() << "Invalid range: " << yyvsp[-2].IntVal << "-" << yyvsp[0].IntVal << "!\n"; exit(1); @@ -1312,11 +1683,12 @@ for (int i = yyvsp[-2].IntVal; i >= yyvsp[0].IntVal; --i) yyval.BitList->push_back(i); } - ; - break;} -case 37: -#line 415 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 38: +#line 415 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyvsp[0].IntVal = -yyvsp[0].IntVal; if (yyvsp[-1].IntVal < 0 || yyvsp[0].IntVal < 0) { err() << "Invalid range: " << yyvsp[-1].IntVal << "-" << yyvsp[0].IntVal << "!\n"; @@ -1330,17 +1702,19 @@ for (int i = yyvsp[-1].IntVal; i >= yyvsp[0].IntVal; --i) yyval.BitList->push_back(i); } - ; - break;} -case 38: -#line 429 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 39: +#line 429 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { (yyval.BitList=yyvsp[-2].BitList)->push_back(yyvsp[0].IntVal); - ; - break;} -case 39: -#line 431 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 40: +#line 431 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { if (yyvsp[-2].IntVal < 0 || yyvsp[0].IntVal < 0) { err() << "Invalid range: " << yyvsp[-2].IntVal << "-" << yyvsp[0].IntVal << "!\n"; exit(1); @@ -1353,11 +1727,12 @@ for (int i = yyvsp[-2].IntVal; i >= yyvsp[0].IntVal; --i) yyval.BitList->push_back(i); } - ; - break;} -case 40: -#line 444 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 41: +#line 444 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyvsp[0].IntVal = -yyvsp[0].IntVal; if (yyvsp[-1].IntVal < 0 || yyvsp[0].IntVal < 0) { err() << "Invalid range: " << yyvsp[-1].IntVal << "-" << yyvsp[0].IntVal << "!\n"; @@ -1371,48 +1746,56 @@ for (int i = yyvsp[-1].IntVal; i >= yyvsp[0].IntVal; --i) yyval.BitList->push_back(i); } - ; - break;} -case 41: -#line 460 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.BitList = yyvsp[0].BitList; std::reverse(yyvsp[0].BitList->begin(), yyvsp[0].BitList->end()); ; - break;} -case 42: -#line 462 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.BitList = 0; ; - break;} -case 43: -#line 462 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.BitList = yyvsp[-1].BitList; ; - break;} -case 44: -#line 466 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 42: +#line 460 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.BitList = yyvsp[0].BitList; std::reverse(yyvsp[0].BitList->begin(), yyvsp[0].BitList->end()); ;} + break; + + case 43: +#line 462 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.BitList = 0; ;} + break; + + case 44: +#line 462 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.BitList = yyvsp[-1].BitList; ;} + break; + + case 45: +#line 466 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.FieldList = new std::vector(); - ; - break;} -case 45: -#line 468 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 46: +#line 468 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.FieldList = yyvsp[0].FieldList; - ; - break;} -case 46: -#line 472 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 47: +#line 472 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.FieldList = new std::vector(); yyval.FieldList->push_back(yyvsp[0].Initializer); - ; - break;} -case 47: -#line 475 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 48: +#line 475 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { (yyval.FieldList = yyvsp[-2].FieldList)->push_back(yyvsp[0].Initializer); - ; - break;} -case 48: -#line 479 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 49: +#line 479 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { std::string DecName = *yyvsp[-1].StrVal; if (ParsingTemplateArgs) DecName = CurRec->getName() + ":" + DecName; @@ -1420,101 +1803,116 @@ addValue(RecordVal(DecName, yyvsp[-2].Ty, yyvsp[-3].IntVal)); setValue(DecName, 0, yyvsp[0].Initializer); yyval.StrVal = new std::string(DecName); -; - break;} -case 49: -#line 489 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 50: +#line 489 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { delete yyvsp[-1].StrVal; -; - break;} -case 50: -#line 491 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 51: +#line 491 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { setValue(*yyvsp[-4].StrVal, yyvsp[-3].BitList, yyvsp[-1].Initializer); delete yyvsp[-4].StrVal; delete yyvsp[-3].BitList; -; - break;} -case 55: -#line 500 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 56: +#line 500 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.SubClassRef = new SubClassRefTy(yyvsp[0].Rec, new std::vector()); - ; - break;} -case 56: -#line 502 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 57: +#line 502 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.SubClassRef = new SubClassRefTy(yyvsp[-3].Rec, yyvsp[-1].FieldList); - ; - break;} -case 57: -#line 506 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 58: +#line 506 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.SubClassList = new std::vector(); yyval.SubClassList->push_back(*yyvsp[0].SubClassRef); delete yyvsp[0].SubClassRef; - ; - break;} -case 58: -#line 511 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 59: +#line 511 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { (yyval.SubClassList=yyvsp[-2].SubClassList)->push_back(*yyvsp[0].SubClassRef); delete yyvsp[0].SubClassRef; - ; - break;} -case 59: -#line 516 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 60: +#line 516 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.SubClassList = new std::vector(); - ; - break;} -case 60: -#line 519 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 61: +#line 519 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.SubClassList = yyvsp[0].SubClassList; - ; - break;} -case 61: -#line 523 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 62: +#line 523 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { CurRec->addTemplateArg(*yyvsp[0].StrVal); delete yyvsp[0].StrVal; -; - break;} -case 62: -#line 526 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 63: +#line 526 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { CurRec->addTemplateArg(*yyvsp[0].StrVal); delete yyvsp[0].StrVal; -; - break;} -case 63: -#line 531 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{; - break;} -case 66: -#line 534 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.StrVal = yyvsp[0].StrVal; ; - break;} -case 67: -#line 534 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ yyval.StrVal = new std::string(); ; - break;} -case 68: -#line 536 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 64: +#line 531 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + {;} + break; + + case 67: +#line 534 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.StrVal = yyvsp[0].StrVal; ;} + break; + + case 68: +#line 534 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.StrVal = new std::string(); ;} + break; + + case 69: +#line 536 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { static unsigned AnonCounter = 0; if (yyvsp[0].StrVal->empty()) *yyvsp[0].StrVal = "anonymous."+utostr(AnonCounter++); CurRec = new Record(*yyvsp[0].StrVal); delete yyvsp[0].StrVal; ParsingTemplateArgs = true; - ; - break;} -case 69: -#line 543 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 70: +#line 543 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { ParsingTemplateArgs = false; for (unsigned i = 0, e = yyvsp[0].SubClassList->size(); i != e; ++i) { addSubClass((*yyvsp[0].SubClassList)[i].first, *(*yyvsp[0].SubClassList)[i].second); @@ -1529,28 +1927,31 @@ setValue(LetStack[i][j].Name, LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0, LetStack[i][j].Value); - ; - break;} -case 70: -#line 558 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 71: +#line 558 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyval.Rec = CurRec; CurRec = 0; - ; - break;} -case 71: -#line 563 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 72: +#line 563 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { if (Records.getClass(yyvsp[0].Rec->getName())) { err() << "Class '" << yyvsp[0].Rec->getName() << "' already defined!\n"; exit(1); } Records.addClass(yyval.Rec = yyvsp[0].Rec); -; - break;} -case 72: -#line 571 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 73: +#line 571 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { yyvsp[0].Rec->resolveReferences(); // If ObjectBody has template arguments, it's an error. @@ -1565,269 +1966,254 @@ exit(1); } Records.addDef(yyval.Rec = yyvsp[0].Rec); -; - break;} -case 75: -#line 591 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 76: +#line 591 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { LetStack.back().push_back(LetRecord(*yyvsp[-3].StrVal, yyvsp[-2].BitList, yyvsp[0].Initializer)); delete yyvsp[-3].StrVal; delete yyvsp[-2].BitList; -; - break;} -case 78: -#line 599 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ LetStack.push_back(std::vector()); ; - break;} -case 80: -#line 602 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ +;} + break; + + case 79: +#line 599 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { LetStack.push_back(std::vector()); ;} + break; + + case 81: +#line 602 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { LetStack.pop_back(); - ; - break;} -case 81: -#line 605 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{ + ;} + break; + + case 82: +#line 605 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + { LetStack.pop_back(); - ; - break;} -case 82: -#line 609 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{; - break;} -case 83: -#line 609 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{; - break;} -case 84: -#line 611 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" -{; - break;} -} - /* the action file gets copied in in place of this dollarsign */ -#line 543 "/usr/share/bison.simple" + ;} + break; + + case 83: +#line 609 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + {;} + break; + + case 84: +#line 609 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + {;} + break; + + case 85: +#line 611 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" + {;} + break; + + + } + +/* Line 999 of yacc.c. */ +#line 2018 "FileParser.tab.c" yyvsp -= yylen; yyssp -= yylen; -#ifdef YYLSP_NEEDED - yylsp -= yylen; -#endif -#if YYDEBUG != 0 - if (yydebug) - { - short *ssp1 = yyss - 1; - fprintf (stderr, "state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif + + YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; -#ifdef YYLSP_NEEDED - yylsp++; - if (yylen == 0) - { - yylsp->first_line = yylloc.first_line; - yylsp->first_column = yylloc.first_column; - yylsp->last_line = (yylsp-1)->last_line; - yylsp->last_column = (yylsp-1)->last_column; - yylsp->text = 0; - } - else - { - yylsp->last_line = (yylsp+yylen-1)->last_line; - yylsp->last_column = (yylsp+yylen-1)->last_column; - } -#endif - /* Now "shift" the result of the reduction. - Determine what state that goes to, - based on the state we popped back to - and the rule number reduced by. */ + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ yyn = yyr1[yyn]; - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else - yystate = yydefgoto[yyn - YYNTBASE]; + yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; -yyerrlab: /* here on detecting error */ - if (! yyerrstatus) - /* If not already recovering from an error, report this error. */ +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) { ++yynerrs; - -#ifdef YYERROR_VERBOSE +#if YYERROR_VERBOSE yyn = yypact[yystate]; - if (yyn > YYFLAG && yyn < YYLAST) + if (YYPACT_NINF < yyn && yyn < YYLAST) { - int size = 0; - char *msg; - int x, count; - - count = 0; - /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) - size += strlen(yytname[x]) + 15, count++; - msg = (char *) malloc(size + 15); - if (msg != 0) + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("syntax error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) { - strcpy(msg, "parse error"); + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); - if (count < 5) + if (yycount < 5) { - count = 0; - for (x = (yyn < 0 ? -yyn : 0); - x < (sizeof(yytname) / sizeof(char *)); x++) - if (yycheck[x + yyn] == x) + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - strcat(msg, count == 0 ? ", expecting `" : " or `"); - strcat(msg, yytname[x]); - strcat(msg, "'"); - count++; + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; } } - yyerror(msg); - free(msg); + yyerror (yymsg); + YYSTACK_FREE (yymsg); } else - yyerror ("parse error; also virtual memory exceeded"); + yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ - yyerror("parse error"); + yyerror ("syntax error"); } - goto yyerrlab1; -yyerrlab1: /* here on error raised explicitly by an action */ + if (yyerrstatus == 3) { - /* if just tried and failed to reuse lookahead token after an error, discard it. */ + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ - /* return failure if at end of input */ + /* Return failure if at end of input. */ if (yychar == YYEOF) - YYABORT; - -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); -#endif + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyss < yyssp) + { + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + YYPOPSTACK; + } + YYABORT; + } + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); yychar = YYEMPTY; - } - - /* Else will try to reuse lookahead token - after shifting the error token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ - - goto yyerrhandle; -yyerrdefault: /* current state does not do anything special for the error token. */ + } -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ - if (yyn) goto yydefault; -#endif + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; -yyerrpop: /* pop the current state because it cannot handle the error token */ - if (yyssp == yyss) YYABORT; - yyvsp--; - yystate = *--yyssp; -#ifdef YYLSP_NEEDED - yylsp--; -#endif +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ -#if YYDEBUG != 0 - if (yydebug) + for (;;) { - short *ssp1 = yyss - 1; - fprintf (stderr, "Error: state stack now"); - while (ssp1 != yyssp) - fprintf (stderr, " %d", *++ssp1); - fprintf (stderr, "\n"); - } -#endif - -yyerrhandle: + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + yyvsp--; + yystate = *--yyssp; - yyn = yytable[yyn]; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; + YY_STACK_PRINT (yyss, yyssp); } - else if (yyn == 0) - goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; -#if YYDEBUG != 0 - if (yydebug) - fprintf(stderr, "Shifting error token, "); -#endif + YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; -#ifdef YYLSP_NEEDED - *++yylsp = yylloc; -#endif + yystate = yyn; goto yynewstate; - yyacceptlab: - /* YYACCEPT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); -#endif - } - return 0; - yyabortlab: - /* YYABORT comes here. */ - if (yyfree_stacks) - { - free (yyss); - free (yyvs); -#ifdef YYLSP_NEEDED - free (yyls); +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); #endif - } - return 1; + return yyresult; } -#line 613 "/Volumes/ProjectsDisk/cvs/llvm/utils/TableGen/FileParser.y" + + +#line 613 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" int yyerror(const char *ErrorMsg) { err() << "Error parsing: " << ErrorMsg << "\n"; exit(1); } + Index: llvm/utils/TableGen/FileParser.h diff -u llvm/utils/TableGen/FileParser.h:1.2 llvm/utils/TableGen/FileParser.h:1.3 --- llvm/utils/TableGen/FileParser.h:1.2 Thu Sep 8 13:22:57 2005 +++ llvm/utils/TableGen/FileParser.h Mon Sep 12 00:30:06 2005 @@ -1,4 +1,83 @@ -typedef union { +/* A Bison parser, made by GNU Bison 1.875. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program 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 2, or (at your option) + any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + INT = 258, + BIT = 259, + STRING = 260, + BITS = 261, + LIST = 262, + CODE = 263, + DAG = 264, + CLASS = 265, + DEF = 266, + FIELD = 267, + LET = 268, + IN = 269, + SHLTOK = 270, + SRATOK = 271, + SRLTOK = 272, + INTVAL = 273, + ID = 274, + VARNAME = 275, + STRVAL = 276, + CODEFRAGMENT = 277 + }; +#endif +#define INT 258 +#define BIT 259 +#define STRING 260 +#define BITS 261 +#define LIST 262 +#define CODE 263 +#define DAG 264 +#define CLASS 265 +#define DEF 266 +#define FIELD 267 +#define LET 268 +#define IN 269 +#define SHLTOK 270 +#define SRATOK 271 +#define SRLTOK 272 +#define INTVAL 273 +#define ID 274 +#define VARNAME 275 +#define STRVAL 276 +#define CODEFRAGMENT 277 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 189 "/home/vadve/lattner/llvm/utils/TableGen/FileParser.y" +typedef union YYSTYPE { std::string* StrVal; int IntVal; llvm::RecTy* Ty; @@ -10,26 +89,14 @@ std::vector* SubClassList; std::vector >* DagValueList; } YYSTYPE; -#define INT 257 -#define BIT 258 -#define STRING 259 -#define BITS 260 -#define LIST 261 -#define CODE 262 -#define DAG 263 -#define CLASS 264 -#define DEF 265 -#define FIELD 266 -#define LET 267 -#define IN 268 -#define SHLTOK 269 -#define SRATOK 270 -#define SRLTOK 271 -#define INTVAL 272 -#define ID 273 -#define VARNAME 274 -#define STRVAL 275 -#define CODEFRAGMENT 276 - +/* Line 1240 of yacc.c. */ +#line 93 "FileParser.tab.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif extern YYSTYPE Filelval; + + + From lattner at cs.uiuc.edu Mon Sep 12 00:50:26 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 00:50:26 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll Message-ID: <200509120550.AAA09967@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LoopStrengthReduce: use_postinc_value_outside_loop.ll added (r1.1) --- Log message: new testcase --- Diffs of the changes: (+28 -0) use_postinc_value_outside_loop.ll | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+) Index: llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll diff -c /dev/null llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll:1.1 *** /dev/null Mon Sep 12 00:50:25 2005 --- llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll Mon Sep 12 00:50:15 2005 *************** *** 0 **** --- 1,28 ---- + ; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep 'add uint %iv..inc, 1' + ; + ; Make sure that the use of the IV outside of the loop (the store) uses the + ; post incremented value of the IV, not the preincremented value. This + ; prevents the loop from having to keep the post and pre-incremented value + ; around for the duration of the loop, adding a copy and an extra register + ; to the loop. + + declare bool %pred(int %X) + + void %test([700 x int]* %nbeaux_.0__558, int* %i_.16574) { + then.0: + br label %no_exit.2 + + no_exit.2: ; preds = %no_exit.2, %then.0 + %indvar630 = phi uint [ 0, %then.0 ], [ %indvar.next631, %no_exit.2 ] ; [#uses=3] + %indvar630 = cast uint %indvar630 to int ; [#uses=1] + %tmp.38 = getelementptr [700 x int]* %nbeaux_.0__558, int 0, uint %indvar630 ; [#uses=1] + store int 0, int* %tmp.38 + %inc.2 = add int %indvar630, 2 ; [#uses=2] + %tmp.34 = call bool %pred(int %indvar630) + %indvar.next631 = add uint %indvar630, 1 ; [#uses=1] + br bool %tmp.34, label %no_exit.2, label %loopexit.2.loopexit + + loopexit.2.loopexit: ; preds = %no_exit.2 + store int %inc.2, int* %i_.16574 + ret void + } From lattner at cs.uiuc.edu Mon Sep 12 01:04:58 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 01:04:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200509120604.BAA10449@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.55 -> 1.56 --- Log message: _test: li r2, 0 LBB_test_1: ; no_exit.2 li r5, 0 stw r5, 0(r3) addi r2, r2, 1 addi r3, r3, 4 cmpwi cr0, r2, 701 blt cr0, LBB_test_1 ; no_exit.2 LBB_test_2: ; loopexit.2.loopexit addi r2, r2, 1 stw r2, 0(r4) blr [zion ~/llvm]$ cat > ~/xx Uses of IV's outside of the loop should use hte post-incremented version of the IV, not the preincremented version. This helps many loops (e.g. in sixtrack) which used to generate code like this (this is the code from the dont-hoist-simple-loop-constants.ll testcase): _test: li r2, 0 **** IV starts at 0 LBB_test_1: ; no_exit.2 or r5, r2, r2 **** Copy for loop exit li r2, 0 stw r2, 0(r3) addi r3, r3, 4 addi r2, r5, 1 addi r6, r5, 2 **** IV+2 cmpwi cr0, r6, 701 blt cr0, LBB_test_1 ; no_exit.2 LBB_test_2: ; loopexit.2.loopexit addi r2, r5, 2 **** IV+2 stw r2, 0(r4) blr And now generated code like this: _test: li r2, 1 *** IV starts at 1 LBB_test_1: ; no_exit.2 li r5, 0 stw r5, 0(r3) addi r2, r2, 1 addi r3, r3, 4 cmpwi cr0, r2, 701 *** IV.postinc + 0 blt cr0, LBB_test_1 LBB_test_2: ; loopexit.2.loopexit stw r2, 0(r4) *** IV.postinc + 0 blr --- Diffs of the changes: (+19 -5) LoopStrengthReduce.cpp | 24 +++++++++++++++++++----- 1 files changed, 19 insertions(+), 5 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.55 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.56 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.55 Fri Sep 9 20:18:45 2005 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Sep 12 01:04:47 2005 @@ -52,7 +52,7 @@ // isUseOfPostIncrementedValue - True if this should use the // post-incremented version of this IV, not the preincremented version. // This can only be set in special cases, such as the terminating setcc - // instruction for a loop. + // instruction for a loop or uses dominated by the loop. bool isUseOfPostIncrementedValue; IVStrideUse(const SCEVHandle &Offs, Instruction *U, Value *O) @@ -351,8 +351,17 @@ if (AddUserToIVUsers) { // Okay, we found a user that we cannot reduce. Analyze the instruction - // and decide what to do with it. - IVUsesByStride[Stride].addUser(Start, User, I); + // and decide what to do with it. If we are a use inside of the loop, use + // the value before incrementation, otherwise use it after incrementation. + if (L->contains(User->getParent())) { + IVUsesByStride[Stride].addUser(Start, User, I); + } else { + // The value used will be incremented by the stride more than we are + // expecting, so subtract this off. + SCEVHandle NewStart = SCEV::getMinusSCEV(Start, Stride); + IVUsesByStride[Stride].addUser(NewStart, User, I); + IVUsesByStride[Stride].Users.back().isUseOfPostIncrementedValue = true; + } } } return true; @@ -387,7 +396,8 @@ // isUseOfPostIncrementedValue - True if this should use the // post-incremented version of this IV, not the preincremented version. // This can only be set in special cases, such as the terminating setcc - // instruction for a loop. + // instruction for a loop and uses outside the loop that are dominated by + // the loop. bool isUseOfPostIncrementedValue; BasedUser(IVStrideUse &IVSU) @@ -842,7 +852,11 @@ Value *RewriteOp = NewPHI; if (User.isUseOfPostIncrementedValue) { RewriteOp = IncV; - User.Inst->moveBefore(LatchBlock->getTerminator()); + + // If this user is in the loop, make sure it is the last thing in the + // loop to ensure it is dominated by the increment. + if (L->contains(User.Inst->getParent())) + User.Inst->moveBefore(LatchBlock->getTerminator()); } SCEVHandle RewriteExpr = SCEVUnknown::get(RewriteOp); From lattner at cs.uiuc.edu Mon Sep 12 12:03:27 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 12:03:27 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200509121703.MAA14997@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.49 -> 1.50 --- Log message: new method --- Diffs of the changes: (+6 -0) LoopInfo.h | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.49 llvm/include/llvm/Analysis/LoopInfo.h:1.50 --- llvm/include/llvm/Analysis/LoopInfo.h:1.49 Wed Jun 29 12:41:25 2005 +++ llvm/include/llvm/Analysis/LoopInfo.h Mon Sep 12 12:03:16 2005 @@ -121,6 +121,12 @@ /// BasicBlock *getLoopPreheader() const; + /// getLoopLatch - If there is a latch block for this loop, return it. A + /// latch block is the canonical backedge for a loop. A loop header in normal + /// form has two edges into it: one from a preheader and one from a latch + /// block. + BasicBlock *getLoopLatch() const; + /// getCanonicalInductionVariable - Check to see if the loop has a canonical /// induction variable: an integer recurrence that starts at 0 and increments /// by one each time through the loop. If so, return the phi node that From lattner at cs.uiuc.edu Mon Sep 12 12:04:07 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 12:04:07 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200509121704.MAA15069@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.64 -> 1.65 --- Log message: Add a new getLoopLatch() method. --- Diffs of the changes: (+25 -1) LoopInfo.cpp | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletion(-) Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.64 llvm/lib/Analysis/LoopInfo.cpp:1.65 --- llvm/lib/Analysis/LoopInfo.cpp:1.64 Thu May 5 18:43:47 2005 +++ llvm/lib/Analysis/LoopInfo.cpp Mon Sep 12 12:03:55 2005 @@ -373,12 +373,36 @@ if (SI != succ_end(Out)) return 0; // Multiple exits from the block, must not be a preheader. - // If there is exactly one preheader, return it. If there was zero, then Out // is still null. return Out; } +/// getLoopLatch - If there is a latch block for this loop, return it. A +/// latch block is the canonical backedge for a loop. A loop header in normal +/// form has two edges into it: one from a preheader and one from a latch +/// block. +BasicBlock *Loop::getLoopLatch() const { + BasicBlock *Header = getHeader(); + pred_iterator PI = pred_begin(Header), PE = pred_end(Header); + if (PI == PE) return 0; // no preds? + + BasicBlock *Latch = 0; + if (contains(*PI)) + Latch = *PI; + ++PI; + if (PI == PE) return 0; // only one pred? + + if (contains(*PI)) { + if (Latch) return 0; // multiple backedges + Latch = *PI; + } + ++PI; + if (PI != PE) return 0; // more than two preds + + return Latch; +} + /// getCanonicalInductionVariable - Check to see if the loop has a canonical /// induction variable: an integer recurrence that starts at 0 and increments by /// one each time through the loop. If so, return the phi node that corresponds From lattner at cs.uiuc.edu Mon Sep 12 12:08:26 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 12:08:26 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll Message-ID: <200509121708.MAA15169@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LoopStrengthReduce: 2005-09-12-UsesOutOutsideOfLoop.ll added (r1.1) --- Log message: new testcase --- Diffs of the changes: (+43 -0) 2005-09-12-UsesOutOutsideOfLoop.ll | 43 +++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+) Index: llvm/test/Regression/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll diff -c /dev/null llvm/test/Regression/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll:1.1 *** /dev/null Mon Sep 12 12:08:25 2005 --- llvm/test/Regression/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll Mon Sep 12 12:08:15 2005 *************** *** 0 **** --- 1,43 ---- + ; RUN: llvm-as < %s | opt -loop-reduce -disable-output + + void %main() { + entry: + br label %loopentry.0 + + loopentry.0: ; preds = %then.5, %entry + %arg_index.1.ph = phi int [ 1, %entry ], [ %arg_index.1.ph.be, %then.5 ] ; [#uses=1] + br bool false, label %no_exit.0, label %loopexit.0 + + no_exit.0: ; preds = %loopentry.0 + %arg_index.1.1 = add int 0, %arg_index.1.ph ; [#uses=2] + br bool false, label %then.i55, label %endif.i61 + + then.i55: ; preds = %no_exit.0 + br bool false, label %then.4, label %else.1 + + endif.i61: ; preds = %no_exit.0 + ret void + + then.4: ; preds = %then.i55 + %tmp.19993 = add int %arg_index.1.1, 2 ; [#uses=0] + ret void + + else.1: ; preds = %then.i55 + br bool false, label %then.i86, label %loopexit.i97 + + then.i86: ; preds = %else.1 + ret void + + loopexit.i97: ; preds = %else.1 + br bool false, label %then.5, label %else.2 + + then.5: ; preds = %loopexit.i97 + %arg_index.1.ph.be = add int %arg_index.1.1, 2 ; [#uses=1] + br label %loopentry.0 + + else.2: ; preds = %loopexit.i97 + ret void + + loopexit.0: ; preds = %loopentry.0 + ret void + } From lattner at cs.uiuc.edu Mon Sep 12 12:09:51 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 12:09:51 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll Message-ID: <200509121709.MAA15266@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LoopStrengthReduce: use_postinc_value_outside_loop.ll updated: 1.1 -> 1.2 --- Log message: relax pattern match on name --- Diffs of the changes: (+1 -1) use_postinc_value_outside_loop.ll | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll diff -u llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll:1.1 llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll:1.2 --- llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll:1.1 Mon Sep 12 00:50:15 2005 +++ llvm/test/Regression/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll Mon Sep 12 12:09:40 2005 @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep 'add uint %iv..inc, 1' +; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep 'add uint %iv.*inc, 1' ; ; Make sure that the use of the IV outside of the loop (the store) uses the ; post incremented value of the IV, not the preincremented value. This From lattner at cs.uiuc.edu Mon Sep 12 12:11:38 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 12:11:38 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200509121711.MAA15318@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.56 -> 1.57 --- Log message: Fix a regression from last night, which caused this pass to create invalid code for IV uses outside of loops that are not dominated by the latch block. We should only convert these uses to use the post-inc value if they ARE dominated by the latch block. Also use a new LoopInfo method to simplify some code. This fixes Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll --- Diffs of the changes: (+6 -8) LoopStrengthReduce.cpp | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.56 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.57 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.56 Mon Sep 12 01:04:47 2005 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Sep 12 12:11:27 2005 @@ -353,7 +353,11 @@ // Okay, we found a user that we cannot reduce. Analyze the instruction // and decide what to do with it. If we are a use inside of the loop, use // the value before incrementation, otherwise use it after incrementation. - if (L->contains(User->getParent())) { + if (L->contains(User->getParent()) || + // Alternatively, if we are a use outside of the loop, but is not + // dominated by the latch block, we have to use the preincremented + // value. + !DS->dominates(L->getLoopLatch(), User->getParent())) { IVUsesByStride[Stride].addUser(Start, User, I); } else { // The value used will be incremented by the stride more than we are @@ -784,13 +788,7 @@ Instruction *PreInsertPt = Preheader->getTerminator(); Instruction *PhiInsertBefore = L->getHeader()->begin(); - assert(isa(PhiInsertBefore) && - "How could this loop have IV's without any phis?"); - PHINode *SomeLoopPHI = cast(PhiInsertBefore); - assert(SomeLoopPHI->getNumIncomingValues() == 2 && - "This loop isn't canonicalized right"); - BasicBlock *LatchBlock = - SomeLoopPHI->getIncomingBlock(SomeLoopPHI->getIncomingBlock(0) == Preheader); + BasicBlock *LatchBlock = L->getLoopLatch(); // Create a new Phi for this base, and stick it in the loop header. const Type *ReplacedTy = CommonExprs->getType(); From lattner at cs.uiuc.edu Mon Sep 12 16:59:34 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 16:59:34 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/load.ll Message-ID: <200509122159.QAA13913@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: load.ll updated: 1.8 -> 1.9 --- Log message: new testcase --- Diffs of the changes: (+6 -0) load.ll | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/load.ll diff -u llvm/test/Regression/Transforms/InstCombine/load.ll:1.8 llvm/test/Regression/Transforms/InstCombine/load.ll:1.9 --- llvm/test/Regression/Transforms/InstCombine/load.ll:1.8 Sat Apr 30 23:24:15 2005 +++ llvm/test/Regression/Transforms/InstCombine/load.ll Mon Sep 12 16:59:22 2005 @@ -59,3 +59,9 @@ %R = load int* %V ret int %R } + +int %test8(int* %P) { + store int 1, int* %P + %X = load int* %P ;; Trivial store->load forwarding + ret int %X +} From lattner at cs.uiuc.edu Mon Sep 12 17:00:28 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 17:00:28 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509122200.RAA14087@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.365 -> 1.366 --- Log message: Implement a trivial form of store->load forwarding where the store and the load are exactly consequtive. This is picked up by other passes, but this triggers thousands of times in fortran programs that use static locals (and is thus a compile-time speedup). --- Diffs of the changes: (+9 -0) InstructionCombining.cpp | 9 +++++++++ 1 files changed, 9 insertions(+) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.365 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.366 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.365 Mon Aug 8 14:11:57 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon Sep 12 17:00:15 2005 @@ -4925,6 +4925,15 @@ // None of the following transforms are legal for volatile loads. if (LI.isVolatile()) return 0; + + // If the instruction immediately before this is a store to the same address, + // do a simple form of store->load forwarding. + if (&LI.getParent()->front() != &LI) { + BasicBlock::iterator BBI = &LI; --BBI; + if (StoreInst *SI = dyn_cast(BBI)) + if (SI->getOperand(1) == LI.getOperand(0)) + return ReplaceInstUsesWith(LI, SI->getOperand(0)); + } if (GetElementPtrInst *GEPI = dyn_cast(Op)) if (isa(GEPI->getOperand(0)) || From lattner at cs.uiuc.edu Mon Sep 12 17:19:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 17:19:57 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/load.ll Message-ID: <200509122219.RAA16328@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: load.ll updated: 1.9 -> 1.10 --- Log message: new testcase --- Diffs of the changes: (+7 -0) load.ll | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/load.ll diff -u llvm/test/Regression/Transforms/InstCombine/load.ll:1.9 llvm/test/Regression/Transforms/InstCombine/load.ll:1.10 --- llvm/test/Regression/Transforms/InstCombine/load.ll:1.9 Mon Sep 12 16:59:22 2005 +++ llvm/test/Regression/Transforms/InstCombine/load.ll Mon Sep 12 17:19:46 2005 @@ -65,3 +65,10 @@ %X = load int* %P ;; Trivial store->load forwarding ret int %X } + +int %test9(int* %P) { + %X = load int* %P ;; Trivial load cse + %Y = load int* %P + %Z = sub int %X, %Y + ret int %Z +} From lattner at cs.uiuc.edu Mon Sep 12 17:21:15 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 17:21:15 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509122221.RAA16397@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.366 -> 1.367 --- Log message: Another load-peephole optimization: do gcse when two loads are next to each other. This implements InstCombine/load.ll:test9 --- Diffs of the changes: (+5 -2) InstructionCombining.cpp | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.366 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.367 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.366 Mon Sep 12 17:00:15 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon Sep 12 17:21:03 2005 @@ -4926,13 +4926,16 @@ // None of the following transforms are legal for volatile loads. if (LI.isVolatile()) return 0; - // If the instruction immediately before this is a store to the same address, - // do a simple form of store->load forwarding. if (&LI.getParent()->front() != &LI) { BasicBlock::iterator BBI = &LI; --BBI; + // If the instruction immediately before this is a store to the same + // address, do a simple form of store->load forwarding. if (StoreInst *SI = dyn_cast(BBI)) if (SI->getOperand(1) == LI.getOperand(0)) return ReplaceInstUsesWith(LI, SI->getOperand(0)); + if (LoadInst *LIB = dyn_cast(BBI)) + if (LIB->getOperand(0) == LI.getOperand(0)) + return ReplaceInstUsesWith(LI, LIB); } if (GetElementPtrInst *GEPI = dyn_cast(Op)) From lattner at cs.uiuc.edu Mon Sep 12 18:22:29 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 18:22:29 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/load.ll Message-ID: <200509122322.SAA01622@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: load.ll updated: 1.10 -> 1.11 --- Log message: new testcase --- Diffs of the changes: (+14 -0) load.ll | 14 ++++++++++++++ 1 files changed, 14 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/load.ll diff -u llvm/test/Regression/Transforms/InstCombine/load.ll:1.10 llvm/test/Regression/Transforms/InstCombine/load.ll:1.11 --- llvm/test/Regression/Transforms/InstCombine/load.ll:1.10 Mon Sep 12 17:19:46 2005 +++ llvm/test/Regression/Transforms/InstCombine/load.ll Mon Sep 12 18:22:17 2005 @@ -72,3 +72,17 @@ %Z = sub int %X, %Y ret int %Z } + +int %test10(bool %C, int* %P, int* %Q) { + br bool %C, label %T, label %F +T: + store int 1, int* %Q + store int 0, int* %P + br label %C +F: + store int 0, int* %P + br label %C +C: + %V = load int* %P ;; always 0 + ret int %V +} From lattner at cs.uiuc.edu Mon Sep 12 18:23:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 18:23:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509122323.SAA01907@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.367 -> 1.368 --- Log message: Implement a simple xform to turn code like this: if () { store A -> P; } else { store B -> P; } into a PHI node with one store, in the most trival case. This implements load.ll:test10. --- Diffs of the changes: (+66 -0) InstructionCombining.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 66 insertions(+) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.367 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.368 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.367 Mon Sep 12 17:21:03 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon Sep 12 18:23:25 2005 @@ -5157,6 +5157,72 @@ if (Instruction *Res = InstCombineStoreToCast(*this, SI)) return Res; + + // If this store is the last instruction in the basic block, and if the block + // ends with an unconditional branch, try to move it to the successor block. + BasicBlock::iterator BBI = &SI; ++BBI; + if (BranchInst *BI = dyn_cast(BBI)) + if (BI->isUnconditional()) { + // Check to see if the successor block has exactly two incoming edges. If + // so, see if the other predecessor contains a store to the same location. + // if so, insert a PHI node (if needed) and move the stores down. + BasicBlock *Dest = BI->getSuccessor(0); + + pred_iterator PI = pred_begin(Dest); + BasicBlock *Other = 0; + if (*PI != BI->getParent()) + Other = *PI; + ++PI; + if (PI != pred_end(Dest)) { + if (*PI != BI->getParent()) + if (Other) + Other = 0; + else + Other = *PI; + if (++PI != pred_end(Dest)) + Other = 0; + } + if (Other) { // If only one other pred... + BBI = Other->getTerminator(); + // Make sure this other block ends in an unconditional branch and that + // there is an instruction before the branch. + if (isa(BBI) && cast(BBI)->isUnconditional() && + BBI != Other->begin()) { + --BBI; + StoreInst *OtherStore = dyn_cast(BBI); + + // If this instruction is a store to the same location. + if (OtherStore && OtherStore->getOperand(1) == SI.getOperand(1)) { + // Okay, we know we can perform this transformation. Insert a PHI + // node now if we need it. + Value *MergedVal = OtherStore->getOperand(0); + if (MergedVal != SI.getOperand(0)) { + PHINode *PN = new PHINode(MergedVal->getType(), "storemerge"); + PN->reserveOperandSpace(2); + PN->addIncoming(SI.getOperand(0), SI.getParent()); + PN->addIncoming(OtherStore->getOperand(0), Other); + MergedVal = InsertNewInstBefore(PN, Dest->front()); + } + + // Advance to a place where it is safe to insert the new store and + // insert it. + BBI = Dest->begin(); + while (isa(BBI)) ++BBI; + InsertNewInstBefore(new StoreInst(MergedVal, SI.getOperand(1), + OtherStore->isVolatile()), *BBI); + + // Nuke the old stores. + removeFromWorkList(&SI); + removeFromWorkList(OtherStore); + SI.eraseFromParent(); + OtherStore->eraseFromParent(); + ++NumCombined; + return 0; + } + } + } + } + return 0; } From lattner at cs.uiuc.edu Mon Sep 12 19:40:26 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 19:40:26 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509130040.TAA11519@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.368 -> 1.369 --- Log message: Add a helper function, allowing us to simplify some code a bit, changing indentation, no functionality change --- Diffs of the changes: (+47 -39) InstructionCombining.cpp | 86 +++++++++++++++++++++++++---------------------- 1 files changed, 47 insertions(+), 39 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.368 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.369 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.368 Mon Sep 12 18:23:25 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon Sep 12 19:40:14 2005 @@ -261,6 +261,17 @@ } } +/// isCast - If the specified operand is a CastInst or a constant expr cast, +/// return the operand value, otherwise return null. +static Value *isCast(Value *V) { + if (CastInst *I = dyn_cast(V)) + return I->getOperand(0); + else if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Cast) + return CE->getOperand(0); + return 0; +} + // SimplifyCommutative - This performs a few simplifications for commutative // operators: // @@ -4682,45 +4693,42 @@ // Replace all uses of the GEP with the new constexpr... return ReplaceInstUsesWith(GEP, CE); } - } else if (ConstantExpr *CE = dyn_cast(PtrOp)) { - if (CE->getOpcode() == Instruction::Cast) { - if (HasZeroPointerIndex) { - // transform: GEP (cast [10 x ubyte]* X to [0 x ubyte]*), long 0, ... - // into : GEP [10 x ubyte]* X, long 0, ... - // - // This occurs when the program declares an array extern like "int X[];" - // - Constant *X = CE->getOperand(0); - const PointerType *CPTy = cast(CE->getType()); - if (const PointerType *XTy = dyn_cast(X->getType())) - if (const ArrayType *XATy = - dyn_cast(XTy->getElementType())) - if (const ArrayType *CATy = - dyn_cast(CPTy->getElementType())) - if (CATy->getElementType() == XATy->getElementType()) { - // At this point, we know that the cast source type is a pointer - // to an array of the same type as the destination pointer - // array. Because the array type is never stepped over (there - // is a leading zero) we can fold the cast into this GEP. - GEP.setOperand(0, X); - return &GEP; - } - } else if (GEP.getNumOperands() == 2 && - isa(CE->getOperand(0)->getType())) { - // Transform things like: - // %t = getelementptr ubyte* cast ([2 x sbyte]* %str to ubyte*), uint %V - // into: %t1 = getelementptr [2 x sbyte*]* %str, int 0, uint %V; cast - Constant *X = CE->getOperand(0); - const Type *SrcElTy = cast(X->getType())->getElementType(); - const Type *ResElTy =cast(CE->getType())->getElementType(); - if (isa(SrcElTy) && - TD->getTypeSize(cast(SrcElTy)->getElementType()) == - TD->getTypeSize(ResElTy)) { - Value *V = InsertNewInstBefore( - new GetElementPtrInst(X, Constant::getNullValue(Type::IntTy), - GEP.getOperand(1), GEP.getName()), GEP); - return new CastInst(V, GEP.getType()); - } + } else if (Value *X = isCast(PtrOp)) { // Is the operand a cast? + if (!isa(X->getType())) { + // Not interesting. Source pointer must be a cast from pointer. + } else if (HasZeroPointerIndex) { + // transform: GEP (cast [10 x ubyte]* X to [0 x ubyte]*), long 0, ... + // into : GEP [10 x ubyte]* X, long 0, ... + // + // This occurs when the program declares an array extern like "int X[];" + // + const PointerType *CPTy = cast(PtrOp->getType()); + const PointerType *XTy = cast(X->getType()); + if (const ArrayType *XATy = + dyn_cast(XTy->getElementType())) + if (const ArrayType *CATy = + dyn_cast(CPTy->getElementType())) + if (CATy->getElementType() == XATy->getElementType()) { + // At this point, we know that the cast source type is a pointer + // to an array of the same type as the destination pointer + // array. Because the array type is never stepped over (there + // is a leading zero) we can fold the cast into this GEP. + GEP.setOperand(0, X); + return &GEP; + } + } else if (GEP.getNumOperands() == 2) { + // Transform things like: + // %t = getelementptr ubyte* cast ([2 x sbyte]* %str to ubyte*), uint %V + // into: %t1 = getelementptr [2 x sbyte*]* %str, int 0, uint %V; cast + const Type *SrcElTy = cast(X->getType())->getElementType(); + const Type *ResElTy=cast(PtrOp->getType())->getElementType(); + if (isa(SrcElTy) && + TD->getTypeSize(cast(SrcElTy)->getElementType()) == + TD->getTypeSize(ResElTy)) { + Value *V = InsertNewInstBefore( + new GetElementPtrInst(X, Constant::getNullValue(Type::IntTy), + GEP.getOperand(1), GEP.getName()), GEP); + return new CastInst(V, GEP.getType()); } } } From duraid at octopus.com.au Mon Sep 12 20:04:05 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Mon, 12 Sep 2005 20:04:05 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2004-06-17-UnorderedCompares.c.tr Message-ID: <200509130104.UAA14713@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2004-06-17-UnorderedCompares.c.tr updated: 1.3 -> 1.4 --- Log message: fails since linux-itanium headers are Different --- Diffs of the changes: (+1 -1) 2004-06-17-UnorderedCompares.c.tr | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/Regression/CFrontend/2004-06-17-UnorderedCompares.c.tr diff -u llvm/test/Regression/CFrontend/2004-06-17-UnorderedCompares.c.tr:1.3 llvm/test/Regression/CFrontend/2004-06-17-UnorderedCompares.c.tr:1.4 --- llvm/test/Regression/CFrontend/2004-06-17-UnorderedCompares.c.tr:1.3 Wed Dec 8 10:41:34 2004 +++ llvm/test/Regression/CFrontend/2004-06-17-UnorderedCompares.c.tr Mon Sep 12 20:03:53 2005 @@ -1,5 +1,5 @@ // RUN: %llvmgcc -xc -std=c99 %s -c -o - | llvm-dis | grep -v llvm.isunordered | not grep call -// XFAIL: sparcv9 +// XFAIL: sparcv9|ia64 #include From lattner at cs.uiuc.edu Mon Sep 12 21:10:06 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 12 Sep 2005 21:10:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200509130210.VAA18149@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.57 -> 1.58 --- Log message: Fix an issue where LSR would miss rewriting a use of an IV expression by a PHI node that is not the original PHI. This fixes up a dot-product loop in galgel, speeding it up from 18.47s to 16.13s. --- Diffs of the changes: (+8 -4) LoopStrengthReduce.cpp | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.57 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.58 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.57 Mon Sep 12 12:11:27 2005 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Sep 12 21:09:55 2005 @@ -333,14 +333,14 @@ Instruction *User = cast(*UI); // Do not infinitely recurse on PHI nodes. - if (isa(User) && User->getParent() == L->getHeader()) + if (isa(User) && Processed.count(User)) continue; // If this is an instruction defined in a nested loop, or outside this loop, // don't recurse into it. bool AddUserToIVUsers = false; if (LI->getLoopFor(User->getParent()) != L) { - DEBUG(std::cerr << "FOUND USER in nested loop: " << *User + DEBUG(std::cerr << "FOUND USER in other loop: " << *User << " OF SCEV: " << *ISE << "\n"); AddUserToIVUsers = true; } else if (!AddUsersIfInteresting(User, L, Processed)) { @@ -459,9 +459,13 @@ for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { if (PN->getIncomingValue(i) == OperandValToReplace) { // If this is a critical edge, split the edge so that we do not insert the - // code on all predecessor/successor paths. + // code on all predecessor/successor paths. We do this unless this is the + // canonical backedge for this loop, as this can make some inserted code + // be in an illegal position. if (e != 1 && - PN->getIncomingBlock(i)->getTerminator()->getNumSuccessors() > 1) { + PN->getIncomingBlock(i)->getTerminator()->getNumSuccessors() > 1 && + (PN->getParent() != L->getHeader() || + !L->contains(PN->getIncomingBlock(i)))) { // First step, split the critical edge. SplitCriticalEdge(PN->getIncomingBlock(i), PN->getParent(), P); From lattner at cs.uiuc.edu Tue Sep 13 13:36:15 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 13:36:15 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509131836.NAA23177@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.369 -> 1.370 --- Log message: Add a simple xform to simplify array accesses with casts in the way. This is useful for 178.galgel where resolution of dope vectors (by the optimizer) causes the scales to become apparent. --- Diffs of the changes: (+62 -2) InstructionCombining.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 62 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.369 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.370 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.369 Mon Sep 12 19:40:14 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Sep 13 13:36:04 2005 @@ -4718,8 +4718,8 @@ } } else if (GEP.getNumOperands() == 2) { // Transform things like: - // %t = getelementptr ubyte* cast ([2 x sbyte]* %str to ubyte*), uint %V - // into: %t1 = getelementptr [2 x sbyte*]* %str, int 0, uint %V; cast + // %t = getelementptr ubyte* cast ([2 x int]* %str to uint*), uint %V + // into: %t1 = getelementptr [2 x int*]* %str, int 0, uint %V; cast const Type *SrcElTy = cast(X->getType())->getElementType(); const Type *ResElTy=cast(PtrOp->getType())->getElementType(); if (isa(SrcElTy) && @@ -4730,6 +4730,66 @@ GEP.getOperand(1), GEP.getName()), GEP); return new CastInst(V, GEP.getType()); } + + // Transform things like: + // getelementptr sbyte* cast ([100 x double]* X to sbyte*), int %tmp + // (where tmp = 8*tmp2) into: + // getelementptr [100 x double]* %arr, int 0, int %tmp.2 + + if (isa(SrcElTy) && + (ResElTy == Type::SByteTy || ResElTy == Type::UByteTy)) { + uint64_t ArrayEltSize = + TD->getTypeSize(cast(SrcElTy)->getElementType()); + + // Check to see if "tmp" is a scale by a multiple of ArrayEltSize. We + // allow either a mul, shift, or constant here. + Value *NewIdx = 0; + ConstantInt *Scale = 0; + if (ArrayEltSize == 1) { + NewIdx = GEP.getOperand(1); + Scale = ConstantInt::get(NewIdx->getType(), 1); + } else if (ConstantInt *CI = dyn_cast(GEP.getOperand(1))) { + NewIdx = ConstantInt::get(NewIdx->getType(), 1); + Scale = CI; + } else if (Instruction *Inst =dyn_cast(GEP.getOperand(1))){ + if (Inst->getOpcode() == Instruction::Shl && + isa(Inst->getOperand(1))) { + unsigned ShAmt =cast(Inst->getOperand(1))->getValue(); + if (Inst->getType()->isSigned()) + Scale = ConstantSInt::get(Inst->getType(), 1ULL << ShAmt); + else + Scale = ConstantUInt::get(Inst->getType(), 1ULL << ShAmt); + NewIdx = Inst->getOperand(0); + } else if (Inst->getOpcode() == Instruction::Mul && + isa(Inst->getOperand(1))) { + Scale = cast(Inst->getOperand(1)); + NewIdx = Inst->getOperand(0); + } + } + + // If the index will be to exactly the right offset with the scale taken + // out, perform the transformation. + if (Scale && Scale->getRawValue() % ArrayEltSize == 0) { + if (ConstantSInt *C = dyn_cast(Scale)) + Scale = ConstantSInt::get(C->getType(), + C->getRawValue()/(int64_t)ArrayEltSize); + else + Scale = ConstantUInt::get(Scale->getType(), + Scale->getRawValue() / ArrayEltSize); + if (Scale->getRawValue() != 1) { + Constant *C = ConstantExpr::getCast(Scale, NewIdx->getType()); + Instruction *Sc = BinaryOperator::createMul(NewIdx, C, "idxscale"); + NewIdx = InsertNewInstBefore(Sc, GEP); + } + + // Insert the new GEP instruction. + Instruction *Idx = + new GetElementPtrInst(X, Constant::getNullValue(Type::IntTy), + NewIdx, GEP.getName()); + Idx = InsertNewInstBefore(Idx, GEP); + return new CastInst(Idx, GEP.getType()); + } + } } } From lattner at cs.uiuc.edu Tue Sep 13 13:48:01 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 13:48:01 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp Message-ID: <200509131848.NAA23691@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelLowering.cpp updated: 1.23 -> 1.24 --- Log message: Remove some dead vectors --- Diffs of the changes: (+0 -4) PPC32ISelLowering.cpp | 4 ---- 1 files changed, 4 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp:1.23 llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp:1.24 --- llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp:1.23 Fri Sep 9 19:21:05 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp Tue Sep 13 13:47:49 2005 @@ -312,10 +312,6 @@ MachineBasicBlock& BB = MF.front(); std::vector ArgValues; - // Due to the rather complicated nature of the PowerPC ABI, rather than a - // fixed size array of physical args, for the sake of simplicity let the STL - // handle tracking them for us. - std::vector argVR, argPR, argOp; unsigned ArgOffset = 24; unsigned GPR_remaining = 8; unsigned FPR_remaining = 13; From lattner at cs.uiuc.edu Tue Sep 13 14:03:24 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 14:03:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelLowering.cpp Message-ID: <200509131903.OAA25510@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelLowering.cpp updated: 1.3 -> 1.4 --- Log message: Majik numbers are bad --- Diffs of the changes: (+2 -2) AlphaISelLowering.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Target/Alpha/AlphaISelLowering.cpp diff -u llvm/lib/Target/Alpha/AlphaISelLowering.cpp:1.3 llvm/lib/Target/Alpha/AlphaISelLowering.cpp:1.4 --- llvm/lib/Target/Alpha/AlphaISelLowering.cpp:1.3 Tue Sep 6 12:00:23 2005 +++ llvm/lib/Target/Alpha/AlphaISelLowering.cpp Tue Sep 13 14:03:13 2005 @@ -193,7 +193,7 @@ VarArgsOffset = count * 8; std::vector LS; for (int i = 0; i < 6; ++i) { - if (args_int[i] < 1024) + if (MRegisterInfo::isPhysicalRegister(args_int[i])) args_int[i] = AddLiveIn(MF, args_int[i], getRegClassFor(MVT::i64)); SDOperand argt = DAG.getCopyFromReg(DAG.getRoot(), args_int[i], MVT::i64); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); @@ -202,7 +202,7 @@ LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(), argt, SDFI, DAG.getSrcValue(NULL))); - if (args_float[i] < 1024) + if (MRegisterInfo::isPhysicalRegister(args_float[i])) args_float[i] = AddLiveIn(MF, args_float[i], getRegClassFor(MVT::f64)); argt = DAG.getCopyFromReg(DAG.getRoot(), args_float[i], MVT::f64); FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); From lattner at cs.uiuc.edu Tue Sep 13 14:31:06 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 14:31:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200509131931.OAA27256@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAGISel.cpp updated: 1.82 -> 1.83 --- Log message: If a function has liveins, and if the target requested that they be plopped into particular vregs, emit copies into the entry MBB. --- Diffs of the changes: (+15 -0) SelectionDAGISel.cpp | 15 +++++++++++++++ 1 files changed, 15 insertions(+) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.82 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.83 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.82 Tue Sep 6 19:15:36 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Tue Sep 13 14:30:54 2005 @@ -24,6 +24,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SSARegMap.h" +#include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" #include "llvm/Target/TargetInstrInfo.h" @@ -1115,6 +1116,20 @@ } } + // Next, if the function has live ins that need to be copied into vregs, + // emit the copies now, into the top of the block. + MachineFunction &MF = SDL.DAG.getMachineFunction(); + if (MF.livein_begin() != MF.livein_end()) { + SSARegMap *RegMap = MF.getSSARegMap(); + const MRegisterInfo &MRI = *MF.getTarget().getRegisterInfo(); + for (MachineFunction::livein_iterator LI = MF.livein_begin(), + E = MF.livein_end(); LI != E; ++LI) + if (LI->second) + MRI.copyRegToReg(*MF.begin(), MF.begin()->end(), LI->second, + LI->first, RegMap->getRegClass(LI->second)); + } + + // Finally, if the target has anything special to do, allow it to do so. EmitFunctionEntryCode(F, SDL.DAG.getMachineFunction()); } From lattner at cs.uiuc.edu Tue Sep 13 14:31:56 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 14:31:56 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp Message-ID: <200509131931.OAA27335@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelPattern.cpp updated: 1.177 -> 1.178 --- Log message: This code is no longer needed, it is moved to the target-indep code --- Diffs of the changes: (+0 -25) X86ISelPattern.cpp | 25 ------------------------- 1 files changed, 25 deletions(-) Index: llvm/lib/Target/X86/X86ISelPattern.cpp diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.177 llvm/lib/Target/X86/X86ISelPattern.cpp:1.178 --- llvm/lib/Target/X86/X86ISelPattern.cpp:1.177 Thu Sep 1 19:16:09 2005 +++ llvm/lib/Target/X86/X86ISelPattern.cpp Tue Sep 13 14:31:44 2005 @@ -1156,31 +1156,6 @@ } void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { - // If this function has live-in values, emit the copies from pregs to vregs at - // the top of the function, before anything else. - MachineBasicBlock *BB = MF.begin(); - if (MF.livein_begin() != MF.livein_end()) { - SSARegMap *RegMap = MF.getSSARegMap(); - for (MachineFunction::livein_iterator LI = MF.livein_begin(), - E = MF.livein_end(); LI != E; ++LI) { - const TargetRegisterClass *RC = RegMap->getRegClass(LI->second); - if (RC == X86::R8RegisterClass) { - BuildMI(BB, X86::MOV8rr, 1, LI->second).addReg(LI->first); - } else if (RC == X86::R16RegisterClass) { - BuildMI(BB, X86::MOV16rr, 1, LI->second).addReg(LI->first); - } else if (RC == X86::R32RegisterClass) { - BuildMI(BB, X86::MOV32rr, 1, LI->second).addReg(LI->first); - } else if (RC == X86::RFPRegisterClass) { - BuildMI(BB, X86::FpMOV, 1, LI->second).addReg(LI->first); - } else if (RC == X86::RXMMRegisterClass) { - BuildMI(BB, X86::MOVAPDrr, 1, LI->second).addReg(LI->first); - } else { - assert(0 && "Unknown regclass!"); - } - } - } - - // If this is main, emit special code for main. if (Fn.hasExternalLinkage() && Fn.getName() == "main") EmitSpecialCodeForMain(BB, MF.getFrameInfo()); From lattner at cs.uiuc.edu Tue Sep 13 14:31:56 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 14:31:56 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelPattern.cpp Message-ID: <200509131931.OAA27331@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelPattern.cpp updated: 1.169 -> 1.170 --- Log message: This code is no longer needed, it is moved to the target-indep code --- Diffs of the changes: (+0 -24) AlphaISelPattern.cpp | 24 ------------------------ 1 files changed, 24 deletions(-) Index: llvm/lib/Target/Alpha/AlphaISelPattern.cpp diff -u llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.169 llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.170 --- llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.169 Tue Sep 6 12:00:23 2005 +++ llvm/lib/Target/Alpha/AlphaISelPattern.cpp Tue Sep 13 14:31:44 2005 @@ -116,8 +116,6 @@ CCInvMap.clear(); } - virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); - unsigned SelectExpr(SDOperand N); void Select(SDOperand N); @@ -135,28 +133,6 @@ }; } -void AlphaISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { - // If this function has live-in values, emit the copies from pregs to vregs at - // the top of the function, before anything else. - MachineBasicBlock *BB = MF.begin(); - if (MF.livein_begin() != MF.livein_end()) { - SSARegMap *RegMap = MF.getSSARegMap(); - for (MachineFunction::livein_iterator LI = MF.livein_begin(), - E = MF.livein_end(); LI != E; ++LI) { - const TargetRegisterClass *RC = RegMap->getRegClass(LI->second); - if (RC == Alpha::GPRCRegisterClass) { - BuildMI(BB, Alpha::BIS, 2, LI->second).addReg(LI->first) - .addReg(LI->first); - } else if (RC == Alpha::FPRCRegisterClass) { - BuildMI(BB, Alpha::CPYS, 2, LI->second).addReg(LI->first) - .addReg(LI->first); - } else { - assert(0 && "Unknown regclass!"); - } - } - } -} - static bool isSIntImmediate(SDOperand N, int64_t& Imm) { // test for constant if (ConstantSDNode *CN = dyn_cast(N)) { From lattner at cs.uiuc.edu Tue Sep 13 14:32:29 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 14:32:29 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp Message-ID: <200509131932.OAA27394@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/SparcV8: SparcV8ISelPattern.cpp updated: 1.6 -> 1.7 --- Log message: This has been moved to the target-indep code --- Diffs of the changes: (+0 -22) SparcV8ISelPattern.cpp | 22 ---------------------- 1 files changed, 22 deletions(-) Index: llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp diff -u llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp:1.6 llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp:1.7 --- llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp:1.6 Tue Aug 16 14:49:35 2005 +++ llvm/lib/Target/SparcV8/SparcV8ISelPattern.cpp Tue Sep 13 14:32:18 2005 @@ -245,34 +245,12 @@ ExprMap.clear(); } - virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); - unsigned SelectExpr(SDOperand N); void Select(SDOperand N); }; } -void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { - // If this function has live-in values, emit the copies from pregs to vregs at - // the top of the function, before anything else. - MachineBasicBlock *BB = MF.begin(); - if (MF.livein_begin() != MF.livein_end()) { - SSARegMap *RegMap = MF.getSSARegMap(); - for (MachineFunction::livein_iterator LI = MF.livein_begin(), - E = MF.livein_end(); LI != E; ++LI) { - const TargetRegisterClass *RC = RegMap->getRegClass(LI->second); - if (RC == V8::GPRCRegisterClass) { - BuildMI(BB, V8::ORrr, 2, LI->second).addReg(LI->first).addReg(V8::G0); - } else if (RC == V8::FPRCRegisterClass) { - BuildMI(BB, V8::FMOVSrr, 2, LI->second).addReg(LI->first); - } else { - assert(0 && "Unknown regclass!"); - } - } - } -} - //These describe LDAx static const int IMM_LOW = -32768; static const int IMM_HIGH = 32767; From lattner at cs.uiuc.edu Tue Sep 13 14:33:51 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 14:33:51 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp Message-ID: <200509131933.OAA27428@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelLowering.cpp updated: 1.24 -> 1.25 --- Log message: Change the arg lowering code to use copyfromreg from vregs associated with incoming arguments instead of the pregs themselves. This fixes the scheduler from causing problems by moving a copyfromreg for an argument to after a select_cc node (now it can, and bad things won't happen). --- Diffs of the changes: (+17 -12) PPC32ISelLowering.cpp | 29 +++++++++++++++++------------ 1 files changed, 17 insertions(+), 12 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp:1.24 llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp:1.25 --- llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp:1.24 Tue Sep 13 13:47:49 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelLowering.cpp Tue Sep 13 14:33:40 2005 @@ -17,6 +17,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SSARegMap.h" #include "llvm/Constants.h" #include "llvm/Function.h" using namespace llvm; @@ -310,6 +311,7 @@ MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock& BB = MF.front(); + SSARegMap *RegMap = MF.getSSARegMap(); std::vector ArgValues; unsigned ArgOffset = 24; @@ -344,9 +346,9 @@ ObjSize = 4; if (!ArgLive) break; if (GPR_remaining > 0) { - MF.addLiveIn(GPR[GPR_idx]); - argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), - GPR[GPR_idx], MVT::i32); + unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass); + MF.addLiveIn(GPR[GPR_idx], VReg); + argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); if (ObjectVT != MVT::i32) { unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext : ISD::AssertZext; @@ -362,15 +364,17 @@ if (!ArgLive) break; if (GPR_remaining > 0) { SDOperand argHi, argLo; - MF.addLiveIn(GPR[GPR_idx]); - argHi = DAG.getCopyFromReg(DAG.getRoot(), GPR[GPR_idx], MVT::i32); + unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass); + MF.addLiveIn(GPR[GPR_idx], VReg); + argHi = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); // If we have two or more remaining argument registers, then both halves // of the i64 can be sourced from there. Otherwise, the lower half will // have to come off the stack. This can happen when an i64 is preceded // by 28 bytes of arguments. if (GPR_remaining > 1) { - MF.addLiveIn(GPR[GPR_idx+1]); - argLo = DAG.getCopyFromReg(argHi, GPR[GPR_idx+1], MVT::i32); + unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass); + MF.addLiveIn(GPR[GPR_idx+1], VReg); + argLo = DAG.getCopyFromReg(argHi, VReg, MVT::i32); } else { int FI = MFI->CreateFixedObject(4, ArgOffset+4); SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); @@ -389,9 +393,9 @@ ObjSize = (ObjectVT == MVT::f64) ? 8 : 4; if (!ArgLive) break; if (FPR_remaining > 0) { - MF.addLiveIn(FPR[FPR_idx]); - argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), - FPR[FPR_idx], ObjectVT); + unsigned VReg = RegMap->createVirtualRegister(&PPC32::FPRCRegClass); + MF.addLiveIn(FPR[FPR_idx], VReg); + argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, ObjectVT); --FPR_remaining; ++FPR_idx; } else { @@ -438,8 +442,9 @@ // result of va_next. std::vector MemOps; for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) { - MF.addLiveIn(GPR[GPR_idx]); - SDOperand Val = DAG.getCopyFromReg(DAG.getRoot(), GPR[GPR_idx], MVT::i32); + unsigned VReg = RegMap->createVirtualRegister(&PPC32::GPRCRegClass); + MF.addLiveIn(GPR[GPR_idx], VReg); + SDOperand Val = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), Val, FIN, DAG.getSrcValue(NULL)); MemOps.push_back(Store); From lattner at cs.uiuc.edu Tue Sep 13 16:21:00 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 16:21:00 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509132121.QAA28420@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.9 -> 1.10 DAGISelEmitter.h updated: 1.8 -> 1.9 --- Log message: completely eliminate TreePattern::PatternType --- Diffs of the changes: (+42 -80) DAGISelEmitter.cpp | 102 +++++++++++++++++++---------------------------------- DAGISelEmitter.h | 20 ++-------- 2 files changed, 42 insertions(+), 80 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.9 llvm/utils/TableGen/DAGISelEmitter.cpp:1.10 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.9 Thu Sep 8 20:15:01 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 16:20:49 2005 @@ -329,66 +329,15 @@ // TreePattern implementation // -TreePattern::TreePattern(PatternType pty, Record *TheRec, - const std::vector &RawPat, - DAGISelEmitter &ise) - : PTy(pty), TheRecord(TheRec), ISE(ise) { +TreePattern::TreePattern(Record *TheRec, const std::vector &RawPat, + DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { for (unsigned i = 0, e = RawPat.size(); i != e; ++i) Trees.push_back(ParseTreePattern(RawPat[i])); - - // Sanity checks and cleanup. - switch (PTy) { - case PatFrag: { - assert(Trees.size() == 1 && "How can we have more than one pattern here?"); - - // Validate arguments list, convert it to map, to discard duplicates. - std::set OperandsMap(Args.begin(), Args.end()); - - if (OperandsMap.count("")) - error("Cannot have unnamed 'node' values in pattern fragment!"); - - // Parse the operands list. - DagInit *OpsList = TheRec->getValueAsDag("Operands"); - if (OpsList->getNodeType()->getName() != "ops") - error("Operands list should start with '(ops ... '!"); - - // Copy over the arguments. - Args.clear(); - for (unsigned i = 0, e = OpsList->getNumArgs(); i != e; ++i) { - if (!dynamic_cast(OpsList->getArg(i)) || - static_cast(OpsList->getArg(i))-> - getDef()->getName() != "node") - error("Operands list should all be 'node' values."); - if (OpsList->getArgName(i).empty()) - error("Operands list should have names for each operand!"); - if (!OperandsMap.count(OpsList->getArgName(i))) - error("'" + OpsList->getArgName(i) + - "' does not occur in pattern or was multiply specified!"); - OperandsMap.erase(OpsList->getArgName(i)); - Args.push_back(OpsList->getArgName(i)); - } - - if (!OperandsMap.empty()) - error("Operands list does not contain an entry for operand '" + - *OperandsMap.begin() + "'!"); - - break; - } - default: - if (!Args.empty()) - error("Only pattern fragments can have operands (use 'node' values)!"); - break; - } } void TreePattern::error(const std::string &Msg) const { - std::string M = "In "; - switch (PTy) { - case PatFrag: M += "patfrag "; break; - case Instruction: M += "instruction "; break; - } - throw M + TheRecord->getName() + ": " + Msg; + throw "In " + TheRecord->getName() + ": " + Msg; } /// getIntrinsicType - Check to see if the specified record has an intrinsic @@ -507,11 +456,6 @@ } void TreePattern::print(std::ostream &OS) const { - switch (getPatternType()) { - case TreePattern::PatFrag: OS << "PatFrag pattern "; break; - case TreePattern::Instruction: OS << "Inst pattern "; break; - } - OS << getRecord()->getName(); if (!Args.empty()) { OS << "(" << Args[0]; @@ -565,9 +509,40 @@ for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { std::vector Trees; Trees.push_back(Fragments[i]->getValueAsDag("Fragment")); - TreePattern *P = new TreePattern(TreePattern::PatFrag, Fragments[i], - Trees, *this); + TreePattern *P = new TreePattern(Fragments[i], Trees, *this); PatternFragments[Fragments[i]] = P; + + // Validate the argument list, converting it to map, to discard duplicates. + std::vector &Args = P->getArgList(); + std::set OperandsMap(Args.begin(), Args.end()); + + if (OperandsMap.count("")) + P->error("Cannot have unnamed 'node' values in pattern fragment!"); + + // Parse the operands list. + DagInit *OpsList = Fragments[i]->getValueAsDag("Operands"); + if (OpsList->getNodeType()->getName() != "ops") + P->error("Operands list should start with '(ops ... '!"); + + // Copy over the arguments. + Args.clear(); + for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { + if (!dynamic_cast(OpsList->getArg(j)) || + static_cast(OpsList->getArg(j))-> + getDef()->getName() != "node") + P->error("Operands list should all be 'node' values."); + if (OpsList->getArgName(j).empty()) + P->error("Operands list should have names for each operand!"); + if (!OperandsMap.count(OpsList->getArgName(j))) + P->error("'" + OpsList->getArgName(j) + + "' does not occur in pattern or was multiply specified!"); + OperandsMap.erase(OpsList->getArgName(j)); + Args.push_back(OpsList->getArgName(j)); + } + + if (!OperandsMap.empty()) + P->error("Operands list does not contain an entry for operand '" + + *OperandsMap.begin() + "'!"); // If there is a code init for this fragment, emit the predicate code and // keep track of the fact that this fragment uses it. @@ -596,7 +571,7 @@ E = PatternFragments.end(); I != E; ++I) { TreePattern *ThePat = I->second; ThePat->InlinePatternFragments(); - + // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. try { @@ -631,8 +606,7 @@ Trees.push_back((DagInit*)LI->getElement(j)); // Parse the instruction. - TreePattern *I = new TreePattern(TreePattern::Instruction, Instrs[i], - Trees, *this); + TreePattern *I = new TreePattern(Instrs[i], Trees, *this); // Inline pattern fragments into it. I->InlinePatternFragments(); Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.8 llvm/utils/TableGen/DAGISelEmitter.h:1.9 --- llvm/utils/TableGen/DAGISelEmitter.h:1.8 Fri Sep 9 21:00:02 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Tue Sep 13 16:20:49 2005 @@ -190,19 +190,10 @@ }; - /// TreePattern - Represent a pattern of one form or another. Currently, two - /// types of patterns are possible: Instructions and PatFrags. + /// TreePattern - Represent a pattern, used for instructions, pattern + /// fragments, etc. /// class TreePattern { - public: - enum PatternType { - PatFrag, Instruction - }; - private: - /// PTy - The type of pattern this is. - /// - PatternType PTy; - /// Trees - The list of pattern trees which corresponds to this pattern. /// Note that PatFrag's only have a single tree. /// @@ -223,13 +214,9 @@ /// TreePattern constructor - Parse the specified DagInits into the /// current record. - TreePattern(PatternType pty, Record *TheRec, + TreePattern(Record *TheRec, const std::vector &RawPat, DAGISelEmitter &ise); - /// getPatternType - Return what flavor of Record this pattern originated from - /// - PatternType getPatternType() const { return PTy; } - /// getTrees - Return the tree patterns which corresponds to this pattern. /// const std::vector &getTrees() const { return Trees; } @@ -250,6 +237,7 @@ assert(i < Args.size() && "Argument reference out of range!"); return Args[i]; } + std::vector &getArgList() { return Args; } DAGISelEmitter &getDAGISelEmitter() const { return ISE; } From lattner at cs.uiuc.edu Tue Sep 13 16:44:39 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 16:44:39 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/Record.h Record.cpp CodeGenTarget.cpp Message-ID: <200509132144.QAA28556@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: Record.h updated: 1.51 -> 1.52 Record.cpp updated: 1.44 -> 1.45 CodeGenTarget.cpp updated: 1.36 -> 1.37 --- Log message: Add a new Record::getValueAsCode method to mirror the other getValueAs* methods. Use it to simplify some code. --- Diffs of the changes: (+20 -11) CodeGenTarget.cpp | 13 ++----------- Record.cpp | 12 ++++++++++++ Record.h | 6 ++++++ 3 files changed, 20 insertions(+), 11 deletions(-) Index: llvm/utils/TableGen/Record.h diff -u llvm/utils/TableGen/Record.h:1.51 llvm/utils/TableGen/Record.h:1.52 --- llvm/utils/TableGen/Record.h:1.51 Fri Aug 19 12:58:49 2005 +++ llvm/utils/TableGen/Record.h Tue Sep 13 16:44:28 2005 @@ -1023,6 +1023,12 @@ /// the value is not the right type. /// DagInit *getValueAsDag(const std::string &FieldName) const; + + /// getValueAsCode - This method looks up the specified field and returns + /// its value as the string data in a CodeInit, throwing an exception if the + /// field does not exist or if the value is not a code object. + /// + std::string getValueAsCode(const std::string &FieldName) const; }; std::ostream &operator<<(std::ostream &OS, const Record &R); Index: llvm/utils/TableGen/Record.cpp diff -u llvm/utils/TableGen/Record.cpp:1.44 llvm/utils/TableGen/Record.cpp:1.45 --- llvm/utils/TableGen/Record.cpp:1.44 Fri Aug 19 12:58:11 2005 +++ llvm/utils/TableGen/Record.cpp Tue Sep 13 16:44:28 2005 @@ -773,6 +773,18 @@ "' does not have a dag initializer!"; } +std::string Record::getValueAsCode(const std::string &FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName + "'!\n"; + + if (const CodeInit *CI = dynamic_cast(R->getValue())) + return CI->getValue(); + throw "Record `" + getName() + "', field `" + FieldName + + "' does not have a code initializer!"; +} + void RecordKeeper::dump() const { std::cerr << *this; } Index: llvm/utils/TableGen/CodeGenTarget.cpp diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.36 llvm/utils/TableGen/CodeGenTarget.cpp:1.37 --- llvm/utils/TableGen/CodeGenTarget.cpp:1.36 Thu Sep 8 16:43:21 2005 +++ llvm/utils/TableGen/CodeGenTarget.cpp Tue Sep 13 16:44:28 2005 @@ -154,17 +154,8 @@ SpillAlignment = R->getValueAsInt("Alignment"); VT = getValueType(R->getValueAsDef("RegType")); - if (CodeInit *CI = dynamic_cast(R->getValueInit("MethodBodies"))) - MethodBodies = CI->getValue(); - else - throw "Expected 'code' fragment for 'MethodBodies' value in register " - "class '" + getName() + "'!"; - - if (CodeInit *CI = dynamic_cast(R->getValueInit("MethodProtos"))) - MethodProtos = CI->getValue(); - else - throw "Expected 'code' fragment for 'MethodProtos' value in register " - "class '" + getName() + "'!"; + MethodBodies = R->getValueAsCode("MethodBodies"); + MethodProtos = R->getValueAsCode("MethodProtos"); ListInit *RegList = R->getValueAsListInit("MemberList"); for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { From lattner at cs.uiuc.edu Tue Sep 13 16:51:11 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 16:51:11 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509132151.QAA28704@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.10 -> 1.11 DAGISelEmitter.h updated: 1.9 -> 1.10 --- Log message: Start parsing node transformation information --- Diffs of the changes: (+46 -6) DAGISelEmitter.cpp | 43 +++++++++++++++++++++++++++++++++++++------ DAGISelEmitter.h | 9 +++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.10 llvm/utils/TableGen/DAGISelEmitter.cpp:1.11 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.10 Tue Sep 13 16:20:49 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 16:51:00 2005 @@ -202,7 +202,9 @@ } if (!PredicateFn.empty()) - OS << "<<" << PredicateFn << ">>"; + OS << "<>"; + if (!TransformFn.empty()) + OS << "<>"; if (!getName().empty()) OS << ":$" << getName(); @@ -227,6 +229,7 @@ New->setName(getName()); New->setType(getType()); New->setPredicateFn(getPredicateFn()); + New->setTransformFn(getTransformFn()); return New; } @@ -494,6 +497,35 @@ } } +/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms +/// map, and emit them to the file as functions. +void DAGISelEmitter::ParseNodeTransforms(std::ostream &OS) { + OS << "\n// Node transformations.\n"; + std::vector Xforms = Records.getAllDerivedDefinitions("SDNodeXForm"); + while (!Xforms.empty()) { + Record *XFormNode = Xforms.back(); + Record *SDNode = XFormNode->getValueAsDef("Opcode"); + std::string Code = XFormNode->getValueAsCode("XFormFunction"); + SDNodeXForms.insert(std::make_pair(XFormNode, + std::make_pair(SDNode, Code))); + + if (!Code.empty()) { + std::string ClassName = getSDNodeInfo(SDNode).getSDClassName(); + const char *C2 = ClassName == "SDNode" ? "N" : "inN"; + + OS << "static inline SDOperand Transform_" << XFormNode->getName() + << "(SDNode *" << C2 << ") {\n"; + if (ClassName != "SDNode") + OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n"; + OS << Code << "\n}\n"; + } + + Xforms.pop_back(); + } +} + + + /// ParseAndResolvePatternFragments - Parse all of the PatFrag definitions in /// the .td file, building up the PatternFragments map. After we've collected /// them all, inline fragments together as necessary, so that there are no @@ -546,9 +578,8 @@ // If there is a code init for this fragment, emit the predicate code and // keep track of the fact that this fragment uses it. - CodeInit *CI = - dynamic_cast(Fragments[i]->getValueInit("Predicate")); - if (!CI->getValue().empty()) { + std::string Code = Fragments[i]->getValueAsCode("Predicate"); + if (!Code.empty()) { assert(!P->getOnlyTree()->isLeaf() && "Can't be a leaf!"); std::string ClassName = getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName(); @@ -558,7 +589,7 @@ << "(SDNode *" << C2 << ") {\n"; if (ClassName != "SDNode") OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n"; - OS << CI->getValue() << "\n}\n"; + OS << Code << "\n}\n"; P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName()); } } @@ -657,12 +688,12 @@ << "}\n"; } - void DAGISelEmitter::run(std::ostream &OS) { EmitSourceFileHeader("DAG Instruction Selector for the " + Target.getName() + " target", OS); ParseNodeInfo(); + ParseNodeTransforms(OS); ParseAndResolvePatternFragments(OS); ParseAndResolveInstructions(); Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.9 llvm/utils/TableGen/DAGISelEmitter.h:1.10 --- llvm/utils/TableGen/DAGISelEmitter.h:1.9 Tue Sep 13 16:20:49 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Tue Sep 13 16:51:00 2005 @@ -120,6 +120,10 @@ /// for a match. If this string is empty, no predicate is involved. std::string PredicateFn; + /// TransformFn - The transformation function to execute on this node before + /// it can be substituted into the resulting instruction on a pattern match. + std::string TransformFn; + std::vector Children; public: TreePatternNode(Record *Op, const std::vector &Ch) @@ -147,6 +151,9 @@ const std::string &getPredicateFn() const { return PredicateFn; } void setPredicateFn(const std::string &Fn) { PredicateFn = Fn; } + + const std::string &getTransformFn() const { return TransformFn; } + void setTransformFn(const std::string &Fn) { TransformFn = Fn; } void print(std::ostream &OS) const; void dump() const; @@ -276,6 +283,7 @@ CodeGenTarget Target; std::map SDNodes; + std::map > SDNodeXForms; std::map PatternFragments; std::vector Instructions; public: @@ -296,6 +304,7 @@ private: void ParseNodeInfo(); + void ParseNodeTransforms(std::ostream &OS); void ParseAndResolvePatternFragments(std::ostream &OS); void ParseAndResolveInstructions(); void EmitInstructionSelector(std::ostream &OS); From lattner at cs.uiuc.edu Tue Sep 13 16:59:26 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 16:59:26 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509132159.QAA28852@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.11 -> 1.12 DAGISelEmitter.h updated: 1.10 -> 1.11 --- Log message: continue xform function parsing --- Diffs of the changes: (+12 -1) DAGISelEmitter.cpp | 8 +++++++- DAGISelEmitter.h | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.11 llvm/utils/TableGen/DAGISelEmitter.cpp:1.12 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.11 Tue Sep 13 16:51:00 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 16:59:15 2005 @@ -509,7 +509,7 @@ SDNodeXForms.insert(std::make_pair(XFormNode, std::make_pair(SDNode, Code))); - if (!Code.empty()) { + if (0 && !Code.empty()) { std::string ClassName = getSDNodeInfo(SDNode).getSDClassName(); const char *C2 = ClassName == "SDNode" ? "N" : "inN"; @@ -592,6 +592,12 @@ OS << Code << "\n}\n"; P->getOnlyTree()->setPredicateFn("Predicate_"+Fragments[i]->getName()); } + + // If there is a node transformation corresponding to this, keep track of + // it. + Record *Transform = Fragments[i]->getValueAsDef("OperandTransform"); + if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? + P->getOnlyTree()->setTransformFn("Transform_"+Transform->getName()); } OS << "\n\n"; Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.10 llvm/utils/TableGen/DAGISelEmitter.h:1.11 --- llvm/utils/TableGen/DAGISelEmitter.h:1.10 Tue Sep 13 16:51:00 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Tue Sep 13 16:59:15 2005 @@ -302,6 +302,11 @@ return PatternFragments.find(R)->second; } + const std::pair &getSDNodeTransform(Record *R) const { + assert(SDNodeXForms.count(R) && "Invalid transform!"); + return SDNodeXForms.find(R)->second; + } + private: void ParseNodeInfo(); void ParseNodeTransforms(std::ostream &OS); From lattner at cs.uiuc.edu Tue Sep 13 17:03:18 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 17:03:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200509132203.RAA29005@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.75 -> 1.76 --- Log message: move the #include for the generated code into the isel class body so we can use/define class methods --- Diffs of the changes: (+3 -1) PPC32ISelDAGToDAG.cpp | 4 +++- 1 files changed, 3 insertions(+), 1 deletion(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.75 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.76 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.75 Fri Sep 9 19:21:06 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Tue Sep 13 17:03:06 2005 @@ -97,10 +97,12 @@ virtual const char *getPassName() const { return "PowerPC DAG->DAG Pattern Instruction Selection"; } + +// Include the pieces autogenerated from the target description. +#include "PPC32GenDAGISel.inc" }; } -#include "PPC32GenDAGISel.inc" /// getGlobalBaseReg - Output the instructions required to put the /// base address to use for accessing globals into a register. From lattner at cs.uiuc.edu Tue Sep 13 17:03:48 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 17:03:48 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509132203.RAA29018@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.12 -> 1.13 --- Log message: Emit code suitable for emission into the ISel class, allowing us to use/define methods. --- Diffs of the changes: (+4 -4) DAGISelEmitter.cpp | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.12 llvm/utils/TableGen/DAGISelEmitter.cpp:1.13 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.12 Tue Sep 13 16:59:15 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 17:03:37 2005 @@ -509,11 +509,11 @@ SDNodeXForms.insert(std::make_pair(XFormNode, std::make_pair(SDNode, Code))); - if (0 && !Code.empty()) { + if (!Code.empty()) { std::string ClassName = getSDNodeInfo(SDNode).getSDClassName(); const char *C2 = ClassName == "SDNode" ? "N" : "inN"; - OS << "static inline SDOperand Transform_" << XFormNode->getName() + OS << "inline SDOperand Transform_" << XFormNode->getName() << "(SDNode *" << C2 << ") {\n"; if (ClassName != "SDNode") OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n"; @@ -585,7 +585,7 @@ getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName(); const char *C2 = ClassName == "SDNode" ? "N" : "inN"; - OS << "static inline bool Predicate_" << Fragments[i]->getName() + OS << "inline bool Predicate_" << Fragments[i]->getName() << "(SDNode *" << C2 << ") {\n"; if (ClassName != "SDNode") OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n"; @@ -671,7 +671,7 @@ // Emit boilerplate. OS << "// The main instruction selector code.\n" << "SDOperand " << Target.getName() - << "DAGToDAGISel::SelectCode(SDOperand Op) {\n" + << "SelectCode(SDOperand Op) {\n" << " SDNode *N = Op.Val;\n" << " if (N->getOpcode() >= ISD::BUILTIN_OP_END &&\n" << " N->getOpcode() < PPCISD::FIRST_NUMBER)\n" From lattner at cs.uiuc.edu Tue Sep 13 17:05:13 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 17:05:13 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509132205.RAA29102@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.13 -> 1.14 --- Log message: don't emit the namespace inside the class! --- Diffs of the changes: (+1 -2) DAGISelEmitter.cpp | 3 +-- 1 files changed, 1 insertion(+), 2 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.13 llvm/utils/TableGen/DAGISelEmitter.cpp:1.14 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.13 Tue Sep 13 17:03:37 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 17:05:02 2005 @@ -670,8 +670,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { // Emit boilerplate. OS << "// The main instruction selector code.\n" - << "SDOperand " << Target.getName() - << "SelectCode(SDOperand Op) {\n" + << "SDOperand SelectCode(SDOperand Op) {\n" << " SDNode *N = Op.Val;\n" << " if (N->getOpcode() >= ISD::BUILTIN_OP_END &&\n" << " N->getOpcode() < PPCISD::FIRST_NUMBER)\n" From lattner at cs.uiuc.edu Tue Sep 13 17:05:32 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 17:05:32 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200509132205.RAA29137@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.76 -> 1.77 --- Log message: we don't need this proto any longer --- Diffs of the changes: (+0 -1) PPC32ISelDAGToDAG.cpp | 1 - 1 files changed, 1 deletion(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.76 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.77 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.76 Tue Sep 13 17:03:06 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Tue Sep 13 17:05:21 2005 @@ -62,7 +62,6 @@ // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. SDOperand Select(SDOperand Op); - SDOperand SelectCode(SDOperand Op); SDNode *SelectIntImmediateExpr(SDOperand LHS, SDOperand RHS, unsigned OCHi, unsigned OCLo, From lattner at cs.uiuc.edu Tue Sep 13 19:09:35 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 19:09:35 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509140009.TAA29687@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.14 -> 1.15 DAGISelEmitter.h updated: 1.11 -> 1.12 --- Log message: start parsing instructions into patterns, start doing many more checks of 'set's. --- Diffs of the changes: (+61 -4) DAGISelEmitter.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++++++---- DAGISelEmitter.h | 5 ++++ 2 files changed, 61 insertions(+), 4 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.14 llvm/utils/TableGen/DAGISelEmitter.cpp:1.15 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.14 Tue Sep 13 17:05:02 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 19:09:24 2005 @@ -654,17 +654,66 @@ I->error("Could not infer all types in pattern!"); } - // Verify that the top-level forms in the instruction are of void type. - for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) - if (I->getTree(j)->getType() != MVT::isVoid) { + // Verify that the top-level forms in the instruction are of void type, and + // figure out how many of the instruction operands are destinations. + for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { + TreePatternNode *Pat = I->getTree(j); + if (Pat->getType() != MVT::isVoid) { I->dump(); I->error("Top-level forms in instruction pattern should have" " void types"); } - + + // Investigate sets. + if (Pat->getOperator()->getName() == "set") { + if (Pat->getNumChildren() == 0) + I->error("set requires operands!"); + else if (Pat->getNumChildren() & 1) + I->error("set requires an even number of operands"); + + // Check the set destinations. + unsigned NumValues = Pat->getNumChildren()/2; + for (unsigned i = 0; i != NumValues; ++i) { + TreePatternNode *Dest = Pat->getChild(i); + if (!Dest->isLeaf()) + I->error("set destination should be a virtual register!"); + + DefInit *Val = dynamic_cast(Dest->getLeafValue()); + if (!Val) + I->error("set destination should be a virtual register!"); + + if (!Val->getDef()->isSubClassOf("RegisterClass")) + I->error("set destination should be a virtual register!"); + } + } + } + DEBUG(I->dump()); Instructions.push_back(I); } + + // If we can, convert the instructions to be a patterns that are matched! + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { + TreePattern *I = Instructions[i]; + + if (I->getNumTrees() != 1) { + std::cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!"; + continue; + } + TreePatternNode *Pattern = I->getTree(0); + if (Pattern->getOperator()->getName() != "set") + continue; // Not a set (store or something?) + + if (Pattern->getNumChildren() != 2) + continue; // Not a set of a single value (not handled so far) + + TreePatternNode *SrcPattern = Pattern->getChild(1)->clone(); + TreePatternNode *DstPattern = SrcPattern->clone(); // FIXME: WRONG + PatternsToMatch.push_back(std::make_pair(SrcPattern, DstPattern)); + DEBUG(std::cerr << "PATTERN TO MATCH: "; SrcPattern->dump(); + std::cerr << "\nRESULT DAG : "; + DstPattern->dump(); std::cerr << "\n"); + } } void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { @@ -697,6 +746,9 @@ EmitSourceFileHeader("DAG Instruction Selector for the " + Target.getName() + " target", OS); + OS << "// *** NOTE: This file is #included into the middle of the target\n" + << "// *** instruction selector class. These functions are really " + << "methods.\n\n"; ParseNodeInfo(); ParseNodeTransforms(OS); ParseAndResolvePatternFragments(OS); Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.11 llvm/utils/TableGen/DAGISelEmitter.h:1.12 --- llvm/utils/TableGen/DAGISelEmitter.h:1.11 Tue Sep 13 16:59:15 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Tue Sep 13 19:09:24 2005 @@ -286,6 +286,11 @@ std::map > SDNodeXForms; std::map PatternFragments; std::vector Instructions; + + /// PatternsToMatch - All of the things we are matching on the DAG. The first + /// value is the pattern to match, the second pattern is the result to + /// emit. + std::vector > PatternsToMatch; public: DAGISelEmitter(RecordKeeper &R) : Records(R) {} From lattner at cs.uiuc.edu Tue Sep 13 21:11:24 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 21:11:24 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509140211.VAA03305@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.15 -> 1.16 --- Log message: Add some more checking/verification code --- Diffs of the changes: (+19 -2) DAGISelEmitter.cpp | 21 +++++++++++++++++++-- 1 files changed, 19 insertions(+), 2 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.15 llvm/utils/TableGen/DAGISelEmitter.cpp:1.16 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.15 Tue Sep 13 19:09:24 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 21:11:12 2005 @@ -654,8 +654,12 @@ I->error("Could not infer all types in pattern!"); } + // SetDestinations - Keep track of all the virtual registers that are 'set' + // in the instruction, including what reg class they are. + std::map SetDestinations; + // Verify that the top-level forms in the instruction are of void type, and - // figure out how many of the instruction operands are destinations. + // fill in the SetDestinations map. for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { TreePatternNode *Pat = I->getTree(j); if (Pat->getType() != MVT::isVoid) { @@ -677,16 +681,29 @@ TreePatternNode *Dest = Pat->getChild(i); if (!Dest->isLeaf()) I->error("set destination should be a virtual register!"); - + DefInit *Val = dynamic_cast(Dest->getLeafValue()); if (!Val) I->error("set destination should be a virtual register!"); if (!Val->getDef()->isSubClassOf("RegisterClass")) I->error("set destination should be a virtual register!"); + if (Dest->getName().empty()) + I->error("set destination must have a name!"); + if (SetDestinations.count(Dest->getName())) + I->error("cannot set '" + Dest->getName() +"' multiple times"); + SetDestinations[Dest->getName()] = Val->getDef(); } } } + + // Now that we have operands that are sets, inspect the operands list for + // the instruction. This determines the order that operands are added to + // the machine instruction the node corresponds to. + assert(SetDestinations.size() == 1 && + "This code only handles a single set right now!"); + + DEBUG(I->dump()); Instructions.push_back(I); From lattner at cs.uiuc.edu Tue Sep 13 23:03:27 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 13 Sep 2005 23:03:27 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509140403.XAA04687@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.16 -> 1.17 DAGISelEmitter.h updated: 1.12 -> 1.13 --- Log message: Switch to a slightly more structured representation for instructions --- Diffs of the changes: (+24 -8) DAGISelEmitter.cpp | 11 +++++------ DAGISelEmitter.h | 21 +++++++++++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.16 llvm/utils/TableGen/DAGISelEmitter.cpp:1.17 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.16 Tue Sep 13 21:11:12 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Tue Sep 13 23:03:15 2005 @@ -700,18 +700,19 @@ // Now that we have operands that are sets, inspect the operands list for // the instruction. This determines the order that operands are added to // the machine instruction the node corresponds to. - assert(SetDestinations.size() == 1 && + unsigned NumResults = SetDestinations.size(); + assert(NumResults == 1 && "This code only handles a single set right now!"); - + unsigned NumOperands = 0; DEBUG(I->dump()); - Instructions.push_back(I); + Instructions.push_back(DAGInstruction(I, NumResults, NumOperands)); } // If we can, convert the instructions to be a patterns that are matched! for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { - TreePattern *I = Instructions[i]; + TreePattern *I = Instructions[i].getPattern(); if (I->getNumTrees() != 1) { std::cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!"; @@ -780,7 +781,5 @@ delete I->second; PatternFragments.clear(); - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) - delete Instructions[i]; Instructions.clear(); } Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.12 llvm/utils/TableGen/DAGISelEmitter.h:1.13 --- llvm/utils/TableGen/DAGISelEmitter.h:1.12 Tue Sep 13 19:09:24 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Tue Sep 13 23:03:16 2005 @@ -272,7 +272,24 @@ MVT::ValueType getIntrinsicType(Record *R) const; TreePatternNode *ParseTreePattern(DagInit *DI); }; - + + + class DAGInstruction { + TreePattern *Pattern; + unsigned NumResults; + unsigned NumOperands; + public: + DAGInstruction(TreePattern *TP, unsigned results, unsigned ops) + : Pattern(TP), NumResults(results), NumOperands(ops) {} + + ~DAGInstruction() { + delete Pattern; + } + + TreePattern *getPattern() const { return Pattern; } + unsigned getNumResults() const { return NumResults; } + unsigned getNumOperands() const { return NumOperands; } + }; /// InstrSelectorEmitter - The top-level class which coordinates construction @@ -285,7 +302,7 @@ std::map SDNodes; std::map > SDNodeXForms; std::map PatternFragments; - std::vector Instructions; + std::vector Instructions; /// PatternsToMatch - All of the things we are matching on the DAG. The first /// value is the pattern to match, the second pattern is the result to From lattner at cs.uiuc.edu Wed Sep 14 01:03:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 01:03:21 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509140603.BAA08003@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.17 -> 1.18 DAGISelEmitter.h updated: 1.13 -> 1.14 --- Log message: remove some code that isn't ready for prime time --- Diffs of the changes: (+2 -6) DAGISelEmitter.cpp | 4 ++-- DAGISelEmitter.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.17 llvm/utils/TableGen/DAGISelEmitter.cpp:1.18 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.17 Tue Sep 13 23:03:15 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 01:03:10 2005 @@ -701,8 +701,8 @@ // the instruction. This determines the order that operands are added to // the machine instruction the node corresponds to. unsigned NumResults = SetDestinations.size(); - assert(NumResults == 1 && - "This code only handles a single set right now!"); + //assert(NumResults == 1 && + // "This code only handles a single set right now!"); unsigned NumOperands = 0; Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.13 llvm/utils/TableGen/DAGISelEmitter.h:1.14 --- llvm/utils/TableGen/DAGISelEmitter.h:1.13 Tue Sep 13 23:03:16 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Wed Sep 14 01:03:10 2005 @@ -282,10 +282,6 @@ DAGInstruction(TreePattern *TP, unsigned results, unsigned ops) : Pattern(TP), NumResults(results), NumOperands(ops) {} - ~DAGInstruction() { - delete Pattern; - } - TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return NumResults; } unsigned getNumOperands() const { return NumOperands; } From lattner at cs.uiuc.edu Wed Sep 14 01:06:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 01:06:57 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp Message-ID: <200509140606.BAA08787@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelPattern.cpp updated: 1.178 -> 1.179 --- Log message: fix a major regression from my patch this afternoon --- Diffs of the changes: (+1 -0) X86ISelPattern.cpp | 1 + 1 files changed, 1 insertion(+) Index: llvm/lib/Target/X86/X86ISelPattern.cpp diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.178 llvm/lib/Target/X86/X86ISelPattern.cpp:1.179 --- llvm/lib/Target/X86/X86ISelPattern.cpp:1.178 Tue Sep 13 14:31:44 2005 +++ llvm/lib/Target/X86/X86ISelPattern.cpp Wed Sep 14 01:06:45 2005 @@ -1157,6 +1157,7 @@ void ISel::EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) { // If this is main, emit special code for main. + MachineBasicBlock *BB = MF.begin(); if (Fn.hasExternalLinkage() && Fn.getName() == "main") EmitSpecialCodeForMain(BB, MF.getFrameInfo()); } From lattner at cs.uiuc.edu Wed Sep 14 12:33:07 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 12:33:07 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509141733.MAA18648@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.370 -> 1.371 --- Log message: Fix the regression last night compiling povray --- Diffs of the changes: (+3 -2) InstructionCombining.cpp | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.370 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.371 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.370 Tue Sep 13 13:36:04 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Sep 14 12:32:56 2005 @@ -4749,7 +4749,7 @@ NewIdx = GEP.getOperand(1); Scale = ConstantInt::get(NewIdx->getType(), 1); } else if (ConstantInt *CI = dyn_cast(GEP.getOperand(1))) { - NewIdx = ConstantInt::get(NewIdx->getType(), 1); + NewIdx = ConstantInt::get(CI->getType(), 1); Scale = CI; } else if (Instruction *Inst =dyn_cast(GEP.getOperand(1))){ if (Inst->getOpcode() == Instruction::Shl && @@ -4772,7 +4772,8 @@ if (Scale && Scale->getRawValue() % ArrayEltSize == 0) { if (ConstantSInt *C = dyn_cast(Scale)) Scale = ConstantSInt::get(C->getType(), - C->getRawValue()/(int64_t)ArrayEltSize); + (int64_t)C->getRawValue() / + (int64_t)ArrayEltSize); else Scale = ConstantUInt::get(Scale->getType(), Scale->getRawValue() / ArrayEltSize); From lattner at cs.uiuc.edu Wed Sep 14 13:03:05 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 13:03:05 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeGenTarget.h Message-ID: <200509141803.NAA20116@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeGenTarget.h updated: 1.18 -> 1.19 --- Log message: add an accessor --- Diffs of the changes: (+6 -0) CodeGenTarget.h | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/utils/TableGen/CodeGenTarget.h diff -u llvm/utils/TableGen/CodeGenTarget.h:1.18 llvm/utils/TableGen/CodeGenTarget.h:1.19 --- llvm/utils/TableGen/CodeGenTarget.h:1.18 Thu Sep 8 16:43:21 2005 +++ llvm/utils/TableGen/CodeGenTarget.h Wed Sep 14 13:02:53 2005 @@ -103,6 +103,12 @@ return Instructions; } + CodeGenInstruction &getInstruction(const std::string &Name) const { + const std::map &Insts = getInstructions(); + assert(Insts.count(Name) && "Not an instruction!"); + return const_cast(Insts.find(Name)->second); + } + typedef std::map::const_iterator inst_iterator; inst_iterator inst_begin() const { return getInstructions().begin(); } From lattner at cs.uiuc.edu Wed Sep 14 13:18:51 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 13:18:51 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Message-ID: <200509141818.NAA20297@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PowerPCInstrInfo.td updated: 1.97 -> 1.98 --- Log message: Fix some bugs noticed by new checking code --- Diffs of the changes: (+14 -8) PowerPCInstrInfo.td | 22 ++++++++++++++-------- 1 files changed, 14 insertions(+), 8 deletions(-) Index: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td diff -u llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.97 llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.98 --- llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.97 Fri Sep 9 13:17:41 2005 +++ llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Wed Sep 14 13:18:39 2005 @@ -400,16 +400,16 @@ []>, isDOT; def ORI : DForm_4<24, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2), "ori $dst, $src1, $src2", - [(set GPRC:$rD, (or GPRC:$rA, immZExt16:$imm))]>; + [(set GPRC:$dst, (or GPRC:$src1, immZExt16:$src2))]>; def ORIS : DForm_4<25, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2), "oris $dst, $src1, $src2", - [(set GPRC:$rD, (or GPRC:$rA, imm16Shifted:$imm))]>; + [(set GPRC:$dst, (or GPRC:$src1, imm16Shifted:$src2))]>; def XORI : DForm_4<26, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2), "xori $dst, $src1, $src2", - [(set GPRC:$rD, (xor GPRC:$rA, immZExt16:$imm))]>; + [(set GPRC:$dst, (xor GPRC:$src1, immZExt16:$src2))]>; def XORIS : DForm_4<27, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2), "xoris $dst, $src1, $src2", - [(set GPRC:$rD, (xor GPRC:$rA, imm16Shifted:$imm))]>; + [(set GPRC:$dst, (xor GPRC:$src2, imm16Shifted:$src2))]>; def NOP : DForm_4_zero<24, (ops), "nop">; def CMPI : DForm_5<11, (ops CRRC:$crD, i1imm:$L, GPRC:$rA, s16imm:$imm), "cmpi $crD, $L, $rA, $imm">; @@ -473,7 +473,7 @@ [(set GPRC:$rA, (not (and GPRC:$rS, GPRC:$rB)))]>; def AND : XForm_6<31, 28, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "and $rA, $rS, $rB", - [(set GPRC:$rT, (and GPRC:$rA, GPRC:$rB))]>; + [(set GPRC:$rA, (and GPRC:$rS, GPRC:$rB))]>; def ANDo : XForm_6<31, 28, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "and. $rA, $rS, $rB", []>, isDOT; @@ -482,7 +482,7 @@ [(set GPRC:$rA, (and GPRC:$rS, (not GPRC:$rB)))]>; def OR : XForm_6<31, 444, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "or $rA, $rS, $rB", - [(set GPRC:$rT, (or GPRC:$rA, GPRC:$rB))]>; + [(set GPRC:$rA, (or GPRC:$rS, GPRC:$rB))]>; def NOR : XForm_6<31, 124, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "nor $rA, $rS, $rB", [(set GPRC:$rA, (not (or GPRC:$rS, GPRC:$rB)))]>; @@ -494,10 +494,10 @@ [(set GPRC:$rA, (or GPRC:$rS, (not GPRC:$rB)))]>; def EQV : XForm_6<31, 284, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "eqv $rA, $rS, $rB", - [(set GPRC:$rT, (not (xor GPRC:$rA, GPRC:$rB)))]>; + [(set GPRC:$rA, (not (xor GPRC:$rS, GPRC:$rB)))]>; def XOR : XForm_6<31, 316, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "xor $rA, $rS, $rB", - [(set GPRC:$rT, (xor GPRC:$rA, GPRC:$rB))]>; + [(set GPRC:$rA, (xor GPRC:$rS, GPRC:$rB))]>; def SLD : XForm_6<31, 27, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB), "sld $rA, $rS, $rB", []>, isPPC64; @@ -773,6 +773,12 @@ def : Pat<(xor GPRC:$in, imm:$imm), (XORIS (XORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>; +// Same as above, but using a temporary. +def : Pattern<(xor GPRC:$in, imm:$imm), + [(set GPRC:$tmp, (XORI GPRC:$in, (LO16 imm:$imm))), + (XORIS GPRC:$tmp, (HI16 imm:$imm))]>; + + //===----------------------------------------------------------------------===// // PowerPCInstrInfo Definition // From lattner at cs.uiuc.edu Wed Sep 14 13:19:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 13:19:37 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509141819.NAA20331@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.18 -> 1.19 --- Log message: Verify that set destinations occur first in the instruction operand list. --- Diffs of the changes: (+28 -2) DAGISelEmitter.cpp | 30 ++++++++++++++++++++++++++++-- 1 files changed, 28 insertions(+), 2 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.18 llvm/utils/TableGen/DAGISelEmitter.cpp:1.19 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.18 Wed Sep 14 01:03:10 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 13:19:25 2005 @@ -701,8 +701,34 @@ // the instruction. This determines the order that operands are added to // the machine instruction the node corresponds to. unsigned NumResults = SetDestinations.size(); - //assert(NumResults == 1 && - // "This code only handles a single set right now!"); + + // Parse the operands list from the (ops) list, validating it. + std::vector &Args = I->getArgList(); + assert(Args.empty() && "Args list should still be empty here!"); + CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]->getName()); + + // Check that all of the results occur first in the list. + for (unsigned i = 0; i != NumResults; ++i) { + const std::string &OpName = CGI.OperandList[i].Name; + if (OpName.empty()) + I->error("Operand #" + utostr(i) + " in operands list has no name!"); + + // Check that it exists in SetDestinations. + Record *R = SetDestinations[OpName]; + if (R == 0) + I->error("Operand $" + OpName + " should be a set destination: all " + "outputs must occur before inputs in operand list!"); + + if (CGI.OperandList[i].Rec != R) + I->error("Operand $" + OpName + " class mismatch!"); + + // Okay, this one checks out. + SetDestinations.erase(OpName); + } + + if (!SetDestinations.empty()) + I->error("'" + SetDestinations.begin()->first + + "' set but does not appear in operand list!"); unsigned NumOperands = 0; From lattner at cs.uiuc.edu Wed Sep 14 15:53:16 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 15:53:16 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Message-ID: <200509142053.PAA02874@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PowerPCInstrInfo.td updated: 1.98 -> 1.99 --- Log message: Fix some issues exposed by more testing. XORIS had the wrong operands specified. The various *imm operands defined by PPC are really all i32, even though the actual immediate is restricted to a smaller value in it. --- Diffs of the changes: (+5 -5) PowerPCInstrInfo.td | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td diff -u llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.98 llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.99 --- llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.98 Wed Sep 14 13:18:39 2005 +++ llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Wed Sep 14 15:53:05 2005 @@ -238,16 +238,16 @@ //===----------------------------------------------------------------------===// // PowerPC Operand Definitions. -def u5imm : Operand { +def u5imm : Operand { let PrintMethod = "printU5ImmOperand"; } -def u6imm : Operand { +def u6imm : Operand { let PrintMethod = "printU6ImmOperand"; } -def s16imm : Operand { +def s16imm : Operand { let PrintMethod = "printS16ImmOperand"; } -def u16imm : Operand { +def u16imm : Operand { let PrintMethod = "printU16ImmOperand"; } def target : Operand { @@ -409,7 +409,7 @@ [(set GPRC:$dst, (xor GPRC:$src1, immZExt16:$src2))]>; def XORIS : DForm_4<27, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2), "xoris $dst, $src1, $src2", - [(set GPRC:$dst, (xor GPRC:$src2, imm16Shifted:$src2))]>; + [(set GPRC:$dst, (xor GPRC:$src1, imm16Shifted:$src2))]>; def NOP : DForm_4_zero<24, (ops), "nop">; def CMPI : DForm_5<11, (ops CRRC:$crD, i1imm:$L, GPRC:$rA, s16imm:$imm), "cmpi $crD, $L, $rA, $imm">; From lattner at cs.uiuc.edu Wed Sep 14 15:53:53 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 15:53:53 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509142053.PAA02932@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.19 -> 1.20 DAGISelEmitter.h updated: 1.14 -> 1.15 --- Log message: Parse significantly more of the instruction pattern, now collecting and verifying information about the operands. --- Diffs of the changes: (+141 -46) DAGISelEmitter.cpp | 183 +++++++++++++++++++++++++++++++++++++++-------------- DAGISelEmitter.h | 4 + 2 files changed, 141 insertions(+), 46 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.19 llvm/utils/TableGen/DAGISelEmitter.cpp:1.20 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.19 Wed Sep 14 13:19:25 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 15:53:42 2005 @@ -340,6 +340,7 @@ } void TreePattern::error(const std::string &Msg) const { + dump(); throw "In " + TheRecord->getName() + ": " + Msg; } @@ -625,6 +626,102 @@ } } +/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an +/// instruction input. +static void HandleUse(TreePattern *I, TreePatternNode *Pat, + std::map &InstInputs) { + // No name -> not interesting. + if (Pat->getName().empty()) return; + + Record *Rec; + if (Pat->isLeaf()) { + DefInit *DI = dynamic_cast(Pat->getLeafValue()); + if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!"); + Rec = DI->getDef(); + } else { + assert(Pat->getNumChildren() == 0 && "can't be a use with children!"); + Rec = Pat->getOperator(); + } + + TreePatternNode *&Slot = InstInputs[Pat->getName()]; + if (!Slot) { + Slot = Pat; + } else { + Record *SlotRec; + if (Slot->isLeaf()) { + Rec = dynamic_cast(Slot->getLeafValue())->getDef(); + } else { + assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); + SlotRec = Slot->getOperator(); + } + + // Ensure that the inputs agree if we've already seen this input. + if (Rec != SlotRec) + I->error("All $" + Pat->getName() + " inputs must agree with each other"); + if (Slot->getType() != Pat->getType()) + I->error("All $" + Pat->getName() + " inputs must agree with each other"); + } +} + +/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is +/// part of "I", the instruction), computing the set of inputs and outputs of +/// the pattern. Report errors if we see anything naughty. +void DAGISelEmitter:: +FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, + std::map &InstInputs, + std::map &InstResults) { + if (Pat->isLeaf()) { + HandleUse(I, Pat, InstInputs); + return; + } else if (Pat->getOperator()->getName() != "set") { + // If this is not a set, verify that the children nodes are not void typed, + // and recurse. + for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { + if (Pat->getChild(i)->getType() == MVT::isVoid) + I->error("Cannot have void nodes inside of patterns!"); + FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults); + } + + // If this is a non-leaf node with no children, treat it basically as if + // it were a leaf. This handles nodes like (imm). + if (Pat->getNumChildren() == 0) + HandleUse(I, Pat, InstInputs); + + return; + } + + // Otherwise, this is a set, validate and collect instruction results. + if (Pat->getNumChildren() == 0) + I->error("set requires operands!"); + else if (Pat->getNumChildren() & 1) + I->error("set requires an even number of operands"); + + // Check the set destinations. + unsigned NumValues = Pat->getNumChildren()/2; + for (unsigned i = 0; i != NumValues; ++i) { + TreePatternNode *Dest = Pat->getChild(i); + if (!Dest->isLeaf()) + I->error("set destination should be a virtual register!"); + + DefInit *Val = dynamic_cast(Dest->getLeafValue()); + if (!Val) + I->error("set destination should be a virtual register!"); + + if (!Val->getDef()->isSubClassOf("RegisterClass")) + I->error("set destination should be a virtual register!"); + if (Dest->getName().empty()) + I->error("set destination must have a name!"); + if (InstResults.count(Dest->getName())) + I->error("cannot set '" + Dest->getName() +"' multiple times"); + InstResults[Dest->getName()] = Val->getDef(); + + // Verify and collect info from the computation. + FindPatternInputsAndOutputs(I, Pat->getChild(i+NumValues), + InstInputs, InstResults); + } +} + + /// ParseAndResolveInstructions - Parse all of the instructions, inlining and /// resolving any fragments involved. This populates the Instructions list with /// fully resolved instructions. @@ -654,12 +751,16 @@ I->error("Could not infer all types in pattern!"); } - // SetDestinations - Keep track of all the virtual registers that are 'set' + // InstInputs - Keep track of all of the inputs of the instruction, along + // with the record they are declared as. + std::map InstInputs; + + // InstResults - Keep track of all the virtual registers that are 'set' // in the instruction, including what reg class they are. - std::map SetDestinations; - + std::map InstResults; + // Verify that the top-level forms in the instruction are of void type, and - // fill in the SetDestinations map. + // fill in the InstResults map. for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { TreePatternNode *Pat = I->getTree(j); if (Pat->getType() != MVT::isVoid) { @@ -667,40 +768,15 @@ I->error("Top-level forms in instruction pattern should have" " void types"); } - - // Investigate sets. - if (Pat->getOperator()->getName() == "set") { - if (Pat->getNumChildren() == 0) - I->error("set requires operands!"); - else if (Pat->getNumChildren() & 1) - I->error("set requires an even number of operands"); - - // Check the set destinations. - unsigned NumValues = Pat->getNumChildren()/2; - for (unsigned i = 0; i != NumValues; ++i) { - TreePatternNode *Dest = Pat->getChild(i); - if (!Dest->isLeaf()) - I->error("set destination should be a virtual register!"); - - DefInit *Val = dynamic_cast(Dest->getLeafValue()); - if (!Val) - I->error("set destination should be a virtual register!"); - - if (!Val->getDef()->isSubClassOf("RegisterClass")) - I->error("set destination should be a virtual register!"); - if (Dest->getName().empty()) - I->error("set destination must have a name!"); - if (SetDestinations.count(Dest->getName())) - I->error("cannot set '" + Dest->getName() +"' multiple times"); - SetDestinations[Dest->getName()] = Val->getDef(); - } - } + + // Find inputs and outputs, and verify the structure of the uses/defs. + FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults); } - // Now that we have operands that are sets, inspect the operands list for - // the instruction. This determines the order that operands are added to - // the machine instruction the node corresponds to. - unsigned NumResults = SetDestinations.size(); + // Now that we have inputs and outputs of the pattern, inspect the operands + // list for the instruction. This determines the order that operands are + // added to the machine instruction the node corresponds to. + unsigned NumResults = InstResults.size(); // Parse the operands list from the (ops) list, validating it. std::vector &Args = I->getArgList(); @@ -709,12 +785,16 @@ // Check that all of the results occur first in the list. for (unsigned i = 0; i != NumResults; ++i) { + if (NumResults == CGI.OperandList.size()) + I->error("'" + InstResults.begin()->first + + "' set but does not appear in operand list!"); + const std::string &OpName = CGI.OperandList[i].Name; if (OpName.empty()) I->error("Operand #" + utostr(i) + " in operands list has no name!"); - // Check that it exists in SetDestinations. - Record *R = SetDestinations[OpName]; + // Check that it exists in InstResults. + Record *R = InstResults[OpName]; if (R == 0) I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); @@ -723,20 +803,31 @@ I->error("Operand $" + OpName + " class mismatch!"); // Okay, this one checks out. - SetDestinations.erase(OpName); + InstResults.erase(OpName); } - - if (!SetDestinations.empty()) - I->error("'" + SetDestinations.begin()->first + - "' set but does not appear in operand list!"); - unsigned NumOperands = 0; - + // Loop over the inputs next. + for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) { + const std::string &OpName = CGI.OperandList[i].Name; + if (OpName.empty()) + I->error("Operand #" + utostr(i) + " in operands list has no name!"); + + if (!InstInputs.count(OpName)) + I->error("Operand $" + OpName + + " does not appear in the instruction pattern"); + TreePatternNode *InVal = InstInputs[OpName]; + if (CGI.OperandList[i].Ty != InVal->getType()) + I->error("Operand $" + OpName + + "'s type disagrees between the operand and pattern"); + } + + unsigned NumOperands = CGI.OperandList.size()-NumResults; + DEBUG(I->dump()); Instructions.push_back(DAGInstruction(I, NumResults, NumOperands)); } - // If we can, convert the instructions to be a patterns that are matched! + // If we can, convert the instructions to be patterns that are matched! for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { TreePattern *I = Instructions[i].getPattern(); Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.14 llvm/utils/TableGen/DAGISelEmitter.h:1.15 --- llvm/utils/TableGen/DAGISelEmitter.h:1.14 Wed Sep 14 01:03:10 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Wed Sep 14 15:53:42 2005 @@ -330,6 +330,10 @@ void ParseNodeTransforms(std::ostream &OS); void ParseAndResolvePatternFragments(std::ostream &OS); void ParseAndResolveInstructions(); + void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, + std::map &InstInputs, + std::map &InstResults); void EmitInstructionSelector(std::ostream &OS); }; From lattner at cs.uiuc.edu Wed Sep 14 16:04:24 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:04:24 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509142104.QAA04006@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.20 -> 1.21 --- Log message: fix a broke range check --- Diffs of the changes: (+1 -1) DAGISelEmitter.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.20 llvm/utils/TableGen/DAGISelEmitter.cpp:1.21 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.20 Wed Sep 14 15:53:42 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 16:04:12 2005 @@ -785,7 +785,7 @@ // Check that all of the results occur first in the list. for (unsigned i = 0; i != NumResults; ++i) { - if (NumResults == CGI.OperandList.size()) + if (i == CGI.OperandList.size()) I->error("'" + InstResults.begin()->first + "' set but does not appear in operand list!"); From lattner at cs.uiuc.edu Wed Sep 14 16:05:13 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:05:13 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeGenTarget.cpp Message-ID: <200509142105.QAA04042@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeGenTarget.cpp updated: 1.37 -> 1.38 --- Log message: Check that operands have unique names. REJECT instructions with broken operand lists: only don't parse them if they are entirely missing (sparcv9). --- Diffs of the changes: (+39 -29) CodeGenTarget.cpp | 68 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 39 insertions(+), 29 deletions(-) Index: llvm/utils/TableGen/CodeGenTarget.cpp diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.37 llvm/utils/TableGen/CodeGenTarget.cpp:1.38 --- llvm/utils/TableGen/CodeGenTarget.cpp:1.37 Tue Sep 13 16:44:28 2005 +++ llvm/utils/TableGen/CodeGenTarget.cpp Wed Sep 14 16:05:02 2005 @@ -18,6 +18,7 @@ #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" +#include using namespace llvm; static cl::opt @@ -250,39 +251,48 @@ usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter"); hasVariableNumberOfOperands = false; + DagInit *DI; try { - DagInit *DI = R->getValueAsDag("OperandList"); - - unsigned MIOperandNo = 0; - for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) - if (DefInit *Arg = dynamic_cast(DI->getArg(i))) { - Record *Rec = Arg->getDef(); - MVT::ValueType Ty; - std::string PrintMethod = "printOperand"; - unsigned NumOps = 1; - if (Rec->isSubClassOf("RegisterClass")) { - Ty = getValueType(Rec->getValueAsDef("RegType")); - } else if (Rec->isSubClassOf("Operand")) { - Ty = getValueType(Rec->getValueAsDef("Type")); - PrintMethod = Rec->getValueAsString("PrintMethod"); - NumOps = Rec->getValueAsInt("NumMIOperands"); - } else if (Rec->getName() == "variable_ops") { - hasVariableNumberOfOperands = true; - continue; - } else - throw "Unknown operand class '" + Rec->getName() + - "' in instruction '" + R->getName() + "' instruction!"; - - OperandList.push_back(OperandInfo(Rec, Ty, DI->getArgName(i), - PrintMethod, MIOperandNo, NumOps)); - MIOperandNo += NumOps; - } else { - throw "Illegal operand for the '" + R->getName() + "' instruction!"; - } + DI = R->getValueAsDag("OperandList"); } catch (...) { - // Error parsing operands list, just ignore it. + // Error getting operand list, just ignore it (sparcv9). AsmString.clear(); OperandList.clear(); + return; + } + + unsigned MIOperandNo = 0; + std::set OperandNames; + for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) { + DefInit *Arg = dynamic_cast(DI->getArg(i)); + if (!Arg) + throw "Illegal operand for the '" + R->getName() + "' instruction!"; + + Record *Rec = Arg->getDef(); + MVT::ValueType Ty; + std::string PrintMethod = "printOperand"; + unsigned NumOps = 1; + if (Rec->isSubClassOf("RegisterClass")) { + Ty = getValueType(Rec->getValueAsDef("RegType")); + } else if (Rec->isSubClassOf("Operand")) { + Ty = getValueType(Rec->getValueAsDef("Type")); + PrintMethod = Rec->getValueAsString("PrintMethod"); + NumOps = Rec->getValueAsInt("NumMIOperands"); + } else if (Rec->getName() == "variable_ops") { + hasVariableNumberOfOperands = true; + continue; + } else + throw "Unknown operand class '" + Rec->getName() + + "' in instruction '" + R->getName() + "' instruction!"; + + if (!DI->getArgName(i).empty() && + !OperandNames.insert(DI->getArgName(i)).second) + throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + + " has the same name as a previous operand!"; + + OperandList.push_back(OperandInfo(Rec, Ty, DI->getArgName(i), + PrintMethod, MIOperandNo, NumOps)); + MIOperandNo += NumOps; } } From lattner at cs.uiuc.edu Wed Sep 14 16:08:29 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:08:29 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Message-ID: <200509142108.QAA04294@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PowerPCInstrInfo.td updated: 1.99 -> 1.100 --- Log message: give all operands names --- Diffs of the changes: (+4 -3) PowerPCInstrInfo.td | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) Index: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td diff -u llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.99 llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.100 --- llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.99 Wed Sep 14 15:53:05 2005 +++ llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Wed Sep 14 16:08:18 2005 @@ -275,8 +275,8 @@ def PHI : Pseudo<(ops variable_ops), "; PHI">; let isLoad = 1 in { -def ADJCALLSTACKDOWN : Pseudo<(ops u16imm), "; ADJCALLSTACKDOWN">; -def ADJCALLSTACKUP : Pseudo<(ops u16imm), "; ADJCALLSTACKUP">; +def ADJCALLSTACKDOWN : Pseudo<(ops u16imm:$amt), "; ADJCALLSTACKDOWN">; +def ADJCALLSTACKUP : Pseudo<(ops u16imm:$amt), "; ADJCALLSTACKUP">; } def IMPLICIT_DEF_GPR : Pseudo<(ops GPRC:$rD), "; $rD = IMPLICIT_DEF_GPRC">; def IMPLICIT_DEF_FP : Pseudo<(ops FPRC:$rD), "; %rD = IMPLICIT_DEF_FP">; @@ -301,7 +301,8 @@ def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label">; let isBranch = 1, isTerminator = 1 in { - def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm, target:$true, target:$false), + def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc, + target:$true, target:$false), "; COND_BRANCH">; def B : IForm<18, 0, 0, (ops target:$func), "b $func">; //def BA : IForm<18, 1, 0, (ops target:$func), "ba $func">; From lattner at cs.uiuc.edu Wed Sep 14 16:10:35 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:10:35 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.td Message-ID: <200509142110.QAA04778@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.td updated: 1.133 -> 1.134 --- Log message: give all operands names --- Diffs of the changes: (+10 -9) X86InstrInfo.td | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) Index: llvm/lib/Target/X86/X86InstrInfo.td diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.133 llvm/lib/Target/X86/X86InstrInfo.td:1.134 --- llvm/lib/Target/X86/X86InstrInfo.td:1.133 Thu Aug 18 19:41:29 2005 +++ llvm/lib/Target/X86/X86InstrInfo.td Wed Sep 14 16:10:24 2005 @@ -145,8 +145,9 @@ def PHI : I<0, Pseudo, (ops variable_ops), "PHINODE">; // PHI node. def NOOP : I<0x90, RawFrm, (ops), "nop">; // nop -def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm), "#ADJCALLSTACKDOWN">; -def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm, i32imm), "#ADJCALLSTACKUP">; +def ADJCALLSTACKDOWN : I<0, Pseudo, (ops i32imm:$amt), "#ADJCALLSTACKDOWN">; +def ADJCALLSTACKUP : I<0, Pseudo, (ops i32imm:$amt1, i32imm:$amt2), + "#ADJCALLSTACKUP">; def IMPLICIT_USE : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_USE">; def IMPLICIT_DEF : I<0, Pseudo, (ops variable_ops), "#IMPLICIT_DEF">; let isTerminator = 1 in @@ -1563,20 +1564,20 @@ // forms of instructions for doing these operations. Until the stackifier runs, // we prefer to be abstract. def FpMOV : FPI<0, Pseudo, SpecialFP, - (ops RFP, RFP), "">; // f1 = fmov f2 + (ops RFP:$dst, RFP:$src), "">; // f1 = fmov f2 def FpADD : FPI<0, Pseudo, TwoArgFP , - (ops RFP, RFP, RFP), "">; // f1 = fadd f2, f3 + (ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fadd f2, f3 def FpSUB : FPI<0, Pseudo, TwoArgFP , - (ops RFP, RFP, RFP), "">; // f1 = fsub f2, f3 + (ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fsub f2, f3 def FpMUL : FPI<0, Pseudo, TwoArgFP , - (ops RFP, RFP, RFP), "">; // f1 = fmul f2, f3 + (ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fmul f2, f3 def FpDIV : FPI<0, Pseudo, TwoArgFP , - (ops RFP, RFP, RFP), "">; // f1 = fdiv f2, f3 + (ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fdiv f2, f3 -def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP), "">, +def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "">, Imp<[ST0], []>; // FPR = ST(0) -def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP), "">, +def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "">, Imp<[], [ST0]>; // ST(0) = FPR // FADD reg, mem: Before stackification, these are represented by: From lattner at cs.uiuc.edu Wed Sep 14 16:11:24 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:11:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64InstrInfo.td Message-ID: <200509142111.QAA04858@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64InstrInfo.td updated: 1.14 -> 1.15 --- Log message: Give all operands names --- Diffs of the changes: (+1 -1) IA64InstrInfo.td | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Target/IA64/IA64InstrInfo.td diff -u llvm/lib/Target/IA64/IA64InstrInfo.td:1.14 llvm/lib/Target/IA64/IA64InstrInfo.td:1.15 --- llvm/lib/Target/IA64/IA64InstrInfo.td:1.14 Thu Aug 18 19:47:42 2005 +++ llvm/lib/Target/IA64/IA64InstrInfo.td Wed Sep 14 16:11:13 2005 @@ -43,7 +43,7 @@ "// ADJUSTCALLSTACKUP">; def ADJUSTCALLSTACKDOWN : PseudoInstIA64<(ops variable_ops), "// ADJUSTCALLSTACKDOWN">; -def PSEUDO_ALLOC : PseudoInstIA64<(ops GR), "// PSEUDO_ALLOC">; +def PSEUDO_ALLOC : PseudoInstIA64<(ops GR:$foo), "// PSEUDO_ALLOC">; def ALLOC : AForm<0x03, 0x0b, (ops GR:$dst, i8imm:$inputs, i8imm:$locals, i8imm:$outputs, i8imm:$rotating), From lattner at cs.uiuc.edu Wed Sep 14 16:14:02 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:14:02 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeGenTarget.cpp DAGISelEmitter.cpp Message-ID: <200509142114.QAA04985@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeGenTarget.cpp updated: 1.38 -> 1.39 DAGISelEmitter.cpp updated: 1.21 -> 1.22 --- Log message: force all instruction operands to be named. --- Diffs of the changes: (+5 -5) CodeGenTarget.cpp | 7 +++++-- DAGISelEmitter.cpp | 3 --- 2 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/utils/TableGen/CodeGenTarget.cpp diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.38 llvm/utils/TableGen/CodeGenTarget.cpp:1.39 --- llvm/utils/TableGen/CodeGenTarget.cpp:1.38 Wed Sep 14 16:05:02 2005 +++ llvm/utils/TableGen/CodeGenTarget.cpp Wed Sep 14 16:13:50 2005 @@ -285,8 +285,11 @@ throw "Unknown operand class '" + Rec->getName() + "' in instruction '" + R->getName() + "' instruction!"; - if (!DI->getArgName(i).empty() && - !OperandNames.insert(DI->getArgName(i)).second) + // Check that the operand has a name and that it's unique. + if (DI->getArgName(i).empty()) + throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + + " has no name!"; + if (!OperandNames.insert(DI->getArgName(i)).second) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + " has the same name as a previous operand!"; Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.21 llvm/utils/TableGen/DAGISelEmitter.cpp:1.22 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.21 Wed Sep 14 16:04:12 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 16:13:50 2005 @@ -788,10 +788,7 @@ if (i == CGI.OperandList.size()) I->error("'" + InstResults.begin()->first + "' set but does not appear in operand list!"); - const std::string &OpName = CGI.OperandList[i].Name; - if (OpName.empty()) - I->error("Operand #" + utostr(i) + " in operands list has no name!"); // Check that it exists in InstResults. Record *R = InstResults[OpName]; From lattner at cs.uiuc.edu Wed Sep 14 16:59:45 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 16:59:45 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509142159.QAA06907@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.22 -> 1.23 --- Log message: check that there are no unexpected operands --- Diffs of the changes: (+11 -3) DAGISelEmitter.cpp | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.22 llvm/utils/TableGen/DAGISelEmitter.cpp:1.23 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.22 Wed Sep 14 16:13:50 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 16:59:34 2005 @@ -803,21 +803,29 @@ InstResults.erase(OpName); } - // Loop over the inputs next. + // Loop over the inputs next. Make a copy of InstInputs so we can destroy + // the copy while we're checking the inputs. + std::map InstInputsCheck(InstInputs); + for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) { const std::string &OpName = CGI.OperandList[i].Name; if (OpName.empty()) I->error("Operand #" + utostr(i) + " in operands list has no name!"); - if (!InstInputs.count(OpName)) + if (!InstInputsCheck.count(OpName)) I->error("Operand $" + OpName + " does not appear in the instruction pattern"); - TreePatternNode *InVal = InstInputs[OpName]; + TreePatternNode *InVal = InstInputsCheck[OpName]; + InstInputsCheck.erase(OpName); if (CGI.OperandList[i].Ty != InVal->getType()) I->error("Operand $" + OpName + "'s type disagrees between the operand and pattern"); } + if (!InstInputsCheck.empty()) + I->error("Input operand $" + InstInputsCheck.begin()->first + + " occurs in pattern but not in operands list!"); + unsigned NumOperands = CGI.OperandList.size()-NumResults; DEBUG(I->dump()); From lattner at cs.uiuc.edu Wed Sep 14 17:06:47 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 17:06:47 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509142206.RAA07048@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.23 -> 1.24 --- Log message: catch unnamed inputs --- Diffs of the changes: (+9 -1) DAGISelEmitter.cpp | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletion(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.23 llvm/utils/TableGen/DAGISelEmitter.cpp:1.24 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.23 Wed Sep 14 16:59:34 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 17:06:36 2005 @@ -631,7 +631,15 @@ static void HandleUse(TreePattern *I, TreePatternNode *Pat, std::map &InstInputs) { // No name -> not interesting. - if (Pat->getName().empty()) return; + if (Pat->getName().empty()) { + if (Pat->isLeaf()) { + DefInit *DI = dynamic_cast(Pat->getLeafValue()); + if (DI && DI->getDef()->isSubClassOf("RegisterClass")) + I->error("Input " + DI->getDef()->getName() + " must be named!"); + + } + return; + } Record *Rec; if (Pat->isLeaf()) { From lattner at cs.uiuc.edu Wed Sep 14 17:55:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 17:55:37 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509142255.RAA07869@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.24 -> 1.25 DAGISelEmitter.h updated: 1.15 -> 1.16 --- Log message: start building the instruction dest pattern correctly. Change the xform functions to preserve the Record for the xform instead of making it into a function name. --- Diffs of the changes: (+27 -15) DAGISelEmitter.cpp | 23 +++++++++++++++-------- DAGISelEmitter.h | 19 ++++++++++++------- 2 files changed, 27 insertions(+), 15 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.24 llvm/utils/TableGen/DAGISelEmitter.cpp:1.25 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.24 Wed Sep 14 17:06:36 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 17:55:26 2005 @@ -203,8 +203,8 @@ if (!PredicateFn.empty()) OS << "<>"; - if (!TransformFn.empty()) - OS << "<>"; + if (TransformFn) + OS << "<getName() << ">>"; if (!getName().empty()) OS << ":$" << getName(); @@ -598,7 +598,7 @@ // it. Record *Transform = Fragments[i]->getValueAsDef("OperandTransform"); if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? - P->getOnlyTree()->setTransformFn("Transform_"+Transform->getName()); + P->getOnlyTree()->setTransformFn(Transform); } OS << "\n\n"; @@ -814,7 +814,8 @@ // Loop over the inputs next. Make a copy of InstInputs so we can destroy // the copy while we're checking the inputs. std::map InstInputsCheck(InstInputs); - + + std::vector ResultNodeOperands; for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) { const std::string &OpName = CGI.OperandList[i].Name; if (OpName.empty()) @@ -824,20 +825,26 @@ I->error("Operand $" + OpName + " does not appear in the instruction pattern"); TreePatternNode *InVal = InstInputsCheck[OpName]; - InstInputsCheck.erase(OpName); + InstInputsCheck.erase(OpName); // It occurred, remove from map. if (CGI.OperandList[i].Ty != InVal->getType()) I->error("Operand $" + OpName + "'s type disagrees between the operand and pattern"); + + ResultNodeOperands.push_back(InVal->clone()); } if (!InstInputsCheck.empty()) I->error("Input operand $" + InstInputsCheck.begin()->first + " occurs in pattern but not in operands list!"); - + + TreePatternNode *ResultPattern = + new TreePatternNode(I->getRecord(), ResultNodeOperands); + unsigned NumOperands = CGI.OperandList.size()-NumResults; DEBUG(I->dump()); - Instructions.push_back(DAGInstruction(I, NumResults, NumOperands)); + Instructions.push_back(DAGInstruction(I, NumResults, NumOperands, + ResultPattern)); } // If we can, convert the instructions to be patterns that are matched! @@ -856,7 +863,7 @@ continue; // Not a set of a single value (not handled so far) TreePatternNode *SrcPattern = Pattern->getChild(1)->clone(); - TreePatternNode *DstPattern = SrcPattern->clone(); // FIXME: WRONG + TreePatternNode *DstPattern = Instructions[i].getResultPattern(); PatternsToMatch.push_back(std::make_pair(SrcPattern, DstPattern)); DEBUG(std::cerr << "PATTERN TO MATCH: "; SrcPattern->dump(); std::cerr << "\nRESULT DAG : "; Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.15 llvm/utils/TableGen/DAGISelEmitter.h:1.16 --- llvm/utils/TableGen/DAGISelEmitter.h:1.15 Wed Sep 14 15:53:42 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Wed Sep 14 17:55:26 2005 @@ -122,14 +122,15 @@ /// TransformFn - The transformation function to execute on this node before /// it can be substituted into the resulting instruction on a pattern match. - std::string TransformFn; + Record *TransformFn; std::vector Children; public: TreePatternNode(Record *Op, const std::vector &Ch) - : Ty(MVT::LAST_VALUETYPE), Operator(Op), Val(0), Children(Ch) {} + : Ty(MVT::LAST_VALUETYPE), Operator(Op), Val(0), TransformFn(0), + Children(Ch) {} TreePatternNode(Init *val) // leaf ctor - : Ty(MVT::LAST_VALUETYPE), Operator(0), Val(val) {} + : Ty(MVT::LAST_VALUETYPE), Operator(0), Val(val), TransformFn(0) {} ~TreePatternNode(); const std::string &getName() const { return Name; } @@ -152,8 +153,8 @@ const std::string &getPredicateFn() const { return PredicateFn; } void setPredicateFn(const std::string &Fn) { PredicateFn = Fn; } - const std::string &getTransformFn() const { return TransformFn; } - void setTransformFn(const std::string &Fn) { TransformFn = Fn; } + Record *getTransformFn() const { return TransformFn; } + void setTransformFn(Record *Fn) { TransformFn = Fn; } void print(std::ostream &OS) const; void dump() const; @@ -278,13 +279,17 @@ TreePattern *Pattern; unsigned NumResults; unsigned NumOperands; + TreePatternNode *ResultPattern; public: - DAGInstruction(TreePattern *TP, unsigned results, unsigned ops) - : Pattern(TP), NumResults(results), NumOperands(ops) {} + DAGInstruction(TreePattern *TP, unsigned results, unsigned ops, + TreePatternNode *resultPattern) + : Pattern(TP), NumResults(results), NumOperands(ops), + ResultPattern(resultPattern) {} TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return NumResults; } unsigned getNumOperands() const { return NumOperands; } + TreePatternNode *getResultPattern() const { return ResultPattern; } }; From lattner at cs.uiuc.edu Wed Sep 14 18:02:10 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 18:02:10 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509142302.SAA08044@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.25 -> 1.26 --- Log message: Promote xform fns to be explicit nodes in result patterns, and clean off predicates since they will have already matched at this point. --- Diffs of the changes: (+15 -1) DAGISelEmitter.cpp | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletion(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.25 llvm/utils/TableGen/DAGISelEmitter.cpp:1.26 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.25 Wed Sep 14 17:55:26 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 18:01:59 2005 @@ -830,7 +830,21 @@ I->error("Operand $" + OpName + "'s type disagrees between the operand and pattern"); - ResultNodeOperands.push_back(InVal->clone()); + // Construct the result for the dest-pattern operand list. + TreePatternNode *OpNode = InVal->clone(); + + // No predicate is useful on the result. + OpNode->setPredicateFn(""); + + // Promote the xform function to be an explicit node if set. + if (Record *Xform = OpNode->getTransformFn()) { + OpNode->setTransformFn(0); + std::vector Children; + Children.push_back(OpNode); + OpNode = new TreePatternNode(Xform, Children); + } + + ResultNodeOperands.push_back(OpNode); } if (!InstInputsCheck.empty()) From lattner at cs.uiuc.edu Wed Sep 14 18:05:24 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 18:05:24 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509142305.SAA08111@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.26 -> 1.27 --- Log message: Verify that xform functions only occur in logical places --- Diffs of the changes: (+14 -5) DAGISelEmitter.cpp | 19 ++++++++++++++----- 1 files changed, 14 insertions(+), 5 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.26 llvm/utils/TableGen/DAGISelEmitter.cpp:1.27 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.26 Wed Sep 14 18:01:59 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 18:05:13 2005 @@ -627,8 +627,8 @@ } /// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an -/// instruction input. -static void HandleUse(TreePattern *I, TreePatternNode *Pat, +/// instruction input. Return true if this is a real use. +static bool HandleUse(TreePattern *I, TreePatternNode *Pat, std::map &InstInputs) { // No name -> not interesting. if (Pat->getName().empty()) { @@ -638,7 +638,7 @@ I->error("Input " + DI->getDef()->getName() + " must be named!"); } - return; + return false; } Record *Rec; @@ -669,6 +669,7 @@ if (Slot->getType() != Pat->getType()) I->error("All $" + Pat->getName() + " inputs must agree with each other"); } + return true; } /// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is @@ -679,7 +680,9 @@ std::map &InstInputs, std::map &InstResults) { if (Pat->isLeaf()) { - HandleUse(I, Pat, InstInputs); + bool isUse = HandleUse(I, Pat, InstInputs); + if (!isUse && Pat->getTransformFn()) + I->error("Cannot specify a transform function for a non-input value!"); return; } else if (Pat->getOperator()->getName() != "set") { // If this is not a set, verify that the children nodes are not void typed, @@ -692,9 +695,12 @@ // If this is a non-leaf node with no children, treat it basically as if // it were a leaf. This handles nodes like (imm). + bool isUse = false; if (Pat->getNumChildren() == 0) - HandleUse(I, Pat, InstInputs); + isUse = HandleUse(I, Pat, InstInputs); + if (!isUse && Pat->getTransformFn()) + I->error("Cannot specify a transform function for a non-input value!"); return; } @@ -704,6 +710,9 @@ else if (Pat->getNumChildren() & 1) I->error("set requires an even number of operands"); + if (Pat->getTransformFn()) + I->error("Cannot specify a transform function on a set node!"); + // Check the set destinations. unsigned NumValues = Pat->getNumChildren()/2; for (unsigned i = 0; i != NumValues; ++i) { From lattner at cs.uiuc.edu Wed Sep 14 21:38:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 14 Sep 2005 21:38:14 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509150238.VAA18047@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.27 -> 1.28 DAGISelEmitter.h updated: 1.16 -> 1.17 --- Log message: rename a couple of methods, add structure for pattern parsing --- Diffs of the changes: (+29 -17) DAGISelEmitter.cpp | 41 ++++++++++++++++++++++++++--------------- DAGISelEmitter.h | 5 +++-- 2 files changed, 29 insertions(+), 17 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.27 llvm/utils/TableGen/DAGISelEmitter.cpp:1.28 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.27 Wed Sep 14 18:05:13 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Wed Sep 14 21:38:02 2005 @@ -527,14 +527,14 @@ -/// ParseAndResolvePatternFragments - Parse all of the PatFrag definitions in -/// the .td file, building up the PatternFragments map. After we've collected -/// them all, inline fragments together as necessary, so that there are no -/// references left inside a pattern fragment to a pattern fragment. +/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td +/// file, building up the PatternFragments map. After we've collected them all, +/// inline fragments together as necessary, so that there are no references left +/// inside a pattern fragment to a pattern fragment. /// /// This also emits all of the predicate functions to the output file. /// -void DAGISelEmitter::ParseAndResolvePatternFragments(std::ostream &OS) { +void DAGISelEmitter::ParsePatternFragments(std::ostream &OS) { std::vector Fragments = Records.getAllDerivedDefinitions("PatFrag"); // First step, parse all of the fragments and emit predicate functions. @@ -739,10 +739,10 @@ } -/// ParseAndResolveInstructions - Parse all of the instructions, inlining and -/// resolving any fragments involved. This populates the Instructions list with -/// fully resolved instructions. -void DAGISelEmitter::ParseAndResolveInstructions() { +/// ParseInstructions - Parse all of the instructions, inlining and resolving +/// any fragments involved. This populates the Instructions list with fully +/// resolved instructions. +void DAGISelEmitter::ParseInstructions() { std::vector Instrs = Records.getAllDerivedDefinitions("Instruction"); for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { @@ -888,12 +888,22 @@ TreePatternNode *SrcPattern = Pattern->getChild(1)->clone(); TreePatternNode *DstPattern = Instructions[i].getResultPattern(); PatternsToMatch.push_back(std::make_pair(SrcPattern, DstPattern)); - DEBUG(std::cerr << "PATTERN TO MATCH: "; SrcPattern->dump(); - std::cerr << "\nRESULT DAG : "; - DstPattern->dump(); std::cerr << "\n"); } } +void DAGISelEmitter::ParsePatterns() { + + + + + DEBUG(std::cerr << "\n\nPARSED PATTERNS TO MATCH:\n\n"; + for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) { + std::cerr << "PATTERN: "; PatternsToMatch[i].first->dump(); + std::cerr << "\nRESULT: ";PatternsToMatch[i].second->dump(); + std::cerr << "\n"; + }); +} + void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) { // Emit boilerplate. OS << "// The main instruction selector code.\n" @@ -929,9 +939,10 @@ << "methods.\n\n"; ParseNodeInfo(); ParseNodeTransforms(OS); - ParseAndResolvePatternFragments(OS); - ParseAndResolveInstructions(); - + ParsePatternFragments(OS); + ParseInstructions(); + ParsePatterns(); + // TODO: convert some instructions to expanders if needed or something. EmitInstructionSelector(OS); Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.16 llvm/utils/TableGen/DAGISelEmitter.h:1.17 --- llvm/utils/TableGen/DAGISelEmitter.h:1.16 Wed Sep 14 17:55:26 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Wed Sep 14 21:38:02 2005 @@ -333,8 +333,9 @@ private: void ParseNodeInfo(); void ParseNodeTransforms(std::ostream &OS); - void ParseAndResolvePatternFragments(std::ostream &OS); - void ParseAndResolveInstructions(); + void ParsePatternFragments(std::ostream &OS); + void ParseInstructions(); + void ParsePatterns(); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, std::map &InstInputs, From lattner at cs.uiuc.edu Thu Sep 15 16:42:11 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 16:42:11 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509152142.QAA05160@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.28 -> 1.29 --- Log message: Start parsing "Pattern" nodes --- Diffs of the changes: (+52 -11) DAGISelEmitter.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 52 insertions(+), 11 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.28 llvm/utils/TableGen/DAGISelEmitter.cpp:1.29 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.28 Wed Sep 14 21:38:02 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Thu Sep 15 16:42:00 2005 @@ -317,14 +317,18 @@ MadeChange |= getChild(1)->UpdateNodeType(getChild(0)->getType(), TP); MadeChange |= UpdateNodeType(MVT::isVoid, TP); return MadeChange; + } else if (getOperator()->isSubClassOf("SDNode")) { + const SDNodeInfo &NI = TP.getDAGISelEmitter().getSDNodeInfo(getOperator()); + + bool MadeChange = NI.ApplyTypeConstraints(this, TP); + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP); + return MadeChange; + } else { + assert(getOperator()->isSubClassOf("Instruction") && "Unknown node type!"); + // TODO: type inference for instructions. + return false; } - - const SDNodeInfo &NI = TP.getDAGISelEmitter().getSDNodeInfo(getOperator()); - - bool MadeChange = NI.ApplyTypeConstraints(this, TP); - for (unsigned i = 0, e = getNumChildren(); i != e; ++i) - MadeChange |= getChild(i)->ApplyTypeConstraints(TP); - return MadeChange; } @@ -400,6 +404,8 @@ // Verify that this is something that makes sense for an operator. if (!Operator->isSubClassOf("PatFrag") && !Operator->isSubClassOf("SDNode") && + !Operator->isSubClassOf("Instruction") && + !Operator->isSubClassOf("SDNodeXForm") && Operator->getName() != "set") error("Unrecognized node '" + Operator->getName() + "'!"); @@ -763,10 +769,8 @@ // Infer as many types as possible. If we cannot infer all of them, we can // never do anything with this instruction pattern: report it to the user. - if (!I->InferAllTypes()) { - I->dump(); + if (!I->InferAllTypes()) I->error("Could not infer all types in pattern!"); - } // InstInputs - Keep track of all of the inputs of the instruction, along // with the record they are declared as. @@ -892,9 +896,46 @@ } void DAGISelEmitter::ParsePatterns() { + std::vector Patterns = Records.getAllDerivedDefinitions("Pattern"); + for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { + std::vector Trees; + Trees.push_back(Patterns[i]->getValueAsDag("PatternToMatch")); + TreePattern *Pattern = new TreePattern(Patterns[i], Trees, *this); + Trees.clear(); - + // Inline pattern fragments into it. + Pattern->InlinePatternFragments(); + + // Infer as many types as possible. If we cannot infer all of them, we can + // never do anything with this pattern: report it to the user. + if (!Pattern->InferAllTypes()) + Pattern->error("Could not infer all types in pattern!"); + + ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs"); + if (LI->getSize() == 0) continue; // no pattern. + for (unsigned j = 0, e = LI->getSize(); j != e; ++j) + Trees.push_back((DagInit*)LI->getElement(j)); + + // Parse the instruction. + TreePattern *Result = new TreePattern(Patterns[i], Trees, *this); + + // Inline pattern fragments into it. + Result->InlinePatternFragments(); + + // Infer as many types as possible. If we cannot infer all of them, we can + // never do anything with this pattern: report it to the user. +#if 0 // FIXME: ENABLE when we can infer though instructions! + if (!Result->InferAllTypes()) + Result->error("Could not infer all types in pattern!"); +#endif + + if (Result->getNumTrees() != 1) + Result->error("Cannot handle instructions producing instructions " + "with temporaries yet!"); + PatternsToMatch.push_back(std::make_pair(Pattern->getOnlyTree(), + Result->getOnlyTree())); + } DEBUG(std::cerr << "\n\nPARSED PATTERNS TO MATCH:\n\n"; for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) { From lattner at cs.uiuc.edu Thu Sep 15 16:44:12 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 16:44:12 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Message-ID: <200509152144.QAA05224@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PowerPCInstrInfo.td updated: 1.100 -> 1.101 --- Log message: disable this for now --- Diffs of the changes: (+2 -0) PowerPCInstrInfo.td | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/Target/PowerPC/PowerPCInstrInfo.td diff -u llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.100 llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.101 --- llvm/lib/Target/PowerPC/PowerPCInstrInfo.td:1.100 Wed Sep 14 16:08:18 2005 +++ llvm/lib/Target/PowerPC/PowerPCInstrInfo.td Thu Sep 15 16:44:00 2005 @@ -775,9 +775,11 @@ (XORIS (XORI GPRC:$in, (LO16 imm:$imm)), (HI16 imm:$imm))>; // Same as above, but using a temporary. +/* def : Pattern<(xor GPRC:$in, imm:$imm), [(set GPRC:$tmp, (XORI GPRC:$in, (LO16 imm:$imm))), (XORIS GPRC:$tmp, (HI16 imm:$imm))]>; +*/ //===----------------------------------------------------------------------===// From lattner at cs.uiuc.edu Thu Sep 15 16:51:25 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 16:51:25 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509152151.QAA05300@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.29 -> 1.30 DAGISelEmitter.h updated: 1.17 -> 1.18 --- Log message: when parsing instructions remember information about the types taken and returned. --- Diffs of the changes: (+25 -7) DAGISelEmitter.cpp | 10 +++++++--- DAGISelEmitter.h | 22 ++++++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.29 llvm/utils/TableGen/DAGISelEmitter.cpp:1.30 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.29 Thu Sep 15 16:42:00 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Thu Sep 15 16:51:12 2005 @@ -805,6 +805,7 @@ CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]->getName()); // Check that all of the results occur first in the list. + std::vector ResultTypes; for (unsigned i = 0; i != NumResults; ++i) { if (i == CGI.OperandList.size()) I->error("'" + InstResults.begin()->first + @@ -820,6 +821,9 @@ if (CGI.OperandList[i].Rec != R) I->error("Operand $" + OpName + " class mismatch!"); + // Remember the return type. + ResultTypes.push_back(CGI.OperandList[i].Ty); + // Okay, this one checks out. InstResults.erase(OpName); } @@ -829,6 +833,7 @@ std::map InstInputsCheck(InstInputs); std::vector ResultNodeOperands; + std::vector OperandTypes; for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) { const std::string &OpName = CGI.OperandList[i].Name; if (OpName.empty()) @@ -842,6 +847,7 @@ if (CGI.OperandList[i].Ty != InVal->getType()) I->error("Operand $" + OpName + "'s type disagrees between the operand and pattern"); + OperandTypes.push_back(InVal->getType()); // Construct the result for the dest-pattern operand list. TreePatternNode *OpNode = InVal->clone(); @@ -867,10 +873,8 @@ TreePatternNode *ResultPattern = new TreePatternNode(I->getRecord(), ResultNodeOperands); - unsigned NumOperands = CGI.OperandList.size()-NumResults; - DEBUG(I->dump()); - Instructions.push_back(DAGInstruction(I, NumResults, NumOperands, + Instructions.push_back(DAGInstruction(I, ResultTypes, OperandTypes, ResultPattern)); } Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.17 llvm/utils/TableGen/DAGISelEmitter.h:1.18 --- llvm/utils/TableGen/DAGISelEmitter.h:1.17 Wed Sep 14 21:38:02 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Thu Sep 15 16:51:12 2005 @@ -279,16 +279,30 @@ TreePattern *Pattern; unsigned NumResults; unsigned NumOperands; + std::vector ResultTypes; + std::vector OperandTypes; TreePatternNode *ResultPattern; public: - DAGInstruction(TreePattern *TP, unsigned results, unsigned ops, + DAGInstruction(TreePattern *TP, + const std::vector &resultTypes, + const std::vector &operandTypes, TreePatternNode *resultPattern) - : Pattern(TP), NumResults(results), NumOperands(ops), + : Pattern(TP), ResultTypes(resultTypes), OperandTypes(operandTypes), ResultPattern(resultPattern) {} TreePattern *getPattern() const { return Pattern; } - unsigned getNumResults() const { return NumResults; } - unsigned getNumOperands() const { return NumOperands; } + unsigned getNumResults() const { return ResultTypes.size(); } + unsigned getNumOperands() const { return OperandTypes.size(); } + + MVT::ValueType getResultType(unsigned RN) const { + assert(RN < ResultTypes.size()); + return ResultTypes[RN]; + } + + MVT::ValueType getOperandType(unsigned ON) const { + assert(ON < OperandTypes.size()); + return OperandTypes[ON]; + } TreePatternNode *getResultPattern() const { return ResultPattern; } }; From lattner at cs.uiuc.edu Thu Sep 15 16:57:47 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 16:57:47 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509152157.QAA05396@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.30 -> 1.31 DAGISelEmitter.h updated: 1.18 -> 1.19 --- Log message: put instructions into a map instead of a vector for quick lookup --- Diffs of the changes: (+18 -7) DAGISelEmitter.cpp | 18 ++++++++++++------ DAGISelEmitter.h | 7 ++++++- 2 files changed, 18 insertions(+), 7 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.30 llvm/utils/TableGen/DAGISelEmitter.cpp:1.31 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.30 Thu Sep 15 16:51:12 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Thu Sep 15 16:57:35 2005 @@ -326,6 +326,10 @@ return MadeChange; } else { assert(getOperator()->isSubClassOf("Instruction") && "Unknown node type!"); + + const DAGInstruction &Inst = + TP.getDAGISelEmitter().getInstruction(getOperator()); + // TODO: type inference for instructions. return false; } @@ -874,13 +878,15 @@ new TreePatternNode(I->getRecord(), ResultNodeOperands); DEBUG(I->dump()); - Instructions.push_back(DAGInstruction(I, ResultTypes, OperandTypes, - ResultPattern)); + Instructions.insert(std::make_pair(I->getRecord(), + DAGInstruction(I, ResultTypes, + OperandTypes, ResultPattern))); } // If we can, convert the instructions to be patterns that are matched! - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { - TreePattern *I = Instructions[i].getPattern(); + for (std::map::iterator II = Instructions.begin(), + E = Instructions.end(); II != E; ++II) { + TreePattern *I = II->second.getPattern(); if (I->getNumTrees() != 1) { std::cerr << "CANNOT HANDLE: " << I->getRecord()->getName() << " yet!"; @@ -894,7 +900,7 @@ continue; // Not a set of a single value (not handled so far) TreePatternNode *SrcPattern = Pattern->getChild(1)->clone(); - TreePatternNode *DstPattern = Instructions[i].getResultPattern(); + TreePatternNode *DstPattern = II->second.getResultPattern(); PatternsToMatch.push_back(std::make_pair(SrcPattern, DstPattern)); } } @@ -931,7 +937,7 @@ // never do anything with this pattern: report it to the user. #if 0 // FIXME: ENABLE when we can infer though instructions! if (!Result->InferAllTypes()) - Result->error("Could not infer all types in pattern!"); + Result->error("Could not infer all types in pattern result!"); #endif if (Result->getNumTrees() != 1) Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.18 llvm/utils/TableGen/DAGISelEmitter.h:1.19 --- llvm/utils/TableGen/DAGISelEmitter.h:1.18 Thu Sep 15 16:51:12 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Thu Sep 15 16:57:35 2005 @@ -317,7 +317,7 @@ std::map SDNodes; std::map > SDNodeXForms; std::map PatternFragments; - std::vector Instructions; + std::map Instructions; /// PatternsToMatch - All of the things we are matching on the DAG. The first /// value is the pattern to match, the second pattern is the result to @@ -344,6 +344,11 @@ return SDNodeXForms.find(R)->second; } + const DAGInstruction &getInstruction(Record *R) const { + assert(Instructions.count(R) && "Unknown instruction!"); + return Instructions.find(R)->second; + } + private: void ParseNodeInfo(); void ParseNodeTransforms(std::ostream &OS); From lattner at cs.uiuc.edu Thu Sep 15 17:24:01 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 17:24:01 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h Message-ID: <200509152224.RAA05558@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.31 -> 1.32 DAGISelEmitter.h updated: 1.19 -> 1.20 --- Log message: teach the type inference code how to infer types for instructions and node xforms. Run type inference on result patterns, so we always have fully typed results (and to catch errors in .td files). --- Diffs of the changes: (+66 -33) DAGISelEmitter.cpp | 86 +++++++++++++++++++++++++++++++++++------------------ DAGISelEmitter.h | 13 ++++---- 2 files changed, 66 insertions(+), 33 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.31 llvm/utils/TableGen/DAGISelEmitter.cpp:1.32 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.31 Thu Sep 15 16:57:35 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Thu Sep 15 17:23:50 2005 @@ -324,14 +324,34 @@ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP); return MadeChange; - } else { - assert(getOperator()->isSubClassOf("Instruction") && "Unknown node type!"); - + } else if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = TP.getDAGISelEmitter().getInstruction(getOperator()); - // TODO: type inference for instructions. - return false; + assert(Inst.getNumResults() == 1 && "Only supports one result instrs!"); + // Apply the result type to the node + bool MadeChange = UpdateNodeType(Inst.getResultType(0), TP); + + if (getNumChildren() != Inst.getNumOperands()) + TP.error("Instruction '" + getOperator()->getName() + " expects " + + utostr(Inst.getNumOperands()) + " operands, not " + + utostr(getNumChildren()) + " operands!"); + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { + MadeChange |= getChild(i)->UpdateNodeType(Inst.getOperandType(i), TP); + MadeChange |= getChild(i)->ApplyTypeConstraints(TP); + } + return MadeChange; + } else { + assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); + + // Node transforms always take one operand, and take and return the same + // type. + if (getNumChildren() != 1) + TP.error("Node transform '" + getOperator()->getName() + + "' requires one operand!"); + bool MadeChange = UpdateNodeType(getChild(0)->getType(), TP); + MadeChange |= getChild(0)->UpdateNodeType(getType(), TP); + return MadeChange; } } @@ -340,13 +360,24 @@ // TreePattern implementation // -TreePattern::TreePattern(Record *TheRec, const std::vector &RawPat, +TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, + DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) + Trees.push_back(ParseTreePattern((DagInit*)RawPat->getElement(i))); +} + +TreePattern::TreePattern(Record *TheRec, DagInit *Pat, DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + Trees.push_back(ParseTreePattern(Pat)); +} - for (unsigned i = 0, e = RawPat.size(); i != e; ++i) - Trees.push_back(ParseTreePattern(RawPat[i])); +TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, + DAGISelEmitter &ise) : TheRecord(TheRec), ISE(ise) { + Trees.push_back(Pat); } + + void TreePattern::error(const std::string &Msg) const { dump(); throw "In " + TheRecord->getName() + ": " + Msg; @@ -550,9 +581,8 @@ // First step, parse all of the fragments and emit predicate functions. OS << "\n// Predicate functions.\n"; for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { - std::vector Trees; - Trees.push_back(Fragments[i]->getValueAsDag("Fragment")); - TreePattern *P = new TreePattern(Fragments[i], Trees, *this); + DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); + TreePattern *P = new TreePattern(Fragments[i], Tree, *this); PatternFragments[Fragments[i]] = P; // Validate the argument list, converting it to map, to discard duplicates. @@ -762,12 +792,8 @@ ListInit *LI = Instrs[i]->getValueAsListInit("Pattern"); if (LI->getSize() == 0) continue; // no pattern. - std::vector Trees; - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) - Trees.push_back((DagInit*)LI->getElement(j)); - // Parse the instruction. - TreePattern *I = new TreePattern(Instrs[i], Trees, *this); + TreePattern *I = new TreePattern(Instrs[i], LI, *this); // Inline pattern fragments into it. I->InlinePatternFragments(); @@ -876,11 +902,21 @@ TreePatternNode *ResultPattern = new TreePatternNode(I->getRecord(), ResultNodeOperands); + + // Create and insert the instruction. + DAGInstruction TheInst(I, ResultTypes, OperandTypes); + Instructions.insert(std::make_pair(I->getRecord(), TheInst)); + + // Use a temporary tree pattern to infer all types and make sure that the + // constructed result is correct. This depends on the instruction already + // being inserted into the Instructions map. + TreePattern Temp(I->getRecord(), ResultPattern, *this); + Temp.InferAllTypes(); + + DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second; + TheInsertedInst.setResultPattern(Temp.getOnlyTree()); DEBUG(I->dump()); - Instructions.insert(std::make_pair(I->getRecord(), - DAGInstruction(I, ResultTypes, - OperandTypes, ResultPattern))); } // If we can, convert the instructions to be patterns that are matched! @@ -909,10 +945,8 @@ std::vector Patterns = Records.getAllDerivedDefinitions("Pattern"); for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - std::vector Trees; - Trees.push_back(Patterns[i]->getValueAsDag("PatternToMatch")); - TreePattern *Pattern = new TreePattern(Patterns[i], Trees, *this); - Trees.clear(); + DagInit *Tree = Patterns[i]->getValueAsDag("PatternToMatch"); + TreePattern *Pattern = new TreePattern(Patterns[i], Tree, *this); // Inline pattern fragments into it. Pattern->InlinePatternFragments(); @@ -924,21 +958,17 @@ ListInit *LI = Patterns[i]->getValueAsListInit("ResultInstrs"); if (LI->getSize() == 0) continue; // no pattern. - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) - Trees.push_back((DagInit*)LI->getElement(j)); // Parse the instruction. - TreePattern *Result = new TreePattern(Patterns[i], Trees, *this); + TreePattern *Result = new TreePattern(Patterns[i], LI, *this); // Inline pattern fragments into it. Result->InlinePatternFragments(); // Infer as many types as possible. If we cannot infer all of them, we can // never do anything with this pattern: report it to the user. -#if 0 // FIXME: ENABLE when we can infer though instructions! if (!Result->InferAllTypes()) Result->error("Could not infer all types in pattern result!"); -#endif if (Result->getNumTrees() != 1) Result->error("Cannot handle instructions producing instructions " Index: llvm/utils/TableGen/DAGISelEmitter.h diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.19 llvm/utils/TableGen/DAGISelEmitter.h:1.20 --- llvm/utils/TableGen/DAGISelEmitter.h:1.19 Thu Sep 15 16:57:35 2005 +++ llvm/utils/TableGen/DAGISelEmitter.h Thu Sep 15 17:23:50 2005 @@ -20,6 +20,7 @@ namespace llvm { class Record; struct Init; + class ListInit; class DagInit; class SDNodeInfo; class TreePattern; @@ -222,8 +223,9 @@ /// TreePattern constructor - Parse the specified DagInits into the /// current record. - TreePattern(Record *TheRec, - const std::vector &RawPat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, ListInit *RawPat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, DagInit *Pat, DAGISelEmitter &ise); + TreePattern(Record *TheRec, TreePatternNode *Pat, DAGISelEmitter &ise); /// getTrees - Return the tree patterns which corresponds to this pattern. /// @@ -285,15 +287,16 @@ public: DAGInstruction(TreePattern *TP, const std::vector &resultTypes, - const std::vector &operandTypes, - TreePatternNode *resultPattern) + const std::vector &operandTypes) : Pattern(TP), ResultTypes(resultTypes), OperandTypes(operandTypes), - ResultPattern(resultPattern) {} + ResultPattern(0) {} TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return ResultTypes.size(); } unsigned getNumOperands() const { return OperandTypes.size(); } + void setResultPattern(TreePatternNode *R) { ResultPattern = R; } + MVT::ValueType getResultType(unsigned RN) const { assert(RN < ResultTypes.size()); return ResultTypes[RN]; From lattner at cs.uiuc.edu Thu Sep 15 19:29:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 19:29:57 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp Message-ID: <200509160029.TAA19597@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: DAGISelEmitter.cpp updated: 1.32 -> 1.33 --- Log message: Fix a minor bug, add comments --- Diffs of the changes: (+5 -2) DAGISelEmitter.cpp | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) Index: llvm/utils/TableGen/DAGISelEmitter.cpp diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.32 llvm/utils/TableGen/DAGISelEmitter.cpp:1.33 --- llvm/utils/TableGen/DAGISelEmitter.cpp:1.32 Thu Sep 15 17:23:50 2005 +++ llvm/utils/TableGen/DAGISelEmitter.cpp Thu Sep 15 19:29:46 2005 @@ -697,7 +697,7 @@ } else { Record *SlotRec; if (Slot->isLeaf()) { - Rec = dynamic_cast(Slot->getLeafValue())->getDef(); + SlotRec = dynamic_cast(Slot->getLeafValue())->getDef(); } else { assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); SlotRec = Slot->getOperator(); @@ -1018,13 +1018,16 @@ OS << "// *** NOTE: This file is #included into the middle of the target\n" << "// *** instruction selector class. These functions are really " << "methods.\n\n"; + ParseNodeInfo(); ParseNodeTransforms(OS); ParsePatternFragments(OS); ParseInstructions(); ParsePatterns(); - // TODO: convert some instructions to expanders if needed or something. + // At this point, we have full information about the 'Patterns' we need to + // parse, both implicitly from instructions as well as from explicit pattern + // definitions. EmitInstructionSelector(OS); From natebegeman at mac.com Thu Sep 15 19:54:23 2005 From: natebegeman at mac.com (Nate Begeman) Date: Thu, 15 Sep 2005 19:54:23 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200509160054.TAA21891@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.11 -> 1.12 --- Log message: More DAG combining. Still need the branch instructions, and select_cc --- Diffs of the changes: (+425 -5) DAGCombiner.cpp | 430 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 425 insertions(+), 5 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.11 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.12 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.11 Fri Sep 9 18:53:39 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Sep 15 19:54:12 2005 @@ -100,9 +100,9 @@ SDOperand visitCTLZ(SDNode *N); SDOperand visitCTTZ(SDNode *N); SDOperand visitCTPOP(SDNode *N); - // select - // select_cc - // setcc + SDOperand visitSELECT(SDNode *N); + SDOperand visitSELECT_CC(SDNode *N); + SDOperand visitSETCC(SDNode *N); SDOperand visitSIGN_EXTEND(SDNode *N); SDOperand visitZERO_EXTEND(SDNode *N); SDOperand visitSIGN_EXTEND_INREG(SDNode *N); @@ -116,10 +116,13 @@ SDOperand visitFP_EXTEND(SDNode *N); SDOperand visitFNEG(SDNode *N); SDOperand visitFABS(SDNode *N); - // brcond + SDOperand visitBRCOND(SDNode *N); // brcondtwoway // br_cc // brtwoway_cc + + SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1, + ISD::CondCode Cond); public: DAGCombiner(SelectionDAG &D) : DAG(D), TLI(D.getTargetLoweringInfo()), AfterLegalize(false) {} @@ -234,6 +237,19 @@ return false; } +// FIXME: This should probably go in the ISD class rather than being duplicated +// in several files. +static bool isCommutativeBinOp(unsigned Opcode) { + switch (Opcode) { + case ISD::ADD: + case ISD::MUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: return true; + default: return false; // FIXME: Need commutative info for user ops! + } +} + void DAGCombiner::Run(bool RunningAfterLegalize) { // set the instance variable, so that the various visit routines may use it. AfterLegalize = RunningAfterLegalize; @@ -307,6 +323,9 @@ case ISD::CTLZ: return visitCTLZ(N); case ISD::CTTZ: return visitCTTZ(N); case ISD::CTPOP: return visitCTPOP(N); + case ISD::SELECT: return visitSELECT(N); + case ISD::SELECT_CC: return visitSELECT_CC(N); + case ISD::SETCC: return visitSETCC(N); case ISD::SIGN_EXTEND: return visitSIGN_EXTEND(N); case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N); case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); @@ -669,6 +688,15 @@ WorkList.push_back(ANDNode.Val); return DAG.getNode(ISD::ZERO_EXTEND, VT, ANDNode); } + // fold (and (shl/srl x), (shl/srl y)) -> (shl/srl (and x, y)) + if (((N0.getOpcode() == ISD::SHL && N1.getOpcode() == ISD::SHL) || + (N0.getOpcode() == ISD::SRL && N1.getOpcode() == ISD::SRL)) && + N0.getOperand(1) == N1.getOperand(1)) { + SDOperand ANDNode = DAG.getNode(ISD::AND, N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + WorkList.push_back(ANDNode.Val); + return DAG.getNode(N0.getOpcode(), VT, ANDNode, N0.getOperand(1)); + } return SDOperand(); } @@ -993,6 +1021,63 @@ return SDOperand(); } +SDOperand DAGCombiner::visitSELECT(SDNode *N) { + SDOperand N0 = N->getOperand(0); + SDOperand N1 = N->getOperand(1); + SDOperand N2 = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + ConstantSDNode *N2C = dyn_cast(N2); + MVT::ValueType VT = N->getValueType(0); + + // fold select C, X, X -> X + if (N1 == N2) + return N1; + // fold select true, X, Y -> X + if (N0C && !N0C->isNullValue()) + return N1; + // fold select false, X, Y -> Y + if (N0C && N0C->isNullValue()) + return N2; + // fold select C, 1, X -> C | X + if (MVT::i1 == VT && N1C && !N1C->isNullValue()) + return DAG.getNode(ISD::OR, VT, N0, N2); + // fold select C, 0, X -> ~C & X + // FIXME: this should check for C type == X type, not i1? + if (MVT::i1 == VT && N1C && N1C->isNullValue()) { + SDOperand XORNode = DAG.getNode(ISD::XOR, VT, N0, DAG.getConstant(1, VT)); + WorkList.push_back(XORNode.Val); + return DAG.getNode(ISD::AND, VT, XORNode, N2); + } + // fold select C, X, 1 -> ~C | X + if (MVT::i1 == VT && N2C && !N2C->isNullValue()) { + SDOperand XORNode = DAG.getNode(ISD::XOR, VT, N0, DAG.getConstant(1, VT)); + WorkList.push_back(XORNode.Val); + return DAG.getNode(ISD::OR, VT, XORNode, N1); + } + // fold select C, X, 0 -> C & X + // FIXME: this should check for C type == X type, not i1? + if (MVT::i1 == VT && N2C && N2C->isNullValue()) + return DAG.getNode(ISD::AND, VT, N0, N1); + // fold X ? X : Y --> X ? 1 : Y --> X | Y + if (MVT::i1 == VT && N0 == N1) + return DAG.getNode(ISD::OR, VT, N0, N2); + // fold X ? Y : X --> X ? Y : 0 --> X & Y + if (MVT::i1 == VT && N0 == N2) + return DAG.getNode(ISD::AND, VT, N0, N1); + + return SDOperand(); +} + +SDOperand DAGCombiner::visitSELECT_CC(SDNode *N) { + return SDOperand(); +} + +SDOperand DAGCombiner::visitSETCC(SDNode *N) { + return SimplifySetCC(N->getValueType(0), N->getOperand(0), N->getOperand(1), + cast(N->getOperand(2))->get()); +} + SDOperand DAGCombiner::visitSIGN_EXTEND(SDNode *N) { SDOperand N0 = N->getOperand(0); ConstantSDNode *N0C = dyn_cast(N0); @@ -1024,7 +1109,6 @@ SDOperand DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { SDOperand N0 = N->getOperand(0); SDOperand N1 = N->getOperand(1); - SDOperand LHS, RHS, CC; ConstantSDNode *N0C = dyn_cast(N0); MVT::ValueType VT = N->getValueType(0); MVT::ValueType EVT = cast(N1)->getVT(); @@ -1206,6 +1290,342 @@ return SDOperand(); } +SDOperand DAGCombiner::SimplifySetCC(MVT::ValueType VT, SDOperand N0, + SDOperand N1, ISD::CondCode Cond) { + // These setcc operations always fold. + switch (Cond) { + default: break; + case ISD::SETFALSE: + case ISD::SETFALSE2: return DAG.getConstant(0, VT); + case ISD::SETTRUE: + case ISD::SETTRUE2: return DAG.getConstant(1, VT); + } + + if (ConstantSDNode *N1C = dyn_cast(N1.Val)) { + uint64_t C1 = N1C->getValue(); + if (ConstantSDNode *N0C = dyn_cast(N0.Val)) { + uint64_t C0 = N0C->getValue(); + + // Sign extend the operands if required + if (ISD::isSignedIntSetCC(Cond)) { + C0 = N0C->getSignExtended(); + C1 = N1C->getSignExtended(); + } + + switch (Cond) { + default: assert(0 && "Unknown integer setcc!"); + case ISD::SETEQ: return DAG.getConstant(C0 == C1, VT); + case ISD::SETNE: return DAG.getConstant(C0 != C1, VT); + case ISD::SETULT: return DAG.getConstant(C0 < C1, VT); + case ISD::SETUGT: return DAG.getConstant(C0 > C1, VT); + case ISD::SETULE: return DAG.getConstant(C0 <= C1, VT); + case ISD::SETUGE: return DAG.getConstant(C0 >= C1, VT); + case ISD::SETLT: return DAG.getConstant((int64_t)C0 < (int64_t)C1, VT); + case ISD::SETGT: return DAG.getConstant((int64_t)C0 > (int64_t)C1, VT); + case ISD::SETLE: return DAG.getConstant((int64_t)C0 <= (int64_t)C1, VT); + case ISD::SETGE: return DAG.getConstant((int64_t)C0 >= (int64_t)C1, VT); + } + } else { + // If the LHS is a ZERO_EXTEND, perform the comparison on the input. + if (N0.getOpcode() == ISD::ZERO_EXTEND) { + unsigned InSize = MVT::getSizeInBits(N0.getOperand(0).getValueType()); + + // If the comparison constant has bits in the upper part, the + // zero-extended value could never match. + if (C1 & (~0ULL << InSize)) { + unsigned VSize = MVT::getSizeInBits(N0.getValueType()); + switch (Cond) { + case ISD::SETUGT: + case ISD::SETUGE: + case ISD::SETEQ: return DAG.getConstant(0, VT); + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETNE: return DAG.getConstant(1, VT); + case ISD::SETGT: + case ISD::SETGE: + // True if the sign bit of C1 is set. + return DAG.getConstant((C1 & (1ULL << VSize)) != 0, VT); + case ISD::SETLT: + case ISD::SETLE: + // True if the sign bit of C1 isn't set. + return DAG.getConstant((C1 & (1ULL << VSize)) == 0, VT); + default: + break; + } + } + + // Otherwise, we can perform the comparison with the low bits. + switch (Cond) { + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGT: + case ISD::SETUGE: + case ISD::SETULT: + case ISD::SETULE: + return DAG.getSetCC(VT, N0.getOperand(0), + DAG.getConstant(C1, N0.getOperand(0).getValueType()), + Cond); + default: + break; // todo, be more careful with signed comparisons + } + } else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + MVT::ValueType ExtSrcTy = cast(N0.getOperand(1))->getVT(); + unsigned ExtSrcTyBits = MVT::getSizeInBits(ExtSrcTy); + MVT::ValueType ExtDstTy = N0.getValueType(); + unsigned ExtDstTyBits = MVT::getSizeInBits(ExtDstTy); + + // If the extended part has any inconsistent bits, it cannot ever + // compare equal. In other words, they have to be all ones or all + // zeros. + uint64_t ExtBits = + (~0ULL >> (64-ExtSrcTyBits)) & (~0ULL << (ExtDstTyBits-1)); + if ((C1 & ExtBits) != 0 && (C1 & ExtBits) != ExtBits) + return DAG.getConstant(Cond == ISD::SETNE, VT); + + SDOperand ZextOp; + MVT::ValueType Op0Ty = N0.getOperand(0).getValueType(); + if (Op0Ty == ExtSrcTy) { + ZextOp = N0.getOperand(0); + } else { + int64_t Imm = ~0ULL >> (64-ExtSrcTyBits); + ZextOp = DAG.getNode(ISD::AND, Op0Ty, N0.getOperand(0), + DAG.getConstant(Imm, Op0Ty)); + } + WorkList.push_back(ZextOp.Val); + // Otherwise, make this a use of a zext. + return DAG.getSetCC(VT, ZextOp, + DAG.getConstant(C1 & (~0ULL>>(64-ExtSrcTyBits)), + ExtDstTy), + Cond); + } + + uint64_t MinVal, MaxVal; + unsigned OperandBitSize = MVT::getSizeInBits(N1C->getValueType(0)); + if (ISD::isSignedIntSetCC(Cond)) { + MinVal = 1ULL << (OperandBitSize-1); + if (OperandBitSize != 1) // Avoid X >> 64, which is undefined. + MaxVal = ~0ULL >> (65-OperandBitSize); + else + MaxVal = 0; + } else { + MinVal = 0; + MaxVal = ~0ULL >> (64-OperandBitSize); + } + + // Canonicalize GE/LE comparisons to use GT/LT comparisons. + if (Cond == ISD::SETGE || Cond == ISD::SETUGE) { + if (C1 == MinVal) return DAG.getConstant(1, VT); // X >= MIN --> true + --C1; // X >= C0 --> X > (C0-1) + return DAG.getSetCC(VT, N0, DAG.getConstant(C1, N1.getValueType()), + (Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT); + } + + if (Cond == ISD::SETLE || Cond == ISD::SETULE) { + if (C1 == MaxVal) return DAG.getConstant(1, VT); // X <= MAX --> true + ++C1; // X <= C0 --> X < (C0+1) + return DAG.getSetCC(VT, N0, DAG.getConstant(C1, N1.getValueType()), + (Cond == ISD::SETLE) ? ISD::SETLT : ISD::SETULT); + } + + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal) + return DAG.getConstant(0, VT); // X < MIN --> false + + // Canonicalize setgt X, Min --> setne X, Min + if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MinVal) + return DAG.getSetCC(VT, N0, N1, ISD::SETNE); + + // If we have setult X, 1, turn it into seteq X, 0 + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal+1) + return DAG.getSetCC(VT, N0, DAG.getConstant(MinVal, N0.getValueType()), + ISD::SETEQ); + // If we have setugt X, Max-1, turn it into seteq X, Max + else if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal-1) + return DAG.getSetCC(VT, N0, DAG.getConstant(MaxVal, N0.getValueType()), + ISD::SETEQ); + + // If we have "setcc X, C0", check to see if we can shrink the immediate + // by changing cc. + + // SETUGT X, SINTMAX -> SETLT X, 0 + if (Cond == ISD::SETUGT && OperandBitSize != 1 && + C1 == (~0ULL >> (65-OperandBitSize))) + return DAG.getSetCC(VT, N0, DAG.getConstant(0, N1.getValueType()), + ISD::SETLT); + + // FIXME: Implement the rest of these. + + // Fold bit comparisons when we can. + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + VT == N0.getValueType() && N0.getOpcode() == ISD::AND) + if (ConstantSDNode *AndRHS = + dyn_cast(N0.getOperand(1))) { + if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3 + // Perform the xform if the AND RHS is a single bit. + if ((AndRHS->getValue() & (AndRHS->getValue()-1)) == 0) { + return DAG.getNode(ISD::SRL, VT, N0, + DAG.getConstant(Log2_64(AndRHS->getValue()), + TLI.getShiftAmountTy())); + } + } else if (Cond == ISD::SETEQ && C1 == AndRHS->getValue()) { + // (X & 8) == 8 --> (X & 8) >> 3 + // Perform the xform if C1 is a single bit. + if ((C1 & (C1-1)) == 0) { + return DAG.getNode(ISD::SRL, VT, N0, + DAG.getConstant(Log2_64(C1),TLI.getShiftAmountTy())); + } + } + } + } + } else if (isa(N0.Val)) { + // Ensure that the constant occurs on the RHS. + return DAG.getSetCC(VT, N1, N0, ISD::getSetCCSwappedOperands(Cond)); + } + + if (ConstantFPSDNode *N0C = dyn_cast(N0.Val)) + if (ConstantFPSDNode *N1C = dyn_cast(N1.Val)) { + double C0 = N0C->getValue(), C1 = N1C->getValue(); + + switch (Cond) { + default: break; // FIXME: Implement the rest of these! + case ISD::SETEQ: return DAG.getConstant(C0 == C1, VT); + case ISD::SETNE: return DAG.getConstant(C0 != C1, VT); + case ISD::SETLT: return DAG.getConstant(C0 < C1, VT); + case ISD::SETGT: return DAG.getConstant(C0 > C1, VT); + case ISD::SETLE: return DAG.getConstant(C0 <= C1, VT); + case ISD::SETGE: return DAG.getConstant(C0 >= C1, VT); + } + } else { + // Ensure that the constant occurs on the RHS. + return DAG.getSetCC(VT, N1, N0, ISD::getSetCCSwappedOperands(Cond)); + } + + if (N0 == N1) { + // We can always fold X == Y for integer setcc's. + if (MVT::isInteger(N0.getValueType())) + return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT); + unsigned UOF = ISD::getUnorderedFlavor(Cond); + if (UOF == 2) // FP operators that are undefined on NaNs. + return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT); + if (UOF == unsigned(ISD::isTrueWhenEqual(Cond))) + return DAG.getConstant(UOF, VT); + // Otherwise, we can't fold it. However, we can simplify it to SETUO/SETO + // if it is not already. + ISD::CondCode NewCond = UOF == 0 ? ISD::SETUO : ISD::SETO; + if (NewCond != Cond) + return DAG.getSetCC(VT, N0, N1, NewCond); + } + + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + MVT::isInteger(N0.getValueType())) { + if (N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::SUB || + N0.getOpcode() == ISD::XOR) { + // Simplify (X+Y) == (X+Z) --> Y == Z + if (N0.getOpcode() == N1.getOpcode()) { + if (N0.getOperand(0) == N1.getOperand(0)) + return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(1), Cond); + if (N0.getOperand(1) == N1.getOperand(1)) + return DAG.getSetCC(VT, N0.getOperand(0), N1.getOperand(0), Cond); + if (isCommutativeBinOp(N0.getOpcode())) { + // If X op Y == Y op X, try other combinations. + if (N0.getOperand(0) == N1.getOperand(1)) + return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(0), Cond); + if (N0.getOperand(1) == N1.getOperand(0)) + return DAG.getSetCC(VT, N0.getOperand(1), N1.getOperand(1), Cond); + } + } + + // Simplify (X+Z) == X --> Z == 0 + if (N0.getOperand(0) == N1) + return DAG.getSetCC(VT, N0.getOperand(1), + DAG.getConstant(0, N0.getValueType()), Cond); + if (N0.getOperand(1) == N1) { + if (isCommutativeBinOp(N0.getOpcode())) + return DAG.getSetCC(VT, N0.getOperand(0), + DAG.getConstant(0, N0.getValueType()), Cond); + else { + assert(N0.getOpcode() == ISD::SUB && "Unexpected operation!"); + // (Z-X) == X --> Z == X<<1 + SDOperand SH = DAG.getNode(ISD::SHL, N1.getValueType(), + N1, + DAG.getConstant(1,TLI.getShiftAmountTy())); + WorkList.push_back(SH.Val); + return DAG.getSetCC(VT, N0.getOperand(0), SH, Cond); + } + } + } + + if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB || + N1.getOpcode() == ISD::XOR) { + // Simplify X == (X+Z) --> Z == 0 + if (N1.getOperand(0) == N0) { + return DAG.getSetCC(VT, N1.getOperand(1), + DAG.getConstant(0, N1.getValueType()), Cond); + } else if (N1.getOperand(1) == N0) { + if (isCommutativeBinOp(N1.getOpcode())) { + return DAG.getSetCC(VT, N1.getOperand(0), + DAG.getConstant(0, N1.getValueType()), Cond); + } else { + assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!"); + // X == (Z-X) --> X<<1 == Z + SDOperand SH = DAG.getNode(ISD::SHL, N1.getValueType(), N0, + DAG.getConstant(1,TLI.getShiftAmountTy())); + WorkList.push_back(SH.Val); + return DAG.getSetCC(VT, SH, N1.getOperand(0), Cond); + } + } + } + } + + // Fold away ALL boolean setcc's. + SDOperand Temp; + if (N0.getValueType() == MVT::i1) { + switch (Cond) { + default: assert(0 && "Unknown integer setcc!"); + case ISD::SETEQ: // X == Y -> (X^Y)^1 + Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, N1); + N0 = DAG.getNode(ISD::XOR, MVT::i1, Temp, DAG.getConstant(1, MVT::i1)); + WorkList.push_back(Temp.Val); + break; + case ISD::SETNE: // X != Y --> (X^Y) + N0 = DAG.getNode(ISD::XOR, MVT::i1, N0, N1); + break; + case ISD::SETGT: // X >s Y --> X == 0 & Y == 1 --> X^1 & Y + case ISD::SETULT: // X X == 0 & Y == 1 --> X^1 & Y + Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, DAG.getConstant(1, MVT::i1)); + N0 = DAG.getNode(ISD::AND, MVT::i1, N1, Temp); + WorkList.push_back(Temp.Val); + break; + case ISD::SETLT: // X X == 1 & Y == 0 --> Y^1 & X + case ISD::SETUGT: // X >u Y --> X == 1 & Y == 0 --> Y^1 & X + Temp = DAG.getNode(ISD::XOR, MVT::i1, N1, DAG.getConstant(1, MVT::i1)); + N0 = DAG.getNode(ISD::AND, MVT::i1, N0, Temp); + WorkList.push_back(Temp.Val); + break; + case ISD::SETULE: // X <=u Y --> X == 0 | Y == 1 --> X^1 | Y + case ISD::SETGE: // X >=s Y --> X == 0 | Y == 1 --> X^1 | Y + Temp = DAG.getNode(ISD::XOR, MVT::i1, N0, DAG.getConstant(1, MVT::i1)); + N0 = DAG.getNode(ISD::OR, MVT::i1, N1, Temp); + WorkList.push_back(Temp.Val); + break; + case ISD::SETUGE: // X >=u Y --> X == 1 | Y == 0 --> Y^1 | X + case ISD::SETLE: // X <=s Y --> X == 1 | Y == 0 --> Y^1 | X + Temp = DAG.getNode(ISD::XOR, MVT::i1, N1, DAG.getConstant(1, MVT::i1)); + N0 = DAG.getNode(ISD::OR, MVT::i1, N0, Temp); + break; + } + if (VT != MVT::i1) { + WorkList.push_back(N0.Val); + // FIXME: If running after legalize, we probably can't do this. + N0 = DAG.getNode(ISD::ZERO_EXTEND, VT, N0); + } + return N0; + } + + // Could not fold it. + return SDOperand(); +} + // SelectionDAG::Combine - This is the entry point for the file. // void SelectionDAG::Combine(bool RunningAfterLegalize) { From lattner at cs.uiuc.edu Thu Sep 15 20:28:49 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 15 Sep 2005 20:28:49 -0500 Subject: [llvm-commits] CVS: llvm-test/Makefile.programs Message-ID: <200509160128.UAA22068@zion.cs.uiuc.edu> Changes in directory llvm-test: Makefile.programs updated: 1.169 -> 1.170 --- Log message: Fix these rules to not leave the file around if the diff file doesn't exist --- Diffs of the changes: (+6 -0) Makefile.programs | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm-test/Makefile.programs diff -u llvm-test/Makefile.programs:1.169 llvm-test/Makefile.programs:1.170 --- llvm-test/Makefile.programs:1.169 Tue Sep 6 19:15:36 2005 +++ llvm-test/Makefile.programs Thu Sep 15 20:28:37 2005 @@ -459,26 +459,32 @@ ifndef DISABLE_DIFFS $(PROGRAMS_TO_TEST:%=Output/%.exe-lli): \ Output/%.exe-lli: Output/%.diff-lli + -rm $@ -cp $< $@ $(PROGRAMS_TO_TEST:%=Output/%.exe-jit): \ Output/%.exe-jit: Output/%.diff-jit + -rm $@ -cp $< $@ $(PROGRAMS_TO_TEST:%=Output/%.exe-jit-beta): \ Output/%.exe-jit-beta: Output/%.diff-jit-beta + -rm $@ -cp $< $@ $(PROGRAMS_TO_TEST:%=Output/%.exe-llc): \ Output/%.exe-llc: Output/%.diff-llc + -rm $@ -cp $< $@ $(PROGRAMS_TO_TEST:%=Output/%.exe-llc-beta): \ Output/%.exe-llc-beta: Output/%.diff-llc-beta + -rm $@ -cp $< $@ $(PROGRAMS_TO_TEST:%=Output/%.exe-cbe): \ Output/%.exe-cbe: Output/%.diff-cbe + -rm $@ -cp $< $@ # Pseudo target to build just the bytecode file. From lattner at cs.uiuc.edu Fri Sep 16 20:02:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 16 Sep 2005 20:02:57 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200509170102.UAA01224@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.57 -> 1.58 --- Log message: add a new callback --- Diffs of the changes: (+8 -0) MRegisterInfo.h | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.57 llvm/include/llvm/Target/MRegisterInfo.h:1.58 --- llvm/include/llvm/Target/MRegisterInfo.h:1.57 Thu Apr 21 22:46:24 2005 +++ llvm/include/llvm/Target/MRegisterInfo.h Fri Sep 16 20:02:45 2005 @@ -250,6 +250,14 @@ unsigned DestReg, unsigned SrcReg, const TargetRegisterClass *RC) const = 0; + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return false if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const{ + return 0; + } /// foldMemoryOperand - Attempt to fold a load or store of the /// specified stack slot into the specified machine instruction for From lattner at cs.uiuc.edu Fri Sep 16 20:03:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 16 Sep 2005 20:03:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp PPC32RegisterInfo.h Message-ID: <200509170103.UAA01283@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32RegisterInfo.cpp updated: 1.23 -> 1.24 PPC32RegisterInfo.h updated: 1.4 -> 1.5 --- Log message: Implement hook for ppc --- Diffs of the changes: (+18 -0) PPC32RegisterInfo.cpp | 16 ++++++++++++++++ PPC32RegisterInfo.h | 2 ++ 2 files changed, 18 insertions(+) Index: llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp diff -u llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp:1.23 llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp:1.24 --- llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp:1.23 Fri Sep 9 16:59:44 2005 +++ llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp Fri Sep 16 20:03:26 2005 @@ -134,6 +134,22 @@ } } +unsigned PPC32RegisterInfo::isLoadFromStackSlot(MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case PPC::LWZ: + case PPC::LFD: + if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() && + MI->getOperand(2).isFrameIndex()) { + FrameIndex = MI->getOperand(2).getFrameIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into /// copy instructions, turning them into load/store instructions. MachineInstr *PPC32RegisterInfo::foldMemoryOperand(MachineInstr *MI, Index: llvm/lib/Target/PowerPC/PPC32RegisterInfo.h diff -u llvm/lib/Target/PowerPC/PPC32RegisterInfo.h:1.4 llvm/lib/Target/PowerPC/PPC32RegisterInfo.h:1.5 --- llvm/lib/Target/PowerPC/PPC32RegisterInfo.h:1.4 Fri Sep 9 16:46:49 2005 +++ llvm/lib/Target/PowerPC/PPC32RegisterInfo.h Fri Sep 16 20:03:26 2005 @@ -40,6 +40,8 @@ unsigned DestReg, unsigned SrcReg, const TargetRegisterClass *RC) const; + unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; + /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into /// copy instructions, turning them into load/store instructions. virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, From lattner at cs.uiuc.edu Sat Sep 17 22:39:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 17 Sep 2005 22:39:14 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/or.ll Message-ID: <200509180339.WAA07672@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: or.ll updated: 1.29 -> 1.30 --- Log message: new testcase --- Diffs of the changes: (+8 -0) or.ll | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/or.ll diff -u llvm/test/Regression/Transforms/InstCombine/or.ll:1.29 llvm/test/Regression/Transforms/InstCombine/or.ll:1.30 --- llvm/test/Regression/Transforms/InstCombine/or.ll:1.29 Thu May 5 19:58:09 2005 +++ llvm/test/Regression/Transforms/InstCombine/or.ll Sat Sep 17 22:39:02 2005 @@ -133,3 +133,11 @@ %z = or int %y, %x ret int %z } + +uint %test21(uint %tmp.1) { + %tmp.1.mask1 = add uint %tmp.1, 2 + %tmp.3 = and uint %tmp.1.mask1, 4294967294 + %tmp.5 = and uint %tmp.1, 1 + %tmp.6 = or uint %tmp.5, %tmp.3 ;; add tmp.1, 2 + ret uint %tmp.6 +} From lattner at cs.uiuc.edu Sat Sep 17 22:42:18 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 17 Sep 2005 22:42:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180342.WAA07697@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.371 -> 1.372 --- Log message: Implement or.ll:test21. This teaches instcombine to be able to turn this: struct { unsigned int bit0:1; unsigned int ubyte:31; } sdata; void foo() { sdata.ubyte++; } into this: foo: add DWORD PTR [sdata], 2 ret instead of this: foo: mov %EAX, DWORD PTR [sdata] mov %ECX, %EAX add %ECX, 2 and %ECX, -2 and %EAX, 1 or %EAX, %ECX mov DWORD PTR [sdata], %EAX ret --- Diffs of the changes: (+25 -3) InstructionCombining.cpp | 28 +++++++++++++++++++++++++--- 1 files changed, 25 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.371 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.372 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.371 Wed Sep 14 12:32:56 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Sep 17 22:42:07 2005 @@ -1921,10 +1921,31 @@ return BinaryOperator::createXor(InsertNewInstBefore(NOr, I), C1); } - // (A & C1)|(A & C2) == A & (C1|C2) + // (A & C1)|(B & C2) if (match(Op0, m_And(m_Value(A), m_ConstantInt(C1))) && - match(Op1, m_And(m_Value(B), m_ConstantInt(C2))) && A == B) - return BinaryOperator::createAnd(A, ConstantExpr::getOr(C1, C2)); + match(Op1, m_And(m_Value(B), m_ConstantInt(C2)))) { + + if (A == B) // (A & C1)|(A & C2) == A & (C1|C2) + return BinaryOperator::createAnd(A, ConstantExpr::getOr(C1, C2)); + + + // if A == (add B, C3) or B == (add A, C4) + ConstantInt *C3 = 0; + Value *V = 0; + if ((match(A, m_Add(m_Value(V), m_ConstantInt(C3))) && V == B || + match(B, m_Add(m_Value(V), m_ConstantInt(C3))) && V == A)) { + if (V == A) std::swap(C1, C2); + // We have: ((V + C3) & C1) | (V & C2) + // if C2 = ~C1 and (C3 & C2) == 0 and C2 is 0+1+ + if (C1 == ConstantExpr::getNot(C2) && + ConstantExpr::getAnd(C3, C2)->isNullValue() && + (C2->getRawValue() & (C2->getRawValue()+1)) == 0) { + // Return V+C3. + std::cerr << "Simpl: " << *A << "Simpl2: " << *B << "Simpl3: " << I; + return ReplaceInstUsesWith(I, V == A ? B : A); + } + } + } if (match(Op0, m_Not(m_Value(A)))) { // ~A | Op1 if (A == Op1) // ~A | A == -1 @@ -2040,6 +2061,7 @@ } } } + return Changed ? &I : 0; } From lattner at cs.uiuc.edu Sat Sep 17 22:50:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 17 Sep 2005 22:50:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180350.WAA07750@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.372 -> 1.373 --- Log message: remove debug output --- Diffs of the changes: (+0 -1) InstructionCombining.cpp | 1 - 1 files changed, 1 deletion(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.372 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.373 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.372 Sat Sep 17 22:42:07 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Sep 17 22:50:25 2005 @@ -1941,7 +1941,6 @@ ConstantExpr::getAnd(C3, C2)->isNullValue() && (C2->getRawValue() & (C2->getRawValue()+1)) == 0) { // Return V+C3. - std::cerr << "Simpl: " << *A << "Simpl2: " << *B << "Simpl3: " << I; return ReplaceInstUsesWith(I, V == A ? B : A); } } From lattner at cs.uiuc.edu Sat Sep 17 23:23:11 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 17 Sep 2005 23:23:11 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/add.ll Message-ID: <200509180423.XAA08375@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: add.ll updated: 1.26 -> 1.27 --- Log message: new testcase --- Diffs of the changes: (+10 -0) add.ll | 10 ++++++++++ 1 files changed, 10 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/add.ll diff -u llvm/test/Regression/Transforms/InstCombine/add.ll:1.26 llvm/test/Regression/Transforms/InstCombine/add.ll:1.27 --- llvm/test/Regression/Transforms/InstCombine/add.ll:1.26 Thu Apr 7 11:24:59 2005 +++ llvm/test/Regression/Transforms/InstCombine/add.ll Sat Sep 17 23:22:59 2005 @@ -196,3 +196,13 @@ %Z = sub int 42, %Y ret int %Z } + +uint %test29(uint %X, uint %x) { + %tmp.2 = sub uint %X, %x + %tmp.2.mask = and uint %tmp.2, 63 ; [#uses=1] + %tmp.6 = add uint %tmp.2.mask, %x ; [#uses=1] + %tmp.7 = and uint %tmp.6, 63 ; [#uses=1] + %tmp.9 = and uint %tmp.2, 4294967232 ; [#uses=1] + %tmp.10 = or uint %tmp.7, %tmp.9 ; [#uses=1] + ret uint %tmp.10 +} From lattner at cs.uiuc.edu Sat Sep 17 23:24:56 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 17 Sep 2005 23:24:56 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180424.XAA08505@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.373 -> 1.374 --- Log message: Implement add.ll:test29. Codegening: struct S { unsigned int i : 6, j : 11, k : 15; } b; void plus1 (unsigned int x) { b.i += x; } as: _plus1: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r4, 0(r2) add r3, r4, r3 rlwimi r3, r4, 0, 0, 25 stw r3, 0(r2) blr instead of: _plus1: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r4, 0(r2) rlwinm r5, r4, 0, 26, 31 add r3, r5, r3 rlwimi r3, r4, 0, 0, 25 stw r3, 0(r2) blr --- Diffs of the changes: (+66 -0) InstructionCombining.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 66 insertions(+) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.373 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.374 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.373 Sat Sep 17 22:50:25 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Sep 17 23:24:45 2005 @@ -222,6 +222,9 @@ Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS, ConstantIntegral *AndRHS, BinaryOperator &TheAnd); + + Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantIntegral *Mask, + bool isSub, Instruction &I); Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, bool Inside, Instruction &IB); @@ -1570,6 +1573,46 @@ return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST); } +/// FoldLogicalPlusAnd - We know that Mask is of the form 0+1+, and that this is +/// part of an expression (LHS +/- RHS) & Mask, where isSub determines whether +/// the operator is a sub. If we can fold one of the following xforms: +/// +/// ((A & N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == Mask +/// ((A | N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0 +/// ((A ^ N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0 +/// +/// return (A +/- B). +/// +Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS, + ConstantIntegral *Mask, bool isSub, + Instruction &I) { + Instruction *LHSI = dyn_cast(LHS); + if (!LHSI || LHSI->getNumOperands() != 2 || + !isa(LHSI->getOperand(1))) return 0; + + ConstantInt *N = cast(LHSI->getOperand(1)); + + switch (LHSI->getOpcode()) { + default: return 0; + case Instruction::And: + if (ConstantExpr::getAnd(N, Mask) == Mask) + break; + return 0; + case Instruction::Or: + case Instruction::Xor: + if (ConstantExpr::getAnd(N, Mask)->isNullValue()) + break; + return 0; + } + + Instruction *New; + if (isSub) + New = BinaryOperator::createSub(LHSI->getOperand(0), RHS, "fold"); + else + New = BinaryOperator::createAdd(LHSI->getOperand(0), RHS, "fold"); + return InsertNewInstBefore(New, I); +} + Instruction *InstCombiner::visitAnd(BinaryOperator &I) { bool Changed = SimplifyCommutative(I); @@ -1640,6 +1683,29 @@ MaskedValueIsZero(Op0RHS, AndRHS)) return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); break; + case Instruction::Add: + // If the AndRHS is a power of two minus one (0+1+). + if ((AndRHS->getRawValue() & AndRHS->getRawValue()+1) == 0) { + // ((A & N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == AndRHS. + // ((A | N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 + // ((A ^ N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 + if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I)) + return BinaryOperator::createAnd(V, AndRHS); + if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I)) + return BinaryOperator::createAnd(V, AndRHS); // Add commutes + } + break; + + case Instruction::Sub: + // If the AndRHS is a power of two minus one (0+1+). + if ((AndRHS->getRawValue() & AndRHS->getRawValue()+1) == 0) { + // ((A & N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == AndRHS. + // ((A | N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 + // ((A ^ N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 + if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I)) + return BinaryOperator::createAnd(V, AndRHS); + } + break; } if (ConstantInt *Op0CI = dyn_cast(Op0I->getOperand(1))) From lattner at cs.uiuc.edu Sun Sep 18 00:10:51 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 00:10:51 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/shift.ll Message-ID: <200509180510.AAA11103@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: shift.ll updated: 1.20 -> 1.21 --- Log message: new testcase --- Diffs of the changes: (+8 -0) shift.ll | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/shift.ll diff -u llvm/test/Regression/Transforms/InstCombine/shift.ll:1.20 llvm/test/Regression/Transforms/InstCombine/shift.ll:1.21 --- llvm/test/Regression/Transforms/InstCombine/shift.ll:1.20 Sun May 8 12:31:24 2005 +++ llvm/test/Regression/Transforms/InstCombine/shift.ll Sun Sep 18 00:10:39 2005 @@ -172,3 +172,11 @@ ret sbyte %Q } +uint %test25(uint %tmp.2, uint %AA) { + %x = shr uint %AA, ubyte 17 + %tmp.3 = shr uint %tmp.2, ubyte 17 ; [#uses=1] + %tmp.5 = add uint %tmp.3, %x ; [#uses=1] + %tmp.6 = shl uint %tmp.5, ubyte 17 ; [#uses=1] + ret uint %tmp.6 +} + From lattner at cs.uiuc.edu Sun Sep 18 00:12:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 00:12:21 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180512.AAA11115@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.374 -> 1.375 --- Log message: implement shift.ll:test25. This compiles: struct S { unsigned int i : 6, j : 11, k : 15; } b; void plus3 (unsigned int x) { b.k += x; } to: _plus3: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r3, 0(r2) rlwinm r4, r3, 0, 0, 14 add r4, r4, r3 rlwimi r4, r3, 0, 15, 31 stw r4, 0(r2) blr instead of: _plus3: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r4, 0(r2) srwi r5, r4, 17 add r3, r5, r3 slwi r3, r3, 17 rlwimi r3, r4, 0, 15, 31 stw r3, 0(r2) blr --- Diffs of the changes: (+53 -3) InstructionCombining.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 53 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.374 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.375 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.374 Sat Sep 17 23:24:45 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Sep 18 00:12:10 2005 @@ -3355,9 +3355,58 @@ } } - // If the operand is an bitwise operator with a constant RHS, and the - // shift is the only use, we can pull it out of the shift. - if (BinaryOperator *Op0BO = dyn_cast(Op0)) + if (BinaryOperator *Op0BO = dyn_cast(Op0)) { + // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) + switch (Op0BO->getOpcode()) { + default: break; + case Instruction::Add: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + // These operators commute. + // Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C) + if (ShiftInst *XS = dyn_cast(Op0BO->getOperand(1))) + if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI && + XS->getOpcode() == Instruction::Shr) { + break; + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(0), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, + XS->getOperand(0), + XS->getName()); + InsertNewInstBefore(X, I); // (X + (Y << C)) + Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); + C2 = ConstantExpr::getShl(C2, CUI); + std::cerr << "FOLD1: " << *Op0BO; + return BinaryOperator::createAnd(X, C2); + } + // Fall through. + case Instruction::Sub: + // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) + if (ShiftInst *XS = dyn_cast(Op0BO->getOperand(0))) + if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI && + XS->getOpcode() == Instruction::Shr) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(0), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, + XS->getOperand(0), + XS->getName()); + InsertNewInstBefore(X, I); // (X + (Y << C)) + Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); + C2 = ConstantExpr::getShl(C2, CUI); + std::cerr << "FOLD2: " << *Op0BO; + return BinaryOperator::createAnd(X, C2); + } + break; + } + + + // If the operand is an bitwise operator with a constant RHS, and the + // shift is the only use, we can pull it out of the shift. if (ConstantInt *Op0C = dyn_cast(Op0BO->getOperand(1))) { bool isValid = true; // Valid only for And, Or, Xor bool highBitSet = false; // Transform if high bit of constant set? @@ -3400,6 +3449,7 @@ NewRHS); } } + } } // If this is a shift of a shift, see if we can fold the two together... From lattner at cs.uiuc.edu Sun Sep 18 00:13:02 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 00:13:02 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180513.AAA11127@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.375 -> 1.376 --- Log message: Remove unintentionally committed code --- Diffs of the changes: (+0 -3) InstructionCombining.cpp | 3 --- 1 files changed, 3 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.375 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.376 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.375 Sun Sep 18 00:12:10 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Sep 18 00:12:51 2005 @@ -3368,7 +3368,6 @@ if (ShiftInst *XS = dyn_cast(Op0BO->getOperand(1))) if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI && XS->getOpcode() == Instruction::Shr) { - break; Instruction *YS = new ShiftInst(Instruction::Shl, Op0BO->getOperand(0), CUI, Op0BO->getName()); @@ -3379,7 +3378,6 @@ InsertNewInstBefore(X, I); // (X + (Y << C)) Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); C2 = ConstantExpr::getShl(C2, CUI); - std::cerr << "FOLD1: " << *Op0BO; return BinaryOperator::createAnd(X, C2); } // Fall through. @@ -3398,7 +3396,6 @@ InsertNewInstBefore(X, I); // (X + (Y << C)) Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); C2 = ConstantExpr::getShl(C2, CUI); - std::cerr << "FOLD2: " << *Op0BO; return BinaryOperator::createAnd(X, C2); } break; From lattner at cs.uiuc.edu Sun Sep 18 00:25:31 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 00:25:31 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180525.AAA12036@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.376 -> 1.377 --- Log message: fix typeo --- Diffs of the changes: (+1 -1) InstructionCombining.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.376 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.377 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.376 Sun Sep 18 00:12:51 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Sep 18 00:25:20 2005 @@ -3387,7 +3387,7 @@ if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI && XS->getOpcode() == Instruction::Shr) { Instruction *YS = new ShiftInst(Instruction::Shl, - Op0BO->getOperand(0), CUI, + Op0BO->getOperand(1), CUI, Op0BO->getName()); InsertNewInstBefore(YS, I); // (Y << C) Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, From lattner at cs.uiuc.edu Sun Sep 18 01:03:11 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 01:03:11 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180603.BAA13133@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.377 -> 1.378 --- Log message: Generalize this transform, using MaskedValueIsZero, allowing us to compile: struct S { unsigned int i : 6, j : 11, k : 15; } b; void plus3 (unsigned int x) { b.k += x; } To: plus3: mov %EAX, DWORD PTR [%ESP + 4] shl %EAX, 17 add DWORD PTR [b], %EAX ret instead of: plus3: mov %EAX, DWORD PTR [%ESP + 4] shl %EAX, 17 mov %ECX, DWORD PTR [b] add %EAX, %ECX and %EAX, -131072 and %ECX, 131071 or %ECX, %EAX mov DWORD PTR [b], %ECX ret --- Diffs of the changes: (+21 -14) InstructionCombining.cpp | 35 +++++++++++++++++++++-------------- 1 files changed, 21 insertions(+), 14 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.377 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.378 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.377 Sun Sep 18 00:25:20 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Sep 18 01:02:59 2005 @@ -225,7 +225,6 @@ Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantIntegral *Mask, bool isSub, Instruction &I); - Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, bool Inside, Instruction &IB); }; @@ -1995,19 +1994,27 @@ return BinaryOperator::createAnd(A, ConstantExpr::getOr(C1, C2)); - // if A == (add B, C3) or B == (add A, C4) - ConstantInt *C3 = 0; - Value *V = 0; - if ((match(A, m_Add(m_Value(V), m_ConstantInt(C3))) && V == B || - match(B, m_Add(m_Value(V), m_ConstantInt(C3))) && V == A)) { - if (V == A) std::swap(C1, C2); - // We have: ((V + C3) & C1) | (V & C2) - // if C2 = ~C1 and (C3 & C2) == 0 and C2 is 0+1+ - if (C1 == ConstantExpr::getNot(C2) && - ConstantExpr::getAnd(C3, C2)->isNullValue() && - (C2->getRawValue() & (C2->getRawValue()+1)) == 0) { - // Return V+C3. - return ReplaceInstUsesWith(I, V == A ? B : A); + // If we have: ((V + N) & C1) | (V & C2) + // .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0 + // replace with V+N. + if (C1 == ConstantExpr::getNot(C2)) { + Value *V1, *V2; + if ((C2->getRawValue() & (C2->getRawValue()+1)) == 0 && // C2 == 0+1+ + match(A, m_Add(m_Value(V1), m_Value(V2)))) { + // Add commutes, try both ways. + if (V1 == B && MaskedValueIsZero(V2, C2)) + return ReplaceInstUsesWith(I, A); + if (V2 == B && MaskedValueIsZero(V1, C2)) + return ReplaceInstUsesWith(I, A); + } + // Or commutes, try both ways. + if ((C1->getRawValue() & (C1->getRawValue()+1)) == 0 && + match(B, m_Add(m_Value(V1), m_Value(V2)))) { + // Add commutes, try both ways. + if (V1 == A && MaskedValueIsZero(V2, C1)) + return ReplaceInstUsesWith(I, B); + if (V2 == A && MaskedValueIsZero(V1, C1)) + return ReplaceInstUsesWith(I, B); } } } From lattner at cs.uiuc.edu Sun Sep 18 01:31:10 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 01:31:10 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180631.BAA14577@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.378 -> 1.379 --- Log message: Compile struct S { unsigned int i : 6, j : 11, k : 15; } b; void plus2 (unsigned int x) { b.j += x; } to: plus2: mov %EAX, DWORD PTR [b] mov %ECX, %EAX and %ECX, 131008 mov %EDX, DWORD PTR [%ESP + 4] shl %EDX, 6 add %EDX, %ECX and %EDX, 131008 and %EAX, -131009 or %EDX, %EAX mov DWORD PTR [b], %EDX ret instead of: plus2: mov %EAX, DWORD PTR [b] mov %ECX, %EAX shr %ECX, 6 and %ECX, 2047 add %ECX, DWORD PTR [%ESP + 4] shl %ECX, 6 and %ECX, 131008 and %EAX, -131009 or %ECX, %EAX mov DWORD PTR [b], %ECX ret --- Diffs of the changes: (+70 -31) InstructionCombining.cpp | 101 ++++++++++++++++++++++++++++++++--------------- 1 files changed, 70 insertions(+), 31 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.378 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.379 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.378 Sun Sep 18 01:02:59 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Sep 18 01:30:59 2005 @@ -3364,6 +3364,8 @@ if (BinaryOperator *Op0BO = dyn_cast(Op0)) { // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) + Value *V1, *V2, *V3; + ConstantInt *CC; switch (Op0BO->getOpcode()) { default: break; case Instruction::Add: @@ -3372,39 +3374,76 @@ case Instruction::Xor: // These operators commute. // Turn (Y + (X >> C)) << C -> (X + (Y << C)) & (~0 << C) - if (ShiftInst *XS = dyn_cast(Op0BO->getOperand(1))) - if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI && - XS->getOpcode() == Instruction::Shr) { - Instruction *YS = new ShiftInst(Instruction::Shl, - Op0BO->getOperand(0), CUI, - Op0BO->getName()); - InsertNewInstBefore(YS, I); // (Y << C) - Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, - XS->getOperand(0), - XS->getName()); - InsertNewInstBefore(X, I); // (X + (Y << C)) - Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); - C2 = ConstantExpr::getShl(C2, CUI); - return BinaryOperator::createAnd(X, C2); - } - // Fall through. + if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() && + match(Op0BO->getOperand(1), + m_Shr(m_Value(V1), m_ConstantInt(CC))) && CC == CUI) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(0), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, + V1, + Op0BO->getOperand(1)->getName()); + InsertNewInstBefore(X, I); // (X + (Y << C)) + Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); + C2 = ConstantExpr::getShl(C2, CUI); + return BinaryOperator::createAnd(X, C2); + } + + // Turn (Y + ((X >> C) & CC)) << C -> ((X & (CC << C)) + (Y << C)) + if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() && + match(Op0BO->getOperand(1), + m_And(m_Shr(m_Value(V1), m_Value(V2)), + m_ConstantInt(CC))) && V2 == CUI && + cast(Op0BO->getOperand(1))->getOperand(0)->hasOneUse()) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(0), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *XM = + BinaryOperator::createAnd(V1, ConstantExpr::getShl(CC, CUI), + V1->getName()+".mask"); + InsertNewInstBefore(XM, I); // X & (CC << C) + + return BinaryOperator::create(Op0BO->getOpcode(), YS, XM); + } + + // FALL THROUGH. case Instruction::Sub: // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) - if (ShiftInst *XS = dyn_cast(Op0BO->getOperand(0))) - if (isLeftShift && XS->hasOneUse() && XS->getOperand(1) == CUI && - XS->getOpcode() == Instruction::Shr) { - Instruction *YS = new ShiftInst(Instruction::Shl, - Op0BO->getOperand(1), CUI, - Op0BO->getName()); - InsertNewInstBefore(YS, I); // (Y << C) - Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, - XS->getOperand(0), - XS->getName()); - InsertNewInstBefore(X, I); // (X + (Y << C)) - Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); - C2 = ConstantExpr::getShl(C2, CUI); - return BinaryOperator::createAnd(X, C2); - } + if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && + match(Op0BO->getOperand(0), + m_Shr(m_Value(V1), m_ConstantInt(CC))) && CC == CUI) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(1), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *X = BinaryOperator::create(Op0BO->getOpcode(), YS, + V1, + Op0BO->getOperand(0)->getName()); + InsertNewInstBefore(X, I); // (X + (Y << C)) + Constant *C2 = ConstantInt::getAllOnesValue(X->getType()); + C2 = ConstantExpr::getShl(C2, CUI); + return BinaryOperator::createAnd(X, C2); + } + + if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() && + match(Op0BO->getOperand(0), + m_And(m_Shr(m_Value(V1), m_Value(V2)), + m_ConstantInt(CC))) && V2 == CUI && + cast(Op0BO->getOperand(0))->getOperand(0)->hasOneUse()) { + Instruction *YS = new ShiftInst(Instruction::Shl, + Op0BO->getOperand(1), CUI, + Op0BO->getName()); + InsertNewInstBefore(YS, I); // (Y << C) + Instruction *XM = + BinaryOperator::createAnd(V1, ConstantExpr::getShl(CC, CUI), + V1->getName()+".mask"); + InsertNewInstBefore(XM, I); // X & (CC << C) + + return BinaryOperator::create(Op0BO->getOpcode(), YS, XM); + } + break; } From lattner at cs.uiuc.edu Sun Sep 18 02:22:13 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 18 Sep 2005 02:22:13 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200509180722.CAA16417@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.379 -> 1.380 --- Log message: Refactor this code a bit and make it more general. This now compiles: struct S { unsigned int i : 6, j : 11, k : 15; } b; void plus2 (unsigned int x) { b.j += x; } To: _plus2: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r4, 0(r2) slwi r3, r3, 6 add r3, r4, r3 rlwimi r3, r4, 0, 26, 14 stw r3, 0(r2) blr instead of: _plus2: lis r2, ha16(L_b$non_lazy_ptr) lwz r2, lo16(L_b$non_lazy_ptr)(r2) lwz r4, 0(r2) rlwinm r5, r4, 26, 21, 31 add r3, r5, r3 rlwimi r4, r3, 6, 15, 25 stw r4, 0(r2) blr by eliminating an 'and'. I'm pretty sure this is as small as we can go :) --- Diffs of the changes: (+53 -24) InstructionCombining.cpp | 77 ++++++++++++++++++++++++++++++++--------------- 1 files changed, 53 insertions(+), 24 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.379 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.380 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.379 Sun Sep 18 01:30:59 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Sep 18 02:22:02 2005 @@ -1572,9 +1572,26 @@ return new SetCondInst(Instruction::SetGT, OffsetVal, AddCST); } -/// FoldLogicalPlusAnd - We know that Mask is of the form 0+1+, and that this is -/// part of an expression (LHS +/- RHS) & Mask, where isSub determines whether -/// the operator is a sub. If we can fold one of the following xforms: +// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with +// any number of 0s on either side. The 1s are allowed to wrap from LSB to +// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is +// not, since all 1s are not contiguous. +static bool isRunOfOnes(ConstantIntegral *Val, unsigned &MB, unsigned &ME) { + uint64_t V = Val->getRawValue(); + if (!isShiftedMask_64(V)) return false; + + // look for the first zero bit after the run of ones + MB = 64-CountLeadingZeros_64((V - 1) ^ V); + // look for the first non-zero bit + ME = 64-CountLeadingZeros_64(V); + return true; +} + + + +/// FoldLogicalPlusAnd - This is part of an expression (LHS +/- RHS) & Mask, +/// where isSub determines whether the operator is a sub. If we can fold one of +/// the following xforms: /// /// ((A & N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == Mask /// ((A | N) +/- B) & Mask -> (A +/- B) & Mask iff N&Mask == 0 @@ -1594,12 +1611,30 @@ switch (LHSI->getOpcode()) { default: return 0; case Instruction::And: - if (ConstantExpr::getAnd(N, Mask) == Mask) - break; + if (ConstantExpr::getAnd(N, Mask) == Mask) { + // If the AndRHS is a power of two minus one (0+1+), this is simple. + if ((Mask->getRawValue() & Mask->getRawValue()+1) == 0) + break; + + // Otherwise, if Mask is 0+1+0+, and if B is known to have the low 0+ + // part, we don't need any explicit masks to take them out of A. If that + // is all N is, ignore it. + unsigned MB, ME; + if (isRunOfOnes(Mask, MB, ME)) { // begin/end bit of run, inclusive + Constant *Mask = ConstantInt::getAllOnesValue(RHS->getType()); + Mask = ConstantExpr::getUShr(Mask, + ConstantInt::get(Type::UByteTy, + (64-MB+1))); + if (MaskedValueIsZero(RHS, cast(Mask))) + break; + } + } return 0; case Instruction::Or: case Instruction::Xor: - if (ConstantExpr::getAnd(N, Mask)->isNullValue()) + // If the AndRHS is a power of two minus one (0+1+), and N&Mask == 0 + if ((Mask->getRawValue() & Mask->getRawValue()+1) == 0 && + ConstantExpr::getAnd(N, Mask)->isNullValue()) break; return 0; } @@ -1683,27 +1718,21 @@ return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); break; case Instruction::Add: - // If the AndRHS is a power of two minus one (0+1+). - if ((AndRHS->getRawValue() & AndRHS->getRawValue()+1) == 0) { - // ((A & N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == AndRHS. - // ((A | N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 - // ((A ^ N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 - if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I)) - return BinaryOperator::createAnd(V, AndRHS); - if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I)) - return BinaryOperator::createAnd(V, AndRHS); // Add commutes - } + // ((A & N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == AndRHS. + // ((A | N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 + // ((A ^ N) + B) & AndRHS -> (A + B) & AndRHS iff N&AndRHS == 0 + if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, false, I)) + return BinaryOperator::createAnd(V, AndRHS); + if (Value *V = FoldLogicalPlusAnd(Op0RHS, Op0LHS, AndRHS, false, I)) + return BinaryOperator::createAnd(V, AndRHS); // Add commutes break; case Instruction::Sub: - // If the AndRHS is a power of two minus one (0+1+). - if ((AndRHS->getRawValue() & AndRHS->getRawValue()+1) == 0) { - // ((A & N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == AndRHS. - // ((A | N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 - // ((A ^ N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 - if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I)) - return BinaryOperator::createAnd(V, AndRHS); - } + // ((A & N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == AndRHS. + // ((A | N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 + // ((A ^ N) - B) & AndRHS -> (A - B) & AndRHS iff N&AndRHS == 0 + if (Value *V = FoldLogicalPlusAnd(Op0LHS, Op0RHS, AndRHS, true, I)) + return BinaryOperator::createAnd(V, AndRHS); break; }