Sfoglia il codice sorgente

Add opt support for naming module prints and to diff them in dndxc. (#228)

Marcelo Lopez Ruiz 8 anni fa
parent
commit
b3eb288629

+ 20 - 2
lib/HLSL/DxcOptimizer.cpp

@@ -47,6 +47,13 @@ using namespace hlsl;
 inline static bool wcseq(LPCWSTR a, LPCWSTR b) {
   return 0 == wcscmp(a, b);
 }
+inline static bool wcsstartswith(LPCWSTR value, LPCWSTR prefix) {
+  while (*value && *prefix && *value == *prefix) {
+    ++value;
+    ++prefix;
+  }
+  return *prefix == L'\0';
+}
 
 namespace hlsl {
 
@@ -584,8 +591,19 @@ HRESULT STDMETHODCALLTYPE DxcOptimizer::RunOptimizer(
       }
 
       // Handle some special cases where we can inject a redirected output stream.
-      if (wcseq(ppOptions[i], L"-print-module")) {
-        pPassManager->add(llvm::createPrintModulePass(outStream));
+      if (wcsstartswith(ppOptions[i], L"-print-module")) {
+        LPCWSTR pName = ppOptions[i] + _countof(L"-print-module") - 1;
+        std::string Banner;
+        if (*pName) {
+          IFTARG(*pName != L':' || *pName != L'=');
+          ++pName;
+          CW2A name8(pName);
+          Banner = "MODULE-PRINT ";
+          Banner += name8.m_psz;
+          Banner += "\n";
+        }
+        if (pPassManager == &ModulePasses)
+          pPassManager->add(llvm::createPrintModulePass(outStream, Banner));
         continue;
       }
 

+ 24 - 9
tools/clang/tools/dotnetc/EditorForm.Designer.cs

@@ -105,6 +105,7 @@ namespace MainNs
             this.OutputTabControl = new System.Windows.Forms.TabControl();
             this.RenderLogTabPage = new System.Windows.Forms.TabPage();
             this.RenderLogBox = new System.Windows.Forms.TextBox();
+            this.PrintAllPassesBox = new System.Windows.Forms.CheckBox();
             this.TheStatusStrip.SuspendLayout();
             this.TheMenuStrip.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
@@ -526,7 +527,7 @@ namespace MainNs
             this.ASTTabPage.Margin = new System.Windows.Forms.Padding(4);
             this.ASTTabPage.Name = "ASTTabPage";
             this.ASTTabPage.Padding = new System.Windows.Forms.Padding(4);
-            this.ASTTabPage.Size = new System.Drawing.Size(976, 968);
+            this.ASTTabPage.Size = new System.Drawing.Size(976, 970);
             this.ASTTabPage.TabIndex = 1;
             this.ASTTabPage.Text = "AST";
             this.ASTTabPage.UseVisualStyleBackColor = true;
@@ -538,12 +539,13 @@ namespace MainNs
             this.ASTDumpBox.Margin = new System.Windows.Forms.Padding(4);
             this.ASTDumpBox.Name = "ASTDumpBox";
             this.ASTDumpBox.ReadOnly = true;
-            this.ASTDumpBox.Size = new System.Drawing.Size(968, 960);
+            this.ASTDumpBox.Size = new System.Drawing.Size(968, 962);
             this.ASTDumpBox.TabIndex = 0;
             this.ASTDumpBox.Text = "";
             // 
             // OptimizerTabPage
             // 
+            this.OptimizerTabPage.Controls.Add(this.PrintAllPassesBox);
             this.OptimizerTabPage.Controls.Add(this.ResetDefaultPassesButton);
             this.OptimizerTabPage.Controls.Add(this.AnalyzeCheckBox);
             this.OptimizerTabPage.Controls.Add(this.AddPrintModuleButton);
@@ -558,7 +560,7 @@ namespace MainNs
             this.OptimizerTabPage.Margin = new System.Windows.Forms.Padding(4);
             this.OptimizerTabPage.Name = "OptimizerTabPage";
             this.OptimizerTabPage.Padding = new System.Windows.Forms.Padding(4);
-            this.OptimizerTabPage.Size = new System.Drawing.Size(976, 968);
+            this.OptimizerTabPage.Size = new System.Drawing.Size(976, 970);
             this.OptimizerTabPage.TabIndex = 2;
             this.OptimizerTabPage.Text = "Optimizer";
             this.OptimizerTabPage.UseVisualStyleBackColor = true;
@@ -566,7 +568,7 @@ namespace MainNs
             // ResetDefaultPassesButton
             // 
             this.ResetDefaultPassesButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-            this.ResetDefaultPassesButton.Location = new System.Drawing.Point(560, 806);
+            this.ResetDefaultPassesButton.Location = new System.Drawing.Point(560, 808);
             this.ResetDefaultPassesButton.Margin = new System.Windows.Forms.Padding(4);
             this.ResetDefaultPassesButton.Name = "ResetDefaultPassesButton";
             this.ResetDefaultPassesButton.Size = new System.Drawing.Size(292, 48);
@@ -579,7 +581,7 @@ namespace MainNs
             // 
             this.AnalyzeCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
             this.AnalyzeCheckBox.AutoSize = true;
-            this.AnalyzeCheckBox.Location = new System.Drawing.Point(14, 764);
+            this.AnalyzeCheckBox.Location = new System.Drawing.Point(14, 766);
             this.AnalyzeCheckBox.Margin = new System.Windows.Forms.Padding(6);
             this.AnalyzeCheckBox.Name = "AnalyzeCheckBox";
             this.AnalyzeCheckBox.Size = new System.Drawing.Size(196, 29);
@@ -590,7 +592,7 @@ namespace MainNs
             // AddPrintModuleButton
             // 
             this.AddPrintModuleButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
-            this.AddPrintModuleButton.Location = new System.Drawing.Point(14, 806);
+            this.AddPrintModuleButton.Location = new System.Drawing.Point(14, 844);
             this.AddPrintModuleButton.Margin = new System.Windows.Forms.Padding(4);
             this.AddPrintModuleButton.Name = "AddPrintModuleButton";
             this.AddPrintModuleButton.Size = new System.Drawing.Size(292, 48);
@@ -602,7 +604,7 @@ namespace MainNs
             // RunPassesButton
             // 
             this.RunPassesButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-            this.RunPassesButton.Location = new System.Drawing.Point(560, 858);
+            this.RunPassesButton.Location = new System.Drawing.Point(560, 860);
             this.RunPassesButton.Margin = new System.Windows.Forms.Padding(4);
             this.RunPassesButton.Name = "RunPassesButton";
             this.RunPassesButton.Size = new System.Drawing.Size(292, 48);
@@ -614,7 +616,7 @@ namespace MainNs
             // SelectPassDownButton
             // 
             this.SelectPassDownButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-            this.SelectPassDownButton.Location = new System.Drawing.Point(706, 746);
+            this.SelectPassDownButton.Location = new System.Drawing.Point(706, 748);
             this.SelectPassDownButton.Margin = new System.Windows.Forms.Padding(4);
             this.SelectPassDownButton.Name = "SelectPassDownButton";
             this.SelectPassDownButton.Size = new System.Drawing.Size(146, 48);
@@ -626,7 +628,7 @@ namespace MainNs
             // SelectPassUpButton
             // 
             this.SelectPassUpButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-            this.SelectPassUpButton.Location = new System.Drawing.Point(560, 746);
+            this.SelectPassUpButton.Location = new System.Drawing.Point(560, 748);
             this.SelectPassUpButton.Margin = new System.Windows.Forms.Padding(4);
             this.SelectPassUpButton.Name = "SelectPassUpButton";
             this.SelectPassUpButton.Size = new System.Drawing.Size(138, 48);
@@ -775,6 +777,18 @@ namespace MainNs
             this.RenderLogBox.TabIndex = 0;
             this.RenderLogBox.WordWrap = false;
             // 
+            // PrintAllPassesBox
+            // 
+            this.PrintAllPassesBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.PrintAllPassesBox.AutoSize = true;
+            this.PrintAllPassesBox.Location = new System.Drawing.Point(14, 805);
+            this.PrintAllPassesBox.Margin = new System.Windows.Forms.Padding(6);
+            this.PrintAllPassesBox.Name = "PrintAllPassesBox";
+            this.PrintAllPassesBox.Size = new System.Drawing.Size(191, 29);
+            this.PrintAllPassesBox.TabIndex = 10;
+            this.PrintAllPassesBox.Text = "Print all passes";
+            this.PrintAllPassesBox.UseVisualStyleBackColor = true;
+            // 
             // EditorForm
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F);
@@ -886,5 +900,6 @@ namespace MainNs
         private System.Windows.Forms.TextBox RenderLogBox;
         private System.Windows.Forms.ToolStripMenuItem FontGrowToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem FontShrinkToolStripMenuItem;
+        private System.Windows.Forms.CheckBox PrintAllPassesBox;
     }
 }

+ 210 - 3
tools/clang/tools/dotnetc/EditorForm.cs

@@ -1190,6 +1190,14 @@ namespace MainNs
             return pass.GetOptionName() + OptDescSeparator + pass.GetDescription();
         }
 
+        private string PassStringToBanner(string value)
+        {
+            int separator = value.IndexOf(OptDescSeparator);
+            if (separator >= 0)
+                value = value.Substring(0, separator);
+            return value;
+        }
+
         private string PassStringToOption(string value)
         {
             int separator = value.IndexOf(OptDescSeparator);
@@ -1306,14 +1314,72 @@ namespace MainNs
             List<string> result = new List<string>();
             if (this.AnalyzeCheckBox.Checked)
                 result.Add("-analyze");
+            bool printAll = this.PrintAllPassesBox.Checked;
             var items = this.SelectedPassesBox.Items;
+            if (printAll)
+                result.Add("-print-module:start");
             for (int i = 0; i < items.Count; ++i)
             {
-                result.Add(PassStringToOption(items[i].ToString()));
+                string itemText = items[i].ToString();
+                result.Add(PassStringToOption(itemText));
+                if (printAll)
+                    result.Add("-print-module:" + itemText);
             }
             return result.ToArray();
         }
 
+        class TextSection
+        {
+            private string[] lines;
+            private int[] lineHashes;
+            public string Title;
+            public string Text;
+            public bool HasChange;
+            public string[] Lines
+            {
+                get
+                {
+                    if (lines == null)
+                       lines = Text.Split(new char[] { '\n' });
+                    return lines;
+                }
+            }
+            public int[] LineHashes
+            {
+                get
+                {
+                    if (lineHashes == null)
+                       lineHashes = lines.Select(l => l.GetHashCode()).ToArray();
+                    return lineHashes;
+                }
+            }
+            public override string ToString()
+            {
+                return Title;
+            }
+        }
+
+        private static IEnumerable<TextSection> EnumerateSections(string separator, string text)
+        {
+            string prior = null;
+            int idx = text.IndexOf(separator);
+            while (idx >= 0)
+            {
+                int lineEnd = text.IndexOf('\n', idx);
+                if (lineEnd < 0) break;
+                string title = text.Substring(idx + separator.Length, lineEnd - (idx + separator.Length));
+                title = title.Trim();
+                int next = text.IndexOf(separator, lineEnd);
+                string sectionText = (next < 0) ? text.Substring(lineEnd + 1) : text.Substring(lineEnd + 1, next - (lineEnd + 1));
+                sectionText = sectionText.Trim();
+                if (sectionText == prior)
+                    sectionText = prior;
+                yield return new TextSection { Title = title, Text = sectionText };
+                idx = next;
+                prior = sectionText;
+            }
+        }
+
         private void RunPassesButton_Click(object sender, EventArgs e)
         {
             // TODO: consider accepting DXIL in the code editor as well
@@ -1360,18 +1426,141 @@ namespace MainNs
             LogContextMenuHelper helper = new LogContextMenuHelper(rtb);
             rtb.Dock = DockStyle.Fill;
             rtb.Font = this.CodeBox.Font;
-            rtb.Text = resultText;
             rtb.ContextMenu = new ContextMenu(
                 new MenuItem[]
                 {
                     new MenuItem("Show Graph", helper.ShowGraphClick)
                 });
             rtb.SelectionChanged += DisassemblyTextBox_SelectionChanged;
-            form.Controls.Add(rtb);
+            if (this.PrintAllPassesBox.Checked)
+            {
+                SplitContainer split = new SplitContainer() { Dock = DockStyle.Fill };
+                ListBox sectionBox = new ListBox() { Dock = DockStyle.Fill };
+                RadioButton leftButton = new RadioButton() { Text = "Left Only" };
+                RadioButton diffButton = new RadioButton() { Checked = true, Text = "Both", Left = leftButton.Right };
+                RadioButton rightButton = new RadioButton() { Text = "Right Only", Left = diffButton.Right };
+                Panel optionsPanel = new Panel() { Dock = DockStyle.Top, Height = diffButton.Bottom };
+                optionsPanel.Controls.AddRange(new Control[] { leftButton, diffButton, rightButton } );
+                var sections = EnumerateSections("MODULE-PRINT", resultText).ToArray();
+                TextSection last = null;
+                foreach (var s in sections)
+                {
+                    s.HasChange = last != null && !object.ReferenceEquals(last.Text, s.Text);
+                    if (s.HasChange) s.Title = "* " + s.Title;
+                    last = s;
+                }
+                sectionBox.Items.AddRange(sections);
+                Action updateBox = () =>
+                {
+                    rtb.Clear();
+                    int index = sectionBox.SelectedIndex;
+                    if (index == -1) return;
+                    TextSection section = (TextSection)sectionBox.SelectedItem;
+                    TextSection prior = index == 0 ? null : sectionBox.Items[index-1] as TextSection;
+                    if (prior == null || section.Text == prior.Text || rightButton.Checked)
+                        rtb.Text = section.Text;
+                    else if (leftButton.Checked)
+                        rtb.Text = (prior == null) ? "(no prior text)" : prior.Text;
+                    else
+                        RunDiff(prior, section, rtb);
+                };
+                EventHandler H = (ccChanged, __) =>
+                {
+                    if (((RadioButton)ccChanged).Checked) updateBox();
+                };
+                leftButton.CheckedChanged += H;
+                diffButton.CheckedChanged += H;
+                rightButton.CheckedChanged += H;
+                sectionBox.SelectedIndexChanged += (_, __) => { updateBox(); };
+                split.Panel1.Controls.Add(sectionBox);
+                split.Panel2.Controls.Add(rtb);
+                split.Panel2.Controls.Add(optionsPanel);
+                form.Controls.Add(split);
+            }
+            else
+            {
+                rtb.Text = resultText;
+                form.Controls.Add(rtb);
+            }
             form.StartPosition = FormStartPosition.CenterParent;
             form.Show(this);
         }
 
+        private void RunDiff(TextSection oldText, TextSection newText, RichTextBox rtb)
+        {
+            // Longest common subsequence, simple edition. If/when something faster is needed,
+            // should probably take a dependency on a proper diff package. Other than shorter
+            // comparison windows, other things to look for are avoiding creating strings here,
+            // working on the RichTextBox buffer directly for color, and unique'ing lines.
+            string[] oldLines = oldText.Lines;
+            string[] newLines = newText.Lines;
+            // Reduce strings to hashes.
+            int[] oldHashes = oldText.LineHashes;
+            int[] newHashes = newText.LineHashes;
+            // Reduce by trimming prefix and suffix.
+            int diffStart = 0;
+            while (diffStart < oldHashes.Length && diffStart < newHashes.Length && oldHashes[diffStart] == newHashes[diffStart])
+                diffStart++;
+            int newDiffEndExc = newLines.Length, oldDiffEndExc = oldLines.Length;
+            while (newDiffEndExc > diffStart && oldDiffEndExc > diffStart)
+            {
+                if (oldHashes[oldDiffEndExc - 1] == newHashes[newDiffEndExc - 1])
+                {
+                    oldDiffEndExc--;
+                    newDiffEndExc--;
+                }
+                else
+                    break;
+            }
+            int suffixLength = (newLines.Length - newDiffEndExc);
+            // Build LCS table.
+            int oldLen = oldDiffEndExc - diffStart, newLen = newDiffEndExc - diffStart;
+            int[,] lcs = new int[oldLen + 1, newLen + 1]; // already zero-initialized
+            for (int i = 0; i < oldLen; i++)
+                for (int j = 0; j < newLen; j++)
+                    if (oldHashes[i + diffStart] == newHashes[j + diffStart])
+                        lcs[i + 1, j + 1] = lcs[i, j] + 1;
+                    else
+                        lcs[i + 1, j + 1] = Math.Max(lcs[i, j + 1], lcs[i + 1, j]);
+            // Print the diff - common prefix, backtracked diff and common suffix.
+            rtb.AppendLines("  ", newLines, 0, diffStart, Color.White);
+            {
+                int i = oldLen, j = newLen;
+                Stack<string> o = new Stack<string>();
+                for (;;)
+                {
+                    if (i > 0 && j > 0 && oldHashes[diffStart + i - 1] == newHashes[diffStart + j - 1])
+                    {
+                        o.Push("  " + oldLines[diffStart + i - 1]);
+                        i--;
+                        j--;
+                    }
+                    else if (j > 0 && (i == 0 || lcs[i, j - 1] >= lcs[i - 1, j]))
+                    {
+                        o.Push("+ " + newLines[diffStart + j - 1]);
+                        j--;
+                    }
+                    else if (i > 0 && (j == 0 || lcs[i, j - 1] < lcs[i - 1, j]))
+                    {
+                        o.Push("- " + oldLines[diffStart + i - 1]);
+                        i--;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                while (o.Count != 0)
+                {
+                    string line = o.Pop();
+                    Color c = (line[0] == ' ') ? Color.White :
+                        ((line[0] == '+') ? Color.Yellow : Color.Red);
+                    rtb.AppendLine(line, c);
+                }
+            }
+            rtb.AppendLines("  ", newLines, newDiffEndExc, (newLines.Length - newDiffEndExc), Color.White);
+        }
+
         private void SelectPassUpButton_Click(object sender, EventArgs e)
         {
             ListBox lb = this.SelectedPassesBox;
@@ -2578,4 +2767,22 @@ namespace MainNs
             target.Font = new Font(target.Font.FontFamily, target.Font.Size / 1.1f);
         }
     }
+
+    public static class RichTextBoxExt
+    {
+        public static void AppendLine(this RichTextBox rtb, string line, Color c)
+        {
+            rtb.SelectionBackColor = c;
+            rtb.AppendText(line);
+            rtb.AppendText("\r\n");
+        }
+
+        public static void AppendLines(this RichTextBox rtb, string prefix, string[] lines, int start, int length, Color c)
+        {
+            for (int i = start; i < (start + length); ++i)
+            {
+                rtb.AppendLine(prefix + lines[i], c);
+            }
+        }
+    }
 }