From: Matthijs Kooijman Date: Mon, 4 Aug 2008 07:59:19 +0000 (+0200) Subject: Misc fixes and rewordings. X-Git-Tag: Report-final~19 X-Git-Url: https://git.stderr.nl/gitweb?a=commitdiff_plain;h=8a551a00909d1d76971fbd86fcb4e3cf3948c214;p=matthijs%2Fprojects%2Finternship.git Misc fixes and rewordings. --- diff --git a/Report/Main/Future.tex b/Report/Main/Future.tex index 0225174..3246bab 100644 --- a/Report/Main/Future.tex +++ b/Report/Main/Future.tex @@ -17,17 +17,23 @@ help to fine tune the specifications and find bugs in the frontend. \section{Debug info preservation} \label{PreserveDebug} Currently, transformation passes are mostly ignorant about debugging info, they -treat it as ordinary code. Since debugging info is added to LLVM code by means -of special function calls and transformations by default assume that an unknow -function can do anything, this means that adding debug information can prevent +treat it as ordinary code. Debugging info is added to LLVM code by means +of special function calls. Transformations by default assume that an unknown +function can do anything, which means that adding debug information can prevent transformations from happening. Making transformations aware of debugging info will allow them to perform transformations as normal, by updating or removing debugging info. +Currently, the frontend supports the emission of debugging info, which +the backend can use to improve it's error messages. To still perform all +the needed optimizations, LLVM was patched to ignore debug info in a +specific situation. This is not a long term solution, which requires +more invasive changes to LLVM. + These changes are generic for LLVM and not needed specifically for the Montium. -Currently, most MontiumC code seems to still work even when some transformations -are left out, but especially with the new hardware, some missed out -optimizations might still be useful. +Currently, most MontiumC code seems to still work with only a little +change to LLVM, but especially with the new hardware, some missed out +optimizations might become more useful. \section{LLVM based backend} Currently, the frontend is using the LLVM framework, while the backend is diff --git a/Report/Main/Problems/Challenges.tex b/Report/Main/Problems/Challenges.tex index 39806fa..c70c087 100644 --- a/Report/Main/Problems/Challenges.tex +++ b/Report/Main/Problems/Challenges.tex @@ -39,7 +39,8 @@ because the impact of the new hardware on MontiumC is not quite clear yet. Existing transformations, on the other hand, might miss a few corner cases. When writing the specification, a particular feature might appear supported by the -compiler. On closer inspection, the transformation passes might miss some corner +compiler. On closer inspection, the transformation passes might not do +the right thing when faced with particular corner cases, which either need to be fixed or put into the specification. The best way to detect these cases is writing a lot of structured testing code, @@ -64,10 +65,11 @@ Another problem is the complexity of the C language. Although individual features can be described and supported with relative ease, combining features can easily lead to complex constructs which are hard to transform into supported Montium IR. This became more of an issue after adding features to the base -specification of MontiumC, though. +specification of MontiumC, since the base specification only supports a +few C features. \subsubsection{What is wanted?} -A completely different angle of looking at this, is from the requirements point +A completely different angle of looking at this is from the requirements point of view. What do we want MontiumC to support? This angle is even harder than the previous one, since there are a lot of levels of requirements. Ideally, MontiumC would not exist and our compiler would support the C language fully. However, @@ -81,20 +83,88 @@ anything is mappable, but with a simple compiler this will not result in the most efficient code. In the Montium case, a lot of things simply cannot be mapped on the hardware at all. -Considering that our ideal is not reachable (by far), every feature in our -wanted MontiumC should be evaluated thoroughly for feasibility, both in hardware +Considering that our ideal is not reachable (by far), every feature +considered for MontiumC was evaluated thoroughly for feasibility, both in hardware and in the compiler. In practice, this meant that new language features would be informally expressed and discussed, and only added to the specification after being succesfully implemented. This is conforming to the incremental development of MontiumC that was envisioned at the outset of its development. +To get a feeling for what MontiumC looks like, consider the fragment in +figure \ref{ExampleLow}. This is a piece of code that reads values from +one memory, multiplies them by two, and writes them back to another +memory. As you can see, this is an awful lot of code. This has two main +reasons. First, looping and memory indexing is very explicit and takes a +lot of instructions. Second, the code is effectively software pipelined +to make it run more efficiently. + +In figure \ref{ExampleHigh} the same code is displayed, but this time +using higer level C features (for loops, arra indexing). This is the +level of code we are trying to achieve, but we're not there yet. It +should be noted that this is still not "normal" C, since we use the +"imul" function instead of the normal * operator. However, since the +Montium defines a lot of different operations, most of which have a +number of options (saturation, truncation, post shifting, etc.) these +cannot all be mapped onto normal C operators. By using a specific +function call for each, we can still distinguish between all the +different operations and add extra arguments where needed. + +\begin{figure} + \caption{Low level MontiumC example} +\label{ExampleLow} +\begin{verbatim} +mem input; +mem output; +word factor; + +void run(void) { + factor = from_int(2); + input = alloc_mem(P0M0); + output = alloc_mem(P0M1); + set_base(input, 0); + set_offset(input, 0); + set_base(output, -1); + set_offset(output, -1); + + next_cycle(); + word in = read_mem(input); + word out = p0o0(imul(ra1(in), rc1(factor))) + add_offset(input, 1); + add_offset(output, 1); + init_loop(LC1, 8); + do { + write_mem(output, out); + in = read_mem(input); + out = p0m0(imul(ra1(in), rc1(factor))) + add_offset(input, 1); + add_offset(output, 1); + } while(loop_next(LC1)); + + write_mem(output, out); +\end{verbatim} +\end{figure} + +\begin{figure} + \caption{High level MontiumC example} + \label{ExampleHigh} +\begin{verbatim} +P0M0 int input[10]; +P0M1 int output[10]; + +void run(void) { + for (int i=0; i<10; ++i) + output[i] = mul(input[i], 2); +} +\end{verbatim} +\end{figure} + \subsection{Familiarizing with LLVM} Since the frontend heavily relies on the LLVM project for doing it's work, one -of the first challenges was to get myself familiar with LLVM. There are two main +of the first challenges was to get myself familiar with LLVM. There were two main aspects to this: Getting to know my way around the LLVM codebase and getting to know the LLVM community. -Since LLVM has a pretty large amount of documentation, I spent most of my first +LLVM has a pretty large amount of documentation, I spent most of my first weeks with reading tutorials and documents. Since there was already a (very preliminary) version of the clang-based frontend, I also had some code to play with. @@ -119,11 +189,11 @@ LLVM framework to better suit the needs of Recore. A major challenge during my internship was to find the balance between doing work specifically for Recore, and doing work that is useful for LLVM in general. -Any tasks that are required by the Montium frontend and the LLVM changes they -directly need are obvious. However, usually when making changes to the main LLVM -code, just changing enough for Recore is not engough for LLVM. Since the LLVM +Any changes that are directly required by the Montium frontend and the LLVM changes they +need are obvious. However, usually when making changes to the main LLVM +tree, just changing enough for Recore is not engough for LLVM. Since the LLVM code must work on any program, not just MontiumC programs, extra changes are -required (see also parapgrah \ref{StayingGeneric}. This is also an issue of +required (see also parapgrah \ref{StayingGeneric}). This is also an issue of building up credit within the LLVM community: The more you contribute to LLVM, the more influence you have when things need changing. @@ -134,11 +204,6 @@ interfere with the MontiumC frontend. In the end, I think I managed to find a decent balance, though it might have been tipped slighly in favour of the LLVM project. -\subsection{Coding} -This section says something about the challenges encountered while actually -writing code, if I can think of enough things to say here. So far, haven't -thought of anything particularly interesting yet. - \subsection{Working together} Since the compiler plays a fairly central role in the development process at Recore, I have been cooperating with a number of different people, in different @@ -149,24 +214,24 @@ often providing bug reports and other feedback, which ensures regular contact. On the other end, I have been in contact with the developer of the backend very intensively, since most changes made to either component needed changes in the other one as well. Compiler changes also require hardware support, so working -with the hardware developers was not uncommon either. In practice, most of this -communication went through the backend developer, except for the design -discussion concerning the new Montium hardware design (also see section -\ref{Pipelining} below). +with the hardware developers was not uncommon either. In practice, most +communication with the hardware developers went through the backend +developer, except for the design discussion concerning the new Montium +hardware design (also see section \ref{Pipelining} below). In addition, discussions regarding design issues at various levels often happen -out in the open, which easily invites people with an opinion about something to -chime in, without having to gather people around for every discussion that -happens. This allows for very quick feedback on ideas from people in all areas +out in the open, which invites people with an opinion about something to +chime in, without the overhead of planning a seperate meeting for each +topic. This allows for very quick feedback on ideas from people in all areas in an efficient way. \subsection{Staying generic} \label{StayingGeneric} The toughest challenge by far was to fit the features and changes required by Recore into code that is maintained by the LLVM project. The main problem here -is clash of goals: The LLVM project aims for code that performs well for their +is a clash of goals: The LLVM project aims for code that performs well for their supported architectures, while Recore aims for code that performs well (or more -often, can compile MontiumC at all) for the Montium architecture. +often, can compile at all) for the Montium architecture. In general, these problems mainly occur because MontiumC and in particular MontiumIR poses a number of constraints that are not present in other @@ -199,8 +264,8 @@ but I will highlight the most important challenges and tradeoffs. \subsubsection{Tradeoffs} In general, the most important tradeoff seems to be between flexibility and everything else (code size, performance, complexity, hardware area). This -flexibility is expressed in which instructions are possible, which connections -are present, how big register files are, etc. +flexibility is defined in terms of possible instructions, present +connections, register files sizes, etc. An important reason to be flexible is for programmability. If the hardware is regular, making a compiler that produces optimal code gets a lot easier. @@ -215,10 +280,11 @@ and usable design, without any unused extras. \subsubsection{Inner loop pipelining} When trying to improve runtime performance, the main focus is on optimizing loops, and inner loops (loops that contain no other loops) in -particular. Since the inner loop is executed the most often, it is the most -efficient to optimize the inner loop. Also, the inner loop is also the piece of -code that can most optimally use the parellel processing power of the Montium, -because it can be software pipelined. +particular. Since inner loops are executed the most often (compared to +other loops and code), it is the most +efficient to optimize inner loops. Also, inner loops can most optimally +use the parellel processing power of the Montium, because they can be +software pipelined. Software pipelining means that the compiler will emit code that performs operations that belong in different iterations of the original loop during the