arm_compute v19.02

Change-Id: I853a3ecf38f206da13c1b03640c8adf73c20477c
diff --git a/src/runtime/CPUUtils.cpp b/src/runtime/CPUUtils.cpp
index ac19d08..f3355a7 100644
--- a/src/runtime/CPUUtils.cpp
+++ b/src/runtime/CPUUtils.cpp
@@ -39,7 +39,8 @@
 #include <unistd.h>
 
 #ifndef BARE_METAL
-#include <regex>
+/* C++ std::regex takes up a lot of space in the standalone builds */
+#include <regex.h>
 #include <thread>
 #endif /* BARE_METAL */
 
@@ -94,6 +95,7 @@
             return false;
     }
 }
+
 /* Convert an MIDR register value to a CPUModel enum value. */
 CPUModel midr_to_model(const unsigned int midr)
 {
@@ -144,6 +146,19 @@
                 break;
         }
     }
+    else if(implementer == 0x48) // HiSilicon CPUs
+    {
+        // Only CPUs we have code paths for are detected.  All other CPUs can be safely classed as "GENERIC"
+        switch(cpunum)
+        {
+            case 0xd40: // A76 (Kirin 980)
+                model = CPUModel::GENERIC_FP16_DOT;
+                break;
+            default:
+                model = CPUModel::GENERIC;
+                break;
+        }
+    }
 
     return model;
 }
@@ -172,12 +187,27 @@
 
 void populate_models_cpuinfo(std::vector<CPUModel> &cpusv)
 {
+    regex_t proc_regex;
+    regex_t imp_regex;
+    regex_t var_regex;
+    regex_t part_regex;
+    regex_t rev_regex;
+
+    memset(&proc_regex, 0, sizeof(regex_t));
+    memset(&imp_regex, 0, sizeof(regex_t));
+    memset(&var_regex, 0, sizeof(regex_t));
+    memset(&part_regex, 0, sizeof(regex_t));
+    memset(&rev_regex, 0, sizeof(regex_t));
+
+    int ret_status = 0;
     // If "long-form" cpuinfo is present, parse that to populate models.
-    std::regex proc_regex(R"(^processor.*(\d+)$)");
-    std::regex imp_regex(R"(^CPU implementer.*0x(..)$)");
-    std::regex var_regex(R"(^CPU variant.*0x(.)$)");
-    std::regex part_regex(R"(^CPU part.*0x(...)$)");
-    std::regex rev_regex(R"(^CPU revision.*(\d+)$)");
+    ret_status |= regcomp(&proc_regex, R"(^processor.*([[:digit:]]+)$)", REG_EXTENDED);
+    ret_status |= regcomp(&imp_regex, R"(^CPU implementer.*0x(..)$)", REG_EXTENDED);
+    ret_status |= regcomp(&var_regex, R"(^CPU variant.*0x(.)$)", REG_EXTENDED);
+    ret_status |= regcomp(&part_regex, R"(^CPU part.*0x(...)$)", REG_EXTENDED);
+    ret_status |= regcomp(&rev_regex, R"(^CPU revision.*([[:digit:]]+)$)", REG_EXTENDED);
+    ARM_COMPUTE_UNUSED(ret_status);
+    ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed.");
 
     std::ifstream file;
     file.open("/proc/cpuinfo", std::ios::in);
@@ -190,11 +220,11 @@
 
         while(bool(getline(file, line)))
         {
-            std::smatch match;
-
-            if(std::regex_match(line, match, proc_regex))
+            regmatch_t match[2];
+            ret_status = regexec(&proc_regex, line.c_str(), 2, match, 0);
+            if(ret_status == 0)
             {
-                std::string id     = match[1];
+                std::string id     = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
                 int         newcpu = support::cpp11::stoi(id, nullptr);
 
                 if(curcpu >= 0 && midr == 0)
@@ -214,32 +244,44 @@
                 continue;
             }
 
-            if(std::regex_match(line, match, imp_regex))
+            ret_status = regexec(&imp_regex, line.c_str(), 2, match, 0);
+            if(ret_status == 0)
             {
-                int impv = support::cpp11::stoi(match[1], nullptr, support::cpp11::NumericBase::BASE_16);
+                std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
+                int         impv   = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16);
                 midr |= (impv << 24);
+
                 continue;
             }
 
-            if(std::regex_match(line, match, var_regex))
+            ret_status = regexec(&var_regex, line.c_str(), 2, match, 0);
+            if(ret_status == 0)
             {
-                int varv = support::cpp11::stoi(match[1], nullptr, support::cpp11::NumericBase::BASE_16);
+                std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
+                int         varv   = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16);
                 midr |= (varv << 20);
+
                 continue;
             }
 
-            if(std::regex_match(line, match, part_regex))
+            ret_status = regexec(&part_regex, line.c_str(), 2, match, 0);
+            if(ret_status == 0)
             {
-                int partv = support::cpp11::stoi(match[1], nullptr, support::cpp11::NumericBase::BASE_16);
+                std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
+                int         partv  = support::cpp11::stoi(subexp, nullptr, support::cpp11::NumericBase::BASE_16);
                 midr |= (partv << 4);
+
                 continue;
             }
 
-            if(std::regex_match(line, match, rev_regex))
+            ret_status = regexec(&rev_regex, line.c_str(), 2, match, 0);
+            if(ret_status == 0)
             {
-                int regv = support::cpp11::stoi(match[1], nullptr);
+                std::string subexp = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
+                int         regv   = support::cpp11::stoi(subexp, nullptr);
                 midr |= (regv);
                 midr |= (0xf << 16);
+
                 continue;
             }
         }
@@ -249,6 +291,13 @@
             cpusv[curcpu] = midr_to_model(midr);
         }
     }
+
+    // Free allocated memory
+    regfree(&proc_regex);
+    regfree(&imp_regex);
+    regfree(&var_regex);
+    regfree(&part_regex);
+    regfree(&rev_regex);
 }
 
 int get_max_cpus()
@@ -364,8 +413,11 @@
     std::map<std::string, unsigned int> cpu_part_occurrence_map;
 
     // CPU part regex
-    std::regex  cpu_part_rgx(R"(.*CPU part.+?(?=:).+?(?=\w+)(\w+).*)");
-    std::smatch cpu_part_match;
+    regex_t cpu_part_rgx;
+    memset(&cpu_part_rgx, 0, sizeof(regex_t));
+    int ret_status = regcomp(&cpu_part_rgx, R"(.*CPU part.+/?\:[[:space:]]+([[:alnum:]]+).*)", REG_EXTENDED);
+    ARM_COMPUTE_UNUSED(ret_status);
+    ARM_COMPUTE_ERROR_ON_MSG(ret_status != 0, "Regex compilation failed.");
 
     // Read cpuinfo and get occurrence of each core
     std::ifstream cpuinfo;
@@ -375,9 +427,11 @@
         std::string line;
         while(bool(getline(cpuinfo, line)))
         {
-            if(std::regex_search(line.cbegin(), line.cend(), cpu_part_match, cpu_part_rgx))
+            regmatch_t match[2];
+            ret_status = regexec(&cpu_part_rgx, line.c_str(), 2, match, 0);
+            if(ret_status == 0)
             {
-                std::string cpu_part = cpu_part_match[1];
+                std::string cpu_part = line.substr(match[1].rm_so, (match[1].rm_eo - match[1].rm_so));
                 if(cpu_part_occurrence_map.find(cpu_part) != cpu_part_occurrence_map.end())
                 {
                     cpu_part_occurrence_map[cpu_part]++;
@@ -389,6 +443,7 @@
             }
         }
     }
+    regfree(&cpu_part_rgx);
 
     // Get min number of threads
     auto min_common_cores = std::min_element(cpu_part_occurrence_map.begin(), cpu_part_occurrence_map.end(),