From isanbard at gmail.com Mon Oct 22 00:10:06 2007
From: isanbard at gmail.com (Bill Wendling)
Date: Mon, 22 Oct 2007 05:10:06 -0000
Subject: [llvm-commits] [llvm] r43216 - /llvm/trunk/docs/LangRef.html
Message-ID: <200710220510.l9M5A6Sk001918@zion.cs.uiuc.edu>
Author: void
Date: Mon Oct 22 00:10:05 2007
New Revision: 43216
URL: http://llvm.org/viewvc/llvm-project?rev=43216&view=rev
Log:
Put correct link in example
Modified:
llvm/trunk/docs/LangRef.html
Modified: llvm/trunk/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=43216&r1=43215&r2=43216&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.html (original)
+++ llvm/trunk/docs/LangRef.html Mon Oct 22 00:10:05 2007
@@ -2788,9 +2788,8 @@
at the location specified by the '<pointer>' operand.
The parser we will build uses a combination of Recursive Descent
+Parsing and Operator-Precedence
+Parsing to parse the Kaleidoscope language (the later for binary expression
+and the former for everything else). Before we get to parsing though, lets talk
+about the output of the parser: the Abstract Syntax Tree.
The AST for a program captures its behavior in a way that it is easy for
+later stages of the compiler (e.g. code generation) to interpret. We basically
+want one object for each construct in the language, and the AST should closely
+model the language. In Kaleidoscope, we have expressions, a prototype, and a
+function object. We'll start with expressions first:
+
+
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+ virtual ~ExprAST() {}
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+ double Val;
+public:
+ NumberExprAST(double val) : Val(val) {}
+};
+
+
+
+
The code above shows the definition of the base ExprAST class and one
+subclass which we use for numeric literals. The important thing about this is
+that the NumberExprAST class captures the numeric value of the literal in the
+class, so that later phases of the compiler can know what it is.
+
+
Right now we only create the AST, so there are no useful accessor methods on
+them. It would be very easy to add a virtual method to pretty print the code,
+for example. Here are the other expression AST node definitions that we'll use
+in the basic form of the Kaleidoscope language.
+
+
+
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+ std::string Name;
+public:
+ VariableExprAST(const std::string &name) : Name(name) {}
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+ char Op;
+ ExprAST *LHS, *RHS;
+public:
+ BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs)
+ : Op(op), LHS(lhs), RHS(rhs) {}
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+ std::string Callee;
+ std::vector<ExprAST*> Args;
+public:
+ CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+ : Callee(callee), Args(args) {}
+};
+
+
+
+
This is all (intentially) rather straight-forward: variables capture the
+variable name, binary operators capture their opcode (e.g. '+'), and calls
+capture a function name and list of argument expressions. One thing that is
+nice about our AST is that it captures the language features without talking
+about the syntax of the language. Note that there is no discussion about
+precedence of binary operators, lexical structure etc.
+
+
For our basic language, these are all of the expression nodes we'll define.
+because it doesn't have conditional control flow, it isn't turing complete:
+we'll fix that in a later installment. The two things we need next are a way
+to talk about the interface to a function, and a way to talk about functions
+themselves:
+
+
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its argument names as well as if it is an operator.
+class PrototypeAST {
+ std::string Name;
+ std::vector<std::string> Args;
+public:
+ PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+ : Name(name), Args(args) {}
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+ PrototypeAST *Proto;
+ ExprAST *Body;
+public:
+ FunctionAST(PrototypeAST *proto, ExprAST *body)
+ : Proto(proto), Body(body) {}
+};
+
+
+
+
In Kaleidoscope, functions are typed with just a count of their arguments.
+Since all values are double precision floating point, this fact doesn't need to
+be captured anywhere. In a more aggressive and realistic language, the
+"ExprAST" class would probably have a type field.
+
+
With this scaffolding, we can now talk about parsing expressions and function
+bodies in Kaleidoscope.
Now that we have an AST to build, we need to define the parser code to build
+it. The idea here is that we want to parse something like "x+y" (which is
+returned as three tokens by the lexer) into an AST that could be generated with
+calls like this:
+
+
+
+ ExprAST *X = new VariableExprAST("x");
+ ExprAST *Y = new VariableExprAST("y");
+ ExprAST *Result = new BinaryExprAST('+', X, Y);
+
+
+
+
In order to do this, we'll start by defining some basic helper routines:
+
+
+
+/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
+/// token the parser it looking at. getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+ return CurTok = gettok();
+}
+
+
+
+
+This implements a simple token buffer around the lexer. This allows
+us to look one token ahead at what the lexer is returning. Every function in
+our lexer will assume that CurTok is the current token that needs to be
+parsed.
+
+
Again, we define
+these with global variables: it would be better design to wrap the entire parser
+in a class and use instance variables for these.
+
+
+
+
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+
+
+
+The Error routines are simple helper routines that our parser will use
+to handle errors. The error recovery in our parser will not be the best and
+are not particular user-friendly, but it will be enough for our tutorial. These
+routines make it easier to handle errors in routines that have various return
+types: they always return null.
+
+
With these basic helper functions implemented, we can implement the first
+piece of our grammar: we'll start with numeric literals.
We start with numeric literals, because they are the simplest to process.
+For each production in our grammar, we'll define a function which parses that
+production. For numeric literals, we have:
+
+
+
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+ ExprAST *Result = new NumberExprAST(NumVal);
+ getNextToken(); // consume the number
+ return Result;
+}
+
+
+
+
This routine is very simple: it expects to be called when the current token
+is a tok_number token. It takes the current number value, creates
+a NumberExprAST node, advances the lexer to the next token, then
+returns.
+
+
There are some interesting aspects of this. The most important one is that
+this routine eats all of the tokens that correspond to the production, and
+returns the lexer buffer with the next token (which is not part of the grammar
+production) ready to go. This is a fairly standard way to go for recursive
+descent parsers. For a better example, the parenthesis operator is defined like
+this:
This function illustrates a number of interesting things about the parser:
+1) it shows how we use the Error routines. When called, this function expects
+that the current token is a '(' token, but after parsing the subexpression, it
+is possible that there is not a ')' waiting. For example, if the user types in
+"(4 x" instead of "(4)", the parser should emit an error. Because errors can
+occur, the parser needs a way to indicate that they happened: in our parser, we
+return null on an error.
+
+
Another interesting aspect of this function is that it uses recursion by
+calling ParseExpression (we will soon see that ParseExpression can call
+ParseParenExpr). This is powerful because it allows us to handle
+recursive grammars, and keeps each production very simple. Note that
+parenthesis do not cause construction of AST nodes themselves. While we could
+do this, the most important role of parens are to guide the parser and provide
+grouping. Once the parser constructs the AST, parens are not needed.
+
+
The next simple production is for handling variable references and function
+calls:
This routine follows the same style as the other routines (it expects to be
+called if the current token is a tok_identifier token). It also has
+recursion and error handling. One interesting aspect of this is that it uses
+look-ahead to determine if the current identifier is a stand alone
+variable reference or if it is a function call expression. It handles this by
+checking to see if the token after the identifier is a '(' token, and constructs
+either a VariableExprAST or CallExprAST node as appropriate.
+
+
+
Now that we have all of our simple expression parsing logic in place, we can
+define a helper function to wrap them up in a class. We call this class of
+expressions "primary" expressions, for reasons that will become more clear
+later. In order to parse a primary expression, we need to determine what sort
+of expression it is:
+
+
+
+/// primary
+/// ::= identifierexpr
+/// ::= numberexpr
+/// ::= parenexpr
+static ExprAST *ParsePrimary() {
+ switch (CurTok) {
+ default: return Error("unknown token when expecting an expression");
+ case tok_identifier: return ParseIdentifierExpr();
+ case tok_number: return ParseNumberExpr();
+ case '(': return ParseParenExpr();
+ }
+}
+
+
+
+
Now that you see the definition of this function, it makes it more obvious
+why we can assume the state of CurTok in the various functions. This uses
+look-ahead to determine which sort of expression is being inspected, and parses
+it with a function call.
+
+
Now that basic expressions are handled, we need to handle binary expressions,
+which are a bit more complex.
Binary expressions are significantly harder to parse because they are often
+ambiguous. For example, when given the string "x+y*z", the parser can choose
+to parse it as either "(x+y)*z" or "x+(y*z)". With common definitions from
+mathematics, we expect the later parse, because "*" (multiplication) has
+higher precedence than "+" (addition).
+
+
There are many ways to handle this, but an elegant and efficient way is to
+use Operator-Precedence
+Parsing. This parsing technique uses the precedence of binary operators to
+guide recursion. To start with, we need a table of precedences:
+
+
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+ if (!isascii(CurTok))
+ return -1;
+
+ // Make sure it's a declared binop.
+ int TokPrec = BinopPrecedence[CurTok];
+ if (TokPrec <= 0) return -1;
+ return TokPrec;
+}
+
+int main() {
+ // Install standard binary operators.
+ // 1 is lowest precedence.
+ BinopPrecedence['<'] = 10;
+ BinopPrecedence['+'] = 20;
+ BinopPrecedence['-'] = 20;
+ BinopPrecedence['*'] = 40; // highest.
+ ...
+}
+
+
+
+
For the basic form of Kaleidoscope, we will only support 4 binary operators
+(this can obviously be extended by you, the reader). The
+GetTokPrecedence function returns the precedence for the current token,
+or -1 if the token is not a binary operator. Having a map makes it easy to add
+new operators and makes it clear that the algorithm doesn't depend on the
+specific operators involved, but it would be easy enough to eliminate the map
+and do the comparisons in the GetTokPrecedence function.
+
+
With the helper above defined, we can now start parsing binary expressions.
+The basic idea of operator precedence parsing is to break down an expression
+with potentially ambiguous binary operators into pieces. Consider for example
+the expression "a+b+(c+d)*e*f+g". Operator precedence parsing considers this
+as a stream of primary expressions separated by binary operators. As such,
+it will first parse the leading primary expression "a", then it will see the
+pairs [+, b] [+, (c+d)] [*, e] [*, f] and [+, g]. Note that because parentheses
+are primary expressions that the binary expression parser doesn't need to worry
+about nested subexpressions like (c+d) at all.
+
+
+
+To start, an expression is a primary expression potentially followed by a
+sequence of [binop,primaryexpr] pairs:
ParseBinOpRHS is the function that parses the sequence of pairs for
+us. It takes a precedence and a pointer to an expression for the part parsed
+so far. Note that "x" is a perfectly valid expression: As such, "binoprhs" is
+allowed to be empty, in which case it returns the expression that is passed into
+it. In our example above, the code passes the expression for "a" into
+ParseBinOpRHS and the current token is "+".
+
+
The precedence value passed into ParseBinOpRHS indicates the
+minimal operator precedence that the function is allowed to eat. For
+example, if the current pair stream is [+, x] and ParseBinOpRHS is
+passed in a precedence of 40, it will not consume any tokens (because the
+precedence of '+' is only 20). With this in mind, ParseBinOpRHS starts
+with:
+
+
+
+/// binoprhs
+/// ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+ // If this is a binop, find its precedence.
+ while (1) {
+ int TokPrec = GetTokPrecedence();
+
+ // If this is a binop that binds at least as tightly as the current binop,
+ // consume it, otherwise we are done.
+ if (TokPrec < ExprPrec)
+ return LHS;
+
+
+
+
This code gets the precedence of the current token and checks to see if if is
+too low. Because we defined invalid tokens to have a precedence of -1, this
+check implicitly knows that the pair-stream ends when the token stream runs out
+of binary operators. If this check succeeds, we know that the token is a binary
+operator and that it will be included in this expression:
+
+
+
+ // Okay, we know this is a binop.
+ int BinOp = CurTok;
+ getNextToken(); // eat binop
+
+ // Parse the primary expression after the binary operator.
+ ExprAST *RHS = ParsePrimary();
+ if (!RHS) return 0;
+
+
+
+
As such, this code eats (and remembers) the binary operator and then parses
+the following primary expression. This builds up the whole pair, the first of
+which is [+, b] for the running example.
+
+
Now that we parsed the left-hand side of an expression and one pair of the
+RHS sequence, we have to decide which way the expression associates. In
+particular, we could have "(a+b) binop unparsed" or "a + (b binop unparsed)".
+To determine this, we look ahead at "binop" to determine its precedence and
+compare it to BinOp's precedence (which is '+' in this case):
+
+
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ int NextPrec = GetTokPrecedence();
+ if (TokPrec < NextPrec) {
+
+
+
+
If the precedence of the binop to the right of "RHS" is lower or equal to the
+precedence of our current operator, then we know that the parentheses associate
+as "(a+b) binop ...". In our example, since the next operator is "+" and so is
+our current one, we know that they have the same precedence. In this case we'll
+create the AST node for "a+b", and then continue parsing:
+
+
+
+ ... if body omitted ...
+ }
+
+ // Merge LHS/RHS.
+ LHS = new BinaryExprAST(BinOp, LHS, RHS);
+ } // loop around to the top of the while loop.
+}
+
+
+
+
In our example above, this will turn "a+b+" into "(a+b)" and execute the next
+iteration of the loop, with "+" as the current token. The code above will eat
+and remember it and parse "(c+d)" as the primary expression, which makes the
+current pair be [+, (c+d)]. It will then enter the 'if' above with "*" as the
+binop to the right of the primary. In this case, the precedence of "*" is
+higher than the precedence of "+" so the if condition will be entered.
+
+
The critical question left here is "how can the if condition parse the right
+hand side in full"? In particular, to build the AST correctly for our example,
+it needs to get all of "(c+d)*e*f" as the RHS expression variable. The code to
+do this is surprisingly simple (code from the above two blocks duplicated for
+context):
+
+
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ int NextPrec = GetTokPrecedence();
+ if (TokPrec < NextPrec) {
+ RHS = ParseBinOpRHS(TokPrec+1, RHS);
+ if (RHS == 0) return 0;
+ }
+ // Merge LHS/RHS.
+ LHS = new BinaryExprAST(BinOp, LHS, RHS);
+ } // loop around to the top of the while loop.
+}
+
+
+
+
At this point, we know that the binary operator to the RHS of our primary
+has higher precedence than the binop we are currently parsing. As such, we know
+that any sequence of pairs whose operators are all higher precedence than "+"
+should be parsed together and returned as "RHS". To do this, we recursively
+invoke the ParseBinOpRHS function specifying "TokPrec+1" as the minimum
+precedence required for it to continue. In our example above, this will cause
+it to return the AST node for "(c+d)*e*f" as RHS, which is then set as the RHS
+of the '+' expression.
+
+
Finally, on the next iteration of the while loop, the "+g" piece is parsed.
+and added to the AST. With this little bit of code (14 non-trivial lines), we
+correctly handle fully general binary expression parsing in a very elegant way.
+
+
+
This wraps up handling of expressions. At this point, we can point the
+parser at an arbitrary token stream and build an expression from them, stopping
+at the first token that is not part of the expression. Next up we need to
+handle function definitions etc.
+The first basic thing missing is that of function prototypes. In Kaleidoscope,
+these are used both for 'extern' function declarations as well as function body
+definitions. The code to do this is straight-forward and not very interesting
+(once you've survived expressions):
+
+
+
+
+/// prototype
+/// ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+ if (CurTok != tok_identifier)
+ return ErrorP("Expected function name in prototype");
+
+ std::string FnName = IdentifierStr;
+ getNextToken();
+
+ if (CurTok != '(')
+ return ErrorP("Expected '(' in prototype");
+
+ std::vector<std::string> ArgNames;
+ while (getNextToken() == tok_identifier)
+ ArgNames.push_back(IdentifierStr);
+ if (CurTok != ')')
+ return ErrorP("Expected ')' in prototype");
+
+ // success.
+ getNextToken(); // eat ')'.
+
+ return new PrototypeAST(FnName, ArgNames);
+}
+
+
+
+
Given this, a function definition is very simple, just a prototype plus
+and expression to implement the body:
In addition, we support 'extern' to declare functions like 'sin' and 'cos' as
+well as to support forward declaration of user functions. 'externs' are just
+prototypes with no body:
Finally, we'll also let the user type in arbitrary top-level expressions and
+evaluate them on the fly. We will handle this by defining anonymous nullary
+(zero argument) functions for them:
+
+
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+ if (ExprAST *E = ParseExpression()) {
+ // Make an anonymous proto.
+ PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+ return new FunctionAST(Proto, E);
+ }
+ return 0;
+}
+
+
+
+
Now that we have all the pieces, lets build a little driver that will let us
+actually execute this code we've built!
The driver for this simply invokes all of the parsing pieces with a top-level
+dispatch loop. There isn't much interesting here, so I'll just include the
+top-level loop. See below for full code in the "Top-Level
+Parsing" section.
+
+
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+ while (1) {
+ fprintf(stderr, "ready> ");
+ switch (CurTok) {
+ case tok_eof: return;
+ case ';': getNextToken(); break; // ignore top level semicolons.
+ case tok_def: HandleDefinition(); break;
+ case tok_extern: HandleExtern(); break;
+ default: HandleTopLevelExpression(); break;
+ }
+ }
+}
+
+
+
+
The most interesting part of this is that we ignore top-level semi colons.
+Why is this do you ask? The basic reason is that if you type "4 + 5" at the
+command line, the parser doesn't know that that is the end of what you will
+type. For example, on the next line you could type "def foo..." in which case
+4+5 is the end of a top-level expression. Alternatively you could type "* 6",
+which would continue the expression. Having top-level semicolons allows you to
+type "4+5;" and the parser will know you are done.
With just under 400 lines of commented code, we fully defined our minimal
+language, including a lexer, parser and AST builder. With this done, the
+executable will validate code and tell us if it is gramatically invalid. For
+example, here is a sample interaction:
+
+
+
+$ ./a.out
+ready> def foo(x y) x+foo(y, 4.0);
+ready> Parsed an function definition.
+ready> def foo(x y) x+y y;
+ready> Parsed an function definition.
+ready> Parsed a top-level expr
+ready> def foo(x y) x+y );
+ready> Parsed an function definition.
+ready> Error: unknown token when expecting an expression
+ready> extern sin(a);
+ready> Parsed an extern
+ready> ^D
+$
+
+
+
+
+Here is the full code. Note that it is fully self-contained: you don't even
+need LLVM for this. In the next installment, we
+will describe how to generate LLVM IR from the AST.
+
+
+
+// To build this:
+// g++ -g toy.cpp
+// ./a.out
+
+#include <cstdio>
+#include <string>
+#include <
+#include <vector>
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+ tok_eof = -1,
+
+ // commands
+ tok_def = -2, tok_extern = -3,
+
+ // primary
+ tok_identifier = -4, tok_number = -5,
+};
+
+static std::string IdentifierStr; // Filled in if tok_identifier
+static double NumVal; // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+ static int LastChar = ' ';
+
+ // Skip any whitespace.
+ while (isspace(LastChar))
+ LastChar = getchar();
+
+ if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+ IdentifierStr = LastChar;
+ while (isalnum((LastChar = getchar())))
+ IdentifierStr += LastChar;
+
+ if (IdentifierStr == "def") return tok_def;
+ if (IdentifierStr == "extern") return tok_extern;
+ return tok_identifier;
+ }
+
+ if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+
+ std::string NumStr;
+ do {
+ NumStr += LastChar;
+ LastChar = getchar();
+ } while (isdigit(LastChar) || LastChar == '.');
+
+ NumVal = strtod(NumStr.c_str(), 0);
+ return tok_number;
+ }
+
+ if (LastChar == '#') {
+ // Comment until end of line.
+ do LastChar = getchar();
+ while (LastChar != EOF && LastChar != '\n' & LastChar != '\r');
+
+ if (LastChar != EOF)
+ return gettok();
+ }
+
+ // Check for end of file. Don't eat the EOF.
+ if (LastChar == EOF)
+ return tok_eof;
+
+ // Otherwise, just return the character as its ascii value.
+ int ThisChar = LastChar;
+ LastChar = getchar();
+ return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+ virtual ~ExprAST() {}
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+ double Val;
+public:
+ NumberExprAST(double val) : Val(val) {}
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+ std::string Name;
+public:
+ VariableExprAST(const std::string &name) : Name(name) {}
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+ char Op;
+ ExprAST *LHS, *RHS;
+public:
+ BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs)
+ : Op(op), LHS(lhs), RHS(rhs) {}
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+ std::string Callee;
+ std::vector<ExprAST*> Args;
+public:
+ CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+ : Callee(callee), Args(args) {}
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its argument names as well as if it is an operator.
+class PrototypeAST {
+ std::string Name;
+ std::vector< Args;
+public:
+ PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+ : Name(name), Args(args) {}
+
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+ PrototypeAST *Proto;
+ ExprAST *Body;
+public:
+ FunctionAST(PrototypeAST *proto, ExprAST *body)
+ : Proto(proto), Body(body) {}
+
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current
+/// token the parser it looking at. getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+ return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+ if (!isascii(CurTok))
+ return -1;
+
+ // Make sure it's a declared binop.
+ int TokPrec = BinopPrecedence[CurTok];
+ if (TokPrec <= 0) return -1;
+ return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+/// ::= identifer
+/// ::= identifer '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+ std::string IdName = IdentifierStr;
+
+ getNextToken(); // eat identifer.
+
+ if (CurTok != '(') // Simple variable ref.
+ return new VariableExprAST(IdName);
+
+ // Call.
+ getNextToken(); // eat (
+ std::vector<ExprAST*> Args;
+ while (1) {
+ ExprAST *Arg = ParseExpression();
+ if (!Arg) return 0;
+ Args.push_back(Arg);
+
+ if (CurTok == ')') break;
+
+ if (CurTok != ',')
+ return Error("Expected ')'");
+ getNextToken();
+ }
+
+ // Eat the ')'.
+ getNextToken();
+
+ return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+ ExprAST *Result = new NumberExprAST(NumVal);
+ getNextToken(); // consume the number
+ return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+ getNextToken(); // eat (.
+ ExprAST *V = ParseExpression();
+ if (!V) return 0;
+
+ if (CurTok != ')')
+ return Error("expected ')'");
+ getNextToken(); // eat ).
+ return V;
+}
+
+/// primary
+/// ::= identifierexpr
+/// ::= numberexpr
+/// ::= parenexpr
+static ExprAST *ParsePrimary() {
+ switch (CurTok) {
+ default: return Error("unknown token when expecting an expression");
+ case tok_identifier: return ParseIdentifierExpr();
+ case tok_number: return ParseNumberExpr();
+ case '(': return ParseParenExpr();
+ }
+}
+
+/// binoprhs
+/// ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+ // If this is a binop, find its precedence.
+ while (1) {
+ int TokPrec = GetTokPrecedence();
+
+ // If this is a binop that binds at least as tightly as the current binop,
+ // consume it, otherwise we are done.
+ if (TokPrec < ExprPrec)
+ return LHS;
+
+ // Okay, we know this is a binop.
+ int BinOp = CurTok;
+ getNextToken(); // eat binop
+
+ // Parse the primary expression after the binary operator.
+ ExprAST *RHS = ParsePrimary();
+ if (!RHS) return 0;
+
+ // If BinOp binds less tightly with RHS than the operator after RHS, let
+ // the pending operator take RHS as its LHS.
+ int NextPrec = GetTokPrecedence();
+ if (TokPrec < NextPrec) {
+ RHS = ParseBinOpRHS(TokPrec+1, RHS);
+ if (RHS == 0) return 0;
+ }
+
+ // Merge LHS/RHS.
+ LHS = new BinaryExprAST(BinOp, LHS, RHS);
+ }
+}
+
+/// expression
+/// ::= primary binoprhs
+///
+static ExprAST *ParseExpression() {
+ ExprAST *LHS = ParsePrimary();
+ if (!LHS) return 0;
+
+ return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+/// ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+ if (CurTok != tok_identifier)
+ return ErrorP("Expected function name in prototype");
+
+ std::string FnName = IdentifierStr;
+ getNextToken();
+
+ if (CurTok != '(')
+ return ErrorP("Expected '(' in prototype");
+
+ std::vector<std::string> ArgNames;
+ while (getNextToken() == tok_identifier)
+ ArgNames.push_back(IdentifierStr);
+ if (CurTok != ')')
+ return ErrorP("Expected ')' in prototype");
+
+ // success.
+ getNextToken(); // eat ')'.
+
+ return new PrototypeAST(FnName, ArgNames);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+ getNextToken(); // eat def.
+ PrototypeAST *Proto = ParsePrototype();
+ if (Proto == 0) return 0;
+
+ if (ExprAST *E = ParseExpression())
+ return new FunctionAST(Proto, E);
+ return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+ if (ExprAST *E = ParseExpression()) {
+ // Make an anonymous proto.
+ PrototypeAST *Proto = new PrototypeAST("", std::vector<());
+ return new FunctionAST(Proto, E);
+ }
+ return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+ getNextToken(); // eat extern.
+ return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing
+//===----------------------------------------------------------------------===//
+
+static void HandleDefinition() {
+ if (FunctionAST *F = ParseDefinition()) {
+ fprintf(stderr, "Parsed a function definition.\n");
+ } else {
+ // Skip token for error recovery.
+ getNextToken();
+ }
+}
+
+static void HandleExtern() {
+ if (PrototypeAST *P = ParseExtern()) {
+ fprintf(stderr, "Parsed an extern\n");
+ } else {
+ // Skip token for error recovery.
+ getNextToken();
+ }
+}
+
+static void HandleTopLevelExpression() {
+ // Evaluate a top level expression into an anonymous function.
+ if (FunctionAST *F = ParseTopLevelExpr()) {
+ fprintf(stderr, "Parsed a top-level expr\n");
+ } else {
+ // Skip token for error recovery.
+ getNextToken();
+ }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+ while (1) {
+ fprintf(stderr, "ready> ");
+ switch (CurTok) {
+ case tok_eof: return;
+ case ';': getNextToken(); break; // ignore top level semicolons.
+ case tok_def: HandleDefinition(); break;
+ case tok_extern: HandleExtern(); break;
+ default: HandleTopLevelExpression(); break;
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+ // Install standard binary operators.
+ // 1 is lowest precedence.
+ BinopPrecedence['<'] = 10;
+ BinopPrecedence['+'] = 20;
+ BinopPrecedence['-'] = 20;
+ BinopPrecedence['*'] = 40; // highest.
+
+ // Prime the first token.
+ fprintf(stderr, "ready> ");
+ getNextToken();
+
+ MainLoop();
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+ Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date: 2007-10-17 11:05:13 -0700 (Wed, 17 Oct 2007) $
+
+
+
Modified: llvm/trunk/docs/tutorial/index.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/index.html?rev=43218&r1=43217&r2=43218&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/index.html (original)
+++ llvm/trunk/docs/tutorial/index.html Mon Oct 22 01:34:15 2007
@@ -28,7 +28,7 @@
For starters, lets consider a relatively straightforward function that takes three integer parameters and returns an arithmetic combination of them. This is nice and simple, especially since it involves no control flow:
Added: llvm/trunk/docs/tutorial/Tutorial1.tar.bz2
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/Tutorial1.tar.bz2?rev=43219&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/docs/tutorial/Tutorial1.tar.bz2
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: llvm/trunk/docs/tutorial/Tutorial1.zip
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/Tutorial1.zip?rev=43219&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/docs/tutorial/Tutorial1.zip
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
From resistor at mac.com Mon Oct 22 01:48:29 2007
From: resistor at mac.com (Owen Anderson)
Date: Mon, 22 Oct 2007 06:48:29 -0000
Subject: [llvm-commits] [llvm] r43220 -
/llvm/trunk/docs/tutorial/LangImpl2.html
Message-ID: <200710220648.l9M6mT3D007251@zion.cs.uiuc.edu>
Author: resistor
Date: Mon Oct 22 01:48:28 2007
New Revision: 43220
URL: http://llvm.org/viewvc/llvm-project?rev=43220&view=rev
Log:
Fix a few typos I noticed.
Modified:
llvm/trunk/docs/tutorial/LangImpl2.html
Modified: llvm/trunk/docs/tutorial/LangImpl2.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl2.html?rev=43220&r1=43219&r2=43220&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl2.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl2.html Mon Oct 22 01:48:28 2007
@@ -118,7 +118,7 @@
precedence of binary operators, lexical structure etc.
For our basic language, these are all of the expression nodes we'll define.
-because it doesn't have conditional control flow, it isn't turing complete:
+Because it doesn't have conditional control flow, it isn't Turing-complete;
we'll fix that in a later installment. The two things we need next are a way
to talk about the interface to a function, and a way to talk about functions
themselves:
@@ -195,9 +195,7 @@
our lexer will assume that CurTok is the current token that needs to be
parsed.
-
Again, we define
-these with global variables: it would be better design to wrap the entire parser
-in a class and use instance variables for these.
+
Again, we define these with global variables; it would be better design to wrap the entire parser in a class and use instance variables for these.
@@ -282,7 +280,7 @@
return null on an error.
Another interesting aspect of this function is that it uses recursion by
-calling ParseExpression (we will soon see that ParseExpression can call
+calling ParseExpression (we will soon see that ParseExpression can call
ParseParenExpr). This is powerful because it allows us to handle
recursive grammars, and keeps each production very simple. Note that
parenthesis do not cause construction of AST nodes themselves. While we could
@@ -716,7 +714,7 @@
The most interesting part of this is that we ignore top-level semi colons.
-Why is this do you ask? The basic reason is that if you type "4 + 5" at the
+Why is this, you ask? The basic reason is that if you type "4 + 5" at the
command line, the parser doesn't know that that is the end of what you will
type. For example, on the next line you could type "def foo..." in which case
4+5 is the end of a top-level expression. Alternatively you could type "* 6",
From sabre at nondot.org Mon Oct 22 02:01:42 2007
From: sabre at nondot.org (Chris Lattner)
Date: Mon, 22 Oct 2007 07:01:42 -0000
Subject: [llvm-commits] [llvm] r43221 - in /llvm/trunk/docs/tutorial:
LangImpl3.html index.html
Message-ID: <200710220701.l9M71h3d008003@zion.cs.uiuc.edu>
Author: lattner
Date: Mon Oct 22 02:01:42 2007
New Revision: 43221
URL: http://llvm.org/viewvc/llvm-project?rev=43221&view=rev
Log:
start of chapter 3
Added:
llvm/trunk/docs/tutorial/LangImpl3.html
Modified:
llvm/trunk/docs/tutorial/index.html
Added: llvm/trunk/docs/tutorial/LangImpl3.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl3.html?rev=43221&view=auto
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl3.html (added)
+++ llvm/trunk/docs/tutorial/LangImpl3.html Mon Oct 22 02:01:42 2007
@@ -0,0 +1,787 @@
+
+
+
+
+ Kaleidoscope: Implementing code generation to LLVM IR
+
+
+
+
+
+
+
+
Welcome to part 3 of the "Implementing a language with
+LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree built in Chapter 2 into LLVM IR.
+This will teach you a little bit about how LLVM does things, as well as
+demonstrate how easy it is to use. It's much more work to build a lexer and
+parser than it is to generate LLVM IR code.
+
+In order to generate LLVM IR, we want some simple setup to get started. First,
+we define virtual codegen methods in each AST class:
+
+
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+ virtual ~ExprAST() {}
+ virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+ double Val;
+public:
+ NumberExprAST(double val) : Val(val) {}
+ virtual Value *Codegen();
+};
+...
+
+
+
+
"Value" is the class used to represent a "register" in LLVM. The Codegen()
+method says to emit IR for that AST node and all things it depends on. The
+second thing we want is an "Error" method like we used for parser, which will
+be used to report errors found during code generation (for example, use of an
+undeclared parameter):
The static variables will be used during code generation. TheModule
+is the LLVM construct that contains all of the functions and global variables in
+a chunk of code. In many ways, it is the top-level structure that the LLVM IR
+uses to contain code.
+
+
The Builder object is a helper object that makes it easy to generate
+LLVM instructions. The Builder keeps track of the current place to
+insert instructions and has methods to create new instructions.
+
+
The NamedValues map keeps track of which values are defined in the
+current scope and what their LLVM representation is. In this form of
+Kaleidoscope, the only things that can be referenced are function parameters.
+As such, function parameters will be in this map when generating code for their
+function body.
+
+
+With these basics in place, we can start talking about how to generate code for
+each expression. Note that this assumes that the Builder has been set
+up to generate code into something. For now, we'll assume that this
+has already been done, and we'll just use it to emit code.
+
Generating LLVM code for expression nodes is very straight-forward: less
+than 45 lines of commented code for all four of our expression nodes. First,
+we'll do numeric literals:
In the LLVM IR, numeric constants are represented with the ConstantFP class,
+which holds the numeric value in an APFloat internally (APFloat has the
+capability of holding floating point constants of arbitrary precision). This
+code basically just creates and returns a ConstantFP. Note that in the LLVM IR
+that constants are all uniqued together and shared. For this reason, the API
+uses "the foo::get(...)" idiom instead of a "create" method or "new foo".
+
+
+
+Value *VariableExprAST::Codegen() {
+ // Look this variable up in the function.
+ Value *V = NamedValues[Name];
+ return V ? V : ErrorV("Unknown variable name");
+}
+
+
+
+
References to variables is also quite simple here. In our system, we assume
+that the variable has already been emited somewhere and its value is available.
+In practice, the only values in the NamedValues map will be arguments. This
+code simply checks to see that the specified name is in the map (if not, an
+unknown variable is being referenced) and returns the value for it.
+
+
+
+Value *BinaryExprAST::Codegen() {
+ Value *L = LHS->Codegen();
+ Value *R = RHS->Codegen();
+ if (L == 0 || R == 0) return 0;
+
+ switch (Op) {
+ case '+': return Builder.CreateAdd(L, R, "addtmp");
+ case '-': return Builder.CreateSub(L, R, "subtmp");
+ case '*': return Builder.CreateMul(L, R, "multmp");
+ case '<':
+ L = Builder.CreateFCmpULT(L, R, "multmp");
+ // Convert bool 0/1 to double 0.0 or 1.0
+ return Builder.CreateUIToFP(L, Type::DoubleTy, "booltmp");
+ default: return ErrorV("invalid binary operator");
+ }
+}
+
+
+
+
+
+
+
+Value *CallExprAST::Codegen() {
+ // Look up the name in the global module table.
+ Function *CalleeF = TheModule->getFunction(Callee);
+ if (CalleeF == 0)
+ return ErrorV("Unknown function referenced");
+
+ // If argument mismatch error.
+ if (CalleeF->arg_size() != Args.size())
+ return ErrorV("Incorrect # arguments passed");
+
+ std::vector<Value*> ArgsV;
+ for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+ ArgsV.push_back(Args[i]->Codegen());
+ if (ArgsV.back() == 0) return 0;
+ }
+
+ return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
From clattner at apple.com Mon Oct 22 11:35:47 2007
From: clattner at apple.com (Chris Lattner)
Date: Mon, 22 Oct 2007 09:35:47 -0700
Subject: [llvm-commits] [llvm] r43191 - in /llvm/trunk:
lib/CodeGen/BranchFolding.cpp test/CFrontend/2007-10-15-VoidPtr.c
test/Transforms/BranchFolding/
test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll
In-Reply-To: <5821B330-4E5F-451E-A751-9318E2AA1728@apple.com>
References: <200710192109.l9JL9uN2008645@zion.cs.uiuc.edu>
<200710201053.59713.baldrick@free.fr>
<5821B330-4E5F-451E-A751-9318E2AA1728@apple.com>
Message-ID: <785D1020-A93A-4605-A152-B6D768AB26A9@apple.com>
On Oct 20, 2007, at 11:49 AM, Dale Johannesen wrote:
> On Oct 20, 2007, at 10:29 AM, Chris Lattner wrote:
>> This is just a really ugly compatibility hack. Apparently GCC
>> doesn't do cross jumping of inline asm statements as much as we do,
>> and we've hit a significant body of code that depends on this not
>> happening.
>>
>> The code in question is clearly broken, but at this point, I think
>> it's important for LLVM to be "bug compatible" with GCC if it doesn't
>> cost much. In this case, we only lose tail merging of inline asm
>> statements, which impacts code size but not performance.
>
> Bill's change is not clearly the wrong thing. People using asm's are
> generally trying to do something they can't do more
> straightforwardly; they know what code they want the compiler to
> produce, and regard writing asm's as an exercise in coercing the
> compiler into producing it. (They should be writing in assembler
> IMO, but gcc decided years ago to support asm, and we're all stuck
> with it now.) Before moving to llvm, I was maintaining gcc for some
> time; I never had anybody complain their asm's were not optimized
> enough, and I got many complaints that asm's were optimized too much.
I'm sympathetic to that viewpoint, but it can't be made to work.
In this particular case, the user is using pairs of asms and
expecting them to come out in the .s file in the same order as they
wrote. There is no way the compiler can reasonably guarantee this to
work: it would prevent all block reordering and control flow
optimizations etc. Turning off tail merging happens to fix the cases
that are failing, but it's just a band-aid, not a solution.
-Chris
From sabre at nondot.org Mon Oct 22 11:44:32 2007
From: sabre at nondot.org (Chris Lattner)
Date: Mon, 22 Oct 2007 16:44:32 -0000
Subject: [llvm-commits] [llvm] r43222 -
/llvm/trunk/docs/tutorial/LangImpl2.html
Message-ID: <200710221644.l9MGiWBY016176@zion.cs.uiuc.edu>
Author: lattner
Date: Mon Oct 22 11:44:31 2007
New Revision: 43222
URL: http://llvm.org/viewvc/llvm-project?rev=43222&view=rev
Log:
fit in 80 cols :)
Modified:
llvm/trunk/docs/tutorial/LangImpl2.html
Modified: llvm/trunk/docs/tutorial/LangImpl2.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl2.html?rev=43222&r1=43221&r2=43222&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl2.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl2.html Mon Oct 22 11:44:31 2007
@@ -195,7 +195,8 @@
our lexer will assume that CurTok is the current token that needs to be
parsed.
-
Again, we define these with global variables; it would be better design to wrap the entire parser in a class and use instance variables for these.
+
Again, we define these with global variables; it would be better design to
+wrap the entire parser in a class and use instance variables for these.
From clattner at apple.com Mon Oct 22 11:45:24 2007
From: clattner at apple.com (Chris Lattner)
Date: Mon, 22 Oct 2007 09:45:24 -0700
Subject: [llvm-commits] [llvm] r43171 -
/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
In-Reply-To: <200710211934.13010.baldrick@free.fr>
References: <200710190446.l9J4kkXp018139@zion.cs.uiuc.edu>
<200710191031.52183.baldrick@free.fr>
<28072F1F-0B36-41E5-BE95-1F80A196B132@apple.com>
<200710211934.13010.baldrick@free.fr>
Message-ID:
On Oct 21, 2007, at 10:34 AM, Duncan Sands wrote:
> Hi Chris,
>
>> Assuming an expansion from i64 to 2x i32, the code above will work
>> for sextinreg amounts between 1 and 32. For greater amounts, the top
>> part should get a sextinreg, and the bottom part should or togther
>> the top and bottom shifted parts, similar to a expanded shift.
>
> not sure why you need to do something complicated for the bottom
> part. Consider
> sextinreg from i63 to i64. The operand expands to 2 x i32: Lo and
> Hi. It seems
> to me that nothing needs to be done to Lo, while Hi needs to
> undergo an sextinreg
> from i31 to i32.
Ah, you're right!
-Chris
From dalej at apple.com Mon Oct 22 13:06:39 2007
From: dalej at apple.com (Dale Johannesen)
Date: Mon, 22 Oct 2007 11:06:39 -0700
Subject: [llvm-commits] [llvm] r43191 - in /llvm/trunk:
lib/CodeGen/BranchFolding.cpp test/CFrontend/2007-10-15-VoidPtr.c
test/Transforms/BranchFolding/
test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll
In-Reply-To: <785D1020-A93A-4605-A152-B6D768AB26A9@apple.com>
References: <200710192109.l9JL9uN2008645@zion.cs.uiuc.edu>
<200710201053.59713.baldrick@free.fr>
<5821B330-4E5F-451E-A751-9318E2AA1728@apple.com>
<785D1020-A93A-4605-A152-B6D768AB26A9@apple.com>
Message-ID:
On Oct 22, 2007, at 9:35 AM, Chris Lattner wrote:
> On Oct 20, 2007, at 11:49 AM, Dale Johannesen wrote:
>> On Oct 20, 2007, at 10:29 AM, Chris Lattner wrote:
>>> This is just a really ugly compatibility hack. Apparently GCC
>>> doesn't do cross jumping of inline asm statements as much as we do,
>>> and we've hit a significant body of code that depends on this not
>>> happening.
>>>
>>> The code in question is clearly broken, but at this point, I think
>>> it's important for LLVM to be "bug compatible" with GCC if it
>>> doesn't
>>> cost much. In this case, we only lose tail merging of inline asm
>>> statements, which impacts code size but not performance.
>>
>> Bill's change is not clearly the wrong thing. People using asm's are
>> generally trying to do something they can't do more
>> straightforwardly; they know what code they want the compiler to
>> produce, and regard writing asm's as an exercise in coercing the
>> compiler into producing it. (They should be writing in assembler
>> IMO, but gcc decided years ago to support asm, and we're all stuck
>> with it now.) Before moving to llvm, I was maintaining gcc for some
>> time; I never had anybody complain their asm's were not optimized
>> enough, and I got many complaints that asm's were optimized too much.
>
> I'm sympathetic to that viewpoint, but it can't be made to work.
>
> In this particular case, the user is using pairs of asms and
> expecting them to come out in the .s file in the same order as they
> wrote. There is no way the compiler can reasonably guarantee this to
> work: it would prevent all block reordering and control flow
> optimizations etc.
Yeah, turning all that off is a bit much. (I did, however, get the
question
"how do I prevent the compiler from rearranging my code" more than once
from the asm users. The current answer is "you don't", but this is
something
that certain people want.)
From baldrick at free.fr Mon Oct 22 13:26:21 2007
From: baldrick at free.fr (Duncan Sands)
Date: Mon, 22 Oct 2007 18:26:21 -0000
Subject: [llvm-commits] [llvm] r43223 -
/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
Message-ID: <200710221826.l9MIQLAj021352@zion.cs.uiuc.edu>
Author: baldrick
Date: Mon Oct 22 13:26:21 2007
New Revision: 43223
URL: http://llvm.org/viewvc/llvm-project?rev=43223&view=rev
Log:
Fix up the logic for result expanding the various extension
operations so they work right for integers with funky
bit-widths. For example, consider extending i48 to i64
on a 32 bit machine. The i64 result is expanded to 2 x i32.
We know that the i48 operand will be promoted to i64, then
also expanded to 2 x i32. If we had the expanded promoted
operand to hand, then expanding the result would be trivial.
Unfortunately at this stage we can only get hold of the
promoted operand. So instead we kind of hand-expand, doing
explicit shifting and truncating to get the top and bottom
halves of the i64 operand into 2 x i32, which are then used
to expand the result. This is harmless, because when the
promoted operand is finally expanded all this bit fiddling
turns into trivial operations which are eliminated either
by the expansion code itself or the DAG combiner.
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp?rev=43223&r1=43222&r2=43223&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp Mon Oct 22 13:26:21 2007
@@ -133,7 +133,8 @@
// Common routines.
SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT);
SDOperand HandleMemIntrinsic(SDNode *N);
-
+ void SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+
// Result Promotion.
void PromoteResult(SDNode *N, unsigned ResNo);
SDOperand PromoteResult_UNDEF(SDNode *N);
@@ -498,6 +499,20 @@
return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
}
+/// SplitOp - Return the lower and upper halves of Op's bits in a value type
+/// half the size of Op's.
+void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
+ unsigned NVTBits = MVT::getSizeInBits(Op.getValueType())/2;
+ assert(MVT::getSizeInBits(Op.getValueType()) == 2*NVTBits &&
+ "Cannot split odd sized integer type");
+ MVT::ValueType NVT = MVT::getIntegerType(NVTBits);
+ Lo = DAG.getNode(ISD::TRUNCATE, NVT, Op);
+ Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op,
+ DAG.getConstant(NVTBits, TLI.getShiftAmountTy()));
+ Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
+}
+
+
//===----------------------------------------------------------------------===//
// Result Promotion
//===----------------------------------------------------------------------===//
@@ -805,33 +820,77 @@
Hi = N->getOperand(1);
}
-void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
+void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
-
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- // The low part is any extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, N->getOperand(0));
- Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined.
+ SDOperand Op = N->getOperand(0);
+ if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+ // The low part is any extension of the input (which degenerates to a copy).
+ Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op);
+ Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined.
+ } else {
+ // For example, extension of an i48 to an i64. The operand type necessarily
+ // promotes to the result type, so will end up being expanded too.
+ assert(getTypeAction(Op.getValueType()) == Promote &&
+ "Don't know how to expand this result!");
+ SDOperand Res = GetPromotedOp(Op);
+ assert(Res.getValueType() == N->getValueType(0) &&
+ "Operand over promoted?");
+ // Split the promoted operand. This will simplify when it is expanded.
+ SplitOp(Res, Lo, Hi);
+ }
}
void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- // The low part is zero extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
- Hi = DAG.getConstant(0, NVT); // The high part is just a zero.
+ SDOperand Op = N->getOperand(0);
+ if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+ // The low part is zero extension of the input (which degenerates to a copy).
+ Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
+ Hi = DAG.getConstant(0, NVT); // The high part is just a zero.
+ } else {
+ // For example, extension of an i48 to an i64. The operand type necessarily
+ // promotes to the result type, so will end up being expanded too.
+ assert(getTypeAction(Op.getValueType()) == Promote &&
+ "Don't know how to expand this result!");
+ SDOperand Res = GetPromotedOp(Op);
+ assert(Res.getValueType() == N->getValueType(0) &&
+ "Operand over promoted?");
+ // Split the promoted operand. This will simplify when it is expanded.
+ SplitOp(Res, Lo, Hi);
+ unsigned ExcessBits =
+ MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+ Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerType(ExcessBits));
+ }
}
void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- // The low part is sign extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
-
- // The high part is obtained by SRA'ing all but one of the bits of low part.
- unsigned LoSize = MVT::getSizeInBits(NVT);
- Hi = DAG.getNode(ISD::SRA, NVT, Lo,
- DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+ SDOperand Op = N->getOperand(0);
+ if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(NVT)) {
+ // The low part is sign extension of the input (which degenerates to a copy).
+ Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
+ // The high part is obtained by SRA'ing all but one of the bits of low part.
+ unsigned LoSize = MVT::getSizeInBits(NVT);
+ Hi = DAG.getNode(ISD::SRA, NVT, Lo,
+ DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+ } else {
+ // For example, extension of an i48 to an i64. The operand type necessarily
+ // promotes to the result type, so will end up being expanded too.
+ assert(getTypeAction(Op.getValueType()) == Promote &&
+ "Don't know how to expand this result!");
+ SDOperand Res = GetPromotedOp(Op);
+ assert(Res.getValueType() == N->getValueType(0) &&
+ "Operand over promoted?");
+ // Split the promoted operand. This will simplify when it is expanded.
+ SplitOp(Res, Lo, Hi);
+ unsigned ExcessBits =
+ MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+ Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+ DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+ }
}
void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
@@ -844,18 +903,27 @@
void DAGTypeLegalizer::
ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
GetExpandedOp(N->getOperand(0), Lo, Hi);
-
- // sext_inreg the low part if needed.
- Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
- N->getOperand(1));
-
- // The high part gets the sign extension from the lo-part. This handles
- // things like sextinreg V:i64 from i8.
- Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
- DAG.getConstant(MVT::getSizeInBits(Hi.getValueType())-1,
- TLI.getShiftAmountTy()));
-}
+ MVT::ValueType EVT = N->getOperand(1).getValueType();
+ if (MVT::getSizeInBits(EVT) <= MVT::getSizeInBits(Lo.getValueType())) {
+ // sext_inreg the low part if needed.
+ Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
+ N->getOperand(1));
+
+ // The high part gets the sign extension from the lo-part. This handles
+ // things like sextinreg V:i64 from i8.
+ Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
+ DAG.getConstant(MVT::getSizeInBits(Hi.getValueType())-1,
+ TLI.getShiftAmountTy()));
+ } else {
+ // For example, extension of an i48 to an i64. Leave the low part alone,
+ // sext_inreg the high part.
+ unsigned ExcessBits =
+ MVT::getSizeInBits(EVT) - MVT::getSizeInBits(Lo.getValueType());
+ Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+ DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+ }
+}
void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
SDOperand &Lo, SDOperand &Hi) {
From djg at cray.com Mon Oct 22 13:31:59 2007
From: djg at cray.com (Dan Gohman)
Date: Mon, 22 Oct 2007 18:31:59 -0000
Subject: [llvm-commits] [llvm] r43224 - in /llvm/trunk:
include/llvm/Analysis/ScalarEvolution.h
include/llvm/Analysis/ScalarEvolutionExpander.h
include/llvm/Analysis/ScalarEvolutionExpressions.h
lib/Analysis/ScalarEvolution.cpp lib/Analysis/ScalarEvolutionExpander.cpp
lib/Transforms/Scalar/IndVarSimplify.cpp
lib/Transforms/Scalar/LoopStrengthReduce.cpp
Message-ID: <200710221831.l9MIVxcm021599@zion.cs.uiuc.edu>
Author: djg
Date: Mon Oct 22 13:31:58 2007
New Revision: 43224
URL: http://llvm.org/viewvc/llvm-project?rev=43224&view=rev
Log:
Move the SCEV object factors from being static members of the individual
SCEV subclasses to being non-static member functions of the ScalarEvolution
class.
Modified:
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Mon Oct 22 13:31:58 2007
@@ -27,12 +27,15 @@
#include
namespace llvm {
+ class APInt;
+ class ConstantInt;
class Instruction;
class Type;
class ConstantRange;
class Loop;
class LoopInfo;
class SCEVHandle;
+ class ScalarEvolution;
/// SCEV - This class represent an analyzed expression in the program. These
/// are reference counted opaque objects that the client is not allowed to
@@ -56,16 +59,6 @@
public:
explicit SCEV(unsigned SCEVTy) : SCEVType(SCEVTy), RefCount(0) {}
- /// getNegativeSCEV - Return the SCEV object corresponding to -V.
- ///
- static SCEVHandle getNegativeSCEV(const SCEVHandle &V);
-
- /// getMinusSCEV - Return LHS-RHS.
- ///
- static SCEVHandle getMinusSCEV(const SCEVHandle &LHS,
- const SCEVHandle &RHS);
-
-
unsigned getSCEVType() const { return SCEVType; }
/// getValueRange - Return the tightest constant bounds that this value is
@@ -97,7 +90,8 @@
/// returns itself.
virtual SCEVHandle
replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const = 0;
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const = 0;
/// print - Print out the internal representation of this scalar to the
/// specified stream. This should really only be used for debugging
@@ -131,7 +125,8 @@
void print(std::ostream *OS) const { if (OS) print(*OS); }
virtual SCEVHandle
replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const;
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCouldNotCompute *S) { return true; }
@@ -204,6 +199,58 @@
/// specified expression.
SCEVHandle getSCEV(Value *V) const;
+ SCEVHandle getConstant(ConstantInt *V);
+ SCEVHandle getConstant(const APInt& Val);
+ SCEVHandle getTruncateExpr(const SCEVHandle &Op, const Type *Ty);
+ SCEVHandle getZeroExtendExpr(const SCEVHandle &Op, const Type *Ty);
+ SCEVHandle getSignExtendExpr(const SCEVHandle &Op, const Type *Ty);
+ SCEVHandle getAddExpr(std::vector &Ops);
+ SCEVHandle getAddExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ std::vector Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ return getAddExpr(Ops);
+ }
+ SCEVHandle getAddExpr(const SCEVHandle &Op0, const SCEVHandle &Op1,
+ const SCEVHandle &Op2) {
+ std::vector Ops;
+ Ops.push_back(Op0);
+ Ops.push_back(Op1);
+ Ops.push_back(Op2);
+ return getAddExpr(Ops);
+ }
+ SCEVHandle getMulExpr(std::vector &Ops);
+ SCEVHandle getMulExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ std::vector Ops;
+ Ops.push_back(LHS);
+ Ops.push_back(RHS);
+ return getMulExpr(Ops);
+ }
+ SCEVHandle getSDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
+ SCEVHandle getAddRecExpr(const SCEVHandle &Start, const SCEVHandle &Step,
+ const Loop *L);
+ SCEVHandle getAddRecExpr(std::vector &Operands,
+ const Loop *L);
+ SCEVHandle getAddRecExpr(const std::vector &Operands,
+ const Loop *L) {
+ std::vector NewOp(Operands);
+ return getAddRecExpr(NewOp, L);
+ }
+ SCEVHandle getUnknown(Value *V);
+
+ /// getNegativeSCEV - Return the SCEV object corresponding to -V.
+ ///
+ SCEVHandle getNegativeSCEV(const SCEVHandle &V);
+
+ /// getMinusSCEV - Return LHS-RHS.
+ ///
+ SCEVHandle getMinusSCEV(const SCEVHandle &LHS,
+ const SCEVHandle &RHS);
+
+ /// getIntegerSCEV - Given an integer or FP type, create a constant for the
+ /// specified signed integer value and return a SCEV for the constant.
+ SCEVHandle getIntegerSCEV(int Val, const Type *Ty);
+
/// hasSCEV - Return true if the SCEV for this value has already been
/// computed.
bool hasSCEV(Value *V) const;
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Mon Oct 22 13:31:58 2007
@@ -61,8 +61,8 @@
/// starts at zero and steps by one on each iteration.
Value *getOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty){
assert(Ty->isInteger() && "Can only insert integer induction variables!");
- SCEVHandle H = SCEVAddRecExpr::get(SCEVUnknown::getIntegerSCEV(0, Ty),
- SCEVUnknown::getIntegerSCEV(1, Ty), L);
+ SCEVHandle H = SE.getAddRecExpr(SE.getIntegerSCEV(0, Ty),
+ SE.getIntegerSCEV(1, Ty), L);
return expand(H);
}
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h Mon Oct 22 13:31:58 2007
@@ -32,16 +32,13 @@
/// SCEVConstant - This class represents a constant integer value.
///
class SCEVConstant : public SCEV {
+ friend class ScalarEvolution;
+
ConstantInt *V;
explicit SCEVConstant(ConstantInt *v) : SCEV(scConstant), V(v) {}
virtual ~SCEVConstant();
public:
- /// get method - This just gets and returns a new SCEVConstant object.
- ///
- static SCEVHandle get(ConstantInt *V);
- static SCEVHandle get(const APInt& Val);
-
ConstantInt *getValue() const { return V; }
/// getValueRange - Return the tightest constant bounds that this value is
@@ -59,7 +56,8 @@
virtual const Type *getType() const;
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
return this;
}
@@ -78,15 +76,13 @@
/// to a smaller integer value.
///
class SCEVTruncateExpr : public SCEV {
+ friend class ScalarEvolution;
+
SCEVHandle Op;
const Type *Ty;
SCEVTruncateExpr(const SCEVHandle &op, const Type *ty);
virtual ~SCEVTruncateExpr();
public:
- /// get method - This just gets and returns a new SCEVTruncate object
- ///
- static SCEVHandle get(const SCEVHandle &Op, const Type *Ty);
-
const SCEVHandle &getOperand() const { return Op; }
virtual const Type *getType() const { return Ty; }
@@ -99,11 +95,12 @@
}
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
- SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc);
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
+ SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H == Op)
return this;
- return get(H, Ty);
+ return SE.getTruncateExpr(H, Ty);
}
/// getValueRange - Return the tightest constant bounds that this value is
@@ -125,15 +122,13 @@
/// integer value to a larger integer value.
///
class SCEVZeroExtendExpr : public SCEV {
+ friend class ScalarEvolution;
+
SCEVHandle Op;
const Type *Ty;
SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty);
virtual ~SCEVZeroExtendExpr();
public:
- /// get method - This just gets and returns a new SCEVZeroExtend object
- ///
- static SCEVHandle get(const SCEVHandle &Op, const Type *Ty);
-
const SCEVHandle &getOperand() const { return Op; }
virtual const Type *getType() const { return Ty; }
@@ -150,11 +145,12 @@
virtual ConstantRange getValueRange() const;
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
- SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc);
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
+ SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H == Op)
return this;
- return get(H, Ty);
+ return SE.getZeroExtendExpr(H, Ty);
}
virtual void print(std::ostream &OS) const;
@@ -172,15 +168,13 @@
/// integer value to a larger integer value.
///
class SCEVSignExtendExpr : public SCEV {
+ friend class ScalarEvolution;
+
SCEVHandle Op;
const Type *Ty;
SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty);
virtual ~SCEVSignExtendExpr();
public:
- /// get method - This just gets and returns a new SCEVSignExtend object
- ///
- static SCEVHandle get(const SCEVHandle &Op, const Type *Ty);
-
const SCEVHandle &getOperand() const { return Op; }
virtual const Type *getType() const { return Ty; }
@@ -197,11 +191,12 @@
virtual ConstantRange getValueRange() const;
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
- SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc);
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
+ SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H == Op)
return this;
- return get(H, Ty);
+ return SE.getSignExtendExpr(H, Ty);
}
virtual void print(std::ostream &OS) const;
@@ -220,6 +215,8 @@
/// operators.
///
class SCEVCommutativeExpr : public SCEV {
+ friend class ScalarEvolution;
+
std::vector Operands;
protected:
@@ -264,7 +261,8 @@
}
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const;
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const;
virtual const char *getOperationStr() const = 0;
@@ -285,29 +283,13 @@
/// SCEVAddExpr - This node represents an addition of some number of SCEVs.
///
class SCEVAddExpr : public SCEVCommutativeExpr {
+ friend class ScalarEvolution;
+
SCEVAddExpr(const std::vector &ops)
: SCEVCommutativeExpr(scAddExpr, ops) {
}
public:
- static SCEVHandle get(std::vector &Ops);
-
- static SCEVHandle get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
- std::vector Ops;
- Ops.push_back(LHS);
- Ops.push_back(RHS);
- return get(Ops);
- }
-
- static SCEVHandle get(const SCEVHandle &Op0, const SCEVHandle &Op1,
- const SCEVHandle &Op2) {
- std::vector Ops;
- Ops.push_back(Op0);
- Ops.push_back(Op1);
- Ops.push_back(Op2);
- return get(Ops);
- }
-
virtual const char *getOperationStr() const { return " + "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -321,20 +303,13 @@
/// SCEVMulExpr - This node represents multiplication of some number of SCEVs.
///
class SCEVMulExpr : public SCEVCommutativeExpr {
+ friend class ScalarEvolution;
+
SCEVMulExpr(const std::vector &ops)
: SCEVCommutativeExpr(scMulExpr, ops) {
}
public:
- static SCEVHandle get(std::vector &Ops);
-
- static SCEVHandle get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
- std::vector Ops;
- Ops.push_back(LHS);
- Ops.push_back(RHS);
- return get(Ops);
- }
-
virtual const char *getOperationStr() const { return " * "; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -349,16 +324,14 @@
/// SCEVSDivExpr - This class represents a binary signed division operation.
///
class SCEVSDivExpr : public SCEV {
+ friend class ScalarEvolution;
+
SCEVHandle LHS, RHS;
SCEVSDivExpr(const SCEVHandle &lhs, const SCEVHandle &rhs)
: SCEV(scSDivExpr), LHS(lhs), RHS(rhs) {}
virtual ~SCEVSDivExpr();
public:
- /// get method - This just gets and returns a new SCEVSDiv object.
- ///
- static SCEVHandle get(const SCEVHandle &LHS, const SCEVHandle &RHS);
-
const SCEVHandle &getLHS() const { return LHS; }
const SCEVHandle &getRHS() const { return RHS; }
@@ -372,13 +345,14 @@
}
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
- SCEVHandle L = LHS->replaceSymbolicValuesWithConcrete(Sym, Conc);
- SCEVHandle R = RHS->replaceSymbolicValuesWithConcrete(Sym, Conc);
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
+ SCEVHandle L = LHS->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
+ SCEVHandle R = RHS->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (L == LHS && R == RHS)
return this;
else
- return get(L, R);
+ return SE.getSDivExpr(L, R);
}
@@ -402,6 +376,8 @@
/// All operands of an AddRec are required to be loop invariant.
///
class SCEVAddRecExpr : public SCEV {
+ friend class ScalarEvolution;
+
std::vector Operands;
const Loop *L;
@@ -413,16 +389,6 @@
}
~SCEVAddRecExpr();
public:
- static SCEVHandle get(const SCEVHandle &Start, const SCEVHandle &Step,
- const Loop *);
- static SCEVHandle get(std::vector &Operands,
- const Loop *);
- static SCEVHandle get(const std::vector &Operands,
- const Loop *L) {
- std::vector NewOp(Operands);
- return get(NewOp, L);
- }
-
typedef std::vector::const_iterator op_iterator;
op_iterator op_begin() const { return Operands.begin(); }
op_iterator op_end() const { return Operands.end(); }
@@ -436,10 +402,10 @@
/// getStepRecurrence - This method constructs and returns the recurrence
/// indicating how much this expression steps by. If this is a polynomial
/// of degree N, it returns a chrec of degree N-1.
- SCEVHandle getStepRecurrence() const {
+ SCEVHandle getStepRecurrence(ScalarEvolution &SE) const {
if (getNumOperands() == 2) return getOperand(1);
- return SCEVAddRecExpr::get(std::vector(op_begin()+1,op_end()),
- getLoop());
+ return SE.getAddRecExpr(std::vector(op_begin()+1,op_end()),
+ getLoop());
}
virtual bool hasComputableLoopEvolution(const Loop *QL) const {
@@ -468,7 +434,7 @@
/// evaluateAtIteration - Return the value of this chain of recurrences at
/// the specified iteration number.
- SCEVHandle evaluateAtIteration(SCEVHandle It) const;
+ SCEVHandle evaluateAtIteration(SCEVHandle It, ScalarEvolution &SE) const;
/// getNumIterationsInRange - Return the number of iterations of this loop
/// that produce values in the specified constant range. Another way of
@@ -476,10 +442,12 @@
/// value is not in the condition, thus computing the exit count. If the
/// iteration count can't be computed, an instance of SCEVCouldNotCompute is
/// returned.
- SCEVHandle getNumIterationsInRange(ConstantRange Range) const;
+ SCEVHandle getNumIterationsInRange(ConstantRange Range,
+ ScalarEvolution &SE) const;
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const;
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const;
virtual void print(std::ostream &OS) const;
void print(std::ostream *OS) const { if (OS) print(*OS); }
@@ -497,20 +465,14 @@
/// value for the analysis.
///
class SCEVUnknown : public SCEV {
+ friend class ScalarEvolution;
+
Value *V;
SCEVUnknown(Value *v) : SCEV(scUnknown), V(v) {}
protected:
~SCEVUnknown();
public:
- /// get method - For SCEVUnknown, this just gets and returns a new
- /// SCEVUnknown.
- static SCEVHandle get(Value *V);
-
- /// getIntegerSCEV - Given an integer or FP type, create a constant for the
- /// specified signed integer value and return a SCEV for the constant.
- static SCEVHandle getIntegerSCEV(int Val, const Type *Ty);
-
Value *getValue() const { return V; }
virtual bool isLoopInvariant(const Loop *L) const;
@@ -519,7 +481,8 @@
}
SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
if (&*Sym == this) return Conc;
return this;
}
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Oct 22 13:31:58 2007
@@ -154,7 +154,8 @@
SCEVHandle SCEVCouldNotCompute::
replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
return this;
}
@@ -177,14 +178,14 @@
SCEVConstants->erase(V);
}
-SCEVHandle SCEVConstant::get(ConstantInt *V) {
+SCEVHandle ScalarEvolution::getConstant(ConstantInt *V) {
SCEVConstant *&R = (*SCEVConstants)[V];
if (R == 0) R = new SCEVConstant(V);
return R;
}
-SCEVHandle SCEVConstant::get(const APInt& Val) {
- return get(ConstantInt::get(Val));
+SCEVHandle ScalarEvolution::getConstant(const APInt& Val) {
+ return getConstant(ConstantInt::get(Val));
}
ConstantRange SCEVConstant::getValueRange() const {
@@ -298,9 +299,11 @@
SCEVHandle SCEVCommutativeExpr::
replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- SCEVHandle H = getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc);
+ SCEVHandle H =
+ getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H != getOperand(i)) {
std::vector NewOps;
NewOps.reserve(getNumOperands());
@@ -309,12 +312,12 @@
NewOps.push_back(H);
for (++i; i != e; ++i)
NewOps.push_back(getOperand(i)->
- replaceSymbolicValuesWithConcrete(Sym, Conc));
+ replaceSymbolicValuesWithConcrete(Sym, Conc, SE));
if (isa(this))
- return SCEVAddExpr::get(NewOps);
+ return SE.getAddExpr(NewOps);
else if (isa(this))
- return SCEVMulExpr::get(NewOps);
+ return SE.getMulExpr(NewOps);
else
assert(0 && "Unknown commutative expr!");
}
@@ -355,9 +358,11 @@
SCEVHandle SCEVAddRecExpr::
replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
- const SCEVHandle &Conc) const {
+ const SCEVHandle &Conc,
+ ScalarEvolution &SE) const {
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- SCEVHandle H = getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc);
+ SCEVHandle H =
+ getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H != getOperand(i)) {
std::vector NewOps;
NewOps.reserve(getNumOperands());
@@ -366,9 +371,9 @@
NewOps.push_back(H);
for (++i; i != e; ++i)
NewOps.push_back(getOperand(i)->
- replaceSymbolicValuesWithConcrete(Sym, Conc));
+ replaceSymbolicValuesWithConcrete(Sym, Conc, SE));
- return get(NewOps, L);
+ return SE.getAddRecExpr(NewOps, L);
}
}
return this;
@@ -480,7 +485,7 @@
/// getIntegerSCEV - Given an integer or FP type, create a constant for the
/// specified signed integer value and return a SCEV for the constant.
-SCEVHandle SCEVUnknown::getIntegerSCEV(int Val, const Type *Ty) {
+SCEVHandle ScalarEvolution::getIntegerSCEV(int Val, const Type *Ty) {
Constant *C;
if (Val == 0)
C = Constant::getNullValue(Ty);
@@ -489,42 +494,45 @@
APFloat::IEEEdouble, Val));
else
C = ConstantInt::get(Ty, Val);
- return SCEVUnknown::get(C);
+ return getUnknown(C);
}
/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion of the
/// input value to the specified type. If the type must be extended, it is zero
/// extended.
-static SCEVHandle getTruncateOrZeroExtend(const SCEVHandle &V, const Type *Ty) {
+static SCEVHandle getTruncateOrZeroExtend(const SCEVHandle &V, const Type *Ty,
+ ScalarEvolution &SE) {
const Type *SrcTy = V->getType();
assert(SrcTy->isInteger() && Ty->isInteger() &&
"Cannot truncate or zero extend with non-integer arguments!");
if (SrcTy->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
return V; // No conversion
if (SrcTy->getPrimitiveSizeInBits() > Ty->getPrimitiveSizeInBits())
- return SCEVTruncateExpr::get(V, Ty);
- return SCEVZeroExtendExpr::get(V, Ty);
+ return SE.getTruncateExpr(V, Ty);
+ return SE.getZeroExtendExpr(V, Ty);
}
/// getNegativeSCEV - Return a SCEV corresponding to -V = -1*V
///
-SCEVHandle SCEV::getNegativeSCEV(const SCEVHandle &V) {
+SCEVHandle ScalarEvolution::getNegativeSCEV(const SCEVHandle &V) {
if (SCEVConstant *VC = dyn_cast(V))
- return SCEVUnknown::get(ConstantExpr::getNeg(VC->getValue()));
+ return getUnknown(ConstantExpr::getNeg(VC->getValue()));
- return SCEVMulExpr::get(V, SCEVUnknown::getIntegerSCEV(-1, V->getType()));
+ return getMulExpr(V, getIntegerSCEV(-1, V->getType()));
}
/// getMinusSCEV - Return a SCEV corresponding to LHS - RHS.
///
-SCEVHandle SCEV::getMinusSCEV(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+SCEVHandle ScalarEvolution::getMinusSCEV(const SCEVHandle &LHS,
+ const SCEVHandle &RHS) {
// X - Y --> X + -Y
- return SCEVAddExpr::get(LHS, SCEV::getNegativeSCEV(RHS));
+ return getAddExpr(LHS, getNegativeSCEV(RHS));
}
/// PartialFact - Compute V!/(V-NumSteps)!
-static SCEVHandle PartialFact(SCEVHandle V, unsigned NumSteps) {
+static SCEVHandle PartialFact(SCEVHandle V, unsigned NumSteps,
+ ScalarEvolution &SE) {
// Handle this case efficiently, it is common to have constant iteration
// counts while computing loop exit values.
if (SCEVConstant *SC = dyn_cast(V)) {
@@ -532,17 +540,17 @@
APInt Result(Val.getBitWidth(), 1);
for (; NumSteps; --NumSteps)
Result *= Val-(NumSteps-1);
- return SCEVConstant::get(Result);
+ return SE.getConstant(Result);
}
const Type *Ty = V->getType();
if (NumSteps == 0)
- return SCEVUnknown::getIntegerSCEV(1, Ty);
+ return SE.getIntegerSCEV(1, Ty);
SCEVHandle Result = V;
for (unsigned i = 1; i != NumSteps; ++i)
- Result = SCEVMulExpr::get(Result, SCEV::getMinusSCEV(V,
- SCEVUnknown::getIntegerSCEV(i, Ty)));
+ Result = SE.getMulExpr(Result, SE.getMinusSCEV(V,
+ SE.getIntegerSCEV(i, Ty)));
return Result;
}
@@ -557,16 +565,17 @@
/// FIXME/VERIFY: I don't trust that this is correct in the face of overflow.
/// Is the binomial equation safe using modular arithmetic??
///
-SCEVHandle SCEVAddRecExpr::evaluateAtIteration(SCEVHandle It) const {
+SCEVHandle SCEVAddRecExpr::evaluateAtIteration(SCEVHandle It,
+ ScalarEvolution &SE) const {
SCEVHandle Result = getStart();
int Divisor = 1;
const Type *Ty = It->getType();
for (unsigned i = 1, e = getNumOperands(); i != e; ++i) {
- SCEVHandle BC = PartialFact(It, i);
+ SCEVHandle BC = PartialFact(It, i, SE);
Divisor *= i;
- SCEVHandle Val = SCEVSDivExpr::get(SCEVMulExpr::get(BC, getOperand(i)),
- SCEVUnknown::getIntegerSCEV(Divisor,Ty));
- Result = SCEVAddExpr::get(Result, Val);
+ SCEVHandle Val = SE.getSDivExpr(SE.getMulExpr(BC, getOperand(i)),
+ SE.getIntegerSCEV(Divisor,Ty));
+ Result = SE.getAddExpr(Result, Val);
}
return Result;
}
@@ -576,9 +585,9 @@
// SCEV Expression folder implementations
//===----------------------------------------------------------------------===//
-SCEVHandle SCEVTruncateExpr::get(const SCEVHandle &Op, const Type *Ty) {
+SCEVHandle ScalarEvolution::getTruncateExpr(const SCEVHandle &Op, const Type *Ty) {
if (SCEVConstant *SC = dyn_cast(Op))
- return SCEVUnknown::get(
+ return getUnknown(
ConstantExpr::getTrunc(SC->getValue(), Ty));
// If the input value is a chrec scev made out of constants, truncate
@@ -588,11 +597,11 @@
for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i)
// FIXME: This should allow truncation of other expression types!
if (isa(AddRec->getOperand(i)))
- Operands.push_back(get(AddRec->getOperand(i), Ty));
+ Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty));
else
break;
if (Operands.size() == AddRec->getNumOperands())
- return SCEVAddRecExpr::get(Operands, AddRec->getLoop());
+ return getAddRecExpr(Operands, AddRec->getLoop());
}
SCEVTruncateExpr *&Result = (*SCEVTruncates)[std::make_pair(Op, Ty)];
@@ -600,9 +609,9 @@
return Result;
}
-SCEVHandle SCEVZeroExtendExpr::get(const SCEVHandle &Op, const Type *Ty) {
+SCEVHandle ScalarEvolution::getZeroExtendExpr(const SCEVHandle &Op, const Type *Ty) {
if (SCEVConstant *SC = dyn_cast(Op))
- return SCEVUnknown::get(
+ return getUnknown(
ConstantExpr::getZExt(SC->getValue(), Ty));
// FIXME: If the input value is a chrec scev, and we can prove that the value
@@ -615,9 +624,9 @@
return Result;
}
-SCEVHandle SCEVSignExtendExpr::get(const SCEVHandle &Op, const Type *Ty) {
+SCEVHandle ScalarEvolution::getSignExtendExpr(const SCEVHandle &Op, const Type *Ty) {
if (SCEVConstant *SC = dyn_cast(Op))
- return SCEVUnknown::get(
+ return getUnknown(
ConstantExpr::getSExt(SC->getValue(), Ty));
// FIXME: If the input value is a chrec scev, and we can prove that the value
@@ -631,7 +640,7 @@
}
// get - Get a canonical add expression, or something simpler if possible.
-SCEVHandle SCEVAddExpr::get(std::vector &Ops) {
+SCEVHandle ScalarEvolution::getAddExpr(std::vector &Ops) {
assert(!Ops.empty() && "Cannot get empty add!");
if (Ops.size() == 1) return Ops[0];
@@ -648,7 +657,7 @@
Constant *Fold = ConstantInt::get(LHSC->getValue()->getValue() +
RHSC->getValue()->getValue());
if (ConstantInt *CI = dyn_cast(Fold)) {
- Ops[0] = SCEVConstant::get(CI);
+ Ops[0] = getConstant(CI);
Ops.erase(Ops.begin()+1); // Erase the folded element
if (Ops.size() == 1) return Ops[0];
LHSC = cast(Ops[0]);
@@ -677,13 +686,13 @@
if (Ops[i] == Ops[i+1]) { // X + Y + Y --> X + Y*2
// Found a match, merge the two values into a multiply, and add any
// remaining values to the result.
- SCEVHandle Two = SCEVUnknown::getIntegerSCEV(2, Ty);
- SCEVHandle Mul = SCEVMulExpr::get(Ops[i], Two);
+ SCEVHandle Two = getIntegerSCEV(2, Ty);
+ SCEVHandle Mul = getMulExpr(Ops[i], Two);
if (Ops.size() == 2)
return Mul;
Ops.erase(Ops.begin()+i, Ops.begin()+i+2);
Ops.push_back(Mul);
- return SCEVAddExpr::get(Ops);
+ return getAddExpr(Ops);
}
// Now we know the first non-constant operand. Skip past any cast SCEVs.
@@ -705,7 +714,7 @@
// and they are not necessarily sorted. Recurse to resort and resimplify
// any operands we just aquired.
if (DeletedAdd)
- return get(Ops);
+ return getAddExpr(Ops);
}
// Skip over the add expression until we get to a multiply.
@@ -728,11 +737,11 @@
// Y*Z term.
std::vector MulOps(Mul->op_begin(), Mul->op_end());
MulOps.erase(MulOps.begin()+MulOp);
- InnerMul = SCEVMulExpr::get(MulOps);
+ InnerMul = getMulExpr(MulOps);
}
- SCEVHandle One = SCEVUnknown::getIntegerSCEV(1, Ty);
- SCEVHandle AddOne = SCEVAddExpr::get(InnerMul, One);
- SCEVHandle OuterMul = SCEVMulExpr::get(AddOne, Ops[AddOp]);
+ SCEVHandle One = getIntegerSCEV(1, Ty);
+ SCEVHandle AddOne = getAddExpr(InnerMul, One);
+ SCEVHandle OuterMul = getMulExpr(AddOne, Ops[AddOp]);
if (Ops.size() == 2) return OuterMul;
if (AddOp < Idx) {
Ops.erase(Ops.begin()+AddOp);
@@ -742,7 +751,7 @@
Ops.erase(Ops.begin()+AddOp-1);
}
Ops.push_back(OuterMul);
- return SCEVAddExpr::get(Ops);
+ return getAddExpr(Ops);
}
// Check this multiply against other multiplies being added together.
@@ -760,22 +769,22 @@
if (Mul->getNumOperands() != 2) {
std::vector MulOps(Mul->op_begin(), Mul->op_end());
MulOps.erase(MulOps.begin()+MulOp);
- InnerMul1 = SCEVMulExpr::get(MulOps);
+ InnerMul1 = getMulExpr(MulOps);
}
SCEVHandle InnerMul2 = OtherMul->getOperand(OMulOp == 0);
if (OtherMul->getNumOperands() != 2) {
std::vector MulOps(OtherMul->op_begin(),
OtherMul->op_end());
MulOps.erase(MulOps.begin()+OMulOp);
- InnerMul2 = SCEVMulExpr::get(MulOps);
+ InnerMul2 = getMulExpr(MulOps);
}
- SCEVHandle InnerMulSum = SCEVAddExpr::get(InnerMul1,InnerMul2);
- SCEVHandle OuterMul = SCEVMulExpr::get(MulOpSCEV, InnerMulSum);
+ SCEVHandle InnerMulSum = getAddExpr(InnerMul1,InnerMul2);
+ SCEVHandle OuterMul = getMulExpr(MulOpSCEV, InnerMulSum);
if (Ops.size() == 2) return OuterMul;
Ops.erase(Ops.begin()+Idx);
Ops.erase(Ops.begin()+OtherMulIdx-1);
Ops.push_back(OuterMul);
- return SCEVAddExpr::get(Ops);
+ return getAddExpr(Ops);
}
}
}
@@ -806,9 +815,9 @@
LIOps.push_back(AddRec->getStart());
std::vector AddRecOps(AddRec->op_begin(), AddRec->op_end());
- AddRecOps[0] = SCEVAddExpr::get(LIOps);
+ AddRecOps[0] = getAddExpr(LIOps);
- SCEVHandle NewRec = SCEVAddRecExpr::get(AddRecOps, AddRec->getLoop());
+ SCEVHandle NewRec = getAddRecExpr(AddRecOps, AddRec->getLoop());
// If all of the other operands were loop invariant, we are done.
if (Ops.size() == 1) return NewRec;
@@ -818,7 +827,7 @@
Ops[i] = NewRec;
break;
}
- return SCEVAddExpr::get(Ops);
+ return getAddExpr(Ops);
}
// Okay, if there weren't any loop invariants to be folded, check to see if
@@ -837,16 +846,16 @@
OtherAddRec->op_end());
break;
}
- NewOps[i] = SCEVAddExpr::get(NewOps[i], OtherAddRec->getOperand(i));
+ NewOps[i] = getAddExpr(NewOps[i], OtherAddRec->getOperand(i));
}
- SCEVHandle NewAddRec = SCEVAddRecExpr::get(NewOps, AddRec->getLoop());
+ SCEVHandle NewAddRec = getAddRecExpr(NewOps, AddRec->getLoop());
if (Ops.size() == 2) return NewAddRec;
Ops.erase(Ops.begin()+Idx);
Ops.erase(Ops.begin()+OtherIdx-1);
Ops.push_back(NewAddRec);
- return SCEVAddExpr::get(Ops);
+ return getAddExpr(Ops);
}
}
@@ -864,7 +873,7 @@
}
-SCEVHandle SCEVMulExpr::get(std::vector &Ops) {
+SCEVHandle ScalarEvolution::getMulExpr(std::vector &Ops) {
assert(!Ops.empty() && "Cannot get empty mul!");
// Sort by complexity, this groups all similar expression types together.
@@ -879,8 +888,8 @@
if (SCEVAddExpr *Add = dyn_cast(Ops[1]))
if (Add->getNumOperands() == 2 &&
isa(Add->getOperand(0)))
- return SCEVAddExpr::get(SCEVMulExpr::get(LHSC, Add->getOperand(0)),
- SCEVMulExpr::get(LHSC, Add->getOperand(1)));
+ return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)),
+ getMulExpr(LHSC, Add->getOperand(1)));
++Idx;
@@ -889,7 +898,7 @@
Constant *Fold = ConstantInt::get(LHSC->getValue()->getValue() *
RHSC->getValue()->getValue());
if (ConstantInt *CI = dyn_cast(Fold)) {
- Ops[0] = SCEVConstant::get(CI);
+ Ops[0] = getConstant(CI);
Ops.erase(Ops.begin()+1); // Erase the folded element
if (Ops.size() == 1) return Ops[0];
LHSC = cast(Ops[0]);
@@ -933,7 +942,7 @@
// and they are not necessarily sorted. Recurse to resort and resimplify
// any operands we just aquired.
if (DeletedMul)
- return get(Ops);
+ return getMulExpr(Ops);
}
// If there are any add recurrences in the operands list, see if any other
@@ -963,16 +972,16 @@
if (LIOps.size() == 1) {
SCEV *Scale = LIOps[0];
for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i)
- NewOps.push_back(SCEVMulExpr::get(Scale, AddRec->getOperand(i)));
+ NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i)));
} else {
for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) {
std::vector MulOps(LIOps);
MulOps.push_back(AddRec->getOperand(i));
- NewOps.push_back(SCEVMulExpr::get(MulOps));
+ NewOps.push_back(getMulExpr(MulOps));
}
}
- SCEVHandle NewRec = SCEVAddRecExpr::get(NewOps, AddRec->getLoop());
+ SCEVHandle NewRec = getAddRecExpr(NewOps, AddRec->getLoop());
// If all of the other operands were loop invariant, we are done.
if (Ops.size() == 1) return NewRec;
@@ -983,7 +992,7 @@
Ops[i] = NewRec;
break;
}
- return SCEVMulExpr::get(Ops);
+ return getMulExpr(Ops);
}
// Okay, if there weren't any loop invariants to be folded, check to see if
@@ -996,21 +1005,21 @@
if (AddRec->getLoop() == OtherAddRec->getLoop()) {
// F * G --> {A,+,B} * {C,+,D} --> {A*C,+,F*D + G*B + B*D}
SCEVAddRecExpr *F = AddRec, *G = OtherAddRec;
- SCEVHandle NewStart = SCEVMulExpr::get(F->getStart(),
+ SCEVHandle NewStart = getMulExpr(F->getStart(),
G->getStart());
- SCEVHandle B = F->getStepRecurrence();
- SCEVHandle D = G->getStepRecurrence();
- SCEVHandle NewStep = SCEVAddExpr::get(SCEVMulExpr::get(F, D),
- SCEVMulExpr::get(G, B),
- SCEVMulExpr::get(B, D));
- SCEVHandle NewAddRec = SCEVAddRecExpr::get(NewStart, NewStep,
- F->getLoop());
+ SCEVHandle B = F->getStepRecurrence(*this);
+ SCEVHandle D = G->getStepRecurrence(*this);
+ SCEVHandle NewStep = getAddExpr(getMulExpr(F, D),
+ getMulExpr(G, B),
+ getMulExpr(B, D));
+ SCEVHandle NewAddRec = getAddRecExpr(NewStart, NewStep,
+ F->getLoop());
if (Ops.size() == 2) return NewAddRec;
Ops.erase(Ops.begin()+Idx);
Ops.erase(Ops.begin()+OtherIdx-1);
Ops.push_back(NewAddRec);
- return SCEVMulExpr::get(Ops);
+ return getMulExpr(Ops);
}
}
@@ -1028,17 +1037,17 @@
return Result;
}
-SCEVHandle SCEVSDivExpr::get(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+SCEVHandle ScalarEvolution::getSDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
if (SCEVConstant *RHSC = dyn_cast(RHS)) {
if (RHSC->getValue()->equalsInt(1))
return LHS; // X sdiv 1 --> x
if (RHSC->getValue()->isAllOnesValue())
- return SCEV::getNegativeSCEV(LHS); // X sdiv -1 --> -x
+ return getNegativeSCEV(LHS); // X sdiv -1 --> -x
if (SCEVConstant *LHSC = dyn_cast(LHS)) {
Constant *LHSCV = LHSC->getValue();
Constant *RHSCV = RHSC->getValue();
- return SCEVUnknown::get(ConstantExpr::getSDiv(LHSCV, RHSCV));
+ return getUnknown(ConstantExpr::getSDiv(LHSCV, RHSCV));
}
}
@@ -1052,7 +1061,7 @@
/// SCEVAddRecExpr::get - Get a add recurrence expression for the
/// specified loop. Simplify the expression as much as possible.
-SCEVHandle SCEVAddRecExpr::get(const SCEVHandle &Start,
+SCEVHandle ScalarEvolution::getAddRecExpr(const SCEVHandle &Start,
const SCEVHandle &Step, const Loop *L) {
std::vector Operands;
Operands.push_back(Start);
@@ -1060,23 +1069,23 @@
if (StepChrec->getLoop() == L) {
Operands.insert(Operands.end(), StepChrec->op_begin(),
StepChrec->op_end());
- return get(Operands, L);
+ return getAddRecExpr(Operands, L);
}
Operands.push_back(Step);
- return get(Operands, L);
+ return getAddRecExpr(Operands, L);
}
/// SCEVAddRecExpr::get - Get a add recurrence expression for the
/// specified loop. Simplify the expression as much as possible.
-SCEVHandle SCEVAddRecExpr::get(std::vector &Operands,
+SCEVHandle ScalarEvolution::getAddRecExpr(std::vector &Operands,
const Loop *L) {
if (Operands.size() == 1) return Operands[0];
if (SCEVConstant *StepC = dyn_cast(Operands.back()))
if (StepC->getValue()->isZero()) {
Operands.pop_back();
- return get(Operands, L); // { X,+,0 } --> X
+ return getAddRecExpr(Operands, L); // { X,+,0 } --> X
}
SCEVAddRecExpr *&Result =
@@ -1086,9 +1095,9 @@
return Result;
}
-SCEVHandle SCEVUnknown::get(Value *V) {
+SCEVHandle ScalarEvolution::getUnknown(Value *V) {
if (ConstantInt *CI = dyn_cast(V))
- return SCEVConstant::get(CI);
+ return getConstant(CI);
SCEVUnknown *&Result = (*SCEVUnknowns)[V];
if (Result == 0) Result = new SCEVUnknown(V);
return Result;
@@ -1104,6 +1113,9 @@
///
namespace {
struct VISIBILITY_HIDDEN ScalarEvolutionsImpl {
+ /// SE - A reference to the public ScalarEvolution object.
+ ScalarEvolution &SE;
+
/// F - The function we are analyzing.
///
Function &F;
@@ -1132,8 +1144,8 @@
std::map ConstantEvolutionLoopExitValue;
public:
- ScalarEvolutionsImpl(Function &f, LoopInfo &li)
- : F(f), LI(li), UnknownValue(new SCEVCouldNotCompute()) {}
+ ScalarEvolutionsImpl(ScalarEvolution &se, Function &f, LoopInfo &li)
+ : SE(se), F(f), LI(li), UnknownValue(new SCEVCouldNotCompute()) {}
/// getSCEV - Return an existing SCEV if it exists, otherwise analyze the
/// expression and create a new one.
@@ -1289,7 +1301,7 @@
if (SI == Scalars.end()) return;
SCEVHandle NV =
- SI->second->replaceSymbolicValuesWithConcrete(SymName, NewVal);
+ SI->second->replaceSymbolicValuesWithConcrete(SymName, NewVal, SE);
if (NV == SI->second) return; // No change.
SI->second = NV; // Update the scalars map!
@@ -1314,7 +1326,7 @@
unsigned BackEdge = IncomingEdge^1;
// While we are analyzing this PHI node, handle its value symbolically.
- SCEVHandle SymbolicName = SCEVUnknown::get(PN);
+ SCEVHandle SymbolicName = SE.getUnknown(PN);
assert(Scalars.find(PN) == Scalars.end() &&
"PHI node already processed?");
Scalars.insert(std::make_pair(PN, SymbolicName));
@@ -1345,7 +1357,7 @@
for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
if (i != FoundIndex)
Ops.push_back(Add->getOperand(i));
- SCEVHandle Accum = SCEVAddExpr::get(Ops);
+ SCEVHandle Accum = SE.getAddExpr(Ops);
// This is not a valid addrec if the step amount is varying each
// loop iteration, but is not itself an addrec in this loop.
@@ -1353,7 +1365,7 @@
(isa(Accum) &&
cast(Accum)->getLoop() == L)) {
SCEVHandle StartVal = getSCEV(PN->getIncomingValue(IncomingEdge));
- SCEVHandle PHISCEV = SCEVAddRecExpr::get(StartVal, Accum, L);
+ SCEVHandle PHISCEV = SE.getAddRecExpr(StartVal, Accum, L);
// Okay, for the entire analysis of this edge we assumed the PHI
// to be symbolic. We now need to go back and update all of the
@@ -1375,10 +1387,10 @@
// If StartVal = j.start - j.stride, we can use StartVal as the
// initial step of the addrec evolution.
- if (StartVal == SCEV::getMinusSCEV(AddRec->getOperand(0),
- AddRec->getOperand(1))) {
+ if (StartVal == SE.getMinusSCEV(AddRec->getOperand(0),
+ AddRec->getOperand(1))) {
SCEVHandle PHISCEV =
- SCEVAddRecExpr::get(StartVal, AddRec->getOperand(1), L);
+ SE.getAddRecExpr(StartVal, AddRec->getOperand(1), L);
// Okay, for the entire analysis of this edge we assumed the PHI
// to be symbolic. We now need to go back and update all of the
@@ -1395,7 +1407,7 @@
}
// If it's not a loop phi, we can't handle it yet.
- return SCEVUnknown::get(PN);
+ return SE.getUnknown(PN);
}
/// GetConstantFactor - Determine the largest constant factor that S has. For
@@ -1464,19 +1476,19 @@
if (Instruction *I = dyn_cast(V)) {
switch (I->getOpcode()) {
case Instruction::Add:
- return SCEVAddExpr::get(getSCEV(I->getOperand(0)),
- getSCEV(I->getOperand(1)));
+ return SE.getAddExpr(getSCEV(I->getOperand(0)),
+ getSCEV(I->getOperand(1)));
case Instruction::Mul:
- return SCEVMulExpr::get(getSCEV(I->getOperand(0)),
- getSCEV(I->getOperand(1)));
+ return SE.getMulExpr(getSCEV(I->getOperand(0)),
+ getSCEV(I->getOperand(1)));
case Instruction::SDiv:
- return SCEVSDivExpr::get(getSCEV(I->getOperand(0)),
- getSCEV(I->getOperand(1)));
+ return SE.getSDivExpr(getSCEV(I->getOperand(0)),
+ getSCEV(I->getOperand(1)));
break;
case Instruction::Sub:
- return SCEV::getMinusSCEV(getSCEV(I->getOperand(0)),
- getSCEV(I->getOperand(1)));
+ return SE.getMinusSCEV(getSCEV(I->getOperand(0)),
+ getSCEV(I->getOperand(1)));
case Instruction::Or:
// If the RHS of the Or is a constant, we may have something like:
// X*4+1 which got turned into X*4|1. Handle this as an add so loop
@@ -1488,8 +1500,8 @@
"Common factor should at least be 1!");
if (CommonFact.ugt(CI->getValue())) {
// If the LHS is a multiple that is larger than the RHS, use +.
- return SCEVAddExpr::get(LHS,
- getSCEV(I->getOperand(1)));
+ return SE.getAddExpr(LHS,
+ getSCEV(I->getOperand(1)));
}
}
break;
@@ -1498,8 +1510,8 @@
// Instcombine turns add of signbit into xor as a strength reduction step.
if (ConstantInt *CI = dyn_cast(I->getOperand(1))) {
if (CI->getValue().isSignBit())
- return SCEVAddExpr::get(getSCEV(I->getOperand(0)),
- getSCEV(I->getOperand(1)));
+ return SE.getAddExpr(getSCEV(I->getOperand(0)),
+ getSCEV(I->getOperand(1)));
}
break;
@@ -1509,18 +1521,18 @@
uint32_t BitWidth = cast(V->getType())->getBitWidth();
Constant *X = ConstantInt::get(
APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth)));
- return SCEVMulExpr::get(getSCEV(I->getOperand(0)), getSCEV(X));
+ return SE.getMulExpr(getSCEV(I->getOperand(0)), getSCEV(X));
}
break;
case Instruction::Trunc:
- return SCEVTruncateExpr::get(getSCEV(I->getOperand(0)), I->getType());
+ return SE.getTruncateExpr(getSCEV(I->getOperand(0)), I->getType());
case Instruction::ZExt:
- return SCEVZeroExtendExpr::get(getSCEV(I->getOperand(0)), I->getType());
+ return SE.getZeroExtendExpr(getSCEV(I->getOperand(0)), I->getType());
case Instruction::SExt:
- return SCEVSignExtendExpr::get(getSCEV(I->getOperand(0)), I->getType());
+ return SE.getSignExtendExpr(getSCEV(I->getOperand(0)), I->getType());
case Instruction::BitCast:
// BitCasts are no-op casts so we just eliminate the cast.
@@ -1537,7 +1549,7 @@
}
}
- return SCEVUnknown::get(V);
+ return SE.getUnknown(V);
}
@@ -1673,7 +1685,7 @@
ConstantRange CompRange(
ICmpInst::makeConstantRange(Cond, CompVal->getValue()));
- SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange);
+ SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange, SE);
if (!isa(Ret)) return Ret;
}
}
@@ -1681,13 +1693,13 @@
switch (Cond) {
case ICmpInst::ICMP_NE: { // while (X != Y)
// Convert to: while (X-Y != 0)
- SCEVHandle TC = HowFarToZero(SCEV::getMinusSCEV(LHS, RHS), L);
+ SCEVHandle TC = HowFarToZero(SE.getMinusSCEV(LHS, RHS), L);
if (!isa(TC)) return TC;
break;
}
case ICmpInst::ICMP_EQ: {
// Convert to: while (X-Y == 0) // while (X == Y)
- SCEVHandle TC = HowFarToNonZero(SCEV::getMinusSCEV(LHS, RHS), L);
+ SCEVHandle TC = HowFarToNonZero(SE.getMinusSCEV(LHS, RHS), L);
if (!isa(TC)) return TC;
break;
}
@@ -1697,8 +1709,8 @@
break;
}
case ICmpInst::ICMP_SGT: {
- SCEVHandle TC = HowManyLessThans(SCEV::getNegativeSCEV(LHS),
- SCEV::getNegativeSCEV(RHS), L, true);
+ SCEVHandle TC = HowManyLessThans(SE.getNegativeSCEV(LHS),
+ SE.getNegativeSCEV(RHS), L, true);
if (!isa(TC)) return TC;
break;
}
@@ -1708,8 +1720,8 @@
break;
}
case ICmpInst::ICMP_UGT: {
- SCEVHandle TC = HowManyLessThans(SCEV::getNegativeSCEV(LHS),
- SCEV::getNegativeSCEV(RHS), L, false);
+ SCEVHandle TC = HowManyLessThans(SE.getNegativeSCEV(LHS),
+ SE.getNegativeSCEV(RHS), L, false);
if (!isa(TC)) return TC;
break;
}
@@ -1729,9 +1741,10 @@
}
static ConstantInt *
-EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C) {
- SCEVHandle InVal = SCEVConstant::get(C);
- SCEVHandle Val = AddRec->evaluateAtIteration(InVal);
+EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C,
+ ScalarEvolution &SE) {
+ SCEVHandle InVal = SE.getConstant(C);
+ SCEVHandle Val = AddRec->evaluateAtIteration(InVal, SE);
assert(isa(Val) &&
"Evaluation of SCEV at constant didn't fold correctly?");
return cast(Val)->getValue();
@@ -1823,7 +1836,7 @@
for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) {
ConstantInt *ItCst =
ConstantInt::get(IdxExpr->getType(), IterationNum);
- ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst);
+ ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, SE);
// Form the GEP offset.
Indexes[VarIdxNum] = Val;
@@ -1841,7 +1854,7 @@
<< "***\n";
#endif
++NumArrayLenItCounts;
- return SCEVConstant::get(ItCst); // Found terminating iteration!
+ return SE.getConstant(ItCst); // Found terminating iteration!
}
}
return UnknownValue;
@@ -2012,7 +2025,7 @@
if (CondVal->getValue() == uint64_t(ExitWhen)) {
ConstantEvolutionLoopExitValue[PN] = PHIVal;
++NumBruteForceTripCountsComputed;
- return SCEVConstant::get(ConstantInt::get(Type::Int32Ty, IterationNum));
+ return SE.getConstant(ConstantInt::get(Type::Int32Ty, IterationNum));
}
// Compute the value of the PHI node for the next iteration.
@@ -2053,7 +2066,7 @@
Constant *RV = getConstantEvolutionLoopExitValue(PN,
ICC->getValue()->getValue(),
LI);
- if (RV) return SCEVUnknown::get(RV);
+ if (RV) return SE.getUnknown(RV);
}
}
@@ -2087,7 +2100,7 @@
}
}
Constant *C =ConstantFoldInstOperands(I, &Operands[0], Operands.size());
- return SCEVUnknown::get(C);
+ return SE.getUnknown(C);
}
}
@@ -2113,9 +2126,9 @@
NewOps.push_back(OpAtScope);
}
if (isa(Comm))
- return SCEVAddExpr::get(NewOps);
+ return SE.getAddExpr(NewOps);
assert(isa(Comm) && "Only know about add and mul!");
- return SCEVMulExpr::get(NewOps);
+ return SE.getMulExpr(NewOps);
}
}
// If we got here, all operands are loop invariant.
@@ -2129,7 +2142,7 @@
if (RHS == UnknownValue) return RHS;
if (LHS == Div->getLHS() && RHS == Div->getRHS())
return Div; // must be loop invariant
- return SCEVSDivExpr::get(LHS, RHS);
+ return SE.getSDivExpr(LHS, RHS);
}
// If this is a loop recurrence for a loop that does not contain L, then we
@@ -2141,17 +2154,17 @@
SCEVHandle IterationCount = getIterationCount(AddRec->getLoop());
if (IterationCount == UnknownValue) return UnknownValue;
IterationCount = getTruncateOrZeroExtend(IterationCount,
- AddRec->getType());
+ AddRec->getType(), SE);
// If the value is affine, simplify the expression evaluation to just
// Start + Step*IterationCount.
if (AddRec->isAffine())
- return SCEVAddExpr::get(AddRec->getStart(),
- SCEVMulExpr::get(IterationCount,
- AddRec->getOperand(1)));
+ return SE.getAddExpr(AddRec->getStart(),
+ SE.getMulExpr(IterationCount,
+ AddRec->getOperand(1)));
// Otherwise, evaluate it the hard way.
- return AddRec->evaluateAtIteration(IterationCount);
+ return AddRec->evaluateAtIteration(IterationCount, SE);
}
return UnknownValue;
}
@@ -2166,7 +2179,7 @@
/// might be the same) or two SCEVCouldNotCompute objects.
///
static std::pair
-SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
+SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) {
assert(AddRec->getNumOperands() == 3 && "This is not a quadratic chrec!");
SCEVConstant *LC = dyn_cast(AddRec->getOperand(0));
SCEVConstant *MC = dyn_cast(AddRec->getOperand(1));
@@ -2212,8 +2225,8 @@
ConstantInt *Solution1 = ConstantInt::get((NegB + SqrtVal).sdiv(TwoA));
ConstantInt *Solution2 = ConstantInt::get((NegB - SqrtVal).sdiv(TwoA));
- return std::make_pair(SCEVConstant::get(Solution1),
- SCEVConstant::get(Solution2));
+ return std::make_pair(SE.getConstant(Solution1),
+ SE.getConstant(Solution2));
} // end APIntOps namespace
}
@@ -2248,7 +2261,7 @@
// FIXME: We should add DivExpr and RemExpr operations to our AST.
if (SCEVConstant *StepC = dyn_cast(Step)) {
if (StepC->getValue()->equalsInt(1)) // N % 1 == 0
- return SCEV::getNegativeSCEV(Start); // 0 - Start/1 == -Start
+ return SE.getNegativeSCEV(Start); // 0 - Start/1 == -Start
if (StepC->getValue()->isAllOnesValue()) // N % -1 == 0
return Start; // 0 - Start/-1 == Start
@@ -2259,14 +2272,14 @@
Constant *Rem = ConstantExpr::getSRem(StartNegC, StepC->getValue());
if (Rem->isNullValue()) {
Constant *Result =ConstantExpr::getSDiv(StartNegC,StepC->getValue());
- return SCEVUnknown::get(Result);
+ return SE.getUnknown(Result);
}
}
}
} else if (AddRec->isQuadratic() && AddRec->getType()->isInteger()) {
// If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of
// the quadratic equation to solve it.
- std::pair Roots = SolveQuadraticEquation(AddRec);
+ std::pair Roots = SolveQuadraticEquation(AddRec, SE);
SCEVConstant *R1 = dyn_cast(Roots.first);
SCEVConstant *R2 = dyn_cast(Roots.second);
if (R1) {
@@ -2284,7 +2297,7 @@
// We can only use this value if the chrec ends up with an exact zero
// value at this index. When solving for "X*X != 5", for example, we
// should not accept a root of 2.
- SCEVHandle Val = AddRec->evaluateAtIteration(R1);
+ SCEVHandle Val = AddRec->evaluateAtIteration(R1, SE);
if (SCEVConstant *EvalVal = dyn_cast(Val))
if (EvalVal->getValue()->isZero())
return R1; // We found a quadratic root!
@@ -2333,16 +2346,17 @@
if (AddRec->isAffine()) {
// FORNOW: We only support unit strides.
- SCEVHandle One = SCEVUnknown::getIntegerSCEV(1, RHS->getType());
+ SCEVHandle Zero = SE.getIntegerSCEV(0, RHS->getType());
+ SCEVHandle One = SE.getIntegerSCEV(1, RHS->getType());
if (AddRec->getOperand(1) != One)
return UnknownValue;
- // The number of iterations for "[n,+,1] < m", is m-n. However, we don't
+ // The number of iterations for "{n,+,1} < m", is m-n. However, we don't
// know that m is >= n on input to the loop. If it is, the condition return
// true zero times. What we really should return, for full generality, is
// SMAX(0, m-n). Since we cannot check this, we will instead check for a
// canonical loop form: most do-loops will have a check that dominates the
- // loop, that only enters the loop if [n-1]= n.
// Search for the check.
@@ -2403,15 +2417,15 @@
if (RHS != getSCEV(PreCondRHS))
return UnknownValue; // Not a comparison against 'm'.
- if (SCEV::getMinusSCEV(AddRec->getOperand(0), One)
+ if (SE.getMinusSCEV(AddRec->getOperand(0), One)
!= getSCEV(PreCondLHS))
return UnknownValue; // Not a comparison against 'n-1'.
}
else return UnknownValue;
// cerr << "Computed Loop Trip Count as: "
- // << // *SCEV::getMinusSCEV(RHS, AddRec->getOperand(0)) << "\n";
- return SCEV::getMinusSCEV(RHS, AddRec->getOperand(0));
+ // << // *SE.getMinusSCEV(RHS, AddRec->getOperand(0)) << "\n";
+ return SE.getMinusSCEV(RHS, AddRec->getOperand(0));
}
else
return UnknownValue;
@@ -2425,7 +2439,8 @@
/// this is that it returns the first iteration number where the value is not in
/// the condition, thus computing the exit count. If the iteration count can't
/// be computed, an instance of SCEVCouldNotCompute is returned.
-SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
+SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range,
+ ScalarEvolution &SE) const {
if (Range.isFullSet()) // Infinite loop.
return new SCEVCouldNotCompute();
@@ -2433,11 +2448,11 @@
if (SCEVConstant *SC = dyn_cast(getStart()))
if (!SC->getValue()->isZero()) {
std::vector Operands(op_begin(), op_end());
- Operands[0] = SCEVUnknown::getIntegerSCEV(0, SC->getType());
- SCEVHandle Shifted = SCEVAddRecExpr::get(Operands, getLoop());
+ Operands[0] = SE.getIntegerSCEV(0, SC->getType());
+ SCEVHandle Shifted = SE.getAddRecExpr(Operands, getLoop());
if (SCEVAddRecExpr *ShiftedAddRec = dyn_cast(Shifted))
return ShiftedAddRec->getNumIterationsInRange(
- Range.subtract(SC->getValue()->getValue()));
+ Range.subtract(SC->getValue()->getValue()), SE);
// This is strange and shouldn't happen.
return new SCEVCouldNotCompute();
}
@@ -2455,7 +2470,7 @@
// First check to see if the range contains zero. If not, the first
// iteration exits.
if (!Range.contains(APInt(getBitWidth(),0)))
- return SCEVConstant::get(ConstantInt::get(getType(),0));
+ return SE.getConstant(ConstantInt::get(getType(),0));
if (isAffine()) {
// If this is an affine expression then we have this situation:
@@ -2476,28 +2491,28 @@
// Evaluate at the exit value. If we really did fall out of the valid
// range, then we computed our trip count, otherwise wrap around or other
// things must have happened.
- ConstantInt *Val = EvaluateConstantChrecAtConstant(this, ExitValue);
+ ConstantInt *Val = EvaluateConstantChrecAtConstant(this, ExitValue, SE);
if (Range.contains(Val->getValue()))
return new SCEVCouldNotCompute(); // Something strange happened
// Ensure that the previous value is in the range. This is a sanity check.
assert(Range.contains(
EvaluateConstantChrecAtConstant(this,
- ConstantInt::get(ExitVal - One))->getValue()) &&
+ ConstantInt::get(ExitVal - One), SE)->getValue()) &&
"Linear scev computation is off in a bad way!");
- return SCEVConstant::get(ExitValue);
+ return SE.getConstant(ExitValue);
} else if (isQuadratic()) {
// If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of the
// quadratic equation to solve it. To do this, we must frame our problem in
// terms of figuring out when zero is crossed, instead of when
// Range.getUpper() is crossed.
std::vector NewOps(op_begin(), op_end());
- NewOps[0] = SCEV::getNegativeSCEV(SCEVConstant::get(Range.getUpper()));
- SCEVHandle NewAddRec = SCEVAddRecExpr::get(NewOps, getLoop());
+ NewOps[0] = SE.getNegativeSCEV(SE.getConstant(Range.getUpper()));
+ SCEVHandle NewAddRec = SE.getAddRecExpr(NewOps, getLoop());
// Next, solve the constructed addrec
std::pair Roots =
- SolveQuadraticEquation(cast(NewAddRec));
+ SolveQuadraticEquation(cast(NewAddRec), SE);
SCEVConstant *R1 = dyn_cast(Roots.first);
SCEVConstant *R2 = dyn_cast(Roots.second);
if (R1) {
@@ -2512,21 +2527,22 @@
// not be in the range, but the previous one should be. When solving
// for "X*X < 5", for example, we should not return a root of 2.
ConstantInt *R1Val = EvaluateConstantChrecAtConstant(this,
- R1->getValue());
+ R1->getValue(),
+ SE);
if (Range.contains(R1Val->getValue())) {
// The next iteration must be out of the range...
ConstantInt *NextVal = ConstantInt::get(R1->getValue()->getValue()+1);
- R1Val = EvaluateConstantChrecAtConstant(this, NextVal);
+ R1Val = EvaluateConstantChrecAtConstant(this, NextVal, SE);
if (!Range.contains(R1Val->getValue()))
- return SCEVConstant::get(NextVal);
+ return SE.getConstant(NextVal);
return new SCEVCouldNotCompute(); // Something strange happened
}
// If R1 was not in the range, then it is a good return value. Make
// sure that R1-1 WAS in the range though, just in case.
ConstantInt *NextVal = ConstantInt::get(R1->getValue()->getValue()-1);
- R1Val = EvaluateConstantChrecAtConstant(this, NextVal);
+ R1Val = EvaluateConstantChrecAtConstant(this, NextVal, SE);
if (Range.contains(R1Val->getValue()))
return R1;
return new SCEVCouldNotCompute(); // Something strange happened
@@ -2543,13 +2559,13 @@
ConstantInt *EndVal = TestVal; // Stop when we wrap around.
do {
++NumBruteForceEvaluations;
- SCEVHandle Val = evaluateAtIteration(SCEVConstant::get(TestVal));
+ SCEVHandle Val = evaluateAtIteration(SE.getConstant(TestVal), SE);
if (!isa(Val)) // This shouldn't happen.
return new SCEVCouldNotCompute();
// Check to see if we found the value!
if (!Range.contains(cast(Val)->getValue()->getValue()))
- return SCEVConstant::get(TestVal);
+ return SE.getConstant(TestVal);
// Increment to test the next index.
TestVal = ConstantInt::get(TestVal->getValue()+1);
@@ -2565,7 +2581,7 @@
//===----------------------------------------------------------------------===//
bool ScalarEvolution::runOnFunction(Function &F) {
- Impl = new ScalarEvolutionsImpl(F, getAnalysis());
+ Impl = new ScalarEvolutionsImpl(*this, F, getAnalysis());
return false;
}
Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Mon Oct 22 13:31:58 2007
@@ -128,8 +128,8 @@
!cast(S->getStart())->getValue()->isZero()) {
Value *Start = expand(S->getStart());
std::vector NewOps(S->op_begin(), S->op_end());
- NewOps[0] = SCEVUnknown::getIntegerSCEV(0, Ty);
- Value *Rest = expand(SCEVAddRecExpr::get(NewOps, L));
+ NewOps[0] = SE.getIntegerSCEV(0, Ty);
+ Value *Rest = expand(SE.getAddRecExpr(NewOps, L));
// FIXME: look for an existing add to use.
return InsertBinop(Instruction::Add, Rest, Start, InsertPt);
@@ -137,7 +137,7 @@
// {0,+,1} --> Insert a canonical induction variable into the loop!
if (S->getNumOperands() == 2 &&
- S->getOperand(1) == SCEVUnknown::getIntegerSCEV(1, Ty)) {
+ S->getOperand(1) == SE.getIntegerSCEV(1, Ty)) {
// Create and insert the PHI node for the induction variable in the
// specified loop.
BasicBlock *Header = L->getHeader();
@@ -200,9 +200,9 @@
// folders, then expandCodeFor the closed form. This allows the folders to
// simplify the expression without having to build a bunch of special code
// into this folder.
- SCEVHandle IH = SCEVUnknown::get(I); // Get I as a "symbolic" SCEV.
+ SCEVHandle IH = SE.getUnknown(I); // Get I as a "symbolic" SCEV.
- SCEVHandle V = S->evaluateAtIteration(IH);
+ SCEVHandle V = S->evaluateAtIteration(IH, SE);
//cerr << "Evaluated: " << *this << "\n to: " << *V << "\n";
return expand(V);
Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Mon Oct 22 13:31:58 2007
@@ -268,7 +268,7 @@
// backedge actually branches to the loop header. This is one less than the
// number of times the loop executes, so add one to it.
ConstantInt *OneC = ConstantInt::get(IterationCount->getType(), 1);
- TripCount = SCEVAddExpr::get(IterationCount, SCEVConstant::get(OneC));
+ TripCount = SE->getAddExpr(IterationCount, SE->getConstant(OneC));
IndVar = L->getCanonicalInductionVariableIncrement();
} else {
// We have to use the preincremented value...
@@ -524,9 +524,9 @@
if (!isa(IterationCount)) {
if (IterationCount->getType()->getPrimitiveSizeInBits() <
LargestType->getPrimitiveSizeInBits())
- IterationCount = SCEVZeroExtendExpr::get(IterationCount, LargestType);
+ IterationCount = SE->getZeroExtendExpr(IterationCount, LargestType);
else if (IterationCount->getType() != LargestType)
- IterationCount = SCEVTruncateExpr::get(IterationCount, LargestType);
+ IterationCount = SE->getTruncateExpr(IterationCount, LargestType);
if (Instruction *DI = LinearFunctionTestReplace(L, IterationCount,Rewriter))
DeadInsts.insert(DI);
}
Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=43224&r1=43223&r2=43224&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Oct 22 13:31:58 2007
@@ -90,9 +90,6 @@
PHINode *PHI;
Value *IncV;
- IVExpr()
- : Stride(SCEVUnknown::getIntegerSCEV(0, Type::Int32Ty)),
- Base (SCEVUnknown::getIntegerSCEV(0, Type::Int32Ty)) {}
IVExpr(const SCEVHandle &stride, const SCEVHandle &base, PHINode *phi,
Value *incv)
: Stride(stride), Base(base), PHI(phi), IncV(incv) {}
@@ -261,7 +258,7 @@
// Build up the base expression. Insert an LLVM cast of the pointer to
// uintptr_t first.
- SCEVHandle GEPVal = SCEVUnknown::get(
+ SCEVHandle GEPVal = SE->getUnknown(
getCastedVersionOf(Instruction::PtrToInt, GEP->getOperand(0)));
gep_type_iterator GTI = gep_type_begin(GEP);
@@ -274,8 +271,8 @@
const StructLayout *SL = TD->getStructLayout(STy);
unsigned Idx = cast(GEP->getOperand(i))->getZExtValue();
uint64_t Offset = SL->getElementOffset(Idx);
- GEPVal = SCEVAddExpr::get(GEPVal,
- SCEVUnknown::getIntegerSCEV(Offset, UIntPtrTy));
+ GEPVal = SE->getAddExpr(GEPVal,
+ SE->getIntegerSCEV(Offset, UIntPtrTy));
} else {
unsigned GEPOpiBits =
GEP->getOperand(i)->getType()->getPrimitiveSizeInBits();
@@ -288,10 +285,10 @@
uint64_t TypeSize = TD->getABITypeSize(GTI.getIndexedType());
if (TypeSize != 1)
- Idx = SCEVMulExpr::get(Idx,
- SCEVConstant::get(ConstantInt::get(UIntPtrTy,
- TypeSize)));
- GEPVal = SCEVAddExpr::get(GEPVal, Idx);
+ Idx = SE->getMulExpr(Idx,
+ SE->getConstant(ConstantInt::get(UIntPtrTy,
+ TypeSize)));
+ GEPVal = SE->getAddExpr(GEPVal, Idx);
}
}
@@ -304,7 +301,8 @@
/// is. The stride must be a loop invariant expression, but the start may be
/// a mix of loop invariant and loop variant expressions.
static bool getSCEVStartAndStride(const SCEVHandle &SH, Loop *L,
- SCEVHandle &Start, SCEVHandle &Stride) {
+ SCEVHandle &Start, SCEVHandle &Stride,
+ ScalarEvolution *SE) {
SCEVHandle TheAddRec = Start; // Initialize to zero.
// If the outer level is an AddExpr, the operands are all start values except
@@ -314,11 +312,11 @@
if (SCEVAddRecExpr *AddRec =
dyn_cast(AE->getOperand(i))) {
if (AddRec->getLoop() == L)
- TheAddRec = SCEVAddExpr::get(AddRec, TheAddRec);
+ TheAddRec = SE->getAddExpr(AddRec, TheAddRec);
else
return false; // Nested IV of some sort?
} else {
- Start = SCEVAddExpr::get(Start, AE->getOperand(i));
+ Start = SE->getAddExpr(Start, AE->getOperand(i));
}
} else if (isa(SH)) {
@@ -333,7 +331,7 @@
// FIXME: Generalize to non-affine IV's.
if (!AddRec->isAffine()) return false;
- Start = SCEVAddExpr::get(Start, AddRec->getOperand(0));
+ Start = SE->getAddExpr(Start, AddRec->getOperand(0));
if (!isa(AddRec->getOperand(1)))
DOUT << "[" << L->getHeader()->getName()
@@ -414,9 +412,9 @@
if (isa(ISE)) return false;
// Get the start and stride for this expression.
- SCEVHandle Start = SCEVUnknown::getIntegerSCEV(0, ISE->getType());
+ SCEVHandle Start = SE->getIntegerSCEV(0, ISE->getType());
SCEVHandle Stride = Start;
- if (!getSCEVStartAndStride(ISE, L, Start, Stride))
+ if (!getSCEVStartAndStride(ISE, L, Start, Stride, SE))
return false; // Non-reducible symbolic expression, bail out.
std::vector IUsers;
@@ -458,7 +456,7 @@
if (IVUseShouldUsePostIncValue(User, I, L, DT, this)) {
// The value used will be incremented by the stride more than we are
// expecting, so subtract this off.
- SCEVHandle NewStart = SCEV::getMinusSCEV(Start, Stride);
+ SCEVHandle NewStart = SE->getMinusSCEV(Start, Stride);
StrideUses.addUser(NewStart, User, I);
StrideUses.Users.back().isUseOfPostIncrementedValue = true;
DOUT << " USING POSTINC SCEV, START=" << *NewStart<< "\n";
@@ -474,6 +472,9 @@
/// BasedUser - For a particular base value, keep information about how we've
/// partitioned the expression so far.
struct BasedUser {
+ /// SE - The current ScalarEvolution object.
+ ScalarEvolution *SE;
+
/// Base - The Base value for the PHI node that needs to be inserted for
/// this use. As the use is processed, information gets moved from this
/// field to the Imm field (below). BasedUser values are sorted by this
@@ -503,10 +504,10 @@
// the loop.
bool isUseOfPostIncrementedValue;
- BasedUser(IVStrideUse &IVSU)
- : Base(IVSU.Offset), Inst(IVSU.User),
+ BasedUser(IVStrideUse &IVSU, ScalarEvolution *se)
+ : SE(se), Base(IVSU.Offset), Inst(IVSU.User),
OperandValToReplace(IVSU.OperandValToReplace),
- Imm(SCEVUnknown::getIntegerSCEV(0, Base->getType())), EmittedBase(0),
+ Imm(SE->getIntegerSCEV(0, Base->getType())), EmittedBase(0),
isUseOfPostIncrementedValue(IVSU.isUseOfPostIncrementedValue) {}
// Once we rewrite the code to insert the new IVs we want, update the
@@ -565,7 +566,7 @@
IP = Rewriter.getInsertionPoint();
// Always emit the immediate (if non-zero) into the same block as the user.
- SCEVHandle NewValSCEV = SCEVAddExpr::get(SCEVUnknown::get(Base), Imm);
+ SCEVHandle NewValSCEV = SE->getAddExpr(SE->getUnknown(Base), Imm);
return Rewriter.expandCodeFor(NewValSCEV, IP);
}
@@ -703,7 +704,7 @@
/// MoveLoopVariantsToImediateField - Move any subexpressions from Val that are
/// loop varying to the Imm operand.
static void MoveLoopVariantsToImediateField(SCEVHandle &Val, SCEVHandle &Imm,
- Loop *L) {
+ Loop *L, ScalarEvolution *SE) {
if (Val->isLoopInvariant(L)) return; // Nothing to do.
if (SCEVAddExpr *SAE = dyn_cast(Val)) {
@@ -714,27 +715,27 @@
if (!SAE->getOperand(i)->isLoopInvariant(L)) {
// If this is a loop-variant expression, it must stay in the immediate
// field of the expression.
- Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
+ Imm = SE->getAddExpr(Imm, SAE->getOperand(i));
} else {
NewOps.push_back(SAE->getOperand(i));
}
if (NewOps.empty())
- Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
+ Val = SE->getIntegerSCEV(0, Val->getType());
else
- Val = SCEVAddExpr::get(NewOps);
+ Val = SE->getAddExpr(NewOps);
} else if (SCEVAddRecExpr *SARE = dyn_cast(Val)) {
// Try to pull immediates out of the start value of nested addrec's.
SCEVHandle Start = SARE->getStart();
- MoveLoopVariantsToImediateField(Start, Imm, L);
+ MoveLoopVariantsToImediateField(Start, Imm, L, SE);
std::vector Ops(SARE->op_begin(), SARE->op_end());
Ops[0] = Start;
- Val = SCEVAddRecExpr::get(Ops, SARE->getLoop());
+ Val = SE->getAddRecExpr(Ops, SARE->getLoop());
} else {
// Otherwise, all of Val is variant, move the whole thing over.
- Imm = SCEVAddExpr::get(Imm, Val);
- Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
+ Imm = SE->getAddExpr(Imm, Val);
+ Val = SE->getIntegerSCEV(0, Val->getType());
}
}
@@ -745,7 +746,8 @@
static void MoveImmediateValues(const TargetLowering *TLI,
Instruction *User,
SCEVHandle &Val, SCEVHandle &Imm,
- bool isAddress, Loop *L) {
+ bool isAddress, Loop *L,
+ ScalarEvolution *SE) {
const Type *UseTy = User->getType();
if (StoreInst *SI = dyn_cast(User))
UseTy = SI->getOperand(0)->getType();
@@ -756,31 +758,31 @@
for (unsigned i = 0; i != SAE->getNumOperands(); ++i) {
SCEVHandle NewOp = SAE->getOperand(i);
- MoveImmediateValues(TLI, User, NewOp, Imm, isAddress, L);
+ MoveImmediateValues(TLI, User, NewOp, Imm, isAddress, L, SE);
if (!NewOp->isLoopInvariant(L)) {
// If this is a loop-variant expression, it must stay in the immediate
// field of the expression.
- Imm = SCEVAddExpr::get(Imm, NewOp);
+ Imm = SE->getAddExpr(Imm, NewOp);
} else {
NewOps.push_back(NewOp);
}
}
if (NewOps.empty())
- Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
+ Val = SE->getIntegerSCEV(0, Val->getType());
else
- Val = SCEVAddExpr::get(NewOps);
+ Val = SE->getAddExpr(NewOps);
return;
} else if (SCEVAddRecExpr *SARE = dyn_cast(Val)) {
// Try to pull immediates out of the start value of nested addrec's.
SCEVHandle Start = SARE->getStart();
- MoveImmediateValues(TLI, User, Start, Imm, isAddress, L);
+ MoveImmediateValues(TLI, User, Start, Imm, isAddress, L, SE);
if (Start != SARE->getStart()) {
std::vector Ops(SARE->op_begin(), SARE->op_end());
Ops[0] = Start;
- Val = SCEVAddRecExpr::get(Ops, SARE->getLoop());
+ Val = SE->getAddRecExpr(Ops, SARE->getLoop());
}
return;
} else if (SCEVMulExpr *SME = dyn_cast(Val)) {
@@ -788,22 +790,22 @@
if (isAddress && isTargetConstant(SME->getOperand(0), UseTy, TLI) &&
SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) {
- SCEVHandle SubImm = SCEVUnknown::getIntegerSCEV(0, Val->getType());
+ SCEVHandle SubImm = SE->getIntegerSCEV(0, Val->getType());
SCEVHandle NewOp = SME->getOperand(1);
- MoveImmediateValues(TLI, User, NewOp, SubImm, isAddress, L);
+ MoveImmediateValues(TLI, User, NewOp, SubImm, isAddress, L, SE);
// If we extracted something out of the subexpressions, see if we can
// simplify this!
if (NewOp != SME->getOperand(1)) {
// Scale SubImm up by "8". If the result is a target constant, we are
// good.
- SubImm = SCEVMulExpr::get(SubImm, SME->getOperand(0));
+ SubImm = SE->getMulExpr(SubImm, SME->getOperand(0));
if (isTargetConstant(SubImm, UseTy, TLI)) {
// Accumulate the immediate.
- Imm = SCEVAddExpr::get(Imm, SubImm);
+ Imm = SE->getAddExpr(Imm, SubImm);
// Update what is left of 'Val'.
- Val = SCEVMulExpr::get(SME->getOperand(0), NewOp);
+ Val = SE->getMulExpr(SME->getOperand(0), NewOp);
return;
}
}
@@ -814,8 +816,8 @@
// expression.
if ((isAddress && isTargetConstant(Val, UseTy, TLI)) ||
!Val->isLoopInvariant(L)) {
- Imm = SCEVAddExpr::get(Imm, Val);
- Val = SCEVUnknown::getIntegerSCEV(0, Val->getType());
+ Imm = SE->getAddExpr(Imm, Val);
+ Val = SE->getIntegerSCEV(0, Val->getType());
return;
}
@@ -827,22 +829,23 @@
/// added together. This is used to reassociate common addition subexprs
/// together for maximal sharing when rewriting bases.
static void SeparateSubExprs(std::vector &SubExprs,
- SCEVHandle Expr) {
+ SCEVHandle Expr,
+ ScalarEvolution *SE) {
if (SCEVAddExpr *AE = dyn_cast(Expr)) {
for (unsigned j = 0, e = AE->getNumOperands(); j != e; ++j)
- SeparateSubExprs(SubExprs, AE->getOperand(j));
+ SeparateSubExprs(SubExprs, AE->getOperand(j), SE);
} else if (SCEVAddRecExpr *SARE = dyn_cast(Expr)) {
- SCEVHandle Zero = SCEVUnknown::getIntegerSCEV(0, Expr->getType());
+ SCEVHandle Zero = SE->getIntegerSCEV(0, Expr->getType());
if (SARE->getOperand(0) == Zero) {
SubExprs.push_back(Expr);
} else {
// Compute the addrec with zero as its base.
std::vector Ops(SARE->op_begin(), SARE->op_end());
Ops[0] = Zero; // Start with zero base.
- SubExprs.push_back(SCEVAddRecExpr::get(Ops, SARE->getLoop()));
+ SubExprs.push_back(SE->getAddRecExpr(Ops, SARE->getLoop()));
- SeparateSubExprs(SubExprs, SARE->getOperand(0));
+ SeparateSubExprs(SubExprs, SARE->getOperand(0), SE);
}
} else if (!isa(Expr) ||
!cast(Expr)->getValue()->isZero()) {
@@ -857,11 +860,12 @@
/// removed, accumulated, and returned. This looks for things like (a+b+c) and
/// (a+c+d) -> (a+c). The common expression is *removed* from the Bases.
static SCEVHandle
-RemoveCommonExpressionsFromUseBases(std::vector &Uses) {
+RemoveCommonExpressionsFromUseBases(std::vector &Uses,
+ ScalarEvolution *SE) {
unsigned NumUses = Uses.size();
// Only one use? Use its base, regardless of what it is!
- SCEVHandle Zero = SCEVUnknown::getIntegerSCEV(0, Uses[0].Base->getType());
+ SCEVHandle Zero = SE->getIntegerSCEV(0, Uses[0].Base->getType());
SCEVHandle Result = Zero;
if (NumUses == 1) {
std::swap(Result, Uses[0].Base);
@@ -883,7 +887,7 @@
if (Uses[i].Base == Zero) return Zero;
// Split the expression into subexprs.
- SeparateSubExprs(SubExprs, Uses[i].Base);
+ SeparateSubExprs(SubExprs, Uses[i].Base, SE);
// Add one to SubExpressionUseCounts for each subexpr present.
for (unsigned j = 0, e = SubExprs.size(); j != e; ++j)
if (++SubExpressionUseCounts[SubExprs[j]] == 1)
@@ -898,7 +902,7 @@
SubExpressionUseCounts.find(UniqueSubExprs[i]);
assert(I != SubExpressionUseCounts.end() && "Entry not found?");
if (I->second == NumUses) { // Found CSE!
- Result = SCEVAddExpr::get(Result, I->first);
+ Result = SE->getAddExpr(Result, I->first);
} else {
// Remove non-cse's from SubExpressionUseCounts.
SubExpressionUseCounts.erase(I);
@@ -911,7 +915,7 @@
// Otherwise, remove all of the CSE's we found from each of the base values.
for (unsigned i = 0; i != NumUses; ++i) {
// Split the expression into subexprs.
- SeparateSubExprs(SubExprs, Uses[i].Base);
+ SeparateSubExprs(SubExprs, Uses[i].Base, SE);
// Remove any common subexpressions.
for (unsigned j = 0, e = SubExprs.size(); j != e; ++j)
@@ -924,7 +928,7 @@
if (SubExprs.empty())
Uses[i].Base = Zero;
else
- Uses[i].Base = SCEVAddExpr::get(SubExprs);
+ Uses[i].Base = SE->getAddExpr(SubExprs);
SubExprs.clear();
}
@@ -1037,13 +1041,13 @@
std::vector UsersToProcess;
UsersToProcess.reserve(Uses.Users.size());
for (unsigned i = 0, e = Uses.Users.size(); i != e; ++i) {
- UsersToProcess.push_back(Uses.Users[i]);
+ UsersToProcess.push_back(BasedUser(Uses.Users[i], SE));
// Move any loop invariant operands from the offset field to the immediate
// field of the use, so that we don't try to use something before it is
// computed.
MoveLoopVariantsToImediateField(UsersToProcess.back().Base,
- UsersToProcess.back().Imm, L);
+ UsersToProcess.back().Imm, L, SE);
assert(UsersToProcess.back().Base->isLoopInvariant(L) &&
"Base value is not loop invariant!");
}
@@ -1056,7 +1060,7 @@
// "A+B"), emit it to the preheader, then remove the expression from the
// UsersToProcess base values.
SCEVHandle CommonExprs =
- RemoveCommonExpressionsFromUseBases(UsersToProcess);
+ RemoveCommonExpressionsFromUseBases(UsersToProcess, SE);
// Next, figure out what we can represent in the immediate fields of
// instructions. If we can represent anything there, move it to the imm
@@ -1067,10 +1071,10 @@
// value of the IV. Do not put anything in the base, make sure it's all in
// the immediate field to allow as much factoring as possible.
if (!L->contains(UsersToProcess[i].Inst->getParent())) {
- UsersToProcess[i].Imm = SCEVAddExpr::get(UsersToProcess[i].Imm,
- UsersToProcess[i].Base);
+ UsersToProcess[i].Imm = SE->getAddExpr(UsersToProcess[i].Imm,
+ UsersToProcess[i].Base);
UsersToProcess[i].Base =
- SCEVUnknown::getIntegerSCEV(0, UsersToProcess[i].Base->getType());
+ SE->getIntegerSCEV(0, UsersToProcess[i].Base->getType());
} else {
// Addressing modes can be folded into loads and stores. Be careful that
@@ -1088,7 +1092,7 @@
}
MoveImmediateValues(TLI, UsersToProcess[i].Inst, UsersToProcess[i].Base,
- UsersToProcess[i].Imm, isAddress, L);
+ UsersToProcess[i].Imm, isAddress, L, SE);
}
}
@@ -1098,7 +1102,9 @@
// instruction after this substition, including the immediate field, if any.
PHINode *NewPHI = NULL;
Value *IncV = NULL;
- IVExpr ReuseIV;
+ IVExpr ReuseIV(SE->getIntegerSCEV(0, Type::Int32Ty),
+ SE->getIntegerSCEV(0, Type::Int32Ty),
+ 0, 0);
unsigned RewriteFactor = CheckForIVReuse(Stride, ReuseIV,
CommonExprs->getType(),
UsersToProcess);
@@ -1143,7 +1149,7 @@
bool isNegative = isNonConstantNegative(Stride);
SCEVHandle IncAmount = Stride;
if (isNegative)
- IncAmount = SCEV::getNegativeSCEV(Stride);
+ IncAmount = SE->getNegativeSCEV(Stride);
// Insert the stride into the preheader.
Value *StrideV = PreheaderRewriter.expandCodeFor(IncAmount, PreInsertPt);
@@ -1151,10 +1157,10 @@
// Emit the increment of the base value before the terminator of the loop
// latch block, and add it to the Phi node.
- SCEVHandle IncExp = SCEVUnknown::get(StrideV);
+ SCEVHandle IncExp = SE->getUnknown(StrideV);
if (isNegative)
- IncExp = SCEV::getNegativeSCEV(IncExp);
- IncExp = SCEVAddExpr::get(SCEVUnknown::get(NewPHI), IncExp);
+ IncExp = SE->getNegativeSCEV(IncExp);
+ IncExp = SE->getAddExpr(SE->getUnknown(NewPHI), IncExp);
IncV = Rewriter.expandCodeFor(IncExp, LatchBlock->getTerminator());
IncV->setName(NewPHI->getName()+".inc");
@@ -1168,7 +1174,7 @@
Constant *C = dyn_cast(CommonBaseV);
if (!C ||
(!C->isNullValue() &&
- !isTargetConstant(SCEVUnknown::get(CommonBaseV), ReplacedTy, TLI)))
+ !isTargetConstant(SE->getUnknown(CommonBaseV), ReplacedTy, TLI)))
// We want the common base emitted into the preheader! This is just
// using cast as a copy so BitCast (no-op cast) is appropriate
CommonBaseV = new BitCastInst(CommonBaseV, CommonBaseV->getType(),
@@ -1257,7 +1263,7 @@
RewriteOp = SCEVExpander::InsertCastOfTo(opcode, RewriteOp, ReplacedTy);
}
- SCEVHandle RewriteExpr = SCEVUnknown::get(RewriteOp);
+ SCEVHandle RewriteExpr = SE->getUnknown(RewriteOp);
// Clear the SCEVExpander's expression map so that we are guaranteed
// to have the code emitted where we expect it.
@@ -1267,8 +1273,8 @@
// factor take advantage of addressing mode scale component.
if (RewriteFactor != 0) {
RewriteExpr =
- SCEVMulExpr::get(SCEVUnknown::getIntegerSCEV(RewriteFactor,
- RewriteExpr->getType()),
+ SE->getMulExpr(SE->getIntegerSCEV(RewriteFactor,
+ RewriteExpr->getType()),
RewriteExpr);
// The common base is emitted in the loop preheader. But since we
@@ -1276,15 +1282,15 @@
// Add it to the expression used to rewrite the uses.
if (!isa(CommonBaseV) ||
!cast(CommonBaseV)->isZero())
- RewriteExpr = SCEVAddExpr::get(RewriteExpr,
- SCEVUnknown::get(CommonBaseV));
+ RewriteExpr = SE->getAddExpr(RewriteExpr,
+ SE->getUnknown(CommonBaseV));
}
// Now that we know what we need to do, insert code before User for the
// immediate and any loop-variant expressions.
if (!isa(BaseV) || !cast(BaseV)->isZero())
// Add BaseV to the PHI value if needed.
- RewriteExpr = SCEVAddExpr::get(RewriteExpr, SCEVUnknown::get(BaseV));
+ RewriteExpr = SE->getAddExpr(RewriteExpr, SE->getUnknown(BaseV));
User.RewriteInstructionToUseNewBase(RewriteExpr, Rewriter, L, this);
@@ -1380,7 +1386,7 @@
// If we get to here, we know that we can transform the setcc instruction to
// use the post-incremented version of the IV, allowing us to coalesce the
// live ranges for the IV correctly.
- CondUse->Offset = SCEV::getMinusSCEV(CondUse->Offset, *CondStride);
+ CondUse->Offset = SE->getMinusSCEV(CondUse->Offset, *CondStride);
CondUse->isUseOfPostIncrementedValue = true;
}
From baldrick at free.fr Mon Oct 22 14:00:05 2007
From: baldrick at free.fr (Duncan Sands)
Date: Mon, 22 Oct 2007 19:00:05 -0000
Subject: [llvm-commits] [llvm] r43225 -
/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
Message-ID: <200710221900.l9MJ05fI022929@zion.cs.uiuc.edu>
Author: baldrick
Date: Mon Oct 22 14:00:05 2007
New Revision: 43225
URL: http://llvm.org/viewvc/llvm-project?rev=43225&view=rev
Log:
Support for expanding extending loads of integers with
funky bit-widths.
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp?rev=43225&r1=43224&r2=43225&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAGTypes.cpp Mon Oct 22 14:00:05 2007
@@ -935,17 +935,19 @@
int SVOffset = N->getSrcValueOffset();
unsigned Alignment = N->getAlignment();
bool isVolatile = N->isVolatile();
-
+
+ assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!");
+
if (ExtType == ISD::NON_EXTLOAD) {
Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
isVolatile, Alignment);
// Increment the pointer to the other half.
- unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8;
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
isVolatile, std::max(Alignment, IncrementSize));
-
+
// Build a factor node to remember that this load is independent of the
// other one.
Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
@@ -954,19 +956,15 @@
// Handle endianness of the load.
if (!TLI.isLittleEndian())
std::swap(Lo, Hi);
- } else {
+ } else if (MVT::getSizeInBits(N->getLoadedVT()) <= MVT::getSizeInBits(NVT)) {
MVT::ValueType EVT = N->getLoadedVT();
-
- if (EVT == NVT)
- Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- else
- Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
- SVOffset, EVT, isVolatile,
- Alignment);
+
+ Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT,
+ isVolatile, Alignment);
+
// Remember the chain.
Ch = Lo.getValue(1);
-
+
if (ExtType == ISD::SEXTLOAD) {
// The high part is obtained by SRA'ing all but one of the bits of the
// lo part.
@@ -981,13 +979,70 @@
// The high part is undefined.
Hi = DAG.getNode(ISD::UNDEF, NVT);
}
+ } else if (TLI.isLittleEndian()) {
+ // Little-endian - low bits are at low addresses.
+ Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+ isVolatile, Alignment);
+
+ unsigned ExcessBits =
+ MVT::getSizeInBits(N->getLoadedVT()) - MVT::getSizeInBits(NVT);
+ MVT::ValueType NEVT = MVT::getIntegerType(ExcessBits);
+
+ // Increment the pointer to the other half.
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ getIntPtrConstant(IncrementSize));
+ Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize, NEVT,
+ isVolatile, std::max(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+ } else {
+ // Big-endian - high bits are at low addresses. Favor aligned loads at
+ // the cost of some bit-fiddling.
+ MVT::ValueType EVT = N->getLoadedVT();
+ unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8;
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+ unsigned ExcessBits = (EBytes - IncrementSize)*8;
+
+ // Load both the high bits and maybe some of the low bits.
+ Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+ MVT::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits),
+ isVolatile, Alignment);
+
+ // Increment the pointer to the other half.
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ getIntPtrConstant(IncrementSize));
+ // Load the rest of the low bits.
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize, MVT::getIntegerType(ExcessBits),
+ isVolatile, std::max(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ if (ExcessBits < MVT::getSizeInBits(NVT)) {
+ // Transfer low bits from the bottom of Hi to the top of Lo.
+ Lo = DAG.getNode(ISD::OR, NVT, Lo,
+ DAG.getNode(ISD::SHL, NVT, Hi,
+ DAG.getConstant(ExcessBits,
+ TLI.getShiftAmountTy())));
+ // Move high bits to the right position in Hi.
+ Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi,
+ DAG.getConstant(MVT::getSizeInBits(NVT) - ExcessBits,
+ TLI.getShiftAmountTy()));
+ }
}
-
+
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceLegalValueWith(SDOperand(N, 1), Ch);
-}
-
+}
void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
From sabre at nondot.org Mon Oct 22 14:41:46 2007
From: sabre at nondot.org (Chris Lattner)
Date: Mon, 22 Oct 2007 19:41:46 -0000
Subject: [llvm-commits] [llvm] r43226 - /llvm/trunk/tools/llvmc/llvmc.cpp
Message-ID: <200710221941.l9MJfkwO024915@zion.cs.uiuc.edu>
Author: lattner
Date: Mon Oct 22 14:41:46 2007
New Revision: 43226
URL: http://llvm.org/viewvc/llvm-project?rev=43226&view=rev
Log:
add a 'don't use me' marker.
Modified:
llvm/trunk/tools/llvmc/llvmc.cpp
Modified: llvm/trunk/tools/llvmc/llvmc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc/llvmc.cpp?rev=43226&r1=43225&r2=43226&view=diff
==============================================================================
--- llvm/trunk/tools/llvmc/llvmc.cpp (original)
+++ llvm/trunk/tools/llvmc/llvmc.cpp Mon Oct 22 14:41:46 2007
@@ -253,6 +253,9 @@
// Make sure we print stack trace if we get bad signals
sys::PrintStackTraceOnErrorSignal();
+ std::cout << "NOTE: llvmc is highly experimental and mostly useless right "
+ "now.\nPlease use llvm-gcc directly instead.\n\n";
+
try {
// Parse the command line options
From evan.cheng at apple.com Mon Oct 22 14:42:28 2007
From: evan.cheng at apple.com (Evan Cheng)
Date: Mon, 22 Oct 2007 19:42:28 -0000
Subject: [llvm-commits] [llvm] r43227 -
/llvm/trunk/lib/CodeGen/RegAllocLocal.cpp
Message-ID: <200710221942.l9MJgSek024961@zion.cs.uiuc.edu>
Author: evancheng
Date: Mon Oct 22 14:42:28 2007
New Revision: 43227
URL: http://llvm.org/viewvc/llvm-project?rev=43227&view=rev
Log:
Add missing paratheses.
Modified:
llvm/trunk/lib/CodeGen/RegAllocLocal.cpp
Modified: llvm/trunk/lib/CodeGen/RegAllocLocal.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLocal.cpp?rev=43227&r1=43226&r2=43227&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocLocal.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocLocal.cpp Mon Oct 22 14:42:28 2007
@@ -618,7 +618,7 @@
// Unallocatable register dead, ignore.
continue;
} else {
- assert(!PhysRegsUsed[PhysReg] || PhysRegsUsed[PhysReg] == -1 &&
+ assert((!PhysRegsUsed[PhysReg] || PhysRegsUsed[PhysReg] == -1) &&
"Silently clearing a virtual register?");
}
From evan.cheng at apple.com Mon Oct 22 14:46:19 2007
From: evan.cheng at apple.com (Evan Cheng)
Date: Mon, 22 Oct 2007 19:46:19 -0000
Subject: [llvm-commits] [llvm] r43228 - in /llvm/trunk:
lib/Target/PowerPC/PPCISelLowering.cpp
test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll
Message-ID: <200710221946.l9MJkJII025122@zion.cs.uiuc.edu>
Author: evancheng
Date: Mon Oct 22 14:46:19 2007
New Revision: 43228
URL: http://llvm.org/viewvc/llvm-project?rev=43228&view=rev
Log:
Use ptr type in the immediate field of a BxA instruction so we don't end up selecting 32-bit call instruction for ppc64.
Added:
llvm/trunk/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll
Modified:
llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=43228&r1=43227&r2=43228&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Mon Oct 22 14:46:19 2007
@@ -1537,7 +1537,8 @@
(Addr << 6 >> 6) != Addr)
return 0; // Top 6 bits have to be sext of immediate.
- return DAG.getConstant((int)C->getValue() >> 2, MVT::i32).Val;
+ return DAG.getConstant((int)C->getValue() >> 2,
+ DAG.getTargetLoweringInfo().getPointerTy()).Val;
}
Added: llvm/trunk/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll?rev=43228&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll Mon Oct 22 14:46:19 2007
@@ -0,0 +1,27 @@
+; RUN: llvm-as < %s | llc -mtriple=powerpc64-apple-darwin9 -regalloc=local -relocation-model=pic
+
+ %struct.NSError = type opaque
+ %struct.NSManagedObjectContext = type opaque
+ %struct.NSPersistentStoreCoordinator = type opaque
+ %struct.NSString = type opaque
+ %struct.NSURL = type opaque
+ %struct._message_ref_t = type { %struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)*, %struct.objc_selector* }
+ %struct.objc_object = type { }
+ %struct.objc_selector = type opaque
+@"\01L_OBJC_MESSAGE_REF_2" = external global %struct._message_ref_t ; <%struct._message_ref_t*> [#uses=1]
+@"\01L_OBJC_MESSAGE_REF_6" = external global %struct._message_ref_t ; <%struct._message_ref_t*> [#uses=1]
+ at NSXMLStoreType = external constant %struct.NSString* ; <%struct.NSString**> [#uses=1]
+@"\01L_OBJC_MESSAGE_REF_5" = external global %struct._message_ref_t ; <%struct._message_ref_t*> [#uses=2]
+@"\01L_OBJC_MESSAGE_REF_4" = external global %struct._message_ref_t ; <%struct._message_ref_t*> [#uses=1]
+
+define %struct.NSManagedObjectContext* @"+[ListGenerator(Private) managedObjectContextWithModelURL:storeURL:]"(%struct.objc_object* %self, %struct._message_ref_t* %_cmd, %struct.NSURL* %modelURL, %struct.NSURL* %storeURL) {
+entry:
+ %storeCoordinator = alloca %struct.NSPersistentStoreCoordinator* ; <%struct.NSPersistentStoreCoordinator**> [#uses=0]
+ %tmp29 = call %struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)* null( %struct.objc_object* null, %struct._message_ref_t* @"\01L_OBJC_MESSAGE_REF_2" ) ; <%struct.objc_object*> [#uses=0]
+ %tmp34 = load %struct.NSString** @NSXMLStoreType, align 8 ; <%struct.NSString*> [#uses=1]
+ %tmp37 = load %struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)** getelementptr (%struct._message_ref_t* @"\01L_OBJC_MESSAGE_REF_5", i32 0, i32 0), align 8 ; <%struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)*> [#uses=1]
+ %tmp42 = call %struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)* null( %struct.objc_object* null, %struct._message_ref_t* @"\01L_OBJC_MESSAGE_REF_4", i32 1 ) ; <%struct.objc_object*> [#uses=1]
+ %tmp45 = call %struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)* %tmp37( %struct.objc_object* null, %struct._message_ref_t* @"\01L_OBJC_MESSAGE_REF_5", %struct.objc_object* %tmp42, %struct.NSString* null ) ; <%struct.objc_object*> [#uses=1]
+ %tmp48 = call %struct.objc_object* (%struct.objc_object*, %struct._message_ref_t*, ...)* null( %struct.objc_object* null, %struct._message_ref_t* @"\01L_OBJC_MESSAGE_REF_6", %struct.NSString* %tmp34, i8* null, %struct.NSURL* null, %struct.objc_object* %tmp45, %struct.NSError** null ) ; <%struct.objc_object*> [#uses=0]
+ unreachable
+}
From criswell at uiuc.edu Mon Oct 22 14:57:26 2007
From: criswell at uiuc.edu (John Criswell)
Date: Mon, 22 Oct 2007 19:57:26 -0000
Subject: [llvm-commits] [poolalloc] r43229 -
/poolalloc/branches/SVA/lib/DSA/Local.cpp
Message-ID: <200710221957.l9MJvQmp025589@zion.cs.uiuc.edu>
Author: criswell
Date: Mon Oct 22 14:57:26 2007
New Revision: 43229
URL: http://llvm.org/viewvc/llvm-project?rev=43229&view=rev
Log:
Make DSA compile correctly in kernel and non-kernel mode.
Modified:
poolalloc/branches/SVA/lib/DSA/Local.cpp
Modified: poolalloc/branches/SVA/lib/DSA/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/SVA/lib/DSA/Local.cpp?rev=43229&r1=43228&r2=43229&view=diff
==============================================================================
--- poolalloc/branches/SVA/lib/DSA/Local.cpp (original)
+++ poolalloc/branches/SVA/lib/DSA/Local.cpp Mon Oct 22 14:57:26 2007
@@ -1490,8 +1490,8 @@
N->setModifiedMarker()->setReadMarker();
return true;
#endif
- }
#endif
+ }
return false;
}
@@ -1553,12 +1553,14 @@
}
}
+#ifdef LLVA_KERNEL
if (isSyscall6) {
assert (isa(CS.getArgument(0)) && "llva_syscall6 called with non-const argument");
ConstantInt * C = dyn_cast(CS.getArgument(0));
Callee = syscalls[C->getSExtValue()];
assert (Callee && "llva_syscall: No target for system call vector");
}
+#endif
// Set up the return value...
DSNodeHandle RetVal;
From djg at cray.com Mon Oct 22 15:22:25 2007
From: djg at cray.com (Dan Gohman)
Date: Mon, 22 Oct 2007 20:22:25 -0000
Subject: [llvm-commits] [llvm] r43230 - in /llvm/trunk:
lib/Target/X86/X86ISelDAGToDAG.cpp test/CodeGen/X86/fold-mul-lohi.ll
Message-ID: <200710222022.l9MKMPet026663@zion.cs.uiuc.edu>
Author: djg
Date: Mon Oct 22 15:22:24 2007
New Revision: 43230
URL: http://llvm.org/viewvc/llvm-project?rev=43230&view=rev
Log:
Fix the folding of multiplication into addresses on x86, which was broken
by the recent {U,S}MUL_LOHI changes.
Added:
llvm/trunk/test/CodeGen/X86/fold-mul-lohi.ll
Modified:
llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=43230&r1=43229&r2=43230&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Oct 22 15:22:24 2007
@@ -681,6 +681,11 @@
}
break;
+ case ISD::SMUL_LOHI:
+ case ISD::UMUL_LOHI:
+ // A mul_lohi where we need the low part can be folded as a plain multiply.
+ if (N.ResNo != 0) break;
+ // FALL THROUGH
case ISD::MUL:
// X*[3,5,9] -> X+X*[2,4,8]
if (!Available &&
Added: llvm/trunk/test/CodeGen/X86/fold-mul-lohi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fold-mul-lohi.ll?rev=43230&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/fold-mul-lohi.ll (added)
+++ llvm/trunk/test/CodeGen/X86/fold-mul-lohi.ll Mon Oct 22 15:22:24 2007
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | llc -march=x86 | not grep lea
+; RUN: llvm-as < %s | llc -march=x86-64 | not grep lea
+
+ at B = external global [1000 x i8], align 32
+ at A = external global [1000 x i8], align 32
+ at P = external global [1000 x i8], align 32
+
+define void @foo(i32 %m) {
+entry:
+ %tmp1 = icmp sgt i32 %m, 0
+ br i1 %tmp1, label %bb, label %return
+
+bb:
+ %i.019.0 = phi i32 [ %indvar.next, %bb ], [ 0, %entry ]
+ %tmp2 = getelementptr [1000 x i8]* @B, i32 0, i32 %i.019.0
+ %tmp3 = load i8* %tmp2, align 4
+ %tmp4 = mul i8 %tmp3, 2
+ %tmp5 = getelementptr [1000 x i8]* @A, i32 0, i32 %i.019.0
+ store i8 %tmp4, i8* %tmp5, align 4
+ %tmp8 = mul i32 %i.019.0, 9
+ %tmp10 = getelementptr [1000 x i8]* @P, i32 0, i32 %tmp8
+ store i8 17, i8* %tmp10, align 4
+ %indvar.next = add i32 %i.019.0, 1
+ %exitcond = icmp eq i32 %indvar.next, %m
+ br i1 %exitcond, label %return, label %bb
+
+return:
+ ret void
+}
+
From djg at cray.com Mon Oct 22 15:40:42 2007
From: djg at cray.com (Dan Gohman)
Date: Mon, 22 Oct 2007 20:40:42 -0000
Subject: [llvm-commits] [llvm] r43231 - in /llvm/trunk:
lib/Transforms/Scalar/LoopStrengthReduce.cpp
test/CodeGen/X86/2007-08-10-LEA16Use32.ll
test/CodeGen/X86/stride-nine-with-base-reg.ll
test/CodeGen/X86/stride-reuse.ll
Message-ID: <200710222040.l9MKegSC027675@zion.cs.uiuc.edu>
Author: djg
Date: Mon Oct 22 15:40:42 2007
New Revision: 43231
URL: http://llvm.org/viewvc/llvm-project?rev=43231&view=rev
Log:
Strength reduction improvements.
- Avoid attempting stride-reuse in the case that there are users that
aren't addresses. In that case, there will be places where the
multiplications won't be folded away, so it's better to try to
strength-reduce them.
- Several SSE intrinsics have operands that strength-reduction can
treat as addresses. The previous item makes this more visible, as
any non-address use of an IV can inhibit stride-reuse.
- Make ValidStride aware of whether there's likely to be a base
register in the address computation. This prevents it from thinking
that things like stride 9 are valid on x86 when the base register is
already occupied.
Also, XFAIL the 2007-08-10-LEA16Use32.ll test; the new logic to avoid
stride-reuse elimintes the LEA in the loop, so the test is no longer
testing what it was intended to test.
Added:
llvm/trunk/test/CodeGen/X86/stride-nine-with-base-reg.ll
llvm/trunk/test/CodeGen/X86/stride-reuse.ll
Modified:
llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
llvm/trunk/test/CodeGen/X86/2007-08-10-LEA16Use32.ll
Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=43231&r1=43230&r2=43231&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Oct 22 15:40:42 2007
@@ -175,10 +175,12 @@
bool FindIVForUser(ICmpInst *Cond, IVStrideUse *&CondUse,
const SCEVHandle *&CondStride);
- unsigned CheckForIVReuse(const SCEVHandle&, IVExpr&, const Type*,
+ unsigned CheckForIVReuse(bool, const SCEVHandle&,
+ IVExpr&, const Type*,
const std::vector& UsersToProcess);
- bool ValidStride(int64_t, const std::vector& UsersToProcess);
+ bool ValidStride(bool, int64_t,
+ const std::vector& UsersToProcess);
void StrengthReduceStridedIVUsers(const SCEVHandle &Stride,
IVUsersOfOneStride &Uses,
@@ -937,8 +939,8 @@
/// isZero - returns true if the scalar evolution expression is zero.
///
-static bool isZero(SCEVHandle &V) {
- if (SCEVConstant *SC = dyn_cast(V))
+static bool isZero(const SCEVHandle &V) {
+ if (const SCEVConstant *SC = dyn_cast(V))
return SC->getValue()->isZero();
return false;
}
@@ -946,7 +948,8 @@
/// ValidStride - Check whether the given Scale is valid for all loads and
/// stores in UsersToProcess.
///
-bool LoopStrengthReduce::ValidStride(int64_t Scale,
+bool LoopStrengthReduce::ValidStride(bool HasBaseReg,
+ int64_t Scale,
const std::vector& UsersToProcess) {
for (unsigned i=0, e = UsersToProcess.size(); i!=e; ++i) {
// If this is a load or other access, pass the type of the access in.
@@ -959,6 +962,7 @@
TargetLowering::AddrMode AM;
if (SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm))
AM.BaseOffs = SC->getValue()->getSExtValue();
+ AM.HasBaseReg = HasBaseReg || !isZero(UsersToProcess[i].Base);
AM.Scale = Scale;
// If load[imm+r*scale] is illegal, bail out.
@@ -970,9 +974,11 @@
/// CheckForIVReuse - Returns the multiple if the stride is the multiple
/// of a previous stride and it is a legal value for the target addressing
-/// mode scale component. This allows the users of this stride to be rewritten
-/// as prev iv * factor. It returns 0 if no reuse is possible.
-unsigned LoopStrengthReduce::CheckForIVReuse(const SCEVHandle &Stride,
+/// mode scale component and optional base reg. This allows the users of
+/// this stride to be rewritten as prev iv * factor. It returns 0 if no
+/// reuse is possible.
+unsigned LoopStrengthReduce::CheckForIVReuse(bool HasBaseReg,
+ const SCEVHandle &Stride,
IVExpr &IV, const Type *Ty,
const std::vector& UsersToProcess) {
if (!TLI) return 0;
@@ -992,7 +998,7 @@
// stores; if it can be used for some and not others, we might as well use
// the original stride everywhere, since we have to create the IV for it
// anyway.
- if (ValidStride(Scale, UsersToProcess))
+ if (ValidStride(HasBaseReg, Scale, UsersToProcess))
for (std::vector::iterator II = SI->second.IVs.begin(),
IE = SI->second.IVs.end(); II != IE; ++II)
// FIXME: Only handle base == 0 for now.
@@ -1061,7 +1067,18 @@
// UsersToProcess base values.
SCEVHandle CommonExprs =
RemoveCommonExpressionsFromUseBases(UsersToProcess, SE);
-
+
+ // If we managed to find some expressions in common, we'll need to carry
+ // their value in a register and add it in for each use. This will take up
+ // a register operand, which potentially restricts what stride values are
+ // valid.
+ bool HaveCommonExprs = !isZero(CommonExprs);
+
+ // Keep track if every use in UsersToProcess is an address. If they all are,
+ // we may be able to rewrite the entire collection of them in terms of a
+ // smaller-stride IV.
+ bool AllUsesAreAddresses = true;
+
// Next, figure out what we can represent in the immediate fields of
// instructions. If we can represent anything there, move it to the imm
// fields of the BasedUsers. We do this so that it increases the commonality
@@ -1085,29 +1102,53 @@
isAddress = true;
} else if (IntrinsicInst *II =
dyn_cast(UsersToProcess[i].Inst)) {
- // Addressing modes can also be folded into prefetches.
- if (II->getIntrinsicID() == Intrinsic::prefetch &&
- II->getOperand(1) == UsersToProcess[i].OperandValToReplace)
- isAddress = true;
+ // Addressing modes can also be folded into prefetches and a variety
+ // of intrinsics.
+ switch (II->getIntrinsicID()) {
+ default: break;
+ case Intrinsic::prefetch:
+ case Intrinsic::x86_sse2_loadu_dq:
+ case Intrinsic::x86_sse2_loadu_pd:
+ case Intrinsic::x86_sse_loadu_ps:
+ case Intrinsic::x86_sse_storeu_ps:
+ case Intrinsic::x86_sse2_storeu_pd:
+ case Intrinsic::x86_sse2_storeu_dq:
+ case Intrinsic::x86_sse2_storel_dq:
+ if (II->getOperand(1) == UsersToProcess[i].OperandValToReplace)
+ isAddress = true;
+ break;
+ case Intrinsic::x86_sse2_loadh_pd:
+ case Intrinsic::x86_sse2_loadl_pd:
+ if (II->getOperand(2) == UsersToProcess[i].OperandValToReplace)
+ isAddress = true;
+ break;
+ }
}
+
+ // If this use isn't an address, then not all uses are addresses.
+ if (!isAddress)
+ AllUsesAreAddresses = false;
MoveImmediateValues(TLI, UsersToProcess[i].Inst, UsersToProcess[i].Base,
UsersToProcess[i].Imm, isAddress, L, SE);
}
}
- // Check if it is possible to reuse a IV with stride that is factor of this
- // stride. And the multiple is a number that can be encoded in the scale
- // field of the target addressing mode. And we will have a valid
- // instruction after this substition, including the immediate field, if any.
+ // If all uses are addresses, check if it is possible to reuse an IV with a
+ // stride that is a factor of this stride. And that the multiple is a number
+ // that can be encoded in the scale field of the target addressing mode. And
+ // that we will have a valid instruction after this substition, including the
+ // immediate field, if any.
PHINode *NewPHI = NULL;
Value *IncV = NULL;
IVExpr ReuseIV(SE->getIntegerSCEV(0, Type::Int32Ty),
SE->getIntegerSCEV(0, Type::Int32Ty),
0, 0);
- unsigned RewriteFactor = CheckForIVReuse(Stride, ReuseIV,
- CommonExprs->getType(),
- UsersToProcess);
+ unsigned RewriteFactor = 0;
+ if (AllUsesAreAddresses)
+ RewriteFactor = CheckForIVReuse(HaveCommonExprs, Stride, ReuseIV,
+ CommonExprs->getType(),
+ UsersToProcess);
if (RewriteFactor != 0) {
DOUT << "BASED ON IV of STRIDE " << *ReuseIV.Stride
<< " and BASE " << *ReuseIV.Base << " :\n";
Modified: llvm/trunk/test/CodeGen/X86/2007-08-10-LEA16Use32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-08-10-LEA16Use32.ll?rev=43231&r1=43230&r2=43231&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/2007-08-10-LEA16Use32.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2007-08-10-LEA16Use32.ll Mon Oct 22 15:40:42 2007
@@ -1,4 +1,8 @@
; RUN: llvm-as < %s | llc -march=x86 | grep {leal}
+; XFAIL: *
+; This test is XFAIL'd because strength-reduction was improved to
+; avoid emitting the lea, so it longer tests whether the 16-bit
+; lea is avoided.
@X = global i16 0 ; [#uses=1]
@Y = global i16 0 ; [#uses=1]
Added: llvm/trunk/test/CodeGen/X86/stride-nine-with-base-reg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stride-nine-with-base-reg.ll?rev=43231&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/stride-nine-with-base-reg.ll (added)
+++ llvm/trunk/test/CodeGen/X86/stride-nine-with-base-reg.ll Mon Oct 22 15:40:42 2007
@@ -0,0 +1,34 @@
+; RUN: llvm-as < %s | llc -march=x86 | grep lea | count 1
+; RUN: llvm-as < %s | llc -march=x86-64 | not grep lea
+
+; For x86 there's an lea above the loop. In both cases, there shouldn't
+; be any lea instructions inside the loop.
+
+ at B = external global [1000 x i8], align 32
+ at A = external global [1000 x i8], align 32
+ at P = external global [1000 x i8], align 32
+
+define void @foo(i32 %m, i32 %p) {
+entry:
+ %tmp1 = icmp sgt i32 %m, 0
+ br i1 %tmp1, label %bb, label %return
+
+bb:
+ %i.019.0 = phi i32 [ %indvar.next, %bb ], [ 0, %entry ]
+ %tmp2 = getelementptr [1000 x i8]* @B, i32 0, i32 %i.019.0
+ %tmp3 = load i8* %tmp2, align 4
+ %tmp4 = mul i8 %tmp3, 2
+ %tmp5 = getelementptr [1000 x i8]* @A, i32 0, i32 %i.019.0
+ store i8 %tmp4, i8* %tmp5, align 4
+ %tmp8 = mul i32 %i.019.0, 9
+ %tmp0 = add i32 %tmp8, %p
+ %tmp10 = getelementptr [1000 x i8]* @P, i32 0, i32 %tmp0
+ store i8 17, i8* %tmp10, align 4
+ %indvar.next = add i32 %i.019.0, 1
+ %exitcond = icmp eq i32 %indvar.next, %m
+ br i1 %exitcond, label %return, label %bb
+
+return:
+ ret void
+}
+
Added: llvm/trunk/test/CodeGen/X86/stride-reuse.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/stride-reuse.ll?rev=43231&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/stride-reuse.ll (added)
+++ llvm/trunk/test/CodeGen/X86/stride-reuse.ll Mon Oct 22 15:40:42 2007
@@ -0,0 +1,30 @@
+; RUN: llvm-as < %s | llc -march=x86 | not grep lea
+; RUN: llvm-as < %s | llc -march=x86-64 | not grep lea
+
+ at B = external global [1000 x float], align 32
+ at A = external global [1000 x float], align 32
+ at P = external global [1000 x i32], align 32
+
+define void @foo(i32 %m) {
+entry:
+ %tmp1 = icmp sgt i32 %m, 0
+ br i1 %tmp1, label %bb, label %return
+
+bb:
+ %i.019.0 = phi i32 [ %indvar.next, %bb ], [ 0, %entry ]
+ %tmp2 = getelementptr [1000 x float]* @B, i32 0, i32 %i.019.0
+ %tmp3 = load float* %tmp2, align 4
+ %tmp4 = mul float %tmp3, 2.000000e+00
+ %tmp5 = getelementptr [1000 x float]* @A, i32 0, i32 %i.019.0
+ store float %tmp4, float* %tmp5, align 4
+ %tmp8 = shl i32 %i.019.0, 1
+ %tmp9 = add i32 %tmp8, 64
+ %tmp10 = getelementptr [1000 x i32]* @P, i32 0, i32 %i.019.0
+ store i32 %tmp9, i32* %tmp10, align 4
+ %indvar.next = add i32 %i.019.0, 1
+ %exitcond = icmp eq i32 %indvar.next, %m
+ br i1 %exitcond, label %return, label %bb
+
+return:
+ ret void
+}
From djg at cray.com Mon Oct 22 15:44:10 2007
From: djg at cray.com (Dan Gohman)
Date: Mon, 22 Oct 2007 20:44:10 -0000
Subject: [llvm-commits] [llvm] r43232 - /llvm/trunk/lib/VMCore/ConstantFold.h
Message-ID: <200710222044.l9MKiAgg027994@zion.cs.uiuc.edu>
Author: djg
Date: Mon Oct 22 15:44:10 2007
New Revision: 43232
URL: http://llvm.org/viewvc/llvm-project?rev=43232&view=rev
Log:
The #include isn't needed in this header.
Modified:
llvm/trunk/lib/VMCore/ConstantFold.h
Modified: llvm/trunk/lib/VMCore/ConstantFold.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ConstantFold.h?rev=43232&r1=43231&r2=43232&view=diff
==============================================================================
--- llvm/trunk/lib/VMCore/ConstantFold.h (original)
+++ llvm/trunk/lib/VMCore/ConstantFold.h Mon Oct 22 15:44:10 2007
@@ -19,8 +19,6 @@
#ifndef CONSTANTFOLDING_H
#define CONSTANTFOLDING_H
-#include
-
namespace llvm {
class Value;
class Constant;
@@ -48,7 +46,6 @@
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
const Constant *C1,
const Constant *C2);
-
Constant *ConstantFoldGetElementPtr(const Constant *C,
Constant* const *Idxs, unsigned NumIdx);
} // End llvm namespace
From evan.cheng at apple.com Mon Oct 22 16:31:06 2007
From: evan.cheng at apple.com (Evan Cheng)
Date: Mon, 22 Oct 2007 14:31:06 -0700
Subject: [llvm-commits] [llvm] r43176 - in /llvm/trunk/lib/Target/ARM:
ARMISelLowering.cpp ARMISelLowering.h
In-Reply-To: <200710191435.l9JEZIAM018674@zion.cs.uiuc.edu>
References: <200710191435.l9JEZIAM018674@zion.cs.uiuc.edu>
Message-ID: <90524216-7D9B-4B62-9FFF-E5669A37DEF9@apple.com>
Hi Rafael,
There a couple of problems with this patch.
1. This breaks a number of tests for me:
llc-beta /MultiSource/Applications/JM/ldecod/ldecod
llc /MultiSource/Applications/JM/ldecod/ldecod
llc /External/SPEC/CINT2000/254.gap/254.gap
llc /MultiSource/Benchmarks/MiBench/office-ispell/office-ispell
llc-beta /MultiSource/Benchmarks/MiBench/office-ispell/office-ispell
llc-beta /External/SPEC/CINT2000/254.gap/254.gap
LowerMEMCPYInline() is asserting when the memcpy is 4-byte aligned but
the size isn't multiple of 4. I'm going to remove the assertion and
issue byte / word loads / stores to handle the trailing bytes. Please
let me know if that's undesirable.
2. The stores are unnecessarily serialized. Each of them should use
the load tokenfactor as input chain. All the chains produced by the
stores should then be fed into a new tokenfactor. I'll fix this.
Thanks,
Evan
On Oct 19, 2007, at 7:35 AM, Rafael Espindola wrote:
> Author: rafael
> Date: Fri Oct 19 09:35:17 2007
> New Revision: 43176
>
> URL: http://llvm.org/viewvc/llvm-project?rev=43176&view=rev
> Log:
> split LowerMEMCPY into LowerMEMCPYCall and LowerMEMCPYInline in the
> ARM backend.
>
> Modified:
> llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> llvm/trunk/lib/Target/ARM/ARMISelLowering.h
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=43176&r1=43175&r2=43176&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Oct 19
> 09:35:17 2007
> @@ -1288,40 +1288,73 @@
> }
>
> SDOperand ARMTargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG
> &DAG) {
> - SDOperand Chain = Op.getOperand(0);
> - SDOperand Dest = Op.getOperand(1);
> - SDOperand Src = Op.getOperand(2);
> - SDOperand Count = Op.getOperand(3);
> - unsigned Align =
> - (unsigned)cast(Op.getOperand(4))->getValue();
> + SDOperand ChainOp = Op.getOperand(0);
> + SDOperand DestOp = Op.getOperand(1);
> + SDOperand SourceOp = Op.getOperand(2);
> + SDOperand CountOp = Op.getOperand(3);
> + SDOperand AlignOp = Op.getOperand(4);
> + SDOperand AlwaysInlineOp = Op.getOperand(5);
> +
> + bool AlwaysInline = (bool)cast(AlwaysInlineOp)-
> >getValue();
> + unsigned Align = (unsigned)cast(AlignOp)-
> >getValue();
> if (Align == 0) Align = 1;
>
> - ConstantSDNode *I = dyn_cast(Count);
> - // Just call memcpy if:
> - // not 4-byte aligned
> - // size is unknown
> - // size is >= the threshold.
> - if ((Align & 3) != 0 ||
> - !I ||
> - I->getValue() >= 64 ||
> - (I->getValue() & 3) != 0) {
> - MVT::ValueType IntPtr = getPointerTy();
> - TargetLowering::ArgListTy Args;
> - TargetLowering::ArgListEntry Entry;
> - Entry.Ty = getTargetData()->getIntPtrType();
> - Entry.Node = Op.getOperand(1); Args.push_back(Entry);
> - Entry.Node = Op.getOperand(2); Args.push_back(Entry);
> - Entry.Node = Op.getOperand(3); Args.push_back(Entry);
> - std::pair CallResult =
> + // If size is unknown, call memcpy.
> + ConstantSDNode *I = dyn_cast(CountOp);
> + if (!I) {
> + assert(!AlwaysInline && "Cannot inline copy of unknown size");
> + return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
> + }
> + unsigned Size = I->getValue();
> +
> + if (AlwaysInline)
> + return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size,
> Align, DAG);
> +
> + // The libc version is likely to be faster for the following
> cases. It can
> + // use the address value and run time information about the CPU.
> + // With glibc 2.6.1 on a core 2, coping an array of 100M longs
> was 30% faster
> +
> + // If not DWORD aligned, call memcpy.
> + if ((Align & 3) != 0)
> + return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
> +
> + // If size is more than the threshold, call memcpy.
> + // if (Size > Subtarget->getMinRepStrSizeThreshold())
> + if (Size >= 64)
> + return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
> +
> + return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align,
> DAG);
> +}
> +
> +SDOperand ARMTargetLowering::LowerMEMCPYCall(SDOperand Chain,
> + SDOperand Dest,
> + SDOperand Source,
> + SDOperand Count,
> + SelectionDAG &DAG) {
> + MVT::ValueType IntPtr = getPointerTy();
> + TargetLowering::ArgListTy Args;
> + TargetLowering::ArgListEntry Entry;
> + Entry.Ty = getTargetData()->getIntPtrType();
> + Entry.Node = Dest; Args.push_back(Entry);
> + Entry.Node = Source; Args.push_back(Entry);
> + Entry.Node = Count; Args.push_back(Entry);
> + std::pair CallResult =
> LowerCallTo(Chain, Type::VoidTy, false, false, CallingConv::C,
> false,
> DAG.getExternalSymbol("memcpy", IntPtr), Args, DAG);
> - return CallResult.second;
> - }
> + return CallResult.second;
> +}
> +
> +SDOperand ARMTargetLowering::LowerMEMCPYInline(SDOperand Chain,
> + SDOperand Dest,
> + SDOperand Source,
> + unsigned Size,
> + unsigned Align,
> + SelectionDAG &DAG) {
>
> - // Otherwise do repeated 4-byte loads and stores. To be improved.
> - assert((I->getValue() & 3) == 0);
> + // Do repeated 4-byte loads and stores. To be improved.
> + assert((Size& 3) == 0);
> assert((Align & 3) == 0);
> - unsigned NumMemOps = I->getValue() >> 2;
> + unsigned NumMemOps = Size >> 2;
> unsigned EmittedNumMemOps = 0;
> unsigned SrcOff = 0, DstOff = 0;
> MVT::ValueType VT = MVT::i32;
> @@ -1337,7 +1370,7 @@
> unsigned i;
> for (i=0; i ++) {
> Loads[i] = DAG.getLoad(VT, Chain,
> - DAG.getNode(ISD::ADD, VT, Src,
> + DAG.getNode(ISD::ADD, VT, Source,
> DAG.getConstant(SrcOff, VT)),
> NULL, 0);
> LoadChains[i] = Loads[i].getValue(1);
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=43176&r1=43175&r2=43176&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Fri Oct 19 09:35:17
> 2007
> @@ -135,6 +135,14 @@
> SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
> SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG);
> SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG);
> + SDOperand LowerMEMCPYCall(SDOperand Chain, SDOperand Dest,
> + SDOperand Source, SDOperand Count,
> + SelectionDAG &DAG);
> + SDOperand LowerMEMCPYInline(SDOperand Chain, SDOperand Dest,
> + SDOperand Source, unsigned Size,
> + unsigned Align, SelectionDAG &DAG);
> +
> +
> };
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
From djg at cray.com Mon Oct 22 17:05:07 2007
From: djg at cray.com (Dan Gohman)
Date: Mon, 22 Oct 2007 17:05:07 -0500
Subject: [llvm-commits] [llvm] r43221 - in /llvm/trunk/docs/tutorial:
LangImpl3.html index.html
Message-ID: <20071022220507.GC22306@village.us.cray.com>
> "Value" is the class used to represent a "register" in LLVM. The Codegen() method says to emit IR for that AST
It would be good to mention that the "registers" here cannot be reassigned,
as the word "register" might seem to imply.
I don't know much you want to say about SSA at this point in the tutorial,
or if you want to go into using entry-block Allocas and mem2reg to avoid
having to compute SSA in a front-end here, but it's something that should
be mentioned somewhere.
> NumberExprAST(double val) : Val(val) {}
> VariableExprAST(const std::string &name) : Name(name) {}
These miss explicit keywords.
> case '+': return Builder.CreateAdd(L, R, "addtmp");
> case '-': return Builder.CreateSub(L, R, "subtmp");
> case '*': return Builder.CreateMul(L, R, "multmp");
You might mention that the names "addtmp" and so on are automatically
make unique by LLVM in case there's more than one add in the program,
for example.
Dan
--
Dan Gohman, Cray Inc.
From evan.cheng at apple.com Mon Oct 22 17:11:30 2007
From: evan.cheng at apple.com (Evan Cheng)
Date: Mon, 22 Oct 2007 22:11:30 -0000
Subject: [llvm-commits] [llvm] r43234 - in /llvm/trunk:
lib/Target/ARM/ARMISelLowering.cpp lib/Target/ARM/ARMISelLowering.h
lib/Target/ARM/README-Thumb.txt test/CodeGen/ARM/memcpy-inline.ll
Message-ID: <200710222211.l9MMBUk2032292@zion.cs.uiuc.edu>
Author: evancheng
Date: Mon Oct 22 17:11:27 2007
New Revision: 43234
URL: http://llvm.org/viewvc/llvm-project?rev=43234&view=rev
Log:
Fix memcpy lowering when addresses are 4-byte aligned but size is not multiple of 4.
Added:
llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll
Modified:
llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
llvm/trunk/lib/Target/ARM/ARMISelLowering.h
llvm/trunk/lib/Target/ARM/README-Thumb.txt
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=43234&r1=43233&r2=43234&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Oct 22 17:11:27 2007
@@ -1287,7 +1287,8 @@
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
}
-SDOperand ARMTargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) {
+SDOperand ARMTargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG,
+ const ARMSubtarget *ST) {
SDOperand ChainOp = Op.getOperand(0);
SDOperand DestOp = Op.getOperand(1);
SDOperand SourceOp = Op.getOperand(2);
@@ -1305,25 +1306,18 @@
assert(!AlwaysInline && "Cannot inline copy of unknown size");
return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
}
- unsigned Size = I->getValue();
-
- if (AlwaysInline)
- return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG);
- // The libc version is likely to be faster for the following cases. It can
+ // If not DWORD aligned or if size is more than threshold, then call memcpy.
+ // The libc version is likely to be faster for the these cases. It can
// use the address value and run time information about the CPU.
// With glibc 2.6.1 on a core 2, coping an array of 100M longs was 30% faster
-
- // If not DWORD aligned, call memcpy.
- if ((Align & 3) != 0)
- return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
-
- // If size is more than the threshold, call memcpy.
- // if (Size > Subtarget->getMinRepStrSizeThreshold())
- if (Size >= 64)
- return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
-
- return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG);
+ // FIXME: For now, we don't lower memcpy's to loads / stores for Thumb. Change
+ // this once Thumb ldmia / stmia support is added.
+ unsigned Size = I->getValue();
+ if (AlwaysInline ||
+ (!ST->isThumb() && Size < 64 && (Align & 3) == 0))
+ return LowerMEMCPYInline(ChainOp, DestOp, SourceOp, Size, Align, DAG);
+ return LowerMEMCPYCall(ChainOp, DestOp, SourceOp, CountOp, DAG);
}
SDOperand ARMTargetLowering::LowerMEMCPYCall(SDOperand Chain,
@@ -1350,46 +1344,93 @@
unsigned Size,
unsigned Align,
SelectionDAG &DAG) {
-
- // Do repeated 4-byte loads and stores. To be improved.
- assert((Size& 3) == 0);
- assert((Align & 3) == 0);
+ // Do repeated 4-byte loads and stores. To be improved.
+ assert((Align & 3) == 0 && "Expected 4-byte aligned addresses!");
+ unsigned BytesLeft = Size & 3;
unsigned NumMemOps = Size >> 2;
unsigned EmittedNumMemOps = 0;
unsigned SrcOff = 0, DstOff = 0;
MVT::ValueType VT = MVT::i32;
unsigned VTSize = 4;
+ unsigned i = 0;
const unsigned MAX_LOADS_IN_LDM = 6;
- SDOperand LoadChains[MAX_LOADS_IN_LDM];
+ SDOperand TFOps[MAX_LOADS_IN_LDM];
SDOperand Loads[MAX_LOADS_IN_LDM];
- // Emit up to 4 loads, then a TokenFactor barrier, then the same
- // number of stores. The loads and stores will get combined into
+ // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
+ // same number of stores. The loads and stores will get combined into
// ldm/stm later on.
- while(EmittedNumMemOps < NumMemOps) {
- unsigned i;
- for (i=0; i= 2) {
+ VT = MVT::i16;
+ VTSize = 2;
+ } else {
+ VT = MVT::i8;
+ VTSize = 1;
+ }
+
+ Loads[i] = DAG.getLoad(VT, Chain,
+ DAG.getNode(ISD::ADD, MVT::i32, Source,
+ DAG.getConstant(SrcOff, MVT::i32)),
+ NULL, 0);
+ TFOps[i] = Loads[i].getValue(1);
+ ++i;
+ SrcOff += VTSize;
+ BytesLeft -= VTSize;
+ }
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &TFOps[0], i);
+
+ i = 0;
+ BytesLeft = BytesLeftSave;
+ while (BytesLeft) {
+ if (BytesLeft >= 2) {
+ VT = MVT::i16;
+ VTSize = 2;
+ } else {
+ VT = MVT::i8;
+ VTSize = 1;
+ }
+
+ TFOps[i] = DAG.getStore(Chain, Loads[i],
+ DAG.getNode(ISD::ADD, MVT::i32, Dest,
+ DAG.getConstant(DstOff, MVT::i32)),
+ NULL, 0);
+ ++i;
+ DstOff += VTSize;
+ BytesLeft -= VTSize;
+ }
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, &TFOps[0], i);
}
SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
@@ -1419,7 +1460,7 @@
case ISD::RETURNADDR: break;
case ISD::FRAMEADDR: break;
case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
- case ISD::MEMCPY: return LowerMEMCPY(Op, DAG);
+ case ISD::MEMCPY: return LowerMEMCPY(Op, DAG, Subtarget);
}
return SDOperand();
}
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=43234&r1=43233&r2=43234&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Mon Oct 22 17:11:27 2007
@@ -130,11 +130,12 @@
SDOperand LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
SelectionDAG &DAG);
SDOperand LowerToTLSExecModels(GlobalAddressSDNode *GA,
- SelectionDAG &DAG);
+ SelectionDAG &DAG);
SDOperand LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG);
- SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG);
+ SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG,
+ const ARMSubtarget *ST);
SDOperand LowerMEMCPYCall(SDOperand Chain, SDOperand Dest,
SDOperand Source, SDOperand Count,
SelectionDAG &DAG);
Modified: llvm/trunk/lib/Target/ARM/README-Thumb.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/README-Thumb.txt?rev=43234&r1=43233&r2=43234&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/README-Thumb.txt (original)
+++ llvm/trunk/lib/Target/ARM/README-Thumb.txt Mon Oct 22 17:11:27 2007
@@ -221,3 +221,7 @@
Make register allocator / spiller smarter so we can re-materialize "mov r, imm",
etc. Almost all Thumb instructions clobber condition code.
+
+//===---------------------------------------------------------------------===//
+
+Add ldmia, stmia support.
Added: llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll?rev=43234&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll Mon Oct 22 17:11:27 2007
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep ldmia
+; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep ldrb
+; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep ldrh
+
+ %struct.x = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 }
+ at src = external global %struct.x
+ at dst = external global %struct.x
+
+define i32 @t() {
+entry:
+ call void @llvm.memcpy.i32( i8* getelementptr (%struct.x* @dst, i32 0, i32 0), i8* getelementptr (%struct.x* @src, i32 0, i32 0), i32 11, i32 8 )
+ ret i32 0
+}
+
+declare void @llvm.memcpy.i32(i8*, i8*, i32, i32)
From resistor at mac.com Mon Oct 22 19:02:48 2007
From: resistor at mac.com (Owen Anderson)
Date: Mon, 22 Oct 2007 19:02:48 -0500
Subject: [llvm-commits] [llvm] r43221 - in
/llvm/trunk/docs/tutorial: LangImpl3.html index.html
Message-ID: <8ABBD4C2-17FD-4335-886C-F6A52C21F63A@mac.com>
Dan,
I'm planning to cover both of those points in the "Basic Topics"
sections of the tutorial.
--Owen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2555 bytes
Desc: not available
Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20071022/4856dd20/attachment.bin
From owen at apple.com Mon Oct 22 18:11:24 2007
From: owen at apple.com (Owen Anderson)
Date: Mon, 22 Oct 2007 18:11:24 -0500
Subject: [llvm-commits] [llvm] r43221 - in
/llvm/trunk/docs/tutorial: LangImpl3.html index.html
Message-ID:
Dan,
I'm planning to cover both of those points in the "Basic Topics"
sections of the tutorial.
--Owen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2555 bytes
Desc: not available
Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20071022/5690c2b5/attachment.bin
From owen at apple.com Mon Oct 22 18:11:24 2007
From: owen at apple.com (Owen Anderson)
Date: Mon, 22 Oct 2007 18:11:24 -0500
Subject: [llvm-commits] [llvm] r43221 - in
/llvm/trunk/docs/tutorial: LangImpl3.html index.html
Message-ID:
Dan,
I'm planning to cover both of those points in the "Basic Topics"
sections of the tutorial.
--Owen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2555 bytes
Desc: not available
Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20071022/5690c2b5/attachment-0001.bin
From nlewycky at google.com Mon Oct 22 22:55:28 2007
From: nlewycky at google.com (Nicholas Lewycky)
Date: Mon, 22 Oct 2007 20:55:28 -0700
Subject: [llvm-commits] makeinfo versions for llvm-gcc
Message-ID:
Hi,
There's a problem with the makeinfo test in llvm-gcc where it checks for a
makeinfo version >= 4.4. It treats 4.10 as less than 4.4 The attached patch
should be applied to both llvm-gcc4.0 and 4.2.
Thanks,
Nick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20071022/6dd8b20c/attachment.html
From nlewycky at google.com Mon Oct 22 22:56:13 2007
From: nlewycky at google.com (Nicholas Lewycky)
Date: Mon, 22 Oct 2007 20:56:13 -0700
Subject: [llvm-commits] makeinfo versions for llvm-gcc
Message-ID:
and this time with the attachment!
Hi,
There's a problem with the makeinfo test in llvm-gcc where it checks for a
makeinfo version >= 4.4. It treats 4.10 as less than 4.4 The attached patch
should be applied to both llvm-gcc4.0 and 4.2.
Thanks,
Nick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20071022/7b59802f/attachment.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: makeinfo.patch
Type: text/x-patch
Size: 561 bytes
Desc: not available
Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20071022/7b59802f/attachment.bin
From clattner at apple.com Mon Oct 22 23:29:04 2007
From: clattner at apple.com (Chris Lattner)
Date: Mon, 22 Oct 2007 21:29:04 -0700
Subject: [llvm-commits] [llvm] r43221 - in /llvm/trunk/docs/tutorial:
LangImpl3.html index.html
In-Reply-To: <20071022220507.GC22306@village.us.cray.com>
References: <20071022220507.GC22306@village.us.cray.com>
Message-ID:
On Oct 22, 2007, at 3:05 PM, Dan Gohman wrote:
>> "Value" is the class used to represent a "register" in LLVM. The
>> Codegen() method says to emit IR for that AST
>
> It would be good to mention that the "registers" here cannot be
> reassigned,
> as the word "register" might seem to imply.
Good idea.
> I don't know much you want to say about SSA at this point in the
> tutorial,
> or if you want to go into using entry-block Allocas and mem2reg to
> avoid
> having to compute SSA in a front-end here, but it's something that
> should
> be mentioned somewhere.
I plan to unveil it slowly: in the if/then/else chapter, I'll talk
about phi nodes. In the "mutable variables" chapter, I'll talk about
the alloca trick.
>> NumberExprAST(double val) : Val(val) {}
>
>> VariableExprAST(const std::string &name) : Name(name) {}
>
> These miss explicit keywords.
*grumble* explicit should be the default *grumble* :)
>> case '+': return Builder.CreateAdd(L, R, "addtmp");
>> case '-': return Builder.CreateSub(L, R, "subtmp");
>> case '*': return Builder.CreateMul(L, R, "multmp");
>
> You might mention that the names "addtmp" and so on are automatically
> make unique by LLVM in case there's more than one add in the program,
> for example.
will do!
-Chris
From sabre at nondot.org Mon Oct 22 23:51:30 2007
From: sabre at nondot.org (Chris Lattner)
Date: Tue, 23 Oct 2007 04:51:30 -0000
Subject: [llvm-commits] [llvm] r43238 -
/llvm/trunk/docs/tutorial/LangImpl3.html
Message-ID: <200710230451.l9N4pUiZ019001@zion.cs.uiuc.edu>
Author: lattner
Date: Mon Oct 22 23:51:30 2007
New Revision: 43238
URL: http://llvm.org/viewvc/llvm-project?rev=43238&view=rev
Log:
Finish up expr codegen.
Modified:
llvm/trunk/docs/tutorial/LangImpl3.html
Modified: llvm/trunk/docs/tutorial/LangImpl3.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl3.html?rev=43238&r1=43237&r2=43238&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl3.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl3.html Mon Oct 22 23:51:30 2007
@@ -132,12 +132,13 @@
-
In the LLVM IR, numeric constants are represented with the ConstantFP class,
-which holds the numeric value in an APFloat internally (APFloat has the
-capability of holding floating point constants of arbitrary precision). This
-code basically just creates and returns a ConstantFP. Note that in the LLVM IR
+
In the LLVM IR, numeric constants are represented with the
+ConstantFP class, which holds the numeric value in an APFloat
+internally (APFloat has the capability of holding floating point
+constants of Arbitrary Precision). This code basically just
+creates and returns a ConstantFP. Note that in the LLVM IR
that constants are all uniqued together and shared. For this reason, the API
-uses "the foo::get(...)" idiom instead of a "create" method or "new foo".
+uses "the foo::get(..)" idiom instead of "new foo(..)" or "foo::create(..).
@@ -149,9 +150,10 @@
-
References to variables is also quite simple here. In our system, we assume
-that the variable has already been emited somewhere and its value is available.
-In practice, the only values in the NamedValues map will be arguments. This
+
References to variables is also quite simple here. In the simple version
+of Kaleidoscope, we assume that the variable has already been emited somewhere
+and its value is available. In practice, the only values that can be in the
+NamedValues map are function arguments. This
code simply checks to see that the specified name is in the map (if not, an
unknown variable is being referenced) and returns the value for it.
@@ -176,7 +178,38 @@
-
+
Binary operators start to get more interesting. The basic idea here is that
+we recursively emit code for the left-hand side of the expression, then the
+right-hand side, then we compute the result of the binary expression. In this
+code, we do a simple switch on the opcode to create the right LLVM instruction.
+
+
+
In this example, the LLVM builder class is starting to show its value.
+Because it knows where to insert the newly created instruction, you just have to
+specificy what instruction to create (e.g. with CreateAdd), which
+operands to use (L and R here) and optionally provide a name
+for the generated instruction. One nice thing about LLVM is that the name is
+just a hint: if there are multiple additions in a single function, the first
+will be named "addtmp" and the second will be "autorenamed" by adding a suffix,
+giving it a name like "addtmp42". Local value names for instructions are purely
+optional, but it makes it much easier to read the IR dumps.
+
+
LLVM instructions are constrained to
+have very strict type properties: for example, the Left and Right operators of
+an add instruction have to have the same
+type, and that the result of the add matches the operands. Because all values
+in Kaleidoscope are doubles, this makes for very simple code for add, sub and
+mul.
+
+
On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value
+(a one bit integer). However, Kaleidoscope wants the value to be a 0.0 or 1.0
+value. In order to get these semantics, we combine the fcmp instruction with
+a uitofp instruction. This instruction
+converts its input integer into a floating point value by treating the input
+as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<'
+operator would return 0.0 and -1.0, depending on the input value.
@@ -201,7 +234,24 @@
-
more todo
+
Code generation for function calls is quite straight-forward with LLVM. The
+code above first looks the name of the function up in the LLVM Module's symbol
+table. Recall that the LLVM Module is the container that holds all of the
+functions we are JIT'ing. By giving each function the same name as what the
+user specifies, we can use the LLVM symbol table to resolve function names for
+us.
+
+
Once we have the function to call, we recursively codegen each argument that
+is to be passed in, and create an LLVM call
+instruction. Note that LLVM uses the native C calling conventions by
+default, allowing these calls to call into standard library functions like
+"sin" and "cos" with no additional effort.
+
+
This wraps up our handling of the four basic expressions that we have so far
+in Kaleidoscope. Feel free to go in and add some more. For example, by
+browsing the LLVM language reference you'll find
+several other interesting instructions that are really easy to plug into our
+basic framework.
From sabre at nondot.org Mon Oct 22 23:27:45 2007
From: sabre at nondot.org (Chris Lattner)
Date: Tue, 23 Oct 2007 04:27:45 -0000
Subject: [llvm-commits] [llvm] r43237 - in /llvm/trunk/docs/tutorial:
LangImpl2.html LangImpl3.html
Message-ID: <200710230427.l9N4RkmV018163@zion.cs.uiuc.edu>
Author: lattner
Date: Mon Oct 22 23:27:44 2007
New Revision: 43237
URL: http://llvm.org/viewvc/llvm-project?rev=43237&view=rev
Log:
several improvements suggested by Dan, thanks!
Modified:
llvm/trunk/docs/tutorial/LangImpl2.html
llvm/trunk/docs/tutorial/LangImpl3.html
Modified: llvm/trunk/docs/tutorial/LangImpl2.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl2.html?rev=43237&r1=43236&r2=43237&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl2.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl2.html Mon Oct 22 23:27:44 2007
@@ -65,7 +65,7 @@
class NumberExprAST : public ExprAST {
double Val;
public:
- NumberExprAST(double val) : Val(val) {}
+ explicit NumberExprAST(double val) : Val(val) {}
};
@@ -87,7 +87,7 @@
class VariableExprAST : public ExprAST {
std::string Name;
public:
- VariableExprAST(const std::string &name) : Name(name) {}
+ explicit VariableExprAST(const std::string &name) : Name(name) {}
};
/// BinaryExprAST - Expression class for a binary operator.
@@ -850,14 +850,14 @@
class NumberExprAST : public ExprAST {
double Val;
public:
- NumberExprAST(double val) : Val(val) {}
+ explicit NumberExprAST(double val) : Val(val) {}
};
/// VariableExprAST - Expression class for referencing a variable, like "a".
class VariableExprAST : public ExprAST {
std::string Name;
public:
- VariableExprAST(const std::string &name) : Name(name) {}
+ explicit VariableExprAST(const std::string &name) : Name(name) {}
};
/// BinaryExprAST - Expression class for a binary operator.
Modified: llvm/trunk/docs/tutorial/LangImpl3.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl3.html?rev=43237&r1=43236&r2=43237&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl3.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl3.html Mon Oct 22 23:27:44 2007
@@ -56,15 +56,26 @@
class NumberExprAST : public ExprAST {
double Val;
public:
- NumberExprAST(double val) : Val(val) {}
+ explicit NumberExprAST(double val) : Val(val) {}
virtual Value *Codegen();
};
...
-
"Value" is the class used to represent a "register" in LLVM. The Codegen()
-method says to emit IR for that AST node and all things it depends on. The
+
The Codegen() method says to emit IR for that AST node and all things it
+depends on, and they all return an LLVM Value object.
+"Value" is the class used to represent a "Static Single
+Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect
+of SSA values is that their value is computed as the related instruction
+executes, and it does not get a new value until (and if) the instruction
+re-executes. In order words, there is no way to "change" an SSA value. For
+more information, please read up on Static Single
+Assignment - the concepts are really quite natural once you grok them.
+
+
The
second thing we want is an "Error" method like we used for parser, which will
be used to report errors found during code generation (for example, use of an
undeclared parameter):
@@ -299,7 +310,7 @@
class NumberExprAST : public ExprAST {
double Val;
public:
- NumberExprAST(double val) : Val(val) {}
+ explicit NumberExprAST(double val) : Val(val) {}
virtual Value *Codegen();
};
@@ -307,7 +318,7 @@
class VariableExprAST : public ExprAST {
std::string Name;
public:
- VariableExprAST(const std::string &name) : Name(name) {}
+ explicit VariableExprAST(const std::string &name) : Name(name) {}
virtual Value *Codegen();
};
From sabre at nondot.org Tue Oct 23 00:43:01 2007
From: sabre at nondot.org (Chris Lattner)
Date: Tue, 23 Oct 2007 05:43:01 -0000
Subject: [llvm-commits] [llvm] r43239 -
/llvm/trunk/docs/tutorial/LangImpl2.html
Message-ID: <200710230543.l9N5h1vd021070@zion.cs.uiuc.edu>
Author: lattner
Date: Tue Oct 23 00:43:01 2007
New Revision: 43239
URL: http://llvm.org/viewvc/llvm-project?rev=43239&view=rev
Log:
Fix up a broken #include, move code to its own section, add conclusions.
Modified:
llvm/trunk/docs/tutorial/LangImpl2.html
Modified: llvm/trunk/docs/tutorial/LangImpl2.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl2.html?rev=43239&r1=43238&r2=43239&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl2.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl2.html Tue Oct 23 00:43:01 2007
@@ -753,20 +753,40 @@
+
There is a lot of room for extension here. You can define new AST nodes,
+extend the language in many ways, etc. In the next
+installment, we will describe how to generate LLVM IR from the AST.
-Here is the full code. Note that it is fully self-contained: you don't even
-need LLVM for this. In the next installment, we
-will describe how to generate LLVM IR from the AST.
+Here is the complete code listing for this and the previous chapter.
+Note that it is fully self-contained: you don't need LLVM or any external
+libraries at all for this (other than the C and C++ standard libraries of
+course). To build this, just compile with:
Now that we understand the basics of creating functions in LLVM, let's move on to a more complicated example: something with control flow. As an example, let's consider Euclid's Greatest Common Denominator (GCD) algorithm:
With this example, we'll learn how to create functions with multiple blocks and control flow, and how to make function calls within your LLVM code. For starters, consider the diagram below.
+
+
+
+
The above is a graphical representation of a program in LLVM IR. It places each basic block on a node of a graph, and uses directed edges to indicate flow control. These blocks will be serialized when written to a text or bitcode file, but it is often useful conceptually to think of them as a graph. Again, if you are unsure about the code in the diagram, you should skim through the LLVM Language Reference Manual and convince yourself that it is, in fact, the GCD algorithm.
+
+
The first part of our code is the same as from first tutorial. The same basic setup is required: creating a module, verifying it, and running the PrintModulePass on it. Even the first segment of makeLLVMModule() looks the same, because gcd happens the have the same prototype as our mul_add function.
Here, however, is where our code begins to diverge from the first tutorial. Because gcd has control flow, it is composed of multiple blocks interconnected by branching (br) instructions. For those familiar with assembly language, a block is similar to a labeled set of instructions. For those not familiar with assembly language, a block is basically a set of instructions that can be branched to and is executed linearly until the block is terminated by one of a small number of control flow instructions, such as br or ret.
+
+
Blocks corresponds to the nodes in the diagram we looked at in the beginning of this tutorial. From the diagram, we can see that this function contains five blocks, so we'll go ahead and create them. Note that, in this code sample, we're making use of LLVM's automatic name uniquing, since we're giving two blocks the same name.
+
+
+
+ BasicBlock* entry = new BasicBlock("entry", gcd);
+ BasicBlock* ret = new BasicBlock("return", gcd);
+ BasicBlock* cond_false = new BasicBlock("cond_false", gcd);
+ BasicBlock* cond_true = new BasicBlock("cond_true", gcd);
+ BasicBlock* cond_false_2 = new BasicBlock("cond_false", gcd);
+
+
+
+
Now, we're ready to begin generate code! We'll start with the entry block. This block corresponds to the top-level if-statement in the original C code, so we need to compare x == y To achieve this, we perform an explicity comparison using ICmpEQ. ICmpEQ stands for an integer comparison for equality and returns a 1-bit integer result. This 1-bit result is then used as the input to a conditional branch, with ret as the true and cond_false as the false case.
Our next block, ret, is pretty simple: it just returns the value of x. Recall that this block is only reached if x == y, so this is the correct behavior. Notice that, instead of creating a new LLVMBuilder for each block, we can use SetInsertPoint to retarget our existing one. This saves on construction and memory allocation costs.
cond_false is a more interesting block: we now know that x != y, so we must branch again to determine which of x and y is larger. This is achieved using the ICmpULT instruction, which stands for integer comparison for unsigned less-than. In LLVM, integer types do not carry sign; a 32-bit integer pseudo-register can interpreted as signed or unsigned without casting. Whether a signed or unsigned interpretation is desired is specified in the instruction. This is why several instructions in the LLVM IR, such as integer less-than, include a specifier for signed or unsigned.
+
+
Also, note that we're again making use of LLVM's automatic name uniquing, this time at a register level. We've deliberately chosen to name every instruction "tmp", to illustrate that LLVM will give them all unique names without getting confused.
Our last two blocks are quite similar; they're both recursive calls to gcd with different parameters. To create a call instruction, we have to create a vector (or any other container with InputInterators) to hold the arguments. We then pass in the beginning and ending iterators for this vector.
From resistor at mac.com Tue Oct 23 01:05:39 2007
From: resistor at mac.com (Owen Anderson)
Date: Tue, 23 Oct 2007 06:05:39 -0000
Subject: [llvm-commits] [llvm] r43242 - in /llvm/trunk/docs/tutorial:
JITTutorial2.html Tutorial2.tar.bz2 Tutorial2.zip
Message-ID: <200710230605.l9N65dSk022039@zion.cs.uiuc.edu>
Author: resistor
Date: Tue Oct 23 01:05:37 2007
New Revision: 43242
URL: http://llvm.org/viewvc/llvm-project?rev=43242&view=rev
Log:
Add downloadable code sample for tutorial 2.
Added:
llvm/trunk/docs/tutorial/Tutorial2.tar.bz2 (with props)
llvm/trunk/docs/tutorial/Tutorial2.zip (with props)
Modified:
llvm/trunk/docs/tutorial/JITTutorial2.html
Modified: llvm/trunk/docs/tutorial/JITTutorial2.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/JITTutorial2.html?rev=43242&r1=43241&r2=43242&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/JITTutorial2.html (original)
+++ llvm/trunk/docs/tutorial/JITTutorial2.html Tue Oct 23 01:05:37 2007
@@ -24,7 +24,7 @@
-All the code in this example can be downloaded at Tutorial2.tar.bz2 or Tutorial2.zip.
+All the code in this example can be downloaded at Tutorial2.tar.bz2 or Tutorial2.zip.
Added: llvm/trunk/docs/tutorial/Tutorial2.tar.bz2
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/Tutorial2.tar.bz2?rev=43242&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/docs/tutorial/Tutorial2.tar.bz2
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: llvm/trunk/docs/tutorial/Tutorial2.zip
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/Tutorial2.zip?rev=43242&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/docs/tutorial/Tutorial2.zip
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
From resistor at mac.com Tue Oct 23 01:17:39 2007
From: resistor at mac.com (Owen Anderson)
Date: Tue, 23 Oct 2007 06:17:39 -0000
Subject: [llvm-commits] [llvm] r43243 - /llvm/trunk/docs/tutorial/index.html
Message-ID: <200710230617.l9N6HdH2022434@zion.cs.uiuc.edu>
Author: resistor
Date: Tue Oct 23 01:17:39 2007
New Revision: 43243
URL: http://llvm.org/viewvc/llvm-project?rev=43243&view=rev
Log:
Add a link to the "writing an optimization" tutorial.
Modified:
llvm/trunk/docs/tutorial/index.html
Modified: llvm/trunk/docs/tutorial/index.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/index.html?rev=43243&r1=43242&r2=43243&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/index.html (original)
+++ llvm/trunk/docs/tutorial/index.html Tue Oct 23 01:17:39 2007
@@ -36,6 +36,10 @@