diff --git a/clang/unittests/CodeGen/IRMatchers.h b/clang/unittests/CodeGen/IRMatchers.h index 9cc2a317772e5..25bd1d5aa956b 100644 --- a/clang/unittests/CodeGen/IRMatchers.h +++ b/clang/unittests/CodeGen/IRMatchers.h @@ -356,7 +356,7 @@ class MTupleMatcher : public EntityMatcher { // Helper function used to construct matchers. -std::shared_ptr MSameAs(unsigned N) { +inline std::shared_ptr MSameAs(unsigned N) { return std::shared_ptr(new SameAsMatcher(N)); } @@ -367,36 +367,35 @@ std::shared_ptr MInstruction(unsigned C, T... Args) { return std::shared_ptr(Result); } -std::shared_ptr MConstInt(uint64_t V, unsigned W = 0) { +inline std::shared_ptr MConstInt(uint64_t V, unsigned W = 0) { return std::shared_ptr(new ConstantIntMatcher(V, W)); } -std::shared_ptr> - MValType(std::shared_ptr> T) { +inline std::shared_ptr> +MValType(std::shared_ptr> T) { return std::shared_ptr>(new ValueTypeMatcher(T)); } -std::shared_ptr> MValType(const Type *T) { +inline std::shared_ptr> MValType(const Type *T) { return std::shared_ptr>(new ValueTypeMatcher(T)); } -std::shared_ptr> +inline std::shared_ptr> MType(std::function C) { return std::shared_ptr>(new CondMatcher(C)); } -std::shared_ptr> MMAny() { +inline std::shared_ptr> MMAny() { return std::shared_ptr>(new AnyMatcher); } -std::shared_ptr> +inline std::shared_ptr> MMSave(const Metadata *&V, std::shared_ptr> M) { return std::shared_ptr>( new SavingMatcher(V, M)); } -std::shared_ptr> -MMString(const char *Name) { +inline std::shared_ptr> MMString(const char *Name) { return std::shared_ptr>(new NameMetaMatcher(Name)); } @@ -413,7 +412,8 @@ std::shared_ptr> MMTuple(T... Args) { /// \returns Pointer to the found instruction or nullptr if such instruction /// was not found. /// -const Instruction *match(const BasicBlock *BB, std::shared_ptr M) { +inline const Instruction *match(const BasicBlock *BB, + std::shared_ptr M) { MatcherContext MC; for (const auto &I : *BB) { MC.push(&I); @@ -425,13 +425,12 @@ const Instruction *match(const BasicBlock *BB, std::shared_ptr M) { return nullptr; } - /// Looks for the instruction that satisfies condition of the specified /// matcher starting from the specified instruction inside the same basic block. /// /// The given instruction is not checked. /// -const Instruction *matchNext(const Instruction *I, std::shared_ptr M) { +inline const Instruction *matchNext(const Instruction *I, std::shared_ptr M) { if (!I) return nullptr; MatcherContext MC; diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 8d301fb9404e6..d41bafb0fecbd 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -167,20 +167,6 @@ def usage(parser): $ ./dotest.py --log-success -Option 2: (DEPRECATED) - -The following options can only enable logs from the host lldb process. -Only categories from the "lldb" or "gdb-remote" channels can be enabled -They also do not automatically enable logs in locally running debug servers. -Also, logs from all test case are written into each log file - -o LLDB_LOG: if defined, specifies the log file pathname for the 'lldb' subsystem - with a default option of 'event process' if LLDB_LOG_OPTION is not defined. - -o GDB_REMOTE_LOG: if defined, specifies the log file pathname for the - 'process.gdb-remote' subsystem with a default option of 'packets' if - GDB_REMOTE_LOG_OPTION is not defined. - """) sys.exit(0) @@ -416,12 +402,6 @@ def parseOptionsAndInitTestdirs(): if do_help: usage(parser) - # Capture test results-related args. - if args.curses: - # Act as if the following args were set. - args.results_formatter = "lldbsuite.test_event.formatter.curses.Curses" - args.results_file = "stdout" - if args.results_file: configuration.results_filename = args.results_file @@ -772,61 +752,6 @@ def disabledynamics(): raise Exception('disabling dynamic type support failed') -def lldbLoggings(): - import lldb - """Check and do lldb loggings if necessary.""" - - # Turn on logging for debugging purposes if ${LLDB_LOG} environment variable is - # defined. Use ${LLDB_LOG} to specify the log file. - ci = lldb.DBG.GetCommandInterpreter() - res = lldb.SBCommandReturnObject() - if ("LLDB_LOG" in os.environ): - open(os.environ["LLDB_LOG"], 'w').close() - if ("LLDB_LOG_OPTION" in os.environ): - lldb_log_option = os.environ["LLDB_LOG_OPTION"] - else: - lldb_log_option = "event process expr state api" - ci.HandleCommand( - "log enable -n -f " + - os.environ["LLDB_LOG"] + - " lldb " + - lldb_log_option, - res) - if not res.Succeeded(): - raise Exception('log enable failed (check LLDB_LOG env variable)') - - if ("LLDB_LINUX_LOG" in os.environ): - open(os.environ["LLDB_LINUX_LOG"], 'w').close() - if ("LLDB_LINUX_LOG_OPTION" in os.environ): - lldb_log_option = os.environ["LLDB_LINUX_LOG_OPTION"] - else: - lldb_log_option = "event process expr state api" - ci.HandleCommand( - "log enable -n -f " + - os.environ["LLDB_LINUX_LOG"] + - " linux " + - lldb_log_option, - res) - if not res.Succeeded(): - raise Exception( - 'log enable failed (check LLDB_LINUX_LOG env variable)') - - # Ditto for gdb-remote logging if ${GDB_REMOTE_LOG} environment variable is defined. - # Use ${GDB_REMOTE_LOG} to specify the log file. - if ("GDB_REMOTE_LOG" in os.environ): - if ("GDB_REMOTE_LOG_OPTION" in os.environ): - gdb_remote_log_option = os.environ["GDB_REMOTE_LOG_OPTION"] - else: - gdb_remote_log_option = "packets process" - ci.HandleCommand( - "log enable -n -f " + os.environ["GDB_REMOTE_LOG"] + " gdb-remote " - + gdb_remote_log_option, - res) - if not res.Succeeded(): - raise Exception( - 'log enable failed (check GDB_REMOTE_LOG env variable)') - - # ======================================== # # # # Execution of the test driver starts here # @@ -1097,9 +1022,6 @@ def run_suite(): # Now that we have loaded all the test cases, run the whole test suite. # - # Turn on lldb loggings if necessary. - lldbLoggings() - # Disable default dynamic types for testing purposes disabledynamics() diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py index 8b73fff8a0620..fa36cbcef4569 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest_args.py +++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py @@ -198,10 +198,6 @@ def create_parser(): # Test results support. group = parser.add_argument_group('Test results options') - group.add_argument( - '--curses', - action='store_true', - help='Shortcut for specifying test results using the curses formatter') group.add_argument( '--results-file', action='store', diff --git a/lldb/packages/Python/lldbsuite/test_event/formatter/curses.py b/lldb/packages/Python/lldbsuite/test_event/formatter/curses.py deleted file mode 100644 index c265f03c38b6b..0000000000000 --- a/lldb/packages/Python/lldbsuite/test_event/formatter/curses.py +++ /dev/null @@ -1,341 +0,0 @@ -""" - Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - See https://llvm.org/LICENSE.txt for license information. - SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -""" - -from __future__ import absolute_import -from __future__ import print_function - -# System modules -import curses -import datetime -import math -import sys -import time - -# Third-party modules - -# LLDB modules -from lldbsuite.test import lldbcurses - -from . import results_formatter -from ..event_builder import EventBuilder - - -class Curses(results_formatter.ResultsFormatter): - """Receives live results from tests that are running and reports them to the terminal in a curses GUI""" - - def __init__(self, out_file, options): - # Initialize the parent - super(Curses, self).__init__(out_file, options) - self.using_terminal = True - self.have_curses = True - self.initialize_event = None - self.jobs = [None] * 64 - self.job_tests = [None] * 64 - self.results = list() - try: - self.main_window = lldbcurses.intialize_curses() - self.main_window.add_key_action( - '\t', - self.main_window.select_next_first_responder, - "Switch between views that can respond to keyboard input") - self.main_window.refresh() - self.job_panel = None - self.results_panel = None - self.status_panel = None - self.info_panel = None - self.hide_status_list = list() - self.start_time = time.time() - except: - self.have_curses = False - lldbcurses.terminate_curses() - self.using_terminal = False - print("Unexpected error:", sys.exc_info()[0]) - raise - - self.line_dict = dict() - # self.events_file = open("/tmp/events.txt", "w") - # self.formatters = list() - # if tee_results_formatter: - # self.formatters.append(tee_results_formatter) - - def status_to_short_str(self, status, test_event): - if status == EventBuilder.STATUS_SUCCESS: - return '.' - elif status == EventBuilder.STATUS_FAILURE: - return 'F' - elif status == EventBuilder.STATUS_UNEXPECTED_SUCCESS: - return '?' - elif status == EventBuilder.STATUS_EXPECTED_FAILURE: - return 'X' - elif status == EventBuilder.STATUS_SKIP: - return 'S' - elif status == EventBuilder.STATUS_ERROR: - if test_event.get("issue_phase", None) == "build": - # Build failure - return 'B' - else: - return 'E' - elif status == EventBuilder.STATUS_TIMEOUT: - return 'T' - elif status == EventBuilder.STATUS_EXPECTED_TIMEOUT: - return 't' - else: - return status - - def show_info_panel(self): - selected_idx = self.results_panel.get_selected_idx() - if selected_idx >= 0 and selected_idx < len(self.results): - if self.info_panel is None: - info_frame = self.results_panel.get_contained_rect( - top_inset=10, left_inset=10, right_inset=10, height=30) - self.info_panel = lldbcurses.BoxedPanel( - info_frame, "Result Details") - # Add a key action for any key that will hide this panel when - # any key is pressed - self.info_panel.add_key_action(-1, - self.hide_info_panel, - 'Hide the info panel') - self.info_panel.top() - else: - self.info_panel.show() - - self.main_window.push_first_responder(self.info_panel) - test_start = self.results[selected_idx][0] - test_result = self.results[selected_idx][1] - self.info_panel.set_line( - 0, "File: %s" % - (test_start['test_filename'])) - self.info_panel.set_line( - 1, "Test: %s.%s" % - (test_start['test_class'], test_start['test_name'])) - self.info_panel.set_line( - 2, "Time: %s" % - (test_result['elapsed_time'])) - self.info_panel.set_line(3, "Status: %s" % (test_result['status'])) - - def hide_info_panel(self): - self.main_window.pop_first_responder(self.info_panel) - self.info_panel.hide() - self.main_window.refresh() - - def toggle_status(self, status): - if status: - # Toggle showing and hiding results whose status matches "status" - # in "Results" window - if status in self.hide_status_list: - self.hide_status_list.remove(status) - else: - self.hide_status_list.append(status) - self.update_results() - - def update_results(self, update=True): - '''Called after a category of test have been show/hidden to update the results list with - what the user desires to see.''' - self.results_panel.clear(update=False) - for result in self.results: - test_result = result[1] - status = test_result['status'] - if status in self.hide_status_list: - continue - name = test_result['test_class'] + '.' + test_result['test_name'] - self.results_panel.append_line( - '%s (%6.2f sec) %s' % - (self.status_to_short_str( - status, - test_result), - test_result['elapsed_time'], - name)) - if update: - self.main_window.refresh() - - def handle_event(self, test_event): - with self.lock: - super(Curses, self).handle_event(test_event) - # for formatter in self.formatters: - # formatter.process_event(test_event) - if self.have_curses: - worker_index = -1 - if 'worker_index' in test_event: - worker_index = test_event['worker_index'] - if 'event' in test_event: - check_for_one_key = True - #print(str(test_event), file=self.events_file) - event = test_event['event'] - if self.status_panel: - self.status_panel.update_status( - 'time', str( - datetime.timedelta( - seconds=math.floor( - time.time() - self.start_time)))) - if event == 'test_start': - name = test_event['test_class'] + \ - '.' + test_event['test_name'] - self.job_tests[worker_index] = test_event - if 'pid' in test_event: - line = 'pid: %5d ' % (test_event['pid']) + name - else: - line = name - self.job_panel.set_line(worker_index, line) - self.main_window.refresh() - elif event == 'test_result': - status = test_event['status'] - self.status_panel.increment_status(status) - if 'pid' in test_event: - line = 'pid: %5d ' % (test_event['pid']) - else: - line = '' - self.job_panel.set_line(worker_index, line) - name = test_event['test_class'] + \ - '.' + test_event['test_name'] - elapsed_time = test_event[ - 'event_time'] - self.job_tests[worker_index]['event_time'] - if status not in self.hide_status_list: - self.results_panel.append_line( - '%s (%6.2f sec) %s' % - (self.status_to_short_str( - status, test_event), elapsed_time, name)) - self.main_window.refresh() - # Append the result pairs - test_event['elapsed_time'] = elapsed_time - self.results.append( - [self.job_tests[worker_index], test_event]) - self.job_tests[worker_index] = '' - elif event == 'job_begin': - self.jobs[worker_index] = test_event - if 'pid' in test_event: - line = 'pid: %5d ' % (test_event['pid']) - else: - line = '' - self.job_panel.set_line(worker_index, line) - elif event == 'job_end': - self.jobs[worker_index] = '' - self.job_panel.set_line(worker_index, '') - elif event == 'initialize': - self.initialize_event = test_event - num_jobs = test_event['worker_count'] - job_frame = self.main_window.get_contained_rect( - height=num_jobs + 2) - results_frame = self.main_window.get_contained_rect( - top_inset=num_jobs + 2, bottom_inset=1) - status_frame = self.main_window.get_contained_rect( - height=1, top_inset=self.main_window.get_size().h - 1) - self.job_panel = lldbcurses.BoxedPanel( - frame=job_frame, title="Jobs") - self.results_panel = lldbcurses.BoxedPanel( - frame=results_frame, title="Results") - - self.results_panel.add_key_action( - curses.KEY_UP, - self.results_panel.select_prev, - "Select the previous list entry") - self.results_panel.add_key_action( - curses.KEY_DOWN, self.results_panel.select_next, "Select the next list entry") - self.results_panel.add_key_action( - curses.KEY_HOME, - self.results_panel.scroll_begin, - "Scroll to the start of the list") - self.results_panel.add_key_action( - curses.KEY_END, self.results_panel.scroll_end, "Scroll to the end of the list") - self.results_panel.add_key_action( - curses.KEY_ENTER, - self.show_info_panel, - "Display info for the selected result item") - self.results_panel.add_key_action( - '.', - lambda: self.toggle_status( - EventBuilder.STATUS_SUCCESS), - "Toggle showing/hiding tests whose status is 'success'") - self.results_panel.add_key_action( - 'e', - lambda: self.toggle_status( - EventBuilder.STATUS_ERROR), - "Toggle showing/hiding tests whose status is 'error'") - self.results_panel.add_key_action( - 'f', - lambda: self.toggle_status( - EventBuilder.STATUS_FAILURE), - "Toggle showing/hiding tests whose status is 'failure'") - self.results_panel.add_key_action('s', lambda: self.toggle_status( - EventBuilder.STATUS_SKIP), "Toggle showing/hiding tests whose status is 'skip'") - self.results_panel.add_key_action( - 'x', - lambda: self.toggle_status( - EventBuilder.STATUS_EXPECTED_FAILURE), - "Toggle showing/hiding tests whose status is 'expected_failure'") - self.results_panel.add_key_action( - '?', - lambda: self.toggle_status( - EventBuilder.STATUS_UNEXPECTED_SUCCESS), - "Toggle showing/hiding tests whose status is 'unexpected_success'") - self.status_panel = lldbcurses.StatusPanel( - frame=status_frame) - - self.main_window.add_child(self.job_panel) - self.main_window.add_child(self.results_panel) - self.main_window.add_child(self.status_panel) - self.main_window.set_first_responder( - self.results_panel) - - self.status_panel.add_status_item( - name="time", - title="Elapsed", - format="%s", - width=20, - value="0:00:00", - update=False) - self.status_panel.add_status_item( - name=EventBuilder.STATUS_SUCCESS, - title="Success", - format="%u", - width=20, - value=0, - update=False) - self.status_panel.add_status_item( - name=EventBuilder.STATUS_FAILURE, - title="Failure", - format="%u", - width=20, - value=0, - update=False) - self.status_panel.add_status_item( - name=EventBuilder.STATUS_ERROR, - title="Error", - format="%u", - width=20, - value=0, - update=False) - self.status_panel.add_status_item( - name=EventBuilder.STATUS_SKIP, - title="Skipped", - format="%u", - width=20, - value=0, - update=True) - self.status_panel.add_status_item( - name=EventBuilder.STATUS_EXPECTED_FAILURE, - title="Expected Failure", - format="%u", - width=30, - value=0, - update=False) - self.status_panel.add_status_item( - name=EventBuilder.STATUS_UNEXPECTED_SUCCESS, - title="Unexpected Success", - format="%u", - width=30, - value=0, - update=False) - self.main_window.refresh() - elif event == 'terminate': - # self.main_window.key_event_loop() - lldbcurses.terminate_curses() - check_for_one_key = False - self.using_terminal = False - # Check for 1 keypress with no delay - - # Check for 1 keypress with no delay - if check_for_one_key: - self.main_window.key_event_loop(0, 1) diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp index c9b46e34588a1..89f2139db71b1 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -88,7 +88,6 @@ extern "C" // TODO: dlsym won't work on Windows. void *dlsym(void* handle, const char* symbol); int (*ptr__tsan_get_report_loc_object_type)(void *report, unsigned long idx, const char **object_type); - int (*ptr__tsan_get_report_tag)(void *report, unsigned long *tag); } const int REPORT_TRACE_SIZE = 128; @@ -98,7 +97,6 @@ struct data { void *report; const char *description; int report_count; - unsigned long tag; void *sleep_trace[REPORT_TRACE_SIZE]; @@ -165,14 +163,10 @@ const char *thread_sanitizer_retrieve_report_data_command = R"( data t = {0}; ptr__tsan_get_report_loc_object_type = (typeof(ptr__tsan_get_report_loc_object_type))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_loc_object_type"); -ptr__tsan_get_report_tag = (typeof(ptr__tsan_get_report_tag))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_tag"); t.report = __tsan_get_current_report(); __tsan_get_report_data(t.report, &t.description, &t.report_count, &t.stack_count, &t.mop_count, &t.loc_count, &t.mutex_count, &t.thread_count, &t.unique_tid_count, t.sleep_trace, REPORT_TRACE_SIZE); -if (ptr__tsan_get_report_tag) - ptr__tsan_get_report_tag(t.report, &t.tag); - if (t.stack_count > REPORT_ARRAY_SIZE) t.stack_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.stack_count; i++) { t.stacks[i].idx = i; @@ -353,9 +347,6 @@ ThreadSanitizerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { ->GetValueAsUnsigned(0)); dict->AddItem("sleep_trace", StructuredData::ObjectSP(CreateStackTrace( main_value, ".sleep_trace"))); - dict->AddIntegerItem( - "tag", - main_value->GetValueForExpressionPath(".tag")->GetValueAsUnsigned(0)); StructuredData::Array *stacks = ConvertToStructuredArray( main_value, ".stacks", ".stack_count", @@ -494,8 +485,8 @@ ThreadSanitizerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { return StructuredData::ObjectSP(dict); } -std::string ThreadSanitizerRuntime::FormatDescription( - StructuredData::ObjectSP report, bool &is_swift_access_race) { +std::string +ThreadSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) { std::string description = report->GetAsDictionary() ->GetValueForKey("issue_type") ->GetAsString() @@ -530,18 +521,8 @@ std::string ThreadSanitizerRuntime::FormatDescription( } else if (description == "lock-order-inversion") { return "Lock order inversion (potential deadlock)"; } else if (description == "external-race") { - auto tag = report->GetAsDictionary() - ->GetValueForKey("tag") - ->GetAsInteger() - ->GetValue(); - static const unsigned long kSwiftAccessRaceTag = 0x1; - if (tag == kSwiftAccessRaceTag) { - is_swift_access_race = true; - return "Swift access race"; - } return "Race on a library object"; } else if (description == "swift-access-race") { - is_swift_access_race = true; return "Swift access race"; } @@ -635,14 +616,9 @@ ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) { ->GetValueForKey("description") ->GetAsString() ->GetValue(); - bool is_swift_access_race = report->GetAsDictionary() - ->GetValueForKey("is_swift_access_race") - ->GetAsBoolean() - ->GetValue(); - bool skip_one_frame = - (report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == - "external-race") && (!is_swift_access_race); + report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == + "external-race"; addr_t pc = 0; if (report->GetAsDictionary() @@ -834,12 +810,8 @@ bool ThreadSanitizerRuntime::NotifyBreakpointHit( instance->RetrieveReportData(context->exe_ctx_ref); std::string stop_reason_description; if (report) { - bool is_swift_access_race = false; - std::string issue_description = - instance->FormatDescription(report, is_swift_access_race); + std::string issue_description = instance->FormatDescription(report); report->GetAsDictionary()->AddStringItem("description", issue_description); - report->GetAsDictionary()->AddBooleanItem("is_swift_access_race", - is_swift_access_race); stop_reason_description = issue_description + " detected"; report->GetAsDictionary()->AddStringItem("stop_description", stop_reason_description); diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h index 966edd34797b2..db8bb1db79960 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h @@ -61,8 +61,7 @@ class ThreadSanitizerRuntime : public lldb_private::InstrumentationRuntime { StructuredData::ObjectSP RetrieveReportData(ExecutionContextRef exe_ctx_ref); - std::string FormatDescription(StructuredData::ObjectSP report, - bool &is_swift_access_race); + std::string FormatDescription(StructuredData::ObjectSP report); std::string GenerateSummary(StructuredData::ObjectSP report); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h b/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h index f7b804b3a2116..e2a088f921764 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GISelKnownBits.h @@ -47,6 +47,17 @@ class GISelKnownBits : public GISelChangeObserver { APInt getKnownZeroes(Register R); APInt getKnownOnes(Register R); + /// \return true if 'V & Mask' is known to be zero in DemandedElts. We use + /// this predicate to simplify operations downstream. + /// Mask is known to be zero for bits that V cannot have. + bool maskedValueIsZero(Register Val, const APInt &Mask) { + return Mask.isSubsetOf(getKnownBits(Val).Zero); + } + + /// \return true if the sign bit of Op is known to be zero. We use this + /// predicate to simplify operations downstream. + bool signBitIsZero(Register Op); + // FIXME: Is this the right place for G_FRAME_INDEX? Should it be in // TargetLowering? void computeKnownBitsForFrameIndex(Register R, KnownBits &Known, diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 62010238d24cc..e4877b7ad6391 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -31,6 +31,7 @@ namespace llvm { class APInt; class APFloat; +class GISelKnownBits; class MachineInstr; class MachineInstrBuilder; class MachineFunction; @@ -381,11 +382,15 @@ class InstructionSelector { virtual bool select(MachineInstr &I) = 0; CodeGenCoverage *CoverageInfo = nullptr; + GISelKnownBits *KnownBits = nullptr; MachineFunction *MF = nullptr; /// Setup per-MF selector state. - virtual void setupMF(MachineFunction &mf, CodeGenCoverage &covinfo) { + virtual void setupMF(MachineFunction &mf, + GISelKnownBits &KB, + CodeGenCoverage &covinfo) { CoverageInfo = &covinfo; + KnownBits = &KB; MF = &mf; } diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp index 91b2f1d03a146..61aa13cde1312 100644 --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -84,7 +84,7 @@ bool llvm::VerifyMemorySSA = false; #endif /// Enables memory ssa as a dependency for loop passes in legacy pass manager. cl::opt llvm::EnableMSSALoopDependency( - "enable-mssa-loop-dependency", cl::Hidden, cl::init(false), + "enable-mssa-loop-dependency", cl::Hidden, cl::init(true), cl::desc("Enable MemorySSA dependency for loop pass manager")); static cl::opt diff --git a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp index 31e28f5ed5c64..0870aa3812fe9 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp @@ -75,6 +75,12 @@ KnownBits GISelKnownBits::getKnownBits(Register R) { return Known; } +bool GISelKnownBits::signBitIsZero(Register R) { + LLT Ty = MRI.getType(R); + unsigned BitWidth = Ty.getScalarSizeInBits(); + return maskedValueIsZero(R, APInt::getSignMask(BitWidth)); +} + APInt GISelKnownBits::getKnownZeroes(Register R) { return getKnownBits(R).Zero; } diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp index d699b4d2d4299..1fc12359cd84b 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -12,6 +12,7 @@ #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" #include "llvm/CodeGen/GlobalISel/Utils.h" @@ -53,6 +54,8 @@ InstructionSelect::InstructionSelect() : MachineFunctionPass(ID) { } void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); getSelectionDAGFallbackAnalysisUsage(AU); MachineFunctionPass::getAnalysisUsage(AU); } @@ -64,12 +67,13 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) { return false; LLVM_DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n'); + GISelKnownBits &KB = getAnalysis().get(MF); const TargetPassConfig &TPC = getAnalysis(); InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector(); CodeGenCoverage CoverageInfo; assert(ISel && "Cannot work without InstructionSelector"); - ISel->setupMF(MF, CoverageInfo); + ISel->setupMF(MF, KB, CoverageInfo); // An optimization remark emitter. Used to report failures. MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr); diff --git a/llvm/lib/Target/AArch64/AArch64InstrAtomics.td b/llvm/lib/Target/AArch64/AArch64InstrAtomics.td index 60fbf6589555b..459b53923625d 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrAtomics.td +++ b/llvm/lib/Target/AArch64/AArch64InstrAtomics.td @@ -287,22 +287,30 @@ def : Pat<(and (ldaxr_4 GPR64sp:$addr), 0xffffffff), def stxr_1 : PatFrag<(ops node:$val, node:$ptr), (int_aarch64_stxr node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i8; -}]>; +}]> { + let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 1); }]; +} def stxr_2 : PatFrag<(ops node:$val, node:$ptr), (int_aarch64_stxr node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i16; -}]>; +}]> { + let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 2); }]; +} def stxr_4 : PatFrag<(ops node:$val, node:$ptr), (int_aarch64_stxr node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i32; -}]>; +}]> { + let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 4); }]; +} def stxr_8 : PatFrag<(ops node:$val, node:$ptr), (int_aarch64_stxr node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i64; -}]>; +}]> { + let GISelPredicateCode = [{ return isLoadStoreOfNumBytes(MI, 8); }]; +} def : Pat<(stxr_1 GPR64:$val, GPR64sp:$addr), diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index dda8f1c096832..1865e577b21cb 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -54,8 +54,9 @@ class AArch64InstructionSelector : public InstructionSelector { bool select(MachineInstr &I) override; static const char *getName() { return DEBUG_TYPE; } - void setupMF(MachineFunction &MF, CodeGenCoverage &CoverageInfo) override { - InstructionSelector::setupMF(MF, CoverageInfo); + void setupMF(MachineFunction &MF, GISelKnownBits &KB, + CodeGenCoverage &CoverageInfo) override { + InstructionSelector::setupMF(MF, KB, CoverageInfo); // hasFnAttribute() is expensive to call on every BRCOND selection, so // cache it here for each run of the selector. diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index 4c6c2edc385ed..b4d7f35d2d9a4 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -19,6 +19,7 @@ #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/MustExecute.h" #include "llvm/Analysis/ScalarEvolution.h" @@ -170,6 +171,8 @@ void llvm::getLoopAnalysisUsage(AnalysisUsage &AU) { AU.addPreserved(); AU.addRequired(); AU.addPreserved(); + // FIXME: When all loop passes preserve MemorySSA, it can be required and + // preserved here instead of the individual handling in each pass. } /// Manually defined generic "LoopPass" dependency initialization. This is used @@ -190,6 +193,7 @@ void llvm::initializeLoopPassPass(PassRegistry &Registry) { INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) + INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass) } /// Create MDNode for input string. diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll b/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll index 6d628ed5a294e..fd7809fa0c168 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll @@ -53,6 +53,7 @@ ; VERIFY-NEXT: Verify generated machine code ; ENABLED-O0-NEXT: Localizer ; VERIFY-O0-NEXT: Verify generated machine code +; ENABLED-NEXT: Analysis for ComputingKnownBits ; ENABLED-NEXT: InstructionSelect ; VERIFY-NEXT: Verify generated machine code ; ENABLED-NEXT: ResetMachineFunction diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-stx.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-stx.mir new file mode 100644 index 0000000000000..56071210481ed --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-stx.mir @@ -0,0 +1,122 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s + +--- | + define void @test_store_i8(i32, i8 %val, i8* %addr) { ret void } + define void @test_store_i16(i32, i16 %val, i16* %addr) { ret void } + define void @test_store_i32(i32, i32 %val, i32* %addr) { ret void } + define void @test_store_i64(i32, i64 %val, i64* %addr) { ret void } +... +--- +name: test_store_i8 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $w0, $w1, $x2 + + ; CHECK-LABEL: name: test_store_i8 + ; CHECK: liveins: $w0, $w1, $x2 + ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w1 + ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x2 + ; CHECK: [[DEF:%[0-9]+]]:gpr64all = IMPLICIT_DEF + ; CHECK: [[INSERT_SUBREG:%[0-9]+]]:gpr64all = INSERT_SUBREG [[DEF]], [[COPY]], %subreg.sub_32 + ; CHECK: [[COPY2:%[0-9]+]]:gpr32 = COPY [[INSERT_SUBREG]].sub_32 + ; CHECK: early-clobber %5:gpr32 = STXRB [[COPY2]], [[COPY1]] :: (volatile store 1 into %ir.addr) + ; CHECK: $w0 = COPY %5 + ; CHECK: RET_ReallyLR implicit $w0 + %3:gpr(s32) = COPY $w1 + %2:gpr(p0) = COPY $x2 + %6:gpr(s64) = G_CONSTANT i64 255 + %7:gpr(s64) = G_ANYEXT %3(s32) + %4:gpr(s64) = G_AND %7, %6 + %5:gpr(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.stxr), %4(s64), %2(p0) :: (volatile store 1 into %ir.addr) + $w0 = COPY %5(s32) + RET_ReallyLR implicit $w0 + +... +--- +name: test_store_i16 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $w0, $w1, $x2 + + ; CHECK-LABEL: name: test_store_i16 + ; CHECK: liveins: $w0, $w1, $x2 + ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w1 + ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x2 + ; CHECK: [[DEF:%[0-9]+]]:gpr64all = IMPLICIT_DEF + ; CHECK: [[INSERT_SUBREG:%[0-9]+]]:gpr64all = INSERT_SUBREG [[DEF]], [[COPY]], %subreg.sub_32 + ; CHECK: [[COPY2:%[0-9]+]]:gpr32 = COPY [[INSERT_SUBREG]].sub_32 + ; CHECK: early-clobber %5:gpr32 = STXRH [[COPY2]], [[COPY1]] :: (volatile store 2 into %ir.addr) + ; CHECK: $w0 = COPY %5 + ; CHECK: RET_ReallyLR implicit $w0 + %3:gpr(s32) = COPY $w1 + %2:gpr(p0) = COPY $x2 + %6:gpr(s64) = G_CONSTANT i64 65535 + %7:gpr(s64) = G_ANYEXT %3(s32) + %4:gpr(s64) = G_AND %7, %6 + %5:gpr(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.stxr), %4(s64), %2(p0) :: (volatile store 2 into %ir.addr) + $w0 = COPY %5(s32) + RET_ReallyLR implicit $w0 + +... +--- +name: test_store_i32 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $w0, $w1, $x2 + + ; CHECK-LABEL: name: test_store_i32 + ; CHECK: liveins: $w0, $w1, $x2 + ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w1 + ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x2 + ; CHECK: early-clobber %3:gpr32 = STXRW [[COPY]], [[COPY1]] :: (volatile store 4 into %ir.addr) + ; CHECK: $w0 = COPY %3 + ; CHECK: RET_ReallyLR implicit $w0 + %1:gpr(s32) = COPY $w1 + %2:gpr(p0) = COPY $x2 + %3:gpr(s64) = G_ZEXT %1(s32) + %4:gpr(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.stxr), %3(s64), %2(p0) :: (volatile store 4 into %ir.addr) + $w0 = COPY %4(s32) + RET_ReallyLR implicit $w0 + +... +--- +name: test_store_i64 +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +machineFunctionInfo: {} +body: | + bb.0: + liveins: $w0, $x1, $x2 + + ; CHECK-LABEL: name: test_store_i64 + ; CHECK: liveins: $w0, $x1, $x2 + ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x2 + ; CHECK: early-clobber %2:gpr32 = STXRX [[COPY]], [[COPY1]] :: (volatile store 8 into %ir.addr) + ; CHECK: $w0 = COPY %2 + ; CHECK: RET_ReallyLR implicit $w0 + %1:gpr(s64) = COPY $x1 + %2:gpr(p0) = COPY $x2 + %3:gpr(s32) = G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.stxr), %1(s64), %2(p0) :: (volatile store 8 into %ir.addr) + $w0 = COPY %3(s32) + RET_ReallyLR implicit $w0 + +... diff --git a/llvm/test/CodeGen/AArch64/O0-pipeline.ll b/llvm/test/CodeGen/AArch64/O0-pipeline.ll index 38af1810feb71..9611946f71034 100644 --- a/llvm/test/CodeGen/AArch64/O0-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O0-pipeline.ll @@ -41,6 +41,7 @@ ; CHECK-NEXT: Legalizer ; CHECK-NEXT: RegBankSelect ; CHECK-NEXT: Localizer +; CHECK-NEXT: Analysis for ComputingKnownBits ; CHECK-NEXT: InstructionSelect ; CHECK-NEXT: ResetMachineFunction ; CHECK-NEXT: AArch64 Instruction Selection diff --git a/llvm/test/CodeGen/AArch64/arm64-ldxr-stxr.ll b/llvm/test/CodeGen/AArch64/arm64-ldxr-stxr.ll index 14ed59e8728d1..aa9c5dfff5b7a 100644 --- a/llvm/test/CodeGen/AArch64/arm64-ldxr-stxr.ll +++ b/llvm/test/CodeGen/AArch64/arm64-ldxr-stxr.ll @@ -113,39 +113,57 @@ declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind +; FALLBACK-NOT: remark:{{.*}}test_store_i8 define i32 @test_store_i8(i32, i8 %val, i8* %addr) { ; CHECK-LABEL: test_store_i8: ; CHECK-NOT: uxtb ; CHECK-NOT: and ; CHECK: stxrb w0, w1, [x2] +; GISEL-LABEL: test_store_i8: +; GISEL-NOT: uxtb +; GISEL-NOT: and +; GISEL: stxrb w0, w1, [x2] %extval = zext i8 %val to i64 %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr) ret i32 %res } +; FALLBACK-NOT: remark:{{.*}}test_store_i16 define i32 @test_store_i16(i32, i16 %val, i16* %addr) { ; CHECK-LABEL: test_store_i16: ; CHECK-NOT: uxth ; CHECK-NOT: and ; CHECK: stxrh w0, w1, [x2] +; GISEL-LABEL: test_store_i16: +; GISEL-NOT: uxth +; GISEL-NOT: and +; GISEL: stxrh w0, w1, [x2] %extval = zext i16 %val to i64 %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr) ret i32 %res } +; FALLBACK-NOT: remark:{{.*}}test_store_i32 define i32 @test_store_i32(i32, i32 %val, i32* %addr) { ; CHECK-LABEL: test_store_i32: ; CHECK-NOT: uxtw ; CHECK-NOT: and ; CHECK: stxr w0, w1, [x2] +; GISEL-LABEL: test_store_i32: +; GISEL-NOT: uxtw +; GISEL-NOT: and +; GISEL: stxr w0, w1, [x2] %extval = zext i32 %val to i64 %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr) ret i32 %res } +; FALLBACK-NOT: remark:{{.*}}test_store_i64 define i32 @test_store_i64(i32, i64 %val, i64* %addr) { ; CHECK-LABEL: test_store_i64: ; CHECK: stxr w0, x1, [x2] +; GISEL-LABEL: test_store_i64: +; GISEL: stxr w0, x1, [x2] %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr) ret i32 %res } diff --git a/llvm/test/CodeGen/PowerPC/sms-grp-order.ll b/llvm/test/CodeGen/PowerPC/sms-grp-order.ll index a3e6de1c593f6..c462e18d9f939 100644 --- a/llvm/test/CodeGen/PowerPC/sms-grp-order.ll +++ b/llvm/test/CodeGen/PowerPC/sms-grp-order.ll @@ -4,25 +4,24 @@ define void @lame_encode_buffer_interleaved() local_unnamed_addr { ; CHECK-LABEL: lame_encode_buffer_interleaved: -; CHECK: # %bb.0: -; CHECK-NEXT: lhz 3, 0(0) -; CHECK-NEXT: li 5, 1 -; CHECK-NEXT: sldi 5, 5, 62 -; CHECK-NEXT: lhz 4, 0(3) -; CHECK-NEXT: mtctr 5 -; CHECK-NEXT: .p2align 5 -; CHECK-NEXT: .LBB0_1: # -; CHECK-NEXT: extsh 3, 3 -; CHECK-NEXT: extsh 4, 4 -; CHECK-NEXT: srawi 3, 3, 1 -; CHECK-NEXT: addze 3, 3 -; CHECK-NEXT: srawi 4, 4, 1 -; CHECK-NEXT: addze 4, 4 -; CHECK-NEXT: bdnz .LBB0_1 -; CHECK-NEXT: # %bb.2: -; CHECK-NEXT: sth 3, 0(0) -; CHECK-NEXT: sth 4, 0(3) -; CHECK-NEXT: blr +; CHECK: # %bb.0: +; CHECK-NEXT: lha 3, 0(3) +; CHECK-NEXT: li 5, 1 +; CHECK-NEXT: sldi 5, 5, 62 +; CHECK-NEXT: lhz 4, 0(0) +; CHECK-NEXT: mtctr 5 +; CHECK-NEXT: srawi 3, 3, 1 +; CHECK-NEXT: addze 3, 3 +; CHECK-NEXT: .p2align 4 +; CHECK-NEXT: .LBB0_1: +; CHECK-NEXT: extsh 4, 4 +; CHECK-NEXT: srawi 4, 4, 1 +; CHECK-NEXT: addze 4, 4 +; CHECK-NEXT: bdnz .LBB0_1 +; CHECK-NEXT: # %bb.2: +; CHECK-NEXT: sth 4, 0(0) +; CHECK-NEXT: sth 3, 0(3) +; CHECK-NEXT: blr br label %1 1: ; preds = %1, %0 diff --git a/llvm/test/Other/opt-O2-pipeline.ll b/llvm/test/Other/opt-O2-pipeline.ll index ecd6b7c8a355e..b4acce3cb8b47 100644 --- a/llvm/test/Other/opt-O2-pipeline.ll +++ b/llvm/test/Other/opt-O2-pipeline.ll @@ -93,12 +93,13 @@ ; CHECK-NEXT: Simplify the CFG ; CHECK-NEXT: Reassociate expressions ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Rotate Loops @@ -153,12 +154,13 @@ ; CHECK-NEXT: Phi Values Analysis ; CHECK-NEXT: Memory Dependence Analysis ; CHECK-NEXT: Dead Store Elimination +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Loop Invariant Code Motion @@ -185,12 +187,13 @@ ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Float to int ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Rotate Loops @@ -246,6 +249,7 @@ ; CHECK-NEXT: Lazy Block Frequency Analysis ; CHECK-NEXT: Optimization Remark Emitter ; CHECK-NEXT: Combine redundant instructions +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass diff --git a/llvm/test/Other/opt-O3-pipeline.ll b/llvm/test/Other/opt-O3-pipeline.ll index ee5e55f0d376f..b1f68aed30297 100644 --- a/llvm/test/Other/opt-O3-pipeline.ll +++ b/llvm/test/Other/opt-O3-pipeline.ll @@ -98,12 +98,13 @@ ; CHECK-NEXT: Simplify the CFG ; CHECK-NEXT: Reassociate expressions ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Rotate Loops @@ -158,12 +159,13 @@ ; CHECK-NEXT: Phi Values Analysis ; CHECK-NEXT: Memory Dependence Analysis ; CHECK-NEXT: Dead Store Elimination +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Loop Invariant Code Motion @@ -190,12 +192,13 @@ ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Float to int ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Rotate Loops @@ -251,6 +254,7 @@ ; CHECK-NEXT: Lazy Block Frequency Analysis ; CHECK-NEXT: Optimization Remark Emitter ; CHECK-NEXT: Combine redundant instructions +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass diff --git a/llvm/test/Other/opt-Os-pipeline.ll b/llvm/test/Other/opt-Os-pipeline.ll index 069d198c7a14c..b9902685b88de 100644 --- a/llvm/test/Other/opt-Os-pipeline.ll +++ b/llvm/test/Other/opt-Os-pipeline.ll @@ -80,12 +80,13 @@ ; CHECK-NEXT: Simplify the CFG ; CHECK-NEXT: Reassociate expressions ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Rotate Loops @@ -140,12 +141,13 @@ ; CHECK-NEXT: Phi Values Analysis ; CHECK-NEXT: Memory Dependence Analysis ; CHECK-NEXT: Dead Store Elimination +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Loop Invariant Code Motion @@ -172,12 +174,13 @@ ; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Float to int ; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) +; CHECK-NEXT: Function Alias Analysis Results +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Natural Loop Information ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass -; CHECK-NEXT: Basic Alias Analysis (stateless AA impl) -; CHECK-NEXT: Function Alias Analysis Results ; CHECK-NEXT: Scalar Evolution Analysis ; CHECK-NEXT: Loop Pass Manager ; CHECK-NEXT: Rotate Loops @@ -233,6 +236,7 @@ ; CHECK-NEXT: Lazy Block Frequency Analysis ; CHECK-NEXT: Optimization Remark Emitter ; CHECK-NEXT: Combine redundant instructions +; CHECK-NEXT: Memory SSA ; CHECK-NEXT: Canonicalize natural loops ; CHECK-NEXT: LCSSA Verifier ; CHECK-NEXT: Loop-Closed SSA Form Pass diff --git a/llvm/test/Transforms/InstCombine/bswap.ll b/llvm/test/Transforms/InstCombine/bswap.ll index 69be38df415fa..1f9e418284ebb 100644 --- a/llvm/test/Transforms/InstCombine/bswap.ll +++ b/llvm/test/Transforms/InstCombine/bswap.ll @@ -1,10 +1,11 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" define i32 @test1(i32 %i) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[TMP12:%.*]] = call i32 @llvm.bswap.i32(i32 %i) +; CHECK-NEXT: [[TMP12:%.*]] = call i32 @llvm.bswap.i32(i32 [[I:%.*]]) ; CHECK-NEXT: ret i32 [[TMP12]] ; %tmp1 = lshr i32 %i, 24 @@ -21,7 +22,7 @@ define i32 @test1(i32 %i) { define i32 @test2(i32 %arg) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.bswap.i32(i32 %arg) +; CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.bswap.i32(i32 [[ARG:%.*]]) ; CHECK-NEXT: ret i32 [[TMP14]] ; %tmp2 = shl i32 %arg, 24 @@ -38,7 +39,7 @@ define i32 @test2(i32 %arg) { define i16 @test3(i16 %s) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 %s) +; CHECK-NEXT: [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 [[S:%.*]]) ; CHECK-NEXT: ret i16 [[TMP5]] ; %tmp2 = lshr i16 %s, 8 @@ -49,7 +50,7 @@ define i16 @test3(i16 %s) { define i16 @test4(i16 %s) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 %s) +; CHECK-NEXT: [[TMP5:%.*]] = call i16 @llvm.bswap.i16(i16 [[S:%.*]]) ; CHECK-NEXT: ret i16 [[TMP5]] ; %tmp2 = lshr i16 %s, 8 @@ -60,7 +61,7 @@ define i16 @test4(i16 %s) { define i16 @test5(i16 %a) { ; CHECK-LABEL: @test5( -; CHECK-NEXT: [[TMP_UPGRD_3:%.*]] = call i16 @llvm.bswap.i16(i16 %a) +; CHECK-NEXT: [[TMP_UPGRD_3:%.*]] = call i16 @llvm.bswap.i16(i16 [[A:%.*]]) ; CHECK-NEXT: ret i16 [[TMP_UPGRD_3]] ; %tmp = zext i16 %a to i32 @@ -80,7 +81,7 @@ define i16 @test5(i16 %a) { ; PR2842 define i32 @test6(i32 %x) nounwind readnone { ; CHECK-LABEL: @test6( -; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.bswap.i32(i32 %x) +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]]) ; CHECK-NEXT: ret i32 [[TMP7]] ; %tmp = shl i32 %x, 16 @@ -102,7 +103,7 @@ declare void @extra_use(i32) define i32 @bswap32_and_first(i32 %x) { ; CHECK-LABEL: @bswap32_and_first( -; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 %x) +; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]]) ; CHECK-NEXT: ret i32 [[BSWAP]] ; %shl = shl i32 %x, 16 @@ -122,11 +123,11 @@ define i32 @bswap32_and_first(i32 %x) { define i32 @bswap32_and_first_extra_use(i32 %x) { ; CHECK-LABEL: @bswap32_and_first_extra_use( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 %x, 16 -; CHECK-NEXT: [[SHR:%.*]] = lshr i32 %x, 16 +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 16 +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[SWAPHALF:%.*]] = or i32 [[SHL]], [[SHR]] ; CHECK-NEXT: [[T:%.*]] = and i32 [[SWAPHALF]], 16711935 -; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 %x) +; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X]]) ; CHECK-NEXT: call void @extra_use(i32 [[T]]) ; CHECK-NEXT: ret i32 [[BSWAP]] ; @@ -148,7 +149,7 @@ define i32 @bswap32_and_first_extra_use(i32 %x) { ; PR23863 define i32 @bswap32_shl_first(i32 %x) { ; CHECK-LABEL: @bswap32_shl_first( -; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 %x) +; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X:%.*]]) ; CHECK-NEXT: ret i32 [[BSWAP]] ; %shl = shl i32 %x, 16 @@ -168,11 +169,11 @@ define i32 @bswap32_shl_first(i32 %x) { define i32 @bswap32_shl_first_extra_use(i32 %x) { ; CHECK-LABEL: @bswap32_shl_first_extra_use( -; CHECK-NEXT: [[SHL:%.*]] = shl i32 %x, 16 -; CHECK-NEXT: [[SHR:%.*]] = lshr i32 %x, 16 +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[X:%.*]], 16 +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[X]], 16 ; CHECK-NEXT: [[SWAPHALF:%.*]] = or i32 [[SHL]], [[SHR]] ; CHECK-NEXT: [[T:%.*]] = shl i32 [[SWAPHALF]], 8 -; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 %x) +; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 [[X]]) ; CHECK-NEXT: call void @extra_use(i32 [[T]]) ; CHECK-NEXT: ret i32 [[BSWAP]] ; @@ -190,7 +191,7 @@ define i32 @bswap32_shl_first_extra_use(i32 %x) { define i16 @test8(i16 %a) { ; CHECK-LABEL: @test8( -; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 %a) +; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 [[A:%.*]]) ; CHECK-NEXT: ret i16 [[REV]] ; %conv = zext i16 %a to i32 @@ -204,7 +205,7 @@ define i16 @test8(i16 %a) { define i16 @test9(i16 %a) { ; CHECK-LABEL: @test9( -; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 %a) +; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 [[A:%.*]]) ; CHECK-NEXT: ret i16 [[REV]] ; %conv = zext i16 %a to i32 @@ -217,7 +218,7 @@ define i16 @test9(i16 %a) { define i16 @test10(i32 %a) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 %a to i16 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[A:%.*]] to i16 ; CHECK-NEXT: [[REV:%.*]] = call i16 @llvm.bswap.i16(i16 [[TRUNC]]) ; CHECK-NEXT: ret i16 [[REV]] ; @@ -230,3 +231,65 @@ define i16 @test10(i32 %a) { ret i16 %conv } +define i32 @shuf_4bytes(<4 x i8> %x) { +; CHECK-LABEL: @shuf_4bytes( +; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> undef, <4 x i32> +; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i8> [[BSWAP]] to i32 +; CHECK-NEXT: ret i32 [[CAST]] +; + %bswap = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> + %cast = bitcast <4 x i8> %bswap to i32 + ret i32 %cast +} + +define i32 @shuf_load_4bytes(<4 x i8>* %p) { +; CHECK-LABEL: @shuf_load_4bytes( +; CHECK-NEXT: [[X:%.*]] = load <4 x i8>, <4 x i8>* [[P:%.*]], align 4 +; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <4 x i8> [[X]], <4 x i8> undef, <4 x i32> +; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i8> [[BSWAP]] to i32 +; CHECK-NEXT: ret i32 [[CAST]] +; + %x = load <4 x i8>, <4 x i8>* %p + %bswap = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> + %cast = bitcast <4 x i8> %bswap to i32 + ret i32 %cast +} + +define i32 @shuf_bitcast_twice_4bytes(i32 %x) { +; CHECK-LABEL: @shuf_bitcast_twice_4bytes( +; CHECK-NEXT: [[CAST1:%.*]] = bitcast i32 [[X:%.*]] to <4 x i8> +; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <4 x i8> [[CAST1]], <4 x i8> undef, <4 x i32> +; CHECK-NEXT: [[CAST2:%.*]] = bitcast <4 x i8> [[BSWAP]] to i32 +; CHECK-NEXT: ret i32 [[CAST2]] +; + %cast1 = bitcast i32 %x to <4 x i8> + %bswap = shufflevector <4 x i8> %cast1, <4 x i8> undef, <4 x i32> + %cast2 = bitcast <4 x i8> %bswap to i32 + ret i32 %cast2 +} + +declare void @use(<4 x i8>) + +define i32 @shuf_4bytes_extra_use(<4 x i8> %x) { +; CHECK-LABEL: @shuf_4bytes_extra_use( +; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> undef, <4 x i32> +; CHECK-NEXT: call void @use(<4 x i8> [[BSWAP]]) +; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i8> [[BSWAP]] to i32 +; CHECK-NEXT: ret i32 [[CAST]] +; + %bswap = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> + call void @use(<4 x i8> %bswap) + %cast = bitcast <4 x i8> %bswap to i32 + ret i32 %cast +} + +define i128 @shuf_load_16bytes(<16 x i8> %x) { +; CHECK-LABEL: @shuf_load_16bytes( +; CHECK-NEXT: [[BSWAP:%.*]] = shufflevector <16 x i8> [[X:%.*]], <16 x i8> undef, <16 x i32> +; CHECK-NEXT: [[CAST:%.*]] = bitcast <16 x i8> [[BSWAP]] to i128 +; CHECK-NEXT: ret i128 [[CAST]] +; + %bswap = shufflevector <16 x i8> %x, <16 x i8> undef, <16 x i32> + %cast = bitcast <16 x i8> %bswap to i128 + ret i128 %cast +} diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp index f67184fc2081d..42d676f4a00e5 100644 --- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp @@ -86,3 +86,19 @@ TEST_F(GISelMITest, TestKnownBits) { APInt Zeroes = Info.getKnownZeroes(SrcReg); EXPECT_EQ(Known.Zero, Zeroes); } + +TEST_F(GISelMITest, TestSignBitIsZero) { + if (!TM) + return; + + const LLT S32 = LLT::scalar(32); + auto SignBit = B.buildConstant(S32, 0x8000000); + auto Zero = B.buildConstant(S32, 0); + + GISelKnownBits KnownBits(*MF); + + EXPECT_TRUE(KnownBits.signBitIsZero(Zero.getReg(0))); + EXPECT_FALSE(KnownBits.signBitIsZero(Zero.getReg(0))); + EXPECT_FALSE(KnownBits.signBitIsZero(SignBit.getReg(0))); + EXPECT_TRUE(KnownBits.signBitIsZero(SignBit.getReg(0))); +}