summaryrefslogtreecommitdiff
path: root/src/jit/inline.h
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2016-02-19 11:57:41 -0800
committerAndy Ayers <andya@microsoft.com>2016-02-19 18:29:59 -0800
commitea53f9a34f4c658b207c214568e78c2635629711 (patch)
treee7c87804eb0a8016c063e94cec46a90027460871 /src/jit/inline.h
parentf0b5ca1bf84f2704426b6bda266b410a4eda508f (diff)
downloadcoreclr-ea53f9a34f4c658b207c214568e78c2635629711.tar.gz
coreclr-ea53f9a34f4c658b207c214568e78c2635629711.tar.bz2
coreclr-ea53f9a34f4c658b207c214568e78c2635629711.zip
InlineRefactoring: start to capture failures in the inline tree
This change starts capturing information about failed inlines in the inline tree. Not all failures are captured yet; see below for notes. Sample trees showing a failure: ``` Inlines into Secant:Inner(byref,byref,double,double,int,byref) [IL=0004 TR=000008] [FAILED: exceeds profit threshold] Secant:FF(double):double [IL=0023 TR=000036] [native size estimate ok] Secant:FF(double):double ``` InlineContext is revised to have 3 static constructors: one for the root context, one for successful inlines, and one for failed inlines. Successful inlines are always captured in the tree, since they are used to track inline depth and recursion. Failures are only captured in DEBUG and are just there for diagnostic purposes. The success and failure constructors also link the new contexts into the tree at the proper spot. With this the jit can now capture failures for calls that were initially identified as candidates. Top-level non-candidates are still screened out in fgInline, and lower-level non-candidates simply aren't seen at all by the current code. This will be addressed in a subsequent change. New calls can appear in the gap between caller and callee, as the code for the two is stitched together. These are never candidates and never given candidate screening. For now, if a new failing context is unable to find a parent context from the IR, the code assumes the IR was created in this gap. Down the road we may want to insist that all IR be covered by some InlineContext (eg for improved debugging of optimized code). The InlineContext now also captures and prints the tree ID of the call to make it easier to relate back to IR dumps.
Diffstat (limited to 'src/jit/inline.h')
-rw-r--r--src/jit/inline.h121
1 files changed, 84 insertions, 37 deletions
diff --git a/src/jit/inline.h b/src/jit/inline.h
index 9f72edb90b..a2a060fb11 100644
--- a/src/jit/inline.h
+++ b/src/jit/inline.h
@@ -13,13 +13,13 @@
// InlineTarget -- enum, target of a particular observation
// InlineImpact -- enum, impact of a particular observation
// InlineObservation -- enum, facts observed when considering an inline
-// InlineContext -- class, remembers what inlines happened
// InlineResult -- class, accumulates observations and makes a decision
// InlineCandidateInfo -- struct, detailed information needed for inlining
// InlArgInfo -- struct, information about a candidate's argument
// InlLclVarInfo -- struct, information about a candidate's local variable
// InlineHints -- enum, alternative form of observations
// InlineInfo -- struct, basic information needed for inlining
+// InlineContext -- class, remembers what inlines happened
#ifndef _INLINE_H_
#define _INLINE_H_
@@ -117,42 +117,6 @@ InlineTarget inlGetTarget(InlineObservation obs);
InlineImpact inlGetImpact(InlineObservation obs);
-// InlineContext tracks the inline history in a method.
-//
-// Notes:
-//
-// InlineContexts form a tree with the root method as the root and
-// inlines as children. Nested inlines are represented as granchildren
-// and so on.
-//
-// Leaves in the tree represent successful inlines of leaf methods.
-// In DEBUG builds we also keep track of failed inline attempts.
-//
-// During inlining, all statements in the IR refer back to the
-// InlineContext that is responsible for those statements existing.
-// This makes it possible to detect recursion and to keep track of the
-// depth of each inline attempt.
-
-struct InlineContext
-{
- // Default constructor, suitable for root instance
- InlineContext();
-
- InlineContext* inlParent; // logical caller (parent)
- InlineContext* inlChild; // first child
- InlineContext* inlSibling; // next child of the parent
- IL_OFFSETX inlOffset; // call site location within parent
- BYTE* inlCode; // address of IL buffer for the method
- InlineObservation inlObservation; // what lead to this inline
-
-#ifdef DEBUG
- CORINFO_METHOD_HANDLE inlCallee; // handle to the method
-
- // Dump this entry and all descendants
- void Dump(Compiler* compiler, int indent = 0);
-#endif
-};
-
// InlineResult summarizes what is known about the viability of a
// particular inline candiate.
@@ -361,6 +325,18 @@ public:
return inlObservation;
}
+ // The callee handle for this result
+ CORINFO_METHOD_HANDLE getCallee() const
+ {
+ return inlCallee;
+ }
+
+ // The call being considered
+ GenTreeCall* getCall() const
+ {
+ return inlCall;
+ }
+
// The reason for this particular result
const char * reasonString() const
{
@@ -537,6 +513,77 @@ struct InlineInfo
BasicBlock * iciBlock; // The basic block iciStmt is in.
};
+// InlineContext tracks the inline history in a method.
+//
+// Notes:
+//
+// InlineContexts form a tree with the root method as the root and
+// inlines as children. Nested inlines are represented as granchildren
+// and so on.
+//
+// Leaves in the tree represent successful inlines of leaf methods.
+// In DEBUG builds we also keep track of failed inline attempts.
+//
+// During inlining, all statements in the IR refer back to the
+// InlineContext that is responsible for those statements existing.
+// This makes it possible to detect recursion and to keep track of the
+// depth of each inline attempt.
+
+class InlineContext
+{
+public:
+
+ // New context for the root instance
+ static InlineContext* newRoot(Compiler* compiler);
+
+ // New context for a successful inline
+ static InlineContext* newSuccess(Compiler* compiler,
+ InlineInfo* inlineInfo);
+
+#ifdef DEBUG
+
+ // New context for a failing inline
+ static InlineContext* newFailure(Compiler * compiler,
+ GenTree* stmt,
+ InlineResult* inlineResult);
+
+ // Dump the context and all descendants
+ void Dump(Compiler* compiler, int indent = 0);
+
+#endif
+
+ // Get the parent context for this context.
+ InlineContext* getParent() const
+ {
+ return inlParent;
+ }
+
+ // Get the code pointer for this context.
+ BYTE* getCode() const
+ {
+ return inlCode;
+ }
+
+private:
+
+ InlineContext();
+
+private:
+
+ InlineContext* inlParent; // logical caller (parent)
+ InlineContext* inlChild; // first child
+ InlineContext* inlSibling; // next child of the parent
+ IL_OFFSETX inlOffset; // call site location within parent
+ BYTE* inlCode; // address of IL buffer for the method
+ InlineObservation inlObservation; // what lead to this inline
+
+#ifdef DEBUG
+ CORINFO_METHOD_HANDLE inlCallee; // handle to the method
+ unsigned inlTreeID; // ID of the GenTreeCall
+ bool inlSuccess; // true if this was a successful inline
+#endif
+
+};
#endif // _INLINE_H_