Index: test/tools/llvm-xray/X86/graph-color-simple-case.yaml =================================================================== --- test/tools/llvm-xray/X86/graph-color-simple-case.yaml +++ test/tools/llvm-xray/X86/graph-color-simple-case.yaml @@ -32,15 +32,15 @@ #EDGE: digraph xray { -#EDGE-DAG: F0 -> F7 [label="7.{{[0-9]*}}e+01" color="#B00100"]; -#EDGE-DAG: F0 -> F2 [label="2.{{[0-9]*}}e+01" color="#FD9965"]; -#EDGE-DAG: F0 -> F9 [label="9.{{[0-9]*}}e+01" color="#7F0000"]; -#EDGE-DAG: F0 -> F4 [label="4.{{[0-9]*}}e+01" color="#E8543b"]; -#EDGE-DAG: F0 -> F6 [label="6.{{[0-9]*}}e+01" color="#C5140a"]; -#EDGE-DAG: F0 -> F1 [label="1.{{[0-9]*}}e+01" color="#FDC58c"]; -#EDGE-DAG: F0 -> F8 [label="8.{{[0-9]*}}e+01" color="#990101"]; -#EDGE-DAG: F0 -> F3 [label="3.{{[0-9]*}}e+01" color="#F5744d"]; -#EDGE-DAG: F0 -> F5 [label="5.{{[0-9]*}}e+01" color="#D83323"]; +#EDGE-DAG: F0 -> F7 [label="7.{{[0-9]*}}e+01" color="#B10101"]; +#EDGE-DAG: F0 -> F2 [label="2.{{[0-9]*}}e+01" color="#FC9862"]; +#EDGE-DAG: F0 -> F9 [label="9.{{[0-9]*}}e+01" color="#7E0000"]; +#EDGE-DAG: F0 -> F4 [label="4.{{[0-9]*}}e+01" color="#E9553D"]; +#EDGE-DAG: F0 -> F6 [label="6.{{[0-9]*}}e+01" color="#C5130A"]; +#EDGE-DAG: F0 -> F1 [label="1.{{[0-9]*}}e+01" color="#FDC58E"]; +#EDGE-DAG: F0 -> F8 [label="8.{{[0-9]*}}e+01" color="#9A0000"]; +#EDGE-DAG: F0 -> F3 [label="3.{{[0-9]*}}e+01" color="#F5744E"]; +#EDGE-DAG: F0 -> F5 [label="5.{{[0-9]*}}e+01" color="#D83321"]; #EDGE-DAG: F7 [label="@(7)"]; #EDGE-DAG: F2 [label="@(2)"]; #EDGE-DAG: F9 [label="@(9)"]; @@ -63,13 +63,13 @@ #VERTEX-DAG: F0 -> F8 [label=""]; #VERTEX-DAG: F0 -> F3 [label=""]; #VERTEX-DAG: F0 -> F5 [label=""]; -#VERTEX-DAG: F7 [label="{@(7)|7.{{[0-9]*}}e+01}" color="#B00100"]; -#VERTEX-DAG: F2 [label="{@(2)|2.{{[0-9]*}}e+01}" color="#FD9965"]; -#VERTEX-DAG: F9 [label="{@(9)|9.{{[0-9]*}}e+01}" color="#7F0000"]; -#VERTEX-DAG: F4 [label="{@(4)|4.{{[0-9]*}}e+01}" color="#E8543b"]; -#VERTEX-DAG: F6 [label="{@(6)|6.{{[0-9]*}}e+01}" color="#C5140a"]; -#VERTEX-DAG: F1 [label="{@(1)|1.{{[0-9]*}}e+01}" color="#FDC58c"]; -#VERTEX-DAG: F8 [label="{@(8)|8.{{[0-9]*}}e+01}" color="#990101"]; -#VERTEX-DAG: F3 [label="{@(3)|3.{{[0-9]*}}e+01}" color="#F5744d"]; -#VERTEX-DAG: F5 [label="{@(5)|5.{{[0-9]*}}e+01}" color="#D83323"]; +#VERTEX-DAG: F7 [label="{@(7)|7.{{[0-9]*}}e+01}" color="#B10101"]; +#VERTEX-DAG: F2 [label="{@(2)|2.{{[0-9]*}}e+01}" color="#FC9862"]; +#VERTEX-DAG: F9 [label="{@(9)|9.{{[0-9]*}}e+01}" color="#7E0000"]; +#VERTEX-DAG: F4 [label="{@(4)|4.{{[0-9]*}}e+01}" color="#E9553D"]; +#VERTEX-DAG: F6 [label="{@(6)|6.{{[0-9]*}}e+01}" color="#C5130A"]; +#VERTEX-DAG: F1 [label="{@(1)|1.{{[0-9]*}}e+01}" color="#FDC58E"]; +#VERTEX-DAG: F8 [label="{@(8)|8.{{[0-9]*}}e+01}" color="#9A0000"]; +#VERTEX-DAG: F3 [label="{@(3)|3.{{[0-9]*}}e+01}" color="#F5744E"]; +#VERTEX-DAG: F5 [label="{@(5)|5.{{[0-9]*}}e+01}" color="#D83321"]; #VERTEX-NEXT: } Index: tools/llvm-xray/CMakeLists.txt =================================================================== --- tools/llvm-xray/CMakeLists.txt +++ tools/llvm-xray/CMakeLists.txt @@ -9,6 +9,7 @@ set(LLVM_XRAY_TOOLS func-id-helper.cc xray-account.cc + xray-color-helper.cc xray-converter.cc xray-extract.cc xray-extract.cc Index: tools/llvm-xray/xray-color-helper.h =================================================================== --- /dev/null +++ tools/llvm-xray/xray-color-helper.h @@ -0,0 +1,65 @@ +//===-- xray-graph.h - XRay Function Call Graph Renderer --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A class to get a color from a specified gradient. +// +//===----------------------------------------------------------------------===// + +#ifndef XRAY_COLOR_HELPER_H +#define XRAY_COLOR_HELPER_H + +#include "llvm/ADT/ArrayRef.h" + +namespace llvm{ +namespace xray{ + +class ColorHelper{ + private: + ArrayRef RedPoly; + ArrayRef GreenPoly; + ArrayRef BluePoly; + double MinIn; + double MaxIn; + + public: + enum class SequentialScheme{ + Blues, + Greens, + Greys, + Oranges, + Purples, + Reds, + BuGn, + BuPu, + GnBu, + OrRd, + PuBu, + PuBuGn, + PuRd, + RdPu, + YlGn, + YlGnBu, + YlOrBr, + YlOrRd + }; + + ColorHelper(SequentialScheme S); + + enum class DivergingScheme{ +BrBG, PiYG,PRGn, PuOr, RdBu, RdGy, RdYlBu, RdYlGn, +Spectral + }; + + ColorHelper(DivergingScheme S); + std::string getColor(double Point); +}; + +} +} +#endif Index: tools/llvm-xray/xray-color-helper.cc =================================================================== --- /dev/null +++ tools/llvm-xray/xray-color-helper.cc @@ -0,0 +1,488 @@ +//===-- xray-graph.cc - XRay Function Call Graph Renderer -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A class to get a color from a specified gradient. +// +//===----------------------------------------------------------------------===// +#include + +#include "xray-color-helper.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace xray; + +// Static Polynomials for the ColorHelper. +// +// In order to calculate these polynomials, +// 1. Convert the color scheme samples from sRGB to LAB color space. +// 2. Interpolate between the descrete colors in LAB space using a cubic +// spline interpolation. +// 3. Sample this interpolation at 100 points and convert to sRGB. +// 4. Calculate a polynomial fit for these 100 points for each of R G and B. +// We used a polynomial of varying based on the lowest degree polynomial +// having an error less than 1 part in 200. +// 5. Extract these polynomial coefficients from matlab as a set of constants. +// +// Sequential Color Gradient Polynomials. +// Polynomials based on the Blues color scheme from http://colorbrewer2.org/ +const static double BluesRedPoly[] = {-162.9192458,661.1363283,-1073.973166,883.6280368,-380.2475179, + 78.82940273,-6.801561636,-0.5835807573,0.9638753883}; +const static double BluesGreenPoly[] = {12.51361058,-44.07245353,59.38257571,-36.98884162,9.739164654,-0.8614140648, + -0.506944739,0.9859862907}; +const static double BluesBluePoly[] = {78.05122204,-327.7360452,562.5737804,-509.6864294, + 261.0703167,-74.65580898,10.6377515,-0.8401556996,1.005358902}; + +// Polynomials based on the Greens color scheme from http://colorbrewer2.org/ +const static double GreensRedPoly[] = {128509.879,-797823.2846,2.181834797e6,-3.461790283e6,3.534081369e6, + -2.434410039e6,1.154529311e6,-377805.7923,84179.93116,-12388.36474,1140.686431, + -58.23333701,-0.599401113,-0.3391213896,0.9686205448}; +const static double GreensGreenPoly[] = {-7.461951182,21.39595578,-22.84864083,11.23029325,-3.096687569,0.0646894028, + 0.9845938142}; +const static double GreensBluePoly[] = {-107.7554773,433.5238732,-698.2664276,574.4323065,-256.9205948, + 63.64251157,-9.433399058,-0.07598437676,0.9571862056}; + +// Polynomials based on the Greys color scheme from http://colorbrewer2.org/ +const static double GreysRedPoly[] = {-143.5297649,616.5085865,-1070.840946,962.8673283,-476.4855833,127.9805002, + -18.05029511,0.5613221758,0.9901358241}; +const static double GreysGreenPoly[] = {-143.52956,616.5077415,-1070.839522,962.8660699,-476.4849604,127.9803288, + -18.05027,0.5613209065,0.9901351029}; +const static double GreysBluePoly[] = {-143.5294769,616.5074019,-1070.838957,962.8655805,-476.4847253,127.9802671, + -18.05026156,0.5613206095,0.9901347147}; + +// Polynomials based on the Oranges color scheme from http://colorbrewer2.org/ +const static double OrangesRedPoly[] = {-334.8939504,1523.76056,-2877.815926,2928.537768,-1739.551397,607.1101648, + -118.9429881,11.80374269,-0.5137251743,1.005104319}; +const static double OrangesGreenPoly[] = {-42.83615389,143.6574611,-190.3001089,126.6399211,-43.1204304,5.886082421, + -0.7453255295,0.9636056027}; +const static double OrangesBluePoly[] = {-1710.17825,8893.802623,-19585.32854,23759.7782, + -17303.83263,7728.682269,-2073.560697,316.1050081,-26.47997137,0.1130416623, + 0.9153319099}; + +// Polynomials based on the Purples color scheme from http://colorbrewer2.org/ +const static double PurplesRedPoly[] = {-1.696564207,2.884062273,-0.2668357693,-1.489785313, + -0.1753312058,0.9839885824}; +const static double PurplesGreenPoly[] = {2012.965183,-9732.786019,19786.37572,-21967.31599, + 14491.92446,-5806.24908,1394.521531,-193.2258101,13.62438311,-0.8184148389, + 0.9869814287}; +const static double PurplesBluePoly[] = {190.8592861,-989.1880383,2113.220988,-2408.075381,1579.79904, + -599.5450876,125.4220815,-13.32705929,0.334271261,0.986341708}; + +// Polynomials based on the Reds color scheme from http://colorbrewer2.org/ +const static double RedsRedPoly[] = {1098.113616,-4997.251688,9488.138801,-9772.899613,5959.992777,-2209.219326, + 489.0341315,-59.61204391,3.179287412,-0.06669132569,1.000264016}; +const static double RedsGreenPoly[] = {179.5116774,-740.4193895,1219.571844,-1023.549681,462.3195296,-107.1715527, + 9.686352106,-0.9214068996,0.9683767274}; +const static double RedsBluePoly[] = {18.04407896,-68.20215528,102.9001432,-81.5837095,38.48503892,-10.45114102, + -0.07604611136,0.9370323879}; + +// Polynomials based on the OrRed color scheme from http://colorbrewer2.org/ +const static double BuGnRedPoly[] = {-2164.121047,10419.83248,-21150.30331, + 23256.8391,-14583.15966,4763.232503,-373.8566794,-221.1728408,56.11368279, + -3.859531726,-0.5223079228,0.9666711244}; +const static double BuGnGreenPoly[] = {575.2892884,-2681.538786,5175.083266,-5337.088998,3164.275758,-1078.38952, + 199.2966703,-18.08674004,0.4437484859,0.9810499143}; +const static double BuGnBluePoly[] = {41.26409578,-208.352963,399.5400205,-377.152878,187.8052313,-47.71547797, + 3.89067026,-0.1757733931,0.9964244108}; + +// Polynomials based on the BuPu color scheme from http://colorbrewer2.org/ +const static double BuPuRedPoly[] = {565.1449932,-2592.662888,4929.107756,-5014.635769,2939.25807,-999.5456659, + 193.2527746,-20.8497299,0.2708141304,0.9618238442}; +const static double BuPuGreenPoly[] = {847746.7759,-6.117330635e6,1.980683427e7,-3.801842895e7,4.815808516e7, + -4.241669623e7,2.667200228e7,-1.210496666e7,3.962733596e6,-924923.9906,150108.4084, + -16213.24967,1091.247763,-43.49969562,0.4921382396,0.9858848647}; +const static double BuPuBluePoly[] = {49.38780299,-172.295529,234.7533785,-158.3305372,55.00594638,-9.538295383, + 0.3295111754,0.9872924674}; + +// Polynomials based on the GnBu color scheme from http://colorbrewer2.org/ +const static double GnBuRedPoly[] = {32122.60422,-208773.9722,595945.0471, + -983116.3372,1.03802487e6,-734274.9475,354313.1124,-116680.0393,25866.28121, + -3735.817486,321.1547783,-12.18046992,-0.7143529713,0.9669925893}; +const static double GnBuGreenPoly[] = {-8.471893402,-14.3835949,107.8888603,-167.8783294,117.9995112,-42.403984, + 7.241547581,-0.7406211535,0.9926692269}; +const static double GnBuBluePoly[] = {-5011.063942,28498.03802,-69014.48035,92768.62373,-75707.3449,38652.14984, + -12342.84564,2418.81187,-278.2257073,17.00442399,-1.102980359,0.9439447156}; + +// Polynomials based on the OrRed color scheme from http://colorbrewer2.org/ +const static double OrRdRedPoly[] = {-9.741081771,26.59107248,-23.08764657,3.674199917,3.177273882,-1.208968693, + 0.09313645804,0.996555062}; +const static double OrRdGreenPoly[] = {2117.201282,-11230.55463,25067.4414,-30620.1269, + 22288.62892,-9866.377435,2600.647555,-384.3063815,27.68833123,-1.222129796, + 0.9753227379}; +const static double OrRdBluePoly[] = {42863.44555,-331773.5807,1.122972762e6,-2.190041522e6, + 2.726232049e6,-2.265546873e6,1.276524286e6,-485437.6249,121842.3618,-19383.46884, + 1843.423347,-97.52978299,1.350944135,0.9160833744}; + +// Polynomials based on the PuBu color scheme from http://colorbrewer2.org/ +const static double PuBuRedPoly[] = {-397.2314636, 2579.027278, -6876.412443, 10369.26972, -10415.08411, +7749.526816, -4381.051265, 1768.220022, -456.6488373, 64.95443074, +-5.170425306, -0.3872077729, 0.9989333378}; +const static double PuBuGreenPoly[] = {316.2837758, -1386.633741, 2496.773059, -2390.527123, 1323.209576, \ +-435.7961010, 86.11515238, -10.20656272, 0.03642902561, 0.9654562574}; +const static double PuBuBluePoly[] = {29.76240711, -85.94054297, 82.86745772, -19.60045636, -17.19015772, \ +12.66262712, -3.154522976, -0.03853118536, 0.9822950378}; + +// Polynomials based on the PuBuGn color scheme from http://colorbrewer2.org/ +const static double PuBuGnRedPoly[] = {2.092770724e8,-1.338302115e9,3.300134529e9,-3.357656294e9,-2.210526994e8, + 2.925967695e9,-4.120649617e8,-2.612491973e9,5.776442214e8,2.418823238e9, + -9.021859524e8,-2.127317508e9,1.72129189e9,1.079792855e9,-2.665242736e9, + 2.211843331e9,-1.107249356e9,3.738089198e8,-8.795629308e7,1.444528513e7, + -1.623785122e6,119930.5996,-5425.567499,132.1422988,-1.869649136,1.003397947}; +const static double PuBuGnGreenPoly[] = {-133.6970724,709.8725846,-1540.388566,1773.645168,-1178.548252,461.8248624, + -105.1656276,13.1007346,-1.339592315,0.973770807}; +const static double PuBuGnBluePoly[] = {-28187.2393,166072.0474,-425260.2581,620686.1779,-569382.9389,341689.8288, + -135511.682,35113.62424,-5750.706781,558.6236132,-28.50250673,0.2525093956, + 0.9810974095}; + +// Polynomials based on the PuRd color scheme from http://colorbrewer2.org/ +const static double PuRdRedPoly[] = {-2202.762217,11435.69335,-25248.4439,30784.28254, + -22492.44399,9995.426253,-2631.605551,388.1227397,-29.25020442,0.4190472575, + 0.9623440461}; +const static double PuRdGreenPoly[] = {142210.2277,-894659.1155,2.480558555e6,-3.990708815e6, + 4.128435582e6,-2.87652607e6,1.374434749e6,-449663.6624,98764.9872,-13992.74716, + 1205.672796,-61.4587279,1.14907402,0.9520059636}; +const static double PuRdBluePoly[] = {-3379.723288,20105.05624,-51052.20095,72460.36139,-63269.02362,35271.2722, + -12606.97534,2811.356145,-361.9132726,21.61621714,-0.6808906907,0.9814418093}; + +// Polynomials based on the RdPu color scheme from http://colorbrewer2.org/ +const static double RdPuRedPoly[] = {117.4834462,-513.5812302,906.139353,-820.4867199,402.5265722,-105.8782576, + 13.86141359,-0.7870456274,1.007063795}; +const static double RdPuGreenPoly[] = {-5.596279513e7,4.4073891e8,-1.525131874e9,2.987670582e9,-3.459933872e9, + 1.951051377e9,6.09936545e8,-2.292082693e9,2.311280607e9,-1.414858186e9, + 5.852420154e8,-1.652812489e8,3.021181863e7,-2.850393141e6,-86063.08,62960.25987, + -8192.206251,517.9372802,-16.07700273,-0.5076354515,0.9680424486}; +const static double RdPuBluePoly[] = {-45307.28817,270852.2235,-705295.8823,1.048999574e6,-982011.9283,601276.0493, + -242511.3671,63412.64183,-10369.51324,1010.704944,-56.70435084,0.9523501774, + 0.947747698}; + +// Polynomials based on the YlGn color scheme from http://colorbrewer2.org/ +const static double YlGnRedPoly[] = {-153078.3428,1.316295606e6,-4.957612048e6,1.087139478e7, + -1.551710885e7,1.523865765e7,-1.059953714e7,5.291105253e6,-1.898459493e6, + 485301.7326,-86614.36088,10415.09059,-790.7659441,30.34434264,-0.4563433465, + 1.001513624}; +const static double YlGnGreenPoly[] = {456.6173455,-2077.672779,3904.419251,-3917.824313,2268.493273, + -766.0210486,146.1498685,-15.53011837,0.6447190637,0.9939487551}; +const static double YlGnBluePoly[] = {331.0907176,-1422.525203,2506.606949,-2334.566721,1230.819201,-357.9510683, + 45.46460358,2.231195424,-1.903112721,0.8976786982}; + +// Polynomials based on the YlGnBu color scheme from http://colorbrewer2.org/ +const static double YlGnBuRedPoly[] = {-700.2088464,1373.925269,3246.038198,-14121.86699,21000.52579,-16939.73725, + 8084.534973,-2260.39398,342.4561731,-26.57841229,0.3370952789,0.9940301899}; +const static double YlGnBuGreenPoly[] = {592.8478812,-2579.282889,4586.50152,-4269.260281,2210.212644,-621.5322226, + 84.78432376,-5.030640902,-0.1192375895,0.9997904251}; +const static double YlGnBuBluePoly[] = {891.171196,-3972.475184,7308.058168,-7162.505665,4021.255532,-1284.591053, + 208.5762183,-8.259653287,-1.725683675,0.8451676342}; + +// Polynomials based on the YlOrBr color scheme from http://colorbrewer2.org/ +const static double YlOrBrRedPoly[] = {82.17794157,-328.8039801,535.3925617,-449.1168762,201.9412562,-47.0938933, + 5.121928704,-0.2159704436,1.002044464}; +const static double YlOrBrGreenPoly[] = {-0.1279957404,-3.303062964,8.856052316,-6.229222692,0.1706702785,-0.2251488049, + 1.003713704}; +const static double YlOrBrBluePoly[] = {-7097.65965,38202.9136,-87458.95413,110683.6665,-84199.16695, + 39197.02668,-10907.37228,1724.577297,-153.6107682,9.392195243,-1.690001786, + 0.897572307}; + +// Polynomials based on the YlOrRd color scheme from http://colorbrewer2.org/ +const static double YlOrRdRedPoly[] = {347.4416582,-1671.400143,3330.173175,-3551.794875, + 2190.15113,-789.8171836,160.9250929,-16.90546624,0.7331100217,0.9926020022}; +const static double YlOrRdGreenPoly[] = {42050.25699,-254007.3256,669529.9051,-1.009925101e6,960811.4641,-599256.311, + 246929.7118,-66241.02715,11170.03542,-1122.538702,62.08145931,-2.154000337, + 1.00678571}; +const static double YlOrRdBluePoly[] = {-1526.934295,8539.978183,-20130.51964,25980.76253,-19958.39911, + 9290.827185,-2556.416755,389.372372,-28.73642255,-0.5748168267,0.792483576}; + +ColorHelper::ColorHelper(ColorHelper::SequentialScheme S){ + MinIn = 0.0; + MaxIn = 1.0; + switch (S){ + case SequentialScheme::Blues: + RedPoly = BluesRedPoly; + GreenPoly = BluesGreenPoly; + BluePoly = BluesBluePoly; + break; + case SequentialScheme::Greens: + RedPoly = GreensRedPoly; + GreenPoly = GreensGreenPoly; + BluePoly = GreensBluePoly; + break; + case SequentialScheme::Greys : + RedPoly = GreysRedPoly; + GreenPoly = GreysGreenPoly; + BluePoly = GreysBluePoly; + break; + case SequentialScheme::Oranges : + RedPoly = OrangesRedPoly; + GreenPoly = OrangesGreenPoly; + BluePoly = OrangesBluePoly; + break; + case SequentialScheme::Purples : + RedPoly = PurplesRedPoly; + GreenPoly = PurplesGreenPoly; + BluePoly = PurplesBluePoly; + break; + case SequentialScheme::Reds : + RedPoly = RedsRedPoly; + GreenPoly = RedsGreenPoly; + BluePoly = RedsBluePoly; + break; + case SequentialScheme::BuGn : + RedPoly = BuGnRedPoly; + GreenPoly = BuGnGreenPoly; + BluePoly = BuGnBluePoly; + break; + case SequentialScheme::BuPu : + RedPoly = BuPuRedPoly; + GreenPoly = BuPuGreenPoly; + BluePoly = BuPuBluePoly; + break; + case SequentialScheme::GnBu : + RedPoly = GnBuRedPoly; + GreenPoly = GnBuGreenPoly; + BluePoly = GnBuBluePoly; + break; + case SequentialScheme::OrRd: + RedPoly = OrRdRedPoly; + GreenPoly = OrRdGreenPoly; + BluePoly = OrRdBluePoly; + break; + case SequentialScheme::PuBu : + RedPoly = PuBuRedPoly; + GreenPoly = PuBuGreenPoly; + BluePoly = PuBuBluePoly; + break; + case SequentialScheme::PuBuGn : + RedPoly = PuBuGnRedPoly; + GreenPoly = PuBuGnGreenPoly; + BluePoly = PuBuGnBluePoly; + break; + case SequentialScheme::PuRd : + RedPoly = PuRdRedPoly; + GreenPoly = PuRdGreenPoly; + BluePoly = PuRdBluePoly; + break; + case SequentialScheme::RdPu : + RedPoly = RdPuRedPoly; + GreenPoly = RdPuGreenPoly; + BluePoly = RdPuBluePoly; + break; + case SequentialScheme::YlGn : + RedPoly = YlGnRedPoly; + GreenPoly = YlGnGreenPoly; + BluePoly = YlGnBluePoly; + break; + case SequentialScheme::YlGnBu : + RedPoly = YlGnBuRedPoly; + GreenPoly = YlGnBuGreenPoly; + BluePoly = YlGnBuBluePoly; + break; + case SequentialScheme::YlOrBr : + RedPoly = YlOrBrRedPoly; + GreenPoly = YlOrBrGreenPoly; + BluePoly = YlOrBrBluePoly; + break; + case SequentialScheme::YlOrRd : + RedPoly = YlOrRdRedPoly; + GreenPoly = YlOrRdGreenPoly; + BluePoly = YlOrRdBluePoly; + break; + } +} + +//Diverging Polynomials +// Polynomials based on the BrBG color scheme from http://colorbrewer2.org/ +const static double BrBGRedPoly[]{0.5294837763,-3.91737974,-2.002268846,10.1174594,2.010320887, + -9.757575762,-0.1256734439,5.045304415,-0.1253220524,-2.289568173,-0.4521919584, + 0.9583654395}; +const static double BrBGGreenPoly[]{2.373263075,-0.2616693205,-7.195755845,0.9219509198,7.596904178, + -1.132609927,-2.666893375,0.4951814708,-0.851476127,0.00100428138,0.9561152078}; +const static double BrBGBluePoly[]{-0.5740589404,-51.80933673,5.933606842,190.8711475,-17.60515002,-280.2254106, + 23.70627555,208.0906477,-15.53074134,-82.67647274,4.232398336,18.51393498, + -0.4210568904,-3.624562285,0.343325181,0.9556677359}; + +// Polynomials based on the PiYG color scheme from http://colorbrewer2.org/ +const static double PiYGRedPoly[]{2.686315367,0.1818066989,-6.820061012,-0.6240347033,5.764823487, + 1.044017662,-1.500696055,-0.5968454935,-0.743017334,-0.2061763511,0.9741208999}; +const static double PiYGGreenPoly[]{25.82837592,-478.0082591,265.405487,1958.953608,-1322.827865,-3278.514666, + 2295.320802,2888.256833,-1994.993957,-1440.005462,937.8839818,404.6402812, + -230.1148382,-58.76139211,23.44055027,3.37044763,0.535250268,0.05330372069, + -1.240930319,0.2010813874,0.9678130494}; +const static double PiYGBluePoly[]{6.566648214,-4.259643591,-19.97981922,13.4961515,23.17940053,-16.71986064, + -13.50696717,9.90021622,5.309834643,-2.299206712,-2.319199867,-0.233534209, + 0.964818028}; + +// Polynomials based on the PRGn color scheme from http://colorbrewer2.org/ +const static double PRGnRedPoly[]{-5.037268137,7.310676883,18.89034365,-21.3298236, + -28.20969519,23.80097291,21.21189418,-13.26329632,-7.779385768,4.799471123, + 0.9626697387,-2.146239347,-0.1632212632,0.9627271485}; +const static double PRGnGreenPoly[]{27.70376302,-39.1403529,-101.9551342,141.663995,152.6578233,-204.820855, + -120.9124305,151.7675811,54.38831045,-61.20849002,-13.22680327,13.30089839, + 1.231517631,-2.397363546,0.2459120541,0.9661768459}; +const static double PRGnBluePoly[]{0.2890233005,-46.53351847,-3.390212366,170.4163679,9.940905807,-248.563189, + -12.74136855,183.5702915,7.705418595,-72.68456748,-1.611488339,15.84437642, + -0.08662683146,-2.821513911,-0.2000382851,0.9640579906}; + +// Polynomials based on the PuOr color scheme from http://colorbrewer2.org/ +const static double PuOrRedPoly[]{-3.681026454,7.825731699,11.18480902,-23.10450029,-12.02383864,25.40973649, + 4.896892791,-12.64537306,-0.1389082968,2.891324118,-0.0278193421,-0.995118471, + -0.3720954744,0.9628512429}; +const static double PuOrGreenPoly[]{24.01042545,-28.43205999,-134.1576955,105.9071849, + 294.2538664,-161.8152166,-333.0003126,131.2457398,212.5680161,-59.69920063, + -78.00057893,14.09735835,16.48496014,-1.395557329,-3.010405741,-0.0247322439, + 0.9664721897}; +const static double PuOrBluePoly[]{38.74145857,-70.25593327,-150.8970078,264.4538625,233.2417893, + -395.9786502,-181.1930748,299.0183416,74.78498955,-120.5154649,-16.81392037, + 26.92436846,1.793936342,-4.454840269,0.4744096931,0.9634054758}; + +// Polynomials based on the RdBu color scheme from http://colorbrewer2.org/ +const static double RdBuRedPoly[]{6.936194186,1.308207573,-17.85152386,-3.505585415,14.92660355,2.424503364, + -4.399570266,0.5513789831,1.013046025,-0.5583414845,-1.369433672,-0.412403019, + 0.9637843928}; +const static double RdBuGreenPoly[]{582.8393444,-488.9961581,-2707.709964,2151.793689,5414.088282, + -3938.663025,-6173.86839,3888.488885,4493.193764,-2242.273173,-2200.279444, + 758.7630922,730.7208378,-139.6230898,-158.0436507,9.971104545,21.06121406, + 0.5612577187,-2.870266159,0.06627786897,0.9681621401}; +const static double RdBuBluePoly[]{-11.53462595,9.69685208,42.06073501,-30.67405539,-60.12471234,38.24650971, + 42.08578575,-24.89881773,-14.91463228,9.703917704,2.216675589,-2.779351146, + 0.3385093241,0.9628023114}; + +// Polynomials based on the RdGy color scheme from http://colorbrewer2.org/ +const static double RdGyRedPoly[]{-35.77587586,7.874688034,130.7208297, + -27.63317133,-189.8258592,37.51705049,138.8359798,-24.2554428,-53.55141233, + 7.504333242,10.57755037,-0.9022304474,-1.727339517,-0.2545271441,0.9931484001}; +const static double RdGyGreenPoly[]{940.7677018,-420.7050933,-4603.913055,1812.820476,9740.153737,-3230.273468, + -11738.58697,3084.710995,8935.33313,-1713.150687,-4487.738645,561.6920218, + 1499.120736,-103.9671121,-325.1759042,8.579319324,43.66350008,0.3122312879, + -4.565733055,0.02734696098,0.9990447212}; +const static double RdGyBluePoly[]{150.9666995,1.888055114,-646.4507888,-12.40890595,1150.057089,30.82431888, + -1101.085242,-38.91140127,614.7676222,27.3123262,-203.4289258,-10.49240337, + 39.69025184,1.577865733,-5.394577624,0.1998944399,0.9955666392}; + +// Polynomials based on the RdYlBu color scheme from http://colorbrewer2.org/ +const static double RdYlBuRedPoly[]{5.75293564,-3.470298281,-19.4898014,10.52563062,25.83595957,-12.41156083, + -16.88926037,7.37045594,5.8493945,-2.023140922,-1.632715936,-0.2222877025, + 0.9958204171}; +const static double RdYlBuGreenPoly[]{-26.23751254,-2.132653763,99.04038378,6.078051972,-149.3173043, + -6.993327891,114.4727289,4.548900204,-47.14603532,-2.06476332,10.60885391, + 0.5000541272,-2.315902649,0.1693628426,0.9964815152}; +const static double RdYlBuBluePoly[]{-190.0990285,-10.36353267,814.4602394,46.22896242,-1442.882524,-87.21048396, + 1362.064988,91.26331869,-734.0940148,-58.43685625,223.422648,23.59237473, + -34.69009059,-6.080855872,1.425385656,1.224450206,0.7522655595}; + +// Polynomials based on the RdYlGn color scheme from http://colorbrewer2.org/ +const static double RdYlGnRedPoly[]{200.1308503,104.7864437,-843.3602568,-451.1701694,1451.412696,791.4594203, + -1315.236836,-730.5758596,676.6792519,384.0517159,-199.7640908,-116.5912773, + 33.30645382,19.79505982,-3.219914894,-2.429571625,-0.271093805,0.9948888983}; +const static double RdYlGnGreenPoly[]{-0.6581236191,12.78677277,0.9598185188,-39.87472293,-0.04836970727,48.08354771, + 0.08244671772,-28.40787812,-0.9735039293,8.949936926,0.7215694489,-2.319990233, + 0.1201688537,0.9934969619}; +const static double RdYlGnBluePoly[]{-10.63946244,216.0611234,41.17394797,-926.5998391, + -61.07837796,1655.034126,40.12657909,-1598.09658,-6.252193922,906.8493934, + -5.846296915,-307.9753277,2.470443253,61.02816517,0.0858668193,-6.8526992, + -0.007549403018,0.7427008373}; + +// Polynomials based on the Spectral color scheme from http://colorbrewer2.org/ +const static double SpectralRedPoly[]{-5.542248719,-2.308143637,16.06408619,6.145137891,-17.77435106, + -5.566391809,10.21182246,2.564522594,-2.957557806,-1.336926237,-0.1287516798, + 0.9984221365}; +const static double SpectralGreenPoly[]{6.373851354,-5.048892087,-22.28985269,13.87132947,29.8636573, + -12.55479535,-19.47972158,3.7477125,6.785884212,-0.06703107824,-2.087938334, + 0.1949553685,0.9957989692}; +const static double SpectralBluePoly[]{-735.9799141,44.50209142,3631.528714,-177.4034756, + -7619.078878,275.5098917,8845.528239,-196.9908882,-6187.050799,43.43148149, + 2655.16715,26.04923949,-681.1680745,-19.40374992,98.09305618,4.51219457, + -7.343834502,-0.01703847884,0.7461285097}; + +ColorHelper::ColorHelper(ColorHelper::DivergingScheme S){ + MinIn = -1.0; + MaxIn = 1.0; + switch (S){ + case DivergingScheme::BrBG: + RedPoly = BrBGRedPoly; + GreenPoly = BrBGGreenPoly; + BluePoly = BrBGBluePoly; + break; + case DivergingScheme::PiYG: + RedPoly = PiYGRedPoly; + GreenPoly = PiYGGreenPoly; + BluePoly = PiYGBluePoly; + break; + case DivergingScheme::PRGn: + RedPoly = PRGnRedPoly; + GreenPoly = PRGnGreenPoly; + BluePoly = PRGnBluePoly; + break; + case DivergingScheme::PuOr: + RedPoly = PuOrRedPoly; + GreenPoly = PuOrGreenPoly; + BluePoly = PuOrBluePoly; + break; + case DivergingScheme::RdBu: + RedPoly = RdBuRedPoly; + GreenPoly = RdBuGreenPoly; + BluePoly = RdBuBluePoly; + break; + case DivergingScheme::RdGy: + RedPoly = RdGyRedPoly; + GreenPoly = RdGyGreenPoly; + BluePoly = RdGyBluePoly; + break; + case DivergingScheme::RdYlBu: + RedPoly = RdYlBuRedPoly; + GreenPoly = RdYlBuGreenPoly; + BluePoly = RdYlBuBluePoly; + break; + case DivergingScheme::RdYlGn: + RedPoly = RdYlGnRedPoly; + GreenPoly = RdYlGnGreenPoly; + BluePoly = RdYlGnBluePoly; + break; + case DivergingScheme::Spectral: + RedPoly = SpectralRedPoly; + GreenPoly = SpectralGreenPoly; + BluePoly = SpectralBluePoly; + break; + } +} + +// Evaluates a polynomial given the coefficints provided in an ArrayRef +// evaluating: +// +// p(x) = a[n-0]*x^0 + a[n-1]*x^1 + ... a[n-n]*x^n +// +// at x_0 using Horner's Method for both performance and stability reasons. +static double polyEval(ArrayRef a, double x_0) { + double B = 0; + for (const auto &c : a) { + B = c + B * x_0; + } + return B; +} + +// Takes a double precision number, clips it between 0 and 1 and then converts +// that to an integer between 0x00 and 0xFF with proxpper rounding. +static uint8_t uintIntervalTo8bitChar(double B) { + double n = std::max(std::min(B, 1.0), 0.0); + return static_cast(255 * n + 0.5); +} + +// Gets a color in a gradient given a number in the interval [0,1], it does this +// by evaluating a polynomial which maps [0, 1] -> [0, 1] for each of the R G +// and B values in the color. It then converts this [0,1] colors to a 24 bit +// color. +std::string ColorHelper::getColor(double point) { + point = std::max(std::min(point, MaxIn), MinIn); + + uint8_t r = uintIntervalTo8bitChar(polyEval(RedPoly, point)); + uint8_t g = uintIntervalTo8bitChar(polyEval(GreenPoly, point)); + uint8_t b = uintIntervalTo8bitChar(polyEval(BluePoly, point)); + + return llvm::formatv("#{0:X-2}{1:X-2}{2:X-2}", r, g, b); +} + Index: tools/llvm-xray/xray-graph.h =================================================================== --- tools/llvm-xray/xray-graph.h +++ tools/llvm-xray/xray-graph.h @@ -19,6 +19,7 @@ #include #include "func-id-helper.h" +#include "xray-color-helper.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Errc.h" @@ -97,7 +98,7 @@ PerThreadFunctionStackMap PerThreadFunctionStack; /// Usefull object for getting human readable Symbol Names. - FuncIdConversionHelper &FuncIdHelper; + const FuncIdConversionHelper &FuncIdHelper; bool DeduceSiblingCalls = false; TimestampT CurrentMaxTSC = 0; @@ -117,11 +118,16 @@ /// Normalises latency statistics for each edge and vertex by CycleFrequency; void normalizeStatistics(double CycleFrequency); + /// An object to color gradients + ColorHelper CHelper; + public: /// Takes in a reference to a FuncIdHelper in order to have ready access to /// Symbol names. - explicit GraphRenderer(FuncIdConversionHelper &FuncIdHelper, bool DSC) - : FuncIdHelper(FuncIdHelper), DeduceSiblingCalls(DSC) { + explicit GraphRenderer(const FuncIdConversionHelper &FuncIdHelper, bool DSC) + : FuncIdHelper(FuncIdHelper), + DeduceSiblingCalls(DSC), + CHelper(ColorHelper::SequentialScheme::OrRd) { G[0] = {}; } Index: tools/llvm-xray/xray-graph.cc =================================================================== --- tools/llvm-xray/xray-graph.cc +++ tools/llvm-xray/xray-graph.cc @@ -370,61 +370,6 @@ return S.str(); } -// Evaluates a polynomial given the coefficints provided in an ArrayRef -// evaluating: -// -// p(x) = a[n-0]*x^0 + a[n-1]*x^1 + ... a[n-n]*x^n -// -// at x_0 using Horner's Method for both performance and stability reasons. -static double polyEval(ArrayRef a, double x_0) { - double B = 0; - for (const auto &c : a) { - B = c + B * x_0; - } - return B; -} - -// Takes a double precision number, clips it between 0 and 1 and then converts -// that to an integer between 0x00 and 0xFF with proxpper rounding. -static uint8_t uintIntervalTo8bitChar(double B) { - double n = std::max(std::min(B, 1.0), 0.0); - return static_cast(255 * n + 0.5); -} - -// Gets a color in a gradient given a number in the interval [0,1], it does this -// by evaluating a polynomial which maps [0, 1] -> [0, 1] for each of the R G -// and B values in the color. It then converts this [0,1] colors to a 24 bit -// color. -// -// In order to calculate these polynomials, -// 1. Convert the OrRed9 color scheme from http://colorbrewer2.org/ from sRGB -// to LAB color space. -// 2. Interpolate between the descrete colors in LAB space using a cubic -// spline interpolation. -// 3. Sample this interpolation at 100 points and convert to sRGB. -// 4. Calculate a polynomial fit for these 100 points for each of R G and B. -// We used a polynomial of degree 9 arbitrarily based on a fuzzy goodness -// of fit metric (using human judgement); -// 5. Extract these polynomial coefficients from matlab as a set of constants. -static std::string getColor(double point) { - assert(point >= 0.0 && point <= 1); - const static double RedPoly[] = {-38.4295, 239.239, -600.108, 790.544, - -591.26, 251.304, -58.0983, 6.62999, - -0.325899, 1.00173}; - const static double GreenPoly[] = {-603.634, 2338.15, -3606.74, 2786.16, - -1085.19, 165.15, 11.2584, -6.11338, - -0.0091078, 0.965469}; - const static double BluePoly[] = {-325.686, 947.415, -699.079, -513.75, - 1127.78, -732.617, 228.092, -33.8202, - 0.732108, 0.913916}; - - uint8_t r = uintIntervalTo8bitChar(polyEval(RedPoly, point)); - uint8_t g = uintIntervalTo8bitChar(polyEval(GreenPoly, point)); - uint8_t b = uintIntervalTo8bitChar(polyEval(BluePoly, point)); - - return llvm::formatv("#{0:X-2}{1:X-2}{2:x-2}", r, g, b); -} - // Returns the quotient between the property T of this and another TimeStat as // a double double GraphRenderer::TimeStat::compare(StatType T, const TimeStat &O) const { @@ -488,7 +433,7 @@ OS << "F" << E.first.first << " -> " << "F" << E.first.second << " [label=\"" << S.getAsString(ET) << "\""; if (EC != StatType::NONE) - OS << " color=\"" << getColor(S.compare(EC, G.GraphEdgeMax)) << "\""; + OS << " color=\"" << CHelper.getColor(S.compare(EC, G.GraphEdgeMax)) << "\""; OS << "];\n"; } @@ -505,7 +450,7 @@ else OS << "\""; if (VC != StatType::NONE) - OS << " color=\"" << getColor(VA.S.compare(VC, G.GraphVertexMax)) << "\""; + OS << " color=\"" << CHelper.getColor(VA.S.compare(VC, G.GraphVertexMax)) << "\""; OS << "];\n"; } OS << "}\n";