diff --git a/llvm/projects/hpvm-tensor-rt/opentuner/autotuner/algo_tuner.py b/llvm/projects/hpvm-tensor-rt/opentuner/autotuner/algo_tuner.py
new file mode 100644
index 0000000000000000000000000000000000000000..784625de26bac8d08b59a69bd4ccf1a060de11fc
--- /dev/null
+++ b/llvm/projects/hpvm-tensor-rt/opentuner/autotuner/algo_tuner.py
@@ -0,0 +1,295 @@
+#!/usr/bin/env python
+#
+# Algorithmic Approximation Tuning
+# Purpose: Tunes for Perforation, Sampling, Numerical Precision (FP16)
+
+
+import adddeps  
+
+import argparse
+import opentuner
+from opentuner import ConfigurationManipulator
+from opentuner import MeasurementInterface
+from opentuner import Result
+from opentuner import EnumParameter
+from opentuner.search.objective import ThresholdAccuracyMinimizeTime
+from opentuner.measurement.inputmanager import FixedInputManager
+import shutil
+import os
+import sys
+import subprocess
+import threading
+import psutil
+
+from measure_confidence2 import dump_promise_confidence_files3
+from measure_confidence2 import getConfidence, getMinAccuracy
+from select_top_results import select_top_results
+from time import sleep
+from pareto_curve import findParetoConfigs
+
+
+
+
+class TunerData:
+  def __init__(self):
+    self.binary_path = ""
+    self.output_dir = ""
+    self.num_layers = 0
+    self.knobs_list = []
+    self.knobs_speedup = {}
+    self.accuracy_threshold = 0
+    self.test_id = 0
+    self.layer_costs = []
+    self.tuning_flags = []
+    self.autotuner_runs = 0
+    
+
+
+tunerData = TunerData()
+
+
+def readCostFile(file_path):
+
+  layer_costs = []
+  f = open(file_path)
+  for x in f:
+    cost = float(x.strip())
+    layer_costs.append(cost)
+
+  print ("len(layer_costs) = ", layer_costs)
+  f.close()
+
+  return layer_costs
+
+  
+
+def getAccuracy(file_name):
+  
+  file = open(file_name, "r")
+  acc_str = file.read()
+  file.close()
+  accuracy = float(acc_str)
+  
+  try:
+    accuracy = float(acc_str)
+  except:
+    return 20
+    
+  print (accuracy)
+  return accuracy
+    
+
+
+def createFlagsFile(file_name, cfg):
+
+  f = open(file_name, "w+")
+  cmd_config = ""
+  for flag in tunerData.tuning_flags:
+    flag_value = cfg[flag]
+    cmd_config += str(flag_value) + "\n"
+    
+  f.write(cmd_config)
+  f.close()
+
+  
+
+def readLayerKnobs(file_path):
+
+  f = open(file_path, "r")
+  knobs_list = []
+  for x in f:
+    knobs = []
+    vals = x.split(",")
+    for val in vals:
+      knobs.append(int(val))
+      
+    knobs_list.append(knobs)
+
+  print ("knobs_list = ", knobs_list)
+  
+  return knobs_list
+
+
+
+def readKnobConfig(file_path):
+
+  knobs_speedup = {}
+  f = open(file_path, "r")
+  for x in f:
+    toks = x.split("\t")
+    ID = int(toks[0].split(",")[1])
+
+    speedup = float(toks[2])
+    knobs_speedup[ID] = speedup
+  
+  print ("knobs_speedup = ", knobs_speedup)
+  
+  return knobs_speedup
+
+
+
+
+def getConfigCost(cfg):
+
+  total_cost = 0.0
+  for it in range(tunerData.num_layers):
+    flag = tunerData.tuning_flags[it]
+    flag_value = cfg[flag]
+    op_cost = tunerData.layer_costs[it]
+    speedup = tunerData.knobs_speedup[flag_value]
+
+    total_cost += (op_cost * 1.0 / speedup * 1.0)
+    it += 1
+    
+  return total_cost
+
+
+
+
+class ClangFlagsTuner(MeasurementInterface):
+
+  def __init__(self, args):
+    objective = ThresholdAccuracyMinimizeTime(tunerData.accuracy_threshold)
+    input_manager = FixedInputManager(size=tunerData.num_layers)
+    self.configs_list = []
+
+    super(ClangFlagsTuner, self).__init__(
+        args, program_name=args.binary,
+        program_version=self.file_hash(args.binary),
+        input_manager=input_manager, objective=objective)
+
+
+    
+
+  def manipulator(self):
+    """
+    Define the search space by creating a
+    ConfigurationManipulator
+    """
+    manipulator = ConfigurationManipulator()
+
+    for i in range(tunerData.num_layers):
+      tunerData.tuning_flags.append("flag" + str(i))
+
+         
+    #for flag in tunerData.tuning_flags:
+    for ind in range(tunerData.num_layers):
+        flag = tunerData.tuning_flags[ind]
+        manipulator.add_parameter(
+        EnumParameter(flag, tunerData.knobs_list[ind]))
+
+        print ("ind = ", ind, " len = ", len(tunerData.knobs_list))
+        print (tunerData.knobs_list[ind])
+        ind += 1  
+      
+    return manipulator
+
+  
+  
+  def run(self, desired_result, input, limit):
+    
+    """
+    Run  a given configuration then
+    return performance
+    """
+    global test_id
+    
+    cfg = desired_result.configuration.data
+    
+    # NOTE: creates the file with flags read by the runtime
+    createFlagsFile("promise_flags", cfg)
+    
+    run_cmd = tunerData.binary_path
+    print "\nbinary_path = ", run_cmd
+ 
+
+    total_runs = 1 # NOTE: Single run sufficient in Algorithmic Approx Tuner
+    FNULL = open(os.devnull, 'wb')
+    p = subprocess.Popen([run_cmd, str(total_runs)], stdout = FNULL)
+    p.wait()
+
+       
+    accuracy = getAccuracy("final_accuracy")
+    
+    # getConfigCost returns the cost associated with the selected configuration
+    total_comps = getConfigCost(cfg)
+   
+    
+    Result = opentuner.resultsdb.models.Result()
+    Result.time = total_comps
+    #Result.accuracy = accuracy
+    min_accuracy = getMinAccuracy("run_accuracies.txt")
+    print ("min_accuracy = ", min_accuracy)
+    Result.accuracy = min_accuracy
+    
+    if min_accuracy > tunerData.accuracy_threshold:
+      config_tuple = (total_comps, accuracy, cfg)
+      self.configs_list.append(config_tuple)
+      shutil.copy('promise_flags', tunerData.output_dir + '/' + tunerData.binary_path + '_' + str(tunerData.test_id))
+
+      f_acc = open(tunerData.output_dir + '/' + tunerData.binary_path + '_' + str(tunerData.test_id) + "_accuracy", "w")
+      f_acc.write(str(accuracy))
+      f_acc.close()
+                   
+      
+    tunerData.test_id += 1
+    
+    return Result
+
+
+  def save_final_config(self, configuration):
+
+    print "Done with Autotuning Run \n"
+    sleep(2)
+
+    print "Final configuration", configuration.data
+
+    return
+
+  
+
+
+if __name__ == '__main__':
+
+  argparser = argparse.ArgumentParser(parents=opentuner.argparsers())
+  argparser.add_argument('--binary', help='path to target binary')
+  argparser.add_argument('--num-layers', type=int, help='num of flags to tune')
+  argparser.add_argument('--accuracy', type=float, help='accuracy threshold')
+  argparser.add_argument('--result-dir', help='result directory')
+  argparser.add_argument('--cost-file', help='layer description')
+  argparser.add_argument('--knobs-config', help='knob settings and ID mapping')
+  argparser.add_argument('--layer-knobs', help='per-layer Knobs')
+  
+  
+  args = argparser.parse_args()
+
+  tunerData.binary_path = str(args.binary)
+  tunerData.num_layers = int(args.num_layers)
+  tunerData.accuracy_threshold = float(args.accuracy)
+
+
+  # NOTE: Reading the cost file (with No of ops) to better guide the Autotuner
+  cost_file_path = args.cost_file
+  tunerData.layer_costs = readCostFile(cost_file_path)
+
+  
+  tunerData.knobs_list = readLayerKnobs(args.layer_knobs)
+  tunerData.knobs_speedup = readKnobConfig(args.knobs_config)
+  
+  result_dir = args.result_dir
+  if result_dir == "":
+    print("Provide --result-dir ")
+        
+  tunerData.output_dir = result_dir + "/high_confidence/"
+  if not os.path.exists(result_dir):
+    os.mkdir(result_dir)
+    
+  if not os.path.exists(tunerData.output_dir):
+    print("Creating output directory = ", tunerData.output_dir)
+    os.mkdir(tunerData.output_dir)
+
+
+    
+  ClangFlagsTuner.main(argparser.parse_args())
+
+