diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/prefix_warning_verbosity_nowarn.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/prefix_warning_verbosity_nowarn.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/prefix_warning_verbosity_nowarn.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefixes=CHECK,RV32I +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefixes=CHECK,RV64I + +define i32 @addi(i32 %a) nounwind { + %1 = add i32 %a, 1 + ret i32 %1 +} + +define i32 @slti(i32 %a) nounwind { + %1 = icmp slt i32 %a, 2 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +define i32 @sltiu(i32 %a) nounwind { + %1 = icmp ult i32 %a, 3 + %2 = zext i1 %1 to i32 + ret i32 %2 +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/prefix_warning_verbosity_warn.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/prefix_warning_verbosity_warn.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/prefix_warning_verbosity_warn.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CHECK +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CHECK + +define i32 @addi(i32 %a) nounwind { + %1 = add i32 %a, 1 + ret i32 %1 +} + +define i32 @slti(i32 %a) nounwind { + %1 = icmp slt i32 %a, 2 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +define i32 @sltiu(i32 %a) nounwind { + %1 = icmp ult i32 %a, 3 + %2 = zext i1 %1 to i32 + ret i32 %2 +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/prefix_warning_verbosity.test b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/prefix_warning_verbosity.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/prefix_warning_verbosity.test @@ -0,0 +1,16 @@ +# REQUIRES: riscv-registered-target + +# The 2 files below are identical insofar as IR, they differ in the assert prefixes. +# The _nowarn case generates assertions for all 3 functions. The _warn case +# ends up with conflicting output for 2 of the functions, thus producing a +# warning for each. +# +# RUN: cp -f %S/Inputs/prefix_warning_verbosity_nowarn.ll %t_nowarn.ll +# RUN: cp -f %S/Inputs/prefix_warning_verbosity_warn.ll %t_warn.ll + +# RUN: %update_llc_test_checks %t_nowarn.ll 2>&1 | FileCheck %s --check-prefix=NOWARN --allow-empty +# RUN: %update_llc_test_checks %t_warn.ll 2>&1 | FileCheck %s --check-prefix=WARN + +# NOWARN-NOT: WARNING +# WARN: WARNING: Function slti has no asserts due to conflicts +# WARN: WARNING: Function sltiu has no asserts due to conflicts diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -17,6 +17,11 @@ _verbose = False +PF_DISABLED = 0 +PF_UNUSED = 1 +PF_FCT_NO_ASSERTS = 2 +PF_MAX_VERBOSITY = 3 + def parse_commandline_args(parser): parser.add_argument('--include-generated-funcs', action='store_true', help='Output checks for functions not in source') @@ -30,9 +35,19 @@ help='Activate CHECK line generation from this point forward') parser.add_argument('--disable', action='store_false', dest='enabled', help='Deactivate CHECK line generation from this point forward') + parser.add_argument('--prefix-warnings-verbosity', action='store', + default=PF_FCT_NO_ASSERTS, + type=int, + dest='prefix_warnings_verbosity', + help='0: Disabled\n' + '1: Warn only on unused prefixes.\n' + '2: Warn if a function has no assertions.\n' + '3: Warn if a function assertions are lost due to a conflicting RUN line') + args = parser.parse_args() - global _verbose + global _verbose, _prefix_warnings_verbosity _verbose = args.verbose + _prefix_warnings_verbosity = args.prefix_warnings_verbosity return args @@ -266,19 +281,27 @@ self._scrubber_args = scrubber_args self._func_dict = {} self._func_order = {} + self._per_fct_prefix_count = {} for tuple in run_list: for prefix in tuple[0]: self._func_dict.update({prefix:dict()}) self._func_order.update({prefix: []}) def finish_and_get_func_dict(self): + if _prefix_warnings_verbosity <= PF_DISABLED: + return self._func_dict + if _prefix_warnings_verbosity >= PF_FCT_NO_ASSERTS: + for fct in self._per_fct_prefix_count: + if self._per_fct_prefix_count[fct] == 0: + warn('Function %s has no asserts due to conflicts from different RUN lines' % fct) + for prefix in self._get_failed_prefixes(): warn('Prefix %s had conflicting output from different RUN lines for all functions' % (prefix,)) return self._func_dict def func_order(self): return self._func_order - + def process_run_line(self, function_re, scrubber, raw_tool_output, prefixes): for m in function_re.finditer(raw_tool_output): if not m: @@ -329,11 +352,19 @@ # so the body can't be common accross RUN lines. We use None to # indicate that. self._func_dict[prefix][func] = None + assert func in self._per_fct_prefix_count and self._per_fct_prefix_count[func] > 0 + self._per_fct_prefix_count[func] -= 1 + if _prefix_warnings_verbosity >= PF_MAX_VERBOSITY: + warn('Function %s had conflicting output from different RUN lines for prefix %s' % ( + func, prefix)) continue self._func_dict[prefix][func] = function_body( scrubbed_body, scrubbed_extra, args_and_sig, attrs) self._func_order[prefix].append(func) + if func not in self._per_fct_prefix_count: + self._per_fct_prefix_count[func] = 0 + self._per_fct_prefix_count[func] += 1 def _get_failed_prefixes(self): # This returns the list of those prefixes that failed to match any function, @@ -341,12 +372,11 @@ # all instances of the prefix. Effectively, this prefix is unused and should # be removed. for prefix in self._func_dict: - if (self._func_dict[prefix] and + if (self._func_dict[prefix] and (not [fct for fct in self._func_dict[prefix] if self._func_dict[prefix][fct] is not None])): yield prefix - ##### Generator of LLVM IR CHECK lines SCRUB_IR_COMMENT_RE = re.compile(r'\s*;.*')