ProGraML: Graph-based Deep Learning forProgram Optimization and Analysis

ProGraML: Graph-based Deep Learning for Program Optimization and Analysis

Abstract

The increasing complexity of computing systems places a tremendous burden on optimizing compilers, requiring ever more accurate and aggressive optimizations. Machine learning offers significant benefits for constructing optimization heuristics but there remains a gap between what state-of-the-art methods achieve and the performance of an optimal heuristic. Closing this gap requires improvements in two key areas: a representation that accurately captures the semantics of programs, and a model architecture with sufficient expressiveness to reason about this representation.

We introduce ProGraML — Program Graphs for Machine Learning — a novel graph-based program representation using a low level, language agnostic, and portable format; and machine learning models capable of performing complex downstream tasks over these graphs. The ProGraML representation is a directed attributed multigraph that captures control, data, and call relations, and summarizes instruction and operand types and ordering. Message Passing Neural Networks propagate information through this structured representation, enabling whole-program, per-instruction, and per-variable classification tasks. ProGraML is a compiler-independent representation with support currently for LLVM and XLA IRs.

ProGraML provides a general-purpose program representation that equips learnable models to perform the types of program analysis that are fundamental to optimization. To this end, we evaluate the performance of our approach first on a suite of traditional compiler analysis tasks: control flow reachability, dominator trees, data dependencies, variable liveness, and common subexpression detection. On a benchmark dataset of 250k LLVM-IR files covering six source programming languages, ProGraML achieves an average 94.0 score, significantly outperforming the state-of-the-art approaches. We then apply our approach to two high-level tasks — heterogeneous device mapping and program classification — setting new state-of-the-art performance in both.

\PassOptionsToPackage

tablexcolor

\MakePerPage

footnote

1 Introduction

The landscape of computing ecosystems is becoming increasingly complex: multi-core and many-core processors, heterogeneous systems, distributed and cloud platforms. Manually extracting performance and energy benefits from systems like these is beyond the capabilities of most programmers. In such an environment, high quality optimization heuristics are not just desirable, they are required. Despite this, good optimization heuristics are hard to come by.

Figure 1: Our proposed approach for compiler analyses driven by graph-based deep learning. The ProGraML representation is derived from a compiler’s IR and serves as input to Message Passing Neural Networks, which provide optimization decisions in place of traditional handwritten heuristics.

Designing and tuning optimization heuristics takes time, effort, and resources. To make things worse, this is a Sisyphean task: even minor changes in a development toolchain might require retuning the heuristic; major changes in the software or the hardware usually require freshly designed heuristics. Machine learning offers to liberate us from this cycle by replacing fragile hand-tuned optimization heuristics with models that are inferred automatically from real performance data [8, 56]. Typically, programs are represented using a sequence of numerical features which are derived from programs using ad-hoc analysis, but such approaches fail to capture the rich semantic structure of programs, limiting the ability for models to reason about program behavior. This is easy to see in traditional machine learned approaches, where the designer explicitly chooses a program representation based only on a few properties deemed important. Such representations prevent models from reproducing the reasoning of even basic compiler analyses and that, in turn, limits their ability to make good optimization decisions.

Recent deep learning approaches that work directly on code [2] are limited, both in the way they represent the inputs and in the way they process them. Representations based on source code and its direct artifacts (e.g. AST) put unnecessary emphasis on naming and stylistic choices that might or might not correlate with the functionality of the code [7, 59, 30]. Current IR-based approaches [12, 45, 15] use compilation to remove such noise but in the process they omit important information about the program.

In both cases, the model is expected to reason about the flow of information in the program using representations that do not encode this information clearly. If this was not difficult enough already, processing the code representations sequentially, as most existing approaches do, makes it practically impossible. Related statements can easily be separated by hundreds of lines of irrelevant code in sequential representations. Due to vanishing gradients [13] and catastrophic forgetting [44], neural networks are unlikely to even notice such very long range dependencies.

In this paper, we propose overcoming this limitation by making the program’s control, data, and call dependencies a central part of the program’s representation and a primary consideration when processing it. We achieve this by seeing the program as a graph, in which individual statements are connected to other statements through relational dependencies. The latent representation of each statement is then a function of not just the statement itself but the latent representations of its graph neighborhood. Each statement and data element in the program is understood only in the context of the statements interacting with it. In contrast to prior sequential learning systems for code, this representation closely resembles the intermediate representations used by compilers, and the propagation of information through these graphs mimics the behavior of typical iterative data-flow analyses.

Techniques for learning over graphs have recently been proposed and have shown promise in a number of domains [42, 50, 27]. Our intent with this work is to extend these approaches to the domain of program analysis and provide a systematic evaluation of their suitability and limits for compiler tasks. With a graph-based approach, we are able to automatically learn established compiler analyses that rely on control and data flow and do it far better than existing code modeling approaches. Downstream tasks built on top of such graph models can then natively incorporate approximate compiler analyses into their decision making, leading to superior and more powerful models.

1.1 Contributions

We make the following contributions:

  • A portable, language-agnostic graph representation of programs derived from compiler intermediate representations (IR), and machine learning models for relational reasoning about the control, data, and call relations in programs1. The ProGraML representation is compiler-angostic, with support currently for LLVM and XLA IRs, and is the first to summarize instructions, operand types, and operand order.

  • As a benchmark for our approach, we pose a suite of established compiler analysis tasks as supervised machine learning problems, comparing the performance of models using ProGraML against state-of-the-art code representations. Succeeding at these benchmark tasks requires the ability to model control- and data-flow, function boundaries, instruction types, and the type and order of operands. On a large dataset of over 250k LLVM-IRs taken from real-world software projects, our approach achieves an average 94.0 score (98.9 precision, 92.0 recall), a 3.44 improvement over the state-of-the-art.

  • We demonstrate the efficacy of our approach on two challenging downstream compiler tasks: heterogeneous device mapping, and program classification. Our results in heterogeneous device mapping show the superiority of graph based approaches. In an ablation study in program classification, we show a significant performance improvement due both to the rich structure of the ProGraML representation and the message passing neural network approach. Our approach reaches an accuracy of 96.22% in program classification, a improvement over the state-of-the-art.

2 Motivation

Machine learning promises significant benefits for simplifying and improving the construction of optimization heuristics by replacing fragile and expensive hand-tuned heuristics with data-driven statistical modeling. For this goal to be realized, we require machine learning systems capable of reasoning about program semantics. Despite tremendous gains in recent years, state-of-the-art approaches for learning on code are not sufficiently powerful to replicate the analysis tasks that are fundamental to compilers. The crux of the problem lies in two central aspects of machine learning: input representation and model algorithmic complexity.

(I) Input Representation To be processed by a Neural Network (NN), code inputs may be encoded either directly from a source language, by way of AST analysis, or using an IR. Examples of each abound in the literature [2, 16, 56]. One state-of-the-art encoder, code2vec [7], uses AST paths to embed programs. code2vec proves highly effective at software engineering tasks such as algorithm classification, where the code was written by humans. However, as shown in Figure 1(a), the trained representation can put more weight on names rather than code structure, where minute modifications completely change classification outcome. There are many benefits to such a representation, including smart pasting and automated refactoring. However, when analyzing code for optimization, identifier names are rarely of use, whereas structure and semantics should be the primary consideration. For example, in choosing to represent code at the AST level, the code2vec representation does not capture the data or control relations between statements.

(a) code2vec [7].
(b) XFG [12].
(c) CDFG [15].
Figure 2: Limitations in state-of-the-art learnable code representations. In (\subrefsubfig:code2vec) the model over-emphasizes identifier names such that the same algorithm produces three different classifications by changing the name of a function. The data-flow representation of (\subrefsubfig:inst2vec) does not capture operand order, such that non-commutative statements such as division are indistinguishable. In (\subrefsubfig:cdfg) control and data relations are captured, but both type information and operand order are omitted. Our approach is insensitive to identifier names and preserves operand order and type information.

An alternate approach which emphasizes semantics is Neural Code Comprehension [12], where an encoder uses Contextual Flow Graphs (XFG) built from LLVM-IR statements to create inputs for neural networks. The XFG combines partial data- and control-flow to represent the context of an individual statement. The statements are then mapped to latent-space representations using their neighbors in that graph. However, in partially combining DFGs and CFGs, the XFG representation omits important information such as order of instruction operands (as shown in Figure 1(b)), and the representation fails to capture execution order, critical for many optimization tasks.

A recent LLVM-IR representation uses Control and Data Flow Graphs (CDFG) [15]. This representation makes the control and data relations between instructions explicit, but uses only instruction opcodes to compute latent representations. This omits information about programs that may be critical for optimization, such as data types, the presence of variables and constants, and the ordering of operands, shown in Figure 1(c).

Each of the three methods of encoding programs as inputs to neural networks omit information that is vital for compiler analysis. This hinders the ability of machine learning models to reason about optimizations and their impact on program behavior. To address these shortcomings we require an input representation that captures all parts of a program’s semantics that are required for performing such analyses.

(II) Model Complexity The range of core operators in deep learning on code is largely confined to recurrent units (e.g. RNN, LSTM, GRU) on sequences. This poses limitations on the representation space of any such network’s outputs. Take, for instance, dominator tree construction. An LSTM iterating forward over input code will not be able to solve the task by definition, as statements needs to be analyzed backwards with respect to dependencies. Yet, the neural network only maintains memory capacity w.r.t. program length. Iterating in the opposite direction, in addition to being problem-specialized, would still not suffice, as dependencies may “vanish” in the corresponding gradients if dependent statements are far away from each other, such as in the presence of diverging control flow.

One way to increase the algorithmic complexity of the model is by allowing it to increase the number of code tokens that are processed simultaneously during inference. This approach, commonly used in literature by Transformer Networks [53], use preceding tokens (unidirectional encoding) or preceding and subsequent tokens (bidirectional encoding) to learn attention matrices. Such matrices “focus” the network on certain subsets of tokens, skipping others. However, this approach scales quadratically in memory and computation with the number of tokens.

Unlike in natural language text, the dependency structure of code is made explicit during compilation. We can thus employ domain-specific knowledge to construct the attention matrices in a scalable manner, using a graph representation of the tokens with dependencies as edges. A graph representation not only enables meaningful attention learning, but also facilitates propagating information across the graph in a manner similar to typical compiler analyses. Within the same step, a recurrent unit generates activations, whereas a graph NN generates .

To demonstrate this expressive power, let us consider control-flow reachability analysis as a learning task. The goal of the model is to tag statements that are reachable from one or more given tagged statements. With a sequential LSTM, the model would have to be trained to memorize nodes along some linear order of the given program. With an unbounded number of nodes to track and variably-sized regions to skip, the task becomes infeasible. A message-passing graph neural network, in contrast, needs only to learn to pass a message forward in the case of an existing control-flow edge between two nodes, essentially learning an identity operation over control-flow edges and zero on others.

In this work, we overcome the above limitations of prior model and representation approaches, leveraging the graph structure of IR code, taking path analysis and the semantics of individual statements into account.

3 A Graphical Program Representation for Analysis and Optimization

For machine learning to successfully reason over programs, a suitable input representation must be used. This section presents ProGraML, a novel program representation that closely matches the representations used traditionally within compilers and can be processed natively by machine learning models. Unlike prior approaches that rely on hand-engineered feature extractors [8, 56] or which are closely tied to the syntax of the target program language [3], our approach captures whole-program control, data, and call relations and is both task- and language-agnostic.

(a) Compiler intermediate representation.
(b) Construct control flow.
(c) Add data flow for variables and constants.
(d) Add call flow for call sites.
Figure 3: Construction of a ProGraML representation for a simple C implementation of recursive Fibonacci using LLVM-IR. The input program is passed through the compiler front end to produce an intermediate representation (a). A full flow graph is constructed from the IR statements and control flow edges inserted (b). Vertices for variables and constant values are added and data-flow edges inserted (c). Finally, call sites are extracted and call edges inserted from call sites to function entry statements, and from function exit vertices to call sites (d). All edges are positional, for clarity we have omitted position labels where not required.

3.1 Overview

The ProGraML representation of a compiler IR serves as the union between a call graph, control-flow graph, and data-flow graph. We represent programs as directed multigraphs where statements, identifiers, and immediate values are vertices, and relations between vertices are edges. Edges are typed to differentiate control-, data-, and call-flow. Additionally, we augment edges with a positional label to encode the order of operands for statements, and to differentiate between divergent branches in control-flow. The ProGraML representation is processed natively by our machine learning models, described in Section 4.

3.2 Graph Construction

We construct a ProGraML graph by traversing a compiler IR. Graph construction is divided into three stages: control-flow, data-flow, and call-flow, though in practice the three stages can be combined in a single pass. The representation is compiler-agnostic, adding support for a new compiler requires only a parser for the IR. Currently we support LLVM [38] and XLA HLO [39] IRs. Figure 3 shows the graph construction approach.

(I) Control Flow We construct a full-flow graph from an IR by inserting a graph vertex for each instruction and control flow edges between them, as shown in Figure 2(b). All control edges are augmented with a numeric position label using an ascending sequence based on their order in the list of a vertex’s outgoing control edges. For instructions with a single control successor, the position of the control edge is 0. For a branching statement with successor statements, the control edge positions are in the range . We do not need to encode the source function or basic block [38] of instructions as this information is captured implicitly in structure of the graph; basic blocks are regions of instructions with a single entry and exit control edge, and functions are disconnected subgraphs.

(II) Data Flow We introduce additional graph vertices for constant values and variables, shown in Figure 2(c). Data-flow edges are added to capture the relation from constants and variables to the instructions that use them as operands, and instructions to produced variables. Each unique variable and constant is a vertex, which implicitly models the scope of variables, and unlike the tokenized representations of prior machine learning works, variables in different scopes always map to distinct vertices and can thus be discerned. Similarly, constant values with the same textual representation in source code (such as the number 3.14 with float and double precision types) are distinguishable in our representation. As with control edges, data edges have a position label which encodes the order of operands for instructions. The latent representation of an IR statement is thus a function of the vertex representing the instruction and the vertices of any operand variables or constants, modulated by their order in the list of operands.

(III) Call Flow Control edges do not span functions, such that an IR with functions produces disconnected subgraphs (the same is not true for data edges which may cross function boundaries, for example in the case of an global constant which is used within multiple functions of a program). Instead, the relation between a statement which calls a function and the called function is captured through call edges, shown in Figure 2(d). An outgoing call edge is inserted from the calling statement to the entry statement of a function. Return call edges are added from all terminal statements of a function to the calling statement. Call edges do not use position labels as there is no ordering to be imposed between the call sites of a function. For IRs which support external linkage, an additional vertex is created representing an external callsite and connected to all externally visible functions. Similarly, if a call site references a function not defined in the current IR, a dummy function definition is created consisting of a pair of entry and exit instruction vertices, and connected normally through call edges. A single dummy function definition is created for each externally defined function and shared across all call sites in the current IR.

3.3 Comparison to Other Representations

As an input for machine learning, what distinguishes ProGraML from prior works is its close proximity to the structured representations traditionally used within compilers for program analysis and optimization. Specifically, it is distinct from prior machine learning representations in three key areas:

  1. as an IR-level representation, it is independent of the source language and accompanying variances such as code style and identifier naming that affect source-level representations [7, 20];

  2. by representing programs as graphs with explicit control, data, and call edge types ProGraML captures a greater range of intra-program relations than prior graph representations [12, 3, 47];

  3. and in trading sequential for graph representations, we do not sacrifice local sequence order, such as the ordering of diverging control flow or the ordering of operands that is lost in prior representations [12, 15].

Table 1 provides a comparison of ProGraML to several recent learned representations of code.

Source Languages Representation Flow-sensitive? Position-sensitive? Value-sensitive?
AST Paths [6] C#, Java, JavaScript, Python AST
CDFG [15] OpenCL IR Graph
code2vec [7] Java AST
DeepTune [19] OpenCL Token Sequence
DeepTune-IR[9] OpenCL IR Token Sequence
DeepTyper [31] JavaScript Token Sequence
inst2vec [12] C++, OpenCL IR Graph
ProGraML C, C++, Fortran, Haskell, OpenCL, Swift IR Graph
Table 1: Taxonomy of recent code representations for machine learning. We classify approaches based on the type of representation used and the sensitivity to three categories: {control/data/call}-flow, operand positions, and operand values. Prior approaches require a trade-off in representational power, e.g. substituting a position-sensitive token sequence for a flow-sensitive graph. ProGraML is the first representation to span all categories.

4 Graph-based Machine Learning

We formulate our system in a Message Passing Neural Network (MPNN) framework [27, 42] and implement a single unified model for all our experiments. Our design mimics the transfer functions and meet operators of classical iterative dataflow analysis [34, 18], replacing the rule-based implementations with deep learning analogues (message and update functions). Those can be specialized through training to solve a diverse set of problems without human intervention or algorithm design.

4.1 Overview

We learn over ProGraML representations of compiler IRs by mapping graph vertices to an initial state vector using an embedding. The vertex states are updated iteratively in a sequence of message passing steps, where at each step a new vertex state is computed as a function of its previous state and the state of its neighboring vertices. Separate functions are learned to update vertex neighbors based on their relation type, be it control, data or call, and reverse edges enable backwards propagation of information. After repeating this process of updating vertex states for a fixed number of iterations a readout function is used to aggregate the vertex representations to a single graph-level vector or set of vertex-level vectors.

4.2 Model Design

The ProGraML model takes as input a directed graph with additional information as presented in Section 3 and consists of three logical phases: input encoding, message propagation, and result readout.

(I) Input Encoding Starting from the augmented graph representation introduced in Section 3, we capture the semantics of the program graph vertices by mapping every instruction, constant, and variable vertex to a vector representation by lookup in a fixed size embedding table . The mapping from vertex to embedding vector must be defined for each IR, though the embeddings themselves can be learned during training.

For LLVM-IR we extend the inst2vec [12] vocabulary, which represents 8,566 statements derived from a large corpus of LLVM-IR using 200-dimensional embeddings. Since the space of statements is unbounded, inst2vec uses a normalization process to inline type definitions and strip identifiers and immediate values, depicted in Figure 4. An inst2vec representation combines an instruction and its operands into a single token, so we augment the vocabulary with Id and Val tokens to represent variable and constant value vertices, respectively.

In expressing a statement as a combination of an instruction and its operands, our data-driven approach trades a certain amount of semantic resolution against good coverage of the vocabulary by the available datasets. The long tail of the distribution of statements jointly maps onto a special Unknown token vector in the vocabulary. In future work will simplify the LLVM-IR statement encoding by constructing separate vocabularies for instructions and operand types, increasing the expressiveness of the encoding by allowing a larger combination of instruction and operands to be represented. Input vertex-selectors, encoded as binary one-hot vectors, are used to mark the starting point for certain analyses and are concatenated to the vertex embeddings. Other global input features are used as auxiliary input features at readout time in step (III), where required.

Figure 4: Normalizing an LLVM-IR statement (a) by inlining type definitions and stripping identifiers using inst2vec [12] (b). A normalized statement is used as the key for an embedding table lookups to produce the initial vector representation of a vertex. (c) shows the statement as contextualized in a ProGraML graph, where the operand variables and constants are data elements, differentiated by their position. Vertex labels represent embedding table keys. In this example, the statement is represented using five vertices and encoded with three unique embeddings.

(II) Message Propagation Each iteration step is divided into a message propagation step followed by a vertex state update. During message propagation, each vertex in the graph collects learned messages from its undirected neighbors:

(1)

where denotes the Hadamard product and is the typed edge between vertex and . In order to allow for reverse-propagation of messages, which is necessary for backward compiler analyses, we add backward edges for each edge in the graph. For backward edges we introduce separate parameters following Li et al. [42] to enable the network to distinguish between an edge and its backward sibling. During message propagation we scale the source states with pos, which is a constant sinusoidal position embedding [53, 26] that encodes the argument order of incoming (and outgoing) edges. This information is necessary for the network to distinguish non-commutative operations such as division.

The collected messages are subsequently used to update the vertex states in parallel according to an update function. In all our experiments, we employ a Gated Recurrent Unit (GRU) [17] as our update function:

(2)

Step (II) is iterated times to extract vertex representations that are contextualized with respect to the given graph structure.

(III) Result Readout We support whole program classification, per-statement classification, or per-identifier classification by employing different readout heads on top of the iterated feature extraction: for graph-level classification we define a set function that maps to class-scores, while for vertex-level inference, we separately map the extracted node features to probabilities in parallel:

(3)
(4)

where and are feed forward Neural Networks and is the sigmoid activation function. In the case where auxiliary graph-level features are available, those are concatenated to the readout values and fed through another feed forward Neural Network that employs Batch Normalization [33] to allow for vastly different feature scales.

5 Experimental Methodology

We evaluate the effectiveness of our approach in three case studies. In the first, we apply our methodology to a suite of established compiler analysis tasks. These serve as demonstrations of the representational power of our approach and highlight the limitations both in prior machine learning approaches and in current MPNNs. The second case study then applies the approach to the challenging real-world optimization task of heterogeneous device mapping, comparing the performance of our model against state-of-the-art machine learning-based approaches. Finally, we apply our approach to the task of classifying algorithms from unlabelled implementations. This section describes the methodology used to construct these experiments: the datasets used, the model parameters, and training regimes.

5.1 Case Study A: Compiler Analyses

We construct a benchmark suite of traditional compiler analysis tasks to evaluate the representational power of our approach. We chose a diverse set of tasks to capture a mixture of both forward and backward analyses, and control-, data-, and procedure-sensitive analyses. Our goal is not to suggest that machine learning should replace the existing implementations of these standard algorithms which can be found in any compiler, but rather, if a machine learning system is not capable of producing these analyses, it stands to reason that performance on downstream tasks which depend on these analyses will suffer.

Benchmark Analyses

We selected five traditional compiler analyses to use as benchmarks for evaluating the representational power of our approach.

(I) Reachability Control reachability is a fundamental compiler analysis which determines the set of statements that can be reached from a particular starting statement. Given , which returns the control successors of statement , the set of reachable statements starting at root can be found using forward analysis:

(5)

(II) Dominator trees Statement dominates statement if every control flow path to passes through . A dominator tree is the set of all nodes that dominate the statment at a particular program point. Like reachability, this analysis only requires propagation of control flow, but unlike reachability, dominator trees are typically constructed using backward analysis [40, 14]:

(6)

Where which returns the control predecessors of statement .

(III) Live-out variables A variable is live-out of statement if there exists some control successor of that uses . Given , which returns the operand variables of , and , which returns defined variables, the live-out variables can be computed forwards using:

(7)

(IV) Data dependencies The data dependencies of statement is the set of predecessor statements that must be evaluated to produce the operands of . Computing data dependencies requires data sensitivity and is computed backwards:

(8)

Where returns the statements that produce operands of .

(V) Global Common Subexpressions The identification of common subexpressions is an important analysis for optimization. For compiler IRs we define a subexpression as a statement and its operands, ordered by either their position (for non-commutative operations), or lexicographically (for commutative operations). We thus formulate the common subexpression problem as, given a statement (which forms part of a subexpression), label any other statements in the program which compute the same subexpression. This is an inter-procedural analysis, though operands must obey their scope. Common subexpressions are typically identified using available expression analysis:

Where return the expressions used by statement , and returns the expressions defined by .

Datasets

We assembled a large corpus of real-world LLVM-IRs from a variety of sources, summarized in Table 2. We selected popular open source software projects that cover a diverse range of domains and disciplines, augmented by uncategorized code mined from popular GitHub projects using the methodology described by Cummins et al. [20]. Our corpus comprises a range of source languages (C, C++, Fortran, Haskell, OpenCL, and Swift) and exceeds 250k files. We de-duplicated the corpus first at the source level, then again after lowering to LLVM-IR. Lowering from source to IR was performed using the inst2vec methodology [12], in which an optimization level is chosen randomly per-file.

Source language Domain IR files IR lines Avg. vertices / IR Avg. edges / IR
BLAS 3.8.0 Fortran Scientific Computing 300 345,613 1,664 3,276
Linux 4.19 C Operating Systems 13,851 41,332,089 1,857 3,760
OpenCL Benchmarks [19] OpenCL Benchmarks 256 149,779 1,027 1,970
OpenCV 3.4.0 C++ Computer Vision 400 1,168,758 3,761 7,442
POJ-104 [46] C++ Standard Algorithms 182,815 64,518,837 312 569
Tensorflow [1] C++ Machine learning 1,584 8,444,443 5,786 11,482
GitHub C Various 42,880 89,356,570 927 1,794
Haskell 1,371 6,745,312 4,705 7,518
OpenCL 5,188 10,472,388 2,299 5,132
Swift 1,783 205,140 134 371
Total 250,428 222,738,929 153,426,059 294,685,614
Table 2: The ten sources of LLVM-IR used to produce datasets for evaluating data flow analyses. Our corpus comprises six programming languages from functional to imperative, high-level to accelerators. The software covers a broad range of disciplines from compilers and operating systems to traditional benchmarks, machine learning systems, and unclassified code downloaded from popular open source repositories.

We generated a single ProGraML representation for each of the LLVM-IRs, taking an average of 31 ms per IR. Our corpus of unlabeled graphs totals 153M vertices and 295M edges, with an average of 616 vertices per graph with 472 unique vertex representations, and 1183 edges with a maximum edge position of 355 (a large switch statement found in a Tensorflow compute kernel).

We produced labeled graphs from the unlabeled corpus by computing ground truth labels for each of the analysis tasks using a traditional analysis implementation. For each of the five tasks, and for every unlabeled graph in the corpus, we produce labeled graphs by selecting unique source vertices , where is proportional to the size of the graph:

(9)

Each instance in the datasets consists of an input graph in which the source vertex is indicated using the vertex selector, and an output graph with the ground truth labels used for training or for evaluating the accuracy of model predictions. Figure 5 illustrates an example input-output instance for each of the five tasks.

We divided the datasets randomly using a 3:1:1 ratio for training, validation, and test instances. The same random allocation of instances was used for each of the five tasks. Where multiple labeled graphs were derived from a single IR, instances derived from the same IR were allocated to the same split.

(a) Reachability.
(b) Domtree.
(c) DataDep.
(d) Liveness.
(e) Subexpressions.
Figure 5: Example input-output graphs for each of the five benchmark compiler analyses. A single vertex is randomly selected from the input graph to represent the starting program for computing the analysis results, indicated using the vertex selector. The output graphs contain binary labels for each of the graph vertices after the analysis has completed. As a supervised classification task, the goal of the model is to predict the output vertex labels given the input graph. These small graphs are for illustrative purposes, the LLVM-IR graphs in our real-world corpus contain an average 616 vertices and 1,183 edges.

Models

LSTM Baseline As no prior work offers the expressiveness required to perform the per-statement and per-variable classification required for these analysis tasks, we extended DeepTune [19], a state-of-the-art deep learning framework for whole-program classification, to enable per-statement classification. In DeepTune, an OpenCL program is first tokenized and mapped to a sequence of embedding vectors which are then processed through a sequential LSTM model. The final state of the LSTM is optionally concatenated with program-level features, then fed through a fully connected neural network to produce a program-level classification.

Figure 6 shows how we extended this approach for statement-level classification of LLVM-IR. We first replaced the OpenCL tokenizer using one derived from LLVM IR, resulting in a 179-element vocabulary. To adapt the approach for performing statement-level classification, we group embedding vectors by their source statement before using element-wise summation to merge embedding vectors.

We use the same models parameters as in the original work [19] — 64-dimensional embedding vectors trained jointly, with 64 sequences per batch, padded and truncated to the same length. As LLVM IR is more verbose than OpenCL, the sequences are significantly longer requiring greater device memory during training and inference. This is a common issue with recurrent neural networks, as sufficient memory is required to store both the intermediate results of the forward pass and the gradients during training [11]. We found that a sequence length of 5,000 was the maximum that our experimental platform allowed. Where sequences exceed this length, they are truncated, and the model outputs padded with zeros to match the expected shape.

Figure 6: Extending DeepTune [19] to perform per-statement classification of an LLVM-IR. In the original work, the latent representation of the entire program token sequence was used for program-level classification, we enable classification of arbitrary token groupings so that we can perform statement-level classification of a program. In the above diagram, denotes element-wise summation, and denotes vector concatenation.

ProGraML We use the model design outlined in Section 4 for each of the compiler analysis tasks. While we use the vocabulary of inst2vec, we do not use the pre-trained embeddings, instead initializing the embeddings randomly and training jointly.

Message Passing Neural Networks typically use a small number of propagation steps out of practical consideration for time and space efficiency [27, 42], and address problems on smaller graphs than used in this work [3]. For a large class of monotone data flow analysis problems, however, it is known that up to passes over the graph are required, where is the loop connectedness of  [18, 34]. The loop connectedness captures the notion of loop-nesting depth in a program and is therefore a program-dependent, but generally unbounded quantity2.

We address this challenge with ProGraML by iterating for a fixed number of message passing steps for training and inference and excluding from the test set graphs for which a traditional implementation of the analysis task requires greater than iterations to solve. For the experiments in this work we set , leading to 12.56% of the graphs in the corpus to be excluded across the five tasks. For fairness, we also excluded these graphs from evaluation of the LSTM baseline.

Training Details and Parameters

All models were trained in an end-to-end fashion with the Adam optimizer [36] using the default configuration and learning rate . We trained the models on a NVIDIA GTX 1080 GPU-equipped machine in increments of 10k graphs, testing on a 20k validation set at each checkpoint. Training terminated after six hours, or if accuracy on the validation set reached 99.99%. After training completed we selected the checkpoint with the highest accuracy on the validation set to use for testing.

5.2 Case Study B: Heterogeneous Device Mapping

We apply our methodology to the challenging domain of heterogeneous device mapping (DevMap). Given an OpenCL kernel and a choice of two devices to run it on (CPU or GPU), the DevMap task is to predict the device which will provide the best performance. We chose this problem as it has received significant prior attention, with previous approaches using both hand-engineered features [29] and sequential models [19, 12].

Datasets

We used the dataset of [19], which provides labeled CPU/GPU instances for 256 OpenCL kernels sourced from seven benchmark suites on two combinations of CPU/GPU pairs. The AMD set uses an Intel Core i7-3820 CPU and AMD Tahiti 7970 GPU; the NVIDIA set uses an Intel Core i7-3820 CPU and an NVIDIA GTX 970 GPU. Each dataset consists of 680 labeled instances derived from the 256 unique kernels by varying dynamic inputs.

Models

We compare ProGraML with four approaches: First, with a static baseline that predicts the mode device of the dataset distribution. Second, with DeepTune [19], which is a sequential LSTM model at the OpenCL source level. Third, to isolate the impact of transitioning from OpenCL source to LLVM-IR, we evaluate against a new DeepTune model, which adapts DeepTune to using tokenized sequences of LLVM-IR as input instead of OpenCL tokens, using the vocabulary described in Section 5.1.3. Finally, we compare against the state-of-the-art approach NCC [12], which replaces the OpenCL tokenizer with a sequence of 200-dimensional embeddings, pre-trained on a large corpus of LLVM-IR using a skip-gram model.

Training Details and Parameters

All neural networks are regularized with Dropout [32] for generalization and Batch Normalization [33] in order to be uniformly applicable to vastly different scales of auxiliary input features. We used -fold cross-validation with rotating 80/10/10 splits by training on 80% of the data and selecting the model with the highest validation accuracy, setting aside th of the training data to use for validation. We trained each model for 100 epochs and selected the epoch with the greatest validation accuracy for testing.

5.3 Case Study C: Algorithm Classification

In a third case study, we apply our approach to task of classifying algorithms. We use the POJ-104 [46] dataset. It contains implementations of 104 different algorithms that were submitted to a judge system. All programs were written by students in higher education. The dataset has around 500 samples per algorithm. We compile them with different combinations of optimization flags to generate a dataset of overall 240k samples. Approximately 10,000 files are held out each as a development and test set.

Models

We compare with recently published tree-based convolutional neural networks (TBCNN) [46] and NCC [12], which uses the same approach approach as described in Section 5.2.2 on this dataset. To further test the expressive power of the graph-based representation against the tree-based (TBCNN) and sequential (NCC) prior work, we present additional experiments: Graph-based baselines based on XFG [12] and a ProGraML structure-only baseline.

To better understand the qualitative aspects of replacing a graph-based representation that captures program semantics like Contextual Flow Graphs [12] (XFG) with the more complete ProGraML representation, we adapted a GGNN [42] to directly predict algorithm classes from XFG representations of the programs. In contrast to this, Ben-Nun et al. [12] used XFG only to generate statement contexts for use in skip-gram pre-training. Here, we lift this graphical representation and make it accessible to a deep neural network directly, as opposed to the structureless sequential approach in the original work (NCC).

Additionally, we include a structure-only baseline of our ProGraML approach, where only the type of each node (instruction, variable, or constant) is encoded, refraining completely from tokenizing statements. We think that algorithm classification is a problem that lends itself especially well to judging the power of the representation structure, since most algorithms are well-defined independent of implementation details such as datatypes.

To test the limits of the expressivity of ProGraML, combine our representation with a powerful 10-layer Transformer [53] encoder model, adapted as a graph neural network for attributed graphs. We induce graph structure by masking the attention scores in the self-attention layer with the adjacency matrix of the ProGraML graphs. A new space-efficient sparse implementation allows processing of graphs with on the order of vertices. Different edge types are encoded by introducing separate key and value projection matrices into the self-attention layer [53, 25].

Training Details and Parameters

The GGNN models were trained with the AdamW [43] optimizer with learning rate for 80 epochs. Dropout regularization is employed on the graph states with a rate of . The Transformer model uses the same hyperparameters as the GGNN. Additionally a batch size of 64, Dropout regularization of 0.2 on the graph states and weight-sharing between adjacent pairs of layers is employed. The model dimension is equal to the embedding size (200) and the hidden size of the feed-forward layers is 512. The self-attention layers use 5 heads [53]. Overall, the Transformer model has 5.6 million trainable parameters, around 1.7 million of which are in the embedding layer.

6 Experimental Results

This section evaluates the performance and limitations of our approach for the three case studies described in Section 5, and provides a comparison to state-of-the-art approaches. First we show that ProGraML, unlike prior state-of-the-art approaches to machine learning over code, is capable of replicating core compiler analysis tasks that are key to optimization. Second, we improve upon prior approaches to the task of heterogeneous device mapping. Finally, we set a new state of the art in the difficult task of classifying program algorithms, and ablate the contribution of the structure and content of the ProGraML representation.

6.1 Case Study A: Compiler Analysis

Table 3 summarizes the performance of the ProGraML approach when tasked with learning a suite of benchmark compiler analysis, along with the performance of a state-of-the-art sequential approach, DeepTune. As a binary classification task, compiler analyses display an extreme class imbalance as only a small fraction of a program graph is typically relevant to computing the result set of an analysis. On our datasets, an accuracy of 96.6% can be achieved by always predicting the negative class. For this reason we report only binary precision, recall, and scores with respect to the positive class.

Problem Analysis type Example optimization Model Precision Recall
Reachability Forwards, control flow only Dead code elimination DeepTune 0.520 0.497 0.504
ProGraML 0.997 0.995 0.996
DomTree Backwards, control flow only Global Code Motion DeepTune 0.721 0.081 0.138
ProGraML 0.985 0.693 0.781
DataDep Backwards, control and data flow Instruction scheduling DeepTune 0.999 0.136 0.236
ProGraML 1.000 0.988 0.993
Liveness Backwards, control and data flow Register allocation DeepTune
ProGraML 1.000 0.999 0.999
Subexpressions Forwards, statement and operand values and positions Global Common Subexpression Elimination DeepTune 1.000 0.123 0.214
ProGraML 0.965 0.925 0.930
Average DeepTune 0.810 0.209 0.273
ProGraML 0.989 0.920 0.940
Table 3: Benchmark compiler analyses results using two approaches: (a) DeepTune, a sequential model adapted to work at the LLVM-IR level for statement-level classification, and (b) ProGraML, our approach. The relational representation significantly outperforms a sequential approach across all problems. For the Global Common Subexpressions analysis, DeepTune achieved a higher precision than ProGraML by predicting only the root statement as a component in a subexpression, avoiding false-positives.

As can be seen in Table 3, the relational representation of our approach, coupled with learning through iterative message passing, yields models that far outperform the state-of-the-art sequential approaches to modeling code. The grouping of program tokens by statement performed by DeepTune offers a more restrictive classification interface than with ProGraML (where data elements are also represented as graph vertices). As such, it is not able to perform the per-variable classification required for Liveness analysis3. For fairness, we exclude Liveness from LSTM aggregate values in Table 3. Despite this, ProGraML achieves an average 94.0 , versus 27.3 for DeepTune.

In many cases, the sequential model regresses to a classification mode in which only the source vertex is labeled as positive, yielding poor recall. The ProGraML models achieve both high precision and high recall in all tasks except DomTree, where recall is comparatively poor. When model performance is considered as a function of the number of training graphs, as shown in Figure 7, we see that the performance of the ProGraML models quickly convergences towards near-perfect score on a holdout validation set, except in the case of DomTree, where the model is still improving at the end of training. This suggests estimating the transfer and meet operators of this backwards analysis poses a greater challenge for the network, which may require further training.

(a) DeepTune
(b) ProGraML
Figure 7: The score of compiler analysis models on a 20k-graph validation set as a function of the number of training graphs from 10k to 1M. Each model was given six hours to train on a machine with a GTX 1080 GPU, with early termination if accuracy on the validation set reached 99.99%. We have applied a Gaussian filter () to aid in visualizing the trends in each set of scores.

Table 4 shows confusion matrices for the per-vertex classification of ProGraML models on the test set. While the distribution of errors is balanced for Reachability, in the case of Domtree and Subexpressions the ratio of false negatives () outweighs the false positives (), indicating that models favor under-approximating the value sets of these analyses. This may be an artifact of training with such a large imbalance towards negatives () over positive () class labels. In future work we will explore addressing this class imbalance by selecting multiple root points on a graph for analysis simultaneously, thereby increasing the size of the value set to include multiple (possibly overlapping) regions.

96.64% 0.01%
0.01% 3.34%
(a) Reachability
95.94% 0.13%
1.70% 2.23%
(b) DomTree
98.80% 0.00%
0.00% 1.20 %
(c) DataDep
90.00% 0.00%
0.00% 9.99%
(d) Liveness
99.12% 0.02%
0.13% 0.73%
(e) Subexpressions
Table 4: Confusion matrices for compiler analyses using ProGraML. Rows denote true negative () and true positive (), columns denote predicted negative () and predicted positive (). The value of a cell is the ratio of per-vertex model outputs of this type, e.g. is the ratio of false positives.

6.2 Case Study B: Heterogeneous Device Mapping

The performance of ProGraML and baseline models is shown in Table 5. We reused the pre-trained inst2vec-embeddings for the NCC baseline that were published with the original work, however all models themselves have been reimplemented to ensure fair comparison across different models under a unified evaluation regime and absolute performance numbers can thus deviate from the original publications.

Baseline models were trained with hyperparameters from the original works. For the ProGraML results we used 6 layers in the GGNN corresponding to 6 timesteps of message propagation, while sharing parameters between even and odd layers to introduce additional regularization of the weights. We ran a sweep of basic hyperparameters which led us to use the pre-trained inst2vec statement embeddings [12] and to exclude the use of position representations. Both of these hyperparameter choices help generalization by reducing the complexity of the model. This is not surprising in light of the fact that the dataset only contains 680 samples derived from 256 unique programs. ProGraML was trained with the Adam optimizer with default parameters, a learning rate of and a batch size of 18,000 nodes for 300 epochs (resulting in ca. 12000 iteration steps of the optimizer). Additionally we found dropout [51] with a rate of on the weights of the message propagation function to be beneficial on the validation set as well. For the ProGraML result, we repeat the automated sweep for all hyperparameter configurations and picked the configuration with the best average validation performance. Performance on the unseen tenth of the data is reported.

As can be seen, ProGraML outperforms prior approaches to this problem by all metrics (accuracy, precision, recall, and ), across both device datasets.

Accuracy Precision Recall
Static Mapping 58.8% 0.35 0.59 0.44
DeepTune [19] 71.9% 0.72 0.72 0.72
DeepTune 73.8% 0.76 0.74 0.75
NCC [12] 80.3% 0.81 0.80 0.80
ProGraML 86.6% 0.89 0.87 0.88
(f) AMD
Accuracy Precision Recall
Static Mapping 56.9% 0.32 0.57 0.41
DeepTune [19] 61.0% 0.69 0.61 0.65
DeepTune 68.4% 0.70 0.68 0.69
NCC [12] 78.5% 0.79 0.79 0.79
ProGraML 80.0% 0.81 0.80 0.80
(g) NVIDIA
Table 5: Five approaches to predicting heterogeneous device mapping: (a) Static Mapping (b) DeepTune [19], a sequential model using tokenized OpenCL, (c) DeepTune, the same model adapted for tokenized LLVM-IR, (d) NCC, which uses pre-trained statement embeddings, and (e) ProGraML, our approach.

6.3 Case Study C: Algorithm Classification

Table 6 summarizes the algorithm classification accuracy results of our method and baselines.

Baseline Experiments Lifting the XFG graph representation from pretraining embeddings [12] to the high-level task of algorithm classification showed a strong improvement of performance. We found that jointly learning the embeddings with the model from scratch (cf. XFG-rnd in Table 6) outperformed both fixed inst2vec embeddings (XFG-i2v) as well as finetuning of inst2vec embeddings (not shown). Both baselines are an improvement over inst2vec and show that graph-based models are more suited to the task than models with less structure.

Next, we want to understand whether our particular graph-representation reached its design goals and can provide additional improvement on POJ104.

ProGraML Experiments To ablate the contribution of the tokenization from the performance boost provided by the ProGraML representation itself, we include a GGNN-based structure-only baseline (denoted as GGNN-s) of our approach, where the only information on each node is whether it represents a statement or an identifier in the graph, but we refrain from tokenizing statements. We think that algorithm classification is a problem that lends itself especially well to judging the power of the representation structure, since most algorithms are well-defined independent of implementation details, such as datatypes.

The results in Table 6 show that the structure alone of our ProGraML representation is sufficient to outperform the XFG baselines and prior work on the task of algorithms classification. Adding inst2vec statement tokenization further improves performance. This suggests that there is room for improvement in performance by extending the graph encoding method to achieve better vocabulary coverage and stronger generalization. We leave this to future work.

TBCNN [46] NCC [12] XFG ProGraML
Metric i2v rnd GGNN-s GGNN Transformer
Test Error [%] 6.0 5.17 4.56 4.29 3.87 3.78 3.33
Improvement [%] 0.0 11.8 17.0 25.1 26.9 35.6
Table 6: Algorithm Classification Error on POJ-104 [46]. The two XFG models are distinct only in their embedding layers: XFG-i2v uses inst2vec embeddings, while XFG-rnd jointly learns the embeddings. The results denoted by Surface Features and TBCNN are reproduced from Mou et al. [46].

7 Related Work

In order to perform machine learning on programs, prior work has employed methods from Natural Language Processing and represented programs as a sequence of lexical tokens [4, 5, 19]. However, it has been observed [48, 3, 6] that it is critical to capture the structured nature of programs and syntactic (tree-based) as well as semantic (graph-based) representations have been proposed [2, 15]. There is a line of research that considers program representations based on Abstract Syntax Trees (ASTs): Dam et al. [22] annotate nodes in the AST with type information and employ Tree-Based LSTMs [52] for program defect prediction. Both Raychev et al. [48] and Alon et al. [7, 6] use path-based abstractions of the AST as program representations, while Allamanis et al. [3] augment ASTs with a hand-crafted set of additional typed edges and use GGNNs [42] to learn downstream tasks related to variable naming. Another line of research considers modelling binary similarity via control-flow graphs (CFGs) with an adaptation of GNNs called Graph Matching Networks [41].

The history of representing programs as graphs for optimization goes back to Program Dependence Graphs (PDGs) [24], which remove superfluous control flow edges to ease optimization with a compact graph representation. A more contemporary precursor of our ProGraML representation ConteXtual Flow Graphs (XFGs) [12], which combine control flow with dataflow in order to learn unsupervised embeddings of LLVM-IR statements. While ProGraML is designed to extend the concepts of XFGs, ProGraML preserve the notion of argument order and includes nodes for both variables and constant values and all control flow edges. These changes reflects the design goals of the representations — XFGs are designed to easily express program semantics by omitting superfluous control relations and other execution-specific properties. ProGraML, in combining CG, CFG, and DFG, offers a compiler-level program representation that is designed to be useful for a variety of purposes from specific program analyses to downstream optimization tasks.

Another approach is taken by IR2Vec [35], which defines an LLVM-IR-specific statement representation that elegantly models part-of-statements as relations. However, in order to compute the values of the embeddings, IR2Vec requires access to the type of data flow analyses that our approach is learning from data alone.

Brauckmann et al. independently proposed a graph-based representation based on Control and Data Flow Graphs (CDFG) [15]. As in this work, CDFGs represent instructions as graph vertices and have bi-directional edges for control and data relations. What differentiates ProGraML from CDFGs is the richness of the program representation: CDFGs ignore the data elements of programs, and only instruction opcodes are used for vertex embeddings. The latent representation of statements is thus invariant to instruction operands, their order, data types, and instruction modifiers. This limits the representational power of the approach, e.g. by omitting code properties required for reasoning about variables and expressions, as we explore through the Liveness and Subexpressions experiments in this work. Finally, our approach provides improved inference throughput, though we suspect this may be an artifact of our implementation as both approaches scale linearly w.r.t. the size of the graph and number of message passing steps.

Graph Neural Networks comprise a diverse class of neural networks that learn by propagating information along edges [28, 49, 10]. Approaches based on Recurrent Neural Networks (RNNs) [42, 27] as well as convolutional [23, 37] and attention-based methods [54, 55] exist. GNNs as a family have been shown to have enough expressive power to address difficult combinatorial problems like the graph isomorphism test [58] at least as well as the Weisfeiler-Lehman algorithm [57]. Please refer to Battaglia et al. [10] for a comprehensive review of GNNs.

8 Conclusions

With the demand for aggressively optimizing compilers increasing, there is an increasing burden on compiler heuristics to make good optimization decisions. While tuning heuristics by hand is expensive and slow to keep up with the pace of compiler and architecture advancements, machine learning offers tremendous benefits for automatically constructing heuristics that are both cheaper to develop and better performing than hand-crafted equivalents. The success of these machine learning approaches is bound by the quality of the input used to represent programs, and the ability of models to process these representations.

In this work, we present a graph-based representation for programs, derived from compiler IRs, that accurately captures the semantics of a program’s statements and the relations between them. Our approach is more expressive than prior sequence- or graph-based representations, while closely approximating the representations that are traditionally used within compilers.

We have shown through a constructivist approach that machine learning is capable of approximating the types of compiler analyses that are key for optimizations. In testing our approach on a suite of established compiler tasks that even state-of-the-art machine learning methods struggle with, our goal is to inspire confidence in machine learning as a viable tool for reasoning about program semantics, as opposed to a black box which discourages, rather than inspires, a more systematic approach to reasoning about optimizations. When tasked with real-world problems spanning multiple domains and source languages, our approach outperforms prior state-of-the-art approaches.

Our hope in developing ProGraML is to provide a re-usable toolbox for representing and reasoning about programs that can be used for a wide variety of downstream tasks. Promising research avenues for downstream tasks enabled by our enriched program representation and the ability to perform statement-level inference include automatic parallelization, static performance estimation, and IR-to-IR transpilation. Additionally, while the applications of deep learning to compilers is rapidly evolving [2, 21], we hope to focus attention on the challenges that machine learning methods face in the domain of programming languages: scalability when faced with large inputs, modeling very-long-range dependencies, and learning over unbounded vocabularies.

Footnotes

  1. Code and datasets available at https://chriscummins.cc/ProGraML
  2. Given any depth-first spanning tree (DFST) of , backward edges are defined as edges in that connect a node to one of its ancestors in the DFST and is the maximum number of backwards edges in any acyclic path in .
  3. Theoretically the same approach for grouping embeddings by statement could also be extended to group all statements by variables, but this would require duplicating many statements in the input representation, increasing the length of the sequences far beyond what we can practically process using a sequential model.

References

  1. M. Abadi, P. Barham, J. Chen, Z. Chen, A. Davis, J. Dean, M. Devin, S. Ghemawat, G. Irving, M. Isard, M. Kudlur, J. Levenberg, R. Monga, S. Moore, D. G. Murray, B. Steiner, P. Tucker, V. Vasudevan, P. Warden, M. Wicke, Y. Yu and X. Zheng (2016) TensorFlow: A System for Large-scale Machine Learning. In OSDI, Cited by: Table 2.
  2. M. Allamanis, E. T. Barr, P. Devanbu and C. Sutton (2018) A Survey of Machine Learning for Big Code and Naturalness. CSUR 51 (4). Cited by: §1, §2, §7, §8.
  3. M. Allamanis, M. Brockschmidt and M. Khademi (2017) Learning to Represent Programs with Graphs. In ICLR, Cited by: item 2, §3, §5.1.3, §7.
  4. M. Allamanis and C. Sutton (2013) Mining Source Code Repositories at Massive Scale using Language Modeling. In MSR, Cited by: §7.
  5. M. Allamanis (2016) Learning Natural Coding Conventions. Ph.D. Thesis, University of Edinburgh. Cited by: §7.
  6. U. Alon, M. Zilberstein, O. Levy and E. Yahav (2018) A General Path-Based Representation for Predicting Program Properties. In PLDI, Cited by: Table 1, §7.
  7. U. Alon, M. Zilberstein, O. Levy and E. Yahav (2018) code2vec: Learning Distributed Representations of Code. In POPL, Cited by: §1, 1(a), §2, item 1, Table 1, §7.
  8. A. H. Ashouri, W. Killian, J. Cavazos, G. Palermo and C. Silvano (2018) A Survey on Compiler Autotuning using Machine Learning. CSUR 51 (5). Cited by: §1, §3.
  9. F. Barchi, G. Urgese, E. Macii and A. Acquaviva (2019) Code Mapping in Heterogeneous Platforms Using Deep Learning and LLVM-IR. In DAC, Cited by: Table 1.
  10. P. Battaglia, J. Hamrick, V. Bapst, A. Sanchez-Gonzalez, V. Zambaldi, M. Malinowski, A. Tacchetii, D. Raposo, A. Santoro, R. Faulkner, C. Gulcehre, F. Song, A. Ballard, J. Gilmer, G. Dahl, A. Vaswani, K. Allen, C. Nash, V. Langston, C. Dyer, N. Heess, D. Wierstra, P. Kohli, M. Botvinick, O. Vinyals, Y. Li and R. Pascanu (2018) Relational Inductive Biases, Deep Learning, and Graph Networks. arXiv:1806.01261. Cited by: §7.
  11. T. Ben-Nun and T. Hoefler (2019) Demystifying parallel and distributed deep learning: An in-depth concurrency analysis. ACM Computing Surveys 52 (4). Cited by: §5.1.3.
  12. T. Ben-Nun, A. S. Jakobovits and T. Hoefler (2018) Neural Code Comprehension: A Learnable Representation of Code Semantics. In NeurIPS, Cited by: §1, 1(b), §2, item 2, item 3, Table 1, Figure 4, §4.2, §5.1.2, §5.2.2, §5.2, §5.3.1, §5.3.1, 7(f), 7(g), §6.2, §6.3, Table 6, §7.
  13. Y. Bengio, P. Simard and P. Frasconi (1994) Learning Long-Term Dependencies with Gradient Descent is Difficult. IEEE Transactions on Neural Networks 5 (2). Cited by: §1.
  14. S. Blazy, D. Demange and D. Pichardie (2015) Validating Dominator Trees for a Fast, Verified Dominance Test. In ITP, Cited by: §5.1.1.
  15. A. Brauckmann, S. Ertel, A. Goens and J. Castrillon (2020) Compiler-Based Graph Representations for Deep Learning Models of Code. In CC, Cited by: §1, 1(c), §2, item 3, Table 1, §7, §7.
  16. Z. Chen and M. Monperrus (2019) A Literature Study of Embeddings on Source Code. arXiv:1904.03061. Cited by: §2.
  17. K. Cho, B. van Merrienboer, C. Gulcehre, D. Bahdanau, F. Bougares, H. Schwenk and Y. Bengio (2014) Learning Phrase Representations using RNN Encoder-Decoder for Statistical Machine Translation. In EMNLP, Cited by: §4.2.
  18. K. D. Cooper, T. J. Harvey and K. Kennedy (2004) Iterative Data-flow Analysis, Revisited. Technical report Department of Computer Science, Rice University. Cited by: §4, §5.1.3.
  19. C. Cummins, P. Petoumenos, Z. Wang and H. Leather (2017) End-to-end Deep Learning of Optimization Heuristics. In PACT, Cited by: Table 1, Figure 6, §5.1.3, §5.1.3, §5.2.1, §5.2.2, §5.2, Table 2, 7(f), 7(g), Table 5, §7.
  20. C. Cummins, P. Petoumenos, W. Zang and H. Leather (2017) Synthesizing Benchmarks for Predictive Modeling. In CGO, Cited by: item 1, §5.1.2.
  21. C. Cummins (2020) Deep Learning for Compilers. Ph.D. Thesis, University of Edinburgh. Cited by: §8.
  22. H. K. Dam, J. Grundy, T. Kim and C. Kim (2018) A Deep Tree-Based Model for Software Defect Prediction. arXiv:1802.00921. Cited by: §7.
  23. M. Defferrard, X. Bresson and P. Vandergheynst (2016) Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering. In NIPS, Cited by: §7.
  24. J. Ferrante, K. J. Ottenstein and J. D. Warren (1987) The Program Dependence Graph and Its Use in Optimization. TOPLAS 9 (3). Cited by: §7.
  25. Z. Fisches (2020) Neural Self-Supervised Models of Code. Masters Thesis, ETH Zurich. Cited by: §5.3.1.
  26. J. Gehring, M. Auli, D. Grangier, D. Yarats and Y. N. Dauphin (2017) Convolutional Sequence to Sequence Learning. In ICML, Cited by: §4.2.
  27. J. Gilmer, S. S. Schoenholz, P. F. Riley, O. Vinyals and G. E. Dahl (2017) Neural Message Passing for Quantum Chemistry. In ICML, Cited by: §1, §4, §5.1.3, §7.
  28. M. Gori, G. Monfardini and F. Scarselli (2005) A New Model for Learning in Graph Domains. In IJCNN, Cited by: §7.
  29. D. Grewe, Z. Wang and M. O’Boyle (2013) Portable Mapping of Data Parallel Programs to OpenCL for Heterogeneous Systems. In CGO, Cited by: §5.2.
  30. A. Haj-Ali, N. K. Ahmed, T. Willke, S. Shao, K. Asanovic and I. Stoica (2020) NeuroVectorizer: End-to-End Vectorization with Deep Reinforcement Learning. In CGO, Cited by: §1.
  31. V. J. Hellendoorn, C. Bird, E. T. Barr and M. Allamanis (2018) Deep Learning Type Inference. In ESEC/FSE, Cited by: Table 1.
  32. G. E. Hinton, N. Srivastava, A. Krizhevsky, I. Sutskever and R. R. Salakhutdinov (2012) Improving Neural Networks by Preventing Co-adaptation of Feature Detectors. arXiv:1207.0580. Cited by: §5.2.3.
  33. S. Ioffe and C. Szegedy (2015) Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift. In ICML, Cited by: §4.2, §5.2.3.
  34. J. B. Kam and J. D. Ullman (1977) Monotone Data Flow Analysis Frameworks. Acta Informatica 7 (3). Cited by: §4, §5.1.3.
  35. V. Keerthy S, R. Aggarwal, S. Jain, M. S. Desarkar, R. Upadrasta and Y. N. Spkant (2019) IR2Vec: A Flow Analysis based Scalable Infrastructure for Program Encodings. arXiv:1909.06228. Cited by: §7.
  36. D. P. Kingma and J. L. Ba (2015) Adam: a Method for Stochastic Optimization. In ICLR, Cited by: §5.1.4.
  37. T. N. Kipf and M. Welling (2017) Semi-supervised Classification with Graph Convolutional Networks. arXiv:1609.02907. Cited by: §7.
  38. C. Lattner and V. Adve (2004) LLVM: A compilation framework for lifelong program analysis & transformation. In CGO, Cited by: §3.2, §3.2.
  39. C. Leary and T. Wang (2017) XLA: TensorFlow, compiled. In TensorFlow Dev Summit, Cited by: §3.2.
  40. T. Lengauer and R. E. Tarjan (1979) A Fast Algorithm for Finding Dominators in a Flow Graph. TOPLAS 1 (1). Cited by: §5.1.1.
  41. L. Li, C. Gu, T. Dullien, O. Vinyals and P. Kohli (2019) Graph Matching Networks for Learning the Similarity of Graph Structured Objects. In ICML, Cited by: §7.
  42. Y. Li, R. Zemel, M. Brockscmidt and D. Tarlow (2015) Gated Graph Sequence Neural Networks. arXiv:1511.05493. Cited by: §1, §4.2, §4, §5.1.3, §5.3.1, §7, §7.
  43. I. Loshchilov and F. Hutter (2019) Decoupled weight decay regularization. In ICLR, Cited by: §5.3.2.
  44. M. McCloskey and N. J. Cohen (1989) Catastrophic Interference in Connectionist Networks: The Sequential Learning Problem. Psychology of Learning and Motivation 24. Cited by: §1.
  45. A. Mirhoseini, H. Pham, Q. V. Le, B. Steiner, R. Larsen, Y. Zhou, N. Kumar, M. Norouzi, S. Bengio and J. Dean (2017) Device Placement Optimization with Reinforcement Learning. In ICML, Cited by: §1.
  46. L. Mou, G. Li, L. Zhang, T. Wang and Z. Jin (2016) Convolutional Neural Networks over Tree Structures for Programming Language Processing. In AAAI, Cited by: §5.3.1, §5.3, Table 2, Table 6.
  47. E. Park, J. Cavazos and M. A. Alvarez (2012) Using Graph-Based Program Characterization for Predictive Modeling. In CGO, Cited by: item 2.
  48. V. Raychev, M. Vechev and A. Krause (2015) Predicting Program Properties from ”Big Code”. In POPL, Cited by: §7.
  49. S. Scarselli, M. Gori, A. C. Tsoi, M. Hagenbuchner and G. Monfardini (2009) The Graph Neural Network Model. IEEE Transactions on Neural Networks 20 (1). Cited by: §7.
  50. M. Schlichtkrull, T. N. Kipf, P. Bloem, R. van den Berg, I. Titov and M. Welling (2018) Modeling Relational Data with Graph Convolutional Networks. In ESWC, Cited by: §1.
  51. N. Srivastava, G. Hinton, A. Krizhevsky, I. Sutskever and R. Salakhutdinov (2014) Dropout: A Simple Way to Prevent Neural Networks from Overfitting. JMLR 15. Cited by: §6.2.
  52. K. S. Tai, R. Socher and C. D. Manning (2015) Improved Semantic Representations From Tree-Structured Long Short-Term Memory Networks. arXiv:1503.00075. Cited by: §7.
  53. A. Vaswani, N. Shazeer, N. Parmar, J. Uszkoreit, L. Jones, A. N. Gomez, L. Kaiser and I. Polosukhin (2017) Attention Is All You Need. In NIPS, Cited by: §2, §4.2, §5.3.1, §5.3.2.
  54. P. Velickovic, G. Cucurull, A. Casanova, A. Romera, P. Lio and Y. Bengio (2018) Graph Attention Networks. In ICLR, Cited by: §7.
  55. G. Wang, R. Ying, J. Huang and J. Leskovec (2019) Improving Graph Attention Networks with Large Margin-based Constraints. arXiv:1910.11945. Cited by: §7.
  56. Z. Wang and M. O’Boyle (2018) Machine learning in Compiler Optimization. Proceedings of the IEEE 106 (23). Cited by: §1, §2, §3.
  57. B. Weisfeiler and A. A. Lehman (1968) A Reduction of a Graph to a Canonical Form and an Algebra Arising During this Reduction. Nauchno-Technicheskaya Informatsia 2 (9). Cited by: §7.
  58. K. Xu, W. Hu, J. Leskovec and S. Jegelka (2019) How Powerful are Graph neural Networks?. In ICLR, Cited by: §7.
  59. P. Yin, G. Neubig, M. Allamanis, M. Brockschmidt and A. L. Gaunt (2018) Learning to Represent Edits. arXiv:1810.13337. Cited by: §1.
Comments 0
Request Comment
You are adding the first comment!
How to quickly get a good reply:
  • Give credit where it’s due by listing out the positive aspects of a paper before getting into which changes should be made.
  • Be specific in your critique, and provide supporting evidence with appropriate references to substantiate general statements.
  • Your comment should inspire ideas to flow and help the author improves the paper.

The better we are at sharing our knowledge with each other, the faster we move forward.
""
The feedback must be of minimum 40 characters and the title a minimum of 5 characters
   
Add comment
Cancel
Loading ...
412627
This is a comment super asjknd jkasnjk adsnkj
Upvote
Downvote
""
The feedback must be of minumum 40 characters
The feedback must be of minumum 40 characters
Submit
Cancel

You are asking your first question!
How to quickly get a good answer:
  • Keep your question short and to the point
  • Check for grammar or spelling errors.
  • Phrase it like a question
Test
Test description