From 324396466c720c3a5b961225c7f52aa8043f916d Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 23 May 2019 09:07:51 +0000 Subject: [PATCH 0001/1176] DWARF: Don't compute address ranges for type units Summary: Type units don't describe any code, so they should never be the result of any address lookup queries. Previously, we would compute the address ranges for the type units for via the line tables they reference because the type units looked a lot like line-tables-only compile units. However, this is not correct, as the line tables are only referenced from type units so that other declarations can use the file names contained in them. In this patch I make the BuildAddressRangeTable function virtual, and implement it only for compile units. Testing this was a bit tricky, because the behavior depends on the order in which we add things to the address range map. This rarely caused a problem with DWARF v4 type units, as they are always added after all CUs. It happened more frequently with DWARF v5, as there clang emits the type units first. However, this is still not something that it is required to do, so for testing I've created an assembly file where I've deliberately sandwiched a compile unit between two type units, which should isolate us from both changes in how the compiler emits the units and changes in the order we process them. Reviewers: clayborg, aprantl, JDevlieghere Subscribers: jdoerfert, lldb-commits Differential Revision: https://reviews.llvm.org/D62178 llvm-svn: 361465 --- .../DWARF/debug-types-address-ranges.s | 338 ++++++++++++++++++ .../SymbolFile/DWARF/DWARFCompileUnit.cpp | 93 +++++ .../SymbolFile/DWARF/DWARFCompileUnit.h | 2 + .../Plugins/SymbolFile/DWARF/DWARFTypeUnit.h | 2 + .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 95 ----- .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 38 +- .../SymbolFile/DWARF/SymbolFileDWARF.h | 2 +- .../DWARF/SymbolFileDWARFDebugMap.h | 2 +- 8 files changed, 456 insertions(+), 116 deletions(-) create mode 100644 lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s diff --git a/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s b/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s new file mode 100644 index 0000000000000..892c93d3822cc --- /dev/null +++ b/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s @@ -0,0 +1,338 @@ +# Check address lookup works correctly in the presence of type units. +# Specifically check that we don't use the line table pointed to by the +# DW_AT_stmt_list of the type unit (which used only for the file names) to +# compute address range for the type unit as type units don't describe any +# addresses. The addresses should always resolve to the relevant compile units. + +# RUN: llvm-mc -dwarf-version=5 -triple x86_64-pc-linux %s -filetype=obj >%t.o +# RUN: ld.lld %t.o -o %t -image-base=0x47000 +# RUN: %lldb %t -o "image lookup -a 0x48000 -v" -o exit | FileCheck %s + +# CHECK: CompileUnit: id = {0x00000001}, file = "/tmp/a.cc", language = "c++" +# CHECK: Function: id = {0x7fffffff0000006a}, name = "::_start({{.*}})", range = [0x0000000000048000-0x000000000004800c) +# CHECK: LineEntry: [0x0000000000048000-0x000000000004800a): /tmp/a.cc:4 +# CHECK: Symbol: id = {0x00000002}, range = [0x0000000000048000-0x000000000004800c), name="_start" +# CHECK: Variable: id = {0x7fffffff00000075}, name = "v1", {{.*}} decl = a.cc:4 +# CHECK: Variable: id = {0x7fffffff00000080}, name = "v2", {{.*}} decl = a.cc:4 + + +# Output generated via +# clang -g -fdebug-types-section -gdwarf-5 -S +# from +# enum E1 { e1 }; +# enum E2 { e2 }; +# extern "C" void _start(E1 v1, E2 v2) {} +# The output was modified to place the compile unit in between the two type +# units. + + .text + .file "a.cc" + .file 0 "/tmp" "a.cc" + + .text + .globl _start # -- Begin function _start + .p2align 4, 0x90 + .type _start,@function +_start: # @_start +.Lfunc_begin0: + .loc 0 4 0 # /tmp/a.cc:4:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl %edi, -4(%rbp) + movl %esi, -8(%rbp) +.Ltmp0: + .loc 0 4 23 prologue_end # /tmp/a.cc:4:23 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size _start, .Lfunc_end0-_start + .cfi_endproc + # -- End function + .section .debug_str_offsets,"",@progbits + .long 52 + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 9.0.0 (trunk 360907) (llvm/trunk 360908)" +.Linfo_string1: + .asciz "a.cc" +.Linfo_string2: + .asciz "/tmp" +.Linfo_string3: + .asciz "unsigned int" +.Linfo_string4: + .asciz "e1" +.Linfo_string5: + .asciz "E1" +.Linfo_string6: + .asciz "e2" +.Linfo_string7: + .asciz "E2" +.Linfo_string8: + .asciz "_start" +.Linfo_string9: + .asciz "f" +.Linfo_string10: + .asciz "v1" +.Linfo_string11: + .asciz "v2" + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 4 # DW_TAG_enumeration_type + .byte 1 # DW_CHILDREN_yes + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 40 # DW_TAG_enumerator + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 28 # DW_AT_const_value + .byte 15 # DW_FORM_udata + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 4 # DW_TAG_enumeration_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad -6180787752776176174 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x1d DW_TAG_type_unit + .short 4 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0xd DW_TAG_enumeration_type + .long 48 # DW_AT_type + .byte 5 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x2c:0x3 DW_TAG_enumerator + .byte 4 # DW_AT_name + .byte 0 # DW_AT_const_value + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x30:0x4 DW_TAG_base_type + .byte 3 # DW_AT_name + .byte 7 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + + .long .Ldebug_info_end2-.Ldebug_info_start2 # Length of Unit +.Ldebug_info_start2: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 5 # Abbrev [5] 0xc:0x4d DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 4 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 6 # Abbrev [6] 0x23:0x9 DW_TAG_enumeration_type + # DW_AT_declaration + .quad -6180787752776176174 # DW_AT_signature + .byte 6 # Abbrev [6] 0x2c:0x9 DW_TAG_enumeration_type + # DW_AT_declaration + .quad 7818257750321376053 # DW_AT_signature + .byte 7 # Abbrev [7] 0x35:0x23 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + # DW_AT_external + .byte 8 # Abbrev [8] 0x41:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 35 # DW_AT_type + .byte 8 # Abbrev [8] 0x4c:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 44 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end2: + + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 7818257750321376053 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x1d DW_TAG_type_unit + .short 4 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0xd DW_TAG_enumeration_type + .long 48 # DW_AT_type + .byte 7 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x2c:0x3 DW_TAG_enumerator + .byte 6 # DW_AT_name + .byte 0 # DW_AT_const_value + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x30:0x4 DW_TAG_base_type + .byte 3 # DW_AT_name + .byte 7 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_macinfo,"",@progbits + .byte 0 # End Of Macro List Mark + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 0931c10983c67..c48ca235ec286 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -7,7 +7,11 @@ //===----------------------------------------------------------------------===// #include "DWARFCompileUnit.h" +#include "DWARFDebugAranges.h" +#include "SymbolFileDWARFDebugMap.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Utility/Stream.h" using namespace lldb; @@ -20,3 +24,92 @@ void DWARFCompileUnit::Dump(Stream *s) const { GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(), GetAddressByteSize(), GetNextUnitOffset()); } + +void DWARFCompileUnit::BuildAddressRangeTable( + DWARFDebugAranges *debug_aranges) { + // This function is usually called if there in no .debug_aranges section in + // order to produce a compile unit level set of address ranges that is + // accurate. + + size_t num_debug_aranges = debug_aranges->GetNumRanges(); + + // First get the compile unit DIE only and check if it has a DW_AT_ranges + const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); + + const dw_offset_t cu_offset = GetOffset(); + if (die) { + DWARFRangeList ranges; + const size_t num_ranges = + die->GetAttributeAddressRanges(this, ranges, false); + if (num_ranges > 0) { + // This compile unit has DW_AT_ranges, assume this is correct if it is + // present since clang no longer makes .debug_aranges by default and it + // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with + // recent GCC builds. + for (size_t i = 0; i < num_ranges; ++i) { + const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); + debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), + range.GetRangeEnd()); + } + + return; // We got all of our ranges from the DW_AT_ranges attribute + } + } + // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF + + // If the DIEs weren't parsed, then we don't want all dies for all compile + // units to stay loaded when they weren't needed. So we can end up parsing + // the DWARF and then throwing them all away to keep memory usage down. + ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); + + die = DIEPtr(); + if (die) + die->BuildAddressRangeTable(this, debug_aranges); + + if (debug_aranges->GetNumRanges() == num_debug_aranges) { + // We got nothing from the functions, maybe we have a line tables only + // situation. Check the line tables and build the arange table from this. + SymbolContext sc; + sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this); + if (sc.comp_unit) { + SymbolFileDWARFDebugMap *debug_map_sym_file = + m_dwarf->GetDebugMapSymfile(); + if (debug_map_sym_file == nullptr) { + if (LineTable *line_table = sc.comp_unit->GetLineTable()) { + LineTable::FileAddressRanges file_ranges; + const bool append = true; + const size_t num_ranges = + line_table->GetContiguousFileAddressRanges(file_ranges, append); + for (uint32_t idx = 0; idx < num_ranges; ++idx) { + const LineTable::FileAddressRanges::Entry &range = + file_ranges.GetEntryRef(idx); + debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), + range.GetRangeEnd()); + } + } + } else + debug_map_sym_file->AddOSOARanges(m_dwarf, debug_aranges); + } + } + + if (debug_aranges->GetNumRanges() == num_debug_aranges) { + // We got nothing from the functions, maybe we have a line tables only + // situation. Check the line tables and build the arange table from this. + SymbolContext sc; + sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this); + if (sc.comp_unit) { + if (LineTable *line_table = sc.comp_unit->GetLineTable()) { + LineTable::FileAddressRanges file_ranges; + const bool append = true; + const size_t num_ranges = + line_table->GetContiguousFileAddressRanges(file_ranges, append); + for (uint32_t idx = 0; idx < num_ranges; ++idx) { + const LineTable::FileAddressRanges::Entry &range = + file_ranges.GetEntryRef(idx); + debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), + range.GetRangeEnd()); + } + } + } + } +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 8ed2656dc7c8f..dc5fe25b40f27 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -14,6 +14,8 @@ class DWARFCompileUnit : public DWARFUnit { public: + void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override; + void Dump(lldb_private::Stream *s) const override; private: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h index 0b2e0a8e438a6..e146e6bf50339 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h @@ -14,6 +14,8 @@ class DWARFTypeUnit : public DWARFUnit { public: + void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override {} + void Dump(lldb_private::Stream *s) const override; private: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index c3b9a1931f703..59202061436ff 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -10,8 +10,6 @@ #include "lldb/Core/Module.h" #include "lldb/Host/StringConvert.h" -#include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/StreamString.h" @@ -23,7 +21,6 @@ #include "DWARFDebugInfo.h" #include "DWARFTypeUnit.h" #include "LogChannelDWARF.h" -#include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" using namespace lldb; @@ -407,98 +404,6 @@ void DWARFUnit::ClearDIEsRWLocked() { m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked(); } -void DWARFUnit::BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) { - // This function is usually called if there in no .debug_aranges section in - // order to produce a compile unit level set of address ranges that is - // accurate. - - size_t num_debug_aranges = debug_aranges->GetNumRanges(); - - // First get the compile unit DIE only and check if it has a DW_AT_ranges - const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); - - const dw_offset_t cu_offset = GetOffset(); - if (die) { - DWARFRangeList ranges; - const size_t num_ranges = - die->GetAttributeAddressRanges(this, ranges, false); - if (num_ranges > 0) { - // This compile unit has DW_AT_ranges, assume this is correct if it is - // present since clang no longer makes .debug_aranges by default and it - // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with - // recent GCC builds. - for (size_t i = 0; i < num_ranges; ++i) { - const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); - debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), - range.GetRangeEnd()); - } - - return; // We got all of our ranges from the DW_AT_ranges attribute - } - } - // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF - - // If the DIEs weren't parsed, then we don't want all dies for all compile - // units to stay loaded when they weren't needed. So we can end up parsing - // the DWARF and then throwing them all away to keep memory usage down. - ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); - - die = DIEPtr(); - if (die) - die->BuildAddressRangeTable(this, debug_aranges); - - if (debug_aranges->GetNumRanges() == num_debug_aranges) { - // We got nothing from the functions, maybe we have a line tables only - // situation. Check the line tables and build the arange table from this. - SymbolContext sc; - sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this); - if (sc.comp_unit) { - SymbolFileDWARFDebugMap *debug_map_sym_file = - m_dwarf->GetDebugMapSymfile(); - if (debug_map_sym_file == NULL) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table) { - LineTable::FileAddressRanges file_ranges; - const bool append = true; - const size_t num_ranges = - line_table->GetContiguousFileAddressRanges(file_ranges, append); - for (uint32_t idx = 0; idx < num_ranges; ++idx) { - const LineTable::FileAddressRanges::Entry &range = - file_ranges.GetEntryRef(idx); - debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), - range.GetRangeEnd()); - } - } - } else - debug_map_sym_file->AddOSOARanges(m_dwarf, debug_aranges); - } - } - - if (debug_aranges->GetNumRanges() == num_debug_aranges) { - // We got nothing from the functions, maybe we have a line tables only - // situation. Check the line tables and build the arange table from this. - SymbolContext sc; - sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this); - if (sc.comp_unit) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table) { - LineTable::FileAddressRanges file_ranges; - const bool append = true; - const size_t num_ranges = - line_table->GetContiguousFileAddressRanges(file_ranges, append); - for (uint32_t idx = 0; idx < num_ranges; ++idx) { - const LineTable::FileAddressRanges::Entry &range = - file_ranges.GetEntryRef(idx); - debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), - range.GetRangeEnd()); - } - } - } - } -} - lldb::ByteOrder DWARFUnit::GetByteOrder() const { return m_dwarf->GetObjectFile()->GetByteOrder(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 6b6fffc1e7b09..927ca2ed8de8b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -143,7 +143,7 @@ class DWARFUnit : public lldb_private::UserID { void SetRangesBase(dw_addr_t ranges_base); void SetBaseObjOffset(dw_offset_t base_obj_offset); void SetStrOffsetsBase(dw_offset_t str_offsets_base); - void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges); + virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0; lldb::ByteOrder GetByteOrder() const; @@ -215,6 +215,24 @@ class DWARFUnit : public lldb_private::UserID { const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr); + // Get the DWARF unit DWARF debug information entry. Parse the single DIE + // if needed. + const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { + ExtractUnitDIEIfNeeded(); + // m_first_die_mutex is not required as m_first_die is never cleared. + if (!m_first_die) + return NULL; + return &m_first_die; + } + + // Get all DWARF debug informration entries. Parse all DIEs if needed. + const DWARFDebugInfoEntry *DIEPtr() { + ExtractDIEsIfNeeded(); + if (m_die_array.empty()) + return NULL; + return &m_die_array[0]; + } + SymbolFileDWARF *m_dwarf = nullptr; std::unique_ptr m_dwo_symbol_file; DWARFUnitHeader m_header; @@ -257,24 +275,6 @@ class DWARFUnit : public lldb_private::UserID { void ExtractDIEsRWLocked(); void ClearDIEsRWLocked(); - // Get the DWARF unit DWARF debug informration entry. Parse the single DIE - // if needed. - const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { - ExtractUnitDIEIfNeeded(); - // m_first_die_mutex is not required as m_first_die is never cleared. - if (!m_first_die) - return NULL; - return &m_first_die; - } - - // Get all DWARF debug informration entries. Parse all DIEs if needed. - const DWARFDebugInfoEntry *DIEPtr() { - ExtractDIEsIfNeeded(); - if (m_die_array.empty()) - return NULL; - return &m_die_array[0]; - } - void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); void ComputeCompDirAndGuessPathStyle(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 52d2d061b5dd4..426719bf0b293 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -62,7 +62,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, friend class SymbolFileDWARFDwo; friend class DebugMapModule; friend struct DIERef; - friend class DWARFUnit; + friend class DWARFCompileUnit; friend class DWARFDIE; friend class DWARFASTParserClang; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index b7dc2bcb2a892..13813cd8cb28c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -135,7 +135,7 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile { friend class DebugMapModule; friend struct DIERef; friend class DWARFASTParserClang; - friend class DWARFUnit; + friend class DWARFCompileUnit; friend class SymbolFileDWARF; struct OSOInfo { lldb::ModuleSP module_sp; From e98a8f7b2a8625e99d1024cf100933a6e8551bae Mon Sep 17 00:00:00 2001 From: George Rimar Date: Thu, 23 May 2019 09:18:57 +0000 Subject: [PATCH 0002/1176] [llvm-objcopy] - Many minor NFC changes to cleanup/improve the code in ELF/Object.cpp. The code in ELF/Object.cpp is sometimes a bit hard to read because of lots of auto used everywhere. The main intention of this patch is to replace them with the real type for places where it is not obvious. Also it cleanups few places. It is NFC change, but I want to be sure that there is no objections to do that since it is massive. DIfferential revision: https://reviews.llvm.org/D62260 llvm-svn: 361466 --- llvm/tools/llvm-objcopy/ELF/Object.cpp | 191 +++++++++++-------------- 1 file changed, 85 insertions(+), 106 deletions(-) diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp index b0f7c1e3c35fc..0c80bad6c102d 100644 --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -37,8 +37,8 @@ using namespace object; using namespace ELF; template void ELFWriter::writePhdr(const Segment &Seg) { - uint8_t *B = Buf.getBufferStart(); - B += Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr); + uint8_t *B = Buf.getBufferStart() + Obj.ProgramHdrSegment.Offset + + Seg.Index * sizeof(Elf_Phdr); Elf_Phdr &Phdr = *reinterpret_cast(B); Phdr.p_type = Seg.Type; Phdr.p_flags = Seg.Flags; @@ -67,8 +67,7 @@ void SectionBase::replaceSectionReferences( const DenseMap &) {} template void ELFWriter::writeShdr(const SectionBase &Sec) { - uint8_t *B = Buf.getBufferStart(); - B += Sec.HeaderOffset; + uint8_t *B = Buf.getBufferStart() + Sec.HeaderOffset; Elf_Shdr &Shdr = *reinterpret_cast(B); Shdr.sh_name = Sec.NameIndex; Shdr.sh_type = Sec.Type; @@ -144,10 +143,8 @@ void BinarySectionWriter::visit(const GroupSection &Sec) { } void SectionWriter::visit(const Section &Sec) { - if (Sec.Type == SHT_NOBITS) - return; - uint8_t *Buf = Out.getBufferStart() + Sec.Offset; - llvm::copy(Sec.Contents, Buf); + if (Sec.Type != SHT_NOBITS) + llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset); } void Section::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } @@ -155,8 +152,7 @@ void Section::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } void Section::accept(MutableSectionVisitor &Visitor) { Visitor.visit(*this); } void SectionWriter::visit(const OwnedDataSection &Sec) { - uint8_t *Buf = Out.getBufferStart() + Sec.Offset; - llvm::copy(Sec.Data, Buf); + llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset); } static const std::vector ZlibGnuMagic = {'Z', 'L', 'I', 'B'}; @@ -227,9 +223,7 @@ void BinarySectionWriter::visit(const CompressedSection &Sec) { template void ELFSectionWriter::visit(const CompressedSection &Sec) { - uint8_t *Buf = Out.getBufferStart(); - Buf += Sec.Offset; - + uint8_t *Buf = Out.getBufferStart() + Sec.Offset; if (Sec.CompressionType == DebugCompressionType::None) { std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf); return; @@ -323,8 +317,7 @@ void StringTableSection::accept(MutableSectionVisitor &Visitor) { template void ELFSectionWriter::visit(const SectionIndexSection &Sec) { uint8_t *Buf = Out.getBufferStart() + Sec.Offset; - auto *IndexesBuffer = reinterpret_cast(Buf); - llvm::copy(Sec.Indexes, IndexesBuffer); + llvm::copy(Sec.Indexes, reinterpret_cast(Buf)); } void SectionIndexSection::initialize(SectionTableRef SecTable) { @@ -481,7 +474,7 @@ void SymbolTableSection::initialize(SectionTableRef SecTable) { void SymbolTableSection::finalize() { uint32_t MaxLocalIndex = 0; - for (auto &Sym : Symbols) { + for (std::unique_ptr &Sym : Symbols) { Sym->NameIndex = SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name); if (Sym->Binding == STB_LOCAL) @@ -504,7 +497,7 @@ void SymbolTableSection::prepareForLayout() { // If the symbol names section has been removed, don't try to add strings to // the table. if (SymbolNames != nullptr) - for (auto &Sym : Symbols) + for (std::unique_ptr &Sym : Symbols) SymbolNames->addString(Sym->Name); } @@ -513,7 +506,7 @@ void SymbolTableSection::fillShndxTable() { return; // Fill section index table with real section indexes. This function must // be called after assignOffsets. - for (const auto &Sym : Symbols) { + for (const std::unique_ptr &Sym : Symbols) { if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE) SectionIndexTable->addIndex(Sym->DefinedIn->Index); else @@ -534,11 +527,9 @@ Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) { template void ELFSectionWriter::visit(const SymbolTableSection &Sec) { - uint8_t *Buf = Out.getBufferStart(); - Buf += Sec.Offset; - Elf_Sym *Sym = reinterpret_cast(Buf); + Elf_Sym *Sym = reinterpret_cast(Out.getBufferStart() + Sec.Offset); // Loop though symbols setting each entry of the symbol table. - for (auto &Symbol : Sec.Symbols) { + for (const std::unique_ptr &Symbol : Sec.Symbols) { Sym->st_name = Symbol->NameIndex; Sym->st_value = Symbol->Value; Sym->st_size = Symbol->Size; @@ -671,8 +662,7 @@ void RelocationSection::replaceSectionReferences( } void SectionWriter::visit(const DynamicRelocationSection &Sec) { - llvm::copy(Sec.Contents, - Out.getBufferStart() + Sec.Offset); + llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset); } void DynamicRelocationSection::accept(SectionVisitor &Visitor) const { @@ -680,33 +670,32 @@ void DynamicRelocationSection::accept(SectionVisitor &Visitor) const { } void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); -} - -Error DynamicRelocationSection::removeSectionReferences( - bool AllowBrokenLinks, function_ref ToRemove) { - if (ToRemove(Symbols)) { - if (!AllowBrokenLinks) - return createStringError( - llvm::errc::invalid_argument, + Visitor.visit(*this); +} + +Error DynamicRelocationSection::removeSectionReferences( + bool AllowBrokenLinks, function_ref ToRemove) { + if (ToRemove(Symbols)) { + if (!AllowBrokenLinks) + return createStringError( + llvm::errc::invalid_argument, "symbol table '%s' cannot be removed because it is " "referenced by the relocation section '%s'", - Symbols->Name.data(), this->Name.data()); - Symbols = nullptr; - } - - // SecToApplyRel contains a section referenced by sh_info field. It keeps - // a section to which the relocation section applies. When we remove any - // sections we also remove their relocation sections. Since we do that much - // earlier, this assert should never be triggered. - assert(!SecToApplyRel || !ToRemove(SecToApplyRel)); - - return Error::success(); -} - -Error Section::removeSectionReferences(bool AllowBrokenDependency, - function_ref ToRemove) { - if (ToRemove(LinkSection)) { + Symbols->Name.data(), this->Name.data()); + Symbols = nullptr; + } + + // SecToApplyRel contains a section referenced by sh_info field. It keeps + // a section to which the relocation section applies. When we remove any + // sections we also remove their relocation sections. Since we do that much + // earlier, this assert should never be triggered. + assert(!SecToApplyRel || !ToRemove(SecToApplyRel)); + return Error::success(); +} + +Error Section::removeSectionReferences(bool AllowBrokenDependency, + function_ref ToRemove) { + if (ToRemove(LinkSection)) { if (!AllowBrokenDependency) return createStringError(llvm::errc::invalid_argument, "section '%s' cannot be removed because it is " @@ -744,13 +733,13 @@ void GroupSection::replaceSectionReferences( } void Section::initialize(SectionTableRef SecTable) { - if (Link != ELF::SHN_UNDEF) { - LinkSection = - SecTable.getSection(Link, "Link field value " + Twine(Link) + - " in section " + Name + " is invalid"); - if (LinkSection->Type == ELF::SHT_SYMTAB) - LinkSection = nullptr; - } + if (Link == ELF::SHN_UNDEF) + return; + LinkSection = + SecTable.getSection(Link, "Link field value " + Twine(Link) + + " in section " + Name + " is invalid"); + if (LinkSection->Type == ELF::SHT_SYMTAB) + LinkSection = nullptr; } void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; } @@ -800,7 +789,7 @@ void ELFSectionWriter::visit(const GroupSection &Sec) { ELF::Elf32_Word *Buf = reinterpret_cast(Out.getBufferStart() + Sec.Offset); *Buf++ = Sec.FlagWord; - for (const auto *S : Sec.GroupMembers) + for (SectionBase *S : Sec.GroupMembers) support::endian::write32(Buf++, S->Index); } @@ -908,16 +897,15 @@ void BinaryELFBuilder::addData(SymbolTableSection *SymTab) { } void BinaryELFBuilder::initSections() { - for (auto &Section : Obj->sections()) { + for (SectionBase &Section : Obj->sections()) Section.initialize(Obj->sections()); - } } std::unique_ptr BinaryELFBuilder::build() { initFileHeader(); initHeaderSegment(); - StringTableSection *StrTab = addStrTab(); - SymbolTableSection *SymTab = addSymTab(StrTab); + + SymbolTableSection *SymTab = addSymTab(addStrTab()); initSections(); addData(SymTab); @@ -925,7 +913,7 @@ std::unique_ptr BinaryELFBuilder::build() { } template void ELFBuilder::setParentSegment(Segment &Child) { - for (auto &Parent : Obj.segments()) { + for (Segment &Parent : Obj.segments()) { // Every segment will overlap with itself but we don't want a segment to // be it's own parent so we avoid that situation. if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) { @@ -956,7 +944,7 @@ template void ELFBuilder::readProgramHeaders() { Seg.MemSize = Phdr.p_memsz; Seg.Align = Phdr.p_align; Seg.Index = Index++; - for (auto &Section : Obj.sections()) { + for (SectionBase &Section : Obj.sections()) { if (sectionWithinSegment(Section, Seg)) { Seg.addSection(&Section); if (!Section.ParentSegment || @@ -987,7 +975,7 @@ template void ELFBuilder::readProgramHeaders() { // Now we do an O(n^2) loop through the segments in order to match up // segments. - for (auto &Child : Obj.segments()) + for (Segment &Child : Obj.segments()) setParentSegment(Child); setParentSegment(ElfHdr); setParentSegment(PrHdr); @@ -998,14 +986,14 @@ void ELFBuilder::initGroupSection(GroupSection *GroupSec) { if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0) error("invalid alignment " + Twine(GroupSec->Align) + " of group section '" + GroupSec->Name + "'"); - auto SecTable = Obj.sections(); + SectionTableRef SecTable = Obj.sections(); auto SymTab = SecTable.template getSectionOfType( GroupSec->Link, "link field value '" + Twine(GroupSec->Link) + "' in section '" + GroupSec->Name + "' is invalid", "link field value '" + Twine(GroupSec->Link) + "' in section '" + GroupSec->Name + "' is not a symbol table"); - auto Sym = SymTab->getSymbolByIndex(GroupSec->Info); + Symbol *Sym = SymTab->getSymbolByIndex(GroupSec->Info); if (!Sym) error("info field value '" + Twine(GroupSec->Info) + "' in section '" + GroupSec->Name + "' is not a valid symbol index"); @@ -1294,8 +1282,7 @@ std::unique_ptr ELFReader::create() const { } template void ELFWriter::writeEhdr() { - uint8_t *B = Buf.getBufferStart(); - Elf_Ehdr &Ehdr = *reinterpret_cast(B); + Elf_Ehdr &Ehdr = *reinterpret_cast(Buf.getBufferStart()); std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0); Ehdr.e_ident[EI_MAG0] = 0x7f; Ehdr.e_ident[EI_MAG1] = 'E'; @@ -1357,10 +1344,10 @@ template void ELFWriter::writePhdrs() { } template void ELFWriter::writeShdrs() { - uint8_t *B = Buf.getBufferStart() + Obj.SHOffset; // This reference serves to write the dummy section header at the begining // of the file. It is not used for anything else - Elf_Shdr &Shdr = *reinterpret_cast(B); + Elf_Shdr &Shdr = + *reinterpret_cast(Buf.getBufferStart() + Obj.SHOffset); Shdr.sh_name = 0; Shdr.sh_type = SHT_NULL; Shdr.sh_flags = 0; @@ -1381,12 +1368,12 @@ template void ELFWriter::writeShdrs() { Shdr.sh_addralign = 0; Shdr.sh_entsize = 0; - for (auto &Sec : Obj.sections()) + for (SectionBase &Sec : Obj.sections()) writeShdr(Sec); } template void ELFWriter::writeSectionData() { - for (auto &Sec : Obj.sections()) + for (SectionBase &Sec : Obj.sections()) // Segments are responsible for writing their contents, so only write the // section data if the section is not in a segment. Note that this renders // sections in segments effectively immutable. @@ -1409,8 +1396,7 @@ template void ELFWriter::writeSegmentData() { continue; uint64_t Offset = Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset; - uint8_t *B = Buf.getBufferStart(); - std::memset(B + Offset, 0, Sec.Size); + std::memset(Buf.getBufferStart() + Offset, 0, Sec.Size); } } @@ -1515,20 +1501,20 @@ static uint64_t layoutSegments(std::vector &Segments, // then it's acceptable, but not ideal, to simply move it to after the // segments. So we can simply layout segments one after the other accounting // for alignment. - for (auto &Segment : Segments) { + for (Segment *Seg : Segments) { // We assume that segments have been ordered by OriginalOffset and Index // such that a parent segment will always come before a child segment in // OrderedSegments. This means that the Offset of the ParentSegment should // already be set and we can set our offset relative to it. - if (Segment->ParentSegment != nullptr) { - auto Parent = Segment->ParentSegment; - Segment->Offset = - Parent->Offset + Segment->OriginalOffset - Parent->OriginalOffset; + if (Seg->ParentSegment != nullptr) { + Segment *Parent = Seg->ParentSegment; + Seg->Offset = + Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset; } else { - Offset = alignToAddr(Offset, Segment->VAddr, Segment->Align); - Segment->Offset = Offset; + Offset = alignToAddr(Offset, Seg->VAddr, Seg->Align); + Seg->Offset = Offset; } - Offset = std::max(Offset, Segment->Offset + Segment->FileSize); + Offset = std::max(Offset, Seg->Offset + Seg->FileSize); } return Offset; } @@ -1565,7 +1551,7 @@ static uint64_t layoutSections(Range Sections, uint64_t Offset) { } template void ELFWriter::initEhdrSegment() { - auto &ElfHdr = Obj.ElfHdrSegment; + Segment &ElfHdr = Obj.ElfHdrSegment; ElfHdr.Type = PT_PHDR; ElfHdr.Flags = 0; ElfHdr.OriginalOffset = ElfHdr.Offset = 0; @@ -1580,7 +1566,7 @@ template void ELFWriter::assignOffsets() { // so that we know that anytime ->ParentSegment is set that segment has // already had its offset properly set. std::vector OrderedSegments; - for (auto &Segment : Obj.segments()) + for (Segment &Segment : Obj.segments()) OrderedSegments.push_back(&Segment); OrderedSegments.push_back(&Obj.ElfHdrSegment); OrderedSegments.push_back(&Obj.ProgramHdrSegment); @@ -1635,7 +1621,7 @@ template Error ELFWriter::finalize() { // we go to see if we will actully need large indexes. bool NeedsLargeIndexes = false; if (Obj.sections().size() >= SHN_LORESERVE) { - auto Sections = Obj.sections(); + SectionTableRef Sections = Obj.sections(); NeedsLargeIndexes = std::any_of(Sections.begin() + SHN_LORESERVE, Sections.end(), [](const SectionBase &Sec) { return Sec.HasSymbol; }); @@ -1693,7 +1679,7 @@ template Error ELFWriter::finalize() { // Now that all strings are added we want to finalize string table builders, // because that affects section sizes which in turn affects section offsets. - for (auto &Sec : Obj.sections()) + for (SectionBase &Sec : Obj.sections()) if (auto StrTab = dyn_cast(&Sec)) StrTab->prepareForLayout(); @@ -1707,7 +1693,7 @@ template Error ELFWriter::finalize() { // Finally now that all offsets and indexes have been set we can finalize any // remaining issues. uint64_t Offset = Obj.SHOffset + sizeof(Elf_Shdr); - for (auto &Section : Obj.sections()) { + for (SectionBase &Section : Obj.sections()) { Section.HeaderOffset = Offset; Offset += sizeof(Elf_Shdr); if (WriteSectionHeaders) @@ -1722,11 +1708,9 @@ template Error ELFWriter::finalize() { } Error BinaryWriter::write() { - for (auto &Section : Obj.sections()) { - if ((Section.Flags & SHF_ALLOC) == 0) - continue; - Section.accept(*SecWriter); - } + for (auto &Section : Obj.sections()) + if (Section.Flags & SHF_ALLOC) + Section.accept(*SecWriter); return Buf.commit(); } @@ -1739,11 +1723,9 @@ Error BinaryWriter::finalize() { // already had it's offset properly set. We only want to consider the segments // that will affect layout of allocated sections so we only add those. std::vector OrderedSegments; - for (auto &Section : Obj.sections()) { - if ((Section.Flags & SHF_ALLOC) != 0 && Section.ParentSegment != nullptr) { + for (SectionBase &Section : Obj.sections()) + if ((Section.Flags & SHF_ALLOC) != 0 && Section.ParentSegment != nullptr) OrderedSegments.push_back(Section.ParentSegment); - } - } // For binary output, we're going to use physical addresses instead of // virtual addresses, since a binary output is used for cases like ROM @@ -1770,8 +1752,8 @@ Error BinaryWriter::finalize() { // our layout algorithm to proceed as expected while not writing out the gap // at the start. if (!OrderedSegments.empty()) { - auto Seg = OrderedSegments[0]; - auto Sec = Seg->firstSection(); + Segment *Seg = OrderedSegments[0]; + const SectionBase *Sec = Seg->firstSection(); auto Diff = Sec->OriginalOffset - Seg->OriginalOffset; Seg->OriginalOffset += Diff; // The size needs to be shrunk as well. @@ -1780,7 +1762,7 @@ Error BinaryWriter::finalize() { // section. Seg->PAddr += Diff; uint64_t LowestPAddr = Seg->PAddr; - for (auto &Segment : OrderedSegments) { + for (Segment *Segment : OrderedSegments) { Segment->Offset = Segment->PAddr - LowestPAddr; Offset = std::max(Offset, Segment->Offset + Segment->FileSize); } @@ -1791,11 +1773,9 @@ Error BinaryWriter::finalize() { // not hold. Then pass such a range to LayoutSections instead of constructing // AllocatedSections here. std::vector AllocatedSections; - for (auto &Section : Obj.sections()) { - if ((Section.Flags & SHF_ALLOC) == 0) - continue; - AllocatedSections.push_back(&Section); - } + for (SectionBase &Section : Obj.sections()) + if (Section.Flags & SHF_ALLOC) + AllocatedSections.push_back(&Section); layoutSections(make_pointee_range(AllocatedSections), Offset); // Now that every section has been laid out we just need to compute the total @@ -1803,10 +1783,9 @@ Error BinaryWriter::finalize() { // LayoutSections, because we want to truncate the last segment to the end of // its last section, to match GNU objcopy's behaviour. TotalSize = 0; - for (const auto &Section : AllocatedSections) { + for (SectionBase *Section : AllocatedSections) if (Section->Type != SHT_NOBITS) TotalSize = std::max(TotalSize, Section->Offset + Section->Size); - } if (Error E = Buf.allocate(TotalSize)) return E; From 50434e8df0a32f3f1f7d8de2ef995d3509c33036 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Thu, 23 May 2019 09:20:08 +0000 Subject: [PATCH 0003/1176] Enable queue_t and clk_event_t comparisons in C++ mode Support queue_t and clk_event_t comparisons in C++ for OpenCL mode, to preserve backwards compatibility with OpenCL C. Differential Revision: https://reviews.llvm.org/D62208 llvm-svn: 361467 --- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/test/SemaOpenCL/clk_event_t.cl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index fbbdc666dc979..410d38cf5b6f8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10808,7 +10808,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return computeResultTy(); } - if (getLangOpts().OpenCLVersion >= 200) { + if (getLangOpts().OpenCLVersion >= 200 || getLangOpts().OpenCLCPlusPlus) { if (LHSType->isClkEventT() && RHSType->isClkEventT()) { return computeResultTy(); } diff --git a/clang/test/SemaOpenCL/clk_event_t.cl b/clang/test/SemaOpenCL/clk_event_t.cl index b73daf92fa006..4a884bcfa6c0a 100644 --- a/clang/test/SemaOpenCL/clk_event_t.cl +++ b/clang/test/SemaOpenCL/clk_event_t.cl @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=c++ // Taken from opencl-c.h #define CLK_NULL_EVENT (__builtin_astype(((void*)(__SIZE_MAX__)), clk_event_t)) From 39192043bbfca8d4fe8562e2a2105012edaff8c3 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 23 May 2019 09:22:43 +0000 Subject: [PATCH 0004/1176] Delete default constructors, copy constructors, move constructors, copy assignment, move assignment operators on Expr, Stmt and Decl Reviewers: ilya-biryukov, rsmith Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62187 llvm-svn: 361468 --- clang/include/clang/AST/DeclBase.h | 7 +++++++ clang/include/clang/AST/Expr.h | 7 +++++++ clang/include/clang/AST/Stmt.h | 11 ++++++----- clang/lib/CodeGen/CGBuiltin.cpp | 19 ++++++++----------- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 674e0f4a59b2e..cebf2973c8c3c 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -368,6 +368,13 @@ class alignas(8) Decl { return ModuleOwnershipKind::Unowned; } +public: + Decl() = delete; + Decl(const Decl&) = delete; + Decl(Decl &&) = delete; + Decl &operator=(const Decl&) = delete; + Decl &operator=(Decl&&) = delete; + protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)), diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 143eaae37b2af..96cb8e8f1a81a 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -108,6 +108,13 @@ struct SubobjectAdjustment { class Expr : public ValueStmt { QualType TR; +public: + Expr() = delete; + Expr(const Expr&) = delete; + Expr(Expr &&) = delete; + Expr &operator=(const Expr&) = delete; + Expr &operator=(Expr&&) = delete; + protected: Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index a6ab1851fefaf..8834a60cd6c99 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1040,6 +1040,12 @@ class alignas(void *) Stmt { explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {} public: + Stmt() = delete; + Stmt(const Stmt &) = delete; + Stmt(Stmt &&) = delete; + Stmt &operator=(const Stmt &) = delete; + Stmt &operator=(Stmt &&) = delete; + Stmt(StmtClass SC) { static_assert(sizeof(*this) <= 8, "changing bitfields changed sizeof(Stmt)"); @@ -1054,11 +1060,6 @@ class alignas(void *) Stmt { return static_cast(StmtBits.sClass); } - Stmt(const Stmt &) = delete; - Stmt(Stmt &&) = delete; - Stmt &operator=(const Stmt &) = delete; - Stmt &operator=(Stmt &&) = delete; - const char *getStmtClassName() const; bool isOMPStructuredBlock() const { return StmtBits.IsOMPStructuredBlock; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 34537d3f3ef17..d59e0fc960b3e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1134,9 +1134,10 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( return F; llvm::SmallVector ArgTys; - llvm::SmallVector Params; - Params.emplace_back(Ctx, nullptr, SourceLocation(), &Ctx.Idents.get("buffer"), - Ctx.VoidPtrTy, ImplicitParamDecl::Other); + FunctionArgList Args; + Args.push_back(ImplicitParamDecl::Create( + Ctx, nullptr, SourceLocation(), &Ctx.Idents.get("buffer"), Ctx.VoidPtrTy, + ImplicitParamDecl::Other)); ArgTys.emplace_back(Ctx.VoidPtrTy); for (unsigned int I = 0, E = Layout.Items.size(); I < E; ++I) { @@ -1145,17 +1146,13 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( continue; QualType ArgTy = getOSLogArgType(Ctx, Size); - Params.emplace_back( + Args.push_back(ImplicitParamDecl::Create( Ctx, nullptr, SourceLocation(), &Ctx.Idents.get(std::string("arg") + llvm::to_string(I)), ArgTy, - ImplicitParamDecl::Other); + ImplicitParamDecl::Other)); ArgTys.emplace_back(ArgTy); } - FunctionArgList Args; - for (auto &P : Params) - Args.push_back(&P); - QualType ReturnTy = Ctx.VoidTy; QualType FuncionTy = Ctx.getFunctionType(ReturnTy, ArgTys, {}); @@ -1188,7 +1185,7 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( auto AL = ApplyDebugLocation::CreateArtificial(*this); CharUnits Offset; - Address BufAddr(Builder.CreateLoad(GetAddrOfLocalVar(&Params[0]), "buf"), + Address BufAddr(Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), BufferAlignment); Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); @@ -1208,7 +1205,7 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( if (!Size.getQuantity()) continue; - Address Arg = GetAddrOfLocalVar(&Params[I]); + Address Arg = GetAddrOfLocalVar(Args[I]); Address Addr = Builder.CreateConstByteGEP(BufAddr, Offset, "argData"); Addr = Builder.CreateBitCast(Addr, Arg.getPointer()->getType(), "argDataCast"); From 0baaf45be707c9e13e9f4d74001cb87701a519c1 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 23 May 2019 09:26:27 +0000 Subject: [PATCH 0005/1176] Move SymbolTable::addCombinedLTOObject() to LinkerDriver. Also renames it LinkerDriver::compileBitcodeFiles. The function doesn't logically belong to SymbolTable. We added this function to the symbol table because symbol table used to be a container of input files. This is no longer the case. Differential Revision: https://reviews.llvm.org/D62291 llvm-svn: 361469 --- lld/ELF/Driver.cpp | 25 ++++++++++++++++++++++++- lld/ELF/Driver.h | 5 +++++ lld/ELF/SymbolTable.cpp | 28 ---------------------------- lld/ELF/SymbolTable.h | 5 ----- 4 files changed, 29 insertions(+), 34 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index cad182ea3ee47..6bd00e46b9143 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1436,6 +1436,29 @@ template static Symbol *addUndefined(StringRef Name) { Undefined{nullptr, Name, STB_GLOBAL, STV_DEFAULT, 0}); } +// This function is where all the optimizations of link-time +// optimization takes place. When LTO is in use, some input files are +// not in native object file format but in the LLVM bitcode format. +// This function compiles bitcode files into a few big native files +// using LLVM functions and replaces bitcode symbols with the results. +// Because all bitcode files that the program consists of are passed to +// the compiler at once, it can do a whole-program optimization. +template void LinkerDriver::compileBitcodeFiles() { + // Compile bitcode files and replace bitcode symbols. + LTO.reset(new BitcodeCompiler); + for (BitcodeFile *File : BitcodeFiles) + LTO->add(*File); + + for (InputFile *File : LTO->compile()) { + DenseMap DummyGroups; + auto *Obj = cast>(File); + Obj->parse(DummyGroups); + for (Symbol *Sym : Obj->getGlobalSymbols()) + Sym->parseSymbolVersion(); + ObjectFiles.push_back(File); + } +} + // The --wrap option is a feature to rename symbols so that you can write // wrappers for existing functions. If you pass `-wrap=foo`, all // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are @@ -1645,7 +1668,7 @@ template void LinkerDriver::link(opt::InputArgList &Args) { // // With this the symbol table should be complete. After this, no new names // except a few linker-synthesized ones will be added to the symbol table. - Symtab->addCombinedLTOObject(); + compileBitcodeFiles(); if (errorCount()) return; diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h index 91d52c63723d3..76b91be211951 100644 --- a/lld/ELF/Driver.h +++ b/lld/ELF/Driver.h @@ -9,6 +9,7 @@ #ifndef LLD_ELF_DRIVER_H #define LLD_ELF_DRIVER_H +#include "LTO.h" #include "SymbolTable.h" #include "lld/Common/LLVM.h" #include "lld/Common/Reproduce.h" @@ -33,6 +34,7 @@ class LinkerDriver { void createFiles(llvm::opt::InputArgList &Args); void inferMachineType(); template void link(llvm::opt::InputArgList &Args); + template void compileBitcodeFiles(); // True if we are in --whole-archive and --no-whole-archive. bool InWholeArchive = false; @@ -40,6 +42,9 @@ class LinkerDriver { // True if we are in --start-lib and --end-lib. bool InLib = false; + // For LTO. + std::unique_ptr LTO; + std::vector Files; }; diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index b6d1741f856b2..44fdb96b3e0f8 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -32,29 +32,6 @@ using namespace lld::elf; SymbolTable *elf::Symtab; -// This function is where all the optimizations of link-time -// optimization happens. When LTO is in use, some input files are -// not in native object file format but in the LLVM bitcode format. -// This function compiles bitcode files into a few big native files -// using LLVM functions and replaces bitcode symbols with the results. -// Because all bitcode files that the program consists of are passed -// to the compiler at once, it can do whole-program optimization. -template void SymbolTable::addCombinedLTOObject() { - // Compile bitcode files and replace bitcode symbols. - LTO.reset(new BitcodeCompiler); - for (BitcodeFile *F : BitcodeFiles) - LTO->add(*F); - - for (InputFile *File : LTO->compile()) { - DenseMap DummyGroups; - auto *Obj = cast>(File); - Obj->parse(DummyGroups); - for (Symbol *Sym : Obj->getGlobalSymbols()) - Sym->parseSymbolVersion(); - ObjectFiles.push_back(File); - } -} - // Set a flag for --trace-symbol so that we can print out a log message // if a new symbol with the same name is inserted into the symbol table. void SymbolTable::trace(StringRef Name) { @@ -609,8 +586,3 @@ void elf::resolveSymbol(Symbol *Old, const Symbol &New) { llvm_unreachable("bad symbol kind"); } } - -template void SymbolTable::addCombinedLTOObject(); -template void SymbolTable::addCombinedLTOObject(); -template void SymbolTable::addCombinedLTOObject(); -template void SymbolTable::addCombinedLTOObject(); diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index f77d04516b901..25b73fa5481fe 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -10,7 +10,6 @@ #define LLD_ELF_SYMBOL_TABLE_H #include "InputFiles.h" -#include "LTO.h" #include "lld/Common/Strings.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseMap.h" @@ -40,7 +39,6 @@ class Undefined; // is one add* function per symbol type. class SymbolTable { public: - template void addCombinedLTOObject(); void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap); ArrayRef getSymbols() const { return SymVector; } @@ -92,9 +90,6 @@ class SymbolTable { // can have the same name. We use this map to handle "extern C++ {}" // directive in version scripts. llvm::Optional>> DemangledSyms; - - // For LTO. - std::unique_ptr LTO; }; extern SymbolTable *Symtab; From b9889bbacb4b3cf68838fb54b792435d8d9e341e Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 23 May 2019 09:41:03 +0000 Subject: [PATCH 0006/1176] [WebAssembly] Seal imports section before counting imports Summary: Before we can assign entries in the function of global index space we need to know the total number of function and global imports respectively. To avoid programmer error this change seals that imports section before assigned function and global index space. Any attempt to add an import after the section is sealed will assert. The lack this such as check caused https://reviews.llvm.org/D61876 to be reverted. I'm also trying to craft a test case the this failure. Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62240 llvm-svn: 361470 --- lld/wasm/SyntheticSections.cpp | 11 +++++++---- lld/wasm/SyntheticSections.h | 20 +++++++++++++++++--- lld/wasm/Writer.cpp | 16 +++++++++------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index 6dd68f6f10a1b..198e6dbdffee1 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -92,6 +92,7 @@ void TypeSection::writeBody() { } uint32_t ImportSection::numImports() const { + assert(IsSealed); uint32_t NumImports = ImportedSymbols.size() + GOTSymbols.size(); if (Config->ImportMemory) ++NumImports; @@ -101,6 +102,7 @@ uint32_t ImportSection::numImports() const { } void ImportSection::addGOTEntry(Symbol *Sym) { + assert(!IsSealed); if (Sym->hasGOTIndex()) return; Sym->setGOTIndex(NumImportedGlobals++); @@ -108,6 +110,7 @@ void ImportSection::addGOTEntry(Symbol *Sym) { } void ImportSection::addImport(Symbol *Sym) { + assert(!IsSealed); ImportedSymbols.emplace_back(Sym); if (auto *F = dyn_cast(Sym)) F->setFunctionIndex(NumImportedFunctions++); @@ -202,7 +205,7 @@ void FunctionSection::addFunction(InputFunction *Func) { if (!Func->Live) return; uint32_t FunctionIndex = - Out.ImportSec->NumImportedFunctions + InputFunctions.size(); + Out.ImportSec->numImportedFunctions() + InputFunctions.size(); InputFunctions.emplace_back(Func); Func->setFunctionIndex(FunctionIndex); } @@ -251,7 +254,7 @@ void GlobalSection::addGlobal(InputGlobal *Global) { if (!Global->Live) return; uint32_t GlobalIndex = - Out.ImportSec->NumImportedGlobals + InputGlobals.size(); + Out.ImportSec->numImportedGlobals() + InputGlobals.size(); LLVM_DEBUG(dbgs() << "addGlobal: " << GlobalIndex << "\n"); Global->setGlobalIndex(GlobalIndex); Out.GlobalSec->InputGlobals.push_back(Global); @@ -270,7 +273,7 @@ void EventSection::writeBody() { void EventSection::addEvent(InputEvent *Event) { if (!Event->Live) return; - uint32_t EventIndex = Out.ImportSec->NumImportedEvents + InputEvents.size(); + uint32_t EventIndex = Out.ImportSec->numImportedEvents() + InputEvents.size(); LLVM_DEBUG(dbgs() << "addEvent: " << EventIndex << "\n"); Event->setEventIndex(EventIndex); InputEvents.push_back(Event); @@ -457,7 +460,7 @@ void LinkingSection::addToSymtab(Symbol *Sym) { } unsigned NameSection::numNames() const { - unsigned NumNames = Out.ImportSec->NumImportedFunctions; + unsigned NumNames = Out.ImportSec->numImportedFunctions(); for (const InputFunction *F : Out.FunctionSec->InputFunctions) if (!F->getName().empty() || !F->getDebugName().empty()) ++NumNames; diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h index c897132c35532..ccd66326a2461 100644 --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -101,14 +101,28 @@ class ImportSection : public SyntheticSection { void writeBody() override; void addImport(Symbol *Sym); void addGOTEntry(Symbol *Sym); + void seal() { IsSealed = true; } uint32_t numImports() const; + uint32_t numImportedGlobals() const { + assert(IsSealed); + return NumImportedGlobals; + } + uint32_t numImportedFunctions() const { + assert(IsSealed); + return NumImportedFunctions; + } + uint32_t numImportedEvents() const { + assert(IsSealed); + return NumImportedEvents; + } - unsigned NumImportedGlobals = 0; - unsigned NumImportedFunctions = 0; - unsigned NumImportedEvents = 0; std::vector ImportedSymbols; protected: + bool IsSealed = false; + unsigned NumImportedGlobals = 0; + unsigned NumImportedFunctions = 0; + unsigned NumImportedEvents = 0; std::vector GOTSymbols; }; diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index eb567ecf5c55e..01dbd82dc3549 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -439,7 +439,7 @@ void Writer::calculateExports() { WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0}); unsigned FakeGlobalIndex = - Out.ImportSec->NumImportedGlobals + Out.GlobalSec->InputGlobals.size(); + Out.ImportSec->numImportedGlobals() + Out.GlobalSec->InputGlobals.size(); for (Symbol *Sym : Symtab->getSymbols()) { if (!Sym->isExported()) @@ -532,7 +532,9 @@ static void scanRelocations() { } void Writer::assignIndexes() { - assert(Out.FunctionSec->InputFunctions.empty()); + // Seal the import section, since other index spaces such as function and + // global are effected by the number of imports. + Out.ImportSec->seal(); for (InputFunction *Func : Symtab->SyntheticFunctions) Out.FunctionSec->addFunction(Func); @@ -543,8 +545,6 @@ void Writer::assignIndexes() { Out.FunctionSec->addFunction(Func); } - scanRelocations(); - for (InputGlobal *Global : Symtab->SyntheticGlobals) Out.GlobalSec->addGlobal(Global); @@ -724,6 +724,8 @@ void Writer::run() { populateTargetFeatures(); log("-- calculateImports"); calculateImports(); + log("-- scanRelocations"); + scanRelocations(); log("-- assignIndexes"); assignIndexes(); log("-- calculateInitFunctions"); @@ -750,9 +752,9 @@ void Writer::run() { log("Defined Functions: " + Twine(Out.FunctionSec->InputFunctions.size())); log("Defined Globals : " + Twine(Out.GlobalSec->InputGlobals.size())); log("Defined Events : " + Twine(Out.EventSec->InputEvents.size())); - log("Function Imports : " + Twine(Out.ImportSec->NumImportedFunctions)); - log("Global Imports : " + Twine(Out.ImportSec->NumImportedGlobals)); - log("Event Imports : " + Twine(Out.ImportSec->NumImportedEvents)); + log("Function Imports : " + Twine(Out.ImportSec->numImportedFunctions())); + log("Global Imports : " + Twine(Out.ImportSec->numImportedGlobals())); + log("Event Imports : " + Twine(Out.ImportSec->numImportedEvents())); for (ObjFile *File : Symtab->ObjectFiles) File->dumpInfo(); } From 691502f61e9e6e7de657b21f7c311d1cece3f99b Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 23 May 2019 09:41:39 +0000 Subject: [PATCH 0007/1176] DWARFASTParserClang: Reduce indentation by two levels via early returns. llvm-svn: 361471 --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 3002 ++++++++--------- 1 file changed, 1495 insertions(+), 1507 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 51a37444123c6..15b91f53a80cc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -231,1673 +231,1661 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer, TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, const DWARFDIE &die, Log *log, bool *type_is_new_ptr) { - TypeSP type_sp; - if (type_is_new_ptr) *type_is_new_ptr = false; AccessType accessibility = eAccessNone; - if (die) { - SymbolFileDWARF *dwarf = die.GetDWARF(); - if (log) { - DWARFDIE context_die; - clang::DeclContext *context = - GetClangDeclContextContainingDIE(die, &context_die); - - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die " - "0x%8.8x)) %s name = '%s')", - die.GetOffset(), static_cast(context), - context_die.GetOffset(), die.GetTagAsCString(), die.GetName()); - } - Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); - TypeList *type_list = dwarf->GetTypeList(); - if (type_ptr == NULL) { - if (type_is_new_ptr) - *type_is_new_ptr = true; + if (!die) + return nullptr; - const dw_tag_t tag = die.Tag(); + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (log) { + DWARFDIE context_die; + clang::DeclContext *context = + GetClangDeclContextContainingDIE(die, &context_die); + + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die " + "0x%8.8x)) %s name = '%s')", + die.GetOffset(), static_cast(context), context_die.GetOffset(), + die.GetTagAsCString(), die.GetName()); + } - bool is_forward_declaration = false; - DWARFAttributes attributes; - const char *type_name_cstr = NULL; - const char *mangled_name_cstr = NULL; - ConstString type_name_const_str; - Type::ResolveState resolve_state = Type::eResolveStateUnresolved; - llvm::Optional byte_size; - Declaration decl; - - Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; - CompilerType clang_type; - DWARFFormValue form_value; + Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); + if (type_ptr == DIE_IS_BEING_PARSED) + return nullptr; + if (type_ptr) + return type_ptr->shared_from_this(); - dw_attr_t attr; - - switch (tag) { - case DW_TAG_typedef: - case DW_TAG_base_type: - case DW_TAG_pointer_type: - case DW_TAG_reference_type: - case DW_TAG_rvalue_reference_type: - case DW_TAG_const_type: - case DW_TAG_restrict_type: - case DW_TAG_volatile_type: - case DW_TAG_unspecified_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - - const size_t num_attributes = die.GetAttributes(attributes); - uint32_t encoding = 0; - DWARFFormValue encoding_uid; - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - if (type_name_cstr) - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_encoding: - encoding = form_value.Unsigned(); - break; - case DW_AT_type: - encoding_uid = form_value; - break; - default: - case DW_AT_sibling: - break; - } - } - } - } + TypeList *type_list = dwarf->GetTypeList(); + if (type_is_new_ptr) + *type_is_new_ptr = true; - if (tag == DW_TAG_typedef && encoding_uid.IsValid()) { - // Try to parse a typedef from the DWO file first as modules can - // contain typedef'ed structures that have no names like: - // - // typedef struct { int a; } Foo; - // - // In this case we will have a structure with no name and a typedef - // named "Foo" that points to this unnamed structure. The name in the - // typedef is the only identifier for the struct, so always try to - // get typedefs from DWO files if possible. - // - // The type_sp returned will be empty if the typedef doesn't exist in - // a DWO file, so it is cheap to call this function just to check. - // - // If we don't do this we end up creating a TypeSP that says this is - // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in - // the DW_TAG_typedef), and this is the unnamed structure type. We - // will have a hard time tracking down an unnammed structure type in - // the module DWO file, so we make sure we don't get into this - // situation by always resolving typedefs from the DWO file. - const DWARFDIE encoding_die = encoding_uid.Reference(); + const dw_tag_t tag = die.Tag(); + + bool is_forward_declaration = false; + DWARFAttributes attributes; + const char *type_name_cstr = NULL; + const char *mangled_name_cstr = NULL; + ConstString type_name_const_str; + Type::ResolveState resolve_state = Type::eResolveStateUnresolved; + llvm::Optional byte_size; + Declaration decl; + + Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; + CompilerType clang_type; + DWARFFormValue form_value; + + dw_attr_t attr; + TypeSP type_sp; + switch (tag) { + case DW_TAG_typedef: + case DW_TAG_base_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_const_type: + case DW_TAG_restrict_type: + case DW_TAG_volatile_type: + case DW_TAG_unspecified_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - // First make sure that the die that this is typedef'ed to _is_ just - // a declaration (DW_AT_declaration == 1), not a full definition - // since template types can't be represented in modules since only - // concrete instances of templates are ever emitted and modules won't - // contain those - if (encoding_die && - encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == - 1) { - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; + const size_t num_attributes = die.GetAttributes(attributes); + uint32_t encoding = 0; + DWARFFormValue encoding_uid; + + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_decl_file: + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( + form_value.Unsigned())); + break; + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + if (type_name_cstr) + type_name_const_str.SetCString(type_name_cstr); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_encoding: + encoding = form_value.Unsigned(); + break; + case DW_AT_type: + encoding_uid = form_value; + break; + default: + case DW_AT_sibling: + break; } } + } + } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", - die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, - encoding_uid.Reference()); + if (tag == DW_TAG_typedef && encoding_uid.IsValid()) { + // Try to parse a typedef from the DWO file first as modules can + // contain typedef'ed structures that have no names like: + // + // typedef struct { int a; } Foo; + // + // In this case we will have a structure with no name and a typedef + // named "Foo" that points to this unnamed structure. The name in the + // typedef is the only identifier for the struct, so always try to + // get typedefs from DWO files if possible. + // + // The type_sp returned will be empty if the typedef doesn't exist in + // a DWO file, so it is cheap to call this function just to check. + // + // If we don't do this we end up creating a TypeSP that says this is + // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in + // the DW_TAG_typedef), and this is the unnamed structure type. We + // will have a hard time tracking down an unnammed structure type in + // the module DWO file, so we make sure we don't get into this + // situation by always resolving typedefs from the DWO file. + const DWARFDIE encoding_die = encoding_uid.Reference(); + + // First make sure that the die that this is typedef'ed to _is_ just + // a declaration (DW_AT_declaration == 1), not a full definition + // since template types can't be represented in modules since only + // concrete instances of templates are ever emitted and modules won't + // contain those + if (encoding_die && + encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + } + } - switch (tag) { - default: - break; + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", + die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, + encoding_uid.Reference()); - case DW_TAG_unspecified_type: - if (strcmp(type_name_cstr, "nullptr_t") == 0 || - strcmp(type_name_cstr, "decltype(nullptr)") == 0) { - resolve_state = Type::eResolveStateFull; - clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); - break; - } - // Fall through to base type below in case we can handle the type - // there... - LLVM_FALLTHROUGH; - - case DW_TAG_base_type: - resolve_state = Type::eResolveStateFull; - clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - type_name_cstr, encoding, byte_size.getValueOr(0) * 8); - break; + switch (tag) { + default: + break; - case DW_TAG_pointer_type: - encoding_data_type = Type::eEncodingIsPointerUID; - break; - case DW_TAG_reference_type: - encoding_data_type = Type::eEncodingIsLValueReferenceUID; - break; - case DW_TAG_rvalue_reference_type: - encoding_data_type = Type::eEncodingIsRValueReferenceUID; - break; - case DW_TAG_typedef: - encoding_data_type = Type::eEncodingIsTypedefUID; - break; - case DW_TAG_const_type: - encoding_data_type = Type::eEncodingIsConstUID; - break; - case DW_TAG_restrict_type: - encoding_data_type = Type::eEncodingIsRestrictUID; - break; - case DW_TAG_volatile_type: - encoding_data_type = Type::eEncodingIsVolatileUID; - break; - } + case DW_TAG_unspecified_type: + if (strcmp(type_name_cstr, "nullptr_t") == 0 || + strcmp(type_name_cstr, "decltype(nullptr)") == 0) { + resolve_state = Type::eResolveStateFull; + clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); + break; + } + // Fall through to base type below in case we can handle the type + // there... + LLVM_FALLTHROUGH; + + case DW_TAG_base_type: + resolve_state = Type::eResolveStateFull; + clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( + type_name_cstr, encoding, byte_size.getValueOr(0) * 8); + break; - if (!clang_type && - (encoding_data_type == Type::eEncodingIsPointerUID || - encoding_data_type == Type::eEncodingIsTypedefUID)) { - if (tag == DW_TAG_pointer_type) { - DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type); - - if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) { - // Blocks have a __FuncPtr inside them which is a pointer to a - // function of the proper type. - - for (DWARFDIE child_die = target_die.GetFirstChild(); - child_die.IsValid(); child_die = child_die.GetSibling()) { - if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), - "__FuncPtr")) { - DWARFDIE function_pointer_type = - child_die.GetReferencedDIE(DW_AT_type); - - if (function_pointer_type) { - DWARFDIE function_type = - function_pointer_type.GetReferencedDIE(DW_AT_type); - - bool function_type_is_new_pointer; - TypeSP lldb_function_type_sp = ParseTypeFromDWARF( - sc, function_type, log, &function_type_is_new_pointer); - - if (lldb_function_type_sp) { - clang_type = m_ast.CreateBlockPointerType( - lldb_function_type_sp->GetForwardCompilerType()); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; - } - } + case DW_TAG_pointer_type: + encoding_data_type = Type::eEncodingIsPointerUID; + break; + case DW_TAG_reference_type: + encoding_data_type = Type::eEncodingIsLValueReferenceUID; + break; + case DW_TAG_rvalue_reference_type: + encoding_data_type = Type::eEncodingIsRValueReferenceUID; + break; + case DW_TAG_typedef: + encoding_data_type = Type::eEncodingIsTypedefUID; + break; + case DW_TAG_const_type: + encoding_data_type = Type::eEncodingIsConstUID; + break; + case DW_TAG_restrict_type: + encoding_data_type = Type::eEncodingIsRestrictUID; + break; + case DW_TAG_volatile_type: + encoding_data_type = Type::eEncodingIsVolatileUID; + break; + } - break; + if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || + encoding_data_type == Type::eEncodingIsTypedefUID)) { + if (tag == DW_TAG_pointer_type) { + DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type); + + if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) { + // Blocks have a __FuncPtr inside them which is a pointer to a + // function of the proper type. + + for (DWARFDIE child_die = target_die.GetFirstChild(); + child_die.IsValid(); child_die = child_die.GetSibling()) { + if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), + "__FuncPtr")) { + DWARFDIE function_pointer_type = + child_die.GetReferencedDIE(DW_AT_type); + + if (function_pointer_type) { + DWARFDIE function_type = + function_pointer_type.GetReferencedDIE(DW_AT_type); + + bool function_type_is_new_pointer; + TypeSP lldb_function_type_sp = ParseTypeFromDWARF( + sc, function_type, log, &function_type_is_new_pointer); + + if (lldb_function_type_sp) { + clang_type = m_ast.CreateBlockPointerType( + lldb_function_type_sp->GetForwardCompilerType()); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid.Clear(); + resolve_state = Type::eResolveStateFull; } } + + break; } } + } + } - bool translation_unit_is_objc = - (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || - sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); + bool translation_unit_is_objc = + (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || + sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); - if (translation_unit_is_objc) { - if (type_name_cstr != NULL) { - static ConstString g_objc_type_name_id("id"); - static ConstString g_objc_type_name_Class("Class"); - static ConstString g_objc_type_name_selector("SEL"); + if (translation_unit_is_objc) { + if (type_name_cstr != NULL) { + static ConstString g_objc_type_name_id("id"); + static ConstString g_objc_type_name_Class("Class"); + static ConstString g_objc_type_name_selector("SEL"); - if (type_name_const_str == g_objc_type_name_id) { - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " - "is Objective-C 'id' built-in type.", - die.GetOffset(), die.GetTagAsCString(), die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCID); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; + if (type_name_const_str == g_objc_type_name_id) { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "is Objective-C 'id' built-in type.", + die.GetOffset(), die.GetTagAsCString(), die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCID); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid.Clear(); + resolve_state = Type::eResolveStateFull; - } else if (type_name_const_str == g_objc_type_name_Class) { - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " - "is Objective-C 'Class' built-in type.", - die.GetOffset(), die.GetTagAsCString(), die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; - } else if (type_name_const_str == g_objc_type_name_selector) { + } else if (type_name_const_str == g_objc_type_name_Class) { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "is Objective-C 'Class' built-in type.", + die.GetOffset(), die.GetTagAsCString(), die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid.Clear(); + resolve_state = Type::eResolveStateFull; + } else if (type_name_const_str == g_objc_type_name_selector) { + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " + "is Objective-C 'selector' built-in type.", + die.GetOffset(), die.GetTagAsCString(), die.GetName()); + clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid.Clear(); + resolve_state = Type::eResolveStateFull; + } + } else if (encoding_data_type == Type::eEncodingIsPointerUID && + encoding_uid.IsValid()) { + // Clang sometimes erroneously emits id as objc_object*. In that + // case we fix up the type to "id". + + const DWARFDIE encoding_die = encoding_uid.Reference(); + + if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) { + if (const char *struct_name = encoding_die.GetName()) { + if (!strcmp(struct_name, "objc_object")) { if (log) dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' " - "is Objective-C 'selector' built-in type.", + log, + "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s " + "'%s' is 'objc_object*', which we overrode to " + "'id'.", die.GetOffset(), die.GetTagAsCString(), die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); + clang_type = m_ast.GetBasicType(eBasicTypeObjCID); encoding_data_type = Type::eEncodingIsUID; encoding_uid.Clear(); resolve_state = Type::eResolveStateFull; } - } else if (encoding_data_type == Type::eEncodingIsPointerUID && - encoding_uid.IsValid()) { - // Clang sometimes erroneously emits id as objc_object*. In that - // case we fix up the type to "id". - - const DWARFDIE encoding_die = encoding_uid.Reference(); - - if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) { - if (const char *struct_name = encoding_die.GetName()) { - if (!strcmp(struct_name, "objc_object")) { - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s " - "'%s' is 'objc_object*', which we overrode to " - "'id'.", - die.GetOffset(), die.GetTagAsCString(), - die.GetName()); - clang_type = m_ast.GetBasicType(eBasicTypeObjCID); - encoding_data_type = Type::eEncodingIsUID; - encoding_uid.Clear(); - resolve_state = Type::eResolveStateFull; - } - } - } } } } + } + } - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - dwarf->GetUID(DIERef(encoding_uid)), encoding_data_type, &decl, - clang_type, resolve_state); + type_sp = std::make_shared( + die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, + dwarf->GetUID(DIERef(encoding_uid)), encoding_data_type, &decl, + clang_type, resolve_state); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - } break; + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + } break; - case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_class_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - LanguageType class_language = eLanguageTypeUnknown; - bool is_complete_objc_class = false; - size_t calling_convention - = llvm::dwarf::CallingConvention::DW_CC_normal; - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - - case DW_AT_APPLE_runtime_class: - class_language = (LanguageType)form_value.Signed(); - break; - - case DW_AT_APPLE_objc_complete_type: - is_complete_objc_class = form_value.Signed(); - break; - case DW_AT_calling_convention: - calling_convention = form_value.Unsigned(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - default: - case DW_AT_sibling: - break; - } - } - } - } + LanguageType class_language = eLanguageTypeUnknown; + bool is_complete_objc_class = false; + size_t calling_convention = llvm::dwarf::CallingConvention::DW_CC_normal; - // UniqueDWARFASTType is large, so don't create a local variables on - // the stack, put it on the heap. This function is often called - // recursively and clang isn't good and sharing the stack space for - // variables in different blocks. - std::unique_ptr unique_ast_entry_up( - new UniqueDWARFASTType()); - - ConstString unique_typename(type_name_const_str); - Declaration unique_decl(decl); - - if (type_name_const_str) { - LanguageType die_language = die.GetLanguage(); - if (Language::LanguageIsCPlusPlus(die_language)) { - // For C++, we rely solely upon the one definition rule that says - // only one thing can exist at a given decl context. We ignore the - // file and line that things are declared on. - std::string qualified_name; - if (die.GetQualifiedName(qualified_name)) - unique_typename = ConstString(qualified_name); - unique_decl.Clear(); - } + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_decl_file: + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( + form_value.Unsigned())); + break; - if (dwarf->GetUniqueDWARFASTTypeMap().Find( - unique_typename, die, unique_decl, - byte_size ? *byte_size : -1, *unique_ast_entry_up)) { - type_sp = unique_ast_entry_up->m_type_sp; - if (type_sp) { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - } + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; - int tag_decl_kind = -1; - AccessType default_accessibility = eAccessNone; - if (tag == DW_TAG_structure_type) { - tag_decl_kind = clang::TTK_Struct; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_union_type) { - tag_decl_kind = clang::TTK_Union; - default_accessibility = eAccessPublic; - } else if (tag == DW_TAG_class_type) { - tag_decl_kind = clang::TTK_Class; - default_accessibility = eAccessPrivate; - } + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + + case DW_AT_accessibility: + accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); + break; + + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + + case DW_AT_APPLE_runtime_class: + class_language = (LanguageType)form_value.Signed(); + break; + + case DW_AT_APPLE_objc_complete_type: + is_complete_objc_class = form_value.Signed(); + break; + case DW_AT_calling_convention: + calling_convention = form_value.Unsigned(); + break; - if (byte_size && *byte_size == 0 && type_name_cstr && - !die.HasChildren() && - sc.comp_unit->GetLanguage() == eLanguageTypeObjC) { - // Work around an issue with clang at the moment where forward - // declarations for objective C classes are emitted as: - // DW_TAG_structure_type [2] - // DW_AT_name( "ForwardObjcClass" ) - // DW_AT_byte_size( 0x00 ) - // DW_AT_decl_file( "..." ) - // DW_AT_decl_line( 1 ) - // - // Note that there is no DW_AT_declaration and there are no children, - // and the byte size is zero. - is_forward_declaration = true; + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_description: + case DW_AT_start_scope: + case DW_AT_visibility: + default: + case DW_AT_sibling: + break; + } } + } + } - if (class_language == eLanguageTypeObjC || - class_language == eLanguageTypeObjC_plus_plus) { - if (!is_complete_objc_class && - die.Supports_DW_AT_APPLE_objc_complete_type()) { - // We have a valid eSymbolTypeObjCClass class symbol whose name - // matches the current objective C class that we are trying to find - // and this DIE isn't the complete definition (we checked - // is_complete_objc_class above and know it is false), so the real - // definition is in here somewhere - type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE( - die, type_name_const_str, true); + // UniqueDWARFASTType is large, so don't create a local variables on + // the stack, put it on the heap. This function is often called + // recursively and clang isn't good and sharing the stack space for + // variables in different blocks. + std::unique_ptr unique_ast_entry_up( + new UniqueDWARFASTType()); + + ConstString unique_typename(type_name_const_str); + Declaration unique_decl(decl); + + if (type_name_const_str) { + LanguageType die_language = die.GetLanguage(); + if (Language::LanguageIsCPlusPlus(die_language)) { + // For C++, we rely solely upon the one definition rule that says + // only one thing can exist at a given decl context. We ignore the + // file and line that things are declared on. + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + unique_typename = ConstString(qualified_name); + unique_decl.Clear(); + } - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = - debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( - die, type_name_const_str, true); - } - } + if (dwarf->GetUniqueDWARFASTTypeMap().Find( + unique_typename, die, unique_decl, byte_size ? *byte_size : -1, + *unique_ast_entry_up)) { + type_sp = unique_ast_entry_up->m_type_sp; + if (type_sp) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " - "incomplete objc type, complete type is 0x%8.8" PRIx64, - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, - type_sp->GetID()); - } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + int tag_decl_kind = -1; + AccessType default_accessibility = eAccessNone; + if (tag == DW_TAG_structure_type) { + tag_decl_kind = clang::TTK_Struct; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_union_type) { + tag_decl_kind = clang::TTK_Union; + default_accessibility = eAccessPublic; + } else if (tag == DW_TAG_class_type) { + tag_decl_kind = clang::TTK_Class; + default_accessibility = eAccessPrivate; + } - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } + if (byte_size && *byte_size == 0 && type_name_cstr && !die.HasChildren() && + sc.comp_unit->GetLanguage() == eLanguageTypeObjC) { + // Work around an issue with clang at the moment where forward + // declarations for objective C classes are emitted as: + // DW_TAG_structure_type [2] + // DW_AT_name( "ForwardObjcClass" ) + // DW_AT_byte_size( 0x00 ) + // DW_AT_decl_file( "..." ) + // DW_AT_decl_line( 1 ) + // + // Note that there is no DW_AT_declaration and there are no children, + // and the byte size is zero. + is_forward_declaration = true; + } + + if (class_language == eLanguageTypeObjC || + class_language == eLanguageTypeObjC_plus_plus) { + if (!is_complete_objc_class && + die.Supports_DW_AT_APPLE_objc_complete_type()) { + // We have a valid eSymbolTypeObjCClass class symbol whose name + // matches the current objective C class that we are trying to find + // and this DIE isn't the complete definition (we checked + // is_complete_objc_class above and know it is false), so the real + // definition is in here somewhere + type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE( + die, type_name_const_str, true); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE( + die, type_name_const_str, true); } } - if (is_forward_declaration) { - // We have a forward declaration to a type and we need to try and - // find a full declaration. We look in the current type index just in - // case we have a forward declaration followed by an actual - // declarations in the DWARF. If this fails, we need to look - // elsewhere... + if (type_sp) { if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, trying to find complete type", + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an " + "incomplete objc type, complete type is 0x%8.8" PRIx64, static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr); + DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); } - // See if the type comes from a DWO module and if so, track down that - // type. - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, - // type_name_const_str); - type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, see - // if we have a declaration anywhere else... - type_sp = - debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + } - if (type_sp) { + if (is_forward_declaration) { + // We have a forward declaration to a type and we need to try and + // find a full declaration. We look in the current type index just in + // case we have a forward declaration followed by an actual + // declarations in the DWARF. If this fails, we need to look + // elsewhere... + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, trying to find complete type", + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), type_name_cstr); + } + + // See if the type comes from a DWO module and if so, track down that + // type. + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + // type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, + // type_name_const_str); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, see + // if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); + } + } + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); + } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + assert(tag_decl_kind != -1); + bool clang_type_was_created = false; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + clang::DeclContext *decl_ctx = + GetClangDeclContextContainingDIE(die, nullptr); + + // If your decl context is a record that was imported from another + // AST context (in the gmodules case), we need to make sure the type + // backing the Decl is complete before adding children to it. This is + // not an issue in the non-gmodules case because the debug info will + // always contain a full definition of parent types in that case. + CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, + type_name_cstr); + + if (accessibility == eAccessNone && decl_ctx) { + // Check the decl context that contains this class/struct/union. If + // it is a class we must give it an accessibility. + const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); + if (DeclKindIsCXXClass(containing_decl_kind)) + accessibility = default_accessibility; + } + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + + if (type_name_cstr && strchr(type_name_cstr, '<')) { + ClangASTContext::TemplateParameterInfos template_param_infos; + if (ParseTemplateParameterInfos(die, template_param_infos)) { + clang::ClassTemplateDecl *class_template_decl = + m_ast.ParseClassTemplateDecl(decl_ctx, accessibility, + type_name_cstr, tag_decl_kind, + template_param_infos); + if (!class_template_decl) { if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " + "clang::ClassTemplateDecl failed to return a decl.", static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); + DW_TAG_value_to_name(tag), type_name_cstr); } - - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE( - dwarf->GetDIE(type_sp->GetID())); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; + return TypeSP(); } + + clang::ClassTemplateSpecializationDecl *class_specialization_decl = + m_ast.CreateClassTemplateSpecializationDecl( + decl_ctx, class_template_decl, tag_decl_kind, + template_param_infos); + clang_type = m_ast.CreateClassTemplateSpecializationType( + class_specialization_decl); + clang_type_was_created = true; + + m_ast.SetMetadata(class_template_decl, metadata); + m_ast.SetMetadata(class_specialization_decl, metadata); } - assert(tag_decl_kind != -1); - bool clang_type_was_created = false; - clang_type.SetCompilerType( - &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - clang::DeclContext *decl_ctx = - GetClangDeclContextContainingDIE(die, nullptr); - - // If your decl context is a record that was imported from another - // AST context (in the gmodules case), we need to make sure the type - // backing the Decl is complete before adding children to it. This is - // not an issue in the non-gmodules case because the debug info will - // always contain a full definition of parent types in that case. - CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, - type_name_cstr); - - if (accessibility == eAccessNone && decl_ctx) { - // Check the decl context that contains this class/struct/union. If - // it is a class we must give it an accessibility. - const clang::Decl::Kind containing_decl_kind = - decl_ctx->getDeclKind(); - if (DeclKindIsCXXClass(containing_decl_kind)) - accessibility = default_accessibility; - } + } - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual(die)); + if (!clang_type_was_created) { + clang_type_was_created = true; + clang_type = + m_ast.CreateRecordType(decl_ctx, accessibility, type_name_cstr, + tag_decl_kind, class_language, &metadata); + } + } - if (type_name_cstr && strchr(type_name_cstr, '<')) { - ClangASTContext::TemplateParameterInfos template_param_infos; - if (ParseTemplateParameterInfos(die, template_param_infos)) { - clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, accessibility, - type_name_cstr, tag_decl_kind, - template_param_infos); - if (!class_template_decl) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" " - "clang::ClassTemplateDecl failed to return a decl.", - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr); - } - return TypeSP(); - } - - clang::ClassTemplateSpecializationDecl - *class_specialization_decl = - m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, class_template_decl, tag_decl_kind, - template_param_infos); - clang_type = m_ast.CreateClassTemplateSpecializationType( - class_specialization_decl); - clang_type_was_created = true; - - m_ast.SetMetadata(class_template_decl, metadata); - m_ast.SetMetadata(class_specialization_decl, metadata); - } - } + // Store a forward declaration to this class type in case any + // parameters in any class methods need it for the clang types for + // function prototypes. + LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + type_sp = std::make_shared(die.GetID(), dwarf, type_name_const_str, + byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &decl, clang_type, + Type::eResolveStateForward); + + type_sp->SetIsCompleteObjCClass(is_complete_objc_class); + + // Add our type to the unique type map so we don't end up creating many + // copies of the same type over and over in the ASTContext for our + // module + unique_ast_entry_up->m_type_sp = type_sp; + unique_ast_entry_up->m_die = die; + unique_ast_entry_up->m_declaration = unique_decl; + unique_ast_entry_up->m_byte_size = byte_size.getValueOr(0); + dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, + *unique_ast_entry_up); + + if (is_forward_declaration && die.HasChildren()) { + // Check to see if the DIE actually has a definition, some version of + // GCC will + // emit DIEs with DW_AT_declaration set to true, but yet still have + // subprogram, members, or inheritance, so we can't trust it + DWARFDIE child_die = die.GetFirstChild(); + while (child_die) { + switch (child_die.Tag()) { + case DW_TAG_inheritance: + case DW_TAG_subprogram: + case DW_TAG_member: + case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + child_die.Clear(); + is_forward_declaration = false; + break; + default: + child_die = child_die.GetSibling(); + break; + } + } + } + + if (!is_forward_declaration) { + // Always start the definition for a class type so that if the class + // has child classes or types that require the class to be created + // for use as their decl contexts the class will be ready to accept + // these child definitions. + if (!die.HasChildren()) { + // No children for this struct/union/class, lets finish it + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), type_name_cstr); + } + + if (tag == DW_TAG_structure_type) // this only applies in C + { + clang::RecordDecl *record_decl = + ClangASTContext::GetAsRecordDecl(clang_type); - if (!clang_type_was_created) { - clang_type_was_created = true; - clang_type = m_ast.CreateRecordType(decl_ctx, accessibility, - type_name_cstr, tag_decl_kind, - class_language, &metadata); + if (record_decl) { + GetClangASTImporter().InsertRecordDecl( + record_decl, ClangASTImporter::LayoutInfo()); } } - - // Store a forward declaration to this class type in case any - // parameters in any class methods need it for the clang types for - // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, clang_type, - Type::eResolveStateForward); + } else if (clang_type_was_created) { + // Start the definition if the class is not objective C since the + // underlying decls respond to isCompleteDefinition(). Objective + // C decls don't respond to isCompleteDefinition() so we can't + // start the declaration definition right away. For C++ + // class/union/structs we want to start the definition in case the + // class is needed as the declaration context for a contained class + // or type without the need to complete that type.. + + if (class_language != eLanguageTypeObjC && + class_language != eLanguageTypeObjC_plus_plus) + ClangASTContext::StartTagDeclarationDefinition(clang_type); - type_sp->SetIsCompleteObjCClass(is_complete_objc_class); - - // Add our type to the unique type map so we don't end up creating many - // copies of the same type over and over in the ASTContext for our - // module - unique_ast_entry_up->m_type_sp = type_sp; - unique_ast_entry_up->m_die = die; - unique_ast_entry_up->m_declaration = unique_decl; - unique_ast_entry_up->m_byte_size = byte_size.getValueOr(0); - dwarf->GetUniqueDWARFASTTypeMap().Insert(unique_typename, - *unique_ast_entry_up); - - if (is_forward_declaration && die.HasChildren()) { - // Check to see if the DIE actually has a definition, some version of - // GCC will - // emit DIEs with DW_AT_declaration set to true, but yet still have - // subprogram, members, or inheritance, so we can't trust it - DWARFDIE child_die = die.GetFirstChild(); - while (child_die) { - switch (child_die.Tag()) { - case DW_TAG_inheritance: - case DW_TAG_subprogram: - case DW_TAG_member: - case DW_TAG_APPLE_property: - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_enumeration_type: - case DW_TAG_typedef: - case DW_TAG_union_type: - child_die.Clear(); - is_forward_declaration = false; - break; - default: - child_die = child_die.GetSibling(); - break; - } + // Leave this as a forward declaration until we need to know the + // details of the type. lldb_private::Type will automatically call + // the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" When the definition + // needs to be defined. + assert(!dwarf->GetForwardDeclClangTypeToDie().count( + ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()) && + "Type already in the forward declaration map!"); + // Can't assume m_ast.GetSymbolFile() is actually a + // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple + // binaries. + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = + clang_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie() + [ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = + die.GetDIERef(); + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + } + } + + // If we made a clang type, set the trivial abi if applicable: We only + // do this for pass by value - which implies the Trivial ABI. There + // isn't a way to assert that something that would normally be pass by + // value is pass by reference, so we ignore that attribute if set. + if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) { + record_decl->setHasTrivialSpecialMemberForCall(); + } + } + + if (calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + record_decl->setArgPassingRestrictions( + clang::RecordDecl::APK_CannotPassInRegs); + } + + } break; + + case DW_TAG_enumeration_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + bool is_scoped = false; + DWARFFormValue encoding_form; + + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + uint32_t i; + + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_decl_file: + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( + form_value.Unsigned())); + break; + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + case DW_AT_type: + encoding_form = form_value; + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_accessibility: + break; // accessibility = + // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + case DW_AT_enum_class: + is_scoped = form_value.Boolean(); + break; + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_bit_stride: + case DW_AT_byte_stride: + case DW_AT_data_location: + case DW_AT_description: + case DW_AT_start_scope: + case DW_AT_visibility: + case DW_AT_specification: + case DW_AT_abstract_origin: + case DW_AT_sibling: + break; } } + } - if (!is_forward_declaration) { - // Always start the definition for a class type so that if the class - // has child classes or types that require the class to be created - // for use as their decl contexts the class will be ready to accept - // these child definitions. - if (!die.HasChildren()) { - // No children for this struct/union/class, lets finish it - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), type_name_cstr); - } + if (is_forward_declaration) { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; - if (tag == DW_TAG_structure_type) // this only applies in C - { - clang::RecordDecl *record_decl = - ClangASTContext::GetAsRecordDecl(clang_type); + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); - if (record_decl) { - GetClangASTImporter().InsertRecordDecl( - record_decl, ClangASTImporter::LayoutInfo()); - } - } - } else if (clang_type_was_created) { - // Start the definition if the class is not objective C since the - // underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ - // class/union/structs we want to start the definition in case the - // class is needed as the declaration context for a contained class - // or type without the need to complete that type.. - - if (class_language != eLanguageTypeObjC && - class_language != eLanguageTypeObjC_plus_plus) - ClangASTContext::StartTagDeclarationDefinition(clang_type); - - // Leave this as a forward declaration until we need to know the - // details of the type. lldb_private::Type will automatically call - // the SymbolFile virtual function - // "SymbolFileDWARF::CompleteType(Type *)" When the definition - // needs to be defined. - assert(!dwarf->GetForwardDeclClangTypeToDie().count( - ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()) && - "Type already in the forward declaration map!"); - // Can't assume m_ast.GetSymbolFile() is actually a - // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple - // binaries. - dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = - clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie() - [ClangUtil::RemoveFastQualifiers(clang_type) - .GetOpaqueQualType()] = die.GetDIERef(); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + + if (!type_sp) { + SymbolFileDWARFDebugMap *debug_map_symfile = + dwarf->GetDebugMapSymfile(); + if (debug_map_symfile) { + // We weren't able to find a full declaration in this DWARF, + // see if we have a declaration anywhere else... + type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( + die_decl_ctx); } } - - // If we made a clang type, set the trivial abi if applicable: We only - // do this for pass by value - which implies the Trivial ABI. There - // isn't a way to assert that something that would normally be pass by - // value is pass by reference, so we ignore that attribute if set. - if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) { - record_decl->setHasTrivialSpecialMemberForCall(); + + if (type_sp) { + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " + "forward declaration, complete type is 0x%8.8" PRIx64, + static_cast(this), die.GetOffset(), + DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID()); } + + // We found a real definition for this type elsewhere so lets use + // it and cache the fact that we found a complete type for this + // die + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + clang::DeclContext *defn_decl_ctx = + GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID())); + if (defn_decl_ctx) + LinkDeclContextToDIE(defn_decl_ctx, die); + return type_sp; + } + } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + CompilerType enumerator_clang_type; + clang_type.SetCompilerType( + &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!clang_type) { + if (encoding_form.IsValid()) { + Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form)); + if (enumerator_type) + enumerator_clang_type = enumerator_type->GetFullCompilerType(); } - if (calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) - record_decl->setArgPassingRestrictions( - clang::RecordDecl::APK_CannotPassInRegs); + if (!enumerator_clang_type) { + if (byte_size) { + enumerator_clang_type = + m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( + NULL, DW_ATE_signed, *byte_size * 8); + } else { + enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); + } } - } break; + clang_type = m_ast.CreateEnumerationType( + type_name_cstr, GetClangDeclContextContainingDIE(die, nullptr), + decl, enumerator_clang_type, is_scoped); + } else { + enumerator_clang_type = + m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); + } - case DW_TAG_enumeration_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), + die); - bool is_scoped = false; - DWARFFormValue encoding_form; + type_sp = std::make_shared( + die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, + dwarf->GetUID(DIERef(encoding_form)), Type::eEncodingIsUID, &decl, + clang_type, Type::eResolveStateForward); - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_type: - encoding_form = form_value; - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_accessibility: - break; // accessibility = - // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: - is_forward_declaration = form_value.Boolean(); - break; - case DW_AT_enum_class: - is_scoped = form_value.Boolean(); - break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_bit_stride: - case DW_AT_byte_stride: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } - } + if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { + if (die.HasChildren()) { + SymbolContext cu_sc(die.GetLLDBCompileUnit()); + bool is_signed = false; + enumerator_clang_type.IsIntegerType(is_signed); + ParseChildEnumerators(cu_sc, clang_type, is_signed, + type_sp->GetByteSize().getValueOr(0), die); + } + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " + "definition.\nPlease file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), type_name_cstr); + } + } + } break; - if (is_forward_declaration) { - type_sp = ParseTypeFromDWO(die, log); - if (type_sp) - return type_sp; - - DWARFDeclContext die_decl_ctx; - die.GetDWARFDeclContext(die_decl_ctx); - - type_sp = - dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); - - if (!type_sp) { - SymbolFileDWARFDebugMap *debug_map_symfile = - dwarf->GetDebugMapSymfile(); - if (debug_map_symfile) { - // We weren't able to find a full declaration in this DWARF, - // see if we have a declaration anywhere else... - type_sp = - debug_map_symfile->FindDefinitionTypeForDWARFDeclContext( - die_decl_ctx); - } - } + case DW_TAG_inlined_subroutine: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + DWARFFormValue type_die_form; + bool is_variadic = false; + bool is_inline = false; + bool is_static = false; + bool is_virtual = false; + bool is_explicit = false; + bool is_artificial = false; + bool has_template_params = false; + DWARFFormValue specification_die_form; + DWARFFormValue abstract_origin_die_form; + DWARFDIE object_pointer_die; + + unsigned type_quals = 0; + clang::StorageClass storage = + clang::SC_None; //, Extern, Static, PrivateExtern - if (type_sp) { - if (log) { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a " - "forward declaration, complete type is 0x%8.8" PRIx64, - static_cast(this), die.GetOffset(), - DW_TAG_value_to_name(tag), type_name_cstr, - type_sp->GetID()); - } + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_decl_file: + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( + form_value.Unsigned())); + break; + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; - // We found a real definition for this type elsewhere so lets use - // it and cache the fact that we found a complete type for this - // die - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - clang::DeclContext *defn_decl_ctx = - GetCachedClangDeclContextForDIE( - dwarf->GetDIE(type_sp->GetID())); - if (defn_decl_ctx) - LinkDeclContextToDIE(defn_decl_ctx, die); - return type_sp; - } - } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - CompilerType enumerator_clang_type; - clang_type.SetCompilerType( - &m_ast, - dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); - if (!clang_type) { - if (encoding_form.IsValid()) { - Type *enumerator_type = - dwarf->ResolveTypeUID(DIERef(encoding_form)); - if (enumerator_type) - enumerator_clang_type = enumerator_type->GetFullCompilerType(); - } + case DW_AT_linkage_name: + case DW_AT_MIPS_linkage_name: + mangled_name_cstr = form_value.AsCString(); + break; + case DW_AT_type: + type_die_form = form_value; + break; + case DW_AT_accessibility: + accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); + break; + case DW_AT_declaration: + break; // is_forward_declaration = form_value.Boolean(); break; + case DW_AT_inline: + is_inline = form_value.Boolean(); + break; + case DW_AT_virtuality: + is_virtual = form_value.Boolean(); + break; + case DW_AT_explicit: + is_explicit = form_value.Boolean(); + break; + case DW_AT_artificial: + is_artificial = form_value.Boolean(); + break; - if (!enumerator_clang_type) { - if (byte_size) { - enumerator_clang_type = - m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize( - NULL, DW_ATE_signed, *byte_size * 8); - } else { - enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); - } + case DW_AT_external: + if (form_value.Unsigned()) { + if (storage == clang::SC_None) + storage = clang::SC_Extern; + else + storage = clang::SC_PrivateExtern; } + break; - clang_type = m_ast.CreateEnumerationType( - type_name_cstr, GetClangDeclContextContainingDIE(die, nullptr), - decl, enumerator_clang_type, is_scoped); - } else { - enumerator_clang_type = - m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()); - } + case DW_AT_specification: + specification_die_form = form_value; + break; - LinkDeclContextToDIE( - ClangASTContext::GetDeclContextForType(clang_type), die); - - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - dwarf->GetUID(DIERef(encoding_form)), Type::eEncodingIsUID, &decl, - clang_type, Type::eResolveStateForward); - - if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) { - if (die.HasChildren()) { - SymbolContext cu_sc(die.GetLLDBCompileUnit()); - bool is_signed = false; - enumerator_clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(cu_sc, clang_type, is_signed, - type_sp->GetByteSize().getValueOr(0), die); - } - ClangASTContext::CompleteTagDeclarationDefinition(clang_type); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its " - "definition.\nPlease file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), type_name_cstr); + case DW_AT_abstract_origin: + abstract_origin_die_form = form_value; + break; + + case DW_AT_object_pointer: + object_pointer_die = form_value.Reference(); + break; + + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_address_class: + case DW_AT_calling_convention: + case DW_AT_data_location: + case DW_AT_elemental: + case DW_AT_entry_pc: + case DW_AT_frame_base: + case DW_AT_high_pc: + case DW_AT_low_pc: + case DW_AT_prototyped: + case DW_AT_pure: + case DW_AT_ranges: + case DW_AT_recursive: + case DW_AT_return_addr: + case DW_AT_segment: + case DW_AT_start_scope: + case DW_AT_static_link: + case DW_AT_trampoline: + case DW_AT_visibility: + case DW_AT_vtable_elem_location: + case DW_AT_description: + case DW_AT_sibling: + break; } } - } break; + } + } - case DW_TAG_inlined_subroutine: - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + std::string object_pointer_name; + if (object_pointer_die) { + const char *object_pointer_name_cstr = object_pointer_die.GetName(); + if (object_pointer_name_cstr) + object_pointer_name = object_pointer_name_cstr; + } - DWARFFormValue type_die_form; - bool is_variadic = false; - bool is_inline = false; - bool is_static = false; - bool is_virtual = false; - bool is_explicit = false; - bool is_artificial = false; - bool has_template_params = false; - DWARFFormValue specification_die_form; - DWARFFormValue abstract_origin_die_form; - DWARFDIE object_pointer_die; + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); - unsigned type_quals = 0; - clang::StorageClass storage = - clang::SC_None; //, Extern, Static, PrivateExtern - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_linkage_name: - case DW_AT_MIPS_linkage_name: - mangled_name_cstr = form_value.AsCString(); - break; - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_accessibility: - accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); - break; - case DW_AT_declaration: - break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_inline: - is_inline = form_value.Boolean(); - break; - case DW_AT_virtuality: - is_virtual = form_value.Boolean(); - break; - case DW_AT_explicit: - is_explicit = form_value.Boolean(); - break; - case DW_AT_artificial: - is_artificial = form_value.Boolean(); - break; - - case DW_AT_external: - if (form_value.Unsigned()) { - if (storage == clang::SC_None) - storage = clang::SC_Extern; - else - storage = clang::SC_PrivateExtern; - } - break; - - case DW_AT_specification: - specification_die_form = form_value; - break; - - case DW_AT_abstract_origin: - abstract_origin_die_form = form_value; - break; - - case DW_AT_object_pointer: - object_pointer_die = form_value.Reference(); - break; - - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_address_class: - case DW_AT_calling_convention: - case DW_AT_data_location: - case DW_AT_elemental: - case DW_AT_entry_pc: - case DW_AT_frame_base: - case DW_AT_high_pc: - case DW_AT_low_pc: - case DW_AT_prototyped: - case DW_AT_pure: - case DW_AT_ranges: - case DW_AT_recursive: - case DW_AT_return_addr: - case DW_AT_segment: - case DW_AT_start_scope: - case DW_AT_static_link: - case DW_AT_trampoline: - case DW_AT_visibility: - case DW_AT_vtable_elem_location: - case DW_AT_description: - case DW_AT_sibling: - break; - } - } - } - } + CompilerType return_clang_type; + Type *func_type = NULL; - std::string object_pointer_name; - if (object_pointer_die) { - const char *object_pointer_name_cstr = object_pointer_die.GetName(); - if (object_pointer_name_cstr) - object_pointer_name = object_pointer_name_cstr; - } + if (type_die_form.IsValid()) + func_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + if (func_type) + return_clang_type = func_type->GetForwardCompilerType(); + else + return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); - CompilerType return_clang_type; - Type *func_type = NULL; + std::vector function_param_types; + std::vector function_param_decls; - if (type_die_form.IsValid()) - func_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); + // Parse the function children for the parameters - if (func_type) - return_clang_type = func_type->GetForwardCompilerType(); - else - return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); + DWARFDIE decl_ctx_die; + clang::DeclContext *containing_decl_ctx = + GetClangDeclContextContainingDIE(die, &decl_ctx_die); + const clang::Decl::Kind containing_decl_kind = + containing_decl_ctx->getDeclKind(); - std::vector function_param_types; - std::vector function_param_decls; + bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind); + // Start off static. This will be set to false in + // ParseChildParameters(...) if we find a "this" parameters as the + // first parameter + if (is_cxx_method) { + is_static = true; + } - // Parse the function children for the parameters + if (die.HasChildren()) { + bool skip_artificial = true; + ParseChildParameters(*sc.comp_unit, containing_decl_ctx, die, + skip_artificial, is_static, is_variadic, + has_template_params, function_param_types, + function_param_decls, type_quals); + } - DWARFDIE decl_ctx_die; - clang::DeclContext *containing_decl_ctx = - GetClangDeclContextContainingDIE(die, &decl_ctx_die); - const clang::Decl::Kind containing_decl_kind = - containing_decl_ctx->getDeclKind(); - - bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind); - // Start off static. This will be set to false in - // ParseChildParameters(...) if we find a "this" parameters as the - // first parameter - if (is_cxx_method) { - is_static = true; - } + bool ignore_containing_context = false; + // Check for templatized class member functions. If we had any + // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter + // the DW_TAG_subprogram DIE, then we can't let this become a method in + // a class. Why? Because templatized functions are only emitted if one + // of the templatized methods is used in the current compile unit and + // we will end up with classes that may or may not include these member + // functions and this means one class won't match another class + // definition and it affects our ability to use a class in the clang + // expression parser. So for the greater good, we currently must not + // allow any template member functions in a class definition. + if (is_cxx_method && has_template_params) { + ignore_containing_context = true; + is_cxx_method = false; + } - if (die.HasChildren()) { - bool skip_artificial = true; - ParseChildParameters(*sc.comp_unit, containing_decl_ctx, die, - skip_artificial, is_static, is_variadic, - has_template_params, function_param_types, - function_param_decls, type_quals); - } + // clang_type will get the function prototype clang type after this + // call + clang_type = m_ast.CreateFunctionType( + return_clang_type, function_param_types.data(), + function_param_types.size(), is_variadic, type_quals); + + if (type_name_cstr) { + bool type_handled = false; + if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { + ObjCLanguage::MethodName objc_method(type_name_cstr, true); + if (objc_method.IsValid(true)) { + CompilerType class_opaque_type; + ConstString class_name(objc_method.GetClassName()); + if (class_name) { + TypeSP complete_objc_class_type_sp( + dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(), + class_name, false)); + + if (complete_objc_class_type_sp) { + CompilerType type_clang_forward_type = + complete_objc_class_type_sp->GetForwardCompilerType(); + if (ClangASTContext::IsObjCObjectOrInterfaceType( + type_clang_forward_type)) + class_opaque_type = type_clang_forward_type; + } + } - bool ignore_containing_context = false; - // Check for templatized class member functions. If we had any - // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter - // the DW_TAG_subprogram DIE, then we can't let this become a method in - // a class. Why? Because templatized functions are only emitted if one - // of the templatized methods is used in the current compile unit and - // we will end up with classes that may or may not include these member - // functions and this means one class won't match another class - // definition and it affects our ability to use a class in the clang - // expression parser. So for the greater good, we currently must not - // allow any template member functions in a class definition. - if (is_cxx_method && has_template_params) { - ignore_containing_context = true; - is_cxx_method = false; - } + if (class_opaque_type) { + // If accessibility isn't set to anything valid, assume public + // for now... + if (accessibility == eAccessNone) + accessibility = eAccessPublic; - // clang_type will get the function prototype clang type after this - // call - clang_type = m_ast.CreateFunctionType( - return_clang_type, function_param_types.data(), - function_param_types.size(), is_variadic, type_quals); - - if (type_name_cstr) { - bool type_handled = false; - if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) { - ObjCLanguage::MethodName objc_method(type_name_cstr, true); - if (objc_method.IsValid(true)) { - CompilerType class_opaque_type; - ConstString class_name(objc_method.GetClassName()); - if (class_name) { - TypeSP complete_objc_class_type_sp( - dwarf->FindCompleteObjCDefinitionTypeForDIE( - DWARFDIE(), class_name, false)); - - if (complete_objc_class_type_sp) { - CompilerType type_clang_forward_type = - complete_objc_class_type_sp->GetForwardCompilerType(); - if (ClangASTContext::IsObjCObjectOrInterfaceType( - type_clang_forward_type)) - class_opaque_type = type_clang_forward_type; + clang::ObjCMethodDecl *objc_method_decl = + m_ast.AddMethodToObjCObjectType( + class_opaque_type, type_name_cstr, clang_type, + accessibility, is_artificial, is_variadic); + type_handled = objc_method_decl != NULL; + if (type_handled) { + LinkDeclContextToDIE( + ClangASTContext::GetAsDeclContext(objc_method_decl), die); + m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); + } else { + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " + "please file a bug and attach the file at the start of " + "this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + } + } + } else if (is_cxx_method) { + // Look at the parent of this DIE and see if is is a class or + // struct and see if this is actually a C++ method + Type *class_type = dwarf->ResolveType(decl_ctx_die); + if (class_type) { + bool alternate_defn = false; + if (class_type->GetID() != decl_ctx_die.GetID() || + decl_ctx_die.GetContainingDWOModuleDIE()) { + alternate_defn = true; + + // We uniqued the parent class of this function to another + // class so we now need to associate all dies under + // "decl_ctx_die" to DIEs in the DIE for "class_type"... + DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); + + if (class_type_die) { + std::vector failures; + + CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, + class_type, failures); + + // FIXME do something with these failures that's smarter + // than + // just dropping them on the ground. Unfortunately classes + // don't like having stuff added to them after their + // definitions are complete... + + type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + type_sp = type_ptr->shared_from_this(); + break; } } + } - if (class_opaque_type) { - // If accessibility isn't set to anything valid, assume public - // for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - - clang::ObjCMethodDecl *objc_method_decl = - m_ast.AddMethodToObjCObjectType( - class_opaque_type, type_name_cstr, clang_type, - accessibility, is_artificial, is_variadic); - type_handled = objc_method_decl != NULL; - if (type_handled) { - LinkDeclContextToDIE( - ClangASTContext::GetAsDeclContext(objc_method_decl), die); - m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID()); - } else { - dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), " - "please file a bug and attach the file at the start of " - "this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - } + if (specification_die_form.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the specification has a valid clang decl context. + class_type->GetForwardCompilerType(); + // If we have a specification, then the function type should + // have been made with the specification and not with this + // die. + DWARFDIE spec_die = + dwarf->DebugInfo()->GetDIE(DIERef(specification_die_form)); + clang::DeclContext *spec_clang_decl_ctx = + GetClangDeclContextForDIE(spec_die); + if (spec_clang_decl_ctx) { + LinkDeclContextToDIE(spec_clang_decl_ctx, die); + } else { + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" + ") has no decl\n", + die.GetID(), + specification_die_form.Reference().GetOffset()); } - } else if (is_cxx_method) { - // Look at the parent of this DIE and see if is is a class or - // struct and see if this is actually a C++ method - Type *class_type = dwarf->ResolveType(decl_ctx_die); - if (class_type) { - bool alternate_defn = false; - if (class_type->GetID() != decl_ctx_die.GetID() || - decl_ctx_die.GetContainingDWOModuleDIE()) { - alternate_defn = true; - - // We uniqued the parent class of this function to another - // class so we now need to associate all dies under - // "decl_ctx_die" to DIEs in the DIE for "class_type"... - DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID()); - - if (class_type_die) { - std::vector failures; - - CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die, - class_type, failures); - - // FIXME do something with these failures that's smarter - // than - // just dropping them on the ground. Unfortunately classes - // don't like having stuff added to them after their - // definitions are complete... - - type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); - break; - } - } - } - - if (specification_die_form.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the specification has a valid clang decl context. - class_type->GetForwardCompilerType(); - // If we have a specification, then the function type should - // have been made with the specification and not with this - // die. - DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE( - DIERef(specification_die_form)); - clang::DeclContext *spec_clang_decl_ctx = - GetClangDeclContextForDIE(spec_die); - if (spec_clang_decl_ctx) { - LinkDeclContextToDIE(spec_clang_decl_ctx, die); - } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x" - ") has no decl\n", - die.GetID(), - specification_die_form.Reference().GetOffset()); - } - type_handled = true; - } else if (abstract_origin_die_form.IsValid()) { - // We have a specification which we are going to base our - // function prototype off of, so we need this type to be - // completed so that the m_die_to_decl_ctx for the method in - // the abstract origin has a valid clang decl context. + type_handled = true; + } else if (abstract_origin_die_form.IsValid()) { + // We have a specification which we are going to base our + // function prototype off of, so we need this type to be + // completed so that the m_die_to_decl_ctx for the method in + // the abstract origin has a valid clang decl context. + class_type->GetForwardCompilerType(); + + DWARFDIE abs_die = + dwarf->DebugInfo()->GetDIE(DIERef(abstract_origin_die_form)); + clang::DeclContext *abs_clang_decl_ctx = + GetClangDeclContextForDIE(abs_die); + if (abs_clang_decl_ctx) { + LinkDeclContextToDIE(abs_clang_decl_ctx, die); + } else { + dwarf->GetObjectFile()->GetModule()->ReportWarning( + "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" + ") has no decl\n", + die.GetID(), + abstract_origin_die_form.Reference().GetOffset()); + } + type_handled = true; + } else { + CompilerType class_opaque_type = class_type->GetForwardCompilerType(); - - DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE( - DIERef(abstract_origin_die_form)); - clang::DeclContext *abs_clang_decl_ctx = - GetClangDeclContextForDIE(abs_die); - if (abs_clang_decl_ctx) { - LinkDeclContextToDIE(abs_clang_decl_ctx, die); + if (ClangASTContext::IsCXXClassType(class_opaque_type)) { + if (class_opaque_type.IsBeingDefined() || alternate_defn) { + if (!is_static && !die.HasChildren()) { + // We have a C++ member function with no children (this + // pointer!) and clang will get mad if we try and make + // a function that isn't well formed in the DWARF, so + // we will just skip it... + type_handled = true; } else { - dwarf->GetObjectFile()->GetModule()->ReportWarning( - "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x" - ") has no decl\n", - die.GetID(), - abstract_origin_die_form.Reference().GetOffset()); - } - type_handled = true; - } else { - CompilerType class_opaque_type = - class_type->GetForwardCompilerType(); - if (ClangASTContext::IsCXXClassType(class_opaque_type)) { - if (class_opaque_type.IsBeingDefined() || alternate_defn) { - if (!is_static && !die.HasChildren()) { - // We have a C++ member function with no children (this - // pointer!) and clang will get mad if we try and make - // a function that isn't well formed in the DWARF, so - // we will just skip it... - type_handled = true; - } else { - bool add_method = true; - if (alternate_defn) { - // If an alternate definition for the class exists, - // then add the method only if an equivalent is not - // already present. - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl( - class_opaque_type.GetOpaqueQualType()); - if (record_decl) { - for (auto method_iter = record_decl->method_begin(); - method_iter != record_decl->method_end(); - method_iter++) { - clang::CXXMethodDecl *method_decl = *method_iter; - if (method_decl->getNameInfo().getAsString() == - std::string(type_name_cstr)) { - if (method_decl->getType() == - ClangUtil::GetQualType(clang_type)) { - add_method = false; - LinkDeclContextToDIE( - ClangASTContext::GetAsDeclContext( - method_decl), - die); - type_handled = true; - - break; - } - } + bool add_method = true; + if (alternate_defn) { + // If an alternate definition for the class exists, + // then add the method only if an equivalent is not + // already present. + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl( + class_opaque_type.GetOpaqueQualType()); + if (record_decl) { + for (auto method_iter = record_decl->method_begin(); + method_iter != record_decl->method_end(); + method_iter++) { + clang::CXXMethodDecl *method_decl = *method_iter; + if (method_decl->getNameInfo().getAsString() == + std::string(type_name_cstr)) { + if (method_decl->getType() == + ClangUtil::GetQualType(clang_type)) { + add_method = false; + LinkDeclContextToDIE( + ClangASTContext::GetAsDeclContext( + method_decl), + die); + type_handled = true; + + break; } } } + } + } - if (add_method) { - llvm::PrettyStackTraceFormat stack_trace( - "SymbolFileDWARF::ParseType() is adding a method " - "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", - type_name_cstr, - class_type->GetName().GetCString(), die.GetID(), - dwarf->GetObjectFile() - ->GetFileSpec() - .GetPath() - .c_str()); - - const bool is_attr_used = false; - // Neither GCC 4.2 nor clang++ currently set a valid - // accessibility in the DWARF for C++ methods... - // Default to public for now... - if (accessibility == eAccessNone) - accessibility = eAccessPublic; - - clang::CXXMethodDecl *cxx_method_decl = - m_ast.AddMethodToCXXRecordType( - class_opaque_type.GetOpaqueQualType(), - type_name_cstr, mangled_name_cstr, clang_type, - accessibility, is_virtual, is_static, - is_inline, is_explicit, is_attr_used, - is_artificial); - - type_handled = cxx_method_decl != NULL; - - if (type_handled) { - LinkDeclContextToDIE( - ClangASTContext::GetAsDeclContext( - cxx_method_decl), - die); - - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName( - object_pointer_name.c_str()); - if (log) - log->Printf( - "Setting object pointer name: %s on method " - "object %p.\n", - object_pointer_name.c_str(), - static_cast(cxx_method_decl)); - } - m_ast.SetMetadata(cxx_method_decl, metadata); - } else { - ignore_containing_context = true; - } + if (add_method) { + llvm::PrettyStackTraceFormat stack_trace( + "SymbolFileDWARF::ParseType() is adding a method " + "%s to class %s in DIE 0x%8.8" PRIx64 " from %s", + type_name_cstr, class_type->GetName().GetCString(), + die.GetID(), + dwarf->GetObjectFile() + ->GetFileSpec() + .GetPath() + .c_str()); + + const bool is_attr_used = false; + // Neither GCC 4.2 nor clang++ currently set a valid + // accessibility in the DWARF for C++ methods... + // Default to public for now... + if (accessibility == eAccessNone) + accessibility = eAccessPublic; + + clang::CXXMethodDecl *cxx_method_decl = + m_ast.AddMethodToCXXRecordType( + class_opaque_type.GetOpaqueQualType(), + type_name_cstr, mangled_name_cstr, clang_type, + accessibility, is_virtual, is_static, is_inline, + is_explicit, is_attr_used, is_artificial); + + type_handled = cxx_method_decl != NULL; + + if (type_handled) { + LinkDeclContextToDIE( + ClangASTContext::GetAsDeclContext(cxx_method_decl), + die); + + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); + + if (!object_pointer_name.empty()) { + metadata.SetObjectPtrName( + object_pointer_name.c_str()); + if (log) + log->Printf( + "Setting object pointer name: %s on method " + "object %p.\n", + object_pointer_name.c_str(), + static_cast(cxx_method_decl)); } + m_ast.SetMetadata(cxx_method_decl, metadata); + } else { + ignore_containing_context = true; } - } else { - // We were asked to parse the type for a method in a - // class, yet the class hasn't been asked to complete - // itself through the clang::ExternalASTSource protocol, - // so we need to just have the class complete itself and - // do things the right way, then our - // DIE should then have an entry in the - // dwarf->GetDIEToType() map. First - // we need to modify the dwarf->GetDIEToType() so it - // doesn't think we are trying to parse this DIE - // anymore... - dwarf->GetDIEToType()[die.GetDIE()] = NULL; - - // Now we get the full type to force our class type to - // complete itself using the clang::ExternalASTSource - // protocol which will parse all base classes and all - // methods (including the method for this DIE). - class_type->GetFullCompilerType(); - - // The type for this DIE should have been filled in the - // function call above - type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; - if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); - break; - } - - // FIXME This is fixing some even uglier behavior but we - // really need to - // uniq the methods of each class as well as the class - // itself. - type_handled = true; } } + } else { + // We were asked to parse the type for a method in a + // class, yet the class hasn't been asked to complete + // itself through the clang::ExternalASTSource protocol, + // so we need to just have the class complete itself and + // do things the right way, then our + // DIE should then have an entry in the + // dwarf->GetDIEToType() map. First + // we need to modify the dwarf->GetDIEToType() so it + // doesn't think we are trying to parse this DIE + // anymore... + dwarf->GetDIEToType()[die.GetDIE()] = NULL; + + // Now we get the full type to force our class type to + // complete itself using the clang::ExternalASTSource + // protocol which will parse all base classes and all + // methods (including the method for this DIE). + class_type->GetFullCompilerType(); + + // The type for this DIE should have been filled in the + // function call above + type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; + if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) { + type_sp = type_ptr->shared_from_this(); + break; + } + + // FIXME This is fixing some even uglier behavior but we + // really need to + // uniq the methods of each class as well as the class + // itself. + type_handled = true; } } } } + } + } - if (!type_handled) { - clang::FunctionDecl *function_decl = nullptr; - clang::FunctionDecl *template_function_decl = nullptr; - - if (abstract_origin_die_form.IsValid()) { - DWARFDIE abs_die = abstract_origin_die_form.Reference(); - - SymbolContext sc; + if (!type_handled) { + clang::FunctionDecl *function_decl = nullptr; + clang::FunctionDecl *template_function_decl = nullptr; - if (dwarf->ResolveType(abs_die)) { - function_decl = llvm::dyn_cast_or_null( - GetCachedClangDeclContextForDIE(abs_die)); + if (abstract_origin_die_form.IsValid()) { + DWARFDIE abs_die = abstract_origin_die_form.Reference(); - if (function_decl) { - LinkDeclContextToDIE(function_decl, die); - } - } - } + SymbolContext sc; - if (!function_decl) { - // We just have a function that isn't part of a class - function_decl = m_ast.CreateFunctionDeclaration( - ignore_containing_context ? m_ast.GetTranslationUnitDecl() - : containing_decl_ctx, - type_name_cstr, clang_type, storage, is_inline); - - if (has_template_params) { - ClangASTContext::TemplateParameterInfos template_param_infos; - ParseTemplateParameterInfos(die, template_param_infos); - template_function_decl = m_ast.CreateFunctionDeclaration( - ignore_containing_context ? m_ast.GetTranslationUnitDecl() - : containing_decl_ctx, - type_name_cstr, clang_type, storage, is_inline); - clang::FunctionTemplateDecl *func_template_decl = - m_ast.CreateFunctionTemplateDecl( - containing_decl_ctx, template_function_decl, - type_name_cstr, template_param_infos); - m_ast.CreateFunctionTemplateSpecializationInfo( - function_decl, func_template_decl, template_param_infos); - } - - lldbassert(function_decl); - - if (function_decl) { - LinkDeclContextToDIE(function_decl, die); - - if (!function_param_decls.empty()) { - m_ast.SetFunctionParameters(function_decl, - &function_param_decls.front(), - function_param_decls.size()); - if (template_function_decl) - m_ast.SetFunctionParameters(template_function_decl, - &function_param_decls.front(), - function_param_decls.size()); - } + if (dwarf->ResolveType(abs_die)) { + function_decl = llvm::dyn_cast_or_null( + GetCachedClangDeclContextForDIE(abs_die)); - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); - - if (!object_pointer_name.empty()) { - metadata.SetObjectPtrName(object_pointer_name.c_str()); - if (log) - log->Printf("Setting object pointer name: %s on function " - "object %p.", - object_pointer_name.c_str(), - static_cast(function_decl)); - } - m_ast.SetMetadata(function_decl, metadata); - } + if (function_decl) { + LinkDeclContextToDIE(function_decl, die); } } } - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, llvm::None, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, clang_type, - Type::eResolveStateFull); - assert(type_sp.get()); - } break; - - case DW_TAG_array_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - - DWARFFormValue type_die_form; - uint32_t byte_stride = 0; - uint32_t bit_stride = 0; - bool is_vector = false; - const size_t num_attributes = die.GetAttributes(attributes); - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); - break; - case DW_AT_decl_line: - decl.SetLine(form_value.Unsigned()); - break; - case DW_AT_decl_column: - decl.SetColumn(form_value.Unsigned()); - break; - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_byte_size: - break; // byte_size = form_value.Unsigned(); break; - case DW_AT_byte_stride: - byte_stride = form_value.Unsigned(); - break; - case DW_AT_bit_stride: - bit_stride = form_value.Unsigned(); - break; - case DW_AT_GNU_vector: - is_vector = form_value.Boolean(); - break; - case DW_AT_accessibility: - break; // accessibility = - // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: - break; // is_forward_declaration = form_value.Boolean(); break; - case DW_AT_allocated: - case DW_AT_associated: - case DW_AT_data_location: - case DW_AT_description: - case DW_AT_ordering: - case DW_AT_start_scope: - case DW_AT_visibility: - case DW_AT_specification: - case DW_AT_abstract_origin: - case DW_AT_sibling: - break; - } - } + + if (!function_decl) { + // We just have a function that isn't part of a class + function_decl = m_ast.CreateFunctionDeclaration( + ignore_containing_context ? m_ast.GetTranslationUnitDecl() + : containing_decl_ctx, + type_name_cstr, clang_type, storage, is_inline); + + if (has_template_params) { + ClangASTContext::TemplateParameterInfos template_param_infos; + ParseTemplateParameterInfos(die, template_param_infos); + template_function_decl = m_ast.CreateFunctionDeclaration( + ignore_containing_context ? m_ast.GetTranslationUnitDecl() + : containing_decl_ctx, + type_name_cstr, clang_type, storage, is_inline); + clang::FunctionTemplateDecl *func_template_decl = + m_ast.CreateFunctionTemplateDecl( + containing_decl_ctx, template_function_decl, type_name_cstr, + template_param_infos); + m_ast.CreateFunctionTemplateSpecializationInfo( + function_decl, func_template_decl, template_param_infos); } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); + lldbassert(function_decl); - DIERef type_die_ref(type_die_form); - Type *element_type = dwarf->ResolveTypeUID(type_die_ref); + if (function_decl) { + LinkDeclContextToDIE(function_decl, die); - if (element_type) { - auto array_info = ParseChildArrayInfo(die); - if (array_info) { - byte_stride = array_info->byte_stride; - bit_stride = array_info->bit_stride; + if (!function_param_decls.empty()) { + m_ast.SetFunctionParameters(function_decl, + &function_param_decls.front(), + function_param_decls.size()); + if (template_function_decl) + m_ast.SetFunctionParameters(template_function_decl, + &function_param_decls.front(), + function_param_decls.size()); } - if (byte_stride == 0 && bit_stride == 0) - byte_stride = element_type->GetByteSize().getValueOr(0); - CompilerType array_element_type = - element_type->GetForwardCompilerType(); - - if (ClangASTContext::IsCXXClassType(array_element_type) && - !array_element_type.GetCompleteType()) { - ModuleSP module_sp = die.GetModule(); - if (module_sp) { - if (die.GetCU()->GetProducer() == eProducerClang) - module_sp->ReportError( - "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " - "class/union/struct element type DIE 0x%8.8x that is a " - "forward declaration, not a complete definition.\nTry " - "compiling the source file with -fstandalone-debug or " - "disable -gmodules", - die.GetOffset(), type_die_ref.die_offset); - else - module_sp->ReportError( - "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " - "class/union/struct element type DIE 0x%8.8x that is a " - "forward declaration, not a complete definition.\nPlease " - "file a bug against the compiler and include the " - "preprocessed output for %s", - die.GetOffset(), type_die_ref.die_offset, - die.GetLLDBCompileUnit() - ? die.GetLLDBCompileUnit()->GetPath().c_str() - : "the source file"); - } - // We have no choice other than to pretend that the element class - // type is complete. If we don't do this, clang will crash when - // trying to layout the class. Since we provide layout - // assistance, all ivars in this class and other classes will be - // fine, this is the best we can do short of crashing. - if (ClangASTContext::StartTagDeclarationDefinition( - array_element_type)) { - ClangASTContext::CompleteTagDeclarationDefinition( - array_element_type); - } else { - module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to " - "start its definition.\nPlease file a " - "bug and attach the file at the start " - "of this error message", - type_die_ref.die_offset); - } - } + ClangASTMetadata metadata; + metadata.SetUserID(die.GetID()); - uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; - if (array_info && array_info->element_orders.size() > 0) { - uint64_t num_elements = 0; - auto end = array_info->element_orders.rend(); - for (auto pos = array_info->element_orders.rbegin(); pos != end; - ++pos) { - num_elements = *pos; - clang_type = m_ast.CreateArrayType(array_element_type, - num_elements, is_vector); - array_element_type = clang_type; - array_element_bit_stride = - num_elements ? array_element_bit_stride * num_elements - : array_element_bit_stride; - } - } else { - clang_type = - m_ast.CreateArrayType(array_element_type, 0, is_vector); + if (!object_pointer_name.empty()) { + metadata.SetObjectPtrName(object_pointer_name.c_str()); + if (log) + log->Printf("Setting object pointer name: %s on function " + "object %p.", + object_pointer_name.c_str(), + static_cast(function_decl)); } - ConstString empty_name; - type_sp = std::make_shared( - die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, - nullptr, dwarf->GetUID(DIERef(type_die_form)), - Type::eEncodingIsUID, &decl, clang_type, - Type::eResolveStateFull); - type_sp->SetEncodingType(element_type); - m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), - die.GetID()); + m_ast.SetMetadata(function_decl, metadata); } } - } break; - - case DW_TAG_ptr_to_member_type: { - DWARFFormValue type_die_form; - DWARFFormValue containing_type_die_form; - - const size_t num_attributes = die.GetAttributes(attributes); - - if (num_attributes > 0) { - uint32_t i; - for (i = 0; i < num_attributes; ++i) { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) { - switch (attr) { - case DW_AT_type: - type_die_form = form_value; - break; - case DW_AT_containing_type: - containing_type_die_form = form_value; - break; - } - } + } + } + type_sp = std::make_shared(die.GetID(), dwarf, type_name_const_str, + llvm::None, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, &decl, clang_type, + Type::eResolveStateFull); + assert(type_sp.get()); + } break; + + case DW_TAG_array_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + DWARFFormValue type_die_form; + uint32_t byte_stride = 0; + uint32_t bit_stride = 0; + bool is_vector = false; + const size_t num_attributes = die.GetAttributes(attributes); + + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_decl_file: + decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( + form_value.Unsigned())); + break; + case DW_AT_decl_line: + decl.SetLine(form_value.Unsigned()); + break; + case DW_AT_decl_column: + decl.SetColumn(form_value.Unsigned()); + break; + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; + + case DW_AT_type: + type_die_form = form_value; + break; + case DW_AT_byte_size: + break; // byte_size = form_value.Unsigned(); break; + case DW_AT_byte_stride: + byte_stride = form_value.Unsigned(); + break; + case DW_AT_bit_stride: + bit_stride = form_value.Unsigned(); + break; + case DW_AT_GNU_vector: + is_vector = form_value.Boolean(); + break; + case DW_AT_accessibility: + break; // accessibility = + // DW_ACCESS_to_AccessType(form_value.Unsigned()); break; + case DW_AT_declaration: + break; // is_forward_declaration = form_value.Boolean(); break; + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_description: + case DW_AT_ordering: + case DW_AT_start_scope: + case DW_AT_visibility: + case DW_AT_specification: + case DW_AT_abstract_origin: + case DW_AT_sibling: + break; } + } + } - Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); - Type *class_type = - dwarf->ResolveTypeUID(DIERef(containing_type_die_form)); + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); - CompilerType pointee_clang_type = - pointee_type->GetForwardCompilerType(); - CompilerType class_clang_type = class_type->GetLayoutCompilerType(); + DIERef type_die_ref(type_die_form); + Type *element_type = dwarf->ResolveTypeUID(type_die_ref); - clang_type = ClangASTContext::CreateMemberPointerType( - class_clang_type, pointee_clang_type); + if (element_type) { + auto array_info = ParseChildArrayInfo(die); + if (array_info) { + byte_stride = array_info->byte_stride; + bit_stride = array_info->bit_stride; + } + if (byte_stride == 0 && bit_stride == 0) + byte_stride = element_type->GetByteSize().getValueOr(0); + CompilerType array_element_type = + element_type->GetForwardCompilerType(); + + if (ClangASTContext::IsCXXClassType(array_element_type) && + !array_element_type.GetCompleteType()) { + ModuleSP module_sp = die.GetModule(); + if (module_sp) { + if (die.GetCU()->GetProducer() == eProducerClang) + module_sp->ReportError( + "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " + "class/union/struct element type DIE 0x%8.8x that is a " + "forward declaration, not a complete definition.\nTry " + "compiling the source file with -fstandalone-debug or " + "disable -gmodules", + die.GetOffset(), type_die_ref.die_offset); + else + module_sp->ReportError( + "DWARF DW_TAG_array_type DIE at 0x%8.8x has a " + "class/union/struct element type DIE 0x%8.8x that is a " + "forward declaration, not a complete definition.\nPlease " + "file a bug against the compiler and include the " + "preprocessed output for %s", + die.GetOffset(), type_die_ref.die_offset, + die.GetLLDBCompileUnit() + ? die.GetLLDBCompileUnit()->GetPath().c_str() + : "the source file"); + } - if (llvm::Optional clang_type_size = - clang_type.GetByteSize(nullptr)) { - byte_size = *clang_type_size; - type_sp = std::make_shared( - die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, - LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type, - Type::eResolveStateForward); + // We have no choice other than to pretend that the element class + // type is complete. If we don't do this, clang will crash when + // trying to layout the class. Since we provide layout + // assistance, all ivars in this class and other classes will be + // fine, this is the best we can do short of crashing. + if (ClangASTContext::StartTagDeclarationDefinition( + array_element_type)) { + ClangASTContext::CompleteTagDeclarationDefinition( + array_element_type); + } else { + module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to " + "start its definition.\nPlease file a " + "bug and attach the file at the start " + "of this error message", + type_die_ref.die_offset); } } - break; - } - default: - dwarf->GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " - "attach the file at the start of this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - break; + uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; + if (array_info && array_info->element_orders.size() > 0) { + uint64_t num_elements = 0; + auto end = array_info->element_orders.rend(); + for (auto pos = array_info->element_orders.rbegin(); pos != end; + ++pos) { + num_elements = *pos; + clang_type = m_ast.CreateArrayType(array_element_type, num_elements, + is_vector); + array_element_type = clang_type; + array_element_bit_stride = + num_elements ? array_element_bit_stride * num_elements + : array_element_bit_stride; + } + } else { + clang_type = m_ast.CreateArrayType(array_element_type, 0, is_vector); + } + ConstString empty_name; + type_sp = std::make_shared( + die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, + nullptr, dwarf->GetUID(DIERef(type_die_form)), Type::eEncodingIsUID, + &decl, clang_type, Type::eResolveStateFull); + type_sp->SetEncodingType(element_type); + m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID()); } + } + } break; - if (type_sp.get()) { - DWARFDIE sc_parent_die = - SymbolFileDWARF::GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die.Tag(); - - SymbolContextScope *symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit || - sc_parent_tag == DW_TAG_partial_unit) { - symbol_context_scope = sc.comp_unit; - } else if (sc.function != NULL && sc_parent_die) { - symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; - } + case DW_TAG_ptr_to_member_type: { + DWARFFormValue type_die_form; + DWARFFormValue containing_type_die_form; - if (symbol_context_scope != NULL) { - type_sp->SetSymbolContextScope(symbol_context_scope); + const size_t num_attributes = die.GetAttributes(attributes); + + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_type: + type_die_form = form_value; + break; + case DW_AT_containing_type: + containing_type_die_form = form_value; + break; + } } + } - // We are ready to put this type into the uniqued list up at the module - // level - type_list->Insert(type_sp); + Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); + Type *class_type = + dwarf->ResolveTypeUID(DIERef(containing_type_die_form)); - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType(); + CompilerType class_clang_type = class_type->GetLayoutCompilerType(); + + clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, + pointee_clang_type); + + if (llvm::Optional clang_type_size = + clang_type.GetByteSize(nullptr)) { + byte_size = *clang_type_size; + type_sp = std::make_shared( + die.GetID(), dwarf, type_name_const_str, byte_size, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type, + Type::eResolveStateForward); } - } else if (type_ptr != DIE_IS_BEING_PARSED) { - type_sp = type_ptr->shared_from_this(); } + + break; + } + default: + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and " + "attach the file at the start of this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + break; + } + + if (type_sp.get()) { + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit || + sc_parent_tag == DW_TAG_partial_unit) { + symbol_context_scope = sc.comp_unit; + } else if (sc.function != NULL && sc_parent_die) { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; + } + + if (symbol_context_scope != NULL) { + type_sp->SetSymbolContextScope(symbol_context_scope); + } + + // We are ready to put this type into the uniqued list up at the module + // level + type_list->Insert(type_sp); + + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); } return type_sp; } From 77b4f0abb82c419fedca2ae3a20e1201f752b894 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Thu, 23 May 2019 09:50:18 +0000 Subject: [PATCH 0008/1176] [LLD][ELF] - Improve diagnostic about unrecognized relocations. This is a minor improvement inspired by https://bugs.llvm.org/show_bug.cgi?id=38303. A person reported that he observed message complaining about unsupported R_ARM_V4BX: error: can't create dynamic relocation R_ARM_V4BX against local symbol in readonly segment; recompile object files with -fPIC But with -z notext he only saw a relocation number, what is not convenient: error: ../../gfx/cairo/libpixman/src/pixman-arm-neon-asm-bilinear.o:(.text+0x4F0): unrecognized reloc 40 Also, in the error messages we use relocation but not reloc. With this patch we start to print one of the following messages: error: file.o: unrecognized relocation Unknown(999) error: file.o: unrecognized relocation R_X_KNOWN_BY_LLVM_BUT_UNSUPPORTED_BY_LLD_NAME There is no way to write a test for that I believe. Differential revision: https://reviews.llvm.org/D62237 llvm-svn: 361472 --- lld/ELF/Arch/AArch64.cpp | 2 +- lld/ELF/Arch/ARM.cpp | 2 +- lld/ELF/Arch/AVR.cpp | 2 +- lld/ELF/Arch/Hexagon.cpp | 2 +- lld/ELF/Arch/MSP430.cpp | 2 +- lld/ELF/Arch/PPC.cpp | 2 +- lld/ELF/Arch/PPC64.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 694da898aaf7a..02630c337d996 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -350,7 +350,7 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { or32AArch64Imm(Loc, Val); break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); } } diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index 321b327e5302a..fe3dc8002bc87 100644 --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -518,7 +518,7 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { (Val & 0x00ff)); // imm8 break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); } } diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp index 9ccbd64d34bcb..5a573238d6d01 100644 --- a/lld/ELF/Arch/AVR.cpp +++ b/lld/ELF/Arch/AVR.cpp @@ -66,7 +66,7 @@ void AVR::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { break; } default: - error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); } } diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index 580600ade0074..0ac48c8e01c1b 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -246,7 +246,7 @@ void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { or32le(Loc, applyMask(0x00c03fff, Val)); break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); break; } } diff --git a/lld/ELF/Arch/MSP430.cpp b/lld/ELF/Arch/MSP430.cpp index e104c8c7f2aaf..0f0b5662ec841 100644 --- a/lld/ELF/Arch/MSP430.cpp +++ b/lld/ELF/Arch/MSP430.cpp @@ -83,7 +83,7 @@ void MSP430::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { break; } default: - error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); } } diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index 67bc264b83226..02797df314b88 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -69,7 +69,7 @@ void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); } } diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index bc199fff45a15..8a1b4f887b899 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -860,7 +860,7 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { write64(Loc, Val - DynamicThreadPointerOffset); break; default: - error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); } } From 42548403133d9b9a22f0f3588eded31f050c1664 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 23 May 2019 09:53:30 +0000 Subject: [PATCH 0009/1176] Speed up --start-lib and --end-lib. --{start,end}-lib give files grouped by the options the archive file semantics. That is, each object file between them acts as if it were in an archive file whose sole member is the file. Therefore, files between --{start,end}-lib are linked to the final output only if they are needed to resolve some undefined symbols. Previously, the feature was implemented this way: 1. We read a symbol table and insert defined symbols to the symbol table as lazy symbols. 2. If an undefind symbol is resolved to a lazy symbol, that lazy symbol instantiate ObjFile class for that symbol, which re-insert all defined symbols to the symbol table. So, if an ObjFile is instantiated, defined symbols are inserted to the symbol table twice. Since inserting long symbol names is not cheap, there's a room to optimize here. This patch optimzies it. Now, LazyObjFile remembers symbol handles and passed them over to a new ObjFile instance, so that the ObjFile doesn't insert the same strings. Here is a quick benchmark to link clang. "Original" is the original lld with unmodified command line options. For "Case 1" and "Case 2", I extracted all files from archive files and replace .a's in a command line with .o's wrapped with --{start,end}-lib. I used the original lld for Case 1" and use this patch for Case 2. Original: 5.892 Case 1: 6.001 (+1.8%) Case 2: 5.701 (-3.2%) So, interestingly, --{start,end}-lib are now faster than the regular linking scheme with archive files. That's perhaps not too surprising, though, because for regular archive files, we look up the symbol table with the same string twice. Differential Revision: https://reviews.llvm.org/D62188 llvm-svn: 361473 --- lld/ELF/InputFiles.cpp | 162 ++++++++++++++++++++++++++-------------- lld/ELF/InputFiles.h | 4 +- lld/ELF/SymbolTable.cpp | 1 + 3 files changed, 108 insertions(+), 59 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 6db1217e08fc5..a82d99683ccea 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -913,62 +913,91 @@ StringRef ObjFile::getSectionName(const Elf_Shdr &Sec) { return CHECK(getObj().getSectionName(&Sec, SectionStringTable), this); } +// Initialize this->Symbols. this->Symbols is a parallel array as +// its corresponding ELF symbol table. template void ObjFile::initializeSymbols() { - this->Symbols.reserve(this->getELFSyms().size()); - for (const Elf_Sym &Sym : this->getELFSyms()) - this->Symbols.push_back(createSymbol(&Sym)); -} - -template Symbol *ObjFile::createSymbol(const Elf_Sym *Sym) { - uint32_t SecIdx = getSectionIndex(*Sym); - if (SecIdx >= this->Sections.size()) - fatal(toString(this) + ": invalid section index: " + Twine(SecIdx)); - - InputSectionBase *Sec = this->Sections[SecIdx]; - uint8_t Binding = Sym->getBinding(); - uint8_t StOther = Sym->st_other; - uint8_t Type = Sym->getType(); - uint64_t Value = Sym->st_value; - uint64_t Size = Sym->st_size; - - if (Binding == STB_LOCAL) { - if (Sym->getType() == STT_FILE) - SourceFile = CHECK(Sym->getName(this->StringTable), this); - - if (this->StringTable.size() <= Sym->st_name) - fatal(toString(this) + ": invalid symbol name offset"); - - StringRefZ Name = this->StringTable.data() + Sym->st_name; - if (Sym->st_shndx == SHN_UNDEF) - return make(this, Name, Binding, StOther, Type); - return make(this, Name, Binding, StOther, Type, Value, Size, Sec); - } + ArrayRef ESyms = this->getELFSyms(); + this->Symbols.resize(ESyms.size()); + + // Our symbol table may have already been partially initialized + // because of LazyObjFile. + for (size_t I = 0, End = ESyms.size(); I != End; ++I) + if (!this->Symbols[I] && ESyms[I].getBinding() != STB_LOCAL) + this->Symbols[I] = + Symtab->insert(CHECK(ESyms[I].getName(this->StringTable), this)); + + // Fill this->Symbols. A symbol is either local or global. + for (size_t I = 0, End = ESyms.size(); I != End; ++I) { + const Elf_Sym &ESym = ESyms[I]; + + // Read symbol attributes. + uint32_t SecIdx = getSectionIndex(ESym); + if (SecIdx >= this->Sections.size()) + fatal(toString(this) + ": invalid section index: " + Twine(SecIdx)); + + InputSectionBase *Sec = this->Sections[SecIdx]; + uint8_t Binding = ESym.getBinding(); + uint8_t StOther = ESym.st_other; + uint8_t Type = ESym.getType(); + uint64_t Value = ESym.st_value; + uint64_t Size = ESym.st_size; + StringRefZ Name = this->StringTable.data() + ESym.st_name; + + // Handle local symbols. Local symbols are not added to the symbol + // table because they are not visible from other object files. We + // allocate symbol instances and add their pointers to Symbols. + if (Binding == STB_LOCAL) { + if (ESym.getType() == STT_FILE) + SourceFile = CHECK(ESym.getName(this->StringTable), this); + + if (this->StringTable.size() <= ESym.st_name) + fatal(toString(this) + ": invalid symbol name offset"); + + if (ESym.st_shndx == SHN_UNDEF) + this->Symbols[I] = make(this, Name, Binding, StOther, Type); + else + this->Symbols[I] = + make(this, Name, Binding, StOther, Type, Value, Size, Sec); + continue; + } - StringRef Name = CHECK(Sym->getName(this->StringTable), this); + // Handle global undefined symbols. + if (ESym.st_shndx == SHN_UNDEF) { + resolveSymbol(this->Symbols[I], + Undefined{this, Name, Binding, StOther, Type}); + continue; + } - if (Sym->st_shndx == SHN_UNDEF) - return Symtab->addSymbol(Undefined{this, Name, Binding, StOther, Type}); + // Handle global common symbols. + if (ESym.st_shndx == SHN_COMMON) { + if (Value == 0 || Value >= UINT32_MAX) + fatal(toString(this) + ": common symbol '" + StringRef(Name.Data) + + "' has invalid alignment: " + Twine(Value)); + resolveSymbol(this->Symbols[I], CommonSymbol{this, Name, Binding, StOther, + Type, Value, Size}); + continue; + } - if (Sec == &InputSection::Discarded) - return Symtab->addSymbol(Undefined{this, Name, Binding, StOther, Type, - /*DiscardedSecIdx=*/SecIdx}); + // If a defined symbol is in a discarded section, handle it as if it + // were an undefined symbol. Such symbol doesn't comply with the + // standard, but in practice, a .eh_frame often directly refer + // COMDAT member sections, and if a comdat group is discarded, some + // defined symbol in a .eh_frame becomes dangling symbols. + if (Sec == &InputSection::Discarded) { + resolveSymbol(this->Symbols[I], + Undefined{this, Name, Binding, StOther, Type, SecIdx}); + continue; + } - if (Sym->st_shndx == SHN_COMMON) { - if (Value == 0 || Value >= UINT32_MAX) - fatal(toString(this) + ": common symbol '" + Name + - "' has invalid alignment: " + Twine(Value)); - return Symtab->addSymbol( - CommonSymbol{this, Name, Binding, StOther, Type, Value, Size}); - } + // Handle global defined symbols. + if (Binding == STB_GLOBAL || Binding == STB_WEAK || + Binding == STB_GNU_UNIQUE) { + resolveSymbol(this->Symbols[I], Defined{this, Name, Binding, StOther, + Type, Value, Size, Sec}); + continue; + } - switch (Binding) { - default: fatal(toString(this) + ": unexpected binding: " + Twine((int)Binding)); - case STB_GLOBAL: - case STB_WEAK: - case STB_GNU_UNIQUE: - return Symtab->addSymbol( - Defined{this, Name, Binding, StOther, Type, Value, Size, Sec}); } } @@ -1455,10 +1484,16 @@ InputFile *LazyObjFile::fetch() { InputFile *File = createObjectFile(MBRef, ArchiveName, OffsetInArchive); File->GroupId = GroupId; + + // Copy symbol vector so that the new InputFile doesn't have to + // insert the same defined symbols to the symbol table again. + File->Symbols = std::move(Symbols); return File; } template void LazyObjFile::parse() { + using Elf_Sym = typename ELFT::Sym; + // A lazy object file wraps either a bitcode file or an ELF file. if (isBitcode(this->MB)) { std::unique_ptr Obj = @@ -1476,6 +1511,7 @@ template void LazyObjFile::parse() { return; } + // Find a symbol table. ELFFile Obj = check(ELFFile::create(MB.getBuffer())); ArrayRef Sections = CHECK(Obj.sections(), this); @@ -1483,16 +1519,28 @@ template void LazyObjFile::parse() { if (Sec.sh_type != SHT_SYMTAB) continue; - typename ELFT::SymRange Syms = CHECK(Obj.symbols(&Sec), this); + // A symbol table is found. + ArrayRef ESyms = CHECK(Obj.symbols(&Sec), this); uint32_t FirstGlobal = Sec.sh_info; - StringRef StringTable = - CHECK(Obj.getStringTableForSymtab(Sec, Sections), this); - - for (const typename ELFT::Sym &Sym : Syms.slice(FirstGlobal)) { - if (Sym.st_shndx == SHN_UNDEF) + StringRef Strtab = CHECK(Obj.getStringTableForSymtab(Sec, Sections), this); + this->Symbols.resize(ESyms.size()); + + // Get existing symbols or insert placeholder symbols. + for (size_t I = FirstGlobal, End = ESyms.size(); I != End; ++I) + if (ESyms[I].st_shndx != SHN_UNDEF) + this->Symbols[I] = Symtab->insert(CHECK(ESyms[I].getName(Strtab), this)); + + // Replace existing symbols with LazyObject symbols. + // + // resolveSymbol() may trigger this->fetch() if an existing symbol + // is an undefined symbol. If that happens, this LazyObjFile has + // served its purpose, and we can exit from the loop early. + for (Symbol *Sym : this->Symbols) { + if (!Sym) continue; - Symtab->addSymbol( - LazyObject{*this, CHECK(Sym.getName(StringTable), this)}); + resolveSymbol(Sym, LazyObject{*this, Sym->getName()}); + if (AddedToLink) + return; } return; } diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index f3d9241b5db49..7d5e9a2346fa3 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -139,10 +139,11 @@ class InputFile { // Index of MIPS GOT built for this file. llvm::Optional MipsGotIndex; + std::vector Symbols; + protected: InputFile(Kind K, MemoryBufferRef M); std::vector Sections; - std::vector Symbols; private: const Kind FileKind; @@ -255,7 +256,6 @@ template class ObjFile : public ELFFileBase { StringRef getSectionName(const Elf_Shdr &Sec); bool shouldMerge(const Elf_Shdr &Sec); - Symbol *createSymbol(const Elf_Sym *Sym); // Each ELF symbol contains a section index which the symbol belongs to. // However, because the number of bits dedicated for that is limited, a diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 44fdb96b3e0f8..c77243e010d71 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -92,6 +92,7 @@ Symbol *SymbolTable::insert(StringRef Name) { Symbol *Sym = reinterpret_cast(make()); SymVector.push_back(Sym); + Sym->setName(Name); Sym->SymbolKind = Symbol::PlaceholderKind; Sym->VersionId = Config->DefaultSymbolVersion; Sym->Visibility = STV_DEFAULT; From 7f7d2b2e62ebd89d0ab1e2e066689cdfb2a94899 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 23 May 2019 09:58:08 +0000 Subject: [PATCH 0010/1176] Move code for symbol resolution from SymbolTable.cpp to Symbols.cpp. My recent commits separated symbol resolution from the symbol table, so the functions to resolve symbols are now in a somewhat wrong file. This patch moves it to Symbols.cpp. The functions are now member functions of the symbol. This is code move change. I modified function names so that they are appropriate as member functions, though. No functionality change intended. Differential Revision: https://reviews.llvm.org/D62290 llvm-svn: 361474 --- lld/ELF/Driver.cpp | 4 +- lld/ELF/InputFiles.cpp | 23 ++- lld/ELF/LinkerScript.cpp | 4 +- lld/ELF/SymbolTable.cpp | 322 +-------------------------------------- lld/ELF/SymbolTable.h | 5 - lld/ELF/Symbols.cpp | 316 +++++++++++++++++++++++++++++++++++++- lld/ELF/Symbols.h | 41 ++++- 7 files changed, 364 insertions(+), 351 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 6bd00e46b9143..9a72876631665 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1314,7 +1314,7 @@ static void handleUndefined(StringRef Name) { Sym->IsUsedInRegularObj = true; if (Sym->isLazy()) - Symtab->fetchLazy(Sym); + Sym->fetch(); } static void handleLibcall(StringRef Name) { @@ -1329,7 +1329,7 @@ static void handleLibcall(StringRef Name) { MB = cast(Sym)->getMemberBuffer(); if (isBitcode(MB)) - Symtab->fetchLazy(Sym); + Sym->fetch(); } // Replaces common symbols with defined symbols reside in .bss sections. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index a82d99683ccea..d3a9e14377eff 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -963,8 +963,7 @@ template void ObjFile::initializeSymbols() { // Handle global undefined symbols. if (ESym.st_shndx == SHN_UNDEF) { - resolveSymbol(this->Symbols[I], - Undefined{this, Name, Binding, StOther, Type}); + this->Symbols[I]->resolve(Undefined{this, Name, Binding, StOther, Type}); continue; } @@ -973,8 +972,8 @@ template void ObjFile::initializeSymbols() { if (Value == 0 || Value >= UINT32_MAX) fatal(toString(this) + ": common symbol '" + StringRef(Name.Data) + "' has invalid alignment: " + Twine(Value)); - resolveSymbol(this->Symbols[I], CommonSymbol{this, Name, Binding, StOther, - Type, Value, Size}); + this->Symbols[I]->resolve( + CommonSymbol{this, Name, Binding, StOther, Type, Value, Size}); continue; } @@ -984,16 +983,16 @@ template void ObjFile::initializeSymbols() { // COMDAT member sections, and if a comdat group is discarded, some // defined symbol in a .eh_frame becomes dangling symbols. if (Sec == &InputSection::Discarded) { - resolveSymbol(this->Symbols[I], - Undefined{this, Name, Binding, StOther, Type, SecIdx}); + this->Symbols[I]->resolve( + Undefined{this, Name, Binding, StOther, Type, SecIdx}); continue; } // Handle global defined symbols. if (Binding == STB_GLOBAL || Binding == STB_WEAK || Binding == STB_GNU_UNIQUE) { - resolveSymbol(this->Symbols[I], Defined{this, Name, Binding, StOther, - Type, Value, Size, Sec}); + this->Symbols[I]->resolve( + Defined{this, Name, Binding, StOther, Type, Value, Size, Sec}); continue; } @@ -1532,13 +1531,13 @@ template void LazyObjFile::parse() { // Replace existing symbols with LazyObject symbols. // - // resolveSymbol() may trigger this->fetch() if an existing symbol - // is an undefined symbol. If that happens, this LazyObjFile has - // served its purpose, and we can exit from the loop early. + // resolve() may trigger this->fetch() if an existing symbol is an + // undefined symbol. If that happens, this LazyObjFile has served + // its purpose, and we can exit from the loop early. for (Symbol *Sym : this->Symbols) { if (!Sym) continue; - resolveSymbol(Sym, LazyObject{*this, Sym->getName()}); + Sym->resolve(LazyObject{*this, Sym->getName()}); if (AddedToLink) return; } diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 8519f01181fd2..99f0853c911a2 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -185,7 +185,7 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) { 0, Sec); Symbol *Sym = Symtab->insert(Cmd->Name); - mergeSymbolProperties(Sym, New); + Sym->mergeProperties(New); Sym->replace(New); Cmd->Sym = cast(Sym); } @@ -202,7 +202,7 @@ static void declareSymbol(SymbolAssignment *Cmd) { // We can't calculate final value right now. Symbol *Sym = Symtab->insert(Cmd->Name); - mergeSymbolProperties(Sym, New); + Sym->mergeProperties(New); Sym->replace(New); Cmd->Sym = cast(Sym); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index c77243e010d71..9fc05d98366aa 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -55,14 +55,6 @@ void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { Real->setName(S); } -static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { - if (VA == STV_DEFAULT) - return VB; - if (VB == STV_DEFAULT) - return VA; - return std::min(VA, VB); -} - // Find an existing symbol or create a new one. Symbol *SymbolTable::insert(StringRef Name) { // @@ means the symbol is the default version. In that @@ -105,232 +97,9 @@ Symbol *SymbolTable::insert(StringRef Name) { } Symbol *SymbolTable::addSymbol(const Symbol &New) { - Symbol *Old = Symtab->insert(New.getName()); - resolveSymbol(Old, New); - return Old; -} - -static void addUndefined(Symbol *Old, const Undefined &New) { - // An undefined symbol with non default visibility must be satisfied - // in the same DSO. - // - // If this is a non-weak defined symbol in a discarded section, override the - // existing undefined symbol for better error message later. - if ((Old->isShared() && New.Visibility != STV_DEFAULT) || - (Old->isUndefined() && New.Binding != STB_WEAK && New.DiscardedSecIdx)) { - Old->replace(New); - return; - } - - if (Old->isShared() || Old->isLazy() || - (Old->isUndefined() && New.Binding != STB_WEAK)) - Old->Binding = New.Binding; - - if (Old->isLazy()) { - // An undefined weak will not fetch archive members. See comment on Lazy in - // Symbols.h for the details. - if (New.Binding == STB_WEAK) { - Old->Type = New.Type; - return; - } - - // Do extra check for --warn-backrefs. - // - // --warn-backrefs is an option to prevent an undefined reference from - // fetching an archive member written earlier in the command line. It can be - // used to keep compatibility with GNU linkers to some degree. - // I'll explain the feature and why you may find it useful in this comment. - // - // lld's symbol resolution semantics is more relaxed than traditional Unix - // linkers. For example, - // - // ld.lld foo.a bar.o - // - // succeeds even if bar.o contains an undefined symbol that has to be - // resolved by some object file in foo.a. Traditional Unix linkers don't - // allow this kind of backward reference, as they visit each file only once - // from left to right in the command line while resolving all undefined - // symbols at the moment of visiting. - // - // In the above case, since there's no undefined symbol when a linker visits - // foo.a, no files are pulled out from foo.a, and because the linker forgets - // about foo.a after visiting, it can't resolve undefined symbols in bar.o - // that could have been resolved otherwise. - // - // That lld accepts more relaxed form means that (besides it'd make more - // sense) you can accidentally write a command line or a build file that - // works only with lld, even if you have a plan to distribute it to wider - // users who may be using GNU linkers. With --warn-backrefs, you can detect - // a library order that doesn't work with other Unix linkers. - // - // The option is also useful to detect cyclic dependencies between static - // archives. Again, lld accepts - // - // ld.lld foo.a bar.a - // - // even if foo.a and bar.a depend on each other. With --warn-backrefs, it is - // handled as an error. - // - // Here is how the option works. We assign a group ID to each file. A file - // with a smaller group ID can pull out object files from an archive file - // with an equal or greater group ID. Otherwise, it is a reverse dependency - // and an error. - // - // A file outside --{start,end}-group gets a fresh ID when instantiated. All - // files within the same --{start,end}-group get the same group ID. E.g. - // - // ld.lld A B --start-group C D --end-group E - // - // A forms group 0. B form group 1. C and D (including their member object - // files) form group 2. E forms group 3. I think that you can see how this - // group assignment rule simulates the traditional linker's semantics. - bool Backref = Config->WarnBackrefs && New.File && - Old->File->GroupId < New.File->GroupId; - Symtab->fetchLazy(Old); - - // We don't report backward references to weak symbols as they can be - // overridden later. - if (Backref && !Old->isWeak()) - warn("backward reference detected: " + New.getName() + " in " + - toString(New.File) + " refers to " + toString(Old->File)); - } -} - -// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and -// foo@@VER. We want to effectively ignore foo, so give precedence to -// foo@@VER. -// FIXME: If users can transition to using -// .symver foo,foo@@@VER -// we can delete this hack. -static int compareVersion(StringRef OldName, StringRef NewName) { - bool A = OldName.contains("@@"); - bool B = NewName.contains("@@"); - if (!A && B) - return 1; - if (A && !B) - return -1; - return 0; -} - -// Compare two symbols. Return 1 if the new symbol should win, -1 if -// the new symbol should lose, or 0 if there is a conflict. -static int compare(const Symbol *Old, const Symbol *New) { - assert(New->isDefined() || New->isCommon()); - - if (!Old->isDefined() && !Old->isCommon()) - return 1; - - if (int Cmp = compareVersion(Old->getName(), New->getName())) - return Cmp; - - if (New->isWeak()) - return -1; - - if (Old->isWeak()) - return 1; - - if (Old->isCommon() && New->isCommon()) { - if (Config->WarnCommon) - warn("multiple common of " + Old->getName()); - return 0; - } - - if (Old->isCommon()) { - if (Config->WarnCommon) - warn("common " + Old->getName() + " is overridden"); - return 1; - } - - if (New->isCommon()) { - if (Config->WarnCommon) - warn("common " + Old->getName() + " is overridden"); - return -1; - } - - auto *OldSym = cast(Old); - auto *NewSym = cast(New); - - if (New->File && isa(New->File)) - return 0; - - if (!OldSym->Section && !NewSym->Section && OldSym->Value == NewSym->Value && - NewSym->Binding == STB_GLOBAL) - return -1; - - return 0; -} - -static void addCommon(Symbol *Old, const CommonSymbol &New) { - int Cmp = compare(Old, &New); - if (Cmp < 0) - return; - - if (Cmp > 0) { - Old->replace(New); - return; - } - - CommonSymbol *OldSym = cast(Old); - - OldSym->Alignment = std::max(OldSym->Alignment, New.Alignment); - if (OldSym->Size < New.Size) { - OldSym->File = New.File; - OldSym->Size = New.Size; - } -} - -static void reportDuplicate(Symbol *Sym, InputFile *NewFile, - InputSectionBase *ErrSec, uint64_t ErrOffset) { - if (Config->AllowMultipleDefinition) - return; - - Defined *D = cast(Sym); - if (!D->Section || !ErrSec) { - error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + - toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); - return; - } - - // Construct and print an error message in the form of: - // - // ld.lld: error: duplicate symbol: foo - // >>> defined at bar.c:30 - // >>> bar.o (/home/alice/src/bar.o) - // >>> defined at baz.c:563 - // >>> baz.o in archive libbaz.a - auto *Sec1 = cast(D->Section); - std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value); - std::string Obj1 = Sec1->getObjMsg(D->Value); - std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset); - std::string Obj2 = ErrSec->getObjMsg(ErrOffset); - - std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; - if (!Src1.empty()) - Msg += Src1 + "\n>>> "; - Msg += Obj1 + "\n>>> defined at "; - if (!Src2.empty()) - Msg += Src2 + "\n>>> "; - Msg += Obj2; - error(Msg); -} - -static void addDefined(Symbol *Old, const Defined &New) { - int Cmp = compare(Old, &New); - if (Cmp > 0) - Old->replace(New); - else if (Cmp == 0) - reportDuplicate(Old, New.File, - dyn_cast_or_null(New.Section), New.Value); -} - -static void addShared(Symbol *Old, const SharedSymbol &New) { - if (Old->Visibility == STV_DEFAULT && (Old->isUndefined() || Old->isLazy())) { - // An undefined symbol with non default visibility must be satisfied - // in the same DSO. - uint8_t Binding = Old->Binding; - Old->replace(New); - Old->Binding = Binding; - } + Symbol *Sym = Symtab->insert(New.getName()); + Sym->resolve(New); + return Sym; } Symbol *SymbolTable::find(StringRef Name) { @@ -342,44 +111,6 @@ Symbol *SymbolTable::find(StringRef Name) { return SymVector[It->second]; } -template static void addLazy(Symbol *Old, const LazyT &New) { - if (!Old->isUndefined()) - return; - - // An undefined weak will not fetch archive members. See comment on Lazy in - // Symbols.h for the details. - if (Old->isWeak()) { - uint8_t Type = Old->Type; - Old->replace(New); - Old->Type = Type; - Old->Binding = STB_WEAK; - return; - } - - if (InputFile *F = New.fetch()) - parseFile(F); -} - -static void addLazyArchive(Symbol *Old, const LazyArchive &New) { - addLazy(Old, New); -} - -static void addLazyObject(Symbol *Old, const LazyObject &New) { - addLazy(Old, New); -} - -void SymbolTable::fetchLazy(Symbol *Sym) { - if (auto *S = dyn_cast(Sym)) { - if (InputFile *File = S->fetch()) - parseFile(File); - return; - } - - auto *S = cast(Sym); - if (InputFile *File = cast(S->File)->fetch()) - parseFile(File); -} - // Initialize DemangledSyms with a map from demangled symbols to symbol // objects. Used to handle "extern C++" directive in version scripts. // @@ -540,50 +271,3 @@ void SymbolTable::scanVersionScript() { for (Symbol *Sym : SymVector) Sym->parseSymbolVersion(); } - -// Merge symbol properties. -// -// When we have many symbols of the same name, we choose one of them, -// and that's the result of symbol resolution. However, symbols that -// were not chosen still affect some symbol properties. -void elf::mergeSymbolProperties(Symbol *Old, const Symbol &New) { - // Merge symbol properties. - Old->ExportDynamic = Old->ExportDynamic || New.ExportDynamic; - Old->IsUsedInRegularObj = Old->IsUsedInRegularObj || New.IsUsedInRegularObj; - - // DSO symbols do not affect visibility in the output. - if (!New.isShared()) - Old->Visibility = getMinVisibility(Old->Visibility, New.Visibility); -} - -void elf::resolveSymbol(Symbol *Old, const Symbol &New) { - mergeSymbolProperties(Old, New); - - if (Old->isPlaceholder()) { - Old->replace(New); - return; - } - - switch (New.kind()) { - case Symbol::UndefinedKind: - addUndefined(Old, cast(New)); - break; - case Symbol::CommonKind: - addCommon(Old, cast(New)); - break; - case Symbol::DefinedKind: - addDefined(Old, cast(New)); - break; - case Symbol::LazyArchiveKind: - addLazyArchive(Old, cast(New)); - break; - case Symbol::LazyObjectKind: - addLazyObject(Old, cast(New)); - break; - case Symbol::SharedKind: - addShared(Old, cast(New)); - break; - case Symbol::PlaceholderKind: - llvm_unreachable("bad symbol kind"); - } -} diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 25b73fa5481fe..8c9a8f8f2e760 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -47,8 +47,6 @@ class SymbolTable { Symbol *addSymbol(const Symbol &New); - void fetchLazy(Symbol *Sym); - void scanVersionScript(); Symbol *find(StringRef Name); @@ -94,9 +92,6 @@ class SymbolTable { extern SymbolTable *Symtab; -void mergeSymbolProperties(Symbol *Old, const Symbol &New); -void resolveSymbol(Symbol *Old, const Symbol &New); - } // namespace elf } // namespace lld diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index e1bbb8acedc68..94f0d6ea6cb9d 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -241,8 +241,20 @@ void Symbol::parseSymbolVersion() { Verstr); } -InputFile *LazyArchive::fetch() const { - return cast(File)->fetch(Sym); +void Symbol::fetch() const { + if (auto *Sym = dyn_cast(this)) { + if (auto *F = cast(Sym->File)->fetch(Sym->Sym)) + parseFile(F); + return; + } + + if (auto *Sym = dyn_cast(this)) { + if (auto *F = dyn_cast(Sym->File)->fetch()) + parseFile(F); + return; + } + + llvm_unreachable("Symbol::fetch() is called on a non-lazy symbol"); } MemoryBufferRef LazyArchive::getMemberBuffer() { @@ -254,10 +266,6 @@ MemoryBufferRef LazyArchive::getMemberBuffer() { Sym.getName()); } -InputFile *LazyObject::fetch() const { - return cast(File)->fetch(); -} - uint8_t Symbol::computeBinding() const { if (Config->Relocatable) return Binding; @@ -338,3 +346,299 @@ std::string lld::toString(const Symbol &B) { return *S; return B.getName(); } + +static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { + if (VA == STV_DEFAULT) + return VB; + if (VB == STV_DEFAULT) + return VA; + return std::min(VA, VB); +} + +// Merge symbol properties. +// +// When we have many symbols of the same name, we choose one of them, +// and that's the result of symbol resolution. However, symbols that +// were not chosen still affect some symbol properties. +void Symbol::mergeProperties(const Symbol &Other) { + if (Other.ExportDynamic) + ExportDynamic = true; + if (Other.IsUsedInRegularObj) + IsUsedInRegularObj = true; + + // DSO symbols do not affect visibility in the output. + if (!Other.isShared()) + Visibility = getMinVisibility(Visibility, Other.Visibility); +} + +void Symbol::resolve(const Symbol &Other) { + mergeProperties(Other); + + if (isPlaceholder()) { + replace(Other); + return; + } + + switch (Other.kind()) { + case Symbol::UndefinedKind: + resolveUndefined(cast(Other)); + break; + case Symbol::CommonKind: + resolveCommon(cast(Other)); + break; + case Symbol::DefinedKind: + resolveDefined(cast(Other)); + break; + case Symbol::LazyArchiveKind: + resolveLazy(cast(Other)); + break; + case Symbol::LazyObjectKind: + resolveLazy(cast(Other)); + break; + case Symbol::SharedKind: + resolveShared(cast(Other)); + break; + case Symbol::PlaceholderKind: + llvm_unreachable("bad symbol kind"); + } +} + +void Symbol::resolveUndefined(const Undefined &Other) { + // An undefined symbol with non default visibility must be satisfied + // in the same DSO. + // + // If this is a non-weak defined symbol in a discarded section, override the + // existing undefined symbol for better error message later. + if ((isShared() && Other.Visibility != STV_DEFAULT) || + (isUndefined() && Other.Binding != STB_WEAK && Other.DiscardedSecIdx)) { + replace(Other); + return; + } + + if (isShared() || isLazy() || (isUndefined() && Other.Binding != STB_WEAK)) + Binding = Other.Binding; + + if (isLazy()) { + // An undefined weak will not fetch archive members. See comment on Lazy in + // Symbols.h for the details. + if (Other.Binding == STB_WEAK) { + Type = Other.Type; + return; + } + + // Do extra check for --warn-backrefs. + // + // --warn-backrefs is an option to prevent an undefined reference from + // fetching an archive member written earlier in the command line. It can be + // used to keep compatibility with GNU linkers to some degree. + // I'll explain the feature and why you may find it useful in this comment. + // + // lld's symbol resolution semantics is more relaxed than traditional Unix + // linkers. For example, + // + // ld.lld foo.a bar.o + // + // succeeds even if bar.o contains an undefined symbol that has to be + // resolved by some object file in foo.a. Traditional Unix linkers don't + // allow this kind of backward reference, as they visit each file only once + // from left to right in the command line while resolving all undefined + // symbols at the moment of visiting. + // + // In the above case, since there's no undefined symbol when a linker visits + // foo.a, no files are pulled out from foo.a, and because the linker forgets + // about foo.a after visiting, it can't resolve undefined symbols in bar.o + // that could have been resolved otherwise. + // + // That lld accepts more relaxed form means that (besides it'd make more + // sense) you can accidentally write a command line or a build file that + // works only with lld, even if you have a plan to distribute it to wider + // users who may be using GNU linkers. With --warn-backrefs, you can detect + // a library order that doesn't work with other Unix linkers. + // + // The option is also useful to detect cyclic dependencies between static + // archives. Again, lld accepts + // + // ld.lld foo.a bar.a + // + // even if foo.a and bar.a depend on each other. With --warn-backrefs, it is + // handled as an error. + // + // Here is how the option works. We assign a group ID to each file. A file + // with a smaller group ID can pull out object files from an archive file + // with an equal or greater group ID. Otherwise, it is a reverse dependency + // and an error. + // + // A file outside --{start,end}-group gets a fresh ID when instantiated. All + // files within the same --{start,end}-group get the same group ID. E.g. + // + // ld.lld A B --start-group C D --end-group E + // + // A forms group 0. B form group 1. C and D (including their member object + // files) form group 2. E forms group 3. I think that you can see how this + // group assignment rule simulates the traditional linker's semantics. + bool Backref = Config->WarnBackrefs && Other.File && + File->GroupId < Other.File->GroupId; + fetch(); + + // We don't report backward references to weak symbols as they can be + // overridden later. + if (Backref && !isWeak()) + warn("backward reference detected: " + Other.getName() + " in " + + toString(Other.File) + " refers to " + toString(File)); + } +} + +// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and +// foo@@VER. We want to effectively ignore foo, so give precedence to +// foo@@VER. +// FIXME: If users can transition to using +// .symver foo,foo@@@VER +// we can delete this hack. +static int compareVersion(StringRef A, StringRef B) { + bool X = A.contains("@@"); + bool Y = B.contains("@@"); + if (!X && Y) + return 1; + if (X && !Y) + return -1; + return 0; +} + +// Compare two symbols. Return 1 if the new symbol should win, -1 if +// the new symbol should lose, or 0 if there is a conflict. +int Symbol::compare(const Symbol *Other) const { + assert(Other->isDefined() || Other->isCommon()); + + if (!isDefined() && !isCommon()) + return 1; + + if (int Cmp = compareVersion(getName(), Other->getName())) + return Cmp; + + if (Other->isWeak()) + return -1; + + if (isWeak()) + return 1; + + if (isCommon() && Other->isCommon()) { + if (Config->WarnCommon) + warn("multiple common of " + getName()); + return 0; + } + + if (isCommon()) { + if (Config->WarnCommon) + warn("common " + getName() + " is overridden"); + return 1; + } + + if (Other->isCommon()) { + if (Config->WarnCommon) + warn("common " + getName() + " is overridden"); + return -1; + } + + auto *OldSym = cast(this); + auto *NewSym = cast(Other); + + if (Other->File && isa(Other->File)) + return 0; + + if (!OldSym->Section && !NewSym->Section && OldSym->Value == NewSym->Value && + NewSym->Binding == STB_GLOBAL) + return -1; + + return 0; +} + +static void reportDuplicate(Symbol *Sym, InputFile *NewFile, + InputSectionBase *ErrSec, uint64_t ErrOffset) { + if (Config->AllowMultipleDefinition) + return; + + Defined *D = cast(Sym); + if (!D->Section || !ErrSec) { + error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + + toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); + return; + } + + // Construct and print an error message in the form of: + // + // ld.lld: error: duplicate symbol: foo + // >>> defined at bar.c:30 + // >>> bar.o (/home/alice/src/bar.o) + // >>> defined at baz.c:563 + // >>> baz.o in archive libbaz.a + auto *Sec1 = cast(D->Section); + std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value); + std::string Obj1 = Sec1->getObjMsg(D->Value); + std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset); + std::string Obj2 = ErrSec->getObjMsg(ErrOffset); + + std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; + if (!Src1.empty()) + Msg += Src1 + "\n>>> "; + Msg += Obj1 + "\n>>> defined at "; + if (!Src2.empty()) + Msg += Src2 + "\n>>> "; + Msg += Obj2; + error(Msg); +} + +void Symbol::resolveCommon(const CommonSymbol &Other) { + int Cmp = compare(&Other); + if (Cmp < 0) + return; + + if (Cmp > 0) { + replace(Other); + return; + } + + CommonSymbol *OldSym = cast(this); + + OldSym->Alignment = std::max(OldSym->Alignment, Other.Alignment); + if (OldSym->Size < Other.Size) { + OldSym->File = Other.File; + OldSym->Size = Other.Size; + } +} + +void Symbol::resolveDefined(const Defined &Other) { + int Cmp = compare(&Other); + if (Cmp > 0) + replace(Other); + else if (Cmp == 0) + reportDuplicate(this, Other.File, + dyn_cast_or_null(Other.Section), + Other.Value); +} + +template void Symbol::resolveLazy(const LazyT &Other) { + if (!isUndefined()) + return; + + // An undefined weak will not fetch archive members. See comment on Lazy in + // Symbols.h for the details. + if (isWeak()) { + uint8_t Ty = Type; + replace(Other); + Type = Ty; + Binding = STB_WEAK; + return; + } + + Other.fetch(); +} + +void Symbol::resolveShared(const SharedSymbol &Other) { + if (Visibility == STV_DEFAULT && (isUndefined() || isLazy())) { + // An undefined symbol with non default visibility must be satisfied + // in the same DSO. + uint8_t Bind = Binding; + replace(Other); + Binding = Bind; + } +} diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index a2b904f057d5c..04c23b588f02f 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -22,8 +22,14 @@ namespace lld { namespace elf { -class Symbol; +class CommonSymbol; +class Defined; class InputFile; +class LazyArchive; +class LazyObject; +class SharedSymbol; +class Symbol; +class Undefined; } // namespace elf std::string toString(const elf::Symbol &); @@ -174,6 +180,27 @@ class Symbol { uint64_t getSize() const; OutputSection *getOutputSection() const; + // The following two functions are used for symbol resolution. + // + // You are expected to call mergeProperties for all symbols in input + // files so that attributes that are attached to names rather than + // indivisual symbol (such as visibility) are merged together. + // + // Every time you read a new symbol from an input, you are supposed + // to call resolve() with the new symbol. That function replaces + // "this" object as a result of name resolution if the new symbol is + // more appropriate to be included in the output. + // + // For example, if "this" is an undefined symbol and a new symbol is + // a defined symbol, "this" is replaced with the new symbol. + void mergeProperties(const Symbol &Other); + void resolve(const Symbol &Other); + + // If this is a lazy symbol, fetch an input file and add the symbol + // in the file to the symbol table. Calling this function on + // non-lazy object causes a runtime error. + void fetch() const; + private: static bool isExportDynamic(Kind K, uint8_t Visibility) { if (K == SharedKind) @@ -181,6 +208,14 @@ class Symbol { return Config->Shared || Config->ExportDynamic; } + void resolveUndefined(const Undefined &Other); + void resolveCommon(const CommonSymbol &Other); + void resolveDefined(const Defined &Other); + template void resolveLazy(const LazyT &Other); + void resolveShared(const SharedSymbol &Other); + + int compare(const Symbol *Other) const; + inline size_t getSymbolSize() const; protected: @@ -351,10 +386,8 @@ class LazyArchive : public Symbol { static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; } - InputFile *fetch() const; MemoryBufferRef getMemberBuffer(); -private: const llvm::object::Archive::Symbol Sym; }; @@ -367,8 +400,6 @@ class LazyObject : public Symbol { llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE) {} static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; } - - InputFile *fetch() const; }; // Some linker-generated symbols need to be created as From b970fd718851c655c20a3b978b61d3ed63e7c00d Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Thu, 23 May 2019 09:58:29 +0000 Subject: [PATCH 0011/1176] [clangd-vscode] Do not customize uri converters in vscode Summary: Clangd is already resolving symlinks on the server side, therefore there is no more need to handle it in client side. This was also resulting in breakages whenever index contained a symbol coming from a non-existent file(like a generated file), e.g. during workspace symbols whole response was dropped since stat had failed. Reviewers: ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62288 llvm-svn: 361475 --- .../clangd/clients/clangd-vscode/src/extension.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts b/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts index 2cb97d97ab70a..7b80967151883 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts +++ b/clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts @@ -1,6 +1,5 @@ import * as vscode from 'vscode'; import * as vscodelc from 'vscode-languageclient'; -import { realpathSync } from 'fs'; /** * Method to get workspace configuration option @@ -87,17 +86,6 @@ export function activate(context: vscode.ExtensionContext) { fileEvents: vscode.workspace.createFileSystemWatcher(filePattern) }, initializationOptions: { clangdFileStatus: true }, - // Resolve symlinks for all files provided by clangd. - // This is a workaround for a bazel + clangd issue - bazel produces a symlink tree to build in, - // and when navigating to the included file, clangd passes its path inside the symlink tree - // rather than its filesystem path. - // FIXME: remove this once clangd knows enough about bazel to resolve the - // symlinks where needed (or if this causes problems for other workflows). - uriConverters: { - code2Protocol: (value: vscode.Uri) => value.toString(), - protocol2Code: (value: string) => - vscode.Uri.file(realpathSync(vscode.Uri.parse(value).fsPath)) - }, // Do not switch to output window when clangd returns output revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never }; From 4bce63a0e7c5bfd0c4ee1642d0fbae89702ad490 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Thu, 23 May 2019 10:06:03 +0000 Subject: [PATCH 0012/1176] Reland: [WebAssembly] Add __start_/_stop_ symbols for data sections This is a reland of rL361235. Fixes https://bugs.llvm.org/show_bug.cgi?id=41565 Differential Revision: https://reviews.llvm.org/D61876 llvm-svn: 361476 --- lld/test/wasm/startstop.ll | 57 ++++++++++++++++++++++++++++++++++++++ lld/wasm/Driver.cpp | 4 --- lld/wasm/SymbolTable.cpp | 11 ++++++++ lld/wasm/SymbolTable.h | 2 ++ lld/wasm/Writer.cpp | 45 +++++++++++++++++++++++++++--- 5 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 lld/test/wasm/startstop.ll diff --git a/lld/test/wasm/startstop.ll b/lld/test/wasm/startstop.ll new file mode 100644 index 0000000000000..f83d1ac537856 --- /dev/null +++ b/lld/test/wasm/startstop.ll @@ -0,0 +1,57 @@ +; RUN: llc -filetype=obj -o %t.o %s +; RUN: wasm-ld --no-gc-sections %t.o -o %t.wasm +; RUN: obj2yaml %t.wasm | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +@foo = global i32 3, section "mysection", align 4 +@bar = global i32 4, section "mysection", align 4 + +@__start_mysection = external global i8* +@__stop_mysection = external global i8* + +define i8** @get_start() { + ret i8** @__start_mysection +} + +define i8** @get_end() { + ret i8** @__stop_mysection +} + +define void @_start() { +entry: + ret void +} +; CHECK: - Type: CODE +; CHECK-NEXT: Functions: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 0B +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 4180888080000B +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 4188888080000B +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 0B +; CHECK-NEXT: - Type: DATA +; CHECK-NEXT: Segments: +; CHECK-NEXT: - SectionOffset: 7 +; CHECK-NEXT: InitFlags: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1024 +; CHECK-NEXT: Content: '0300000004000000' +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: name +; CHECK-NEXT: FunctionNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: __wasm_call_ctors +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: get_start +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: get_end +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: _start diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 9ff824a2eec4f..0bea11faf7dc7 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -652,10 +652,6 @@ void LinkerDriver::link(ArrayRef ArgsArr) { // Add synthetic dummies for weak undefined functions. Must happen // after LTO otherwise functions may not yet have signatures. Symtab->handleWeakUndefines(); - - // Make sure we have resolved all symbols. - if (!Config->AllowUndefined) - Symtab->reportRemainingUndefines(); } if (EntrySym) diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index 1a16b6390ba4e..ce1aa5132ba90 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -198,6 +198,17 @@ DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, Flags, nullptr, Function); } +DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value, + uint32_t Flags) { + Symbol *S = find(Name); + if (!S || S->isDefined()) + return nullptr; + LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n"); + auto *rtn = replaceSymbol(S, Name, Flags); + rtn->setVirtualAddress(Value); + return rtn; +} + DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, uint32_t Flags) { LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h index ee4ee244ef538..a35140df136e1 100644 --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -81,6 +81,8 @@ class SymbolTable { InputGlobal *Global); DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags, InputFunction *Function); + DefinedData *addOptionalDataSymbol(StringRef Name, uint32_t Value, + uint32_t Flags); void handleSymbolVariants(); void handleWeakUndefines(); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 01dbd82dc3549..f43191c70273d 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -73,6 +73,8 @@ class Writer { void addSection(OutputSection *Sec); void addSections(); + void addStartStopSymbols(const InputSegment *Seg); + void createCustomSections(); void createSyntheticSections(); void finalizeSections(); @@ -293,6 +295,22 @@ void Writer::addSection(OutputSection *Sec) { OutputSections.push_back(Sec); } +// If a section name is valid as a C identifier (which is rare because of +// the leading '.'), linkers are expected to define __start_ and +// __stop_ symbols. They are at beginning and end of the section, +// respectively. This is not requested by the ELF standard, but GNU ld and +// gold provide the feature, and used by many programs. +void Writer::addStartStopSymbols(const InputSegment *Seg) { + StringRef S = Seg->getName(); + LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << S << "\n"); + if (!isValidCIdentifier(S)) + return; + uint32_t Start = Seg->OutputSeg->StartVA + Seg->OutputSegmentOffset; + uint32_t Stop = Start + Seg->getSize(); + Symtab->addOptionalDataSymbol(Saver.save("__start_" + S), Start, 0); + Symtab->addOptionalDataSymbol(Saver.save("__stop_" + S), Stop, 0); +} + void Writer::addSections() { addSection(Out.DylinkSec); addSection(Out.TypeSec); @@ -724,21 +742,40 @@ void Writer::run() { populateTargetFeatures(); log("-- calculateImports"); calculateImports(); + log("-- layoutMemory"); + layoutMemory(); + + if (!Config->Relocatable) { + // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols + // This has to be done after memory layout is performed. + for (const OutputSegment *Seg : Segments) + for (const InputSegment *S : Seg->InputSegments) + addStartStopSymbols(S); + } + log("-- scanRelocations"); scanRelocations(); log("-- assignIndexes"); assignIndexes(); log("-- calculateInitFunctions"); calculateInitFunctions(); - log("-- calculateTypes"); - calculateTypes(); - log("-- layoutMemory"); - layoutMemory(); + if (!Config->Relocatable) { + // Create linker synthesized functions if (Config->Pic) createApplyRelocationsFunction(); createCallCtorsFunction(); + + // Make sure we have resolved all symbols. + if (!Config->AllowUndefined) + Symtab->reportRemainingUndefines(); + + if (errorCount()) + return; } + + log("-- calculateTypes"); + calculateTypes(); log("-- calculateExports"); calculateExports(); log("-- calculateCustomSections"); From 821a1ac0506cbaa2210eb7158df4c917c394e316 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 23 May 2019 10:08:56 +0000 Subject: [PATCH 0013/1176] Remove LazyObjFile::AddedToLink. Instead we can just clear a MemoryBuffer so that we cannot get the same buffer more than once. llvm-svn: 361477 --- lld/ELF/InputFiles.cpp | 18 +++++++----------- lld/ELF/InputFiles.h | 2 -- lld/ELF/LTO.cpp | 2 +- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index d3a9e14377eff..dbfc867af7ee9 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1469,21 +1469,15 @@ InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { return F; } -MemoryBufferRef LazyObjFile::getBuffer() { - if (AddedToLink) - return MemoryBufferRef(); - AddedToLink = true; - return MB; -} - InputFile *LazyObjFile::fetch() { - MemoryBufferRef MBRef = getBuffer(); - if (MBRef.getBuffer().empty()) + if (MB.getBuffer().empty()) return nullptr; - InputFile *File = createObjectFile(MBRef, ArchiveName, OffsetInArchive); + InputFile *File = createObjectFile(MB, ArchiveName, OffsetInArchive); File->GroupId = GroupId; + MB = {}; + // Copy symbol vector so that the new InputFile doesn't have to // insert the same defined symbols to the symbol table again. File->Symbols = std::move(Symbols); @@ -1538,7 +1532,9 @@ template void LazyObjFile::parse() { if (!Sym) continue; Sym->resolve(LazyObject{*this, Sym->getName()}); - if (AddedToLink) + + // MemoryBuffer is emptied if this file is instantiated as ObjFile. + if (MB.getBuffer().empty()) return; } return; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 7d5e9a2346fa3..8b112e592503c 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -307,9 +307,7 @@ class LazyObjFile : public InputFile { static bool classof(const InputFile *F) { return F->kind() == LazyObjKind; } template void parse(); - MemoryBufferRef getBuffer(); InputFile *fetch(); - bool AddedToLink = false; private: uint64_t OffsetInArchive; diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index f0ad2c06d4792..dad52d8b03fc9 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -212,7 +212,7 @@ void BitcodeCompiler::add(BitcodeFile &F) { // distributed build system that depends on that behavior. static void thinLTOCreateEmptyIndexFiles() { for (LazyObjFile *F : LazyObjFiles) { - if (F->AddedToLink || !isBitcode(F->MB)) + if (!isBitcode(F->MB)) continue; std::string Path = replaceThinLTOSuffix(getThinLTOOutputFile(F->getName())); std::unique_ptr OS = openFile(Path + ".thinlto.bc"); From f5d9d2390592f36e594d8e9f3d4b4cc1733193d3 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 23 May 2019 10:15:12 +0000 Subject: [PATCH 0014/1176] Simplify InputFile::fetch(). We don't have to return a value from the function. Instead, we can directly call parseFile from the functions. llvm-svn: 361478 --- lld/ELF/InputFiles.cpp | 13 +++++++------ lld/ELF/InputFiles.h | 6 +++--- lld/ELF/Symbols.cpp | 6 ++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index dbfc867af7ee9..8a8bf6061e7d8 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1010,14 +1010,14 @@ void ArchiveFile::parse() { } // Returns a buffer pointing to a member file containing a given symbol. -InputFile *ArchiveFile::fetch(const Archive::Symbol &Sym) { +void ArchiveFile::fetch(const Archive::Symbol &Sym) { Archive::Child C = CHECK(Sym.getMember(), toString(this) + ": could not get the member for symbol " + Sym.getName()); if (!Seen.insert(C.getChildOffset()).second) - return nullptr; + return; MemoryBufferRef MB = CHECK(C.getMemoryBufferRef(), @@ -1031,7 +1031,7 @@ InputFile *ArchiveFile::fetch(const Archive::Symbol &Sym) { InputFile *File = createObjectFile( MB, getName(), C.getParent()->isThin() ? 0 : C.getChildOffset()); File->GroupId = GroupId; - return File; + parseFile(File); } unsigned SharedFile::VernauxNum; @@ -1469,9 +1469,9 @@ InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { return F; } -InputFile *LazyObjFile::fetch() { +void LazyObjFile::fetch() { if (MB.getBuffer().empty()) - return nullptr; + return; InputFile *File = createObjectFile(MB, ArchiveName, OffsetInArchive); File->GroupId = GroupId; @@ -1481,7 +1481,8 @@ InputFile *LazyObjFile::fetch() { // Copy symbol vector so that the new InputFile doesn't have to // insert the same defined symbols to the symbol table again. File->Symbols = std::move(Symbols); - return File; + + parseFile(File); } template void LazyObjFile::parse() { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 8b112e592503c..648f5b51452dc 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -307,7 +307,7 @@ class LazyObjFile : public InputFile { static bool classof(const InputFile *F) { return F->kind() == LazyObjKind; } template void parse(); - InputFile *fetch(); + void fetch(); private: uint64_t OffsetInArchive; @@ -322,9 +322,9 @@ class ArchiveFile : public InputFile { // Pulls out an object file that contains a definition for Sym and // returns it. If the same file was instantiated before, this - // function returns a nullptr (so we don't instantiate the same file + // function does nothing (so we don't instantiate the same file // more than once.) - InputFile *fetch(const Archive::Symbol &Sym); + void fetch(const Archive::Symbol &Sym); private: std::unique_ptr File; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 94f0d6ea6cb9d..d44b24dd1b37a 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -243,14 +243,12 @@ void Symbol::parseSymbolVersion() { void Symbol::fetch() const { if (auto *Sym = dyn_cast(this)) { - if (auto *F = cast(Sym->File)->fetch(Sym->Sym)) - parseFile(F); + cast(Sym->File)->fetch(Sym->Sym); return; } if (auto *Sym = dyn_cast(this)) { - if (auto *F = dyn_cast(Sym->File)->fetch()) - parseFile(F); + dyn_cast(Sym->File)->fetch(); return; } From e51b9e42b68c243dbc9b472f7c64c2c0fe821311 Mon Sep 17 00:00:00 2001 From: James Henderson Date: Thu, 23 May 2019 10:17:10 +0000 Subject: [PATCH 0015/1176] [llvm-objdump][test] Improve testing of some switches #2 This patch focuses on adding additional testing for the --source switch. For reference, the source-interleave-x86_64.ll test file has been split into two parts - the input (shared with the other tests) and the test itself. Reviewed by: MaskRay, rupprecht, grimar Differential Revision: https://reviews.llvm.org/D61996 llvm-svn: 361479 --- .../source-interleave.ll} | 19 ++-------- .../X86/source-interleave-invalid-source.test | 16 +++++++++ .../X86/source-interleave-missing-source.test | 15 ++++++++ .../X86/source-interleave-no-debug-info.test | 13 +++++++ .../X86/source-interleave-relative-paths.test | 36 +++++++++++++++++++ .../X86/source-interleave-x86_64.test | 17 +++++++++ 6 files changed, 100 insertions(+), 16 deletions(-) rename llvm/test/tools/llvm-objdump/X86/{source-interleave-x86_64.ll => Inputs/source-interleave.ll} (84%) create mode 100644 llvm/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test create mode 100644 llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test create mode 100644 llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test create mode 100644 llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test create mode 100644 llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.test diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.ll b/llvm/test/tools/llvm-objdump/X86/Inputs/source-interleave.ll similarity index 84% rename from llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.ll rename to llvm/test/tools/llvm-objdump/X86/Inputs/source-interleave.ll index 24a212028bf7a..1db42f5aaa8c2 100644 --- a/llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.ll +++ b/llvm/test/tools/llvm-objdump/X86/Inputs/source-interleave.ll @@ -1,13 +1,6 @@ -; RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %s > %t.ll -; RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll -; RUN: llvm-objdump -d -l %t.o >%t0 -; RUN: llvm-objdump -dl %t.o >%t1 -; RUN: llvm-objdump -d -S %t.o >%t2 -; RUN: llvm-objdump -dS %t.o >%t3 -; RUN: cmp %t0 %t1 -; RUN: cmp %t2 %t3 -; RUN: FileCheck --check-prefix=LINES %t.ll < %t0 -; RUN: FileCheck --check-prefix=SOURCE --strict-whitespace %t.ll < %t2 +; NOTE: To be able to use this file as an input, the string SRC_CMPDIR needs +; replacing with a directory path by using sed or similar. + ; ModuleID = 'source-interleave-x86_64.bc' source_filename = "source-interleave-x86_64.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @@ -71,9 +64,3 @@ attributes #1 = { nounwind readnone } !21 = !DILocation(line: 8, column: 15, scope: !14) !22 = !DILocation(line: 8, column: 13, scope: !14) !23 = !DILocation(line: 8, column: 3, scope: !14) -; LINES: main: -; LINES-NEXT: ; {{[ -\(\)_A-Za-z0-9.\\/:]+}}source-interleave-x86_64.c:6 - -; SOURCE: main: -; SOURCE-NEXT: ; int main() { -; SOURCE: ; int *b = &a; diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test new file mode 100644 index 0000000000000..e958173d16e90 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-invalid-source.test @@ -0,0 +1,16 @@ +## Test llvm-objdump's --source behaviour when a line number is greater than the +## file length. + +# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t.ll +# RUN: sed -e "s,line: 7,line: 9999,g" %t.ll > %t2.ll + +# RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll +# RUN: llc -o %t2.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll + +# RUN: llvm-objdump --source %t.o | FileCheck %s --check-prefixes=CHECK,GOOD +# RUN: llvm-objdump --source %t2.o | FileCheck %s --implicit-check-not="int *b = &a;" + +# CHECK: main: +# CHECK-NEXT: ; int main() { +# GOOD: ; int *b = &a; +# CHECK: ; return *b + foo(); diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test new file mode 100644 index 0000000000000..166caeb41b50d --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test @@ -0,0 +1,15 @@ +## Test that if the source cannot be found that disassembly is still printed, +## and that no source is printed. + +# RUN: sed -e "s,SRC_COMPDIR,%/t,g" %p/Inputs/source-interleave.ll > %t.ll +# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t2.ll + +# RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll +# RUN: llc -o %t2.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll + +# RUN: llvm-objdump --source %t.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source %t2.o | FileCheck %s --check-prefixes=CHECK,SOURCE + +# CHECK: 0000000000000010 main: +# SOURCE-NEXT: ; int main() { +# CHECK-NEXT: 10: 55 pushq %rbp diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test new file mode 100644 index 0000000000000..4a0a34a9eae0e --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test @@ -0,0 +1,13 @@ +## Test that if an object has no debug information, only the disassembly is +## printed when --source is specified. + +# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t.ll +# RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll +# RUN: llvm-objcopy --strip-debug %t.o %t2.o + +# RUN: llvm-objdump --source %t.o | FileCheck %s --check-prefixes=CHECK,SOURCE +# RUN: llvm-objdump --source %t2.o | FileCheck %s --implicit-check-not=main + +# CHECK: 0000000000000010 main: +# SOURCE-NEXT: ; int main() { +# CHECK-NEXT: 10: 55 pushq %rbp diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test new file mode 100644 index 0000000000000..f9c69dfc0c06a --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test @@ -0,0 +1,36 @@ +## Test that llvm-objdump prints source and disassembly for relative directory +## paths for appropriate working directories. We also test that when the directory +## string is empty the behaviour is the same as the current working directory. + +# RUN: mkdir -p %t/a/b +# RUN: cp %p/Inputs/source-interleave-x86_64.c %t/a/source-interleave-x86_64.c + +# RUN: sed -e "s,SRC_COMPDIR,a,g" %p/Inputs/source-interleave.ll > %t.ll +# RUN: sed -e "s,SRC_COMPDIR,,g" %p/Inputs/source-interleave.ll > %t2.ll +# RUN: sed -e "s,SRC_COMPDIR,.,g" %p/Inputs/source-interleave.ll > %t3.ll +# RUN: sed -e "s,SRC_COMPDIR,..,g" %p/Inputs/source-interleave.ll > %t4.ll + +# RUN: llc -o %t/a/a.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll +# RUN: llc -o %t/a/b.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll +# RUN: llc -o %t/a/c.o -filetype=obj -mtriple=x86_64-pc-linux %t3.ll +# RUN: llc -o %t/a/d.o -filetype=obj -mtriple=x86_64-pc-linux %t4.ll + +# RUN: cd %t +# RUN: llvm-objdump --source a/a.o | FileCheck %s --check-prefixes=CHECK,SOURCE +# RUN: llvm-objdump --source a/b.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source a/c.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source a/d.o | FileCheck %s --implicit-check-not=main +# RUN: cd a +# RUN: llvm-objdump --source a.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source b.o | FileCheck %s --check-prefixes=CHECK,SOURCE +# RUN: llvm-objdump --source c.o | FileCheck %s --check-prefixes=CHECK,SOURCE +# RUN: llvm-objdump --source d.o | FileCheck %s --implicit-check-not=main +# RUN: cd b +# RUN: llvm-objdump --source ../a.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source ../b.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source ../c.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source ../d.o | FileCheck %s --check-prefixes=CHECK,SOURCE + +# CHECK: 0000000000000010 main: +# SOURCE-NEXT: ; int main() { +# CHECK-NEXT: 10: 55 pushq %rbp diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.test new file mode 100644 index 0000000000000..63a6c0571802a --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-x86_64.test @@ -0,0 +1,17 @@ +# RUN: sed -e "s,SRC_COMPDIR,%/p/Inputs,g" %p/Inputs/source-interleave.ll > %t.ll +# RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll +# RUN: llvm-objdump -d -l %t.o >%t0 +# RUN: llvm-objdump -dl %t.o >%t1 +# RUN: llvm-objdump -d -S %t.o >%t2 +# RUN: llvm-objdump -dS %t.o >%t3 +# RUN: cmp %t0 %t1 +# RUN: cmp %t2 %t3 +# RUN: FileCheck --check-prefix=LINES %s < %t0 +# RUN: FileCheck --check-prefix=SOURCE --strict-whitespace %s < %t2 + +# LINES: main: +# LINES-NEXT: ; {{[ -\(\)_A-Za-z0-9.\\/:]+}}source-interleave-x86_64.c:6 + +# SOURCE: main: +# SOURCE-NEXT: ; int main() { +# SOURCE: ; int *b = &a; From ff47d83e7820f0342ee5d0b98f8b66a84bfee350 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Thu, 23 May 2019 10:37:13 +0000 Subject: [PATCH 0016/1176] [DwarfExpression] Refactor dwarf expression (NFC) Refactor location description kind in order to be easier for extensions (needed for D60866). In addition, cut off some bits from the other class fields. Patch by Djordje Todorovic. Differential Revision: https://reviews.llvm.org/D62002 llvm-svn: 361480 --- .../CodeGen/AsmPrinter/DwarfExpression.cpp | 28 ++++++------- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h | 39 ++++++++++++++----- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index 1235c14900574..c7c283202022e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -40,7 +40,7 @@ void DwarfExpression::emitConstu(uint64_t Value) { void DwarfExpression::addReg(int DwarfReg, const char *Comment) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); - assert((LocationKind == Unknown || LocationKind == Register) && + assert((isUnknownLocation() || isRegisterLocation()) && "location description already locked down"); LocationKind = Register; if (DwarfReg < 32) { @@ -53,7 +53,7 @@ void DwarfExpression::addReg(int DwarfReg, const char *Comment) { void DwarfExpression::addBReg(int DwarfReg, int Offset) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); - assert(LocationKind != Register && "location description already locked down"); + assert(!isRegisterLocation() && "location description already locked down"); if (DwarfReg < 32) { emitOp(dwarf::DW_OP_breg0 + DwarfReg); } else { @@ -184,20 +184,20 @@ void DwarfExpression::addStackValue() { } void DwarfExpression::addSignedConstant(int64_t Value) { - assert(LocationKind == Implicit || LocationKind == Unknown); + assert(isImplicitLocation() || isUnknownLocation()); LocationKind = Implicit; emitOp(dwarf::DW_OP_consts); emitSigned(Value); } void DwarfExpression::addUnsignedConstant(uint64_t Value) { - assert(LocationKind == Implicit || LocationKind == Unknown); + assert(isImplicitLocation() || isUnknownLocation()); LocationKind = Implicit; emitConstu(Value); } void DwarfExpression::addUnsignedConstant(const APInt &Value) { - assert(LocationKind == Implicit || LocationKind == Unknown); + assert(isImplicitLocation() || isUnknownLocation()); LocationKind = Implicit; unsigned Size = Value.getBitWidth(); @@ -242,7 +242,7 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, } // Handle simple register locations. - if (LocationKind != Memory && !HasComplexExpression) { + if (!isMemoryLocation() && !HasComplexExpression) { for (auto &Reg : DwarfRegs) { if (Reg.DwarfRegNo >= 0) addReg(Reg.DwarfRegNo, Reg.Comment); @@ -343,7 +343,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, SizeInBits = std::min(SizeInBits, SubRegisterSizeInBits); // Emit a DW_OP_stack_value for implicit location descriptions. - if (LocationKind == Implicit) + if (isImplicitLocation()) addStackValue(); // Emit the DW_OP_piece. @@ -354,7 +354,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, return; } case dwarf::DW_OP_plus_uconst: - assert(LocationKind != Register); + assert(!isRegisterLocation()); emitOp(dwarf::DW_OP_plus_uconst); emitUnsigned(Op->getArg(0)); break; @@ -375,8 +375,8 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, emitOp(Op->getOp()); break; case dwarf::DW_OP_deref: - assert(LocationKind != Register); - if (LocationKind != Memory && ::isMemoryLocation(ExprCursor)) + assert(!isRegisterLocation()); + if (!isMemoryLocation() && ::isMemoryLocation(ExprCursor)) // Turning this into a memory location description makes the deref // implicit. LocationKind = Memory; @@ -384,7 +384,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, emitOp(dwarf::DW_OP_deref); break; case dwarf::DW_OP_constu: - assert(LocationKind != Register); + assert(!isRegisterLocation()); emitConstu(Op->getArg(0)); break; case dwarf::DW_OP_LLVM_convert: { @@ -427,11 +427,11 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, LocationKind = Implicit; break; case dwarf::DW_OP_swap: - assert(LocationKind != Register); + assert(!isRegisterLocation()); emitOp(dwarf::DW_OP_swap); break; case dwarf::DW_OP_xderef: - assert(LocationKind != Register); + assert(!isRegisterLocation()); emitOp(dwarf::DW_OP_xderef); break; case dwarf::DW_OP_deref_size: @@ -443,7 +443,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, } } - if (LocationKind == Implicit) + if (isImplicitLocation()) // Turn this into an implicit location description. addStackValue(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 145504946a5cb..6985debe6138f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -111,18 +111,40 @@ class DwarfExpression { /// Current Fragment Offset in Bits. uint64_t OffsetInBits = 0; - unsigned DwarfVersion; /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. - unsigned SubRegisterSizeInBits = 0; - unsigned SubRegisterOffsetInBits = 0; + unsigned SubRegisterSizeInBits : 16; + unsigned SubRegisterOffsetInBits : 16; /// The kind of location description being produced. - enum { Unknown = 0, Register, Memory, Implicit } LocationKind = Unknown; + enum { Unknown = 0, Register, Memory, Implicit }; + unsigned LocationKind : 3; + unsigned LocationFlags : 2; + unsigned DwarfVersion : 4; + +public: + bool isUnknownLocation() const { + return LocationKind == Unknown; + } + + bool isMemoryLocation() const { + return LocationKind == Memory; + } + + bool isRegisterLocation() const { + return LocationKind == Register; + } + + bool isImplicitLocation() const { + return LocationKind == Implicit; + } + +protected: /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed /// to represent a subregister. void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { + assert(SizeInBits < 65536 && OffsetInBits < 65536); SubRegisterSizeInBits = SizeInBits; SubRegisterOffsetInBits = OffsetInBits; } @@ -206,7 +228,9 @@ class DwarfExpression { public: DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) - : CU(CU), DwarfVersion(DwarfVersion) {} + : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0), + LocationKind(Unknown), LocationFlags(Unknown), + DwarfVersion(DwarfVersion) {} /// This needs to be called last to commit any pending changes. void finalize(); @@ -220,12 +244,9 @@ class DwarfExpression { /// Emit an unsigned constant. void addUnsignedConstant(const APInt &Value); - bool isMemoryLocation() const { return LocationKind == Memory; } - bool isUnknownLocation() const { return LocationKind == Unknown; } - /// Lock this down to become a memory location description. void setMemoryLocationKind() { - assert(LocationKind == Unknown); + assert(isUnknownLocation()); LocationKind = Memory; } From f95b05c3df6eccb66d934c6529091400195d57ff Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 23 May 2019 10:46:35 +0000 Subject: [PATCH 0017/1176] Add REQUIRES: lld to debug-types-address-ranges.s This should fix the green dragon bots. llvm-svn: 361481 --- lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s b/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s index 892c93d3822cc..5fc7c41955c35 100644 --- a/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s +++ b/lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s @@ -4,6 +4,8 @@ # compute address range for the type unit as type units don't describe any # addresses. The addresses should always resolve to the relevant compile units. +# REQUIRES: lld + # RUN: llvm-mc -dwarf-version=5 -triple x86_64-pc-linux %s -filetype=obj >%t.o # RUN: ld.lld %t.o -o %t -image-base=0x47000 # RUN: %lldb %t -o "image lookup -a 0x48000 -v" -o exit | FileCheck %s From 28afd8dc711261aeb082739740e86d28d1a50082 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Thu, 23 May 2019 10:50:01 +0000 Subject: [PATCH 0018/1176] [MCA] Make the bool conversion operator in class InstRef explicit. NFCI This patch makes the bool conversion operator in InstRef explicit. It also adds a operator< to hel comparing InstRef objects in sets. llvm-svn: 361482 --- llvm/include/llvm/MCA/Instruction.h | 6 +++++- llvm/lib/MCA/Stages/EntryStage.cpp | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h index 0cb6f6cd4170f..a7a47fd3645ed 100644 --- a/llvm/include/llvm/MCA/Instruction.h +++ b/llvm/include/llvm/MCA/Instruction.h @@ -526,13 +526,17 @@ class InstRef { InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {} bool operator==(const InstRef &Other) const { return Data == Other.Data; } + bool operator!=(const InstRef &Other) const { return Data != Other.Data; } + bool operator<(const InstRef &Other) const { + return Data.first < Other.Data.first; + } unsigned getSourceIndex() const { return Data.first; } Instruction *getInstruction() { return Data.second; } const Instruction *getInstruction() const { return Data.second; } /// Returns true if this references a valid instruction. - operator bool() const { return Data.second != nullptr; } + explicit operator bool() const { return Data.second != nullptr; } /// Invalidate this reference. void invalidate() { Data.second = nullptr; } diff --git a/llvm/lib/MCA/Stages/EntryStage.cpp b/llvm/lib/MCA/Stages/EntryStage.cpp index 2028b9e2b765c..d2f5613a0fb6e 100644 --- a/llvm/lib/MCA/Stages/EntryStage.cpp +++ b/llvm/lib/MCA/Stages/EntryStage.cpp @@ -18,7 +18,9 @@ namespace llvm { namespace mca { -bool EntryStage::hasWorkToComplete() const { return CurrentInstruction; } +bool EntryStage::hasWorkToComplete() const { + return static_cast(CurrentInstruction); +} bool EntryStage::isAvailable(const InstRef & /* unused */) const { if (CurrentInstruction) From 32d976bac194d78656974e3e05bf52997a06f509 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 10:55:13 +0000 Subject: [PATCH 0019/1176] [NFC][X86] Fix check prefixes and autogenerate fold-pcmpeqd-2.ll test Being affected by (sub %x, c) -> (add %x, (sub 0, c)) patch in an uncertain way. llvm-svn: 361483 --- llvm/test/CodeGen/X86/fold-pcmpeqd-2.ll | 176 ++++++++++++++++++++++-- 1 file changed, 168 insertions(+), 8 deletions(-) diff --git a/llvm/test/CodeGen/X86/fold-pcmpeqd-2.ll b/llvm/test/CodeGen/X86/fold-pcmpeqd-2.ll index d95c6323de4ee..55c3287028caa 100644 --- a/llvm/test/CodeGen/X86/fold-pcmpeqd-2.ll +++ b/llvm/test/CodeGen/X86/fold-pcmpeqd-2.ll @@ -1,5 +1,6 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin -mcpu=yonah -regalloc=basic | FileCheck %s -; RUN: llc < %s -mtriple=x86_64-apple-darwin -regalloc=basic | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i386-apple-darwin -mcpu=yonah -regalloc=basic | FileCheck %s --check-prefixes=ALL,X32 +; RUN: llc < %s -mtriple=x86_64-apple-darwin -regalloc=basic | FileCheck %s --check-prefixes=ALL,X64 ; This testcase should need to spill the -1 value on both x86-32 and x86-64, ; so it shouldn't use pcmpeqd to materialize an all-ones vector; it @@ -7,18 +8,177 @@ ; ; RAGreedy defeats the test by splitting live ranges. -; Constant pool all-ones vector: -; CHECK: .space 16,255 - -; No pcmpeqd instructions, everybody uses the constant pool. -; CHECK-LABEL: program_1: -; CHECK-NOT: pcmpeqd +; There should be no pcmpeqd instructions, everybody should the constant pool. %struct.__ImageExecInfo = type <{ <4 x i32>, <4 x float>, <2 x i64>, i8*, i8*, i8*, i32, i32, i32, i32, i32 }> %struct._cl_image_format_t = type <{ i32, i32, i32 }> %struct._image2d_t = type <{ i8*, %struct._cl_image_format_t, i32, i32, i32, i32, i32, i32 }> define void @program_1(%struct._image2d_t* %dest, %struct._image2d_t* %t0, <4 x float> %p0, <4 x float> %p1, <4 x float> %p4, <4 x float> %p5, <4 x float> %p6) nounwind { +; X32-LABEL: program_1: +; X32: ## %bb.0: ## %entry +; X32-NEXT: cmpl $0, 0 +; X32-NEXT: jle LBB0_2 +; X32-NEXT: ## %bb.1: ## %forcond +; X32-NEXT: cmpl $0, 0 +; X32-NEXT: jg LBB0_3 +; X32-NEXT: LBB0_2: ## %ifthen +; X32-NEXT: retl +; X32-NEXT: LBB0_3: ## %forbody +; X32-NEXT: pushl %esi +; X32-NEXT: subl $88, %esp +; X32-NEXT: movaps {{.*#+}} xmm1 = [1.28E+2,1.28E+2,1.28E+2,1.28E+2] +; X32-NEXT: minps LCPI0_3, %xmm1 +; X32-NEXT: cvttps2dq %xmm1, %xmm0 +; X32-NEXT: cvtdq2ps %xmm0, %xmm0 +; X32-NEXT: subps %xmm0, %xmm1 +; X32-NEXT: movaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: mulps LCPI0_3, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: addps LCPI0_1, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: mulps %xmm1, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: addps LCPI0_2, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movdqa {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: psubd LCPI0_4, %xmm0 +; X32-NEXT: movdqa %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: mulps LCPI0_3, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: xorps %xmm0, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: mulps %xmm0, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: mulps LCPI0_3, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: xorps %xmm0, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: cmpunordps %xmm0, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: minps LCPI0_3, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: xorps %xmm0, %xmm0 +; X32-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) +; X32-NEXT: movl $0, (%esp) +; X32-NEXT: xorl %esi, %esi +; X32-NEXT: xorps %xmm3, %xmm3 +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: movdqa {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 ## 16-byte Reload +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 ## 16-byte Reload +; X32-NEXT: calll *%esi +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: minps LCPI0_3, %xmm0 +; X32-NEXT: movaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: pxor %xmm1, %xmm1 +; X32-NEXT: psubd {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 ## 16-byte Folded Reload +; X32-NEXT: movdqa {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: psubd LCPI0_4, %xmm0 +; X32-NEXT: movdqa %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: movdqa {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: por %xmm1, %xmm0 +; X32-NEXT: movdqa %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill +; X32-NEXT: pxor %xmm0, %xmm0 +; X32-NEXT: movdqa %xmm0, {{[0-9]+}}(%esp) +; X32-NEXT: movl $0, (%esp) +; X32-NEXT: xorps %xmm3, %xmm3 +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm1 ## 16-byte Reload +; X32-NEXT: movaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm2 ## 16-byte Reload +; X32-NEXT: calll *%esi +; X32-NEXT: ud2 +; +; X64-LABEL: program_1: +; X64: ## %bb.0: ## %entry +; X64-NEXT: cmpl $0, 0 +; X64-NEXT: jle LBB0_2 +; X64-NEXT: ## %bb.1: ## %forcond +; X64-NEXT: cmpl $0, 0 +; X64-NEXT: jg LBB0_3 +; X64-NEXT: LBB0_2: ## %ifthen +; X64-NEXT: retq +; X64-NEXT: LBB0_3: ## %forbody +; X64-NEXT: pushq %rbx +; X64-NEXT: subq $64, %rsp +; X64-NEXT: xorps %xmm0, %xmm0 +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movaps {{.*#+}} xmm1 = [1.28E+2,1.28E+2,1.28E+2,1.28E+2] +; X64-NEXT: minps {{.*}}(%rip), %xmm1 +; X64-NEXT: cvttps2dq %xmm1, %xmm0 +; X64-NEXT: cvtdq2ps %xmm0, %xmm0 +; X64-NEXT: subps %xmm0, %xmm1 +; X64-NEXT: movaps %xmm1, (%rsp) ## 16-byte Spill +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: mulps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: addps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: mulps %xmm1, %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: addps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: movdqa (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: psubd {{.*}}(%rip), %xmm0 +; X64-NEXT: movdqa %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: mulps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: xorps %xmm0, %xmm0 +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: mulps %xmm0, %xmm0 +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: mulps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: xorps %xmm0, %xmm0 +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: cmpunordps %xmm0, %xmm0 +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: minps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: xorl %ebx, %ebx +; X64-NEXT: xorps %xmm3, %xmm3 +; X64-NEXT: xorps %xmm4, %xmm4 +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 ## 16-byte Reload +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 ## 16-byte Reload +; X64-NEXT: xorl %edi, %edi +; X64-NEXT: callq *%rbx +; X64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload +; X64-NEXT: minps {{.*}}(%rip), %xmm0 +; X64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill +; X64-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: psubd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Folded Reload +; X64-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: psubd {{.*}}(%rip), %xmm0 +; X64-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: orps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Folded Reload +; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill +; X64-NEXT: xorps %xmm3, %xmm3 +; X64-NEXT: xorps %xmm4, %xmm4 +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 ## 16-byte Reload +; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 ## 16-byte Reload +; X64-NEXT: movaps (%rsp), %xmm2 ## 16-byte Reload +; X64-NEXT: xorl %edi, %edi +; X64-NEXT: callq *%rbx +; X64-NEXT: ud2 entry: %tmp3.i = load i32, i32* null ; [#uses=1] %cmp = icmp slt i32 0, %tmp3.i ; [#uses=1] From 248a13057a4adbdb8d511b1458daf39d01a4b520 Mon Sep 17 00:00:00 2001 From: Konrad Kleine Date: Thu, 23 May 2019 11:14:47 +0000 Subject: [PATCH 0020/1176] [lldb] NFC modernize codebase with modernize-use-nullptr Summary: NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]] This commit is the result of modernizing the LLDB codebase by using `nullptr` instread of `0` or `NULL`. See https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html for more information. This is the command I ran and I to fix and format the code base: ``` run-clang-tidy.py \ -header-filter='.*' \ -checks='-*,modernize-use-nullptr' \ -fix ~/dev/llvm-project/lldb/.* \ -format \ -style LLVM \ -p ~/llvm-builds/debug-ninja-gcc ``` NOTE: There were also changes to `llvm/utils/unittest` but I did not include them because I felt that maybe this library shall be updated in isolation somehow. NOTE: I know this is a rather large commit but it is a nobrainer in most parts. Reviewers: martong, espindola, shafik, #lldb, JDevlieghere Reviewed By: JDevlieghere Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits Tags: #lldb, #llvm Differential Revision: https://reviews.llvm.org/D61847 llvm-svn: 361484 --- .../lldb/Breakpoint/BreakpointResolver.h | 2 +- lldb/source/API/SBAddress.cpp | 6 +- lldb/source/API/SBBlock.cpp | 12 +- lldb/source/API/SBBreakpointLocation.cpp | 6 +- lldb/source/API/SBBroadcaster.cpp | 19 +- lldb/source/API/SBCommunication.cpp | 12 +- lldb/source/API/SBCompileUnit.cpp | 10 +- lldb/source/API/SBData.cpp | 10 +- lldb/source/API/SBDeclaration.cpp | 2 +- lldb/source/API/SBError.cpp | 9 +- lldb/source/API/SBEvent.cpp | 6 +- lldb/source/API/SBFunction.cpp | 16 +- lldb/source/API/SBHostOS.cpp | 5 +- lldb/source/API/SBInstruction.cpp | 13 +- lldb/source/API/SBInstructionList.cpp | 8 +- lldb/source/API/SBLineEntry.cpp | 2 +- lldb/source/API/SBListener.cpp | 20 +- lldb/source/API/SBModule.cpp | 23 +- lldb/source/API/SBPlatform.cpp | 28 +- lldb/source/API/SBProcess.cpp | 10 +- lldb/source/API/SBQueue.cpp | 4 +- lldb/source/API/SBQueueItem.cpp | 2 +- lldb/source/API/SBSection.cpp | 4 +- lldb/source/API/SBSourceManager.cpp | 2 +- lldb/source/API/SBStream.cpp | 10 +- lldb/source/API/SBStringList.cpp | 10 +- lldb/source/API/SBSymbol.cpp | 18 +- lldb/source/API/SBSymbolContext.cpp | 17 +- lldb/source/API/SBSymbolContextList.cpp | 4 +- lldb/source/API/SBTarget.cpp | 54 ++-- lldb/source/API/SBThread.cpp | 22 +- lldb/source/API/SBThreadCollection.cpp | 2 +- lldb/source/API/SBThreadPlan.cpp | 4 +- lldb/source/API/SBType.cpp | 16 +- lldb/source/API/SBTypeCategory.cpp | 4 +- lldb/source/API/SBTypeEnumMember.cpp | 6 +- lldb/source/API/SBTypeFilter.cpp | 4 +- lldb/source/API/SBTypeFormat.cpp | 2 +- lldb/source/API/SBTypeNameSpecifier.cpp | 8 +- lldb/source/API/SBTypeSummary.cpp | 4 +- lldb/source/API/SBTypeSynthetic.cpp | 4 +- lldb/source/API/SBValue.cpp | 26 +- lldb/source/API/SBValueList.cpp | 4 +- lldb/source/API/SBWatchpoint.cpp | 4 +- .../Breakpoint/BreakpointResolverAddress.cpp | 2 +- .../Breakpoint/BreakpointResolverFileLine.cpp | 2 +- .../BreakpointResolverFileRegex.cpp | 4 +- .../Breakpoint/BreakpointResolverScripted.cpp | 4 +- .../source/Commands/CommandObjectExpression.h | 2 +- lldb/source/Core/Communication.cpp | 2 +- lldb/source/Core/Debugger.cpp | 4 +- lldb/source/Core/Mangled.cpp | 2 +- lldb/source/Core/Section.cpp | 14 +- lldb/source/Core/SourceManager.cpp | 10 +- lldb/source/Core/Value.cpp | 30 +- lldb/source/Core/ValueObject.cpp | 67 ++-- .../Core/ValueObjectConstResultImpl.cpp | 20 +- lldb/source/Core/ValueObjectMemory.cpp | 2 +- lldb/source/Core/ValueObjectRegister.cpp | 20 +- lldb/source/Core/ValueObjectVariable.cpp | 8 +- .../DataFormatters/DataVisualization.cpp | 2 +- lldb/source/DataFormatters/FormatManager.cpp | 12 +- .../DataFormatters/FormattersHelpers.cpp | 2 +- lldb/source/DataFormatters/StringPrinter.cpp | 8 +- lldb/source/DataFormatters/TypeFormat.cpp | 2 +- lldb/source/DataFormatters/TypeSynthetic.cpp | 18 +- .../DataFormatters/ValueObjectPrinter.cpp | 7 +- lldb/source/Expression/DWARFExpression.cpp | 12 +- lldb/source/Expression/ExpressionVariable.cpp | 2 +- lldb/source/Expression/FunctionCaller.cpp | 21 +- lldb/source/Expression/IRExecutionUnit.cpp | 8 +- lldb/source/Expression/IRInterpreter.cpp | 2 +- lldb/source/Expression/IRMemoryMap.cpp | 2 +- lldb/source/Expression/LLVMUserExpression.cpp | 4 +- lldb/source/Expression/UserExpression.cpp | 6 +- lldb/source/Host/common/Editline.cpp | 14 +- lldb/source/Host/common/File.cpp | 8 +- lldb/source/Host/common/Host.cpp | 8 +- .../Host/common/HostNativeThreadBase.cpp | 8 +- lldb/source/Host/common/OptionParser.cpp | 6 +- lldb/source/Host/common/ProcessRunLock.cpp | 2 +- lldb/source/Host/common/SocketAddress.cpp | 6 +- lldb/source/Host/common/TCPSocket.cpp | 4 +- lldb/source/Host/common/TaskPool.cpp | 2 +- lldb/source/Host/common/Terminal.cpp | 6 +- lldb/source/Host/common/ThreadLauncher.cpp | 2 +- lldb/source/Host/common/XML.cpp | 2 +- lldb/source/Host/linux/Host.cpp | 8 +- lldb/source/Host/linux/HostInfoLinux.cpp | 3 +- .../posix/ConnectionFileDescriptorPosix.cpp | 2 +- lldb/source/Host/posix/HostThreadPosix.cpp | 2 +- .../source/Interpreter/CommandInterpreter.cpp | 6 +- lldb/source/Interpreter/OptionValue.cpp | 6 +- .../Plugins/ABI/SysV-arm/ABISysV_arm.cpp | 6 +- .../Disassembler/llvm/DisassemblerLLVMC.cpp | 16 +- .../DynamicLoaderDarwinKernel.cpp | 42 +-- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 4 +- .../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 29 +- .../MacOSX-DYLD/DynamicLoaderMacOS.cpp | 4 +- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 14 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 6 +- .../Static/DynamicLoaderStatic.cpp | 2 +- .../ExpressionParser/Clang/ASTDumper.cpp | 2 +- .../Clang/ASTResultSynthesizer.cpp | 18 +- .../Clang/ASTStructExtractor.cpp | 12 +- .../ExpressionParser/Clang/ClangASTSource.cpp | 55 ++-- .../ExpressionParser/Clang/ClangASTSource.h | 6 +- .../Clang/ClangExpressionDeclMap.cpp | 39 +-- .../Clang/ClangExpressionDeclMap.h | 15 +- .../Clang/ClangExpressionParser.cpp | 2 +- .../Clang/ClangExpressionVariable.h | 8 +- .../Clang/ClangFunctionCaller.h | 2 +- .../Clang/ClangPersistentVariables.cpp | 4 +- .../Clang/ClangUserExpression.cpp | 2 +- .../Clang/ClangUtilityFunction.cpp | 2 +- .../ExpressionParser/Clang/IRForTarget.cpp | 55 ++-- .../Instruction/ARM/EmulateInstructionARM.cpp | 14 +- .../Instruction/ARM/EmulationStateARM.cpp | 14 +- .../ARM64/EmulateInstructionARM64.cpp | 4 +- .../MIPS/EmulateInstructionMIPS.cpp | 10 +- .../MIPS64/EmulateInstructionMIPS64.cpp | 10 +- .../ASan/ASanRuntime.cpp | 2 +- .../TSan/TSanRuntime.cpp | 2 +- .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 10 +- .../AppleObjCRuntime/AppleObjCDeclVendor.cpp | 27 +- .../AppleObjCRuntime/AppleObjCRuntime.cpp | 10 +- .../AppleObjCRuntime/AppleObjCRuntimeV1.cpp | 4 +- .../AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 28 +- .../AppleObjCTrampolineHandler.cpp | 16 +- .../AppleObjCTrampolineHandler.h | 5 +- ...pleThreadPlanStepThroughObjCTrampoline.cpp | 4 +- .../MemoryHistory/asan/MemoryHistoryASan.cpp | 2 +- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 10 +- .../BSD-Archive/ObjectContainerBSDArchive.h | 2 +- .../ObjectContainerUniversalMachO.cpp | 2 +- .../Plugins/ObjectFile/ELF/ELFHeader.cpp | 32 +- .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 30 +- .../Plugins/ObjectFile/JIT/ObjectFileJIT.cpp | 12 +- .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 298 +++++++++--------- .../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 10 +- .../Python/OperatingSystemPython.cpp | 16 +- .../Platform/FreeBSD/PlatformFreeBSD.cpp | 4 +- .../Plugins/Platform/Linux/PlatformLinux.cpp | 4 +- .../Platform/MacOSX/PlatformDarwin.cpp | 16 +- .../Platform/MacOSX/PlatformMacOSX.cpp | 4 +- .../MacOSX/PlatformRemoteDarwinDevice.cpp | 24 +- .../Platform/NetBSD/PlatformNetBSD.cpp | 4 +- .../Plugins/Platform/POSIX/PlatformPOSIX.cpp | 22 +- .../gdb-server/PlatformRemoteGDBServer.cpp | 23 +- .../NativeRegisterContextLinux_x86_64.cpp | 10 +- .../Plugins/Process/Linux/ProcessorTrace.cpp | 4 +- .../Plugins/Process/POSIX/ProcessMessage.cpp | 2 +- .../Process/Utility/DynamicRegisterInfo.cpp | 20 +- .../Plugins/Process/Utility/HistoryThread.cpp | 2 +- .../Process/Utility/InferiorCallPOSIX.cpp | 6 +- .../Utility/RegisterContextDarwin_arm.cpp | 102 +++--- .../Utility/RegisterContextDarwin_arm64.cpp | 4 +- .../Utility/RegisterContextDarwin_i386.cpp | 28 +- .../Utility/RegisterContextDarwin_x86_64.cpp | 38 +-- .../Process/Utility/RegisterContextDummy.cpp | 8 +- .../Utility/RegisterContextFreeBSD_i386.cpp | 2 +- .../RegisterContextFreeBSD_powerpc.cpp | 2 +- .../Utility/RegisterContextHistory.cpp | 8 +- .../Process/Utility/RegisterContextLLDB.cpp | 20 +- .../Utility/RegisterContextLinux_i386.cpp | 6 +- .../Utility/RegisterContextLinux_mips.cpp | 2 +- .../Utility/RegisterContextLinux_x86_64.cpp | 4 +- .../Utility/RegisterContextOpenBSD_i386.cpp | 2 +- .../Utility/RegisterContextPOSIX_arm.cpp | 6 +- .../Utility/RegisterContextPOSIX_arm64.cpp | 6 +- .../Utility/RegisterContextPOSIX_mips64.cpp | 2 +- .../Utility/RegisterContextPOSIX_powerpc.cpp | 4 +- .../Utility/RegisterContextPOSIX_ppc64le.cpp | 4 +- .../Utility/RegisterContextPOSIX_s390x.cpp | 6 +- .../Utility/RegisterContextPOSIX_x86.cpp | 6 +- .../Utility/RegisterContextThreadMemory.cpp | 4 +- .../Process/Utility/RegisterInfoPOSIX_arm.cpp | 2 +- .../Utility/RegisterInfoPOSIX_arm64.cpp | 2 +- .../Utility/RegisterInfoPOSIX_ppc64le.cpp | 2 +- .../Process/Utility/StopInfoMachException.cpp | 8 +- .../Plugins/Process/Utility/UnwindLLDB.cpp | 12 +- .../Utility/UnwindMacOSXFrameBackchain.cpp | 8 +- .../Process/elf-core/ProcessElfCore.cpp | 10 +- .../Plugins/Process/elf-core/ThreadElfCore.h | 2 +- .../gdb-remote/GDBRemoteClientBase.cpp | 4 +- .../gdb-remote/GDBRemoteCommunication.cpp | 18 +- .../GDBRemoteCommunicationClient.cpp | 10 +- .../gdb-remote/GDBRemoteRegisterContext.cpp | 37 +-- .../Process/gdb-remote/ProcessGDBRemote.cpp | 93 +++--- .../Process/mach-core/ProcessMachCore.cpp | 14 +- .../Process/minidump/ProcessMinidump.cpp | 3 +- .../Python/ScriptInterpreterPython.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 48 +-- .../SymbolFile/DWARF/DWARFDebugAbbrev.cpp | 4 +- .../SymbolFile/DWARF/DWARFDebugAranges.cpp | 2 +- .../SymbolFile/DWARF/DWARFDebugInfo.cpp | 4 +- .../Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 4 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 28 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.h | 23 +- .../SymbolFile/DWARF/DWARFDebugLine.cpp | 2 +- .../SymbolFile/DWARF/DWARFDebugRanges.cpp | 2 +- .../SymbolFile/DWARF/DWARFDeclContext.cpp | 4 +- .../SymbolFile/DWARF/DWARFDeclContext.h | 2 +- .../SymbolFile/DWARF/DWARFFormValue.cpp | 6 +- .../Plugins/SymbolFile/DWARF/DWARFFormValue.h | 2 +- .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 9 +- .../SymbolFile/DWARF/HashedNameToDIE.cpp | 6 +- .../SymbolFile/DWARF/ManualDWARFIndex.cpp | 10 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 125 ++++---- .../SymbolFile/DWARF/SymbolFileDWARF.h | 2 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 56 ++-- .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 4 +- .../SymbolFile/Symtab/SymbolFileSymtab.cpp | 12 +- .../SymbolVendor/ELF/SymbolVendorELF.cpp | 12 +- .../MacOSX/AppleGetItemInfoHandler.cpp | 2 +- .../MacOSX/AppleGetPendingItemsHandler.cpp | 4 +- .../MacOSX/AppleGetQueuesHandler.cpp | 4 +- .../MacOSX/AppleGetThreadItemInfoHandler.cpp | 2 +- .../MacOSX/SystemRuntimeMacOSX.cpp | 17 +- .../UnwindAssemblyInstEmulation.cpp | 10 +- .../UnwindAssemblyInstEmulation.h | 2 +- .../UnwindAssembly/x86/UnwindAssembly-x86.cpp | 2 +- lldb/source/Symbol/ClangASTContext.cpp | 12 +- lldb/source/Symbol/ClangASTImporter.cpp | 12 +- lldb/source/Symbol/CompactUnwindInfo.cpp | 2 +- lldb/source/Symbol/CompilerType.cpp | 4 +- lldb/source/Symbol/LocateSymbolFile.cpp | 7 +- lldb/source/Symbol/SymbolContext.cpp | 2 +- lldb/source/Symbol/Symtab.cpp | 2 +- lldb/source/Symbol/Type.cpp | 2 +- lldb/source/Target/CPPLanguageRuntime.cpp | 2 +- lldb/source/Target/Process.cpp | 6 +- lldb/source/Target/SectionLoadHistory.cpp | 2 +- lldb/source/Target/StopInfo.cpp | 2 +- .../Target/ThreadPlanShouldStopHere.cpp | 2 +- lldb/tools/lldb-mi/MICmdCmdExec.cpp | 4 +- lldb/tools/lldb-mi/MICmdCmdTarget.cpp | 2 +- lldb/tools/lldb-mi/MICmnBase.cpp | 2 +- lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp | 4 +- lldb/tools/lldb-mi/MICmnMIResultRecord.cpp | 2 +- lldb/tools/lldb-mi/MIDriver.cpp | 4 +- lldb/tools/lldb-mi/MIDriverBase.cpp | 2 +- lldb/tools/lldb-mi/MIDriverMgr.cpp | 2 +- lldb/tools/lldb-server/lldb-gdbserver.cpp | 20 +- lldb/tools/lldb-server/lldb-platform.cpp | 18 +- .../unittests/Utility/StringExtractorTest.cpp | 2 +- .../lldb-server/inferior/thread_inferior.cpp | 2 +- .../lldb-server/tests/MessageObjects.cpp | 8 +- llvm/include/llvm/ADT/DenseMap.h | 2 +- .../llvm/Demangle/MicrosoftDemangleNodes.h | 2 +- 250 files changed, 1487 insertions(+), 1461 deletions(-) diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/lldb/include/lldb/Breakpoint/BreakpointResolver.h index 8767e0d8b5c45..11e183b33482d 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolver.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolver.h @@ -209,7 +209,7 @@ class BreakpointResolver : public Searcher { const char *) = delete; lldb::BreakpointLocationSP AddLocation(Address loc_addr, - bool *new_location = NULL); + bool *new_location = nullptr); Breakpoint *m_breakpoint; // This is the breakpoint we add locations to. lldb::addr_t m_offset; // A random offset the user asked us to add to any diff --git a/lldb/source/API/SBAddress.cpp b/lldb/source/API/SBAddress.cpp index cb67690544b25..358cb400a76cc 100644 --- a/lldb/source/API/SBAddress.cpp +++ b/lldb/source/API/SBAddress.cpp @@ -83,7 +83,7 @@ bool SBAddress::IsValid() const { SBAddress::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBAddress, operator bool); - return m_opaque_up != NULL && m_opaque_up->IsValid(); + return m_opaque_up != nullptr && m_opaque_up->IsValid(); } void SBAddress::Clear() { @@ -186,7 +186,7 @@ Address *SBAddress::operator->() { return m_opaque_up.get(); } const Address *SBAddress::operator->() const { return m_opaque_up.get(); } Address &SBAddress::ref() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new Address()); return *m_opaque_up; } @@ -208,7 +208,7 @@ bool SBAddress::GetDescription(SBStream &description) { // case there isn't one already... Stream &strm = description.ref(); if (m_opaque_up->IsValid()) { - m_opaque_up->Dump(&strm, NULL, Address::DumpStyleResolvedDescription, + m_opaque_up->Dump(&strm, nullptr, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress, 4); StreamString sstrm; // m_opaque_up->Dump (&sstrm, NULL, diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp index b8ca473894fc7..f333d1d7b5f32 100644 --- a/lldb/source/API/SBBlock.cpp +++ b/lldb/source/API/SBBlock.cpp @@ -25,7 +25,7 @@ using namespace lldb; using namespace lldb_private; -SBBlock::SBBlock() : m_opaque_ptr(NULL) { +SBBlock::SBBlock() : m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBlock); } @@ -44,7 +44,7 @@ const SBBlock &SBBlock::operator=(const SBBlock &rhs) { return LLDB_RECORD_RESULT(*this); } -SBBlock::~SBBlock() { m_opaque_ptr = NULL; } +SBBlock::~SBBlock() { m_opaque_ptr = nullptr; } bool SBBlock::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsValid); @@ -53,14 +53,14 @@ bool SBBlock::IsValid() const { SBBlock::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, operator bool); - return m_opaque_ptr != NULL; + return m_opaque_ptr != nullptr; } bool SBBlock::IsInlined() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsInlined); if (m_opaque_ptr) - return m_opaque_ptr->GetInlinedFunctionInfo() != NULL; + return m_opaque_ptr->GetInlinedFunctionInfo() != nullptr; return false; } @@ -77,10 +77,10 @@ const char *SBBlock::GetInlinedName() const { language = function->GetLanguage(); else language = lldb::eLanguageTypeUnknown; - return inlined_info->GetName(language).AsCString(NULL); + return inlined_info->GetName(language).AsCString(nullptr); } } - return NULL; + return nullptr; } SBFileSpec SBBlock::GetInlinedCallSiteFile() const { diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp index 560687507097e..640545f55ef97 100644 --- a/lldb/source/API/SBBreakpointLocation.cpp +++ b/lldb/source/API/SBBreakpointLocation.cpp @@ -179,7 +179,7 @@ const char *SBBreakpointLocation::GetCondition() { loc_sp->GetTarget().GetAPIMutex()); return loc_sp->GetConditionText(); } - return NULL; + return nullptr; } void SBBreakpointLocation::SetAutoContinue(bool auto_continue) { @@ -357,7 +357,7 @@ const char *SBBreakpointLocation::GetThreadName() const { loc_sp->GetTarget().GetAPIMutex()); return loc_sp->GetThreadName(); } - return NULL; + return nullptr; } void SBBreakpointLocation::SetQueueName(const char *queue_name) { @@ -382,7 +382,7 @@ const char *SBBreakpointLocation::GetQueueName() const { loc_sp->GetTarget().GetAPIMutex()); loc_sp->GetQueueName(); } - return NULL; + return nullptr; } bool SBBreakpointLocation::IsResolved() { diff --git a/lldb/source/API/SBBroadcaster.cpp b/lldb/source/API/SBBroadcaster.cpp index 4119fb2c134cc..e1efdf7baf61f 100644 --- a/lldb/source/API/SBBroadcaster.cpp +++ b/lldb/source/API/SBBroadcaster.cpp @@ -16,20 +16,19 @@ using namespace lldb; using namespace lldb_private; -SBBroadcaster::SBBroadcaster() : m_opaque_sp(), m_opaque_ptr(NULL) { +SBBroadcaster::SBBroadcaster() : m_opaque_sp(), m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBroadcaster); } SBBroadcaster::SBBroadcaster(const char *name) - : m_opaque_sp(new Broadcaster(NULL, name)), m_opaque_ptr(NULL) { + : m_opaque_sp(new Broadcaster(nullptr, name)), m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR(SBBroadcaster, (const char *), name); m_opaque_ptr = m_opaque_sp.get(); } SBBroadcaster::SBBroadcaster(lldb_private::Broadcaster *broadcaster, bool owns) - : m_opaque_sp(owns ? broadcaster : NULL), m_opaque_ptr(broadcaster) { -} + : m_opaque_sp(owns ? broadcaster : nullptr), m_opaque_ptr(broadcaster) {} SBBroadcaster::SBBroadcaster(const SBBroadcaster &rhs) : m_opaque_sp(rhs.m_opaque_sp), m_opaque_ptr(rhs.m_opaque_ptr) { @@ -48,13 +47,13 @@ const SBBroadcaster &SBBroadcaster::operator=(const SBBroadcaster &rhs) { return LLDB_RECORD_RESULT(*this); } -SBBroadcaster::~SBBroadcaster() { reset(NULL, false); } +SBBroadcaster::~SBBroadcaster() { reset(nullptr, false); } void SBBroadcaster::BroadcastEventByType(uint32_t event_type, bool unique) { LLDB_RECORD_METHOD(void, SBBroadcaster, BroadcastEventByType, (uint32_t, bool), event_type, unique); - if (m_opaque_ptr == NULL) + if (m_opaque_ptr == nullptr) return; if (unique) @@ -67,7 +66,7 @@ void SBBroadcaster::BroadcastEvent(const SBEvent &event, bool unique) { LLDB_RECORD_METHOD(void, SBBroadcaster, BroadcastEvent, (const lldb::SBEvent &, bool), event, unique); - if (m_opaque_ptr == NULL) + if (m_opaque_ptr == nullptr) return; EventSP event_sp = event.GetSP(); @@ -104,7 +103,7 @@ const char *SBBroadcaster::GetName() const { if (m_opaque_ptr) return m_opaque_ptr->GetBroadcasterName().GetCString(); - return NULL; + return nullptr; } bool SBBroadcaster::EventTypeHasListeners(uint32_t event_type) { @@ -144,14 +143,14 @@ bool SBBroadcaster::IsValid() const { SBBroadcaster::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBroadcaster, operator bool); - return m_opaque_ptr != NULL; + return m_opaque_ptr != nullptr; } void SBBroadcaster::Clear() { LLDB_RECORD_METHOD_NO_ARGS(void, SBBroadcaster, Clear); m_opaque_sp.reset(); - m_opaque_ptr = NULL; + m_opaque_ptr = nullptr; } bool SBBroadcaster::operator==(const SBBroadcaster &rhs) const { diff --git a/lldb/source/API/SBCommunication.cpp b/lldb/source/API/SBCommunication.cpp index 21bcde12cb3de..90df70bde72f1 100644 --- a/lldb/source/API/SBCommunication.cpp +++ b/lldb/source/API/SBCommunication.cpp @@ -16,7 +16,7 @@ using namespace lldb; using namespace lldb_private; -SBCommunication::SBCommunication() : m_opaque(NULL), m_opaque_owned(false) { +SBCommunication::SBCommunication() : m_opaque(nullptr), m_opaque_owned(false) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommunication); } @@ -28,7 +28,7 @@ SBCommunication::SBCommunication(const char *broadcaster_name) SBCommunication::~SBCommunication() { if (m_opaque && m_opaque_owned) delete m_opaque; - m_opaque = NULL; + m_opaque = nullptr; m_opaque_owned = false; } @@ -39,7 +39,7 @@ bool SBCommunication::IsValid() const { SBCommunication::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommunication, operator bool); - return m_opaque != NULL; + return m_opaque != nullptr; } bool SBCommunication::GetCloseOnEOF() { @@ -64,7 +64,7 @@ ConnectionStatus SBCommunication::Connect(const char *url) { if (m_opaque) { if (!m_opaque->HasConnection()) m_opaque->SetConnection(Host::CreateDefaultConnection(url).release()); - return m_opaque->Connect(url, NULL); + return m_opaque->Connect(url, nullptr); } return eConnectionStatusNoConnection; } @@ -115,7 +115,7 @@ size_t SBCommunication::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ? Timeout(llvm::None) : std::chrono::microseconds(timeout_usec); if (m_opaque) - bytes_read = m_opaque->Read(dst, dst_len, timeout, status, NULL); + bytes_read = m_opaque->Read(dst, dst_len, timeout, status, nullptr); else status = eConnectionStatusNoConnection; @@ -130,7 +130,7 @@ size_t SBCommunication::Write(const void *src, size_t src_len, size_t bytes_written = 0; if (m_opaque) - bytes_written = m_opaque->Write(src, src_len, status, NULL); + bytes_written = m_opaque->Write(src, src_len, status, nullptr); else status = eConnectionStatusNoConnection; diff --git a/lldb/source/API/SBCompileUnit.cpp b/lldb/source/API/SBCompileUnit.cpp index b5bac6bf7d1ad..48b501043e1cd 100644 --- a/lldb/source/API/SBCompileUnit.cpp +++ b/lldb/source/API/SBCompileUnit.cpp @@ -20,7 +20,7 @@ using namespace lldb; using namespace lldb_private; -SBCompileUnit::SBCompileUnit() : m_opaque_ptr(NULL) { +SBCompileUnit::SBCompileUnit() : m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCompileUnit); } @@ -41,7 +41,7 @@ const SBCompileUnit &SBCompileUnit::operator=(const SBCompileUnit &rhs) { return LLDB_RECORD_RESULT(*this); } -SBCompileUnit::~SBCompileUnit() { m_opaque_ptr = NULL; } +SBCompileUnit::~SBCompileUnit() { m_opaque_ptr = nullptr; } SBFileSpec SBCompileUnit::GetFileSpec() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBFileSpec, SBCompileUnit, @@ -108,8 +108,8 @@ uint32_t SBCompileUnit::FindLineEntryIndex(uint32_t start_idx, uint32_t line, file_spec = *m_opaque_ptr; index = m_opaque_ptr->FindLineEntry( - start_idx, line, inline_file_spec ? inline_file_spec->get() : NULL, - exact, NULL); + start_idx, line, inline_file_spec ? inline_file_spec->get() : nullptr, + exact, nullptr); } return index; @@ -193,7 +193,7 @@ bool SBCompileUnit::IsValid() const { SBCompileUnit::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCompileUnit, operator bool); - return m_opaque_ptr != NULL; + return m_opaque_ptr != nullptr; } bool SBCompileUnit::operator==(const SBCompileUnit &rhs) const { diff --git a/lldb/source/API/SBData.cpp b/lldb/source/API/SBData.cpp index d9e54d54a1807..528cd8d43ecce 100644 --- a/lldb/source/API/SBData.cpp +++ b/lldb/source/API/SBData.cpp @@ -64,7 +64,7 @@ bool SBData::IsValid() { SBData::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBData, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } uint8_t SBData::GetAddressByteSize() { @@ -312,13 +312,13 @@ const char *SBData::GetString(lldb::SBError &error, lldb::offset_t offset) { LLDB_RECORD_METHOD(const char *, SBData, GetString, (lldb::SBError &, lldb::offset_t), error, offset); - const char *value = 0; + const char *value = nullptr; if (!m_opaque_sp.get()) { error.SetErrorString("no value to read from"); } else { uint32_t old_offset = offset; value = m_opaque_sp->GetCStr(&offset); - if (offset == old_offset || (value == NULL)) + if (offset == old_offset || (value == nullptr)) error.SetErrorString("unable to read data"); } return value; @@ -346,13 +346,13 @@ size_t SBData::ReadRawData(lldb::SBError &error, lldb::offset_t offset, (lldb::SBError &, lldb::offset_t, void *, size_t), error, offset, buf, size); - void *ok = NULL; + void *ok = nullptr; if (!m_opaque_sp.get()) { error.SetErrorString("no value to read from"); } else { uint32_t old_offset = offset; ok = m_opaque_sp->GetU8(&offset, buf, size); - if ((offset == old_offset) || (ok == NULL)) + if ((offset == old_offset) || (ok == nullptr)) error.SetErrorString("unable to read data"); } return ok ? size : 0; diff --git a/lldb/source/API/SBDeclaration.cpp b/lldb/source/API/SBDeclaration.cpp index f14ca3993f41a..a7790b2939810 100644 --- a/lldb/source/API/SBDeclaration.cpp +++ b/lldb/source/API/SBDeclaration.cpp @@ -147,7 +147,7 @@ const lldb_private::Declaration *SBDeclaration::operator->() const { } lldb_private::Declaration &SBDeclaration::ref() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new lldb_private::Declaration()); return *m_opaque_up; } diff --git a/lldb/source/API/SBError.cpp b/lldb/source/API/SBError.cpp index c4627898282e5..7256e8e55de94 100644 --- a/lldb/source/API/SBError.cpp +++ b/lldb/source/API/SBError.cpp @@ -41,7 +41,7 @@ const char *SBError::GetCString() const { if (m_opaque_up) return m_opaque_up->AsCString(); - return NULL; + return nullptr; } void SBError::Clear() { @@ -144,11 +144,11 @@ bool SBError::IsValid() const { SBError::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBError, operator bool); - return m_opaque_up != NULL; + return m_opaque_up != nullptr; } void SBError::CreateIfNeeded() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new Status()); } @@ -175,7 +175,8 @@ bool SBError::GetDescription(SBStream &description) { description.Printf("success"); else { const char *err_string = GetCString(); - description.Printf("error: %s", (err_string != NULL ? err_string : "")); + description.Printf("error: %s", + (err_string != nullptr ? err_string : "")); } } else description.Printf("error: "); diff --git a/lldb/source/API/SBEvent.cpp b/lldb/source/API/SBEvent.cpp index b63108ec1fc93..75ca2830df9fb 100644 --- a/lldb/source/API/SBEvent.cpp +++ b/lldb/source/API/SBEvent.cpp @@ -22,7 +22,7 @@ using namespace lldb; using namespace lldb_private; -SBEvent::SBEvent() : m_event_sp(), m_opaque_ptr(NULL) { +SBEvent::SBEvent() : m_event_sp(), m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBEvent); } @@ -69,7 +69,7 @@ const char *SBEvent::GetDataFlavor() { if (event_data) return lldb_event->GetData()->GetFlavor().AsCString(); } - return NULL; + return nullptr; } uint32_t SBEvent::GetType() const { @@ -168,7 +168,7 @@ SBEvent::operator bool() const { // Do NOT use m_opaque_ptr directly!!! Must use the SBEvent::get() accessor. // See comments in SBEvent::get().... - return SBEvent::get() != NULL; + return SBEvent::get() != nullptr; } const char *SBEvent::GetCStringFromEvent(const SBEvent &event) { diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp index 35ddb1c7cd6b8..1770bede2f428 100644 --- a/lldb/source/API/SBFunction.cpp +++ b/lldb/source/API/SBFunction.cpp @@ -22,7 +22,7 @@ using namespace lldb; using namespace lldb_private; -SBFunction::SBFunction() : m_opaque_ptr(NULL) { +SBFunction::SBFunction() : m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBFunction); } @@ -42,7 +42,7 @@ const SBFunction &SBFunction::operator=(const SBFunction &rhs) { return LLDB_RECORD_RESULT(*this); } -SBFunction::~SBFunction() { m_opaque_ptr = NULL; } +SBFunction::~SBFunction() { m_opaque_ptr = nullptr; } bool SBFunction::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFunction, IsValid); @@ -51,13 +51,13 @@ bool SBFunction::IsValid() const { SBFunction::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBFunction, operator bool); - return m_opaque_ptr != NULL; + return m_opaque_ptr != nullptr; } const char *SBFunction::GetName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetName); - const char *cstr = NULL; + const char *cstr = nullptr; if (m_opaque_ptr) cstr = m_opaque_ptr->GetName().AsCString(); @@ -67,7 +67,7 @@ const char *SBFunction::GetName() const { const char *SBFunction::GetDisplayName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetDisplayName); - const char *cstr = NULL; + const char *cstr = nullptr; if (m_opaque_ptr) cstr = m_opaque_ptr->GetMangled() .GetDisplayDemangledName(m_opaque_ptr->GetLanguage()) @@ -79,7 +79,7 @@ const char *SBFunction::GetDisplayName() const { const char *SBFunction::GetMangledName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBFunction, GetMangledName); - const char *cstr = NULL; + const char *cstr = nullptr; if (m_opaque_ptr) cstr = m_opaque_ptr->GetMangled().GetMangledName().AsCString(); return cstr; @@ -118,7 +118,7 @@ SBInstructionList SBFunction::GetInstructions(SBTarget target) { LLDB_RECORD_METHOD(lldb::SBInstructionList, SBFunction, GetInstructions, (lldb::SBTarget), target); - return LLDB_RECORD_RESULT(GetInstructions(target, NULL)); + return LLDB_RECORD_RESULT(GetInstructions(target, nullptr)); } SBInstructionList SBFunction::GetInstructions(SBTarget target, @@ -141,7 +141,7 @@ SBInstructionList SBFunction::GetInstructions(SBTarget target, if (module_sp) { const bool prefer_file_cache = false; sb_instructions.SetDisassembler(Disassembler::DisassembleRange( - module_sp->GetArchitecture(), NULL, flavor, exe_ctx, + module_sp->GetArchitecture(), nullptr, flavor, exe_ctx, m_opaque_ptr->GetAddressRange(), prefer_file_cache)); } } diff --git a/lldb/source/API/SBHostOS.cpp b/lldb/source/API/SBHostOS.cpp index b8aa94d97a13a..b5464c4e7df71 100644 --- a/lldb/source/API/SBHostOS.cpp +++ b/lldb/source/API/SBHostOS.cpp @@ -107,8 +107,9 @@ lldb::thread_t SBHostOS::ThreadCreate(const char *name, LLDB_RECORD_DUMMY(lldb::thread_t, SBHostOS, ThreadCreate, (lldb::thread_func_t, void *, SBError *), name, thread_function, thread_arg, error_ptr); - HostThread thread(ThreadLauncher::LaunchThread( - name, thread_function, thread_arg, error_ptr ? error_ptr->get() : NULL)); + HostThread thread( + ThreadLauncher::LaunchThread(name, thread_function, thread_arg, + error_ptr ? error_ptr->get() : nullptr)); return thread.Release(); } diff --git a/lldb/source/API/SBInstruction.cpp b/lldb/source/API/SBInstruction.cpp index 8502aad9dbb21..fcf66fd258240 100644 --- a/lldb/source/API/SBInstruction.cpp +++ b/lldb/source/API/SBInstruction.cpp @@ -127,7 +127,7 @@ const char *SBInstruction::GetMnemonic(SBTarget target) { } return inst_sp->GetMnemonic(&exe_ctx); } - return NULL; + return nullptr; } const char *SBInstruction::GetOperands(SBTarget target) { @@ -147,7 +147,7 @@ const char *SBInstruction::GetOperands(SBTarget target) { } return inst_sp->GetOperands(&exe_ctx); } - return NULL; + return nullptr; } const char *SBInstruction::GetComment(SBTarget target) { @@ -167,7 +167,7 @@ const char *SBInstruction::GetComment(SBTarget target) { } return inst_sp->GetComment(&exe_ctx); } - return NULL; + return nullptr; } size_t SBInstruction::GetByteSize() { @@ -249,7 +249,7 @@ bool SBInstruction::GetDescription(lldb::SBStream &s) { // didn't have a stream already created, one will get created... FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - inst_sp->Dump(&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0); + inst_sp->Dump(&s.ref(), 0, true, false, nullptr, &sc, nullptr, &format, 0); return true; } return false; @@ -258,7 +258,7 @@ bool SBInstruction::GetDescription(lldb::SBStream &s) { void SBInstruction::Print(FILE *out) { LLDB_RECORD_METHOD(void, SBInstruction, Print, (FILE *), out); - if (out == NULL) + if (out == nullptr) return; lldb::InstructionSP inst_sp(GetOpaque()); @@ -272,7 +272,8 @@ void SBInstruction::Print(FILE *out) { StreamFile out_stream(out, false); FormatEntity::Entry format; FormatEntity::Parse("${addr}: ", format); - inst_sp->Dump(&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0); + inst_sp->Dump(&out_stream, 0, true, false, nullptr, &sc, nullptr, &format, + 0); } } diff --git a/lldb/source/API/SBInstructionList.cpp b/lldb/source/API/SBInstructionList.cpp index 390ad4750613e..cce923bf04a4b 100644 --- a/lldb/source/API/SBInstructionList.cpp +++ b/lldb/source/API/SBInstructionList.cpp @@ -49,7 +49,7 @@ bool SBInstructionList::IsValid() const { SBInstructionList::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBInstructionList, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } size_t SBInstructionList::GetSize() { @@ -119,7 +119,7 @@ void SBInstructionList::SetDisassembler(const lldb::DisassemblerSP &opaque_sp) { void SBInstructionList::Print(FILE *out) { LLDB_RECORD_METHOD(void, SBInstructionList, Print, (FILE *), out); - if (out == NULL) + if (out == nullptr) return; } @@ -142,7 +142,7 @@ bool SBInstructionList::GetDescription(lldb::SBStream &description) { for (size_t i = 0; i < num_instructions; ++i) { Instruction *inst = m_opaque_sp->GetInstructionList().GetInstructionAtIndex(i).get(); - if (inst == NULL) + if (inst == nullptr) break; const Address &addr = inst->GetAddress(); @@ -153,7 +153,7 @@ bool SBInstructionList::GetDescription(lldb::SBStream &description) { addr, eSymbolContextEverything, sc); } - inst->Dump(&sref, max_opcode_byte_size, true, false, NULL, &sc, + inst->Dump(&sref, max_opcode_byte_size, true, false, nullptr, &sc, &prev_sc, &format, 0); sref.EOL(); } diff --git a/lldb/source/API/SBLineEntry.cpp b/lldb/source/API/SBLineEntry.cpp index b7aac0be93562..010a6057cd310 100644 --- a/lldb/source/API/SBLineEntry.cpp +++ b/lldb/source/API/SBLineEntry.cpp @@ -162,7 +162,7 @@ const lldb_private::LineEntry *SBLineEntry::operator->() const { } lldb_private::LineEntry &SBLineEntry::ref() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new lldb_private::LineEntry()); return *m_opaque_up; } diff --git a/lldb/source/API/SBListener.cpp b/lldb/source/API/SBListener.cpp index 5eb5abd80280b..4fe90f6f68620 100644 --- a/lldb/source/API/SBListener.cpp +++ b/lldb/source/API/SBListener.cpp @@ -20,7 +20,7 @@ using namespace lldb; using namespace lldb_private; -SBListener::SBListener() : m_opaque_sp(), m_unused_ptr(NULL) { +SBListener::SBListener() : m_opaque_sp(), m_unused_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBListener); } @@ -160,7 +160,7 @@ bool SBListener::WaitForEvent(uint32_t timeout_secs, SBEvent &event) { } if (!success) - event.reset(NULL); + event.reset(nullptr); return success; } @@ -182,7 +182,7 @@ bool SBListener::WaitForEventForBroadcaster(uint32_t num_seconds, return true; } } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -205,7 +205,7 @@ bool SBListener::WaitForEventForBroadcasterWithType( return true; } } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -217,7 +217,7 @@ bool SBListener::PeekAtNextEvent(SBEvent &event) { event.reset(m_opaque_sp->PeekAtNextEvent()); return event.IsValid(); } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -231,7 +231,7 @@ bool SBListener::PeekAtNextEventForBroadcaster(const SBBroadcaster &broadcaster, event.reset(m_opaque_sp->PeekAtNextEventForBroadcaster(broadcaster.get())); return event.IsValid(); } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -247,7 +247,7 @@ bool SBListener::PeekAtNextEventForBroadcasterWithType( broadcaster.get(), event_type_mask)); return event.IsValid(); } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -261,7 +261,7 @@ bool SBListener::GetNextEvent(SBEvent &event) { return true; } } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -279,7 +279,7 @@ bool SBListener::GetNextEventForBroadcaster(const SBBroadcaster &broadcaster, return true; } } - event.reset(NULL); + event.reset(nullptr); return false; } @@ -299,7 +299,7 @@ bool SBListener::GetNextEventForBroadcasterWithType( return true; } } - event.reset(NULL); + event.reset(nullptr); return false; } diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index a22d7ca298907..4bd32bce1c532 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -40,8 +40,8 @@ SBModule::SBModule(const SBModuleSpec &module_spec) : m_opaque_sp() { LLDB_RECORD_CONSTRUCTOR(SBModule, (const lldb::SBModuleSpec &), module_spec); ModuleSP module_sp; - Status error = ModuleList::GetSharedModule(*module_spec.m_opaque_up, - module_sp, NULL, NULL, NULL); + Status error = ModuleList::GetSharedModule( + *module_spec.m_opaque_up, module_sp, nullptr, nullptr, nullptr); if (module_sp) SetSP(module_sp); } @@ -85,7 +85,7 @@ bool SBModule::IsValid() const { SBModule::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBModule, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } void SBModule::Clear() { @@ -159,7 +159,7 @@ bool SBModule::SetRemoteInstallFileSpec(lldb::SBFileSpec &file) { const uint8_t *SBModule::GetUUIDBytes() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const uint8_t *, SBModule, GetUUIDBytes); - const uint8_t *uuid_bytes = NULL; + const uint8_t *uuid_bytes = nullptr; ModuleSP module_sp(GetSP()); if (module_sp) uuid_bytes = module_sp->GetUUID().GetBytes().data(); @@ -170,8 +170,7 @@ const uint8_t *SBModule::GetUUIDBytes() const { const char *SBModule::GetUUIDString() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBModule, GetUUIDString); - - const char *uuid_cstr = NULL; + const char *uuid_cstr = nullptr; ModuleSP module_sp(GetSP()); if (module_sp) { // We are going to return a "const char *" value through the public API, so @@ -185,7 +184,7 @@ const char *SBModule::GetUUIDString() const { return uuid_cstr; } - return NULL; + return nullptr; } bool SBModule::operator==(const SBModule &rhs) const { @@ -296,7 +295,7 @@ static Symtab *GetUnifiedSymbolTable(const lldb::ModuleSP &module_sp) { if (symbols) return symbols->GetSymtab(); } - return NULL; + return nullptr; } size_t SBModule::GetNumSymbols() { @@ -410,7 +409,7 @@ lldb::SBSymbolContextList SBModule::FindFunctions(const char *name, const bool symbols_ok = true; const bool inlines_ok = true; FunctionNameType type = static_cast(name_type_mask); - module_sp->FindFunctions(ConstString(name), NULL, type, symbols_ok, + module_sp->FindFunctions(ConstString(name), nullptr, type, symbols_ok, inlines_ok, append, *sb_sc_list); } return LLDB_RECORD_RESULT(sb_sc_list); @@ -427,7 +426,7 @@ SBValueList SBModule::FindGlobalVariables(SBTarget &target, const char *name, if (name && module_sp) { VariableList variable_list; const uint32_t match_count = module_sp->FindGlobalVariables( - ConstString(name), NULL, max_matches, variable_list); + ConstString(name), nullptr, max_matches, variable_list); if (match_count > 0) { for (uint32_t i = 0; i < match_count; ++i) { @@ -558,7 +557,7 @@ lldb::SBTypeList SBModule::GetTypes(uint32_t type_mask) { TypeClass type_class = static_cast(type_mask); TypeList type_list; - vendor->GetTypes(NULL, type_class, type_list); + vendor->GetTypes(nullptr, type_class, type_list); sb_type_list.m_opaque_up->Append(type_list); return LLDB_RECORD_RESULT(sb_type_list); } @@ -606,7 +605,7 @@ const char *SBModule::GetTriple() { ConstString const_triple(triple.c_str()); return const_triple.GetCString(); } - return NULL; + return nullptr; } uint32_t SBModule::GetAddressByteSize() { diff --git a/lldb/source/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp index 235c37a810197..f3708d8e084f3 100644 --- a/lldb/source/API/SBPlatform.cpp +++ b/lldb/source/API/SBPlatform.cpp @@ -28,7 +28,7 @@ using namespace lldb_private; // PlatformConnectOptions struct PlatformConnectOptions { - PlatformConnectOptions(const char *url = NULL) + PlatformConnectOptions(const char *url = nullptr) : m_url(), m_rsync_options(), m_rsync_remote_path_prefix(), m_rsync_enabled(false), m_rsync_omit_hostname_from_remote_path(false), m_local_cache_directory() { @@ -48,7 +48,7 @@ struct PlatformConnectOptions { // PlatformShellCommand struct PlatformShellCommand { - PlatformShellCommand(const char *shell_command = NULL) + PlatformShellCommand(const char *shell_command = nullptr) : m_command(), m_working_dir(), m_status(0), m_signo(0) { if (shell_command && shell_command[0]) m_command = shell_command; @@ -94,7 +94,7 @@ const char *SBPlatformConnectOptions::GetURL() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBPlatformConnectOptions, GetURL); if (m_opaque_ptr->m_url.empty()) - return NULL; + return nullptr; return m_opaque_ptr->m_url.c_str(); } @@ -188,7 +188,7 @@ const char *SBPlatformShellCommand::GetCommand() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBPlatformShellCommand, GetCommand); if (m_opaque_ptr->m_command.empty()) - return NULL; + return nullptr; return m_opaque_ptr->m_command.c_str(); } @@ -207,7 +207,7 @@ const char *SBPlatformShellCommand::GetWorkingDirectory() { GetWorkingDirectory); if (m_opaque_ptr->m_working_dir.empty()) - return NULL; + return nullptr; return m_opaque_ptr->m_working_dir.c_str(); } @@ -256,7 +256,7 @@ const char *SBPlatformShellCommand::GetOutput() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBPlatformShellCommand, GetOutput); if (m_opaque_ptr->m_output.empty()) - return NULL; + return nullptr; return m_opaque_ptr->m_output.c_str(); } @@ -282,7 +282,7 @@ bool SBPlatform::IsValid() const { SBPlatform::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBPlatform, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } void SBPlatform::Clear() { @@ -297,7 +297,7 @@ const char *SBPlatform::GetName() { PlatformSP platform_sp(GetSP()); if (platform_sp) return platform_sp->GetName().GetCString(); - return NULL; + return nullptr; } lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; } @@ -312,7 +312,7 @@ const char *SBPlatform::GetWorkingDirectory() { PlatformSP platform_sp(GetSP()); if (platform_sp) return platform_sp->GetWorkingDirectory().GetCString(); - return NULL; + return nullptr; } bool SBPlatform::SetWorkingDirectory(const char *path) { @@ -376,7 +376,7 @@ const char *SBPlatform::GetTriple() { return ConstString(arch.GetTriple().getTriple().c_str()).GetCString(); } } - return NULL; + return nullptr; } const char *SBPlatform::GetOSBuild() { @@ -393,7 +393,7 @@ const char *SBPlatform::GetOSBuild() { } } } - return NULL; + return nullptr; } const char *SBPlatform::GetOSDescription() { @@ -410,7 +410,7 @@ const char *SBPlatform::GetOSDescription() { } } } - return NULL; + return nullptr; } const char *SBPlatform::GetHostname() { @@ -419,7 +419,7 @@ const char *SBPlatform::GetHostname() { PlatformSP platform_sp(GetSP()); if (platform_sp) return platform_sp->GetHostname(); - return NULL; + return nullptr; } uint32_t SBPlatform::GetOSMajorVersion() { @@ -513,7 +513,7 @@ SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) { return Status("invalid shell command (empty)"); const char *working_dir = shell_command.GetWorkingDirectory(); - if (working_dir == NULL) { + if (working_dir == nullptr) { working_dir = platform_sp->GetWorkingDirectory().GetCString(); if (working_dir) shell_command.SetWorkingDirectory(working_dir); diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index d97494b38c7ea..4226ff77ecdc3 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -335,7 +335,7 @@ void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const { LLDB_RECORD_METHOD_CONST(void, SBProcess, ReportEventState, (const lldb::SBEvent &, FILE *), event, out); - if (out == NULL) + if (out == nullptr) return; ProcessSP process_sp(GetSP()); @@ -534,7 +534,7 @@ int SBProcess::GetExitStatus() { const char *SBProcess::GetExitDescription() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBProcess, GetExitDescription); - const char *exit_desc = NULL; + const char *exit_desc = nullptr; ProcessSP process_sp(GetSP()); if (process_sp) { std::lock_guard guard( @@ -602,7 +602,7 @@ SBError SBProcess::Continue() { if (process_sp->GetTarget().GetDebugger().GetAsyncExecution()) sb_error.ref() = process_sp->Resume(); else - sb_error.ref() = process_sp->ResumeSynchronous(NULL); + sb_error.ref() = process_sp->ResumeSynchronous(nullptr); } else sb_error.SetErrorString("SBProcess is invalid"); @@ -985,7 +985,7 @@ bool SBProcess::GetDescription(SBStream &description) { char path[PATH_MAX]; GetTarget().GetExecutable().GetPath(path, sizeof(path)); Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer(); - const char *exe_name = NULL; + const char *exe_name = nullptr; if (exe_module) exe_name = exe_module->GetFileSpec().GetFilename().AsCString(); @@ -1156,7 +1156,7 @@ const char *SBProcess::GetExtendedBacktraceTypeAtIndex(uint32_t idx) { return names[idx].AsCString(); } } - return NULL; + return nullptr; } SBThreadCollection SBProcess::GetHistoryThreads(addr_t addr) { diff --git a/lldb/source/API/SBQueue.cpp b/lldb/source/API/SBQueue.cpp index 465bbac93872c..7d1581c42f60a 100644 --- a/lldb/source/API/SBQueue.cpp +++ b/lldb/source/API/SBQueue.cpp @@ -49,7 +49,7 @@ class QueueImpl { ~QueueImpl() {} - bool IsValid() { return m_queue_wp.lock() != NULL; } + bool IsValid() { return m_queue_wp.lock() != nullptr; } void Clear() { m_queue_wp.reset(); @@ -83,7 +83,7 @@ class QueueImpl { } const char *GetName() const { - const char *name = NULL; + const char *name = nullptr; lldb::QueueSP queue_sp = m_queue_wp.lock(); if (queue_sp.get()) { name = queue_sp->GetName(); diff --git a/lldb/source/API/SBQueueItem.cpp b/lldb/source/API/SBQueueItem.cpp index edb258029d1d8..5f2cbd1bdbfb9 100644 --- a/lldb/source/API/SBQueueItem.cpp +++ b/lldb/source/API/SBQueueItem.cpp @@ -41,7 +41,7 @@ bool SBQueueItem::IsValid() const { SBQueueItem::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBQueueItem, operator bool); - return m_queue_item_sp.get() != NULL; + return m_queue_item_sp.get() != nullptr; } void SBQueueItem::Clear() { diff --git a/lldb/source/API/SBSection.cpp b/lldb/source/API/SBSection.cpp index f47a799697dcf..14e1e14f59aa1 100644 --- a/lldb/source/API/SBSection.cpp +++ b/lldb/source/API/SBSection.cpp @@ -54,7 +54,7 @@ SBSection::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSection, operator bool); SectionSP section_sp(GetSP()); - return section_sp && section_sp->GetModule().get() != NULL; + return section_sp && section_sp->GetModule().get() != nullptr; } const char *SBSection::GetName() { @@ -63,7 +63,7 @@ const char *SBSection::GetName() { SectionSP section_sp(GetSP()); if (section_sp) return section_sp->GetName().GetCString(); - return NULL; + return nullptr; } lldb::SBSection SBSection::GetParent() { diff --git a/lldb/source/API/SBSourceManager.cpp b/lldb/source/API/SBSourceManager.cpp index 785f3090777cf..9c4ce3c7f4e3a 100644 --- a/lldb/source/API/SBSourceManager.cpp +++ b/lldb/source/API/SBSourceManager.cpp @@ -131,7 +131,7 @@ size_t SBSourceManager::DisplaySourceLinesWithLineNumbersAndColumn( const char *, lldb::SBStream &), file, line, column, context_before, context_after, current_line_cstr, s); - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) return 0; return m_opaque_up->DisplaySourceLinesWithLineNumbers( diff --git a/lldb/source/API/SBStream.cpp b/lldb/source/API/SBStream.cpp index 2f149a24d1351..ae652338e1ea5 100644 --- a/lldb/source/API/SBStream.cpp +++ b/lldb/source/API/SBStream.cpp @@ -34,7 +34,7 @@ bool SBStream::IsValid() const { SBStream::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStream, operator bool); - return (m_opaque_up != NULL); + return (m_opaque_up != nullptr); } // If this stream is not redirected to a file, it will maintain a local cache @@ -42,8 +42,8 @@ SBStream::operator bool() const { const char *SBStream::GetData() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBStream, GetData); - if (m_is_file || m_opaque_up == NULL) - return NULL; + if (m_is_file || m_opaque_up == nullptr) + return nullptr; return static_cast(m_opaque_up.get())->GetData(); } @@ -53,7 +53,7 @@ const char *SBStream::GetData() { size_t SBStream::GetSize() { LLDB_RECORD_METHOD_NO_ARGS(size_t, SBStream, GetSize); - if (m_is_file || m_opaque_up == NULL) + if (m_is_file || m_opaque_up == nullptr) return 0; return static_cast(m_opaque_up.get())->GetSize(); @@ -160,7 +160,7 @@ lldb_private::Stream *SBStream::operator->() { return m_opaque_up.get(); } lldb_private::Stream *SBStream::get() { return m_opaque_up.get(); } lldb_private::Stream &SBStream::ref() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new StreamString()); return *m_opaque_up; } diff --git a/lldb/source/API/SBStringList.cpp b/lldb/source/API/SBStringList.cpp index b08f232389cf0..2f8bd55855a11 100644 --- a/lldb/source/API/SBStringList.cpp +++ b/lldb/source/API/SBStringList.cpp @@ -56,13 +56,13 @@ bool SBStringList::IsValid() const { SBStringList::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStringList, operator bool); - return (m_opaque_up != NULL); + return (m_opaque_up != nullptr); } void SBStringList::AppendString(const char *str) { LLDB_RECORD_METHOD(void, SBStringList, AppendString, (const char *), str); - if (str != NULL) { + if (str != nullptr) { if (IsValid()) m_opaque_up->AppendString(str); else @@ -74,7 +74,7 @@ void SBStringList::AppendList(const char **strv, int strc) { LLDB_RECORD_METHOD(void, SBStringList, AppendList, (const char **, int), strv, strc); - if ((strv != NULL) && (strc > 0)) { + if ((strv != nullptr) && (strc > 0)) { if (IsValid()) m_opaque_up->AppendList(strv, strc); else @@ -115,7 +115,7 @@ const char *SBStringList::GetStringAtIndex(size_t idx) { if (IsValid()) { return m_opaque_up->GetStringAtIndex(idx); } - return NULL; + return nullptr; } const char *SBStringList::GetStringAtIndex(size_t idx) const { @@ -125,7 +125,7 @@ const char *SBStringList::GetStringAtIndex(size_t idx) const { if (IsValid()) { return m_opaque_up->GetStringAtIndex(idx); } - return NULL; + return nullptr; } void SBStringList::Clear() { diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index a3c5acf3941cf..6cc90e0ee368b 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -18,7 +18,7 @@ using namespace lldb; using namespace lldb_private; -SBSymbol::SBSymbol() : m_opaque_ptr(NULL) { +SBSymbol::SBSymbol() : m_opaque_ptr(nullptr) { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBSymbol); } @@ -37,7 +37,7 @@ const SBSymbol &SBSymbol::operator=(const SBSymbol &rhs) { return LLDB_RECORD_RESULT(*this); } -SBSymbol::~SBSymbol() { m_opaque_ptr = NULL; } +SBSymbol::~SBSymbol() { m_opaque_ptr = nullptr; } void SBSymbol::SetSymbol(lldb_private::Symbol *lldb_object_ptr) { m_opaque_ptr = lldb_object_ptr; @@ -50,13 +50,13 @@ bool SBSymbol::IsValid() const { SBSymbol::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSymbol, operator bool); - return m_opaque_ptr != NULL; + return m_opaque_ptr != nullptr; } const char *SBSymbol::GetName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBSymbol, GetName); - const char *name = NULL; + const char *name = nullptr; if (m_opaque_ptr) name = m_opaque_ptr->GetName().AsCString(); @@ -66,7 +66,7 @@ const char *SBSymbol::GetName() const { const char *SBSymbol::GetDisplayName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBSymbol, GetDisplayName); - const char *name = NULL; + const char *name = nullptr; if (m_opaque_ptr) name = m_opaque_ptr->GetMangled() .GetDisplayDemangledName(m_opaque_ptr->GetLanguage()) @@ -78,7 +78,7 @@ const char *SBSymbol::GetDisplayName() const { const char *SBSymbol::GetMangledName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBSymbol, GetMangledName); - const char *name = NULL; + const char *name = nullptr; if (m_opaque_ptr) name = m_opaque_ptr->GetMangled().GetMangledName().AsCString(); return name; @@ -105,7 +105,7 @@ bool SBSymbol::GetDescription(SBStream &description) { Stream &strm = description.ref(); if (m_opaque_ptr) { - m_opaque_ptr->GetDescription(&strm, lldb::eDescriptionLevelFull, NULL); + m_opaque_ptr->GetDescription(&strm, lldb::eDescriptionLevelFull, nullptr); } else strm.PutCString("No value"); @@ -116,7 +116,7 @@ SBInstructionList SBSymbol::GetInstructions(SBTarget target) { LLDB_RECORD_METHOD(lldb::SBInstructionList, SBSymbol, GetInstructions, (lldb::SBTarget), target); - return LLDB_RECORD_RESULT(GetInstructions(target, NULL)); + return LLDB_RECORD_RESULT(GetInstructions(target, nullptr)); } SBInstructionList SBSymbol::GetInstructions(SBTarget target, @@ -141,7 +141,7 @@ SBInstructionList SBSymbol::GetInstructions(SBTarget target, AddressRange symbol_range(symbol_addr, m_opaque_ptr->GetByteSize()); const bool prefer_file_cache = false; sb_instructions.SetDisassembler(Disassembler::DisassembleRange( - module_sp->GetArchitecture(), NULL, flavor_string, exe_ctx, + module_sp->GetArchitecture(), nullptr, flavor_string, exe_ctx, symbol_range, prefer_file_cache)); } } diff --git a/lldb/source/API/SBSymbolContext.cpp b/lldb/source/API/SBSymbolContext.cpp index f8f446ba57455..365f0ccc2fbf1 100644 --- a/lldb/source/API/SBSymbolContext.cpp +++ b/lldb/source/API/SBSymbolContext.cpp @@ -63,7 +63,7 @@ bool SBSymbolContext::IsValid() const { SBSymbolContext::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSymbolContext, operator bool); - return m_opaque_up != NULL; + return m_opaque_up != nullptr; } SBModule SBSymbolContext::GetModule() { @@ -84,13 +84,13 @@ SBCompileUnit SBSymbolContext::GetCompileUnit() { GetCompileUnit); return LLDB_RECORD_RESULT( - SBCompileUnit(m_opaque_up ? m_opaque_up->comp_unit : NULL)); + SBCompileUnit(m_opaque_up ? m_opaque_up->comp_unit : nullptr)); } SBFunction SBSymbolContext::GetFunction() { LLDB_RECORD_METHOD_NO_ARGS(lldb::SBFunction, SBSymbolContext, GetFunction); - Function *function = NULL; + Function *function = nullptr; if (m_opaque_up) function = m_opaque_up->function; @@ -103,7 +103,8 @@ SBFunction SBSymbolContext::GetFunction() { SBBlock SBSymbolContext::GetBlock() { LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBSymbolContext, GetBlock); - return LLDB_RECORD_RESULT(SBBlock(m_opaque_up ? m_opaque_up->block : NULL)); + return LLDB_RECORD_RESULT( + SBBlock(m_opaque_up ? m_opaque_up->block : nullptr)); } SBLineEntry SBSymbolContext::GetLineEntry() { @@ -119,7 +120,7 @@ SBLineEntry SBSymbolContext::GetLineEntry() { SBSymbol SBSymbolContext::GetSymbol() { LLDB_RECORD_METHOD_NO_ARGS(lldb::SBSymbol, SBSymbolContext, GetSymbol); - Symbol *symbol = NULL; + Symbol *symbol = nullptr; if (m_opaque_up) symbol = m_opaque_up->symbol; @@ -183,13 +184,13 @@ const lldb_private::SymbolContext &SBSymbolContext::operator*() const { } lldb_private::SymbolContext &SBSymbolContext::operator*() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new SymbolContext); return *m_opaque_up; } lldb_private::SymbolContext &SBSymbolContext::ref() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new SymbolContext); return *m_opaque_up; } @@ -205,7 +206,7 @@ bool SBSymbolContext::GetDescription(SBStream &description) { Stream &strm = description.ref(); if (m_opaque_up) { - m_opaque_up->GetDescription(&strm, lldb::eDescriptionLevelFull, NULL); + m_opaque_up->GetDescription(&strm, lldb::eDescriptionLevelFull, nullptr); } else strm.PutCString("No value"); diff --git a/lldb/source/API/SBSymbolContextList.cpp b/lldb/source/API/SBSymbolContextList.cpp index 7c9a9dbb871b6..915d04a0282a2 100644 --- a/lldb/source/API/SBSymbolContextList.cpp +++ b/lldb/source/API/SBSymbolContextList.cpp @@ -93,7 +93,7 @@ bool SBSymbolContextList::IsValid() const { SBSymbolContextList::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBSymbolContextList, operator bool); - return m_opaque_up != NULL; + return m_opaque_up != nullptr; } lldb_private::SymbolContextList *SBSymbolContextList::operator->() const { @@ -111,7 +111,7 @@ bool SBSymbolContextList::GetDescription(lldb::SBStream &description) { Stream &strm = description.ref(); if (m_opaque_up) - m_opaque_up->GetDescription(&strm, lldb::eDescriptionLevelFull, NULL); + m_opaque_up->GetDescription(&strm, lldb::eDescriptionLevelFull, nullptr); return true; } diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index ee0897e59509c..56d258187ea07 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -126,7 +126,7 @@ bool SBTarget::EventIsTargetEvent(const SBEvent &event) { LLDB_RECORD_STATIC_METHOD(bool, SBTarget, EventIsTargetEvent, (const lldb::SBEvent &), event); - return Target::TargetEventData::GetEventDataFromEvent(event.get()) != NULL; + return Target::TargetEventData::GetEventDataFromEvent(event.get()) != nullptr; } SBTarget SBTarget::GetTargetFromEvent(const SBEvent &event) { @@ -171,7 +171,7 @@ bool SBTarget::IsValid() const { SBTarget::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTarget, operator bool); - return m_opaque_sp.get() != NULL && m_opaque_sp->IsValid(); + return m_opaque_sp.get() != nullptr && m_opaque_sp->IsValid(); } SBProcess SBTarget::GetProcess() { @@ -288,9 +288,9 @@ SBProcess SBTarget::LaunchSimple(char const **argv, char const **envp, (const char **, const char **, const char *), argv, envp, working_directory); - char *stdin_path = NULL; - char *stdout_path = NULL; - char *stderr_path = NULL; + char *stdin_path = nullptr; + char *stdout_path = nullptr; + char *stderr_path = nullptr; uint32_t launch_flags = 0; bool stop_at_entry = false; SBError error; @@ -307,7 +307,7 @@ SBError SBTarget::Install() { TargetSP target_sp(GetSP()); if (target_sp) { std::lock_guard guard(target_sp->GetAPIMutex()); - sb_error.ref() = target_sp->Install(NULL); + sb_error.ref() = target_sp->Install(nullptr); } return LLDB_RECORD_RESULT(sb_error); } @@ -381,7 +381,7 @@ SBProcess SBTarget::Launch(SBListener &listener, char const **argv, if (listener.IsValid()) launch_info.SetListener(listener.GetSP()); - error.SetError(target_sp->Launch(launch_info, NULL)); + error.SetError(target_sp->Launch(launch_info, nullptr)); sb_process.SetSP(target_sp->GetProcessSP()); } else { @@ -430,7 +430,7 @@ SBProcess SBTarget::Launch(SBLaunchInfo &sb_launch_info, SBError &error) { if (arch_spec.IsValid()) launch_info.GetArchitecture() = arch_spec; - error.SetError(target_sp->Launch(launch_info, NULL)); + error.SetError(target_sp->Launch(launch_info, nullptr)); sb_launch_info.set_ref(launch_info); sb_process.SetSP(target_sp->GetProcessSP()); } else { @@ -551,14 +551,14 @@ lldb::SBProcess SBTarget::ConnectRemote(SBListener &listener, const char *url, std::lock_guard guard(target_sp->GetAPIMutex()); if (listener.IsValid()) process_sp = - target_sp->CreateProcess(listener.m_opaque_sp, plugin_name, NULL); + target_sp->CreateProcess(listener.m_opaque_sp, plugin_name, nullptr); else process_sp = target_sp->CreateProcess( - target_sp->GetDebugger().GetListener(), plugin_name, NULL); + target_sp->GetDebugger().GetListener(), plugin_name, nullptr); if (process_sp) { sb_process.SetSP(process_sp); - error.SetError(process_sp->ConnectRemote(NULL, url)); + error.SetError(process_sp->ConnectRemote(nullptr, url)); } else { error.SetErrorString("unable to create lldb_private::Process"); } @@ -788,12 +788,12 @@ SBBreakpoint SBTarget::BreakpointCreateByName(const char *symbol_name, FileSpecList module_spec_list; module_spec_list.Append(FileSpec(module_name)); sb_bp = target_sp->CreateBreakpoint( - &module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, + &module_spec_list, nullptr, symbol_name, eFunctionNameTypeAuto, eLanguageTypeUnknown, offset, skip_prologue, internal, hardware); } else { sb_bp = target_sp->CreateBreakpoint( - NULL, NULL, symbol_name, eFunctionNameTypeAuto, eLanguageTypeUnknown, - offset, skip_prologue, internal, hardware); + nullptr, nullptr, symbol_name, eFunctionNameTypeAuto, + eLanguageTypeUnknown, offset, skip_prologue, internal, hardware); } } @@ -1425,7 +1425,7 @@ lldb::SBWatchpoint SBTarget::WatchAddress(lldb::addr_t addr, size_t size, // Target::CreateWatchpoint() is thread safe. Status cw_error; // This API doesn't take in a type, so we can't figure out what it is. - CompilerType *type = NULL; + CompilerType *type = nullptr; watchpoint_sp = target_sp->CreateWatchpoint(addr, size, type, watch_type, cw_error); error.SetError(cw_error); @@ -1559,7 +1559,7 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple, (const char *, const char *, const char *), path, triple, uuid_cstr); - return LLDB_RECORD_RESULT(AddModule(path, triple, uuid_cstr, NULL)); + return LLDB_RECORD_RESULT(AddModule(path, triple, uuid_cstr, nullptr)); } lldb::SBModule SBTarget::AddModule(const char *path, const char *triple, @@ -1683,7 +1683,7 @@ const char *SBTarget::GetTriple() { ConstString const_triple(triple.c_str()); return const_triple.GetCString(); } - return NULL; + return nullptr; } uint32_t SBTarget::GetDataByteSize() { @@ -1969,7 +1969,7 @@ SBValueList SBTarget::FindGlobalVariables(const char *name, if (match_count > 0) { ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); - if (exe_scope == NULL) + if (exe_scope == nullptr) exe_scope = target_sp.get(); for (uint32_t i = 0; i < match_count; ++i) { lldb::ValueObjectSP valobj_sp(ValueObjectVariable::Create( @@ -2017,7 +2017,7 @@ SBValueList SBTarget::FindGlobalVariables(const char *name, if (match_count > 0) { ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); - if (exe_scope == NULL) + if (exe_scope == nullptr) exe_scope = target_sp.get(); for (uint32_t i = 0; i < match_count; ++i) { lldb::ValueObjectSP valobj_sp(ValueObjectVariable::Create( @@ -2053,7 +2053,7 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr, LLDB_RECORD_METHOD(lldb::SBInstructionList, SBTarget, ReadInstructions, (lldb::SBAddress, uint32_t), base_addr, count); - return LLDB_RECORD_RESULT(ReadInstructions(base_addr, count, NULL)); + return LLDB_RECORD_RESULT(ReadInstructions(base_addr, count, nullptr)); } lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr, @@ -2080,7 +2080,7 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr, data.GetByteSize(), error, &load_addr); const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; sb_instructions.SetDisassembler(Disassembler::DisassembleBytes( - target_sp->GetArchitecture(), NULL, flavor_string, *addr_ptr, + target_sp->GetArchitecture(), nullptr, flavor_string, *addr_ptr, data.GetBytes(), bytes_read, count, data_from_file)); } } @@ -2095,7 +2095,7 @@ lldb::SBInstructionList SBTarget::GetInstructions(lldb::SBAddress base_addr, (lldb::SBAddress, const void *, size_t), base_addr, buf, size); - return GetInstructionsWithFlavor(base_addr, NULL, buf, size); + return GetInstructionsWithFlavor(base_addr, nullptr, buf, size); } lldb::SBInstructionList @@ -2119,7 +2119,7 @@ SBTarget::GetInstructionsWithFlavor(lldb::SBAddress base_addr, const bool data_from_file = true; sb_instructions.SetDisassembler(Disassembler::DisassembleBytes( - target_sp->GetArchitecture(), NULL, flavor_string, addr, buf, size, + target_sp->GetArchitecture(), nullptr, flavor_string, addr, buf, size, UINT32_MAX, data_from_file)); } @@ -2132,7 +2132,7 @@ lldb::SBInstructionList SBTarget::GetInstructions(lldb::addr_t base_addr, LLDB_RECORD_DUMMY(lldb::SBInstructionList, SBTarget, GetInstructions, (lldb::addr_t, const void *, size_t), base_addr, buf, size); - return GetInstructionsWithFlavor(ResolveLoadAddress(base_addr), NULL, buf, + return GetInstructionsWithFlavor(ResolveLoadAddress(base_addr), nullptr, buf, size); } @@ -2353,9 +2353,9 @@ lldb::SBValue SBTarget::EvaluateExpression(const char *expr, SBValue expr_result; ValueObjectSP expr_value_sp; TargetSP target_sp(GetSP()); - StackFrame *frame = NULL; + StackFrame *frame = nullptr; if (target_sp) { - if (expr == NULL || expr[0] == '\0') { + if (expr == nullptr || expr[0] == '\0') { return LLDB_RECORD_RESULT(expr_result); } @@ -2409,7 +2409,7 @@ lldb::addr_t SBTarget::GetStackRedZoneSize() { lldb::SBLaunchInfo SBTarget::GetLaunchInfo() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBLaunchInfo, SBTarget, GetLaunchInfo); - lldb::SBLaunchInfo launch_info(NULL); + lldb::SBLaunchInfo launch_info(nullptr); TargetSP target_sp(GetSP()); if (target_sp) launch_info.set_ref(m_opaque_sp->GetProcessLaunchInfo()); diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 5f4f69f021364..85e9a6b47955a 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -122,7 +122,7 @@ SBThread::operator bool() const { if (target && process) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) - return m_opaque_sp->GetThreadSP().get() != NULL; + return m_opaque_sp->GetThreadSP().get() != nullptr; } // Without a valid target & process, this thread can't be valid. return false; @@ -359,7 +359,7 @@ size_t SBThread::GetStopDescription(char *dst, size_t dst_len) { stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString( stop_info_sp->GetValue()); - if (stop_desc == NULL || stop_desc[0] == '\0') { + if (stop_desc == nullptr || stop_desc[0] == '\0') { static char signal_desc[] = "signal"; stop_desc = signal_desc; stop_desc_len = @@ -452,7 +452,7 @@ uint32_t SBThread::GetIndexID() const { const char *SBThread::GetName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBThread, GetName); - const char *name = NULL; + const char *name = nullptr; std::unique_lock lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock); @@ -469,7 +469,7 @@ const char *SBThread::GetName() const { const char *SBThread::GetQueueName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBThread, GetQueueName); - const char *name = NULL; + const char *name = nullptr; std::unique_lock lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock); @@ -566,7 +566,7 @@ SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx, // User level plans should be Master Plans so they can be interrupted, other // plans executed, and then a "continue" will resume the plan. - if (new_plan != NULL) { + if (new_plan != nullptr) { new_plan->SetIsMasterPlan(true); new_plan->SetOkayToDiscard(false); } @@ -577,7 +577,7 @@ SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx, if (process->GetTarget().GetDebugger().GetAsyncExecution()) sb_error.ref() = process->Resume(); else - sb_error.ref() = process->ResumeSynchronous(NULL); + sb_error.ref() = process->ResumeSynchronous(nullptr); return sb_error; } @@ -627,7 +627,7 @@ void SBThread::StepInto(lldb::RunMode stop_other_threads) { LLDB_RECORD_METHOD(void, SBThread, StepInto, (lldb::RunMode), stop_other_threads); - StepInto(NULL, stop_other_threads); + StepInto(nullptr, stop_other_threads); } void SBThread::StepInto(const char *target_name, @@ -716,7 +716,7 @@ void SBThread::StepOut(SBError &error) { const LazyBool avoid_no_debug = eLazyBoolCalculate; Status new_plan_status; ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut( - abort_other_plans, NULL, false, stop_other_threads, eVoteYes, + abort_other_plans, nullptr, false, stop_other_threads, eVoteYes, eVoteNoOpinion, 0, new_plan_status, avoid_no_debug)); if (new_plan_status.Success()) @@ -763,7 +763,7 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { Status new_plan_status; ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut( - abort_other_plans, NULL, false, stop_other_threads, eVoteYes, + abort_other_plans, nullptr, false, stop_other_threads, eVoteYes, eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status)); if (new_plan_status.Success()) @@ -878,7 +878,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, eSymbolContextCompUnit | eSymbolContextFunction | eSymbolContextLineEntry | eSymbolContextSymbol); - if (frame_sc.comp_unit == NULL) { + if (frame_sc.comp_unit == nullptr) { sb_error.SetErrorStringWithFormat( "frame %u doesn't have debug information", frame_sp->GetFrameIndex()); return LLDB_RECORD_RESULT(sb_error); @@ -1235,7 +1235,7 @@ bool SBThread::EventIsThreadEvent(const SBEvent &event) { LLDB_RECORD_STATIC_METHOD(bool, SBThread, EventIsThreadEvent, (const lldb::SBEvent &), event); - return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != NULL; + return Thread::ThreadEventData::GetEventDataFromEvent(event.get()) != nullptr; } SBFrame SBThread::GetStackFrameFromEvent(const SBEvent &event) { diff --git a/lldb/source/API/SBThreadCollection.cpp b/lldb/source/API/SBThreadCollection.cpp index 766fe8f5516d6..3c1cf98650620 100644 --- a/lldb/source/API/SBThreadCollection.cpp +++ b/lldb/source/API/SBThreadCollection.cpp @@ -67,7 +67,7 @@ bool SBThreadCollection::IsValid() const { SBThreadCollection::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThreadCollection, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } size_t SBThreadCollection::GetSize() { diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp index ecb1a4fd1d9cd..8f6802fe9cef4 100644 --- a/lldb/source/API/SBThreadPlan.cpp +++ b/lldb/source/API/SBThreadPlan.cpp @@ -92,7 +92,7 @@ bool SBThreadPlan::IsValid() const { SBThreadPlan::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBThreadPlan, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } void SBThreadPlan::Clear() { @@ -262,7 +262,7 @@ SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address, Status plan_status; SBThreadPlan plan = SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange( - false, range, sc, NULL, eAllThreads, plan_status)); + false, range, sc, nullptr, eAllThreads, plan_status)); if (plan_status.Fail()) error.SetErrorString(plan_status.AsCString()); diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index e016ee46f235b..5402128b3faeb 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -92,7 +92,7 @@ SBType &SBType::operator=(const SBType &rhs) { SBType::~SBType() {} TypeImpl &SBType::ref() { - if (m_opaque_sp.get() == NULL) + if (m_opaque_sp.get() == nullptr) m_opaque_sp = std::make_shared(); return *m_opaque_sp; } @@ -112,7 +112,7 @@ bool SBType::IsValid() const { SBType::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBType, operator bool); - if (m_opaque_sp.get() == NULL) + if (m_opaque_sp.get() == nullptr) return false; return m_opaque_sp->IsValid(); @@ -579,7 +579,7 @@ bool SBTypeList::IsValid() { SBTypeList::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeList, operator bool); - return (m_opaque_up != NULL); + return (m_opaque_up != nullptr); } SBTypeList &SBTypeList::operator=(const SBTypeList &rhs) { @@ -660,7 +660,7 @@ const char *SBTypeMember::GetName() { if (m_opaque_up) return m_opaque_up->GetName().GetCString(); - return NULL; + return nullptr; } SBType SBTypeMember::GetType() { @@ -743,7 +743,7 @@ void SBTypeMember::reset(TypeMemberImpl *type_member_impl) { } TypeMemberImpl &SBTypeMember::ref() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new TypeMemberImpl()); return *m_opaque_up; } @@ -789,7 +789,7 @@ const char *SBTypeMemberFunction::GetName() { if (m_opaque_sp) return m_opaque_sp->GetName().GetCString(); - return NULL; + return nullptr; } const char *SBTypeMemberFunction::GetDemangledName() { @@ -803,7 +803,7 @@ const char *SBTypeMemberFunction::GetDemangledName() { return mangled.GetDemangledName(mangled.GuessLanguage()).GetCString(); } } - return NULL; + return nullptr; } const char *SBTypeMemberFunction::GetMangledName() { @@ -812,7 +812,7 @@ const char *SBTypeMemberFunction::GetMangledName() { if (m_opaque_sp) return m_opaque_sp->GetMangledName().GetCString(); - return NULL; + return nullptr; } SBType SBTypeMemberFunction::GetType() { diff --git a/lldb/source/API/SBTypeCategory.cpp b/lldb/source/API/SBTypeCategory.cpp index c2ec8cf8522ee..43d5a3ab140fb 100644 --- a/lldb/source/API/SBTypeCategory.cpp +++ b/lldb/source/API/SBTypeCategory.cpp @@ -49,7 +49,7 @@ bool SBTypeCategory::IsValid() const { SBTypeCategory::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeCategory, operator bool); - return (m_opaque_sp.get() != NULL); + return (m_opaque_sp.get() != nullptr); } bool SBTypeCategory::GetEnabled() { @@ -75,7 +75,7 @@ const char *SBTypeCategory::GetName() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeCategory, GetName); if (!IsValid()) - return NULL; + return nullptr; return m_opaque_sp->GetName(); } diff --git a/lldb/source/API/SBTypeEnumMember.cpp b/lldb/source/API/SBTypeEnumMember.cpp index c0e1c7942db95..bd0755a140c33 100644 --- a/lldb/source/API/SBTypeEnumMember.cpp +++ b/lldb/source/API/SBTypeEnumMember.cpp @@ -64,7 +64,7 @@ const char *SBTypeEnumMember::GetName() { if (m_opaque_sp.get()) return m_opaque_sp->GetName().GetCString(); - return NULL; + return nullptr; } int64_t SBTypeEnumMember::GetValueAsSigned() { @@ -98,7 +98,7 @@ void SBTypeEnumMember::reset(TypeEnumMemberImpl *type_member_impl) { } TypeEnumMemberImpl &SBTypeEnumMember::ref() { - if (m_opaque_sp.get() == NULL) + if (m_opaque_sp.get() == nullptr) m_opaque_sp = std::make_shared(); return *m_opaque_sp.get(); } @@ -130,7 +130,7 @@ bool SBTypeEnumMemberList::IsValid() { SBTypeEnumMemberList::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeEnumMemberList, operator bool); - return (m_opaque_up != NULL); + return (m_opaque_up != nullptr); } SBTypeEnumMemberList &SBTypeEnumMemberList:: diff --git a/lldb/source/API/SBTypeFilter.cpp b/lldb/source/API/SBTypeFilter.cpp index 104ef95650faa..d40301b4c1538 100644 --- a/lldb/source/API/SBTypeFilter.cpp +++ b/lldb/source/API/SBTypeFilter.cpp @@ -40,7 +40,7 @@ bool SBTypeFilter::IsValid() const { SBTypeFilter::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeFilter, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } uint32_t SBTypeFilter::GetOptions() { @@ -98,7 +98,7 @@ const char *SBTypeFilter::GetExpressionPathAtIndex(uint32_t i) { item++; return item; } - return NULL; + return nullptr; } bool SBTypeFilter::ReplaceExpressionPathAtIndex(uint32_t i, const char *item) { diff --git a/lldb/source/API/SBTypeFormat.cpp b/lldb/source/API/SBTypeFormat.cpp index 12729aaf98274..6024631e7054f 100644 --- a/lldb/source/API/SBTypeFormat.cpp +++ b/lldb/source/API/SBTypeFormat.cpp @@ -49,7 +49,7 @@ bool SBTypeFormat::IsValid() const { SBTypeFormat::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeFormat, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } lldb::Format SBTypeFormat::GetFormat() { diff --git a/lldb/source/API/SBTypeNameSpecifier.cpp b/lldb/source/API/SBTypeNameSpecifier.cpp index cccd0ee449e08..895f697756598 100644 --- a/lldb/source/API/SBTypeNameSpecifier.cpp +++ b/lldb/source/API/SBTypeNameSpecifier.cpp @@ -27,7 +27,7 @@ SBTypeNameSpecifier::SBTypeNameSpecifier(const char *name, bool is_regex) LLDB_RECORD_CONSTRUCTOR(SBTypeNameSpecifier, (const char *, bool), name, is_regex); - if (name == NULL || (*name) == 0) + if (name == nullptr || (*name) == 0) m_opaque_sp.reset(); } @@ -54,14 +54,14 @@ bool SBTypeNameSpecifier::IsValid() const { SBTypeNameSpecifier::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeNameSpecifier, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } const char *SBTypeNameSpecifier::GetName() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeNameSpecifier, GetName); if (!IsValid()) - return NULL; + return nullptr; return m_opaque_sp->GetName(); } @@ -129,7 +129,7 @@ bool SBTypeNameSpecifier::IsEqualTo(lldb::SBTypeNameSpecifier &rhs) { if (IsRegex() != rhs.IsRegex()) return false; - if (GetName() == NULL || rhs.GetName() == NULL) + if (GetName() == nullptr || rhs.GetName() == nullptr) return false; return (strcmp(GetName(), rhs.GetName()) == 0); diff --git a/lldb/source/API/SBTypeSummary.cpp b/lldb/source/API/SBTypeSummary.cpp index 8ffb114470b00..8ffb234357572 100644 --- a/lldb/source/API/SBTypeSummary.cpp +++ b/lldb/source/API/SBTypeSummary.cpp @@ -202,7 +202,7 @@ bool SBTypeSummary::IsValid() const { SBTypeSummary::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSummary, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } bool SBTypeSummary::IsFunctionCode() { @@ -244,7 +244,7 @@ const char *SBTypeSummary::GetData() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeSummary, GetData); if (!IsValid()) - return NULL; + return nullptr; if (ScriptSummaryFormat *script_summary_ptr = llvm::dyn_cast(m_opaque_sp.get())) { const char *fname = script_summary_ptr->GetFunctionName(); diff --git a/lldb/source/API/SBTypeSynthetic.cpp b/lldb/source/API/SBTypeSynthetic.cpp index f1e15525a08d0..df6fce1269f09 100644 --- a/lldb/source/API/SBTypeSynthetic.cpp +++ b/lldb/source/API/SBTypeSynthetic.cpp @@ -60,7 +60,7 @@ bool SBTypeSynthetic::IsValid() const { SBTypeSynthetic::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTypeSynthetic, operator bool); - return m_opaque_sp.get() != NULL; + return m_opaque_sp.get() != nullptr; } bool SBTypeSynthetic::IsClassCode() { @@ -84,7 +84,7 @@ const char *SBTypeSynthetic::GetData() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTypeSynthetic, GetData); if (!IsValid()) - return NULL; + return nullptr; if (IsClassCode()) return m_opaque_sp->GetPythonCode(); else diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index 3db84fa298049..8383007635229 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -57,7 +57,7 @@ class ValueImpl { ValueImpl(lldb::ValueObjectSP in_valobj_sp, lldb::DynamicValueType use_dynamic, bool use_synthetic, - const char *name = NULL) + const char *name = nullptr) : m_valobj_sp(), m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic), m_name(name) { if (in_valobj_sp) { @@ -84,7 +84,7 @@ class ValueImpl { } bool IsValid() { - if (m_valobj_sp.get() == NULL) + if (m_valobj_sp.get() == nullptr) return false; else { // FIXME: This check is necessary but not sufficient. We for sure don't @@ -251,8 +251,8 @@ SBValue::operator bool() const { // If this function ever changes to anything that does more than just check // if the opaque shared pointer is non NULL, then we need to update all "if // (m_opaque_sp)" code in this file. - return m_opaque_sp.get() != NULL && m_opaque_sp->IsValid() && - m_opaque_sp->GetRootSP().get() != NULL; + return m_opaque_sp.get() != nullptr && m_opaque_sp->IsValid() && + m_opaque_sp->GetRootSP().get() != nullptr; } void SBValue::Clear() { @@ -290,7 +290,7 @@ user_id_t SBValue::GetID() { const char *SBValue::GetName() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetName); - const char *name = NULL; + const char *name = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) @@ -302,7 +302,7 @@ const char *SBValue::GetName() { const char *SBValue::GetTypeName() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetTypeName); - const char *name = NULL; + const char *name = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -315,7 +315,7 @@ const char *SBValue::GetTypeName() { const char *SBValue::GetDisplayTypeName() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetDisplayTypeName); - const char *name = NULL; + const char *name = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -356,7 +356,7 @@ bool SBValue::IsInScope() { const char *SBValue::GetValue() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetValue); - const char *cstr = NULL; + const char *cstr = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -381,7 +381,7 @@ ValueType SBValue::GetValueType() { const char *SBValue::GetObjectDescription() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetObjectDescription); - const char *cstr = NULL; + const char *cstr = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -394,7 +394,7 @@ const char *SBValue::GetObjectDescription() { const char *SBValue::GetTypeValidatorResult() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetTypeValidatorResult); - const char *cstr = NULL; + const char *cstr = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -442,7 +442,7 @@ bool SBValue::GetValueDidChange() { const char *SBValue::GetSummary() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetSummary); - const char *cstr = NULL; + const char *cstr = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -472,7 +472,7 @@ const char *SBValue::GetSummary(lldb::SBStream &stream, const char *SBValue::GetLocation() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBValue, GetLocation); - const char *cstr = NULL; + const char *cstr = nullptr; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { @@ -1042,7 +1042,7 @@ void *SBValue::GetOpaqueType() { lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) return value_sp->GetCompilerType().GetOpaqueQualType(); - return NULL; + return nullptr; } lldb::SBTarget SBValue::GetTarget() { diff --git a/lldb/source/API/SBValueList.cpp b/lldb/source/API/SBValueList.cpp index 2f74c99225267..7e909df260d7d 100644 --- a/lldb/source/API/SBValueList.cpp +++ b/lldb/source/API/SBValueList.cpp @@ -92,7 +92,7 @@ bool SBValueList::IsValid() const { SBValueList::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBValueList, operator bool); - return (m_opaque_up != NULL); + return (m_opaque_up != nullptr); } void SBValueList::Clear() { @@ -172,7 +172,7 @@ uint32_t SBValueList::GetSize() const { } void SBValueList::CreateIfNeeded() { - if (m_opaque_up == NULL) + if (m_opaque_up == nullptr) m_opaque_up.reset(new ValueListImpl()); } diff --git a/lldb/source/API/SBWatchpoint.cpp b/lldb/source/API/SBWatchpoint.cpp index 0f35c3eda872a..d0a36b71e5c18 100644 --- a/lldb/source/API/SBWatchpoint.cpp +++ b/lldb/source/API/SBWatchpoint.cpp @@ -218,7 +218,7 @@ const char *SBWatchpoint::GetCondition() { watchpoint_sp->GetTarget().GetAPIMutex()); return watchpoint_sp->GetConditionText(); } - return NULL; + return nullptr; } void SBWatchpoint::SetCondition(const char *condition) { @@ -277,7 +277,7 @@ bool SBWatchpoint::EventIsWatchpointEvent(const lldb::SBEvent &event) { (const lldb::SBEvent &), event); return Watchpoint::WatchpointEventData::GetEventDataFromEvent(event.get()) != - NULL; + nullptr; } WatchpointEventType diff --git a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp index d3610982026f8..8a6fd6a2692c8 100644 --- a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp @@ -124,7 +124,7 @@ Searcher::CallbackReturn BreakpointResolverAddress::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) { - assert(m_breakpoint != NULL); + assert(m_breakpoint != nullptr); if (filter.AddressPasses(m_addr)) { if (m_breakpoint->GetNumLocations() == 0) { diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index 494b4c77d0203..a6095be316471 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -204,7 +204,7 @@ BreakpointResolverFileLine::SearchCallback(SearchFilter &filter, Address *addr, bool containing) { SymbolContextList sc_list; - assert(m_breakpoint != NULL); + assert(m_breakpoint != nullptr); // There is a tricky bit here. You can have two compilation units that // #include the same file, and in one of them the function at m_line_number diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp index c17dcb8342c1a..0b2485245b726 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -98,7 +98,7 @@ BreakpointResolverFileRegex::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) { - assert(m_breakpoint != NULL); + assert(m_breakpoint != nullptr); if (!context.target_sp) return eCallbackReturnContinue; @@ -145,7 +145,7 @@ BreakpointResolverFileRegex::SearchCallback(SearchFilter &filter, BreakpointResolver::SetSCMatchesByLine(filter, sc_list, skip_prologue, m_regex.GetText()); } - assert(m_breakpoint != NULL); + assert(m_breakpoint != nullptr); return Searcher::eCallbackReturnContinue; } diff --git a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp index ae9775738f2c6..8363795a4d7f4 100644 --- a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp @@ -127,7 +127,7 @@ Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) { - assert(m_breakpoint != NULL); + assert(m_breakpoint != nullptr); bool should_continue = true; if (!m_implementation_sp) return Searcher::eCallbackReturnStop; @@ -144,7 +144,7 @@ BreakpointResolverScripted::SearchCallback(SearchFilter &filter, lldb::SearchDepth BreakpointResolverScripted::GetDepth() { - assert(m_breakpoint != NULL); + assert(m_breakpoint != nullptr); lldb::SearchDepth depth = lldb::eSearchDepthModule; if (m_implementation_sp) { ScriptInterpreter *interp = GetScriptInterpreter(); diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h index 5bd8384fb4ef2..89c8e1dbecebd 100644 --- a/lldb/source/Commands/CommandObjectExpression.h +++ b/lldb/source/Commands/CommandObjectExpression.h @@ -68,7 +68,7 @@ class CommandObjectExpression : public CommandObjectRaw, bool EvaluateExpression(llvm::StringRef expr, Stream *output_stream, Stream *error_stream, - CommandReturnObject *result = NULL); + CommandReturnObject *result = nullptr); void GetMultilineExpression(); diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp index ed5f5a559c54f..f2919d807d596 100644 --- a/lldb/source/Core/Communication.cpp +++ b/lldb/source/Core/Communication.cpp @@ -359,7 +359,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) { // Let clients know that this thread is exiting comm->BroadcastEvent(eBroadcastBitNoMorePendingInput); comm->BroadcastEvent(eBroadcastBitReadThreadDidExit); - return NULL; + return nullptr; } void Communication::SetReadThreadBytesReceivedCallback( diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 7f180c1575ad6..79402813e845f 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1616,7 +1616,7 @@ void Debugger::DefaultEventHandler() { lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) { ((Debugger *)arg)->DefaultEventHandler(); - return NULL; + return nullptr; } bool Debugger::StartEventHandlerThread() { @@ -1661,7 +1661,7 @@ lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) { Debugger *debugger = (Debugger *)arg; debugger->ExecuteIOHandlers(); debugger->StopEventHandlerThread(); - return NULL; + return nullptr; } bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 608ea8964e715..c6759cc944ca9 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -160,7 +160,7 @@ Mangled::~Mangled() {} // if (mangled) // { ... Mangled::operator void *() const { - return (m_mangled) ? const_cast(this) : NULL; + return (m_mangled) ? const_cast(this) : nullptr; } // Logical NOT operator. This allows code to check any Mangled objects to see diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 05d1468314c7a..a0d4cee47391b 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -342,7 +342,7 @@ void Section::DumpName(Stream *s) const { s->PutChar('.'); } else { // The top most section prints the module basename - const char *name = NULL; + const char *name = nullptr; ModuleSP module_sp(GetModule()); if (m_obj_file) { @@ -509,7 +509,7 @@ SectionList::FindSectionByName(ConstString section_dstr) const { const_iterator sect_iter; const_iterator end = m_sections.end(); for (sect_iter = m_sections.begin(); - sect_iter != end && sect_sp.get() == NULL; ++sect_iter) { + sect_iter != end && sect_sp.get() == nullptr; ++sect_iter) { Section *child_section = sect_iter->get(); if (child_section) { if (child_section->GetName() == section_dstr) { @@ -530,7 +530,7 @@ SectionSP SectionList::FindSectionByID(user_id_t sect_id) const { const_iterator sect_iter; const_iterator end = m_sections.end(); for (sect_iter = m_sections.begin(); - sect_iter != end && sect_sp.get() == NULL; ++sect_iter) { + sect_iter != end && sect_sp.get() == nullptr; ++sect_iter) { if ((*sect_iter)->GetID() == sect_id) { sect_sp = *sect_iter; break; @@ -567,7 +567,7 @@ SectionSP SectionList::FindSectionContainingFileAddress(addr_t vm_addr, const_iterator sect_iter; const_iterator end = m_sections.end(); for (sect_iter = m_sections.begin(); - sect_iter != end && sect_sp.get() == NULL; ++sect_iter) { + sect_iter != end && sect_sp.get() == nullptr; ++sect_iter) { Section *sect = sect_iter->get(); if (sect->ContainsFileAddress(vm_addr)) { // The file address is in this section. We need to make sure one of our @@ -577,7 +577,7 @@ SectionSP SectionList::FindSectionContainingFileAddress(addr_t vm_addr, sect_sp = sect->GetChildren().FindSectionContainingFileAddress( vm_addr, depth - 1); - if (sect_sp.get() == NULL && !sect->IsFake()) + if (sect_sp.get() == nullptr && !sect->IsFake()) sect_sp = *sect_iter; } } @@ -585,7 +585,7 @@ SectionSP SectionList::FindSectionContainingFileAddress(addr_t vm_addr, } bool SectionList::ContainsSection(user_id_t sect_id) const { - return FindSectionByID(sect_id).get() != NULL; + return FindSectionByID(sect_id).get() != nullptr; } void SectionList::Dump(Stream *s, Target *target, bool show_header, @@ -608,7 +608,7 @@ void SectionList::Dump(Stream *s, Target *target, bool show_header, const_iterator sect_iter; const_iterator end = m_sections.end(); for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) { - (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth); + (*sect_iter)->Dump(s, target_has_loaded_sections ? target : nullptr, depth); } if (show_header && !m_sections.empty()) diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp index 9cd9ac163fb8f..87065ab624251 100644 --- a/lldb/source/Core/SourceManager.cpp +++ b/lldb/source/Core/SourceManager.cpp @@ -326,7 +326,7 @@ bool SourceManager::GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line) { bool inlines_okay = true; bool append = false; size_t num_matches = executable_ptr->FindFunctions( - main_name, NULL, lldb::eFunctionNameTypeBase, inlines_okay, + main_name, nullptr, lldb::eFunctionNameTypeBase, inlines_okay, symbols_okay, append, sc_list); for (size_t idx = 0; idx < num_matches; idx++) { SymbolContext sc; @@ -399,7 +399,7 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec, if (num_matches != 0) { if (num_matches > 1) { SymbolContext sc; - FileSpec *test_cu_spec = NULL; + FileSpec *test_cu_spec = nullptr; for (unsigned i = 0; i < num_matches; i++) { sc_list.GetContextAtIndex(i, sc); @@ -461,12 +461,12 @@ uint32_t SourceManager::File::GetNumLines() { const char *SourceManager::File::PeekLineData(uint32_t line) { if (!LineIsValid(line)) - return NULL; + return nullptr; size_t line_offset = GetLineOffset(line); if (line_offset < m_data_sp->GetByteSize()) return (const char *)m_data_sp->GetBytes() + line_offset; - return NULL; + return nullptr; } uint32_t SourceManager::File::GetLineLength(uint32_t line, @@ -621,7 +621,7 @@ bool SourceManager::File::CalculateLineOffsets(uint32_t line) { return true; if (m_offsets.empty()) { - if (m_data_sp.get() == NULL) + if (m_data_sp.get() == nullptr) return false; const char *start = (char *)m_data_sp->GetBytes(); diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index 541e0933bcae7..fdb4adb5f4314 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -39,17 +39,17 @@ using namespace lldb; using namespace lldb_private; Value::Value() - : m_value(), m_vector(), m_compiler_type(), m_context(NULL), + : m_value(), m_vector(), m_compiler_type(), m_context(nullptr), m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid), m_data_buffer() {} Value::Value(const Scalar &scalar) - : m_value(scalar), m_vector(), m_compiler_type(), m_context(NULL), + : m_value(scalar), m_vector(), m_compiler_type(), m_context(nullptr), m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid), m_data_buffer() {} Value::Value(const void *bytes, int len) - : m_value(), m_vector(), m_compiler_type(), m_context(NULL), + : m_value(), m_vector(), m_compiler_type(), m_context(nullptr), m_value_type(eValueTypeHostAddress), m_context_type(eContextTypeInvalid), m_data_buffer() { SetBytes(bytes, len); @@ -131,13 +131,13 @@ AddressType Value::GetValueAddressType() const { RegisterInfo *Value::GetRegisterInfo() const { if (m_context_type == eContextTypeRegisterInfo) return static_cast(m_context); - return NULL; + return nullptr; } Type *Value::GetType() { if (m_context_type == eContextTypeLLDBType) return static_cast(m_context); - return NULL; + return nullptr; } size_t Value::AppendDataToHostBuffer(const Value &rhs) { @@ -353,11 +353,11 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, break; } case eValueTypeLoadAddress: - if (exe_ctx == NULL) { + if (exe_ctx == nullptr) { error.SetErrorString("can't read load address (no execution context)"); } else { Process *process = exe_ctx->GetProcessPtr(); - if (process == NULL || !process->IsAlive()) { + if (process == nullptr || !process->IsAlive()) { Target *target = exe_ctx->GetTargetPtr(); if (target) { // Allow expressions to run and evaluate things when the target has @@ -390,16 +390,16 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, break; case eValueTypeFileAddress: - if (exe_ctx == NULL) { + if (exe_ctx == nullptr) { error.SetErrorString("can't read file address (no execution context)"); - } else if (exe_ctx->GetTargetPtr() == NULL) { + } else if (exe_ctx->GetTargetPtr() == nullptr) { error.SetErrorString("can't read file address (invalid target)"); } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); if (address == LLDB_INVALID_ADDRESS) { error.SetErrorString("invalid file address"); } else { - if (module == NULL) { + if (module == nullptr) { // The only thing we can currently lock down to a module so that we // can resolve a file address, is a variable. Variable *variable = GetVariable(); @@ -527,7 +527,7 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, } uint8_t *dst = const_cast(data.PeekData(data_offset, byte_size)); - if (dst != NULL) { + if (dst != nullptr) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it. if (address == 0) { @@ -597,7 +597,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { { DataExtractor data; lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); - Status error(GetValueAsData(exe_ctx, data, 0, NULL)); + Status error(GetValueAsData(exe_ctx, data, 0, nullptr)); if (error.Success()) { Scalar scalar; if (compiler_type.GetValueAsScalar(data, 0, data.GetByteSize(), @@ -625,7 +625,7 @@ Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { Variable *Value::GetVariable() { if (m_context_type == eContextTypeVariable) return static_cast(m_context); - return NULL; + return nullptr; } void Value::Clear() { @@ -633,7 +633,7 @@ void Value::Clear() { m_vector.Clear(); m_compiler_type.Clear(); m_value_type = eValueTypeScalar; - m_context = NULL; + m_context = nullptr; m_context_type = eContextTypeInvalid; m_data_buffer.Clear(); } @@ -702,7 +702,7 @@ Value *ValueList::GetValueAtIndex(size_t idx) { if (idx < GetSize()) { return &(m_values[idx]); } else - return NULL; + return nullptr; } void ValueList::Clear() { m_values.clear(); } diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 8bb542263f95f..e083b8dc086c4 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -81,12 +81,13 @@ static user_id_t g_value_obj_uid = 0; // ValueObject constructor ValueObject::ValueObject(ValueObject &parent) : UserID(++g_value_obj_uid), // Unique identifier for every value object - m_parent(&parent), m_root(NULL), m_update_point(parent.GetUpdatePoint()), - m_name(), m_data(), m_value(), m_error(), m_value_str(), - m_old_value_str(), m_location_str(), m_summary_str(), m_object_desc_str(), - m_validation_result(), m_manager(parent.GetManager()), m_children(), - m_synthetic_children(), m_dynamic_value(NULL), m_synthetic_value(NULL), - m_deref_valobj(NULL), m_format(eFormatDefault), + m_parent(&parent), m_root(nullptr), + m_update_point(parent.GetUpdatePoint()), m_name(), m_data(), m_value(), + m_error(), m_value_str(), m_old_value_str(), m_location_str(), + m_summary_str(), m_object_desc_str(), m_validation_result(), + m_manager(parent.GetManager()), m_children(), m_synthetic_children(), + m_dynamic_value(nullptr), m_synthetic_value(nullptr), + m_deref_valobj(nullptr), m_format(eFormatDefault), m_last_format(eFormatDefault), m_last_format_mgr_revision(0), m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(), m_type_validator_sp(), m_user_id_of_forced_summary(), @@ -108,15 +109,15 @@ ValueObject::ValueObject(ValueObject &parent) ValueObject::ValueObject(ExecutionContextScope *exe_scope, AddressType child_ptr_or_ref_addr_type) : UserID(++g_value_obj_uid), // Unique identifier for every value object - m_parent(NULL), m_root(NULL), m_update_point(exe_scope), m_name(), + m_parent(nullptr), m_root(nullptr), m_update_point(exe_scope), m_name(), m_data(), m_value(), m_error(), m_value_str(), m_old_value_str(), m_location_str(), m_summary_str(), m_object_desc_str(), m_validation_result(), m_manager(), m_children(), m_synthetic_children(), - m_dynamic_value(NULL), m_synthetic_value(NULL), m_deref_valobj(NULL), - m_format(eFormatDefault), m_last_format(eFormatDefault), - m_last_format_mgr_revision(0), m_type_summary_sp(), m_type_format_sp(), - m_synthetic_children_sp(), m_type_validator_sp(), - m_user_id_of_forced_summary(), + m_dynamic_value(nullptr), m_synthetic_value(nullptr), + m_deref_valobj(nullptr), m_format(eFormatDefault), + m_last_format(eFormatDefault), m_last_format_mgr_revision(0), + m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(), + m_type_validator_sp(), m_user_id_of_forced_summary(), m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), m_value_checksum(), m_preferred_display_language(lldb::eLanguageTypeUnknown), @@ -465,7 +466,7 @@ ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) { } ValueObject *child = m_children.GetChildAtIndex(idx); - if (child != NULL) + if (child != nullptr) return child->GetSP(); } return child_sp; @@ -617,7 +618,7 @@ void ValueObject::SetName(ConstString name) { m_name = name; } ValueObject *ValueObject::CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) { - ValueObject *valobj = NULL; + ValueObject *valobj = nullptr; bool omit_empty_base_classes = true; bool ignore_array_bounds = synthetic_array_member; @@ -710,7 +711,7 @@ const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) { summary_options); } if (m_summary_str.empty()) - return NULL; + return nullptr; return m_summary_str.c_str(); } @@ -763,12 +764,12 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, if (is_pointer_type) { Status error; ValueObjectSP pointee_sp = Dereference(error); - if (error.Fail() || pointee_sp.get() == NULL) + if (error.Fail() || pointee_sp.get() == nullptr) return 0; return pointee_sp->GetData(data, error); } else { ValueObjectSP child_sp = GetChildAtIndex(0, true); - if (child_sp.get() == NULL) + if (child_sp.get() == nullptr) return 0; Status error; return child_sp->GetData(data, error); @@ -777,7 +778,7 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, } else /* (items > 1) */ { Status error; - lldb_private::DataBufferHeap *heap_buf_ptr = NULL; + lldb_private::DataBufferHeap *heap_buf_ptr = nullptr; lldb::DataBufferSP data_sp(heap_buf_ptr = new lldb_private::DataBufferHeap()); @@ -964,7 +965,7 @@ ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error, if (is_array) { // We have an array uint64_t array_size = 0; - if (compiler_type.IsArrayType(NULL, &array_size, NULL)) { + if (compiler_type.IsArrayType(nullptr, &array_size, nullptr)) { cstr_len = array_size; if (cstr_len > max_length) { capped_data = true; @@ -1170,7 +1171,7 @@ const char *ValueObject::GetValueAsCString() { } } if (m_value_str.empty()) - return NULL; + return nullptr; return m_value_str.c_str(); } @@ -1281,7 +1282,7 @@ bool ValueObject::DumpPrintableRepresentation( buffer_sp, lldb::eByteOrderInvalid, 8)); // none of this matters for a string - pass some defaults options.SetStream(&s); - options.SetPrefixToken(0); + options.SetPrefixToken(nullptr); options.SetQuote('"'); options.SetSourceSize(buffer_sp->GetByteSize()); options.SetIsTruncated(read_string.second); @@ -1670,7 +1671,7 @@ ValueObject::GetTypeInfo(CompilerType *pointee_or_element_compiler_type) { bool ValueObject::IsPointerType() { return GetCompilerType().IsPointerType(); } bool ValueObject::IsArrayType() { - return GetCompilerType().IsArrayType(NULL, NULL, NULL); + return GetCompilerType().IsArrayType(nullptr, nullptr, nullptr); } bool ValueObject::IsScalarType() { return GetCompilerType().IsScalarType(); } @@ -1689,7 +1690,7 @@ bool ValueObject::IsPossibleDynamicType() { if (process) return process->IsPossibleDynamicValue(*this); else - return GetCompilerType().IsPossibleDynamicType(NULL, true, true); + return GetCompilerType().IsPossibleDynamicType(nullptr, true, true); } bool ValueObject::IsRuntimeSupportValue() { @@ -1900,7 +1901,7 @@ ValueObject::GetSyntheticExpressionPathChild(const char *expression, // We haven't made a synthetic array member for expression yet, so lets // make one and cache it for any future reference. synthetic_child_sp = GetValueForExpressionPath( - expression, NULL, NULL, + expression, nullptr, nullptr, GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal( GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: None)); @@ -1923,7 +1924,7 @@ void ValueObject::CalculateSyntheticValue(bool use_synthetic) { TargetSP target_sp(GetTargetSP()); if (target_sp && !target_sp->GetEnableSyntheticValue()) { - m_synthetic_value = NULL; + m_synthetic_value = nullptr; return; } @@ -1932,7 +1933,7 @@ void ValueObject::CalculateSyntheticValue(bool use_synthetic) { if (!UpdateFormatsIfNeeded() && m_synthetic_value) return; - if (m_synthetic_children_sp.get() == NULL) + if (m_synthetic_children_sp.get() == nullptr) return; if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value) @@ -1959,7 +1960,7 @@ ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) { if (use_dynamic == eNoDynamicValues) return ValueObjectSP(); - if (!IsDynamic() && m_dynamic_value == NULL) { + if (!IsDynamic() && m_dynamic_value == nullptr) { CalculateDynamicValue(use_dynamic); } if (m_dynamic_value) @@ -1987,7 +1988,7 @@ ValueObjectSP ValueObject::GetSyntheticValue(bool use_synthetic) { bool ValueObject::HasSyntheticValue() { UpdateFormatsIfNeeded(); - if (m_synthetic_children_sp.get() == NULL) + if (m_synthetic_children_sp.get() == nullptr) return false; CalculateSyntheticValue(true); @@ -2020,7 +2021,7 @@ ValueObject *ValueObject::GetNonBaseClassParent() { else return GetParent(); } - return NULL; + return nullptr; } bool ValueObject::IsBaseClass(uint32_t &depth) { @@ -3005,12 +3006,12 @@ bool ValueObject::EvaluationPoint::SyncWithProcessState( ExecutionContext exe_ctx( m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped)); - if (exe_ctx.GetTargetPtr() == NULL) + if (exe_ctx.GetTargetPtr() == nullptr) return false; // If we don't have a process nothing can change. Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) + if (process == nullptr) return false; // If our stop id is the current stop ID, nothing has changed: @@ -3091,7 +3092,7 @@ void ValueObject::ClearUserVisibleData(uint32_t clear_mask) { if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) == eClearUserVisibleDataItemsSyntheticChildren) { if (m_synthetic_value) - m_synthetic_value = NULL; + m_synthetic_value = nullptr; } if ((clear_mask & eClearUserVisibleDataItemsValidator) == @@ -3104,7 +3105,7 @@ SymbolContextScope *ValueObject::GetSymbolContextScope() { if (!m_parent->IsPointerOrReferenceType()) return m_parent->GetSymbolContextScope(); } - return NULL; + return nullptr; } lldb::ValueObjectSP diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp index aeea1743682c8..de51735736b9c 100644 --- a/lldb/source/Core/ValueObjectConstResultImpl.cpp +++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp @@ -39,7 +39,7 @@ ValueObjectConstResultImpl::ValueObjectConstResultImpl( m_address_of_backend() {} lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) { - if (m_impl_backend == NULL) + if (m_impl_backend == nullptr) return lldb::ValueObjectSP(); return m_impl_backend->ValueObject::Dereference(error); @@ -47,12 +47,12 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) { ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex( size_t idx, bool synthetic_array_member, int32_t synthetic_index) { - if (m_impl_backend == NULL) - return NULL; + if (m_impl_backend == nullptr) + return nullptr; m_impl_backend->UpdateValueIfNeeded(false); - ValueObjectConstResultChild *valobj = NULL; + ValueObjectConstResultChild *valobj = nullptr; bool omit_empty_base_classes = true; bool ignore_array_bounds = synthetic_array_member; @@ -106,7 +106,7 @@ ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex( lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset( uint32_t offset, const CompilerType &type, bool can_create, ConstString name_const_str) { - if (m_impl_backend == NULL) + if (m_impl_backend == nullptr) return lldb::ValueObjectSP(); return m_impl_backend->ValueObject::GetSyntheticChildAtOffset( @@ -114,10 +114,10 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset( } lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) { - if (m_address_of_backend.get() != NULL) + if (m_address_of_backend.get() != nullptr) return m_address_of_backend; - if (m_impl_backend == NULL) + if (m_impl_backend == nullptr) return lldb::ValueObjectSP(); if (m_live_address != LLDB_INVALID_ADDRESS) { CompilerType compiler_type(m_impl_backend->GetCompilerType()); @@ -143,7 +143,7 @@ lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) { lldb::ValueObjectSP ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) { - if (m_impl_backend == NULL) + if (m_impl_backend == nullptr) return lldb::ValueObjectSP(); ValueObjectConstResultCast *result_cast = @@ -156,7 +156,7 @@ lldb::addr_t ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address, AddressType *address_type) { - if (m_impl_backend == NULL) + if (m_impl_backend == nullptr) return 0; if (m_live_address == LLDB_INVALID_ADDRESS) { @@ -173,7 +173,7 @@ ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address, size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data, uint32_t item_idx, uint32_t item_count) { - if (m_impl_backend == NULL) + if (m_impl_backend == nullptr) return 0; return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp index 42d1263b3909f..95d4330ee0c6b 100644 --- a/lldb/source/Core/ValueObjectMemory.cpp +++ b/lldb/source/Core/ValueObjectMemory.cpp @@ -49,7 +49,7 @@ ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), m_compiler_type() { // Do not attempt to construct one of these objects with no variable! - assert(m_type_sp.get() != NULL); + assert(m_type_sp.get() != nullptr); SetName(ConstString(name)); m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); TargetSP target_sp(GetTargetSP()); diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp index 1d12747649e3d..75a254fbbc21d 100644 --- a/lldb/source/Core/ValueObjectRegister.cpp +++ b/lldb/source/Core/ValueObjectRegister.cpp @@ -76,7 +76,7 @@ bool ValueObjectRegisterContext::UpdateValue() { else m_reg_ctx_sp.reset(); - if (m_reg_ctx_sp.get() == NULL) { + if (m_reg_ctx_sp.get() == nullptr) { SetValueIsValid(false); m_error.SetErrorToGenericError(); } else @@ -87,7 +87,7 @@ bool ValueObjectRegisterContext::UpdateValue() { ValueObject *ValueObjectRegisterContext::CreateChildAtIndex( size_t idx, bool synthetic_array_member, int32_t synthetic_index) { - ValueObject *new_valobj = NULL; + ValueObject *new_valobj = nullptr; const size_t num_children = GetNumChildren(); if (idx < num_children) { @@ -112,7 +112,7 @@ ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope, ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx, uint32_t reg_set_idx) - : ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_set(NULL), + : ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_set(nullptr), m_reg_set_idx(reg_set_idx) { assert(reg_ctx); m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx); @@ -149,13 +149,13 @@ bool ValueObjectRegisterSet::UpdateValue() { SetValueDidChange(false); ExecutionContext exe_ctx(GetExecutionContextRef()); StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) + if (frame == nullptr) m_reg_ctx_sp.reset(); else { m_reg_ctx_sp = frame->GetRegisterContext(); if (m_reg_ctx_sp) { const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); - if (reg_set == NULL) + if (reg_set == nullptr) m_reg_ctx_sp.reset(); else if (m_reg_set != reg_set) { SetValueDidChange(true); @@ -175,7 +175,7 @@ bool ValueObjectRegisterSet::UpdateValue() { ValueObject *ValueObjectRegisterSet::CreateChildAtIndex( size_t idx, bool synthetic_array_member, int32_t synthetic_index) { - ValueObject *valobj = NULL; + ValueObject *valobj = nullptr; if (m_reg_ctx_sp && m_reg_set) { const size_t num_children = GetNumChildren(); if (idx < num_children) @@ -188,11 +188,11 @@ ValueObject *ValueObjectRegisterSet::CreateChildAtIndex( lldb::ValueObjectSP ValueObjectRegisterSet::GetChildMemberWithName(ConstString name, bool can_create) { - ValueObject *valobj = NULL; + ValueObject *valobj = nullptr; if (m_reg_ctx_sp && m_reg_set) { const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString()); - if (reg_info != NULL) + if (reg_info != nullptr) valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info->kinds[eRegisterKindLLDB]); } @@ -207,7 +207,7 @@ ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) { if (m_reg_ctx_sp && m_reg_set) { const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString()); - if (reg_info != NULL) + if (reg_info != nullptr) return reg_info->kinds[eRegisterKindLLDB]; } return UINT32_MAX; @@ -289,7 +289,7 @@ bool ValueObjectRegister::UpdateValue() { m_error.Clear(); ExecutionContext exe_ctx(GetExecutionContextRef()); StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) { + if (frame == nullptr) { m_reg_ctx_sp.reset(); m_reg_value.Clear(); } diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index dae9c709ecd8c..5aee82493b28f 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -57,7 +57,7 @@ ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) : ValueObject(exe_scope), m_variable_sp(var_sp) { // Do not attempt to construct one of these objects with no variable! - assert(m_variable_sp.get() != NULL); + assert(m_variable_sp.get() != nullptr); m_name = var_sp->GetName(); } @@ -135,7 +135,7 @@ bool ValueObjectVariable::UpdateValue() { else m_error.SetErrorString("empty constant data"); // constant bytes can't be edited - sorry - m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); + m_resolved_value.SetContext(Value::eContextTypeInvalid, nullptr); } else { lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; ExecutionContext exe_ctx(GetExecutionContextRef()); @@ -261,7 +261,7 @@ bool ValueObjectVariable::UpdateValue() { SetValueIsValid(m_error.Success()); } else { // could not find location, won't allow editing - m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); + m_resolved_value.SetContext(Value::eContextTypeInvalid, nullptr); } } return m_error.Success(); @@ -298,7 +298,7 @@ lldb::ModuleSP ValueObjectVariable::GetModule() { SymbolContextScope *ValueObjectVariable::GetSymbolContextScope() { if (m_variable_sp) return m_variable_sp->GetSymbolContextScope(); - return NULL; + return nullptr; } bool ValueObjectVariable::GetDeclaration(Declaration &decl) { diff --git a/lldb/source/DataFormatters/DataVisualization.cpp b/lldb/source/DataFormatters/DataVisualization.cpp index 948aa71b8ac9a..08b3b34447bba 100644 --- a/lldb/source/DataFormatters/DataVisualization.cpp +++ b/lldb/source/DataFormatters/DataVisualization.cpp @@ -89,7 +89,7 @@ bool DataVisualization::Categories::GetCategory(ConstString category, lldb::TypeCategoryImplSP &entry, bool allow_create) { entry = GetFormatManager().GetCategory(category, allow_create); - return (entry.get() != NULL); + return (entry.get() != nullptr); } bool DataVisualization::Categories::GetCategory( diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp index 40d6407eadeb3..dd2808a7cf7c9 100644 --- a/lldb/source/DataFormatters/FormatManager.cpp +++ b/lldb/source/DataFormatters/FormatManager.cpp @@ -146,7 +146,7 @@ char FormatManager::GetFormatAsFormatChar(lldb::Format format) { const char *FormatManager::GetFormatAsCString(Format format) { if (format >= eFormatDefault && format < kNumFormats) return g_format_infos[format].format_name; - return NULL; + return nullptr; } void FormatManager::EnableAllCategories() { @@ -297,7 +297,7 @@ FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) { lldb::TypeFormatImplSP format_current_sp = category_sp->GetFormatForType(type_sp); if (format_current_sp && - (format_chosen_sp.get() == NULL || + (format_chosen_sp.get() == nullptr || (prio_category > category_sp->GetEnabledPosition()))) { prio_category = category_sp->GetEnabledPosition(); format_chosen_sp = format_current_sp; @@ -321,7 +321,7 @@ FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) { lldb::TypeSummaryImplSP summary_current_sp = category_sp->GetSummaryForType(type_sp); if (summary_current_sp && - (summary_chosen_sp.get() == NULL || + (summary_chosen_sp.get() == nullptr || (prio_category > category_sp->GetEnabledPosition()))) { prio_category = category_sp->GetEnabledPosition(); summary_chosen_sp = summary_current_sp; @@ -345,7 +345,7 @@ FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) { lldb::TypeFilterImplSP filter_current_sp( (TypeFilterImpl *)category_sp->GetFilterForType(type_sp).get()); if (filter_current_sp && - (filter_chosen_sp.get() == NULL || + (filter_chosen_sp.get() == nullptr || (prio_category > category_sp->GetEnabledPosition()))) { prio_category = category_sp->GetEnabledPosition(); filter_chosen_sp = filter_current_sp; @@ -370,7 +370,7 @@ FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) { (ScriptedSyntheticChildren *)category_sp->GetSyntheticForType(type_sp) .get()); if (synth_current_sp && - (synth_chosen_sp.get() == NULL || + (synth_chosen_sp.get() == nullptr || (prio_category > category_sp->GetEnabledPosition()))) { prio_category = category_sp->GetEnabledPosition(); synth_chosen_sp = synth_current_sp; @@ -394,7 +394,7 @@ FormatManager::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_sp) { lldb::TypeValidatorImplSP validator_current_sp( category_sp->GetValidatorForType(type_sp).get()); if (validator_current_sp && - (validator_chosen_sp.get() == NULL || + (validator_chosen_sp.get() == nullptr || (prio_category > category_sp->GetEnabledPosition()))) { prio_category = category_sp->GetEnabledPosition(); validator_chosen_sp = validator_current_sp; diff --git a/lldb/source/DataFormatters/FormattersHelpers.cpp b/lldb/source/DataFormatters/FormattersHelpers.cpp index b2bd1ebdfedde..8f007df03faa4 100644 --- a/lldb/source/DataFormatters/FormattersHelpers.cpp +++ b/lldb/source/DataFormatters/FormattersHelpers.cpp @@ -123,7 +123,7 @@ size_t lldb_private::formatters::ExtractIndexFromString(const char *item_name) { if (*item_name != '[') return UINT32_MAX; item_name++; - char *endptr = NULL; + char *endptr = nullptr; unsigned long int idx = ::strtoul(item_name, &endptr, 0); if (idx == 0 && endptr == item_name) return UINT32_MAX; diff --git a/lldb/source/DataFormatters/StringPrinter.cpp b/lldb/source/DataFormatters/StringPrinter.cpp index 4dfe0250c3b95..27d649bfc370e 100644 --- a/lldb/source/DataFormatters/StringPrinter.cpp +++ b/lldb/source/DataFormatters/StringPrinter.cpp @@ -271,7 +271,7 @@ static bool DumpUTFBufferToStream( llvm::ConversionFlags), const StringPrinter::ReadBufferAndDumpToStreamOptions &dump_options) { Stream &stream(*dump_options.GetStream()); - if (dump_options.GetPrefixToken() != 0) + if (dump_options.GetPrefixToken() != nullptr) stream.Printf("%s", dump_options.GetPrefixToken()); if (dump_options.GetQuote() != 0) stream.Printf("%c", dump_options.GetQuote()); @@ -373,7 +373,7 @@ static bool DumpUTFBufferToStream( } if (dump_options.GetQuote() != 0) stream.Printf("%c", dump_options.GetQuote()); - if (dump_options.GetSuffixToken() != 0) + if (dump_options.GetSuffixToken() != nullptr) stream.Printf("%s", dump_options.GetSuffixToken()); if (dump_options.GetIsTruncated()) stream.Printf("..."); @@ -449,7 +449,7 @@ bool StringPrinter::ReadStringAndDumpToStream< const char *prefix_token = options.GetPrefixToken(); char quote = options.GetQuote(); - if (prefix_token != 0) + if (prefix_token != nullptr) options.GetStream()->Printf("%s%c", prefix_token, quote); else if (quote != 0) options.GetStream()->Printf("%c", quote); @@ -497,7 +497,7 @@ bool StringPrinter::ReadStringAndDumpToStream< const char *suffix_token = options.GetSuffixToken(); - if (suffix_token != 0) + if (suffix_token != nullptr) options.GetStream()->Printf("%c%s", quote, suffix_token); else if (quote != 0) options.GetStream()->Printf("%c", quote); diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp index 72008b2431605..b526e9a744bc4 100644 --- a/lldb/source/DataFormatters/TypeFormat.cpp +++ b/lldb/source/DataFormatters/TypeFormat.cpp @@ -69,7 +69,7 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj, // default value logic if (GetFormat() == eFormatCString) { lldb_private::Flags type_flags(compiler_type.GetTypeInfo( - NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags + nullptr)); // disambiguate w.r.t. TypeFormatImpl::Flags if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC)) { // if we are dumping a pointer as a c-string, get the pointee data diff --git a/lldb/source/DataFormatters/TypeSynthetic.cpp b/lldb/source/DataFormatters/TypeSynthetic.cpp index c40aed1f79234..23c80fc58d021 100644 --- a/lldb/source/DataFormatters/TypeSynthetic.cpp +++ b/lldb/source/DataFormatters/TypeSynthetic.cpp @@ -128,7 +128,7 @@ lldb::ValueObjectSP SyntheticChildrenFrontEnd::CreateValueObjectFromData( ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, ValueObject &backend) : SyntheticChildrenFrontEnd(backend), m_python_class(pclass), - m_wrapper_sp(), m_interpreter(NULL) { + m_wrapper_sp(), m_interpreter(nullptr) { if (backend == LLDB_INVALID_UID) return; @@ -139,7 +139,7 @@ ScriptedSyntheticChildren::FrontEnd::FrontEnd(std::string pclass, m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); - if (m_interpreter != NULL) + if (m_interpreter != nullptr) m_wrapper_sp = m_interpreter->CreateSyntheticScriptedProvider( m_python_class.c_str(), backend.GetSP()); } @@ -159,26 +159,26 @@ bool ScriptedSyntheticChildren::FrontEnd::IsValid() { } size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren() { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return 0; return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX); } size_t ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren(uint32_t max) { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return 0; return m_interpreter->CalculateNumChildren(m_wrapper_sp, max); } bool ScriptedSyntheticChildren::FrontEnd::Update() { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return false; return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); } bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return false; return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); @@ -186,21 +186,21 @@ bool ScriptedSyntheticChildren::FrontEnd::MightHaveChildren() { size_t ScriptedSyntheticChildren::FrontEnd::GetIndexOfChildWithName( ConstString name) { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return UINT32_MAX; return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); } lldb::ValueObjectSP ScriptedSyntheticChildren::FrontEnd::GetSyntheticValue() { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return nullptr; return m_interpreter->GetSyntheticValue(m_wrapper_sp); } ConstString ScriptedSyntheticChildren::FrontEnd::GetSyntheticTypeName() { - if (!m_wrapper_sp || m_interpreter == NULL) + if (!m_wrapper_sp || m_interpreter == nullptr) return ConstString(); return m_interpreter->GetSyntheticTypeName(m_wrapper_sp); diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp index 5fe7e20bac15b..409cffed9b0f9 100644 --- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp +++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp @@ -331,7 +331,7 @@ TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) { : m_valobj->GetSummaryFormat().get(); if (m_options.m_omit_summary_depth > 0) - entry = NULL; + entry = nullptr; m_summary_formatter.first = entry; m_summary_formatter.second = true; } @@ -415,8 +415,9 @@ bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed, // explicitly) TypeSummaryImpl *entry = GetSummaryFormatter(); if (!IsNil() && !IsUninitialized() && !m_value.empty() && - (entry == NULL || (entry->DoesPrintValue(m_valobj) || - m_options.m_format != eFormatDefault) || + (entry == nullptr || + (entry->DoesPrintValue(m_valobj) || + m_options.m_format != eFormatDefault) || m_summary.empty()) && !m_options.m_hide_value) { if (m_options.m_hide_pointer_value && diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 45c42dfad81b8..c86def753d923 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -649,7 +649,7 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx, lldb::RegisterKind reg_kind, uint32_t reg_num, Status *error_ptr, Value &value) { - if (reg_ctx == NULL) { + if (reg_ctx == nullptr) { if (error_ptr) error_ptr->SetErrorStringWithFormat("No register context in frame.\n"); } else { @@ -1249,7 +1249,7 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx, if (IsLocationList()) { lldb::offset_t offset = 0; addr_t pc; - StackFrame *frame = NULL; + StackFrame *frame = nullptr; if (reg_ctx) pc = reg_ctx->GetPC(); else { @@ -1323,14 +1323,14 @@ bool DWARFExpression::Evaluate( } std::vector stack; - Process *process = NULL; - StackFrame *frame = NULL; + Process *process = nullptr; + StackFrame *frame = nullptr; if (exe_ctx) { process = exe_ctx->GetProcessPtr(); frame = exe_ctx->GetFramePtr(); } - if (reg_ctx == NULL && frame) + if (reg_ctx == nullptr && frame) reg_ctx = frame->GetRegisterContext().get(); if (initial_value_ptr) @@ -3166,7 +3166,7 @@ void DWARFExpression::PrintDWARFLocationList( s.Indent(); if (cu) s.AddressRange(start_addr + base_addr, end_addr + base_addr, - cu->GetAddressByteSize(), NULL, ": "); + cu->GetAddressByteSize(), nullptr, ": "); uint32_t loc_length = debug_loc_data.GetU16(&offset); DataExtractor locationData(debug_loc_data, offset, loc_length); diff --git a/lldb/source/Expression/ExpressionVariable.cpp b/lldb/source/Expression/ExpressionVariable.cpp index faac977cde98e..97305dcf5a026 100644 --- a/lldb/source/Expression/ExpressionVariable.cpp +++ b/lldb/source/Expression/ExpressionVariable.cpp @@ -25,7 +25,7 @@ uint8_t *ExpressionVariable::GetValueBytes() { return const_cast( m_frozen_sp->GetDataExtractor().GetDataStart()); } - return NULL; + return nullptr; } PersistentExpressionState::~PersistentExpressionState() {} diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp index 5f5e3b86ccdbc..618c1a13212c4 100644 --- a/lldb/source/Expression/FunctionCaller.cpp +++ b/lldb/source/Expression/FunctionCaller.cpp @@ -35,10 +35,9 @@ FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope, const Address &functionAddress, const ValueList &arg_value_list, const char *name) - : Expression(exe_scope, eKindFunctionCaller), - m_execution_unit_sp(), m_parser(), - m_jit_module_wp(), m_name(name ? name : ""), - m_function_ptr(NULL), m_function_addr(functionAddress), + : Expression(exe_scope, eKindFunctionCaller), m_execution_unit_sp(), + m_parser(), m_jit_module_wp(), m_name(name ? name : ""), + m_function_ptr(nullptr), m_function_addr(functionAddress), m_function_return_type(return_type), m_wrapper_function_name("__lldb_caller_function"), m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(), @@ -138,7 +137,7 @@ bool FunctionCaller::WriteFunctionArguments( Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) + if (process == nullptr) return return_value; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); @@ -239,11 +238,11 @@ lldb::ThreadPlanSP FunctionCaller::GetThreadPlanToCallFunction( // FIXME: Use the errors Stream for better error reporting. Thread *thread = exe_ctx.GetThreadPtr(); - if (thread == NULL) { + if (thread == nullptr) { diagnostic_manager.PutString( eDiagnosticSeverityError, "Can't call a function without a valid thread."); - return NULL; + return nullptr; } // Okay, now run the function: @@ -279,7 +278,7 @@ bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx, Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) + if (process == nullptr) return false; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); @@ -326,7 +325,7 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction( lldb::addr_t args_addr; - if (args_addr_ptr != NULL) + if (args_addr_ptr != nullptr) args_addr = *args_addr_ptr; else args_addr = LLDB_INVALID_ADDRESS; @@ -376,7 +375,7 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction( if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - if (args_addr_ptr != NULL) + if (args_addr_ptr != nullptr) *args_addr_ptr = args_addr; if (return_value != lldb::eExpressionCompleted) @@ -384,7 +383,7 @@ lldb::ExpressionResults FunctionCaller::ExecuteFunction( FetchFunctionResults(exe_ctx, args_addr, results); - if (args_addr_ptr == NULL) + if (args_addr_ptr == nullptr) DeallocateFunctionResults(exe_ctx, args_addr); return lldb::eExpressionCompleted; diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 7c0379cdee8e6..34a3488578cde 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -165,8 +165,8 @@ Status IRExecutionUnit::DisassembleFunction(Stream &stream, ArchSpec arch(target->GetArchitecture()); - const char *plugin_name = NULL; - const char *flavor_string = NULL; + const char *plugin_name = nullptr; + const char *flavor_string = nullptr; lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name); @@ -251,7 +251,7 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, std::string s; llvm::raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, nullptr); oss.flush(); @@ -839,7 +839,7 @@ lldb::addr_t IRExecutionUnit::FindInSymbols( }; if (sc.module_sp) { - sc.module_sp->FindFunctions(spec.name, NULL, spec.mask, + sc.module_sp->FindFunctions(spec.name, nullptr, spec.mask, true, // include_symbols false, // include_inlines true, // append diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index 85eb78f539de9..24a3cd24fdd27 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -654,7 +654,7 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, std::string s; raw_string_ostream oss(s); - module.print(oss, NULL); + module.print(oss, nullptr); oss.flush(); diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index a8bf6733d8dbb..70e62ac12b0e8 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -263,7 +263,7 @@ ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const { if (target_sp) return target_sp.get(); - return NULL; + return nullptr; } IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc, diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp index 6f5972b32bbd2..5a1b750318c9f 100644 --- a/lldb/source/Expression/LLVMUserExpression.cpp +++ b/lldb/source/Expression/LLVMUserExpression.cpp @@ -50,7 +50,7 @@ LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope, m_allow_objc(false), m_transformed_text(), m_execution_unit_sp(), m_materializer_up(), m_jit_module_wp(), m_enforce_valid_object(true), m_in_cplusplus_method(false), m_in_objectivec_method(false), - m_in_static_method(false), m_needs_object_ptr(false), m_target(NULL), + m_in_static_method(false), m_needs_object_ptr(false), m_target(nullptr), m_can_interpret(false), m_materialized_address(LLDB_INVALID_ADDRESS) {} LLVMUserExpression::~LLVMUserExpression() { @@ -181,7 +181,7 @@ LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) { - const char *error_desc = NULL; + const char *error_desc = nullptr; if (call_plan_sp) { lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index 47aadba3578ac..a72e2a07599e5 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -174,7 +174,7 @@ lldb::ExpressionResults UserExpression::Evaluate( Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL || process->GetState() != lldb::eStateStopped) { + if (process == nullptr || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but " @@ -186,7 +186,7 @@ lldb::ExpressionResults UserExpression::Evaluate( } } - if (process == NULL || !process->CanJIT()) + if (process == nullptr || !process->CanJIT()) execution_policy = eExecutionPolicyNever; // We need to set the expression execution thread here, turns out parse can @@ -375,7 +375,7 @@ lldb::ExpressionResults UserExpression::Evaluate( return lldb::eExpressionInterrupted; } - if (result_valobj_sp.get() == NULL) { + if (result_valobj_sp.get() == nullptr) { result_valobj_sp = ValueObjectConstResult::Create( exe_ctx.GetBestExecutionContextScope(), error); } diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index 2b647be572ab5..d3a70aeaa3267 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -163,7 +163,7 @@ class EditlineHistory { // Use static GetHistory() function to get a EditlineHistorySP to one of // these objects EditlineHistory(const std::string &prefix, uint32_t size, bool unique_entries) - : m_history(NULL), m_event(), m_prefix(prefix), m_path() { + : m_history(nullptr), m_event(), m_prefix(prefix), m_path() { m_history = history_winit(); history_w(m_history, &m_event, H_SETSIZE, size); if (unique_entries) @@ -202,7 +202,7 @@ class EditlineHistory { if (m_history) { history_wend(m_history); - m_history = NULL; + m_history = nullptr; } } @@ -224,7 +224,7 @@ class EditlineHistory { return history_sp; } - bool IsValid() const { return m_history != NULL; } + bool IsValid() const { return m_history != nullptr; } HistoryW *GetHistoryPtr() { return m_history; } @@ -514,11 +514,13 @@ int Editline::GetCharacter(EditLineGetCharType *c) { // Read returns, immediately lock the mutex again and check if we were // interrupted. m_output_mutex.unlock(); - int read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); + int read_count = + m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); m_output_mutex.lock(); if (m_editor_status == EditorStatus::Interrupted) { while (read_count > 0 && status == lldb::eConnectionStatusSuccess) - read_count = m_input_connection.Read(&ch, 1, llvm::None, status, NULL); + read_count = + m_input_connection.Read(&ch, 1, llvm::None, status, nullptr); lldbassert(status == lldb::eConnectionStatusInterrupted); return 0; } @@ -1081,7 +1083,7 @@ void Editline::ConfigureEditor(bool multiline) { // Allow user-specific customization prior to registering bindings we // absolutely require - el_source(m_editline, NULL); + el_source(m_editline, nullptr); // Register an internal binding that external developers shouldn't use el_wset(m_editline, EL_ADDFN, EditLineConstString("lldb-revert-line"), diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 85e625ca78f89..c8c8d7a0d496c 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -65,11 +65,11 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) { } else if (options & File::eOpenOptionWrite) { return "w"; } - return NULL; + return nullptr; } int File::kInvalidDescriptor = -1; -FILE *File::kInvalidStream = NULL; +FILE *File::kInvalidStream = nullptr; File::~File() { Close(); } @@ -634,9 +634,9 @@ size_t File::Printf(const char *format, ...) { size_t File::PrintfVarArg(const char *format, va_list args) { size_t result = 0; if (DescriptorIsValid()) { - char *s = NULL; + char *s = nullptr; result = vasprintf(&s, format, args); - if (s != NULL) { + if (s != nullptr) { if (result > 0) { size_t s_len = result; Write(s, s_len); diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index d3e41a2b044f6..be206406e93a6 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -112,7 +112,7 @@ HostThread Host::StartMonitoringChildProcess( ::snprintf(thread_name, sizeof(thread_name), "", pid); return ThreadLauncher::LaunchThread( - thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); + thread_name, MonitorChildProcessThreadFunction, info_ptr, nullptr); } #ifndef __linux__ @@ -219,7 +219,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { bool exited = false; int signal = 0; int exit_status = 0; - const char *status_cstr = NULL; + const char *status_cstr = nullptr; if (WIFSTOPPED(status)) { signal = WSTOPSIG(status); status_cstr = "STOPPED"; @@ -282,7 +282,7 @@ static thread_result_t MonitorChildProcessThreadFunction(void *arg) { if (log) log->Printf("%s (arg = %p) thread exiting...", __FUNCTION__, arg); - return NULL; + return nullptr; } #endif // #if !defined (__APPLE__) && !defined (_WIN32) @@ -393,7 +393,7 @@ const char *Host::GetSignalAsCString(int signo) { default: break; } - return NULL; + return nullptr; } #endif diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp index a5f876a7232af..82f519e14f17b 100644 --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -18,10 +18,10 @@ using namespace lldb; using namespace lldb_private; HostNativeThreadBase::HostNativeThreadBase() - : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {} + : m_thread(LLDB_INVALID_HOST_THREAD), m_result(nullptr) {} HostNativeThreadBase::HostNativeThreadBase(thread_t thread) - : m_thread(thread), m_result(0) {} + : m_thread(thread), m_result(nullptr) {} lldb::thread_t HostNativeThreadBase::GetSystemHandle() const { return m_thread; @@ -37,7 +37,7 @@ bool HostNativeThreadBase::IsJoinable() const { void HostNativeThreadBase::Reset() { m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; + m_result = nullptr; } bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { @@ -47,7 +47,7 @@ bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { lldb::thread_t HostNativeThreadBase::Release() { lldb::thread_t result = m_thread; m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; + m_result = nullptr; return result; } diff --git a/lldb/source/Host/common/OptionParser.cpp b/lldb/source/Host/common/OptionParser.cpp index 97704988d36ad..92ff6f63d951f 100644 --- a/lldb/source/Host/common/OptionParser.cpp +++ b/lldb/source/Host/common/OptionParser.cpp @@ -55,11 +55,11 @@ std::string OptionParser::GetShortOptionString(struct option *long_options) { int i = 0; bool done = false; while (!done) { - if (long_options[i].name == 0 && long_options[i].has_arg == 0 && - long_options[i].flag == 0 && long_options[i].val == 0) { + if (long_options[i].name == nullptr && long_options[i].has_arg == 0 && + long_options[i].flag == nullptr && long_options[i].val == 0) { done = true; } else { - if (long_options[i].flag == NULL && isalpha(long_options[i].val)) { + if (long_options[i].flag == nullptr && isalpha(long_options[i].val)) { s.append(1, (char)long_options[i].val); switch (long_options[i].has_arg) { default: diff --git a/lldb/source/Host/common/ProcessRunLock.cpp b/lldb/source/Host/common/ProcessRunLock.cpp index 65a5dcca31fba..a931da7187665 100644 --- a/lldb/source/Host/common/ProcessRunLock.cpp +++ b/lldb/source/Host/common/ProcessRunLock.cpp @@ -12,7 +12,7 @@ namespace lldb_private { ProcessRunLock::ProcessRunLock() : m_running(false) { - int err = ::pthread_rwlock_init(&m_rwlock, NULL); + int err = ::pthread_rwlock_init(&m_rwlock, nullptr); (void)err; } diff --git a/lldb/source/Host/common/SocketAddress.cpp b/lldb/source/Host/common/SocketAddress.cpp index 06171d49bf68f..882fd24558f74 100644 --- a/lldb/source/Host/common/SocketAddress.cpp +++ b/lldb/source/Host/common/SocketAddress.cpp @@ -236,11 +236,11 @@ SocketAddress::GetAddressInfo(const char *hostname, const char *servname, hints.ai_protocol = ai_protocol; hints.ai_flags = ai_flags; - struct addrinfo *service_info_list = NULL; + struct addrinfo *service_info_list = nullptr; int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list); if (err == 0 && service_info_list) { - for (struct addrinfo *service_ptr = service_info_list; service_ptr != NULL; - service_ptr = service_ptr->ai_next) { + for (struct addrinfo *service_ptr = service_info_list; + service_ptr != nullptr; service_ptr = service_ptr->ai_next) { addr_list.emplace_back(SocketAddress(service_ptr)); } } diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp index 3f11e4e3b49f3..f97ca9eb55b86 100644 --- a/lldb/source/Host/common/TCPSocket.cpp +++ b/lldb/source/Host/common/TCPSocket.cpp @@ -143,7 +143,7 @@ Status TCPSocket::Connect(llvm::StringRef name) { return error; auto addresses = lldb_private::SocketAddress::GetAddressInfo( - host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); for (auto address : addresses) { error = CreateSocket(address.GetFamily()); if (error.Fail()) @@ -182,7 +182,7 @@ Status TCPSocket::Listen(llvm::StringRef name, int backlog) { if (host_str == "*") host_str = "0.0.0.0"; auto addresses = lldb_private::SocketAddress::GetAddressInfo( - host_str.c_str(), NULL, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); for (auto address : addresses) { int fd = Socket::CreateSocket(address.GetFamily(), kType, IPPROTO_TCP, m_child_processes_inherit, error); diff --git a/lldb/source/Host/common/TaskPool.cpp b/lldb/source/Host/common/TaskPool.cpp index 062fa4abd06c0..d63d9f35d1e21 100644 --- a/lldb/source/Host/common/TaskPool.cpp +++ b/lldb/source/Host/common/TaskPool.cpp @@ -73,7 +73,7 @@ void TaskPoolImpl::AddTask(std::function &&task_fn) { lldb::thread_result_t TaskPoolImpl::WorkerPtr(void *pool) { Worker((TaskPoolImpl *)pool); - return 0; + return nullptr; } void TaskPoolImpl::Worker(TaskPoolImpl *pool) { diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp index 9c60f0d1190cc..4b536b03d852b 100644 --- a/lldb/source/Host/common/Terminal.cpp +++ b/lldb/source/Host/common/Terminal.cpp @@ -112,7 +112,7 @@ bool TerminalState::Save(int fd, bool save_process_group) { m_tflags = ::fcntl(fd, F_GETFL, 0); #endif #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - if (m_termios_up == NULL) + if (m_termios_up == nullptr) m_termios_up.reset(new struct termios); int err = ::tcgetattr(fd, m_termios_up.get()); if (err != 0) @@ -151,7 +151,7 @@ bool TerminalState::Restore() const { if (ProcessGroupIsValid()) { // Save the original signal handler. - void (*saved_sigttou_callback)(int) = NULL; + void (*saved_sigttou_callback)(int) = nullptr; saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN); // Set the process group tcsetpgrp(fd, m_process_group); @@ -177,7 +177,7 @@ bool TerminalState::TFlagsIsValid() const { return m_tflags != -1; } // Returns true if m_ttystate is valid bool TerminalState::TTYStateIsValid() const { #ifdef LLDB_CONFIG_TERMIOS_SUPPORTED - return m_termios_up != 0; + return m_termios_up != nullptr; #else return false; #endif diff --git a/lldb/source/Host/common/ThreadLauncher.cpp b/lldb/source/Host/common/ThreadLauncher.cpp index ede864db108fa..2eff981bfa85d 100644 --- a/lldb/source/Host/common/ThreadLauncher.cpp +++ b/lldb/source/Host/common/ThreadLauncher.cpp @@ -49,7 +49,7 @@ HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, } #endif - pthread_attr_t *thread_attr_ptr = NULL; + pthread_attr_t *thread_attr_ptr = nullptr; pthread_attr_t thread_attr; bool destroy_attr = false; if (min_stack_byte_size > 0) { diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp index 006b49f4e1064..cb23ac17ef53b 100644 --- a/lldb/source/Host/common/XML.cpp +++ b/lldb/source/Host/common/XML.cpp @@ -134,7 +134,7 @@ XMLNode XMLNode::GetChild() const { llvm::StringRef XMLNode::GetAttributeValue(const char *name, const char *fail_value) const { - const char *attr_value = NULL; + const char *attr_value = nullptr; #if defined(LIBXML2_DEFINED) if (IsValid()) diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp index 03fa798f0f5b8..f6a8766a71c56 100644 --- a/lldb/source/Host/linux/Host.cpp +++ b/lldb/source/Host/linux/Host.cpp @@ -216,12 +216,12 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, DIR *dirproc = opendir(procdir); if (dirproc) { - struct dirent *direntry = NULL; + struct dirent *direntry = nullptr; const uid_t our_uid = getuid(); const lldb::pid_t our_pid = getpid(); bool all_users = match_info.GetMatchAllUsers(); - while ((direntry = readdir(dirproc)) != NULL) { + while ((direntry = readdir(dirproc)) != nullptr) { if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) continue; @@ -269,8 +269,8 @@ bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { DIR *dirproc = opendir(process_task_dir.c_str()); if (dirproc) { - struct dirent *direntry = NULL; - while ((direntry = readdir(dirproc)) != NULL) { + struct dirent *direntry = nullptr; + while ((direntry = readdir(dirproc)) != nullptr) { if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) continue; diff --git a/lldb/source/Host/linux/HostInfoLinux.cpp b/lldb/source/Host/linux/HostInfoLinux.cpp index 2b2207e7afa9c..78dd77b61fa71 100644 --- a/lldb/source/Host/linux/HostInfoLinux.cpp +++ b/lldb/source/Host/linux/HostInfoLinux.cpp @@ -121,7 +121,8 @@ llvm::StringRef HostInfoLinux::GetDistributionId() { // retrieve the distribution id string. char distribution_id[256] = {'\0'}; - if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != NULL) { + if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != + nullptr) { if (log) log->Printf("distribution id command returned \"%s\"", distribution_id); diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 4bbebd627d44b..167569dca69e9 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -111,7 +111,7 @@ ConnectionFileDescriptor::~ConnectionFileDescriptor() { if (log) log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast(this)); - Disconnect(NULL); + Disconnect(nullptr); CloseCommandPipe(); } diff --git a/lldb/source/Host/posix/HostThreadPosix.cpp b/lldb/source/Host/posix/HostThreadPosix.cpp index caa137ae3d029..d78bba517f69c 100644 --- a/lldb/source/Host/posix/HostThreadPosix.cpp +++ b/lldb/source/Host/posix/HostThreadPosix.cpp @@ -29,7 +29,7 @@ Status HostThreadPosix::Join(lldb::thread_result_t *result) { error.SetError(err, lldb::eErrorTypePOSIX); } else { if (result) - *result = NULL; + *result = nullptr; error.SetError(EINVAL, eErrorTypePOSIX); } diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index f6027636bd3cc..b951cce8c5984 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -1739,7 +1739,7 @@ bool CommandInterpreter::HandleCommand(const char *command_line, log->Printf("HandleCommand, (revised) command_string: '%s'", command_string.c_str()); const bool wants_raw_input = - (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false; + (cmd_obj != nullptr) ? cmd_obj->WantsRawCommandString() : false; log->Printf("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); } @@ -2214,7 +2214,7 @@ void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result) { const char *CommandInterpreter::GetCommandPrefix() { const char *prefix = GetDebugger().GetIOHandlerCommandPrefix(); - return prefix == NULL ? "" : prefix; + return prefix == nullptr ? "" : prefix; } PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) { @@ -3206,7 +3206,7 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line, if (!scratch_command.empty()) revised_command_line.Printf(" %s", scratch_command.c_str()); - if (cmd_obj != NULL) + if (cmd_obj != nullptr) command_line = revised_command_line.GetString(); return cmd_obj; diff --git a/lldb/source/Interpreter/OptionValue.cpp b/lldb/source/Interpreter/OptionValue.cpp index f45109f31fba5..00c8642595b72 100644 --- a/lldb/source/Interpreter/OptionValue.cpp +++ b/lldb/source/Interpreter/OptionValue.cpp @@ -165,13 +165,13 @@ const OptionValueFormat *OptionValue::GetAsFormat() const { OptionValueLanguage *OptionValue::GetAsLanguage() { if (GetType() == OptionValue::eTypeLanguage) return static_cast(this); - return NULL; + return nullptr; } const OptionValueLanguage *OptionValue::GetAsLanguage() const { if (GetType() == OptionValue::eTypeLanguage) return static_cast(this); - return NULL; + return nullptr; } OptionValueFormatEntity *OptionValue::GetAsFormatEntity() { @@ -520,7 +520,7 @@ lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask( value_sp.reset(new OptionValueFormat(eFormatInvalid)); break; case 1u << eTypeFormatEntity: - value_sp.reset(new OptionValueFormatEntity(NULL)); + value_sp.reset(new OptionValueFormatEntity(nullptr)); break; case 1u << eTypeLanguage: value_sp.reset(new OptionValueLanguage(eLanguageTypeUnknown)); diff --git a/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index c97c76c0a91d2..dd47ac7cbe3cc 100644 --- a/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/lldb/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -1739,8 +1739,8 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( uint32_t index = 0; for (index = 0; index < num_children; index++) { std::string name; - base_type = - compiler_type.GetFieldAtIndex(index, name, NULL, NULL, NULL); + base_type = compiler_type.GetFieldAtIndex(index, name, nullptr, + nullptr, nullptr); if (base_type.IsFloatingPointType(float_count, is_complex)) { llvm::Optional base_byte_size = @@ -1799,7 +1799,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindDWARF, regnum); - if (reg_info == NULL) + if (reg_info == nullptr) break; RegisterValue reg_value; diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 36261a335a8ba..44c75fc953c82 100644 --- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -356,7 +356,7 @@ class InstructionLLVMC : public lldb_private::Instruction { return; else { const uint8_t *bytes = data.PeekData(offset, inst_size); - if (bytes == NULL) + if (bytes == nullptr) return; m_opcode_name.assign(".byte"); m_opcode.SetOpcodeBytes(bytes, inst_size); @@ -956,7 +956,7 @@ DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, return Instance(); std::unique_ptr context_up( - new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), 0)); + new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), nullptr)); if (!context_up) return Instance(); @@ -1079,7 +1079,7 @@ bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const { DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch, const char *flavor_string) - : Disassembler(arch, flavor_string), m_exe_ctx(NULL), m_inst(NULL), + : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr), m_data_from_file(false) { if (!FlavorValidForArchSpec(arch, m_flavor.c_str())) { m_flavor.assign("default"); @@ -1242,7 +1242,7 @@ Disassembler *DisassemblerLLVMC::CreateInstance(const ArchSpec &arch, if (disasm_up.get() && disasm_up->IsValid()) return disasm_up.release(); } - return NULL; + return nullptr; } size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr, @@ -1329,7 +1329,7 @@ const char *DisassemblerLLVMC::SymbolLookupCallback(void *disassembler, bool DisassemblerLLVMC::FlavorValidForArchSpec( const lldb_private::ArchSpec &arch, const char *flavor) { llvm::Triple triple = arch.GetTriple(); - if (flavor == NULL || strcmp(flavor, "default") == 0) + if (flavor == nullptr || strcmp(flavor, "default") == 0) return true; if (triple.getArch() == llvm::Triple::x86 || @@ -1358,7 +1358,7 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, if (*type_ptr) { if (m_exe_ctx && m_inst) { // std::string remove_this_prior_to_checkin; - Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL; + Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : nullptr; Address value_so_addr; Address pc_so_addr; if (m_inst->UsingFileAddress()) { @@ -1423,8 +1423,8 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, } *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; - *name = NULL; - return NULL; + *name = nullptr; + return nullptr; } // PluginInterface protocol diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 760f344e5ab45..242085ac872a3 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -73,9 +73,9 @@ static constexpr OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = { "on 32-bit targets)."}}; static constexpr PropertyDefinition g_properties[] = { - {"load-kexts", OptionValue::eTypeBoolean, true, true, NULL, {}, + {"load-kexts", OptionValue::eTypeBoolean, true, true, nullptr, {}, "Automatically loads kext images when attaching to a kernel."}, - {"scan-type", OptionValue::eTypeEnum, true, eKASLRScanNearPC, NULL, + {"scan-type", OptionValue::eTypeEnum, true, eKASLRScanNearPC, nullptr, OptionEnumValues(g_kaslr_kernel_scan_enum_values), "Control how many reads lldb will make while searching for a Darwin " "kernel on attach."}}; @@ -99,13 +99,13 @@ class DynamicLoaderDarwinKernelProperties : public Properties { bool GetLoadKexts() const { const uint32_t idx = ePropertyLoadKexts; return m_collection_sp->GetPropertyAtIndexAsBoolean( - NULL, idx, g_properties[idx].default_uint_value != 0); + nullptr, idx, g_properties[idx].default_uint_value != 0); } KASLRScanType GetScanType() const { const uint32_t idx = ePropertyScanType; return (KASLRScanType)m_collection_sp->GetPropertyAtIndexAsEnumeration( - NULL, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_properties[idx].default_uint_value); } }; @@ -132,7 +132,7 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process, ObjectFile *object_file = exe_module->GetObjectFile(); if (object_file) { if (object_file->GetStrata() != ObjectFile::eStrataKernel) { - return NULL; + return nullptr; } } } @@ -149,7 +149,7 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process, case llvm::Triple::WatchOS: // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: if (triple_ref.getVendor() != llvm::Triple::Apple) { - return NULL; + return nullptr; } break; // If we have triple like armv7-unknown-unknown, we should try looking for @@ -157,7 +157,7 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process, case llvm::Triple::UnknownOS: break; default: - return NULL; + return nullptr; break; } } @@ -171,7 +171,7 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process, process->SetCanRunCode(false); return new DynamicLoaderDarwinKernel(process, kernel_load_address); } - return NULL; + return nullptr; } lldb::addr_t @@ -198,11 +198,11 @@ DynamicLoaderDarwinKernel::SearchForDarwinKernel(Process *process) { lldb::addr_t DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr(Process *process) { Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module == NULL) + if (exe_module == nullptr) return LLDB_INVALID_ADDRESS; ObjectFile *exe_objfile = exe_module->GetObjectFile(); - if (exe_objfile == NULL) + if (exe_objfile == nullptr) return LLDB_INVALID_ADDRESS; if (exe_objfile->GetType() != ObjectFile::eTypeExecutable || @@ -282,7 +282,7 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) { } ThreadSP thread = process->GetThreadList().GetSelectedThread(); - if (thread.get() == NULL) + if (thread.get() == nullptr) return LLDB_INVALID_ADDRESS; addr_t pc = thread->GetRegisterContext()->GetPC(LLDB_INVALID_ADDRESS); @@ -454,7 +454,7 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr, return UUID(); ObjectFile *exe_objfile = memory_module_sp->GetObjectFile(); - if (exe_objfile == NULL) { + if (exe_objfile == nullptr) { if (log) log->Printf("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress " "found a binary at 0x%" PRIx64 @@ -541,7 +541,7 @@ void DynamicLoaderDarwinKernel::Clear(bool clear_process) { m_process->ClearBreakpointSiteByID(m_break_id); if (clear_process) - m_process = NULL; + m_process = nullptr; m_kernel.Clear(); m_known_kexts.clear(); m_kext_summary_header_ptr_addr.Clear(); @@ -638,7 +638,7 @@ UUID DynamicLoaderDarwinKernel::KextImageInfo::GetUUID() const { bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule( Process *process) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (m_memory_module_sp.get() != NULL) + if (m_memory_module_sp.get() != nullptr) return true; if (m_load_address == LLDB_INVALID_ADDRESS) return false; @@ -658,7 +658,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule( ModuleSP memory_module_sp = process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read); - if (memory_module_sp.get() == NULL) + if (memory_module_sp.get() == nullptr) return false; bool is_kernel = false; @@ -806,9 +806,9 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule( FileSpec kext_filespec(m_name.c_str()); FileSpecList search_paths = target.GetExecutableSearchPaths(); kext_bundle_module_spec.GetFileSpec() = kext_filespec; - platform_sp->GetSharedModule( - kext_bundle_module_spec, process, m_module_sp, - &search_paths, NULL, NULL); + platform_sp->GetSharedModule(kext_bundle_module_spec, process, + m_module_sp, &search_paths, nullptr, + nullptr); } } @@ -1378,7 +1378,7 @@ uint32_t DynamicLoaderDarwinKernel::ReadKextSummaries( lldb::offset_t offset = kext_summary_offset; const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME); - if (name_data == NULL) + if (name_data == nullptr) break; image_infos[i].SetName((const char *)name_data); UUID uuid = UUID::fromOptionalData(extractor.GetData(&offset, 16), 16); @@ -1426,7 +1426,7 @@ void DynamicLoaderDarwinKernel::KextImageInfo::PutToLog(Log *log) const { // Dump the _dyld_all_image_infos members and all current image infos that we // have parsed to the file handle provided. void DynamicLoaderDarwinKernel::PutToLog(Log *log) const { - if (log == NULL) + if (log == nullptr) return; std::lock_guard guard(m_mutex); @@ -1464,7 +1464,7 @@ void DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded() { module_spec_list.Append(m_kernel.GetModule()->GetFileSpec()); Breakpoint *bp = m_process->GetTarget() - .CreateBreakpoint(&module_spec_list, NULL, + .CreateBreakpoint(&module_spec_list, nullptr, "OSKextLoadedKextSummariesUpdated", eFunctionNameTypeFull, eLanguageTypeUnknown, 0, skip_prologue, internal_bp, hardware) diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 0fb05e99a072e..23c8416f49860 100644 --- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -104,7 +104,7 @@ DynamicLoader *DynamicLoaderHexagonDYLD::CreateInstance(Process *process, if (create) return new DynamicLoaderHexagonDYLD(process); - return NULL; + return nullptr; } DynamicLoaderHexagonDYLD::DynamicLoaderHexagonDYLD(Process *process) @@ -420,7 +420,7 @@ DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread &thread, const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); Symbol *sym = context.symbol; - if (sym == NULL || !sym->IsTrampoline()) + if (sym == nullptr || !sym->IsTrampoline()) return thread_plan_sp; const ConstString sym_name = sym->GetMangled().GetName( diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index 7475b1a87aad5..339aeaec50f78 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -84,7 +84,7 @@ void DynamicLoaderDarwin::DidLaunch() { void DynamicLoaderDarwin::Clear(bool clear_process) { std::lock_guard guard(m_mutex); if (clear_process) - m_process = NULL; + m_process = nullptr; m_dyld_image_infos.clear(); m_dyld_image_infos_stop_id = UINT32_MAX; m_dyld.Clear(false); @@ -115,7 +115,7 @@ ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo( // We'll call Target::ModulesDidLoad after all the modules have been // added to the target, don't let it be called for every one. module_sp = target.GetOrCreateModule(module_spec, false /* notify */); - if (!module_sp || module_sp->GetObjectFile() == NULL) + if (!module_sp || module_sp->GetObjectFile() == nullptr) module_sp = m_process->ReadModuleFromMemory(image_info.file_spec, image_info.address); @@ -533,8 +533,8 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos( if (exe_idx != UINT32_MAX) { const bool can_create = true; - ModuleSP exe_module_sp( - FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, NULL)); + ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx], + can_create, nullptr)); if (exe_module_sp) { if (log) log->Printf("Found executable module: %s", @@ -549,8 +549,8 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos( if (dyld_idx != UINT32_MAX) { const bool can_create = true; - ModuleSP dyld_sp = - FindTargetModuleForImageInfo(image_infos[dyld_idx], can_create, NULL); + ModuleSP dyld_sp = FindTargetModuleForImageInfo(image_infos[dyld_idx], + can_create, nullptr); if (dyld_sp.get()) { if (log) log->Printf("Found dyld module: %s", @@ -567,7 +567,7 @@ void DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo( if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) { const bool can_create = true; ModuleSP dyld_sp = - FindTargetModuleForImageInfo(image_info, can_create, NULL); + FindTargetModuleForImageInfo(image_info, can_create, nullptr); if (dyld_sp.get()) { Target &target = m_process->GetTarget(); target.GetImages().AppendIfNeeded(dyld_sp); @@ -605,7 +605,7 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos( m_dyld_image_infos.push_back(image_infos[idx]); ModuleSP image_module_sp( - FindTargetModuleForImageInfo(image_infos[idx], true, NULL)); + FindTargetModuleForImageInfo(image_infos[idx], true, nullptr)); if (image_module_sp) { ObjectFile *objfile = image_module_sp->GetObjectFile(); @@ -628,7 +628,7 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos( commpage_image_module_sp = target.GetOrCreateModule(module_spec, true /* notify */); if (!commpage_image_module_sp || - commpage_image_module_sp->GetObjectFile() == NULL) { + commpage_image_module_sp->GetObjectFile() == nullptr) { commpage_image_module_sp = m_process->ReadModuleFromMemory( image_infos[idx].file_spec, image_infos[idx].address); // Always load a memory image right away in the target in case @@ -686,15 +686,16 @@ bool DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo(SymbolContext &sym_ctx) { if (sym_ctx.symbol) { module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); } - if (module_sp.get() == NULL && sym_ctx.function) { + if (module_sp.get() == nullptr && sym_ctx.function) { module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); } - if (module_sp.get() == NULL) + if (module_sp.get() == nullptr) return false; ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); - return objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary(module_sp); + return objc_runtime != nullptr && + objc_runtime->IsModuleObjCLibrary(module_sp); } // Dump a Segment to the file handle provided. @@ -719,7 +720,7 @@ DynamicLoaderDarwin::ImageInfo::FindSegment(ConstString name) const { if (segments[i].name == name) return &segments[i]; } - return NULL; + return nullptr; } // Dump an image info structure to the file handle provided. @@ -791,7 +792,7 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); TargetSP target_sp(thread.CalculateTarget()); - if (current_symbol != NULL) { + if (current_symbol != nullptr) { std::vector
addresses; if (current_symbol->IsTrampoline()) { diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp index 29e4ac0654ab0..6bc65ecef35dd 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp @@ -68,7 +68,7 @@ DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process, if (create) return new DynamicLoaderMacOS(process); - return NULL; + return nullptr; } // Constructor @@ -334,7 +334,7 @@ void DynamicLoaderMacOS::AddBinaries( // Dump the _dyld_all_image_infos members and all current image infos that we // have parsed to the file handle provided. void DynamicLoaderMacOS::PutToLog(Log *log) const { - if (log == NULL) + if (log == nullptr) return; } diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index 9c0125a6db045..7d00380bfcd45 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -88,7 +88,7 @@ DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process, if (create) return new DynamicLoaderMacOSXDYLD(process); - return NULL; + return nullptr; } // Constructor @@ -608,7 +608,7 @@ bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress( // We'll remove them all at one go later on. ModuleSP unload_image_module_sp( - FindTargetModuleForImageInfo(image_infos[idx], false, NULL)); + FindTargetModuleForImageInfo(image_infos[idx], false, nullptr)); if (unload_image_module_sp.get()) { // When we unload, be sure to use the image info from the old list, // since that has sections correctly filled in. @@ -794,7 +794,7 @@ bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr, if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header) / sizeof(uint32_t)) - 1)) { - if (load_command_data == NULL) + if (load_command_data == nullptr) return true; // We were able to read the mach_header and weren't asked // to read the load command bytes @@ -922,7 +922,7 @@ void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands( &data)) continue; - ParseLoadCommands(data, image_infos[i], NULL); + ParseLoadCommands(data, image_infos[i], nullptr); if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) exe_idx = i; @@ -933,8 +933,8 @@ void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands( if (exe_idx < image_infos.size()) { const bool can_create = true; - ModuleSP exe_module_sp( - FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, NULL)); + ModuleSP exe_module_sp(FindTargetModuleForImageInfo(image_infos[exe_idx], + can_create, nullptr)); if (exe_module_sp) { UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]); @@ -969,7 +969,7 @@ void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands( // Dump the _dyld_all_image_infos members and all current image infos that we // have parsed to the file handle provided. void DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const { - if (log == NULL) + if (log == nullptr) return; std::lock_guard guard(m_mutex); diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 31ab9faca705a..587b2d36accf2 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -68,7 +68,7 @@ DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, if (create) return new DynamicLoaderPOSIXDYLD(process); - return NULL; + return nullptr; } DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) @@ -463,7 +463,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); Symbol *sym = context.symbol; - if (sym == NULL || !sym->IsTrampoline()) + if (sym == nullptr || !sym->IsTrampoline()) return thread_plan_sp; ConstString sym_name = sym->GetName(); @@ -638,7 +638,7 @@ addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { if (m_entry_point != LLDB_INVALID_ADDRESS) return m_entry_point; - if (m_auxv == NULL) + if (m_auxv == nullptr) return LLDB_INVALID_ADDRESS; AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_ENTRY); diff --git a/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp index 88ca2e2de01c9..6bc951c4d35b2 100644 --- a/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp +++ b/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp @@ -43,7 +43,7 @@ DynamicLoader *DynamicLoaderStatic::CreateInstance(Process *process, if (create) return new DynamicLoaderStatic(process); - return NULL; + return nullptr; } // Constructor diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp index 3fecb0c7da929..369f88327dd9d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -85,7 +85,7 @@ void ASTDumper::ToLog(Log *log, const char *prefix) { memcpy(str, m_dump.c_str(), len); - char *end = NULL; + char *end = nullptr; end = strchr(str, '\n'); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 71e130708976e..5dc39e8dac4d0 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -34,8 +34,9 @@ using namespace lldb_private; ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, bool top_level, Target &target) - : m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL), - m_target(target), m_sema(NULL), m_top_level(top_level) { + : m_ast_context(nullptr), m_passthrough(passthrough), + m_passthrough_sema(nullptr), m_target(target), m_sema(nullptr), + m_top_level(top_level) { if (!m_passthrough) return; @@ -311,7 +312,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); } - clang::VarDecl *result_decl = NULL; + clang::VarDecl *result_decl = nullptr; if (is_lvalue) { IdentifierInfo *result_ptr_id; @@ -329,14 +330,14 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, QualType ptr_qual_type; - if (expr_qual_type->getAs() != NULL) + if (expr_qual_type->getAs() != nullptr) ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); else ptr_qual_type = Ctx.getPointerType(expr_qual_type); result_decl = VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), - result_ptr_id, ptr_qual_type, NULL, SC_Static); + result_ptr_id, ptr_qual_type, nullptr, SC_Static); if (!result_decl) return false; @@ -350,8 +351,9 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, } else { IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); - result_decl = VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), - &result_id, expr_qual_type, NULL, SC_Static); + result_decl = + VarDecl::Create(Ctx, DC, SourceLocation(), SourceLocation(), &result_id, + expr_qual_type, nullptr, SC_Static); if (!result_decl) return false; @@ -507,7 +509,7 @@ void ASTResultSynthesizer::InitializeSema(Sema &S) { } void ASTResultSynthesizer::ForgetSema() { - m_sema = NULL; + m_sema = nullptr; if (m_passthrough_sema) m_passthrough_sema->ForgetSema(); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp index 1d8e6931cb9ad..190eacaa2b62b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -29,9 +29,9 @@ using namespace lldb_private; ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, const char *struct_name, ClangFunctionCaller &function) - : m_ast_context(NULL), m_passthrough(passthrough), m_passthrough_sema(NULL), - m_sema(NULL), m_action(NULL), m_function(function), - m_struct_name(struct_name) { + : m_ast_context(nullptr), m_passthrough(passthrough), + m_passthrough_sema(nullptr), m_sema(nullptr), m_action(nullptr), + m_function(function), m_struct_name(struct_name) { if (!m_passthrough) return; @@ -57,7 +57,7 @@ void ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) { if (!body_compound_stmt) return; // do we have to handle this? - RecordDecl *struct_decl = NULL; + RecordDecl *struct_decl = nullptr; StringRef desired_name(m_struct_name); @@ -177,8 +177,8 @@ void ASTStructExtractor::InitializeSema(Sema &S) { } void ASTStructExtractor::ForgetSema() { - m_sema = NULL; - m_action = NULL; + m_sema = nullptr; + m_action = nullptr; if (m_passthrough_sema) m_passthrough_sema->ForgetSema(); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 92191793d19e9..632594f1c460a 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -51,7 +51,7 @@ class ScopedLexicalDeclEraser { ClangASTSource::ClangASTSource(const lldb::TargetSP &target) : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), - m_ast_context(NULL), m_active_lexical_decls(), m_active_lookups() { + m_ast_context(nullptr), m_active_lexical_decls(), m_active_lookups() { if (!target->GetUseModernTypeLookup()) { m_ast_importer_sp = m_target->GetClangASTImporter(); } @@ -441,8 +441,8 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { return; } - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; + Decl *original_decl = nullptr; + ASTContext *original_ctx = nullptr; if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx)) { @@ -475,12 +475,12 @@ clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( lldb::ProcessSP process(m_target->GetProcessSP()); if (!process) - return NULL; + return nullptr; ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); if (!language_runtime) - return NULL; + return nullptr; ConstString class_name(interface_decl->getNameAsString().c_str()); @@ -488,7 +488,7 @@ clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( language_runtime->LookupInCompleteClassCache(class_name)); if (!complete_type_sp) - return NULL; + return nullptr; TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType()); @@ -496,7 +496,7 @@ clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( complete_type.GetOpaqueQualType(); if (!complete_opaque_type) - return NULL; + return nullptr; const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); @@ -504,7 +504,7 @@ clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( dyn_cast(complete_clang_type); if (!complete_interface_type) - return NULL; + return nullptr; ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); @@ -569,8 +569,8 @@ void ClangASTSource::FindExternalLexicalDecls( current_id, static_cast(m_ast_context)); } - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; + Decl *original_decl = nullptr; + ASTContext *original_ctx = nullptr; if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx)) @@ -993,9 +993,9 @@ void ClangASTSource::FindExternalVisibleDecls( template class TaggedASTDecl { public: - TaggedASTDecl() : decl(NULL) {} + TaggedASTDecl() : decl(nullptr) {} TaggedASTDecl(D *_decl) : decl(_decl) {} - bool IsValid() const { return (decl != NULL); } + bool IsValid() const { return (decl != nullptr); } bool IsInvalid() const { return !IsValid(); } D *operator->() const { return decl; } D *decl; @@ -1028,7 +1028,7 @@ template class DeclFromUser : public TaggedASTDecl { template DeclFromUser DeclFromParser::GetOrigin(ClangASTSource &source) { DeclFromUser<> origin_decl; - source.ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + source.ResolveDeclOrigin(this->decl, &origin_decl.decl, nullptr); if (origin_decl.IsInvalid()) return DeclFromUser(); return DeclFromUser(dyn_cast(origin_decl.decl)); @@ -1158,8 +1158,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { return; do { - Decl *original_decl = NULL; - ASTContext *original_ctx = NULL; + Decl *original_decl = nullptr; + ASTContext *original_ctx = nullptr; m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx); @@ -2063,12 +2063,12 @@ clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { assert(type && "Type for variable must be valid!"); if (!type.IsValid()) - return NULL; + return nullptr; ClangASTContext *lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); if (!lldb_ast) - return NULL; + return nullptr; IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); @@ -2076,7 +2076,7 @@ clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { clang::NamedDecl *Decl = VarDecl::Create( *ast, const_cast(m_decl_context), SourceLocation(), - SourceLocation(), ii, ClangUtil::GetQualType(type), 0, SC_Static); + SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static); m_decls.push_back(Decl); return Decl; @@ -2087,15 +2087,15 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, assert(type && "Type for variable must be valid!"); if (!type.IsValid()) - return NULL; + return nullptr; if (m_function_types.count(type)) - return NULL; + return nullptr; ClangASTContext *lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); if (!lldb_ast) - return NULL; + return nullptr; m_function_types.insert(type); @@ -2124,7 +2124,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, clang::FunctionDecl *func_decl = FunctionDecl::Create( *ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type, - NULL, SC_Extern, isInlineSpecified, hasWrittenPrototype, + nullptr, SC_Extern, isInlineSpecified, hasWrittenPrototype, isConstexprSpecified); // We have to do more than just synthesize the FunctionDecl. We have to @@ -2143,9 +2143,10 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) { QualType arg_qual_type(func_proto_type->getParamType(ArgIndex)); - parm_var_decls.push_back(ParmVarDecl::Create( - *ast, const_cast(context), SourceLocation(), - SourceLocation(), NULL, arg_qual_type, NULL, SC_Static, NULL)); + parm_var_decls.push_back( + ParmVarDecl::Create(*ast, const_cast(context), + SourceLocation(), SourceLocation(), nullptr, + arg_qual_type, nullptr, SC_Static, nullptr)); } func_decl->setParams(ArrayRef(parm_var_decls)); @@ -2166,7 +2167,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, ClangASTContext::IsOperator(decl_name.getAsString().c_str(), op_kind)) { if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount( false, op_kind, func_proto_type->getNumParams())) - return NULL; + return nullptr; } m_decls.push_back(func_decl); @@ -2214,7 +2215,7 @@ NameSearchContext::AddTypeDecl(const CompilerType &clang_type) { return (NamedDecl *)interface_decl; } } - return NULL; + return nullptr; } void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 624c86a51740d..7a8bacf48a8fd 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -45,15 +45,15 @@ class ClangASTSource : public ClangExternalASTSourceCommon, ~ClangASTSource() override; /// Interface stubs. - clang::Decl *GetExternalDecl(uint32_t) override { return NULL; } - clang::Stmt *GetExternalDeclStmt(uint64_t) override { return NULL; } + clang::Decl *GetExternalDecl(uint32_t) override { return nullptr; } + clang::Stmt *GetExternalDeclStmt(uint64_t) override { return nullptr; } clang::Selector GetExternalSelector(uint32_t) override { return clang::Selector(); } uint32_t GetNumExternalSelectors() override { return 0; } clang::CXXBaseSpecifier * GetExternalCXXBaseSpecifiers(uint64_t Offset) override { - return NULL; + return nullptr; } void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 83cbe517643a1..496d5b40e3e79 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -367,7 +367,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; Target *target = exe_ctx.GetTargetPtr(); - if (target == NULL) + if (target == nullptr) return false; ClangASTContext *context(target->GetScratchClangASTContext()); @@ -951,7 +951,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( // Clang is looking for the type of "this" - if (frame == NULL) + if (frame == nullptr) return; // Find the block that defines the function represented by "sym_ctx" @@ -1277,7 +1277,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } } if (target) { - var = FindGlobalVariable(*target, module_sp, name, &namespace_decl, NULL); + var = FindGlobalVariable(*target, module_sp, name, &namespace_decl, + nullptr); if (var) { valobj = ValueObjectVariable::Create(target, var); @@ -1434,8 +1435,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } if (sc_list.GetSize()) { - Symbol *extern_symbol = NULL; - Symbol *non_extern_symbol = NULL; + Symbol *extern_symbol = nullptr; + Symbol *non_extern_symbol = nullptr; for (uint32_t index = 0, num_indices = sc_list.GetSize(); index < num_indices; ++index) { @@ -1452,13 +1453,13 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) continue; - AddOneFunction(context, sym_ctx.function, NULL, current_id); + AddOneFunction(context, sym_ctx.function, nullptr, current_id); context.m_found.function_with_type_info = true; context.m_found.function = true; } else if (sym_ctx.symbol) { if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) { sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); - if (sym_ctx.symbol == NULL) + if (sym_ctx.symbol == nullptr) continue; } @@ -1484,10 +1485,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (!context.m_found.function_with_type_info) { if (extern_symbol) { - AddOneFunction(context, NULL, extern_symbol, current_id); + AddOneFunction(context, nullptr, extern_symbol, current_id); context.m_found.function = true; } else if (non_extern_symbol) { - AddOneFunction(context, NULL, non_extern_symbol, current_id); + AddOneFunction(context, nullptr, non_extern_symbol, current_id); context.m_found.function = true; } } @@ -1723,7 +1724,7 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, bool is_reference = pt.IsReferenceType(); - NamedDecl *var_decl = NULL; + NamedDecl *var_decl = nullptr; if (is_reference) var_decl = context.AddVarDecl(pt); else @@ -1740,7 +1741,7 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, entity->GetParserVars(GetParserID()); parser_vars->m_parser_type = pt; parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; + parser_vars->m_llvm_value = nullptr; parser_vars->m_lldb_value = var_location; parser_vars->m_lldb_var = var; @@ -1783,7 +1784,7 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, ->GetParserVars(GetParserID()); parser_vars->m_parser_type = parser_type; parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; + parser_vars->m_llvm_value = nullptr; parser_vars->m_lldb_value.Clear(); if (log) { @@ -1802,7 +1803,7 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - if (target == NULL) + if (target == nullptr) return; ASTContext *scratch_ast_context = @@ -1841,7 +1842,7 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, parser_vars->m_parser_type = parser_type; parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; + parser_vars->m_llvm_value = nullptr; parser_vars->m_lldb_sym = &symbol; if (log) { @@ -1889,7 +1890,7 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); - lldb::opaque_compiler_type_t copied_type = 0; + lldb::opaque_compiler_type_t copied_type = nullptr; if (m_ast_importer_sp) { copied_type = m_ast_importer_sp->CopyType( scratch_ast_context->getASTContext(), &var_decl->getASTContext(), @@ -1962,7 +1963,7 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context, entity->GetParserVars(GetParserID()); parser_vars->m_parser_type = parser_clang_type; parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = NULL; + parser_vars->m_llvm_value = nullptr; parser_vars->m_lldb_value.Clear(); entity->m_flags |= ClangExpressionVariable::EVBareRegister; @@ -1981,7 +1982,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - NamedDecl *function_decl = NULL; + NamedDecl *function_decl = nullptr; Address fun_address; CompilerType function_clang_type; @@ -2141,7 +2142,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, } parser_vars->m_named_decl = function_decl; - parser_vars->m_llvm_value = NULL; + parser_vars->m_llvm_value = nullptr; if (log) { std::string function_str = @@ -2194,7 +2195,7 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, CXXMethodDecl *method_decl = ClangASTContext::GetASTContext(m_ast_context) ->AddMethodToCXXRecordType( - copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", NULL, + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr, method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index a7e2ced2c4563..03b73e6be391f 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -242,9 +242,8 @@ class ClangExpressionDeclMap : public ClangASTSource { /// \return /// Valid load address for the symbol lldb::addr_t GetSymbolAddress(Target &target, Process *process, - ConstString name, - lldb::SymbolType symbol_type, - Module *module = NULL); + ConstString name, lldb::SymbolType symbol_type, + Module *module = nullptr); lldb::addr_t GetSymbolAddress(ConstString name, lldb::SymbolType symbol_type); @@ -331,7 +330,7 @@ class ClangExpressionDeclMap : public ClangASTSource { return m_exe_ctx.GetTargetPtr(); else if (m_sym_ctx.target_sp) m_sym_ctx.target_sp.get(); - return NULL; + return nullptr; } ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. @@ -368,7 +367,7 @@ class ClangExpressionDeclMap : public ClangASTSource { struct StructVars { StructVars() : m_struct_alignment(0), m_struct_size(0), m_struct_laid_out(false), - m_result_name(), m_object_pointer_type(NULL, NULL) {} + m_result_name(), m_object_pointer_type(nullptr, nullptr) {} lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes. @@ -421,7 +420,7 @@ class ClangExpressionDeclMap : public ClangASTSource { lldb::VariableSP FindGlobalVariable(Target &target, lldb::ModuleSP &module, ConstString name, CompilerDeclContext *namespace_decl, - TypeFromUser *type = NULL); + TypeFromUser *type = nullptr); /// Get the value of a variable in a given execution context and return the /// associated Types if needed. @@ -449,8 +448,8 @@ class ClangExpressionDeclMap : public ClangASTSource { /// Return true if the value was successfully filled in. bool GetVariableValue(lldb::VariableSP &var, lldb_private::Value &var_location, - TypeFromUser *found_type = NULL, - TypeFromParser *parser_type = NULL); + TypeFromUser *found_type = nullptr, + TypeFromParser *parser_type = nullptr); /// Use the NameSearchContext to generate a Decl for the given LLDB /// Variable, and put it in the Tuple list. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 0659851fa08b4..9fd9fe9a59f69 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -1229,7 +1229,7 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( type_system_helper->DeclMap(); // result can be NULL if (decl_map) { - Stream *error_stream = NULL; + Stream *error_stream = nullptr; Target *target = exe_ctx.GetTargetPtr(); error_stream = target->GetDebugger().GetErrorFile().get(); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index bb5e6e7987030..eb7f74f20a20d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -117,8 +117,8 @@ class ClangExpressionVariable : public ExpressionVariable { class ParserVars { public: ParserVars() - : m_parser_type(), m_named_decl(NULL), m_llvm_value(NULL), - m_lldb_value(), m_lldb_var(), m_lldb_sym(NULL) {} + : m_parser_type(), m_named_decl(nullptr), m_llvm_value(nullptr), + m_lldb_value(), m_lldb_var(), m_lldb_sym(nullptr) {} TypeFromParser m_parser_type; ///< The type of the variable according to the parser @@ -152,7 +152,7 @@ class ClangExpressionVariable : public ExpressionVariable { ParserVarMap::iterator i = m_parser_vars.find(parser_id); if (i == m_parser_vars.end()) - return NULL; + return nullptr; else return &i->second; } @@ -186,7 +186,7 @@ class ClangExpressionVariable : public ExpressionVariable { JITVarMap::iterator i = m_jit_vars.find(parser_id); if (i == m_jit_vars.end()) - return NULL; + return nullptr; else return &i->second; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index bdcead230c5d3..24f6f2eb91b3b 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -72,7 +72,7 @@ class ClangFunctionCaller : public FunctionCaller { /// Return the object that the parser should use when resolving external /// values. May be NULL if everything should be self-contained. - ClangExpressionDeclMap *DeclMap() override { return NULL; } + ClangExpressionDeclMap *DeclMap() override { return nullptr; } /// Return the object that the parser should allow to access ASTs. May be /// NULL if the ASTs do not need to be transformed. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index e77ba86eb100f..912c9ef2e1b82 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -48,7 +48,7 @@ void ClangPersistentVariables::RemovePersistentVariable( return; name++; - if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) + if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1) m_next_persistent_variable_id--; } @@ -72,7 +72,7 @@ ClangPersistentVariables::GetPersistentDecl(ConstString name) { m_persistent_decls.find(name.GetCString()); if (i == m_persistent_decls.end()) - return NULL; + return nullptr; else return i->second; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 9fcf2d49845e3..2dae5b7022f30 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -102,7 +102,7 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { } StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) { + if (frame == nullptr) { if (log) log->Printf(" [CUE::SC] Null stack frame"); return; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 684cffd815e93..5eec224477fcb 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -90,7 +90,7 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ResetDeclMap(exe_ctx, keep_result_in_memory); - if (!DeclMap()->WillParse(exe_ctx, NULL)) { + if (!DeclMap()->WillParse(exe_ctx, nullptr)) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 9c928054cfb5e..f083b92e3d627 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -60,7 +60,7 @@ IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) { static llvm::Value *FindEntryInstruction(llvm::Function *function) { if (function->empty()) - return NULL; + return nullptr; return function->getEntryBlock().getFirstNonPHIOrDbg(); } @@ -71,11 +71,12 @@ IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, lldb_private::Stream &error_stream, const char *func_name) : ModulePass(ID), m_resolve_vars(resolve_vars), m_func_name(func_name), - m_module(NULL), m_decl_map(decl_map), m_CFStringCreateWithBytes(NULL), - m_sel_registerName(NULL), m_objc_getClass(NULL), m_intptr_ty(NULL), - m_error_stream(error_stream), - m_execution_unit(execution_unit), m_result_store(NULL), - m_result_is_pointer(false), m_reloc_placeholder(NULL), + m_module(nullptr), m_decl_map(decl_map), + m_CFStringCreateWithBytes(nullptr), m_sel_registerName(nullptr), + m_objc_getClass(nullptr), m_intptr_ty(nullptr), + m_error_stream(error_stream), m_execution_unit(execution_unit), + m_result_store(nullptr), m_result_is_pointer(false), + m_reloc_placeholder(nullptr), m_entry_instruction_finder(FindEntryInstruction) {} /* Handy utility functions used at several places in the code */ @@ -116,7 +117,7 @@ clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val, module->getNamedMetadata("clang.global.decl.ptrs"); if (!named_metadata) - return NULL; + return nullptr; unsigned num_nodes = named_metadata->getNumOperands(); unsigned node_index; @@ -125,7 +126,7 @@ clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val, llvm::MDNode *metadata_node = dyn_cast(named_metadata->getOperand(node_index)); if (!metadata_node) - return NULL; + return nullptr; if (metadata_node->getNumOperands() != 2) continue; @@ -138,14 +139,14 @@ clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val, mdconst::dyn_extract(metadata_node->getOperand(1)); if (!constant_int) - return NULL; + return nullptr; uintptr_t ptr = constant_int->getZExtValue(); return reinterpret_cast(ptr); } - return NULL; + return nullptr; } clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { @@ -164,7 +165,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); std::string result_name_str; - const char *result_name = NULL; + const char *result_name = nullptr; for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); @@ -342,8 +343,8 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { GlobalVariable *new_result_global = new GlobalVariable( (*m_module), result_global->getType()->getElementType(), - false, /* not constant */ - GlobalValue::ExternalLinkage, NULL, /* no initializer */ + false, /* not constant */ + GlobalValue::ExternalLinkage, nullptr, /* no initializer */ m_result_name.GetCString()); // It's too late in compilation to create a new VarDecl for this, but we @@ -488,7 +489,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)}; } - ConstantDataSequential *string_array = NULL; + ConstantDataSequential *string_array = nullptr; if (cstr) string_array = dyn_cast(cstr->getInitializer()); @@ -733,7 +734,7 @@ bool IRForTarget::RewriteObjCConstStrings() { } if (!cstr_array) - cstr_global = NULL; + cstr_global = nullptr; if (!RewriteObjCConstString(nsstring_global, cstr_global)) { if (log) @@ -1149,8 +1150,8 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { return false; GlobalVariable *persistent_global = new GlobalVariable( - (*m_module), alloc->getType(), false, /* not constant */ - GlobalValue::ExternalLinkage, NULL, /* no initializer */ + (*m_module), alloc->getType(), false, /* not constant */ + GlobalValue::ExternalLinkage, nullptr, /* no initializer */ alloc->getName().str()); // What we're going to do here is make believe this was a regular old @@ -1346,13 +1347,13 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { std::string name(named_decl->getName().str()); clang::ValueDecl *value_decl = dyn_cast(named_decl); - if (value_decl == NULL) + if (value_decl == nullptr) return false; lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType()); - const Type *value_type = NULL; + const Type *value_type = nullptr; if (name[0] == '$') { // The $__lldb_expr_result name indicates the return value has allocated @@ -1630,12 +1631,12 @@ bool IRForTarget::ResolveExternals(Function &llvm_function) { } static bool isGuardVariableRef(Value *V) { - Constant *Old = NULL; + Constant *Old = nullptr; if (!(Old = dyn_cast(V))) return false; - ConstantExpr *CE = NULL; + ConstantExpr *CE = nullptr; if ((CE = dyn_cast(V))) { if (CE->getOpcode() != Instruction::BitCast) @@ -1930,8 +1931,8 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { } for (element_index = 0; element_index < num_elements; ++element_index) { - const clang::NamedDecl *decl = NULL; - Value *value = NULL; + const clang::NamedDecl *decl = nullptr; + Value *value = nullptr; lldb::offset_t offset; lldb_private::ConstString name; @@ -2051,7 +2052,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { std::string s; raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, nullptr); oss.flush(); @@ -2088,7 +2089,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { m_reloc_placeholder = new llvm::GlobalVariable( (*m_module), int8_ty, false /* IsConstant */, GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty), - "reloc_placeholder", NULL /* InsertBefore */, + "reloc_placeholder", nullptr /* InsertBefore */, GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */); //////////////////////////////////////////////////////////// @@ -2110,7 +2111,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { std::string s; raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, nullptr); oss.flush(); @@ -2245,7 +2246,7 @@ bool IRForTarget::runOnModule(Module &llvm_module) { std::string s; raw_string_ostream oss(s); - m_module->print(oss, NULL); + m_module->print(oss, nullptr); oss.flush(); diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 130adbd607143..6323889c2e093 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -749,7 +749,7 @@ EmulateInstructionARM::CreateInstance(const ArchSpec &arch, } } - return NULL; + return nullptr; } bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) { @@ -13213,7 +13213,7 @@ EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode, (g_arm_opcodes[i].variants & arm_isa) != 0) return &g_arm_opcodes[i]; } - return NULL; + return nullptr; } EmulateInstructionARM::ARMOpcode * @@ -13763,7 +13763,7 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode, (g_thumb_opcodes[i].variants & arm_isa) != 0) return &g_thumb_opcodes[i]; } - return NULL; + return nullptr; } bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) { @@ -14311,7 +14311,7 @@ bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result, } bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) { - ARMOpcode *opcode_data = NULL; + ARMOpcode *opcode_data = nullptr; if (m_opcode_mode == eModeThumb) opcode_data = @@ -14400,7 +14400,7 @@ bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch, OptionValueSP value_sp = test_data->GetValueForKey(opcode_key); uint32_t test_opcode; - if ((value_sp.get() == NULL) || + if ((value_sp.get() == nullptr) || (value_sp->GetType() != OptionValue::eTypeUInt64)) { out_stream->Printf("TestEmulation: Error reading opcode from test file.\n"); return false; @@ -14426,7 +14426,7 @@ bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch, EmulationStateARM after_state; value_sp = test_data->GetValueForKey(before_key); - if ((value_sp.get() == NULL) || + if ((value_sp.get() == nullptr) || (value_sp->GetType() != OptionValue::eTypeDictionary)) { out_stream->Printf("TestEmulation: Failed to find 'before' state.\n"); return false; @@ -14439,7 +14439,7 @@ bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch, } value_sp = test_data->GetValueForKey(after_key); - if ((value_sp.get() == NULL) || + if ((value_sp.get() == nullptr) || (value_sp->GetType() != OptionValue::eTypeDictionary)) { out_stream->Printf("TestEmulation: Failed to find 'after' state.\n"); return false; diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 37ec53bba2b3b..11c7677c201a3 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -284,14 +284,14 @@ bool EmulationStateARM::LoadStateFromDictionary( // Load memory, if present. - if (value_sp.get() != NULL) { + if (value_sp.get() != nullptr) { static ConstString address_key("address"); static ConstString data_key("data"); uint64_t start_address = 0; OptionValueDictionary *mem_dict = value_sp->GetAsDictionary(); value_sp = mem_dict->GetValueForKey(address_key); - if (value_sp.get() == NULL) + if (value_sp.get() == nullptr) return false; else start_address = value_sp->GetUInt64Value(); @@ -306,7 +306,7 @@ bool EmulationStateARM::LoadStateFromDictionary( for (uint32_t i = 0; i < num_elts; ++i) { value_sp = mem_array->GetValueAtIndex(i); - if (value_sp.get() == NULL) + if (value_sp.get() == nullptr) return false; uint64_t value = value_sp->GetUInt64Value(); StoreToPseudoAddress(address, value); @@ -315,7 +315,7 @@ bool EmulationStateARM::LoadStateFromDictionary( } value_sp = test_data->GetValueForKey(registers_key); - if (value_sp.get() == NULL) + if (value_sp.get() == nullptr) return false; // Load General Registers @@ -328,7 +328,7 @@ bool EmulationStateARM::LoadStateFromDictionary( sstr.Printf("r%d", i); ConstString reg_name(sstr.GetString()); value_sp = reg_dict->GetValueForKey(reg_name); - if (value_sp.get() == NULL) + if (value_sp.get() == nullptr) return false; uint64_t reg_value = value_sp->GetUInt64Value(); StorePseudoRegisterValue(dwarf_r0 + i, reg_value); @@ -336,7 +336,7 @@ bool EmulationStateARM::LoadStateFromDictionary( static ConstString cpsr_name("cpsr"); value_sp = reg_dict->GetValueForKey(cpsr_name); - if (value_sp.get() == NULL) + if (value_sp.get() == nullptr) return false; StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value()); @@ -346,7 +346,7 @@ bool EmulationStateARM::LoadStateFromDictionary( sstr.Printf("s%d", i); ConstString reg_name(sstr.GetString()); value_sp = reg_dict->GetValueForKey(reg_name); - if (value_sp.get() == NULL) + if (value_sp.get() == nullptr) return false; uint64_t reg_value = value_sp->GetUInt64Value(); StorePseudoRegisterValue(dwarf_s0 + i, reg_value); diff --git a/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index c30d9bc906d2b..d835d62ad2e07 100644 --- a/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -154,7 +154,7 @@ EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, } } - return NULL; + return nullptr; } bool EmulateInstructionARM64::SetTargetTriple(const ArchSpec &arch) { @@ -411,7 +411,7 @@ bool EmulateInstructionARM64::ReadInstruction() { bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) { const uint32_t opcode = m_opcode.GetOpcode32(); Opcode *opcode_data = GetOpcodeForInstruction(opcode); - if (opcode_data == NULL) + if (opcode_data == nullptr) return false; // printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name); diff --git a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index b5a657819af14..cbf3dda7896e4 100644 --- a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -213,7 +213,7 @@ EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch, } } - return NULL; + return nullptr; } bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) { @@ -966,7 +966,7 @@ EmulateInstructionMIPS::GetOpcodeForInstruction(const char *op_name) { return &g_opcodes[i]; } - return NULL; + return nullptr; } uint32_t @@ -1083,7 +1083,7 @@ bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) { */ const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data(); - if (op_name == NULL) + if (op_name == nullptr) return false; /* @@ -1092,7 +1092,7 @@ bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) { */ MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name); - if (opcode_data == NULL) + if (opcode_data == nullptr) return false; uint64_t old_pc = 0, new_pc = 0; @@ -2875,7 +2875,7 @@ bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn, bool success = false, branch_hit = true; int32_t target = 0; RegisterValue reg_value; - const uint8_t *ptr = NULL; + const uint8_t *ptr = nullptr; uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); int32_t offset = insn.getOperand(1).getImm(); diff --git a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 7c1044c499ae7..69f0278d14377 100644 --- a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -200,7 +200,7 @@ EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch, } } - return NULL; + return nullptr; } bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) { @@ -931,7 +931,7 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { return &g_opcodes[i]; } - return NULL; + return nullptr; } bool EmulateInstructionMIPS64::ReadInstruction() { @@ -974,7 +974,7 @@ bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) { */ const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data(); - if (op_name == NULL) + if (op_name == nullptr) return false; /* @@ -983,7 +983,7 @@ bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) { */ MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name); - if (opcode_data == NULL) + if (opcode_data == nullptr) return false; uint64_t old_pc = 0, new_pc = 0; @@ -2186,7 +2186,7 @@ bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn, bool success = false, branch_hit = true; int64_t target = 0; RegisterValue reg_value; - const uint8_t *ptr = NULL; + const uint8_t *ptr = nullptr; uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); int64_t offset = insn.getOperand(1).getImm(); diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp index 60c8ed01ac1f4..c8ac04641e685 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp @@ -287,7 +287,7 @@ void AddressSanitizerRuntime::Activate() { const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( symbol_name, eSymbolTypeCode); - if (symbol == NULL) + if (symbol == nullptr) return; if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp index afdd97e6a74bd..fac20de0eb4bd 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp @@ -900,7 +900,7 @@ void ThreadSanitizerRuntime::Activate() { const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( symbol_name, eSymbolTypeCode); - if (symbol == NULL) + if (symbol == nullptr) return; if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index ca2847f6a8c46..24683e687188e 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -46,7 +46,7 @@ static const char *vtable_demangled_prefix = "vtable for "; bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) { const bool check_cxx = true; const bool check_objc = false; - return in_value.GetCompilerType().IsPossibleDynamicType(NULL, check_cxx, + return in_value.GetCompilerType().IsPossibleDynamicType(nullptr, check_cxx, check_objc); } @@ -69,7 +69,7 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress( target.GetImages().ResolveSymbolContextForAddress( vtable_addr, eSymbolContextSymbol, sc); Symbol *symbol = sc.symbol; - if (symbol != NULL) { + if (symbol != nullptr) { const char *name = symbol->GetMangled() .GetDemangledName(lldb::eLanguageTypeC_plus_plus) @@ -306,7 +306,7 @@ TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType( } bool ItaniumABILanguageRuntime::IsVTableName(const char *name) { - if (name == NULL) + if (name == nullptr) return false; // Can we maybe ask Clang about this? @@ -326,7 +326,7 @@ ItaniumABILanguageRuntime::CreateInstance(Process *process, language == eLanguageTypeC_plus_plus_14) return new ItaniumABILanguageRuntime(process); else - return NULL; + return nullptr; } class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed { @@ -490,7 +490,7 @@ lldb::BreakpointSP ItaniumABILanguageRuntime::CreateExceptionBreakpoint( Target &target = m_process->GetTarget(); FileSpecList filter_modules; BreakpointResolverSP exception_resolver_sp = - CreateExceptionResolver(NULL, catch_bp, throw_bp, for_expressions); + CreateExceptionResolver(nullptr, catch_bp, throw_bp, for_expressions); SearchFilterSP filter_sp(CreateExceptionSearchFilter()); const bool hardware = false; const bool resolve_indirect_functions = false; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 6b51177437c6a..b5cac92213b29 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -173,7 +173,7 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) { m_runtime.GetClassDescriptorFromISA(isa); if (!descriptor) - return NULL; + return nullptr; ConstString name(descriptor->GetClassName()); @@ -203,7 +203,7 @@ class ObjCRuntimeMethodType { ObjCRuntimeMethodType(const char *types) : m_is_valid(false) { const char *cursor = types; enum ParserState { Start = 0, InType, InPos } state = Start; - const char *type = NULL; + const char *type = nullptr; int brace_depth = 0; uint32_t stepsLeft = 256; @@ -261,7 +261,7 @@ class ObjCRuntimeMethodType { m_is_valid = false; return; } - type = NULL; + type = nullptr; } else { ++cursor; } @@ -319,7 +319,7 @@ class ObjCRuntimeMethodType { bool instance, ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) { if (!m_is_valid || m_type_vector.size() < 3) - return NULL; + return nullptr; clang::ASTContext &ast_ctx(interface_decl->getASTContext()); @@ -354,7 +354,7 @@ class ObjCRuntimeMethodType { clang::IdentifierInfo **identifier_infos = selector_components.data(); if (!identifier_infos) { - return NULL; + return nullptr; } clang::Selector sel = ast_ctx.Selectors.getSelector( @@ -367,12 +367,13 @@ class ObjCRuntimeMethodType { for_expression)); if (ret_type.isNull()) - return NULL; + return nullptr; clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create( ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel, - ret_type, NULL, interface_decl, isInstance, isVariadic, isSynthesized, - isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); + ret_type, nullptr, interface_decl, isInstance, isVariadic, + isSynthesized, isImplicitlyDeclared, isDefined, impControl, + HasRelatedResultType); std::vector parm_vars; @@ -383,12 +384,12 @@ class ObjCRuntimeMethodType { ast_ctx, m_type_vector[ai].c_str(), for_expression)); if (arg_type.isNull()) - return NULL; // well, we just wasted a bunch of time. Wish we could - // delete the stuff we'd just made! + return nullptr; // well, we just wasted a bunch of time. Wish we could + // delete the stuff we'd just made! parm_vars.push_back(clang::ParmVarDecl::Create( - ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), NULL, - arg_type, NULL, clang::SC_None, NULL)); + ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), + nullptr, arg_type, nullptr, clang::SC_None, nullptr)); } ret->setMethodParams(ast_ctx, @@ -512,7 +513,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name), ClangUtil::GetQualType(ivar_type), type_source_info, // TypeSourceInfo * - clang::ObjCIvarDecl::Public, 0, is_synthesized); + clang::ObjCIvarDecl::Public, nullptr, is_synthesized); if (ivar_decl) { interface_decl->addDecl(ivar_decl); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 8e7014dcd6118..8a0b5bf392ccb 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -128,9 +128,9 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value, // ret.SetContext(Value::eContextTypeClangType, return_compiler_type); ret.SetCompilerType(return_compiler_type); - if (exe_ctx.GetFramePtr() == NULL) { + if (exe_ctx.GetFramePtr() == nullptr) { Thread *thread = exe_ctx.GetThreadPtr(); - if (thread == NULL) { + if (thread == nullptr) { exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread()); thread = exe_ctx.GetThreadPtr(); } @@ -225,7 +225,7 @@ Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { eSymbolTypeCode, contexts)) && (!modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"), eSymbolTypeCode, contexts))) - return NULL; + return nullptr; contexts.GetContextAtIndex(0, context); @@ -237,7 +237,7 @@ Address *AppleObjCRuntime::GetPrintForDebuggerAddr() { bool AppleObjCRuntime::CouldHaveDynamicValue(ValueObject &in_value) { return in_value.GetCompilerType().IsPossibleDynamicType( - NULL, + nullptr, false, // do not check C++ true); // check ObjC } @@ -327,7 +327,7 @@ bool AppleObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) { // reread it? m_objc_trampoline_handler_up.reset( new AppleObjCTrampolineHandler(m_process->shared_from_this(), module_sp)); - if (m_objc_trampoline_handler_up != NULL) { + if (m_objc_trampoline_handler_up != nullptr) { m_read_objc_library = true; return true; } else diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 116f4d78ea206..31f9c40066ee7 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -75,9 +75,9 @@ AppleObjCRuntimeV1::CreateInstance(Process *process, ObjCRuntimeVersions::eAppleObjC_V1) return new AppleObjCRuntimeV1(process); else - return NULL; + return nullptr; } else - return NULL; + return nullptr; } void AppleObjCRuntimeV1::Initialize() { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 9f2540fd6255d..5d8d068a76c3d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -414,8 +414,9 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, m_encoding_to_type_sp(), m_noclasses_warning_emitted(false), m_CFBoolean_values() { static const ConstString g_gdb_object_getClass("gdb_object_getClass"); - m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType( - g_gdb_object_getClass, eSymbolTypeCode) != NULL); + m_has_object_getClass = + (objc_module_sp->FindFirstSymbolWithNameAndType( + g_gdb_object_getClass, eSymbolTypeCode) != nullptr); RegisterObjCExceptionRecognizer(); } @@ -424,7 +425,7 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type) { // We should never get here with a null process... - assert(m_process != NULL); + assert(m_process != nullptr); // The Runtime is attached to a particular process, you shouldn't pass in a // value from another process. Note, however, the process might be NULL (e.g. @@ -488,9 +489,9 @@ LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process, ObjCRuntimeVersions::eAppleObjC_V2) return new AppleObjCRuntimeV2(process, objc_module_sp); else - return NULL; + return nullptr; } else - return NULL; + return nullptr; } static constexpr OptionDefinition g_objc_classtable_dump_options[] = { @@ -938,7 +939,7 @@ class RemoteNXMapTable { public: RemoteNXMapTable() : m_count(0), m_num_buckets_minus_one(0), - m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(NULL), + m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr), m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS), m_map_pair_size(0), m_invalid_key(0) {} @@ -1273,7 +1274,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( RemoteNXMapTable &hash_table) { Process *process = GetProcess(); - if (process == NULL) + if (process == nullptr) return DescriptorMapUpdateResult::Fail(); uint32_t num_class_infos = 0; @@ -1509,7 +1510,8 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, } else { // Read the 32 bit hash for the class name const uint32_t name_hash = data.GetU32(&offset); - ClassDescriptorSP descriptor_sp(new ClassDescriptorV2(*this, isa, NULL)); + ClassDescriptorSP descriptor_sp( + new ClassDescriptorV2(*this, isa, nullptr)); // The code in g_get_shared_cache_class_info_body sets the value of the hash // to 0 to signal a demangled symbol. We use class_getName() in that code to @@ -1538,7 +1540,7 @@ AppleObjCRuntimeV2::DescriptorMapUpdateResult AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { Process *process = GetProcess(); - if (process == NULL) + if (process == nullptr) return DescriptorMapUpdateResult::Fail(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); @@ -1752,7 +1754,7 @@ bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory( Process *process = GetProcess(); - if (process == NULL) + if (process == nullptr) return false; uint32_t num_map_table_isas = 0; @@ -2037,18 +2039,18 @@ AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error); if (error.Fail()) - return NULL; + return nullptr; auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_magic_value"), objc_module_sp, error); if (error.Fail()) - return NULL; + return nullptr; auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error); if (error.Fail()) - return NULL; + return nullptr; if (log) log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks"); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index 377c8b3c713a5..4589b1f5d5e39 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -470,7 +470,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() { const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(trampoline_name, eSymbolTypeData); - if (trampoline_symbol != NULL) { + if (trampoline_symbol != nullptr) { m_trampoline_header = trampoline_symbol->GetLoadAddress(&target); if (m_trampoline_header == LLDB_INVALID_ADDRESS) return false; @@ -480,7 +480,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() { const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(changed_name, eSymbolTypeCode); - if (changed_symbol != NULL) { + if (changed_symbol != nullptr) { const Address changed_symbol_addr = changed_symbol->GetAddress(); if (!changed_symbol_addr.IsValid()) return false; @@ -541,7 +541,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( Status error; DataExtractor data; error = argument_values.GetValueAtIndex(0)->GetValueAsData(&exe_ctx, data, - 0, NULL); + 0, nullptr); lldb::offset_t offset = 0; lldb::addr_t region_addr = data.GetPointer(&offset); @@ -668,7 +668,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( ConstString msg_forward_name("_objc_msgForward"); ConstString msg_forward_stret_name("_objc_msgForward_stret"); - Target *target = process_sp ? &process_sp->GetTarget() : NULL; + Target *target = process_sp ? &process_sp->GetTarget() : nullptr; const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType(get_impl_name, eSymbolTypeCode); @@ -771,7 +771,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, // First stage is to make the ClangUtility to hold our injected function: if (!m_impl_code) { - if (m_lookup_implementation_function_code != NULL) { + if (m_lookup_implementation_function_code != nullptr) { Status error; m_impl_code.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( m_lookup_implementation_function_code, eLanguageTypeObjC, @@ -886,11 +886,11 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - const ABI *abi = NULL; + const ABI *abi = nullptr; ProcessSP process_sp(thread.CalculateProcess()); if (process_sp) abi = process_sp->GetABI().get(); - if (abi == NULL) + if (abi == nullptr) return ret_plan_sp; TargetSP target_sp(thread.CalculateTarget()); @@ -1037,7 +1037,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, } ObjCLanguageRuntime *objc_runtime = thread.GetProcess()->GetObjCLanguageRuntime(); - assert(objc_runtime != NULL); + assert(objc_runtime != nullptr); impl_addr = objc_runtime->LookupInMethodCache(isa_addr, sel_addr); } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h index f1356afe6df3f..d120d671eeb3e 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h @@ -74,8 +74,9 @@ class AppleObjCTrampolineHandler { class VTableRegion { public: VTableRegion() - : m_valid(false), m_owner(NULL), m_header_addr(LLDB_INVALID_ADDRESS), - m_code_start_addr(0), m_code_end_addr(0), m_next_region(0) {} + : m_valid(false), m_owner(nullptr), + m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0), + m_code_end_addr(0), m_next_region(0) {} VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index 3436464d02486..f3f38d3f9de60 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -36,7 +36,7 @@ AppleThreadPlanStepThroughObjCTrampoline:: eVoteNoOpinion), m_trampoline_handler(trampoline_handler), m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values), - m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(NULL), + m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr), m_stop_others(stop_others) {} // Destructor @@ -172,7 +172,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { ObjCLanguageRuntime *objc_runtime = GetThread().GetProcess()->GetObjCLanguageRuntime(); - assert(objc_runtime != NULL); + assert(objc_runtime != nullptr); objc_runtime->AddToMethodCache(m_isa_addr, m_sel_addr, target_addr); if (log) log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp index 95aeb41e55c92..a2dafdbd52681 100644 --- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -30,7 +30,7 @@ using namespace lldb_private; MemoryHistorySP MemoryHistoryASan::CreateInstance(const ProcessSP &process_sp) { if (!process_sp.get()) - return NULL; + return nullptr; Target &target = process_sp->GetTarget(); diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index c364dd0757820..ddd7ba7ce823d 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -121,7 +121,7 @@ ObjectContainerBSDArchive::Object::Extract(const DataExtractor &data, if (ar_name_len > 0) { const void *ar_name_ptr = data.GetData(&offset, ar_name_len); // Make sure there was enough data for the string value and bail if not - if (ar_name_ptr == NULL) + if (ar_name_ptr == nullptr) return LLDB_INVALID_OFFSET; str.assign((const char *)ar_name_ptr, ar_name_len); ar_name.SetCString(str.c_str()); @@ -190,7 +190,7 @@ ObjectContainerBSDArchive::Archive::FindObject( return &m_objects[match->value]; } } - return NULL; + return nullptr; } ObjectContainerBSDArchive::Archive::shared_ptr @@ -351,7 +351,7 @@ ObjectContainer *ObjectContainerBSDArchive::CreateInstance( } } } - return NULL; + return nullptr; } bool ObjectContainerBSDArchive::MagicBytesMatch(const DataExtractor &data) { @@ -378,7 +378,7 @@ void ObjectContainerBSDArchive::SetArchive(Archive::shared_ptr &archive_sp) { ObjectContainerBSDArchive::~ObjectContainerBSDArchive() {} bool ObjectContainerBSDArchive::ParseHeader() { - if (m_archive_sp.get() == NULL) { + if (m_archive_sp.get() == nullptr) { if (m_data.GetByteSize() > 0) { ModuleSP module_sp(GetModule()); if (module_sp) { @@ -391,7 +391,7 @@ bool ObjectContainerBSDArchive::ParseHeader() { m_data.Clear(); } } - return m_archive_sp.get() != NULL; + return m_archive_sp.get() != nullptr; } void ObjectContainerBSDArchive::Dump(Stream *s) const { diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index 84ddd058571e1..fdcf39ed576b1 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -125,7 +125,7 @@ class ObjectContainerBSDArchive : public lldb_private::ObjectContainer { const Object *GetObjectAtIndex(size_t idx) { if (idx < m_objects.size()) return &m_objects[idx]; - return NULL; + return nullptr; } size_t ParseObjects(); diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp index c392addc82b55..839a71cfdc7bc 100644 --- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp @@ -57,7 +57,7 @@ ObjectContainer *ObjectContainerUniversalMachO::CreateInstance( } } } - return NULL; + return nullptr; } bool ObjectContainerUniversalMachO::MagicBytesMatch(const DataExtractor &data) { diff --git a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp index 7f9665af9a3b0..aa9871071b0e0 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp @@ -114,7 +114,7 @@ void ELFHeader::ParseHeaderExtension(lldb_private::DataExtractor &data) { bool ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset) { // Read e_ident. This provides byte order and address size info. - if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL) + if (data.GetU8(offset, &e_ident, EI_NIDENT) == nullptr) return false; const unsigned byte_size = Is32Bit() ? 4 : 8; @@ -122,11 +122,11 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data, data.SetAddressByteSize(byte_size); // Read e_type and e_machine. - if (data.GetU16(offset, &e_type, 2) == NULL) + if (data.GetU16(offset, &e_type, 2) == nullptr) return false; // Read e_version. - if (data.GetU32(offset, &e_version, 1) == NULL) + if (data.GetU32(offset, &e_version, 1) == nullptr) return false; // Read e_entry, e_phoff and e_shoff. @@ -134,11 +134,11 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data, return false; // Read e_flags. - if (data.GetU32(offset, &e_flags, 1) == NULL) + if (data.GetU32(offset, &e_flags, 1) == nullptr) return false; // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx. - if (data.GetU16(offset, &e_ehsize, 6) == NULL) + if (data.GetU16(offset, &e_ehsize, 6) == nullptr) return false; // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the @@ -224,7 +224,7 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data, const unsigned byte_size = data.GetAddressByteSize(); // Read sh_name and sh_type. - if (data.GetU32(offset, &sh_name, 2) == NULL) + if (data.GetU32(offset, &sh_name, 2) == nullptr) return false; // Read sh_flags. @@ -236,7 +236,7 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data, return false; // Read sh_link and sh_info. - if (data.GetU32(offset, &sh_link, 2) == NULL) + if (data.GetU32(offset, &sh_link, 2) == nullptr) return false; // Read sh_addralign and sh_entsize. @@ -322,7 +322,7 @@ bool ELFSymbol::Parse(const lldb_private::DataExtractor &data, const bool parsing_32 = byte_size == 4; // Read st_name. - if (data.GetU32(offset, &st_name, 1) == NULL) + if (data.GetU32(offset, &st_name, 1) == nullptr) return false; if (parsing_32) { @@ -331,23 +331,23 @@ bool ELFSymbol::Parse(const lldb_private::DataExtractor &data, return false; // Read st_info and st_other. - if (data.GetU8(offset, &st_info, 2) == NULL) + if (data.GetU8(offset, &st_info, 2) == nullptr) return false; // Read st_shndx. - if (data.GetU16(offset, &st_shndx, 1) == NULL) + if (data.GetU16(offset, &st_shndx, 1) == nullptr) return false; } else { // Read st_info and st_other. - if (data.GetU8(offset, &st_info, 2) == NULL) + if (data.GetU8(offset, &st_info, 2) == nullptr) return false; // Read st_shndx. - if (data.GetU16(offset, &st_shndx, 1) == NULL) + if (data.GetU16(offset, &st_shndx, 1) == nullptr) return false; // Read st_value and st_size. - if (data.GetU64(offset, &st_value, 2) == NULL) + if (data.GetU64(offset, &st_value, 2) == nullptr) return false; } return true; @@ -365,7 +365,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, const bool parsing_32 = byte_size == 4; // Read p_type; - if (data.GetU32(offset, &p_type, 1) == NULL) + if (data.GetU32(offset, &p_type, 1) == nullptr) return false; if (parsing_32) { @@ -374,7 +374,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, return false; // Read p_flags. - if (data.GetU32(offset, &p_flags, 1) == NULL) + if (data.GetU32(offset, &p_flags, 1) == nullptr) return false; // Read p_align. @@ -382,7 +382,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, return false; } else { // Read p_flags. - if (data.GetU32(offset, &p_flags, 1) == NULL) + if (data.GetU32(offset, &p_flags, 1) == nullptr) return false; // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align. diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 0040599c1b5f6..bc802040bf7fd 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -162,7 +162,7 @@ ELFRelocation::ELFRelocation(unsigned type) { reloc = new ELFRela(); else { assert(false && "unexpected relocation type"); - reloc = static_cast(NULL); + reloc = static_cast(nullptr); } } @@ -243,7 +243,7 @@ static user_id_t SegmentID(size_t PHdrIndex) { return ~PHdrIndex; } bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) { // Read all fields. - if (data.GetU32(offset, &n_namesz, 3) == NULL) + if (data.GetU32(offset, &n_namesz, 3) == nullptr) return false; // The name field is required to be nul-terminated, and n_namesz includes the @@ -262,7 +262,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) { } const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4)); - if (cstr == NULL) { + if (cstr == nullptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); if (log) log->Printf("Failed to parse note name lacking nul terminator"); @@ -396,7 +396,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp, return objfile_up.release(); } - return NULL; + return nullptr; } ObjectFile *ObjectFileELF::CreateMemoryInstance( @@ -415,7 +415,7 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance( } } } - return NULL; + return nullptr; } bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp, @@ -1656,12 +1656,12 @@ size_t ObjectFileELF::ParseSectionHeaders() { const ObjectFileELF::ELFSectionHeaderInfo * ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) { if (!ParseSectionHeaders()) - return NULL; + return nullptr; if (id < m_section_headers.size()) return &m_section_headers[id]; - return NULL; + return nullptr; } lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) { @@ -2376,7 +2376,7 @@ size_t ObjectFileELF::ParseDynamicSymbols() { const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) { if (!ParseDynamicSymbols()) - return NULL; + return nullptr; DynamicSymbolCollIter I = m_dynamic_symbols.begin(); DynamicSymbolCollIter E = m_dynamic_symbols.end(); @@ -2387,7 +2387,7 @@ const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) { return symbol; } - return NULL; + return nullptr; } unsigned ObjectFileELF::PLTRelocationType() { @@ -2604,7 +2604,7 @@ unsigned ObjectFileELF::ApplyRelocations( if (!rel.Parse(rel_data, &offset)) break; - Symbol *symbol = NULL; + Symbol *symbol = nullptr; if (hdr->Is32Bit()) { switch (reloc_type(rel)) { @@ -2723,7 +2723,7 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, Symtab *ObjectFileELF::GetSymtab() { ModuleSP module_sp(GetModule()); if (!module_sp) - return NULL; + return nullptr; // We always want to use the main object file so we (hopefully) only have one // cached copy of our symtab, dynamic sections, etc. @@ -2731,10 +2731,10 @@ Symtab *ObjectFileELF::GetSymtab() { if (module_obj_file && module_obj_file != this) return module_obj_file->GetSymtab(); - if (m_symtab_up == NULL) { + if (m_symtab_up == nullptr) { SectionList *section_list = module_sp->GetSectionList(); if (!section_list) - return NULL; + return nullptr; uint64_t symbol_id = 0; std::lock_guard guard(module_sp->GetMutex()); @@ -2934,10 +2934,10 @@ void ObjectFileELF::Dump(Stream *s) { s->EOL(); SectionList *section_list = GetSectionList(); if (section_list) - section_list->Dump(s, NULL, true, UINT32_MAX); + section_list->Dump(s, nullptr, true, UINT32_MAX); Symtab *symtab = GetSymtab(); if (symtab) - symtab->Dump(s, NULL, eSortOrderNone); + symtab->Dump(s, nullptr, eSortOrderNone); s->EOL(); DumpDependentModules(s); s->EOL(); diff --git a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index ad15f961736c1..7d7453c0a87ae 100644 --- a/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -66,7 +66,7 @@ ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp, lldb::offset_t length) { // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from // a file - return NULL; + return nullptr; } ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp, @@ -75,7 +75,7 @@ ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp, lldb::addr_t header_addr) { // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from // memory - return NULL; + return nullptr; } size_t ObjectFileJIT::GetModuleSpecifications( @@ -88,7 +88,7 @@ size_t ObjectFileJIT::GetModuleSpecifications( ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp, const ObjectFileJITDelegateSP &delegate_sp) - : ObjectFile(module_sp, NULL, 0, 0, DataBufferSP(), 0), m_delegate_wp() { + : ObjectFile(module_sp, nullptr, 0, 0, DataBufferSP(), 0), m_delegate_wp() { if (delegate_sp) { m_delegate_wp = delegate_sp; m_data.SetByteOrder(delegate_sp->GetByteOrder()); @@ -115,7 +115,7 @@ Symtab *ObjectFileJIT::GetSymtab() { ModuleSP module_sp(GetModule()); if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); - if (m_symtab_up == NULL) { + if (m_symtab_up == nullptr) { m_symtab_up.reset(new Symtab(this)); std::lock_guard symtab_guard( m_symtab_up->GetMutex()); @@ -159,10 +159,10 @@ void ObjectFileJIT::Dump(Stream *s) { SectionList *sections = GetSectionList(); if (sections) - sections->Dump(s, NULL, true, UINT32_MAX); + sections->Dump(s, nullptr, true, UINT32_MAX); if (m_symtab_up) - m_symtab_up->Dump(s, NULL, eSortOrderNone); + m_symtab_up->Dump(s, nullptr, eSortOrderNone); } } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index b6db8d77a2643..62991dc2095e8 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -173,7 +173,7 @@ class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 { const char *alt_name, size_t reg_byte_size, Stream &data) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) + if (reg_info == nullptr) reg_info = reg_ctx->GetRegisterInfoByName(alt_name); if (reg_info) { lldb_private::RegisterValue reg_value; @@ -202,27 +202,27 @@ class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 { data.PutHex32(GPRRegSet); // Flavor data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "rax", NULL, 8, data); - WriteRegister(reg_ctx, "rbx", NULL, 8, data); - WriteRegister(reg_ctx, "rcx", NULL, 8, data); - WriteRegister(reg_ctx, "rdx", NULL, 8, data); - WriteRegister(reg_ctx, "rdi", NULL, 8, data); - WriteRegister(reg_ctx, "rsi", NULL, 8, data); - WriteRegister(reg_ctx, "rbp", NULL, 8, data); - WriteRegister(reg_ctx, "rsp", NULL, 8, data); - WriteRegister(reg_ctx, "r8", NULL, 8, data); - WriteRegister(reg_ctx, "r9", NULL, 8, data); - WriteRegister(reg_ctx, "r10", NULL, 8, data); - WriteRegister(reg_ctx, "r11", NULL, 8, data); - WriteRegister(reg_ctx, "r12", NULL, 8, data); - WriteRegister(reg_ctx, "r13", NULL, 8, data); - WriteRegister(reg_ctx, "r14", NULL, 8, data); - WriteRegister(reg_ctx, "r15", NULL, 8, data); - WriteRegister(reg_ctx, "rip", NULL, 8, data); - WriteRegister(reg_ctx, "rflags", NULL, 8, data); - WriteRegister(reg_ctx, "cs", NULL, 8, data); - WriteRegister(reg_ctx, "fs", NULL, 8, data); - WriteRegister(reg_ctx, "gs", NULL, 8, data); + WriteRegister(reg_ctx, "rax", nullptr, 8, data); + WriteRegister(reg_ctx, "rbx", nullptr, 8, data); + WriteRegister(reg_ctx, "rcx", nullptr, 8, data); + WriteRegister(reg_ctx, "rdx", nullptr, 8, data); + WriteRegister(reg_ctx, "rdi", nullptr, 8, data); + WriteRegister(reg_ctx, "rsi", nullptr, 8, data); + WriteRegister(reg_ctx, "rbp", nullptr, 8, data); + WriteRegister(reg_ctx, "rsp", nullptr, 8, data); + WriteRegister(reg_ctx, "r8", nullptr, 8, data); + WriteRegister(reg_ctx, "r9", nullptr, 8, data); + WriteRegister(reg_ctx, "r10", nullptr, 8, data); + WriteRegister(reg_ctx, "r11", nullptr, 8, data); + WriteRegister(reg_ctx, "r12", nullptr, 8, data); + WriteRegister(reg_ctx, "r13", nullptr, 8, data); + WriteRegister(reg_ctx, "r14", nullptr, 8, data); + WriteRegister(reg_ctx, "r15", nullptr, 8, data); + WriteRegister(reg_ctx, "rip", nullptr, 8, data); + WriteRegister(reg_ctx, "rflags", nullptr, 8, data); + WriteRegister(reg_ctx, "cs", nullptr, 8, data); + WriteRegister(reg_ctx, "fs", nullptr, 8, data); + WriteRegister(reg_ctx, "gs", nullptr, 8, data); // // Write out the FPU registers // const size_t fpu_byte_size = sizeof(FPU); @@ -311,9 +311,9 @@ class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 { // Write out the EXC registers data.PutHex32(EXCRegSet); data.PutHex32(EXCWordCount); - WriteRegister(reg_ctx, "trapno", NULL, 4, data); - WriteRegister(reg_ctx, "err", NULL, 4, data); - WriteRegister(reg_ctx, "faultvaddr", NULL, 8, data); + WriteRegister(reg_ctx, "trapno", nullptr, 4, data); + WriteRegister(reg_ctx, "err", nullptr, 4, data); + WriteRegister(reg_ctx, "faultvaddr", nullptr, 8, data); return true; } return false; @@ -404,7 +404,7 @@ class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386 { const char *alt_name, size_t reg_byte_size, Stream &data) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) + if (reg_info == nullptr) reg_info = reg_ctx->GetRegisterInfoByName(alt_name); if (reg_info) { lldb_private::RegisterValue reg_value; @@ -433,29 +433,29 @@ class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386 { data.PutHex32(GPRRegSet); // Flavor data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "eax", NULL, 4, data); - WriteRegister(reg_ctx, "ebx", NULL, 4, data); - WriteRegister(reg_ctx, "ecx", NULL, 4, data); - WriteRegister(reg_ctx, "edx", NULL, 4, data); - WriteRegister(reg_ctx, "edi", NULL, 4, data); - WriteRegister(reg_ctx, "esi", NULL, 4, data); - WriteRegister(reg_ctx, "ebp", NULL, 4, data); - WriteRegister(reg_ctx, "esp", NULL, 4, data); - WriteRegister(reg_ctx, "ss", NULL, 4, data); - WriteRegister(reg_ctx, "eflags", NULL, 4, data); - WriteRegister(reg_ctx, "eip", NULL, 4, data); - WriteRegister(reg_ctx, "cs", NULL, 4, data); - WriteRegister(reg_ctx, "ds", NULL, 4, data); - WriteRegister(reg_ctx, "es", NULL, 4, data); - WriteRegister(reg_ctx, "fs", NULL, 4, data); - WriteRegister(reg_ctx, "gs", NULL, 4, data); + WriteRegister(reg_ctx, "eax", nullptr, 4, data); + WriteRegister(reg_ctx, "ebx", nullptr, 4, data); + WriteRegister(reg_ctx, "ecx", nullptr, 4, data); + WriteRegister(reg_ctx, "edx", nullptr, 4, data); + WriteRegister(reg_ctx, "edi", nullptr, 4, data); + WriteRegister(reg_ctx, "esi", nullptr, 4, data); + WriteRegister(reg_ctx, "ebp", nullptr, 4, data); + WriteRegister(reg_ctx, "esp", nullptr, 4, data); + WriteRegister(reg_ctx, "ss", nullptr, 4, data); + WriteRegister(reg_ctx, "eflags", nullptr, 4, data); + WriteRegister(reg_ctx, "eip", nullptr, 4, data); + WriteRegister(reg_ctx, "cs", nullptr, 4, data); + WriteRegister(reg_ctx, "ds", nullptr, 4, data); + WriteRegister(reg_ctx, "es", nullptr, 4, data); + WriteRegister(reg_ctx, "fs", nullptr, 4, data); + WriteRegister(reg_ctx, "gs", nullptr, 4, data); // Write out the EXC registers data.PutHex32(EXCRegSet); data.PutHex32(EXCWordCount); - WriteRegister(reg_ctx, "trapno", NULL, 4, data); - WriteRegister(reg_ctx, "err", NULL, 4, data); - WriteRegister(reg_ctx, "faultvaddr", NULL, 4, data); + WriteRegister(reg_ctx, "trapno", nullptr, 4, data); + WriteRegister(reg_ctx, "err", nullptr, 4, data); + WriteRegister(reg_ctx, "faultvaddr", nullptr, 4, data); return true; } return false; @@ -555,7 +555,7 @@ class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm { const char *alt_name, size_t reg_byte_size, Stream &data) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) + if (reg_info == nullptr) reg_info = reg_ctx->GetRegisterInfoByName(alt_name); if (reg_info) { lldb_private::RegisterValue reg_value; @@ -584,23 +584,23 @@ class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm { data.PutHex32(GPRRegSet); // Flavor data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "r0", NULL, 4, data); - WriteRegister(reg_ctx, "r1", NULL, 4, data); - WriteRegister(reg_ctx, "r2", NULL, 4, data); - WriteRegister(reg_ctx, "r3", NULL, 4, data); - WriteRegister(reg_ctx, "r4", NULL, 4, data); - WriteRegister(reg_ctx, "r5", NULL, 4, data); - WriteRegister(reg_ctx, "r6", NULL, 4, data); - WriteRegister(reg_ctx, "r7", NULL, 4, data); - WriteRegister(reg_ctx, "r8", NULL, 4, data); - WriteRegister(reg_ctx, "r9", NULL, 4, data); - WriteRegister(reg_ctx, "r10", NULL, 4, data); - WriteRegister(reg_ctx, "r11", NULL, 4, data); - WriteRegister(reg_ctx, "r12", NULL, 4, data); - WriteRegister(reg_ctx, "sp", NULL, 4, data); - WriteRegister(reg_ctx, "lr", NULL, 4, data); - WriteRegister(reg_ctx, "pc", NULL, 4, data); - WriteRegister(reg_ctx, "cpsr", NULL, 4, data); + WriteRegister(reg_ctx, "r0", nullptr, 4, data); + WriteRegister(reg_ctx, "r1", nullptr, 4, data); + WriteRegister(reg_ctx, "r2", nullptr, 4, data); + WriteRegister(reg_ctx, "r3", nullptr, 4, data); + WriteRegister(reg_ctx, "r4", nullptr, 4, data); + WriteRegister(reg_ctx, "r5", nullptr, 4, data); + WriteRegister(reg_ctx, "r6", nullptr, 4, data); + WriteRegister(reg_ctx, "r7", nullptr, 4, data); + WriteRegister(reg_ctx, "r8", nullptr, 4, data); + WriteRegister(reg_ctx, "r9", nullptr, 4, data); + WriteRegister(reg_ctx, "r10", nullptr, 4, data); + WriteRegister(reg_ctx, "r11", nullptr, 4, data); + WriteRegister(reg_ctx, "r12", nullptr, 4, data); + WriteRegister(reg_ctx, "sp", nullptr, 4, data); + WriteRegister(reg_ctx, "lr", nullptr, 4, data); + WriteRegister(reg_ctx, "pc", nullptr, 4, data); + WriteRegister(reg_ctx, "cpsr", nullptr, 4, data); // Write out the EXC registers // data.PutHex32 (EXCRegSet); @@ -710,7 +710,7 @@ class RegisterContextDarwin_arm64_Mach : public RegisterContextDarwin_arm64 { const char *alt_name, size_t reg_byte_size, Stream &data) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) + if (reg_info == nullptr) reg_info = reg_ctx->GetRegisterInfoByName(alt_name); if (reg_info) { lldb_private::RegisterValue reg_value; @@ -739,40 +739,40 @@ class RegisterContextDarwin_arm64_Mach : public RegisterContextDarwin_arm64 { data.PutHex32(GPRRegSet); // Flavor data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "x0", NULL, 8, data); - WriteRegister(reg_ctx, "x1", NULL, 8, data); - WriteRegister(reg_ctx, "x2", NULL, 8, data); - WriteRegister(reg_ctx, "x3", NULL, 8, data); - WriteRegister(reg_ctx, "x4", NULL, 8, data); - WriteRegister(reg_ctx, "x5", NULL, 8, data); - WriteRegister(reg_ctx, "x6", NULL, 8, data); - WriteRegister(reg_ctx, "x7", NULL, 8, data); - WriteRegister(reg_ctx, "x8", NULL, 8, data); - WriteRegister(reg_ctx, "x9", NULL, 8, data); - WriteRegister(reg_ctx, "x10", NULL, 8, data); - WriteRegister(reg_ctx, "x11", NULL, 8, data); - WriteRegister(reg_ctx, "x12", NULL, 8, data); - WriteRegister(reg_ctx, "x13", NULL, 8, data); - WriteRegister(reg_ctx, "x14", NULL, 8, data); - WriteRegister(reg_ctx, "x15", NULL, 8, data); - WriteRegister(reg_ctx, "x16", NULL, 8, data); - WriteRegister(reg_ctx, "x17", NULL, 8, data); - WriteRegister(reg_ctx, "x18", NULL, 8, data); - WriteRegister(reg_ctx, "x19", NULL, 8, data); - WriteRegister(reg_ctx, "x20", NULL, 8, data); - WriteRegister(reg_ctx, "x21", NULL, 8, data); - WriteRegister(reg_ctx, "x22", NULL, 8, data); - WriteRegister(reg_ctx, "x23", NULL, 8, data); - WriteRegister(reg_ctx, "x24", NULL, 8, data); - WriteRegister(reg_ctx, "x25", NULL, 8, data); - WriteRegister(reg_ctx, "x26", NULL, 8, data); - WriteRegister(reg_ctx, "x27", NULL, 8, data); - WriteRegister(reg_ctx, "x28", NULL, 8, data); - WriteRegister(reg_ctx, "fp", NULL, 8, data); - WriteRegister(reg_ctx, "lr", NULL, 8, data); - WriteRegister(reg_ctx, "sp", NULL, 8, data); - WriteRegister(reg_ctx, "pc", NULL, 8, data); - WriteRegister(reg_ctx, "cpsr", NULL, 4, data); + WriteRegister(reg_ctx, "x0", nullptr, 8, data); + WriteRegister(reg_ctx, "x1", nullptr, 8, data); + WriteRegister(reg_ctx, "x2", nullptr, 8, data); + WriteRegister(reg_ctx, "x3", nullptr, 8, data); + WriteRegister(reg_ctx, "x4", nullptr, 8, data); + WriteRegister(reg_ctx, "x5", nullptr, 8, data); + WriteRegister(reg_ctx, "x6", nullptr, 8, data); + WriteRegister(reg_ctx, "x7", nullptr, 8, data); + WriteRegister(reg_ctx, "x8", nullptr, 8, data); + WriteRegister(reg_ctx, "x9", nullptr, 8, data); + WriteRegister(reg_ctx, "x10", nullptr, 8, data); + WriteRegister(reg_ctx, "x11", nullptr, 8, data); + WriteRegister(reg_ctx, "x12", nullptr, 8, data); + WriteRegister(reg_ctx, "x13", nullptr, 8, data); + WriteRegister(reg_ctx, "x14", nullptr, 8, data); + WriteRegister(reg_ctx, "x15", nullptr, 8, data); + WriteRegister(reg_ctx, "x16", nullptr, 8, data); + WriteRegister(reg_ctx, "x17", nullptr, 8, data); + WriteRegister(reg_ctx, "x18", nullptr, 8, data); + WriteRegister(reg_ctx, "x19", nullptr, 8, data); + WriteRegister(reg_ctx, "x20", nullptr, 8, data); + WriteRegister(reg_ctx, "x21", nullptr, 8, data); + WriteRegister(reg_ctx, "x22", nullptr, 8, data); + WriteRegister(reg_ctx, "x23", nullptr, 8, data); + WriteRegister(reg_ctx, "x24", nullptr, 8, data); + WriteRegister(reg_ctx, "x25", nullptr, 8, data); + WriteRegister(reg_ctx, "x26", nullptr, 8, data); + WriteRegister(reg_ctx, "x27", nullptr, 8, data); + WriteRegister(reg_ctx, "x28", nullptr, 8, data); + WriteRegister(reg_ctx, "fp", nullptr, 8, data); + WriteRegister(reg_ctx, "lr", nullptr, 8, data); + WriteRegister(reg_ctx, "sp", nullptr, 8, data); + WriteRegister(reg_ctx, "pc", nullptr, 8, data); + WriteRegister(reg_ctx, "cpsr", nullptr, 4, data); // Write out the EXC registers // data.PutHex32 (EXCRegSet); @@ -889,7 +889,7 @@ ObjectFile *ObjectFileMachO::CreateMemoryInstance( if (objfile_up.get() && objfile_up->ParseHeader()) return objfile_up.release(); } - return NULL; + return nullptr; } size_t ObjectFileMachO::GetModuleSpecifications( @@ -1312,7 +1312,7 @@ Symtab *ObjectFileMachO::GetSymtab() { ModuleSP module_sp(GetModule()); if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); - if (m_symtab_up == NULL) { + if (m_symtab_up == nullptr) { m_symtab_up.reset(new Symtab(this)); std::lock_guard symtab_guard( m_symtab_up->GetMutex()); @@ -1332,14 +1332,14 @@ bool ObjectFileMachO::IsStripped() { const lldb::offset_t load_cmd_offset = offset; load_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) + if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr) break; if (lc.cmd == LC_DYSYMTAB) { m_dysymtab.cmd = lc.cmd; m_dysymtab.cmdsize = lc.cmdsize; if (m_data.GetU32(&offset, &m_dysymtab.ilocalsym, (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2) == - NULL) { + nullptr) { // Clear m_dysymtab if we were unable to read all items from the // load command ::memset(&m_dysymtab, 0, sizeof(m_dysymtab)); @@ -1361,7 +1361,7 @@ ObjectFileMachO::EncryptedFileRanges ObjectFileMachO::GetEncryptedFileRanges() { encryption_info_command encryption_cmd; for (uint32_t i = 0; i < m_header.ncmds; ++i) { const lldb::offset_t load_cmd_offset = offset; - if (m_data.GetU32(&offset, &encryption_cmd, 2) == NULL) + if (m_data.GetU32(&offset, &encryption_cmd, 2) == nullptr) break; // LC_ENCRYPTION_INFO and LC_ENCRYPTION_INFO_64 have the same sizes for the @@ -1713,15 +1713,15 @@ void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_, for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects; ++segment_sect_idx) { if (m_data.GetU8(&offset, (uint8_t *)sect64.sectname, - sizeof(sect64.sectname)) == NULL) + sizeof(sect64.sectname)) == nullptr) break; if (m_data.GetU8(&offset, (uint8_t *)sect64.segname, - sizeof(sect64.segname)) == NULL) + sizeof(sect64.segname)) == nullptr) break; sect64.addr = m_data.GetAddress(&offset); sect64.size = m_data.GetAddress(&offset); - if (m_data.GetU32(&offset, §64.offset, num_u32s) == NULL) + if (m_data.GetU32(&offset, §64.offset, num_u32s) == nullptr) break; // Keep a list of mach sections around in case we need to get at data that @@ -1830,7 +1830,7 @@ void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_, bool section_is_encrypted = false; if (!segment_is_encrypted && load_cmd.filesize != 0) section_is_encrypted = context.EncryptedRanges.FindEntryThatContains( - sect64.offset) != NULL; + sect64.offset) != nullptr; section_sp->SetIsEncrypted(segment_is_encrypted || section_is_encrypted); section_sp->SetPermissions(segment_permissions); @@ -1856,7 +1856,7 @@ void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_, if (curr_section_sp.get()) { if (curr_section_sp->GetByteSize() == 0) { - if (next_section_sp.get() != NULL) + if (next_section_sp.get() != nullptr) curr_section_sp->SetByteSize(next_section_sp->GetFileAddress() - curr_section_sp->GetFileAddress()); else @@ -1892,7 +1892,7 @@ void ObjectFileMachO::CreateSections(SectionList &unified_section_list) { struct load_command load_cmd; for (uint32_t i = 0; i < m_header.ncmds; ++i) { const lldb::offset_t load_cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) + if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr) break; if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64) @@ -2021,7 +2021,7 @@ static bool ParseTrieEntries(DataExtractor &data, lldb::offset_t offset, if (terminalSize != 0) { TrieEntryWithOffset e(offset); e.entry.flags = data.GetULEB128(&offset); - const char *import_name = NULL; + const char *import_name = nullptr; if (e.entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) { e.entry.address = 0; e.entry.other = data.GetULEB128(&offset); // dylib ordinal @@ -2129,7 +2129,7 @@ size_t ObjectFileMachO::ParseSymtab() { const lldb::offset_t cmd_offset = offset; // Read in the load command and load command size struct load_command lc; - if (m_data.GetU32(&offset, &lc, 2) == NULL) + if (m_data.GetU32(&offset, &lc, 2) == nullptr) break; // Watch for the symbol table load command switch (lc.cmd) { @@ -2138,7 +2138,7 @@ size_t ObjectFileMachO::ParseSymtab() { symtab_load_command.cmdsize = lc.cmdsize; // Read in the rest of the symtab load command if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4) == - 0) // fill in symoff, nsyms, stroff, strsize fields + nullptr) // fill in symoff, nsyms, stroff, strsize fields return 0; if (symtab_load_command.symoff == 0) { if (log) @@ -2201,7 +2201,7 @@ size_t ObjectFileMachO::ParseSymtab() { function_starts_load_command.cmd = lc.cmd; function_starts_load_command.cmdsize = lc.cmdsize; if (m_data.GetU32(&offset, &function_starts_load_command.dataoff, 2) == - NULL) // fill in symoff, nsyms, stroff, strsize fields + nullptr) // fill in symoff, nsyms, stroff, strsize fields memset(&function_starts_load_command, 0, sizeof(function_starts_load_command)); break; @@ -2215,7 +2215,7 @@ size_t ObjectFileMachO::ParseSymtab() { if (symtab_load_command.cmd) { Symtab *symtab = m_symtab_up.get(); SectionList *section_list = GetSectionList(); - if (section_list == NULL) + if (section_list == nullptr) return 0; const uint32_t addr_byte_size = m_data.GetAddressByteSize(); @@ -2224,12 +2224,12 @@ size_t ObjectFileMachO::ParseSymtab() { const size_t nlist_byte_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64); - DataExtractor nlist_data(NULL, 0, byte_order, addr_byte_size); - DataExtractor strtab_data(NULL, 0, byte_order, addr_byte_size); - DataExtractor function_starts_data(NULL, 0, byte_order, addr_byte_size); - DataExtractor indirect_symbol_index_data(NULL, 0, byte_order, + DataExtractor nlist_data(nullptr, 0, byte_order, addr_byte_size); + DataExtractor strtab_data(nullptr, 0, byte_order, addr_byte_size); + DataExtractor function_starts_data(nullptr, 0, byte_order, addr_byte_size); + DataExtractor indirect_symbol_index_data(nullptr, 0, byte_order, addr_byte_size); - DataExtractor dyld_trie_data(NULL, 0, byte_order, addr_byte_size); + DataExtractor dyld_trie_data(nullptr, 0, byte_order, addr_byte_size); const addr_t nlist_data_byte_size = symtab_load_command.nsyms * nlist_byte_size; @@ -2550,10 +2550,10 @@ size_t ObjectFileMachO::ParseSymtab() { // so we know NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx; uint32_t nlist_idx = 0; - Symbol *symbol_ptr = NULL; + Symbol *symbol_ptr = nullptr; uint32_t sym_idx = 0; - Symbol *sym = NULL; + Symbol *sym = nullptr; size_t num_syms = 0; std::string memory_symbol_name; uint32_t unmapped_local_symbols_found = 0; @@ -3749,7 +3749,7 @@ size_t ObjectFileMachO::ParseSymtab() { // If the sym array was not created while parsing the DSC unmapped // symbols, create it now. - if (sym == NULL) { + if (sym == nullptr) { sym = symtab->Resize(symtab_load_command.nsyms + m_dysymtab.nindirectsyms); num_syms = symtab->GetNumSymbols(); @@ -3780,12 +3780,12 @@ size_t ObjectFileMachO::ParseSymtab() { nlist.n_value = nlist_data.GetAddress_unchecked(&nlist_data_offset); SymbolType type = eSymbolTypeInvalid; - const char *symbol_name = NULL; + const char *symbol_name = nullptr; if (have_strtab_data) { symbol_name = strtab_data.PeekCStr(nlist.n_strx); - if (symbol_name == NULL) { + if (symbol_name == nullptr) { // No symbol should be NULL, even the symbols with no string values // should have an offset zero which points to an empty C-string Host::SystemLog(Host::eSystemLogError, @@ -3796,7 +3796,7 @@ size_t ObjectFileMachO::ParseSymtab() { continue; } if (symbol_name[0] == '\0') - symbol_name = NULL; + symbol_name = nullptr; } else { const addr_t str_addr = strtab_addr + nlist.n_strx; Status str_error; @@ -3804,7 +3804,7 @@ size_t ObjectFileMachO::ParseSymtab() { str_error)) symbol_name = memory_symbol_name.c_str(); } - const char *symbol_name_non_abi_mangled = NULL; + const char *symbol_name_non_abi_mangled = nullptr; SectionSP symbol_section; lldb::addr_t symbol_byte_size = 0; @@ -3957,7 +3957,7 @@ size_t ObjectFileMachO::ParseSymtab() { case N_SO: // source file name type = eSymbolTypeSourceFile; - if (symbol_name == NULL) { + if (symbol_name == nullptr) { add_nlist = false; if (N_SO_index != UINT32_MAX) { // Set the size of the N_SO to the terminating index of this @@ -4426,7 +4426,7 @@ size_t ObjectFileMachO::ParseSymtab() { if (func_start_entry->addr != symbol_lookup_file_addr && func_start_entry->addr != (symbol_lookup_file_addr + 1)) { // Not the right entry, NULL it out... - func_start_entry = NULL; + func_start_entry = nullptr; } } if (func_start_entry) { @@ -4710,7 +4710,7 @@ size_t ObjectFileMachO::ParseSymtab() { NListIndexToSymbolIndexMap::const_iterator index_pos = m_nlist_idx_to_sym_idx.find(stub_sym_id); - Symbol *stub_symbol = NULL; + Symbol *stub_symbol = nullptr; if (index_pos != end_index_pos) { // We have a remapping from the original nlist index to a // current symbol index, so just look this up by index @@ -4742,7 +4742,7 @@ size_t ObjectFileMachO::ParseSymtab() { Mangled stub_symbol_mangled_name(stub_symbol->GetMangled()); if (sym_idx >= num_syms) { sym = symtab->Resize(++num_syms); - stub_symbol = NULL; // this pointer no longer valid + stub_symbol = nullptr; // this pointer no longer valid } sym[sym_idx].SetID(synthetic_sym_id++); sym[sym_idx].GetMangled() = stub_symbol_mangled_name; @@ -4828,10 +4828,10 @@ void ObjectFileMachO::Dump(Stream *s) { SectionList *sections = GetSectionList(); if (sections) - sections->Dump(s, NULL, true, UINT32_MAX); + sections->Dump(s, nullptr, true, UINT32_MAX); if (m_symtab_up) - m_symtab_up->Dump(s, NULL, eSortOrderNone); + m_symtab_up->Dump(s, nullptr, eSortOrderNone); } } @@ -4844,7 +4844,7 @@ UUID ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header, lldb::offset_t offset = lc_offset; for (i = 0; i < header.ncmds; ++i) { const lldb::offset_t cmd_offset = offset; - if (data.GetU32(&offset, &load_cmd, 2) == NULL) + if (data.GetU32(&offset, &load_cmd, 2) == nullptr) break; if (load_cmd.cmd == LC_UUID) { @@ -4982,7 +4982,7 @@ ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header, lldb::offset_t offset = lc_offset; for (uint32_t i = 0; i < header.ncmds; ++i) { const lldb::offset_t cmd_offset = offset; - if (data.GetU32(&offset, &load_cmd, 2) == NULL) + if (data.GetU32(&offset, &load_cmd, 2) == nullptr) break; struct version_min_command version_min; @@ -5015,7 +5015,7 @@ ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header, offset = lc_offset; for (uint32_t i = 0; i < header.ncmds; ++i) { const lldb::offset_t cmd_offset = offset; - if (data.GetU32(&offset, &load_cmd, 2) == NULL) + if (data.GetU32(&offset, &load_cmd, 2) == nullptr) break; do { if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) { @@ -5077,7 +5077,7 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) { uint32_t i; for (i = 0; i < m_header.ncmds; ++i) { const uint32_t cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) + if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr) break; switch (load_cmd.cmd) { @@ -5211,7 +5211,7 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() { for (i = 0; i < m_header.ncmds; ++i) { const lldb::offset_t cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) + if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr) break; switch (load_cmd.cmd) { @@ -5350,7 +5350,7 @@ uint32_t ObjectFileMachO::GetNumThreadContexts() { thread_command thread_cmd; for (uint32_t i = 0; i < m_header.ncmds; ++i) { const uint32_t cmd_offset = offset; - if (m_data.GetU32(&offset, &thread_cmd, 2) == NULL) + if (m_data.GetU32(&offset, &thread_cmd, 2) == nullptr) break; if (thread_cmd.cmd == LC_THREAD) { @@ -5377,8 +5377,8 @@ std::string ObjectFileMachO::GetIdentifierString() { for (uint32_t i = 0; i < m_header.ncmds; ++i) { const uint32_t cmd_offset = offset; load_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; + if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr) + break; if (lc.cmd == LC_NOTE) { char data_owner[17]; @@ -5422,7 +5422,7 @@ std::string ObjectFileMachO::GetIdentifierString() { for (uint32_t i = 0; i < m_header.ncmds; ++i) { const uint32_t cmd_offset = offset; struct ident_command ident_command; - if (m_data.GetU32(&offset, &ident_command, 2) == NULL) + if (m_data.GetU32(&offset, &ident_command, 2) == nullptr) break; if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) { char *buf = (char *) malloc (ident_command.cmdsize); @@ -5451,8 +5451,8 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo (addr_t &address, UUID &uuid) { for (uint32_t i = 0; i < m_header.ncmds; ++i) { const uint32_t cmd_offset = offset; load_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; + if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr) + break; if (lc.cmd == LC_NOTE) { char data_owner[17]; @@ -5649,13 +5649,13 @@ llvm::VersionTuple ObjectFileMachO::GetVersion() { uint32_t i; for (i = 0; i < m_header.ncmds; ++i) { const lldb::offset_t cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) + if (m_data.GetU32(&offset, &load_cmd, 2) == nullptr) break; if (load_cmd.cmd == LC_ID_DYLIB) { if (version_cmd == 0) { version_cmd = load_cmd.cmd; - if (m_data.GetU32(&offset, &load_cmd.dylib, 4) == NULL) + if (m_data.GetU32(&offset, &load_cmd.dylib, 4) == nullptr) break; version = load_cmd.dylib.current_version; } @@ -5795,7 +5795,7 @@ llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() { const lldb::offset_t load_cmd_offset = offset; version_min_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) + if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr) break; if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX || lc.cmd == llvm::MachO::LC_VERSION_MIN_IPHONEOS || @@ -5855,7 +5855,7 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions, const lldb::offset_t load_cmd_offset = offset; version_min_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) + if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr) break; if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX || lc.cmd == llvm::MachO::LC_VERSION_MIN_IPHONEOS || @@ -5886,7 +5886,7 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions, const lldb::offset_t load_cmd_offset = offset; version_min_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) + if (m_data.GetU32(&offset, &lc.cmd, 2) == nullptr) break; if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) { // struct build_version_command { @@ -5932,7 +5932,7 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions, // the sentinel value indicating that this object file // does not have a valid minimum os version #. if (m_sdk_versions.size() > 1) { - if (versions != NULL && num_versions > 0) { + if (versions != nullptr && num_versions > 0) { for (size_t i = 0; i < num_versions; ++i) { if (i < m_sdk_versions.size()) versions[i] = m_sdk_versions[i]; diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 2bd75a4fadf95..fab379037fc05 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -596,7 +596,7 @@ Symtab *ObjectFilePECOFF::GetSymtab() { ModuleSP module_sp(GetModule()); if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); - if (m_symtab_up == NULL) { + if (m_symtab_up == nullptr) { SectionList *sect_list = GetSectionList(); m_symtab_up.reset(new Symtab(this)); std::lock_guard guard(m_symtab_up->GetMutex()); @@ -627,7 +627,7 @@ Symtab *ObjectFilePECOFF::GetSymtab() { for (uint32_t i = 0; i < num_syms; ++i) { coff_symbol_t symbol; const uint32_t symbol_offset = offset; - const char *symbol_name_cstr = NULL; + const char *symbol_name_cstr = nullptr; // If the first 4 bytes of the symbol string are zero, then they // are followed by a 4-byte string table offset. Else these // 8 bytes contain the symbol name @@ -642,7 +642,7 @@ Symtab *ObjectFilePECOFF::GetSymtab() { // bytes offset += sizeof(symbol.name) - 4; // Skip remaining symbol_name_cstr = symtab_data.PeekCStr(symbol_offset); - if (symbol_name_cstr == NULL) + if (symbol_name_cstr == nullptr) break; symbol_name.assign(symbol_name_cstr, sizeof(symbol.name)); } @@ -1006,10 +1006,10 @@ void ObjectFilePECOFF::Dump(Stream *s) { SectionList *sections = GetSectionList(); if (sections) - sections->Dump(s, NULL, true, UINT32_MAX); + sections->Dump(s, nullptr, true, UINT32_MAX); if (m_symtab_up) - m_symtab_up->Dump(s, NULL, eSortOrderNone); + m_symtab_up->Dump(s, nullptr, eSortOrderNone); if (m_dos_header.e_magic) DumpDOSHeader(s, m_dos_header); diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 874ca85fb4374..c1fe0cc8dddaf 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -59,7 +59,7 @@ OperatingSystem *OperatingSystemPython::CreateInstance(Process *process, if (os_up.get() && os_up->IsValid()) return os_up.release(); } - return NULL; + return nullptr; } ConstString OperatingSystemPython::GetPluginNameStatic() { @@ -75,7 +75,7 @@ const char *OperatingSystemPython::GetPluginDescriptionStatic() { OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process, const FileSpec &python_module_path) : OperatingSystem(process), m_thread_list_valobj_sp(), m_register_info_up(), - m_interpreter(NULL), m_python_object_sp() { + m_interpreter(nullptr), m_python_object_sp() { if (!process) return; TargetSP target_sp = process->CalculateTarget(); @@ -115,9 +115,9 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process, OperatingSystemPython::~OperatingSystemPython() {} DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { - if (m_register_info_up == NULL) { + if (m_register_info_up == nullptr) { if (!m_interpreter || !m_python_object_sp) - return NULL; + return nullptr; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); if (log) @@ -128,7 +128,7 @@ DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { StructuredData::DictionarySP dictionary = m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp); if (!dictionary) - return NULL; + return nullptr; m_register_info_up.reset(new DynamicRegisterInfo( *dictionary, m_process->GetTarget().GetArchitecture())); @@ -198,9 +198,9 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list, StructuredData::ObjectSP thread_dict_obj = threads_list->GetItemAtIndex(i); if (auto thread_dict = thread_dict_obj->GetAsDictionary()) { - ThreadSP thread_sp( - CreateThreadFromThreadInfo(*thread_dict, core_thread_list, - old_thread_list, core_used_map, NULL)); + ThreadSP thread_sp(CreateThreadFromThreadInfo( + *thread_dict, core_thread_list, old_thread_list, core_used_map, + nullptr)); if (thread_sp) new_thread_list.AddThread(thread_sp); } diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 7d8f43a697acd..946f0ea3a5cfe 100644 --- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -262,7 +262,7 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, Status &error) { lldb::ProcessSP process_sp; if (IsHost()) { - if (target == NULL) { + if (target == nullptr) { TargetSP new_target_sp; ArchSpec emptyArchSpec; @@ -279,7 +279,7 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, // even when debugging locally we are debugging remotely! Just like the // darwin plugin. process_sp = target->CreateProcess( - attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); + attach_info.GetListenerForProcess(debugger), "gdb-remote", nullptr); if (process_sp) error = process_sp->Attach(attach_info); diff --git a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp index a4d381eafe95b..d0ad2f34d11d8 100644 --- a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -237,7 +237,7 @@ PlatformLinux::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { // Figure out what shell we're planning on using. const char *shell_name = strrchr(shell_string.c_str(), '/'); - if (shell_name == NULL) + if (shell_name == nullptr) shell_name = shell_string.c_str(); else shell_name++; @@ -372,7 +372,7 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // Handle the hijacking of process events. if (listener_sp) { const StateType state = process_sp->WaitForProcessToStop( - llvm::None, NULL, false, listener_sp); + llvm::None, nullptr, false, listener_sp); LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index a4b17a93d7d50..955987121d62b 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -374,7 +374,7 @@ Status PlatformDarwin::GetSharedModule( new_module_spec.GetFileSpec() = bundle_directory; if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) { Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, old_module_sp_ptr, + new_module_spec, process, module_sp, nullptr, old_module_sp_ptr, did_create_ptr)); if (module_sp) @@ -401,7 +401,7 @@ Status PlatformDarwin::GetSharedModule( ModuleSpec new_module_spec(module_spec); new_module_spec.GetFileSpec() = new_file_spec; Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, + new_module_spec, process, module_sp, nullptr, old_module_sp_ptr, did_create_ptr)); if (module_sp) { @@ -1171,7 +1171,7 @@ const char *PlatformDarwin::GetDeveloperDirectory() { std::string command_output; Status error = Host::RunShellCommand("/usr/bin/xcode-select --print-path", - NULL, // current working directory + nullptr, // current working directory &exit_status, &signo, &command_output, std::chrono::seconds(2), // short timeout false); // don't run in a shell @@ -1212,7 +1212,7 @@ const char *PlatformDarwin::GetDeveloperDirectory() { assert(m_developer_directory.empty() == false); if (m_developer_directory[0]) return m_developer_directory.c_str(); - return NULL; + return nullptr; } BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) { @@ -1233,7 +1233,7 @@ BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) { bool internal = true; bool hardware = false; LazyBool skip_prologue = eLazyBoolNo; - bp_sp = target.CreateBreakpoint(&bp_modules, NULL, g_bp_names, + bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names, llvm::array_lengthof(g_bp_names), eFunctionNameTypeFull, eLanguageTypeUnknown, 0, skip_prologue, internal, hardware); @@ -1250,7 +1250,7 @@ PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { std::string shell_string = shell.GetPath(); const char *shell_name = strrchr(shell_string.c_str(), '/'); - if (shell_name == NULL) + if (shell_name == nullptr) shell_name = shell_string.c_str(); else shell_name++; @@ -1341,7 +1341,7 @@ static FileSpec GetXcodeContentsPath() { const char *command = "/usr/bin/xcode-select -p"; lldb_private::Status error = Host::RunShellCommand( command, // shell command to run - NULL, // current working directory + nullptr, // current working directory &status, // Put the exit status of the process in here &signo, // Put the signal that caused the process to exit in here &output, // Get the output from the command and place it in this @@ -1742,7 +1742,7 @@ PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec ModuleSpec new_module_spec(module_spec); new_module_spec.GetFileSpec() = path_to_try; Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, old_module_sp_ptr, + new_module_spec, process, module_sp, nullptr, old_module_sp_ptr, did_create_ptr)); if (module_sp) { diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index 47b7b9f77ebf3..5fbb0f1babd45 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -183,7 +183,7 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) { const char *command = "xcrun -sdk macosx --show-sdk-path"; lldb_private::Status error = RunShellCommand( command, // shell command to run - NULL, // current working directory + nullptr, // current working directory &status, // Put the exit status of the process in here &signo, // Put the signal that caused the process to exit in // here @@ -309,7 +309,7 @@ lldb_private::Status PlatformMacOSX::GetSharedModule( if (module_spec.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h) { ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile == NULL) { + if (objfile == nullptr) { // We didn't find an x86_64h slice, fall back to a x86_64 slice ModuleSpec module_spec_x86_64(module_spec); module_spec_x86_64.GetArchitecture() = ArchSpec("x86_64-apple-macosx"); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index b77a54958b8e8..439ca8fcf0505 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -81,7 +81,7 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable( if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid()) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); + nullptr, nullptr, nullptr); if (exe_module_sp && exe_module_sp->GetObjectFile()) return error; @@ -95,7 +95,7 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable( idx, resolved_module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); + nullptr, nullptr, nullptr); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) @@ -308,12 +308,12 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() { return &m_sdk_directory_infos[i]; } } - return NULL; + return nullptr; } const PlatformRemoteDarwinDevice::SDKDirectoryInfo * PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() { - const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL; + const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = nullptr; if (UpdateSDKDirectoryInfosIfNeeded()) { auto max = std::max_element( m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(), @@ -344,7 +344,7 @@ const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() { assert(m_device_support_directory.empty() == false); if (m_device_support_directory[0]) return m_device_support_directory.c_str(); - return NULL; + return nullptr; } const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() { @@ -354,7 +354,7 @@ const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() if (m_device_support_directory_for_os_version.empty()) { const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info = GetSDKDirectoryForCurrentOSVersion(); - if (sdk_dir_info == NULL) + if (sdk_dir_info == nullptr) sdk_dir_info = GetSDKDirectoryForLatestOSVersion(); if (sdk_dir_info) { char path[PATH_MAX]; @@ -374,7 +374,7 @@ const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() assert(m_device_support_directory_for_os_version.empty() == false); if (m_device_support_directory_for_os_version[0]) return m_device_support_directory_for_os_version.c_str(); - return NULL; + return nullptr; } uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path, @@ -523,7 +523,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( if (GetFileInSDK(platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); + error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { m_last_module_sdk_idx = connected_sdk_idx; error.Clear(); @@ -540,7 +540,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); + error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { error.Clear(); return error; @@ -562,7 +562,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( if (GetFileInSDK(platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); + error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { m_last_module_sdk_idx = current_sdk_idx; error.Clear(); @@ -583,7 +583,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( platform_module_spec.GetFileSpec())) { // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); + error = ResolveExecutable(platform_module_spec, module_sp, nullptr); if (module_sp) { // Remember the index of the last SDK that we found a file in in case // the wrong SDK was selected. @@ -648,7 +648,7 @@ uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() { uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo( const SDKDirectoryInfo *sdk_info) { - if (sdk_info == NULL) { + if (sdk_info == nullptr) { return UINT32_MAX; } diff --git a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index f741f4a05160f..63245d18fc5c3 100644 --- a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -206,7 +206,7 @@ PlatformNetBSD::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { // Figure out what shell we're planning on using. const char *shell_name = strrchr(shell_string.c_str(), '/'); - if (shell_name == NULL) + if (shell_name == nullptr) shell_name = shell_string.c_str(); else shell_name++; @@ -322,7 +322,7 @@ PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // Handle the hijacking of process events. if (listener_sp) { const StateType state = process_sp->WaitForProcessToStop( - llvm::None, NULL, false, listener_sp); + llvm::None, nullptr, false, listener_sp); LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); } diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 4b5a985b6d53a..d10557596ff80 100644 --- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -223,8 +223,8 @@ static uint32_t chown_file(Platform *platform, const char *path, command.Printf(":%d", gid); command.Printf("%s", path); int status; - platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, - std::chrono::seconds(10)); + platform->RunShellCommand(command.GetData(), nullptr, &status, nullptr, + nullptr, std::chrono::seconds(10)); return status; } @@ -248,7 +248,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, StreamString command; command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; - RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, + RunShellCommand(command.GetData(), nullptr, &status, nullptr, nullptr, std::chrono::seconds(10)); if (status != 0) return Status("unable to perform copy"); @@ -279,8 +279,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, if (log) log->Printf("[PutFile] Running command: %s\n", command.GetData()); int retcode; - Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, - std::chrono::minutes(1)); + Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr, + nullptr, std::chrono::minutes(1)); if (retcode == 0) { // Don't chown a local file for a remote system // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) @@ -315,7 +315,7 @@ lldb_private::Status PlatformPOSIX::GetFile( StreamString cp_command; cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; - RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, + RunShellCommand(cp_command.GetData(), nullptr, &status, nullptr, nullptr, std::chrono::seconds(10)); if (status != 0) return Status("unable to perform copy"); @@ -337,8 +337,8 @@ lldb_private::Status PlatformPOSIX::GetFile( if (log) log->Printf("[GetFile] Running command: %s\n", command.GetData()); int retcode; - Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, - std::chrono::minutes(1)); + Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr, + nullptr, std::chrono::minutes(1)); if (retcode == 0) return Status(); // If we are here, rsync has failed - let's try the slow way before @@ -509,11 +509,11 @@ lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info, Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (IsHost()) { - if (target == NULL) { + if (target == nullptr) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( - debugger, "", "", eLoadDependentsNo, NULL, new_target_sp); + debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); target = new_target_sp.get(); if (log) log->Printf("PlatformPOSIX::%s created new target", __FUNCTION__); @@ -537,7 +537,7 @@ lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info, process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), - attach_info.GetProcessPluginName(), NULL); + attach_info.GetProcessPluginName(), nullptr); if (process_sp) { ListenerSP listener_sp = attach_info.GetHijackListener(); diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index dea7ccf04221f..9c52b59e2b06d 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -109,7 +109,8 @@ Status PlatformRemoteGDBServer::ResolveExecutable( if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid()) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - module_search_paths_ptr, NULL, NULL); + module_search_paths_ptr, nullptr, + nullptr); if (exe_module_sp && exe_module_sp->GetObjectFile()) return error; @@ -123,7 +124,8 @@ Status PlatformRemoteGDBServer::ResolveExecutable( idx, resolved_module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - module_search_paths_ptr, NULL, NULL); + module_search_paths_ptr, nullptr, + nullptr); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) @@ -333,7 +335,7 @@ Status PlatformRemoteGDBServer::DisconnectRemote() { const char *PlatformRemoteGDBServer::GetHostname() { m_gdb_client.GetHostname(m_name); if (m_name.empty()) - return NULL; + return nullptr; return m_name.c_str(); } @@ -469,11 +471,11 @@ lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess( error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", GetHostname()); } else { - if (target == NULL) { + if (target == nullptr) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( - debugger, "", "", eLoadDependentsNo, NULL, new_target_sp); + debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); target = new_target_sp.get(); } else error.Clear(); @@ -484,7 +486,7 @@ lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess( // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! process_sp = target->CreateProcess(launch_info.GetListener(), - "gdb-remote", NULL); + "gdb-remote", nullptr); if (process_sp) { error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); @@ -555,11 +557,11 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach( error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'", GetHostname()); } else { - if (target == NULL) { + if (target == nullptr) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( - debugger, "", "", eLoadDependentsNo, NULL, new_target_sp); + debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); target = new_target_sp.get(); } else error.Clear(); @@ -569,8 +571,9 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach( // The darwin always currently uses the GDB remote debugger plug-in // so even when debugging locally we are debugging remotely! - process_sp = target->CreateProcess( - attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); + process_sp = + target->CreateProcess(attach_info.GetListenerForProcess(debugger), + "gdb-remote", nullptr); if (process_sp) { error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); if (error.Success()) { diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index c35cb54bb69ca..029bdf48b12ae 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -29,13 +29,13 @@ static inline int get_cpuid_count(unsigned int __leaf, unsigned int *__eax, unsigned int *__ebx, unsigned int *__ecx, unsigned int *__edx) { - unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0); + unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, nullptr); - if (__max_leaf == 0 || __max_leaf < __leaf) - return 0; + if (__max_leaf == 0 || __max_leaf < __leaf) + return 0; - __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx); - return 1; + __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx); + return 1; } using namespace lldb_private; diff --git a/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp b/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp index 749a765731b6b..a7e8c00f0fe94 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp @@ -117,7 +117,7 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, errno = 0; auto base = - mmap(NULL, (metabufsize + page_size), PROT_WRITE, MAP_SHARED, fd, 0); + mmap(nullptr, (metabufsize + page_size), PROT_WRITE, MAP_SHARED, fd, 0); if (base == MAP_FAILED) { LLDB_LOG(log, "mmap base error {0}", errno); @@ -133,7 +133,7 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, m_mmap_meta->aux_size = bufsize; errno = 0; - auto mmap_aux = mmap(NULL, bufsize, PROT_READ, MAP_SHARED, fd, + auto mmap_aux = mmap(nullptr, bufsize, PROT_READ, MAP_SHARED, fd, static_cast(m_mmap_meta->aux_offset)); if (mmap_aux == MAP_FAILED) { diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp index 3dde2f4394319..aa8449131a689 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -20,7 +20,7 @@ const char *ProcessMessage::PrintKind(Kind kind) { chcar str[8]; sprintf(str, "%d", reason); #else - const char *str = NULL; + const char *str = nullptr; switch (kind) { case eInvalidMessage: diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index f59d0374f634e..1afe4d920599d 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -67,7 +67,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, for (uint32_t i = 0; i < num_sets; ++i) { ConstString set_name; if (sets->GetItemAtIndexAsString(i, set_name) && !set_name.IsEmpty()) { - m_sets.push_back({ set_name.AsCString(), NULL, 0, NULL }); + m_sets.push_back({set_name.AsCString(), nullptr, 0, nullptr}); } else { Clear(); printf("error: register sets must have valid names\n"); @@ -302,7 +302,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, llvm::StringRef format_str; if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) { if (OptionArgParser::ToFormat(format_str.str().c_str(), reg_info.format, - NULL) + nullptr) .Fail()) { Clear(); printf("error: invalid 'format' value in register dictionary\n"); @@ -414,7 +414,7 @@ void DynamicRegisterInfo::AddRegister(RegisterInfo ®_info, const uint32_t reg_num = m_regs.size(); reg_info.name = reg_name.AsCString(); assert(reg_info.name); - reg_info.alt_name = reg_alt_name.AsCString(NULL); + reg_info.alt_name = reg_alt_name.AsCString(nullptr); uint32_t i; if (reg_info.value_regs) { for (i = 0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i) @@ -480,7 +480,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { if (m_value_regs_map.find(i) != m_value_regs_map.end()) m_regs[i].value_regs = m_value_regs_map[i].data(); else - m_regs[i].value_regs = NULL; + m_regs[i].value_regs = nullptr; } // Expand all invalidation dependencies @@ -529,7 +529,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { if (m_invalidate_regs_map.find(i) != m_invalidate_regs_map.end()) m_regs[i].invalidate_regs = m_invalidate_regs_map[i].data(); else - m_regs[i].invalidate_regs = NULL; + m_regs[i].invalidate_regs = nullptr; } // Check if we need to automatically set the generic registers in case they @@ -639,19 +639,19 @@ const RegisterInfo * DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) const { if (i < m_regs.size()) return &m_regs[i]; - return NULL; + return nullptr; } RegisterInfo *DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) { if (i < m_regs.size()) return &m_regs[i]; - return NULL; + return nullptr; } const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const { if (i < m_sets.size()) return &m_sets[i]; - return NULL; + return nullptr; } uint32_t DynamicRegisterInfo::GetRegisterSetIndexByName(ConstString &set_name, @@ -664,7 +664,7 @@ uint32_t DynamicRegisterInfo::GetRegisterSetIndexByName(ConstString &set_name, m_set_names.push_back(set_name); m_set_reg_nums.resize(m_set_reg_nums.size() + 1); - RegisterSet new_set = {set_name.AsCString(), NULL, 0, NULL}; + RegisterSet new_set = {set_name.AsCString(), nullptr, 0, nullptr}; m_sets.push_back(new_set); return m_sets.size() - 1; } @@ -754,5 +754,5 @@ const lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo( return ®_info; } } - return NULL; + return nullptr; } diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp index 23f6077b32c15..f0e39eed0924f 100644 --- a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp @@ -66,7 +66,7 @@ lldb::StackFrameListSP HistoryThread::GetStackFrameList() { // FIXME do not throw away the lock after we acquire it.. std::unique_lock lock(m_framelist_mutex); lock.unlock(); - if (m_framelist.get() == NULL) { + if (m_framelist.get() == nullptr) { m_framelist = std::make_shared(*this, StackFrameListSP(), true); } diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 3bf5d9b52a776..9beaf2fc7ac87 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -38,7 +38,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, unsigned flags, addr_t fd, addr_t offset) { Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == NULL) + if (thread == nullptr) return false; const bool append = true; @@ -126,7 +126,7 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, addr_t length) { Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == NULL) + if (thread == nullptr) return false; const bool append = true; @@ -188,7 +188,7 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func, bool trap_exceptions) { Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); - if (thread == NULL || address == NULL) + if (thread == nullptr || address == nullptr) return false; EvaluateExpressionOptions options; diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index ea950cee75a8f..e804a4d251f73 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -198,7 +198,7 @@ static RegisterInfo g_register_infos[] = { // =============== =============== ========================= // ===================== ============= {"r0", - NULL, + nullptr, 4, GPR_OFFSET(0), eEncodingUint, @@ -209,7 +209,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r1", - NULL, + nullptr, 4, GPR_OFFSET(1), eEncodingUint, @@ -220,7 +220,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r2", - NULL, + nullptr, 4, GPR_OFFSET(2), eEncodingUint, @@ -231,7 +231,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r3", - NULL, + nullptr, 4, GPR_OFFSET(3), eEncodingUint, @@ -242,7 +242,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r4", - NULL, + nullptr, 4, GPR_OFFSET(4), eEncodingUint, @@ -253,7 +253,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r5", - NULL, + nullptr, 4, GPR_OFFSET(5), eEncodingUint, @@ -264,7 +264,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r6", - NULL, + nullptr, 4, GPR_OFFSET(6), eEncodingUint, @@ -275,7 +275,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r7", - NULL, + nullptr, 4, GPR_OFFSET(7), eEncodingUint, @@ -287,7 +287,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r8", - NULL, + nullptr, 4, GPR_OFFSET(8), eEncodingUint, @@ -298,7 +298,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r9", - NULL, + nullptr, 4, GPR_OFFSET(9), eEncodingUint, @@ -309,7 +309,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r10", - NULL, + nullptr, 4, GPR_OFFSET(10), eEncodingUint, @@ -321,7 +321,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r11", - NULL, + nullptr, 4, GPR_OFFSET(11), eEncodingUint, @@ -333,7 +333,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"r12", - NULL, + nullptr, 4, GPR_OFFSET(12), eEncodingUint, @@ -394,7 +394,7 @@ static RegisterInfo g_register_infos[] = { 0}, {"s0", - NULL, + nullptr, 4, FPU_OFFSET(0), eEncodingIEEE754, @@ -406,7 +406,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s1", - NULL, + nullptr, 4, FPU_OFFSET(1), eEncodingIEEE754, @@ -418,7 +418,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s2", - NULL, + nullptr, 4, FPU_OFFSET(2), eEncodingIEEE754, @@ -430,7 +430,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s3", - NULL, + nullptr, 4, FPU_OFFSET(3), eEncodingIEEE754, @@ -442,7 +442,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s4", - NULL, + nullptr, 4, FPU_OFFSET(4), eEncodingIEEE754, @@ -454,7 +454,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s5", - NULL, + nullptr, 4, FPU_OFFSET(5), eEncodingIEEE754, @@ -466,7 +466,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s6", - NULL, + nullptr, 4, FPU_OFFSET(6), eEncodingIEEE754, @@ -478,7 +478,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s7", - NULL, + nullptr, 4, FPU_OFFSET(7), eEncodingIEEE754, @@ -490,7 +490,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s8", - NULL, + nullptr, 4, FPU_OFFSET(8), eEncodingIEEE754, @@ -502,7 +502,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s9", - NULL, + nullptr, 4, FPU_OFFSET(9), eEncodingIEEE754, @@ -514,7 +514,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s10", - NULL, + nullptr, 4, FPU_OFFSET(10), eEncodingIEEE754, @@ -526,7 +526,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s11", - NULL, + nullptr, 4, FPU_OFFSET(11), eEncodingIEEE754, @@ -538,7 +538,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s12", - NULL, + nullptr, 4, FPU_OFFSET(12), eEncodingIEEE754, @@ -550,7 +550,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s13", - NULL, + nullptr, 4, FPU_OFFSET(13), eEncodingIEEE754, @@ -562,7 +562,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s14", - NULL, + nullptr, 4, FPU_OFFSET(14), eEncodingIEEE754, @@ -574,7 +574,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s15", - NULL, + nullptr, 4, FPU_OFFSET(15), eEncodingIEEE754, @@ -586,7 +586,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s16", - NULL, + nullptr, 4, FPU_OFFSET(16), eEncodingIEEE754, @@ -598,7 +598,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s17", - NULL, + nullptr, 4, FPU_OFFSET(17), eEncodingIEEE754, @@ -610,7 +610,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s18", - NULL, + nullptr, 4, FPU_OFFSET(18), eEncodingIEEE754, @@ -622,7 +622,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s19", - NULL, + nullptr, 4, FPU_OFFSET(19), eEncodingIEEE754, @@ -634,7 +634,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s20", - NULL, + nullptr, 4, FPU_OFFSET(20), eEncodingIEEE754, @@ -646,7 +646,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s21", - NULL, + nullptr, 4, FPU_OFFSET(21), eEncodingIEEE754, @@ -658,7 +658,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s22", - NULL, + nullptr, 4, FPU_OFFSET(22), eEncodingIEEE754, @@ -670,7 +670,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s23", - NULL, + nullptr, 4, FPU_OFFSET(23), eEncodingIEEE754, @@ -682,7 +682,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s24", - NULL, + nullptr, 4, FPU_OFFSET(24), eEncodingIEEE754, @@ -694,7 +694,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s25", - NULL, + nullptr, 4, FPU_OFFSET(25), eEncodingIEEE754, @@ -706,7 +706,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s26", - NULL, + nullptr, 4, FPU_OFFSET(26), eEncodingIEEE754, @@ -718,7 +718,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s27", - NULL, + nullptr, 4, FPU_OFFSET(27), eEncodingIEEE754, @@ -730,7 +730,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s28", - NULL, + nullptr, 4, FPU_OFFSET(28), eEncodingIEEE754, @@ -742,7 +742,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s29", - NULL, + nullptr, 4, FPU_OFFSET(29), eEncodingIEEE754, @@ -754,7 +754,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s30", - NULL, + nullptr, 4, FPU_OFFSET(30), eEncodingIEEE754, @@ -766,7 +766,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"s31", - NULL, + nullptr, 4, FPU_OFFSET(31), eEncodingIEEE754, @@ -778,7 +778,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"fpscr", - NULL, + nullptr, 4, FPU_OFFSET(32), eEncodingUint, @@ -791,7 +791,7 @@ static RegisterInfo g_register_infos[] = { 0}, {"exception", - NULL, + nullptr, 4, EXC_OFFSET(0), eEncodingUint, @@ -803,7 +803,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"fsr", - NULL, + nullptr, 4, EXC_OFFSET(1), eEncodingUint, @@ -815,7 +815,7 @@ static RegisterInfo g_register_infos[] = { nullptr, 0}, {"far", - NULL, + nullptr, 4, EXC_OFFSET(2), eEncodingUint, @@ -944,7 +944,7 @@ RegisterContextDarwin_arm::GetRegisterInfoAtIndex(size_t reg) { assert(k_num_register_infos == k_num_registers); if (reg < k_num_registers) return &g_register_infos[reg]; - return NULL; + return nullptr; } size_t RegisterContextDarwin_arm::GetRegisterInfosCount() { @@ -979,7 +979,7 @@ size_t RegisterContextDarwin_arm::GetRegisterSetCount() { const RegisterSet *RegisterContextDarwin_arm::GetRegisterSet(size_t reg_set) { if (reg_set < k_num_regsets) return &g_reg_sets[reg_set]; - return NULL; + return nullptr; } // Register information definitions for 32 bit i386. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index c264831c0ddb9..e0d67d12d4971 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -122,7 +122,7 @@ RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) { assert(k_num_register_infos == k_num_registers); if (reg < k_num_registers) return &g_register_infos_arm64_le[reg]; - return NULL; + return nullptr; } size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() { @@ -157,7 +157,7 @@ size_t RegisterContextDarwin_arm64::GetRegisterSetCount() { const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) { if (reg_set < k_num_regsets) return &g_reg_sets[reg_set]; - return NULL; + return nullptr; } // Register information definitions for arm64 diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 130a2673fde0a..69b56242c86ce 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -176,42 +176,42 @@ static RegisterInfo g_register_infos[] = { // =============================== ======================= // =================== ========================= ================== // ================= - {DEFINE_GPR(eax, NULL), + {DEFINE_GPR(eax, nullptr), {ehframe_eax, dwarf_eax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_eax}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(ebx, NULL), + {DEFINE_GPR(ebx, nullptr), {ehframe_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_ebx}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(ecx, NULL), + {DEFINE_GPR(ecx, nullptr), {ehframe_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_ecx}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(edx, NULL), + {DEFINE_GPR(edx, nullptr), {ehframe_edx, dwarf_edx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_edx}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(edi, NULL), + {DEFINE_GPR(edi, nullptr), {ehframe_edi, dwarf_edi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_edi}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(esi, NULL), + {DEFINE_GPR(esi, nullptr), {ehframe_esi, dwarf_esi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_esi}, nullptr, @@ -232,7 +232,7 @@ static RegisterInfo g_register_infos[] = { nullptr, nullptr, 0}, - {DEFINE_GPR(ss, NULL), + {DEFINE_GPR(ss, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_ss}, nullptr, @@ -253,35 +253,35 @@ static RegisterInfo g_register_infos[] = { nullptr, nullptr, 0}, - {DEFINE_GPR(cs, NULL), + {DEFINE_GPR(cs, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_cs}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(ds, NULL), + {DEFINE_GPR(ds, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_ds}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(es, NULL), + {DEFINE_GPR(es, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_es}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(fs, NULL), + {DEFINE_GPR(fs, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_fs}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(gs, NULL), + {DEFINE_GPR(gs, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_gs}, nullptr, @@ -427,7 +427,7 @@ RegisterContextDarwin_i386::GetRegisterInfoAtIndex(size_t reg) { assert(k_num_register_infos == k_num_registers); if (reg < k_num_registers) return &g_register_infos[reg]; - return NULL; + return nullptr; } size_t RegisterContextDarwin_i386::GetRegisterInfosCount() { @@ -479,7 +479,7 @@ size_t RegisterContextDarwin_i386::GetRegisterSetCount() { const RegisterSet *RegisterContextDarwin_i386::GetRegisterSet(size_t reg_set) { if (reg_set < k_num_regsets) return &g_reg_sets[reg_set]; - return NULL; + return nullptr; } // Register information definitions for 32 bit i386. diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index 4a37454ba8c5f..e908c6dffafcf 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -195,42 +195,42 @@ static RegisterInfo g_register_infos[] = { // =============================== ====================== // =================== ========================== ==================== // =================== - {DEFINE_GPR(rax, NULL), + {DEFINE_GPR(rax, nullptr), {ehframe_dwarf_gpr_rax, ehframe_dwarf_gpr_rax, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_rax}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(rbx, NULL), + {DEFINE_GPR(rbx, nullptr), {ehframe_dwarf_gpr_rbx, ehframe_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_rbx}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(rcx, NULL), + {DEFINE_GPR(rcx, nullptr), {ehframe_dwarf_gpr_rcx, ehframe_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_rcx}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(rdx, NULL), + {DEFINE_GPR(rdx, nullptr), {ehframe_dwarf_gpr_rdx, ehframe_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_rdx}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(rdi, NULL), + {DEFINE_GPR(rdi, nullptr), {ehframe_dwarf_gpr_rdi, ehframe_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_rdi}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(rsi, NULL), + {DEFINE_GPR(rsi, nullptr), {ehframe_dwarf_gpr_rsi, ehframe_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_rsi}, nullptr, @@ -251,56 +251,56 @@ static RegisterInfo g_register_infos[] = { nullptr, nullptr, 0}, - {DEFINE_GPR(r8, NULL), + {DEFINE_GPR(r8, nullptr), {ehframe_dwarf_gpr_r8, ehframe_dwarf_gpr_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r9, NULL), + {DEFINE_GPR(r9, nullptr), {ehframe_dwarf_gpr_r9, ehframe_dwarf_gpr_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r10, NULL), + {DEFINE_GPR(r10, nullptr), {ehframe_dwarf_gpr_r10, ehframe_dwarf_gpr_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r11, NULL), + {DEFINE_GPR(r11, nullptr), {ehframe_dwarf_gpr_r11, ehframe_dwarf_gpr_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r11}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r12, NULL), + {DEFINE_GPR(r12, nullptr), {ehframe_dwarf_gpr_r12, ehframe_dwarf_gpr_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r13, NULL), + {DEFINE_GPR(r13, nullptr), {ehframe_dwarf_gpr_r13, ehframe_dwarf_gpr_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r13}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r14, NULL), + {DEFINE_GPR(r14, nullptr), {ehframe_dwarf_gpr_r14, ehframe_dwarf_gpr_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r14}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(r15, NULL), + {DEFINE_GPR(r15, nullptr), {ehframe_dwarf_gpr_r15, ehframe_dwarf_gpr_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r15}, nullptr, @@ -321,21 +321,21 @@ static RegisterInfo g_register_infos[] = { nullptr, nullptr, 0}, - {DEFINE_GPR(cs, NULL), + {DEFINE_GPR(cs, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_cs}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(fs, NULL), + {DEFINE_GPR(fs, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_fs}, nullptr, nullptr, nullptr, 0}, - {DEFINE_GPR(gs, NULL), + {DEFINE_GPR(gs, nullptr), {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_gs}, nullptr, @@ -489,7 +489,7 @@ RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex(size_t reg) { assert(k_num_register_infos == k_num_registers); if (reg < k_num_registers) return &g_register_infos[reg]; - return NULL; + return nullptr; } size_t RegisterContextDarwin_x86_64::GetRegisterInfosCount() { @@ -541,7 +541,7 @@ const RegisterSet * RegisterContextDarwin_x86_64::GetRegisterSet(size_t reg_set) { if (reg_set < k_num_regsets) return &g_reg_sets[reg_set]; - return NULL; + return nullptr; } int RegisterContextDarwin_x86_64::GetSetForNativeRegNum(int reg_num) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp index 5ea13a54fd2ba..6832b6095931b 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDummy.cpp @@ -49,8 +49,8 @@ RegisterContextDummy::RegisterContextDummy(Thread &thread, m_pc_reg_info.byte_size = address_byte_size; m_pc_reg_info.encoding = eEncodingUint; m_pc_reg_info.format = eFormatPointer; - m_pc_reg_info.invalidate_regs = NULL; - m_pc_reg_info.value_regs = NULL; + m_pc_reg_info.invalidate_regs = nullptr; + m_pc_reg_info.value_regs = nullptr; m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; @@ -71,7 +71,7 @@ size_t RegisterContextDummy::GetRegisterCount() { return 1; } const lldb_private::RegisterInfo * RegisterContextDummy::GetRegisterInfoAtIndex(size_t reg) { if (reg) - return NULL; + return nullptr; return &m_pc_reg_info; } @@ -80,7 +80,7 @@ size_t RegisterContextDummy::GetRegisterSetCount() { return 1; } const lldb_private::RegisterSet * RegisterContextDummy::GetRegisterSet(size_t reg_set) { if (reg_set) - return NULL; + return nullptr; return &m_reg_set0; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp index 1c3f33d287c78..b90b381082672 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.cpp @@ -70,7 +70,7 @@ const RegisterInfo *RegisterContextFreeBSD_i386::GetRegisterInfo() const { return g_register_infos_i386; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index a0c314653af2e..4f869eb3b1771 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -188,7 +188,7 @@ size_t RegisterContextFreeBSD_powerpc::GetGPRSize() const { const RegisterInfo *RegisterContextFreeBSD_powerpc::GetRegisterInfo() const { // assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc); llvm_unreachable("Abstract class!"); - return NULL; + return nullptr; } uint32_t RegisterContextFreeBSD_powerpc::GetRegisterCount() const { return 0; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp index 8c2268aeaacba..c19a2bfae668a 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextHistory.cpp @@ -50,8 +50,8 @@ RegisterContextHistory::RegisterContextHistory(Thread &thread, m_pc_reg_info.byte_size = address_byte_size; m_pc_reg_info.encoding = eEncodingUint; m_pc_reg_info.format = eFormatPointer; - m_pc_reg_info.invalidate_regs = NULL; - m_pc_reg_info.value_regs = NULL; + m_pc_reg_info.invalidate_regs = nullptr; + m_pc_reg_info.value_regs = nullptr; m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; @@ -72,7 +72,7 @@ size_t RegisterContextHistory::GetRegisterCount() { return 1; } const lldb_private::RegisterInfo * RegisterContextHistory::GetRegisterInfoAtIndex(size_t reg) { if (reg) - return NULL; + return nullptr; return &m_pc_reg_info; } @@ -81,7 +81,7 @@ size_t RegisterContextHistory::GetRegisterSetCount() { return 1; } const lldb_private::RegisterSet * RegisterContextHistory::GetRegisterSet(size_t reg_set) { if (reg_set) - return NULL; + return nullptr; return &m_reg_set0; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index ecda5556e606e..4ec8bba098148 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -113,7 +113,7 @@ void RegisterContextLLDB::InitializeZerothFrame() { ExecutionContext exe_ctx(m_thread.shared_from_this()); RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); - if (reg_ctx_sp.get() == NULL) { + if (reg_ctx_sp.get() == nullptr) { m_frame_type = eNotAValidFrame; UnwindLogMsg("frame does not have a register context"); return; @@ -664,7 +664,7 @@ UnwindPlanSP RegisterContextLLDB::GetFastUnwindPlanForFrame() { ModuleSP pc_module_sp(m_current_pc.GetModule()); if (!m_current_pc.IsValid() || !pc_module_sp || - pc_module_sp->GetObjectFile() == NULL) + pc_module_sp->GetObjectFile() == nullptr) return unwind_plan_sp; if (IsFrameZero()) @@ -715,7 +715,7 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { UnwindPlanSP arch_default_unwind_plan_sp; ExecutionContext exe_ctx(m_thread.shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); - ABI *abi = process ? process->GetABI().get() : NULL; + ABI *abi = process ? process->GetABI().get() : nullptr; if (abi) { arch_default_unwind_plan_sp = std::make_shared(lldb::eRegisterKindGeneric); @@ -743,7 +743,7 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // This is for jumping to memory regions without any information available. if ((!m_sym_ctx_valid || - (m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) && + (m_sym_ctx.function == nullptr && m_sym_ctx.symbol == nullptr)) && behaves_like_zeroth_frame && m_current_pc.IsValid()) { uint32_t permissions; addr_t current_pc_addr = @@ -765,7 +765,7 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // No Module for the current pc, try using the architecture default unwind. ModuleSP pc_module_sp(m_current_pc.GetModule()); if (!m_current_pc.IsValid() || !pc_module_sp || - pc_module_sp->GetObjectFile() == NULL) { + pc_module_sp->GetObjectFile() == nullptr) { m_frame_type = eNormalFrame; return arch_default_unwind_plan_sp; } @@ -1349,7 +1349,7 @@ RegisterContextLLDB::SavedLocationForRegister( // register, we may be able to fall back to some ABI-defined default. For // example, some ABIs allow to determine the caller's SP via the CFA. Also, // the ABI may set volatile registers to the undefined state. - ABI *abi = process ? process->GetABI().get() : NULL; + ABI *abi = process ? process->GetABI().get() : nullptr; if (abi) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB)); @@ -1702,10 +1702,10 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() { } bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() { - if (m_fallback_unwind_plan_sp.get() == NULL) + if (m_fallback_unwind_plan_sp.get() == nullptr) return false; - if (m_full_unwind_plan_sp.get() == NULL) + if (m_full_unwind_plan_sp.get() == nullptr) return false; if (m_full_unwind_plan_sp.get() == m_fallback_unwind_plan_sp.get() || @@ -2067,7 +2067,7 @@ void RegisterContextLLDB::UnwindLogMsg(const char *fmt, ...) { va_start(args, fmt); char *logmsg; - if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == NULL) { + if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == nullptr) { if (logmsg) free(logmsg); va_end(args); @@ -2088,7 +2088,7 @@ void RegisterContextLLDB::UnwindLogMsgVerbose(const char *fmt, ...) { va_start(args, fmt); char *logmsg; - if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == NULL) { + if (vasprintf(&logmsg, fmt, args) == -1 || logmsg == nullptr) { if (logmsg) free(logmsg); va_end(args); diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index 1210a7e385757..79979639dc7ee 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -90,8 +90,8 @@ RegisterContextLinux_i386::RegisterContextLinux_i386( const ArchSpec &target_arch) : RegisterInfoInterface(target_arch) { RegisterInfo orig_ax = {"orig_eax", - NULL, - sizeof(((GPR *)NULL)->orig_eax), + nullptr, + sizeof(((GPR *)nullptr)->orig_eax), (LLVM_EXTENSION offsetof(GPR, orig_eax)), eEncodingUint, eFormatHex, @@ -114,7 +114,7 @@ const RegisterInfo *RegisterContextLinux_i386::GetRegisterInfo() const { return g_register_infos_i386; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp index 4797afbc0eeb4..fc60fea791761 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp @@ -116,7 +116,7 @@ const RegisterInfo *RegisterContextLinux_mips::GetRegisterInfo() const { return g_register_infos_mips; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index 6f78f84e93f89..640d5bc022569 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -157,8 +157,8 @@ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64( m_register_info_count(GetRegisterInfoCount(target_arch)), m_user_register_count(GetUserRegisterInfoCount(target_arch)) { RegisterInfo orig_ax = {"orig_rax", - NULL, - sizeof(((GPR *)NULL)->orig_rax), + nullptr, + sizeof(((GPR *)nullptr)->orig_rax), (LLVM_EXTENSION offsetof(GPR, orig_rax)), eEncodingUint, eFormatHex, diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp index c1f141cf2d6ce..06eac6f7f9910 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.cpp @@ -67,7 +67,7 @@ const RegisterInfo *RegisterContextOpenBSD_i386::GetRegisterInfo() const { return g_register_infos_i386; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp index 7366130dd9b1b..821e2aa73b5b1 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp @@ -146,7 +146,7 @@ RegisterContextPOSIX_arm::GetRegisterInfoAtIndex(size_t reg) { if (reg < m_reg_info.num_registers) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_arm::GetRegisterSetCount() { @@ -167,10 +167,10 @@ RegisterContextPOSIX_arm::GetRegisterSet(size_t set) { return &g_reg_sets_arm[set]; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } - return NULL; + return nullptr; } const char *RegisterContextPOSIX_arm::GetRegisterName(unsigned reg) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 5fb9f1f85a10d..99b897d441b59 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -166,7 +166,7 @@ RegisterContextPOSIX_arm64::GetRegisterInfoAtIndex(size_t reg) { if (reg < m_reg_info.num_registers) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_arm64::GetRegisterSetCount() { @@ -187,10 +187,10 @@ RegisterContextPOSIX_arm64::GetRegisterSet(size_t set) { return &g_reg_sets_arm64[set]; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } - return NULL; + return nullptr; } const char *RegisterContextPOSIX_arm64::GetRegisterName(unsigned reg) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp index cedbcd42373e7..f1fa3035b2ef7 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp @@ -96,7 +96,7 @@ RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) { if (reg < m_num_registers) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index 9698b2d84d64f..a78e9ed37947d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -133,7 +133,7 @@ RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg) { if (reg < k_num_registers_powerpc) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_powerpc::GetRegisterSetCount() { @@ -150,7 +150,7 @@ const RegisterSet *RegisterContextPOSIX_powerpc::GetRegisterSet(size_t set) { if (IsRegisterSetAvailable(set)) return &g_reg_sets_powerpc[set]; else - return NULL; + return nullptr; } const char *RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp index 2b380797f1928..02546c0ed16fa 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp @@ -151,7 +151,7 @@ RegisterContextPOSIX_ppc64le::GetRegisterInfoAtIndex(size_t reg) { if (reg < k_num_registers_ppc64le) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_ppc64le::GetRegisterSetCount() { @@ -168,7 +168,7 @@ const RegisterSet *RegisterContextPOSIX_ppc64le::GetRegisterSet(size_t set) { if (IsRegisterSetAvailable(set)) return &g_reg_sets_ppc64le[set]; else - return NULL; + return nullptr; } const char *RegisterContextPOSIX_ppc64le::GetRegisterName(unsigned reg) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp index 2301c82290712..e040e5075721e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -113,7 +113,7 @@ RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg) { if (reg < m_reg_info.num_registers) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_s390x::GetRegisterCount() { @@ -156,10 +156,10 @@ const RegisterSet *RegisterContextPOSIX_s390x::GetRegisterSet(size_t set) { return &g_reg_sets_s390x[set]; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } - return NULL; + return nullptr; } lldb::ByteOrder RegisterContextPOSIX_s390x::GetByteOrder() { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index ee447642426c3..856ce9448dbbd 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -423,7 +423,7 @@ RegisterContextPOSIX_x86::GetRegisterInfoAtIndex(size_t reg) { if (reg < m_reg_info.num_registers) return &GetRegisterInfo()[reg]; else - return NULL; + return nullptr; } size_t RegisterContextPOSIX_x86::GetRegisterSetCount() { @@ -445,10 +445,10 @@ const RegisterSet *RegisterContextPOSIX_x86::GetRegisterSet(size_t set) { return &g_reg_sets_x86_64[set]; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } - return NULL; + return nullptr; } const char *RegisterContextPOSIX_x86::GetRegisterName(unsigned reg) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp index c21c02f24979d..bcf60cc7a3384 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -73,7 +73,7 @@ RegisterContextThreadMemory::GetRegisterInfoAtIndex(size_t reg) { UpdateRegisterContext(); if (m_reg_ctx_sp) return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg); - return NULL; + return nullptr; } size_t RegisterContextThreadMemory::GetRegisterSetCount() { @@ -87,7 +87,7 @@ const RegisterSet *RegisterContextThreadMemory::GetRegisterSet(size_t reg_set) { UpdateRegisterContext(); if (m_reg_ctx_sp) return m_reg_ctx_sp->GetRegisterSet(reg_set); - return NULL; + return nullptr; } bool RegisterContextThreadMemory::ReadRegister(const RegisterInfo *reg_info, diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp index 118c9ffe654ea..d392d3be1c41c 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp @@ -55,7 +55,7 @@ GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { return g_register_infos_arm; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 14d1119026464..f7471526d0548 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -60,7 +60,7 @@ GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { return g_register_infos_arm64_le; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp index 63d35c291e98a..35051a3ce095f 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp @@ -27,7 +27,7 @@ GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { return g_register_infos_ppc64le; default: assert(false && "Unhandled target architecture."); - return NULL; + return nullptr; } } diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index 64b88e665046b..588015a51ef16 100644 --- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -37,11 +37,11 @@ const char *StopInfoMachException::GetDescription() { target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch; - const char *exc_desc = NULL; + const char *exc_desc = nullptr; const char *code_label = "code"; - const char *code_desc = NULL; + const char *code_desc = nullptr; const char *subcode_label = "subcode"; - const char *subcode_desc = NULL; + const char *subcode_desc = nullptr; #if defined(__APPLE__) char code_desc_buf[32]; @@ -593,7 +593,7 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( // the thread ID so we must always report the breakpoint regardless // of the thread. if (bp_site_sp->ValidForThisThread(&thread) || - thread.GetProcess()->GetOperatingSystem() != NULL) + thread.GetProcess()->GetOperatingSystem() != nullptr) return StopInfo::CreateStopReasonWithBreakpointSiteID( thread, bp_site_sp->GetID()); else if (is_trace_if_actual_breakpoint_missing) diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index d11fda293f8cc..38209fb249483 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -50,7 +50,7 @@ uint32_t UnwindLLDB::DoGetFrameCount() { return 0; ProcessSP process_sp(m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; while (AddOneMoreFrame(abi)) { #if DEBUG_FRAME_SPEED @@ -73,13 +73,13 @@ bool UnwindLLDB::AddFirstFrame() { return true; ProcessSP process_sp(m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; // First, set up the 0th (initial) frame CursorSP first_cursor_sp(new Cursor()); RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB( m_thread, RegisterContextLLDBSP(), first_cursor_sp->sctx, 0, *this)); - if (reg_ctx_sp.get() == NULL) + if (reg_ctx_sp.get() == nullptr) goto unwind_done; if (!reg_ctx_sp->IsValid()) @@ -147,7 +147,7 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) { return nullptr; } - if (reg_ctx_sp.get() == NULL) { + if (reg_ctx_sp.get() == nullptr) { // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to // that and return true. Subsequent calls to TryFallbackUnwindPlan() will // return false. @@ -402,7 +402,7 @@ bool UnwindLLDB::DoGetFrameInfoAtIndex(uint32_t idx, addr_t &cfa, addr_t &pc) { } ProcessSP process_sp(m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; while (idx >= m_frames.size() && AddOneMoreFrame(abi)) ; @@ -430,7 +430,7 @@ UnwindLLDB::DoCreateRegisterContextForFrame(StackFrame *frame) { } ProcessSP process_sp(m_thread.GetProcess()); - ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; while (idx >= m_frames.size()) { if (!AddOneMoreFrame(abi)) diff --git a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index 4a35637cffbc2..7dc5a5f5fdd1b 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -79,7 +79,7 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386( StackFrame *first_frame = exe_ctx.GetFramePtr(); Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) + if (process == nullptr) return 0; struct Frame_i386 { @@ -121,7 +121,7 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386( SymbolContext first_frame_sc( first_frame->GetSymbolContext(resolve_scope)); - const AddressRange *addr_range_ptr = NULL; + const AddressRange *addr_range_ptr = nullptr; AddressRange range; if (first_frame_sc.function) addr_range_ptr = &first_frame_sc.function->GetAddressRange(); @@ -169,7 +169,7 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( m_cursors.clear(); Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) + if (process == nullptr) return 0; StackFrame *first_frame = exe_ctx.GetFramePtr(); @@ -212,7 +212,7 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( SymbolContext first_frame_sc( first_frame->GetSymbolContext(resolve_scope)); - const AddressRange *addr_range_ptr = NULL; + const AddressRange *addr_range_ptr = nullptr; AddressRange range; if (first_frame_sc.function) addr_range_ptr = &first_frame_sc.function->GetAddressRange(); diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 25074f854920e..f40ff130cf515 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -80,7 +80,7 @@ bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp, if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) { ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture()); Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp, - NULL, NULL, NULL)); + nullptr, nullptr, nullptr)); if (m_core_module_sp) { ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) @@ -149,7 +149,7 @@ Status ProcessElfCore::DoLoadCore() { } ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); - if (core == NULL) { + if (core == nullptr) { error.SetErrorString("invalid core object file"); return error; } @@ -247,7 +247,7 @@ Status ProcessElfCore::DoLoadCore() { } lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() { - if (m_dyld_up.get() == NULL) + if (m_dyld_up.get() == nullptr) m_dyld_up.reset(DynamicLoader::FindPlugin( this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString())); return m_dyld_up.get(); @@ -327,13 +327,13 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Status &error) { ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile == NULL) + if (core_objfile == nullptr) return 0; // Get the address range const VMRangeToFileOffset::Entry *address_range = m_core_aranges.FindEntryThatContains(addr); - if (address_range == NULL || address_range->GetRangeEnd() < addr) { + if (address_range == nullptr || address_range->GetRangeEnd() < addr) { error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64, addr); return 0; diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index 13291d56a0cbc..ddcf35013b345 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -149,7 +149,7 @@ class ThreadElfCore : public lldb_private::Thread { const char *GetName() override { if (m_thread_name.empty()) - return NULL; + return nullptr; return m_thread_name.c_str(); } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index 3bf0f5c2ce541..fe7ef6b3aceab 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -285,7 +285,7 @@ bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals, void GDBRemoteClientBase::OnRunPacketSent(bool first) { if (first) - BroadcastEvent(eBroadcastBitRunPacketSent, NULL); + BroadcastEvent(eBroadcastBitRunPacketSent, nullptr); } /////////////////////////////////////// @@ -365,7 +365,7 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { // packet. Let's interrupt it. const char ctrl_c = '\x03'; ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL); + size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr); if (bytes_written == 0) { --m_comm.m_async_count; if (log) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 31af1cd26b781..9c3a02e77e58a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -98,7 +98,7 @@ size_t GDBRemoteCommunication::SendAck() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); ConnectionStatus status = eConnectionStatusSuccess; char ch = '+'; - const size_t bytes_written = Write(&ch, 1, status, NULL); + const size_t bytes_written = Write(&ch, 1, status, nullptr); if (log) log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, @@ -110,7 +110,7 @@ size_t GDBRemoteCommunication::SendNack() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); ConnectionStatus status = eConnectionStatusSuccess; char ch = '-'; - const size_t bytes_written = Write(&ch, 1, status, NULL); + const size_t bytes_written = Write(&ch, 1, status, nullptr); if (log) log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend, @@ -138,7 +138,7 @@ GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet, ConnectionStatus status = eConnectionStatusSuccess; const char *packet_data = packet.data(); const size_t packet_length = packet.size(); - size_t bytes_written = Write(packet_data, packet_length, status, NULL); + size_t bytes_written = Write(packet_data, packet_length, status, nullptr); if (log) { size_t binary_start_offset = 0; if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == @@ -274,7 +274,7 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet, Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); // Check for a packet from our cache first without trying any reading... - if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid) + if (CheckForPacket(nullptr, 0, packet) != PacketType::Invalid) return PacketResult::Success; bool timed_out = false; @@ -470,7 +470,7 @@ bool GDBRemoteCommunication::DecompressPacket() { content_length = hash_mark_idx - content_start; std::string bufsize_str(m_bytes.data() + 2, i - 2 - 1); errno = 0; - decompressed_bufsize = ::strtoul(bufsize_str.c_str(), NULL, 10); + decompressed_bufsize = ::strtoul(bufsize_str.c_str(), nullptr, 10); if (errno != 0 || decompressed_bufsize == ULONG_MAX) { m_bytes.erase(0, size_of_first_packet); return false; @@ -483,7 +483,7 @@ bool GDBRemoteCommunication::DecompressPacket() { packet_checksum_cstr[0] = m_bytes[checksum_idx]; packet_checksum_cstr[1] = m_bytes[checksum_idx + 1]; packet_checksum_cstr[2] = '\0'; - long packet_checksum = strtol(packet_checksum_cstr, NULL, 16); + long packet_checksum = strtol(packet_checksum_cstr, nullptr, 16); long actual_checksum = CalculcateChecksum( llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1)); @@ -848,7 +848,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, ::isxdigit(m_bytes[checksum_idx + 1])) { if (GetSendAcks()) { const char *packet_checksum_cstr = &m_bytes[checksum_idx]; - char packet_checksum = strtol(packet_checksum_cstr, NULL, 16); + char packet_checksum = strtol(packet_checksum_cstr, nullptr, 16); char actual_checksum = CalculcateChecksum( llvm::StringRef(m_bytes).slice(content_start, content_end)); success = packet_checksum == actual_checksum; @@ -923,9 +923,9 @@ GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) { // Do the listen on another thread so we can continue on... if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess) - comm->SetConnection(NULL); + comm->SetConnection(nullptr); } - return NULL; + return nullptr; } Status GDBRemoteCommunication::StartDebugserverProcess( diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c6b792e70fcb9..9797184026e06 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -386,14 +386,14 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { std::vector supported_compressions; compressions += sizeof("SupportedCompressions=") - 1; const char *end_of_compressions = strchr(compressions, ';'); - if (end_of_compressions == NULL) { + if (end_of_compressions == nullptr) { end_of_compressions = strchr(compressions, '\0'); } const char *current_compression = compressions; while (current_compression < end_of_compressions) { const char *next_compression_name = strchr(current_compression, ','); const char *end_of_this_word = next_compression_name; - if (next_compression_name == NULL || + if (next_compression_name == nullptr || end_of_compressions < next_compression_name) { end_of_this_word = end_of_compressions; } @@ -775,7 +775,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket( std::vector argv; FileSpec exe_file = launch_info.GetExecutableFile(); std::string exe_path; - const char *arg = NULL; + const char *arg = nullptr; const Args &launch_args = launch_info.GetArguments(); if (exe_file) exe_path = exe_file.GetPath(false); @@ -786,7 +786,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket( } if (!exe_path.empty()) { argv.push_back(exe_path.c_str()); - for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; + for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != nullptr; ++i) { if (arg) argv.push_back(arg); @@ -1094,7 +1094,7 @@ const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() { if (!m_gdb_server_name.empty()) return m_gdb_server_name.c_str(); } - return NULL; + return nullptr; } uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 56ee0a1463c1a..a77e659a55fa2 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -98,7 +98,7 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, bool GDBRemoteRegisterContext::PrivateSetRegisterValue( uint32_t reg, llvm::ArrayRef data) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info == NULL) + if (reg_info == nullptr) return false; // Invalidate if needed @@ -122,7 +122,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue( bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, uint64_t new_reg_val) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); - if (reg_info == NULL) + if (reg_info == nullptr) return false; // Early in process startup, we can get a thread that has an invalid byte @@ -148,7 +148,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, uint8_t *dst = const_cast( m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); - if (dst == NULL) + if (dst == nullptr) return false; if (data.CopyByteOrderedData(0, // src offset @@ -183,7 +183,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -228,7 +228,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, // We have a valid primordial register as our constituent. Grab the // corresponding register info. const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg); - if (prim_reg_info == NULL) + if (prim_reg_info == nullptr) success = false; else { // Read the containing register if it hasn't already been read @@ -301,7 +301,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -319,7 +319,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, uint8_t *dst = const_cast( m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); - if (dst == NULL) + if (dst == nullptr) return false; if (data.CopyByteOrderedData(data_offset, // src offset @@ -361,7 +361,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, // We have a valid primordial register as our constituent. Grab the // corresponding register info. const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg); - if (value_reg_info == NULL) + if (value_reg_info == nullptr) success = false; else success = SetPrimordialRegister(value_reg_info, gdb_comm); @@ -409,7 +409,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -434,7 +434,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -452,7 +452,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -474,7 +474,8 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( // individually and store them as binary data in a buffer. const RegisterInfo *reg_info; - for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++) { + for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr; + i++) { if (reg_info ->value_regs) // skip registers that are slices of real registers continue; @@ -508,14 +509,14 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( bool GDBRemoteRegisterContext::WriteAllRegisterValues( const lldb::DataBufferSP &data_sp) { - if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0) + if (!data_sp || data_sp->GetBytes() == nullptr || data_sp->GetByteSize() == 0) return false; ExecutionContext exe_ctx(CalculateThread()); Process *process = exe_ctx.GetProcessPtr(); Thread *thread = exe_ctx.GetThreadPtr(); - if (process == NULL || thread == NULL) + if (process == nullptr || thread == nullptr) return false; GDBRemoteCommunicationClient &gdb_comm( @@ -557,9 +558,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( uint64_t size_by_highest_offset = 0; for (uint32_t reg_idx = 0; - (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; ++reg_idx) { + (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr; ++reg_idx) { size_including_slice_registers += reg_info->byte_size; - if (reg_info->value_regs == NULL) + if (reg_info->value_regs == nullptr) size_not_including_slice_registers += reg_info->byte_size; if (reg_info->byte_offset >= size_by_highest_offset) size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size; @@ -591,7 +592,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( // keep track of the size of each reg & compute offset based on that. uint32_t running_byte_offset = 0; for (uint32_t reg_idx = 0; - (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; + (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr; ++reg_idx, running_byte_offset += reg_info->byte_size) { // Skip composite aka slice registers (e.g. eax is a slice of rax). if (reg_info->value_regs) @@ -637,7 +638,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( } uint32_t num_restored = 0; const RegisterInfo *reg_info; - for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; + for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr; i++) { if (reg_info->value_regs) // skip registers that are slices of real // registers diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index db95d91449e64..422b092895592 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -114,12 +114,12 @@ static constexpr PropertyDefinition g_properties[] = { {"packet-timeout", OptionValue::eTypeUInt64, true, 5 #if defined(__has_feature) #if __has_feature(address_sanitizer) - * 2 + * 2 #endif #endif - , NULL, {}, + , nullptr, {}, "Specify the default packet timeout in seconds."}, - {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, {}, + {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, nullptr, {}, "The file that provides the description for remote target registers."}}; enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile }; @@ -140,17 +140,17 @@ class PluginProperties : public Properties { uint64_t GetPacketTimeout() { const uint32_t idx = ePropertyPacketTimeout; return m_collection_sp->GetPropertyAtIndexAsUInt64( - NULL, idx, g_properties[idx].default_uint_value); + nullptr, idx, g_properties[idx].default_uint_value); } bool SetPacketTimeout(uint64_t timeout) { const uint32_t idx = ePropertyPacketTimeout; - return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout); + return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, timeout); } FileSpec GetTargetDefinitionFile() const { const uint32_t idx = ePropertyTargetDefinitionFile; - return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx); + return m_collection_sp->GetPropertyAtIndexAsFileSpec(nullptr, idx); } }; @@ -252,7 +252,7 @@ ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; - if (crash_file_path == NULL) + if (crash_file_path == nullptr) process_sp = std::make_shared(target_sp, listener_sp); return process_sp; } @@ -294,7 +294,7 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, : Process(target_sp, listener_sp), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), m_register_info(), - m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), + m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"), m_async_listener_sp( Listener::MakeListener("lldb.process.gdb-remote.async-listener")), m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), @@ -547,8 +547,8 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { std::vector invalidate_regs; std::vector dwarf_opcode_bytes; RegisterInfo reg_info = { - NULL, // Name - NULL, // Alt name + nullptr, // Name + nullptr, // Alt name 0, // byte size reg_offset, // offset eEncodingUint, // encoding @@ -560,10 +560,10 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { reg_num, // process plugin reg num reg_num // native register number }, - NULL, - NULL, - NULL, // Dwarf expression opcode bytes pointer - 0 // Dwarf expression opcode bytes length + nullptr, + nullptr, + nullptr, // Dwarf expression opcode bytes pointer + 0 // Dwarf expression opcode bytes length }; while (response.GetNameColonValue(name, value)) { @@ -583,7 +583,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { reg_info.encoding = encoding; } else if (name.equals("format")) { Format format = eFormatInvalid; - if (OptionArgParser::ToFormat(value.str().c_str(), format, NULL) + if (OptionArgParser::ToFormat(value.str().c_str(), format, nullptr) .Success()) reg_info.format = format; else { @@ -888,8 +888,8 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, // since 'O' packets can really slow down debugging if the inferior // does a lot of output. if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) && - pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) { - FileSpec slave_name{pty.GetSlaveName(NULL, 0)}; + pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, nullptr, 0)) { + FileSpec slave_name{pty.GetSlaveName(nullptr, 0)}; if (!stdin_file_spec) stdin_file_spec = slave_name; @@ -933,7 +933,7 @@ Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module, GetTarget().GetArchitecture().GetArchitectureName()); const char *launch_event_data = launch_info.GetLaunchEventData(); - if (launch_event_data != NULL && *launch_event_data != '\0') + if (launch_event_data != nullptr && *launch_event_data != '\0') m_gdb_comm.SendLaunchEventDataPacket(launch_event_data); if (working_dir) { @@ -1847,7 +1847,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); } - thread_sp->SetName(thread_name.empty() ? NULL : thread_name.c_str()); + thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); // Check if the GDB server was able to provide the queue name, kind and @@ -3126,7 +3126,7 @@ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, Status &error) { if (m_stdio_communication.IsConnected()) { ConnectionStatus status; - m_stdio_communication.Write(src, src_len, status, NULL); + m_stdio_communication.Write(src, src_len, status, nullptr); } else if (m_stdin_forward) { m_gdb_comm.SendStdinNotification(src, src_len); } @@ -3135,7 +3135,7 @@ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { Status error; - assert(bp_site != NULL); + assert(bp_site != nullptr); // Get logging info Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); @@ -3261,7 +3261,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { Status error; - assert(bp_site != NULL); + assert(bp_site != nullptr); addr_t addr = bp_site->GetLoadAddress(); user_id_t site_id = bp_site->GetID(); Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); @@ -3672,9 +3672,9 @@ bool ProcessGDBRemote::StartAsyncThread() { // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). - m_async_thread = - ThreadLauncher::LaunchThread("", - ProcessGDBRemote::AsyncThread, this, NULL); + m_async_thread = ThreadLauncher::LaunchThread( + "", ProcessGDBRemote::AsyncThread, this, + nullptr); } else if (log) log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " "already running.", @@ -3768,7 +3768,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); - if (::strstr(continue_cstr, "vAttach") == NULL) + if (::strstr(continue_cstr, "vAttach") == nullptr) process->SetPrivateState(eStateRunning); StringExtractorGDBRemote response; @@ -3834,11 +3834,11 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { // the "E87" error code from debugserver -- this indicates that // the process is not debuggable. Return a slightly more // helpful error message about why the attach failed. - if (::strstr(continue_cstr, "vAttach") != NULL && + if (::strstr(continue_cstr, "vAttach") != nullptr && response.GetError() == 0x87) { process->SetExitStatus(-1, "cannot attach to process due to " "System Integrity Protection"); - } else if (::strstr(continue_cstr, "vAttach") != NULL && + } else if (::strstr(continue_cstr, "vAttach") != nullptr && response.GetStatus().Fail()) { process->SetExitStatus(-1, response.GetStatus().AsCString()); } else { @@ -3913,7 +3913,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ") thread exiting...", __FUNCTION__, arg, process->GetID()); - return NULL; + return nullptr; } // uint32_t @@ -4009,7 +4009,7 @@ bool ProcessGDBRemote::StartNoticingNewThreads() { } } } - return m_thread_create_bp_sp.get() != NULL; + return m_thread_create_bp_sp.get() != nullptr; } bool ProcessGDBRemote::StopNoticingNewThreads() { @@ -4024,8 +4024,8 @@ bool ProcessGDBRemote::StopNoticingNewThreads() { } DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { - if (m_dyld_up.get() == NULL) - m_dyld_up.reset(DynamicLoader::FindPlugin(this, NULL)); + if (m_dyld_up.get() == nullptr) + m_dyld_up.reset(DynamicLoader::FindPlugin(this, nullptr)); return m_dyld_up.get(); } @@ -4366,8 +4366,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, bool encoding_set = false; bool format_set = false; RegisterInfo reg_info = { - NULL, // Name - NULL, // Alt name + nullptr, // Name + nullptr, // Alt name 0, // byte size reg_offset, // offset eEncodingUint, // encoding @@ -4379,10 +4379,10 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, cur_reg_num, // process plugin reg num cur_reg_num // native register number }, - NULL, - NULL, - NULL, // Dwarf Expression opcode bytes pointer - 0 // Dwarf Expression opcode bytes length + nullptr, + nullptr, + nullptr, // Dwarf Expression opcode bytes pointer + 0 // Dwarf Expression opcode bytes length }; reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, @@ -4416,7 +4416,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, } else if (name == "format") { format_set = true; Format format = eFormatInvalid; - if (OptionArgParser::ToFormat(value.data(), format, NULL).Success()) + if (OptionArgParser::ToFormat(value.data(), format, nullptr) + .Success()) reg_info.format = format; else if (value == "vector-sint8") reg_info.format = eFormatVectorOfSInt8; @@ -5133,7 +5134,7 @@ class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed { "Tests packet speeds of various sizes to determine " "the performance characteristics of the GDB remote " "connection. ", - NULL), + nullptr), m_option_group(), m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size " @@ -5207,7 +5208,7 @@ class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed { public: CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin packet history", - "Dumps the packet history buffer. ", NULL) {} + "Dumps the packet history buffer. ", nullptr) {} ~CommandObjectProcessGDBRemotePacketHistory() override {} @@ -5238,7 +5239,7 @@ class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed { : CommandObjectParsed( interpreter, "process plugin packet xfer-size", "Maximum size that lldb will try to read/write one one chunk.", - NULL) {} + nullptr) {} ~CommandObjectProcessGDBRemotePacketXferSize() override {} @@ -5258,7 +5259,7 @@ class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed { if (process) { const char *packet_size = command.GetArgumentAtIndex(0); errno = 0; - uint64_t user_specified_max = strtoul(packet_size, NULL, 10); + uint64_t user_specified_max = strtoul(packet_size, nullptr, 10); if (errno == 0 && user_specified_max != 0) { process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -5280,7 +5281,7 @@ class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { "The packet header and footer will automatically " "be added to the packet prior to sending and " "stripped from the result.", - NULL) {} + nullptr) {} ~CommandObjectProcessGDBRemotePacketSend() override {} @@ -5308,7 +5309,7 @@ class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { output_strm.Printf(" packet: %s\n", packet_cstr); std::string &response_str = response.GetStringRef(); - if (strstr(packet_cstr, "qGetProfileData") != NULL) { + if (strstr(packet_cstr, "qGetProfileData") != nullptr) { response_str = process->HarmonizeThreadIdsForProfileData(response); } @@ -5376,7 +5377,7 @@ class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword { CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) : CommandObjectMultiword(interpreter, "process plugin packet", "Commands that deal with GDB remote packets.", - NULL) { + nullptr) { LoadSubCommand( "history", CommandObjectSP( diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index f27c80b5d1a1c..cdb7aa006242c 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -93,7 +93,7 @@ bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp, // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach. ModuleSpec core_module_spec(m_core_file); Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp, - NULL, NULL, NULL)); + nullptr, nullptr, nullptr)); if (m_core_module_sp) { ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); @@ -196,7 +196,7 @@ Status ProcessMachCore::DoLoadCore() { } ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile == NULL) { + if (core_objfile == nullptr) { error.SetErrorString("invalid core object file"); return error; } @@ -209,7 +209,7 @@ Status ProcessMachCore::DoLoadCore() { } SectionList *section_list = core_objfile->GetSectionList(); - if (section_list == NULL) { + if (section_list == nullptr) { error.SetErrorString("core file has no sections"); return error; } @@ -308,7 +308,7 @@ Status ProcessMachCore::DoLoadCore() { size_t p = corefile_identifier.find("stext=") + strlen("stext="); if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') { errno = 0; - addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16); + addr = ::strtoul(corefile_identifier.c_str() + p, nullptr, 16); if (errno != 0 || addr == 0) addr = LLDB_INVALID_ADDRESS; } @@ -447,10 +447,10 @@ Status ProcessMachCore::DoLoadCore() { } lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() { - if (m_dyld_up.get() == NULL) + if (m_dyld_up.get() == nullptr) m_dyld_up.reset(DynamicLoader::FindPlugin( - this, - m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); + this, m_dyld_plugin_name.IsEmpty() ? nullptr + : m_dyld_plugin_name.GetCString())); return m_dyld_up.get(); } diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index d3d2a07afac66..a7fc42cad16c9 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -600,10 +600,9 @@ class CommandObjectProcessMinidumpDump : public CommandObjectParsed { return DumpFacebook() || m_fb_logcat.GetOptionValue().GetCurrentValue(); } public: - CommandObjectProcessMinidumpDump(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin dump", - "Dump information from the minidump file.", NULL), + "Dump information from the minidump file.", nullptr), m_option_group(), INIT_BOOL(m_dump_all, "all", 'a', "Dump the everything in the minidump."), diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index a4959265fadce..2d2b68ceaaa6b 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -1943,7 +1943,7 @@ lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); should_step = LLDBSWIGPythonCallThreadPlan( - generic->GetValue(), "should_step", NULL, script_error); + generic->GetValue(), "should_step", nullptr, script_error); if (script_error) should_step = true; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 15b91f53a80cc..def7eb2e1eb28 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -185,7 +185,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) { SymbolFileDWARF *dwarf = die.GetDWARF(); TypeSP type_sp(new Type( die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(), - NULL, LLDB_INVALID_UID, Type::eEncodingInvalid, + nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward)); dwarf->GetTypeList()->Insert(type_sp); @@ -461,7 +461,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); if (translation_unit_is_objc) { - if (type_name_cstr != NULL) { + if (type_name_cstr != nullptr) { static ConstString g_objc_type_name_id("id"); static ConstString g_objc_type_name_Class("Class"); static ConstString g_objc_type_name_selector("SEL"); @@ -1907,7 +1907,7 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { m_property_setter_name(property_setter_name), m_property_getter_name(property_getter_name), m_property_attributes(property_attributes) { - if (metadata != NULL) { + if (metadata != nullptr) { m_metadata_up.reset(new ClangASTMetadata()); *m_metadata_up = *metadata; } @@ -2442,7 +2442,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators( DWARFAttributes attributes; const size_t num_child_attributes = die.GetAttributes(attributes); if (num_child_attributes > 0) { - const char *name = NULL; + const char *name = nullptr; bool got_value = false; int64_t enum_value = 0; Declaration decl; @@ -2545,8 +2545,8 @@ class DIEStack { Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, const DWARFDIE &die) { DWARFRangeList func_ranges; - const char *name = NULL; - const char *mangled = NULL; + const char *name = nullptr; + const char *mangled = nullptr; int decl_file = 0; int decl_line = 0; int decl_column = 0; @@ -2558,7 +2558,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, const dw_tag_t tag = die.Tag(); if (tag != DW_TAG_subprogram) - return NULL; + return nullptr; if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column, @@ -2633,7 +2633,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, // Supply the type _only_ if it has already been parsed Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE()); - assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED); if (dwarf->FixupAddress(func_range.GetBaseAddress())) { const user_id_t func_user_id = die.GetID(); @@ -2643,7 +2643,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, func_user_id, func_name, func_type, func_range); // first address range - if (func_sp.get() != NULL) { + if (func_sp.get() != nullptr) { if (frame_base.IsValid()) func_sp->GetFrameBaseExpression() = frame_base; comp_unit.AddFunction(func_sp); @@ -2652,7 +2652,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, } } } - return NULL; + return nullptr; } bool DWARFASTParserClang::ParseChildMembers( @@ -2693,10 +2693,10 @@ bool DWARFASTParserClang::ParseChildMembers( if (num_attributes > 0) { Declaration decl; // DWARFExpression location; - const char *name = NULL; - const char *prop_name = NULL; - const char *prop_getter_name = NULL; - const char *prop_setter_name = NULL; + const char *name = nullptr; + const char *prop_name = nullptr; + const char *prop_getter_name = nullptr; + const char *prop_setter_name = nullptr; uint32_t prop_attributes = 0; bool is_artificial = false; @@ -2758,7 +2758,8 @@ bool DWARFASTParserClang::ParseChildMembers( module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, &initialValue, nullptr, memberOffset, nullptr)) { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + member_byte_offset = + memberOffset.ResolveValue(nullptr).UInt(); } } else { // With DWARF 3 and later, if the value is an integer constant, @@ -2874,7 +2875,7 @@ bool DWARFASTParserClang::ParseChildMembers( if (!is_artificial) { Type *member_type = die.ResolveTypeUID(DIERef(encoding_form)); - clang::FieldDecl *field_decl = NULL; + clang::FieldDecl *field_decl = nullptr; if (tag == DW_TAG_member) { if (member_type) { if (accessibility == eAccessNone) @@ -3133,12 +3134,12 @@ bool DWARFASTParserClang::ParseChildMembers( } } - if (prop_name != NULL && member_type) { - clang::ObjCIvarDecl *ivar_decl = NULL; + if (prop_name != nullptr && member_type) { + clang::ObjCIvarDecl *ivar_decl = nullptr; if (field_decl) { ivar_decl = clang::dyn_cast(field_decl); - assert(ivar_decl != NULL); + assert(ivar_decl != nullptr); } ClangASTMetadata metadata; @@ -3209,7 +3210,8 @@ bool DWARFASTParserClang::ParseChildMembers( block_offset, block_length, eRegisterKindDWARF, &initialValue, nullptr, memberOffset, nullptr)) { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); + member_byte_offset = + memberOffset.ResolveValue(nullptr).UInt(); } } else { // With DWARF 3 and later, if the value is an integer constant, @@ -3237,7 +3239,7 @@ bool DWARFASTParserClang::ParseChildMembers( } Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form)); - if (base_class_type == NULL) { + if (base_class_type == nullptr) { module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to " "resolve the base class at 0x%8.8x" " from enclosing type 0x%8.8x. \nPlease file " @@ -3314,7 +3316,7 @@ size_t DWARFASTParserClang::ParseChildParameters( DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); if (num_attributes > 0) { - const char *name = NULL; + const char *name = nullptr; Declaration decl; DWARFFormValue param_type_die_form; bool is_artificial = false; @@ -3371,7 +3373,7 @@ size_t DWARFASTParserClang::ParseChildParameters( // Often times compilers omit the "this" name for the // specification DIEs, so we can't rely upon the name being in // the formal parameter DIE... - (name == NULL || ::strcmp(name, "this") == 0)) { + (name == nullptr || ::strcmp(name, "this") == 0)) { Type *this_type = die.ResolveTypeUID(DIERef(param_type_die_form)); if (this_type) { uint32_t encoding_mask = this_type->GetEncodingMask(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp index 25d64d4f62f13..e9aa8f360bcab 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp @@ -66,7 +66,7 @@ DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration( if (idx < m_decls.size()) return &m_decls[idx]; } - return NULL; + return nullptr; } @@ -137,7 +137,7 @@ DWARFDebugAbbrev::GetAbbreviationDeclarationSet( if (pos != m_abbrevCollMap.end()) return &(pos->second); - return NULL; + return nullptr; } // DWARFDebugAbbrev::GetUnsupportedForms() diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index 4d22c825390e6..e2de7d536f17e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -68,7 +68,7 @@ DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) { } void DWARFDebugAranges::Dump(Log *log) const { - if (log == NULL) + if (log == nullptr) return; const size_t num_entries = m_aranges.GetSize(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index f17caf1bca576..c81b6ce05f0f7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -30,7 +30,7 @@ using namespace std; // Constructor DWARFDebugInfo::DWARFDebugInfo(lldb_private::DWARFContext &context) - : m_dwarf2Data(NULL), m_context(context), m_units(), m_cu_aranges_up() {} + : m_dwarf2Data(nullptr), m_context(context), m_units(), m_cu_aranges_up() {} // SetDwarfData void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) { @@ -114,7 +114,7 @@ size_t DWARFDebugInfo::GetNumUnits() { } DWARFUnit *DWARFDebugInfo::GetUnitAtIndex(user_id_t idx) { - DWARFUnit *cu = NULL; + DWARFUnit *cu = nullptr; if (idx < GetNumUnits()) cu = m_units[idx].get(); return cu; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index 25aecf3accf44..215862c1aa7b4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -41,8 +41,8 @@ class DWARFDebugInfo { size_t GetNumUnits(); DWARFUnit *GetUnitAtIndex(lldb::user_id_t idx); - DWARFUnit *GetUnitAtOffset(DIERef::Section section, - dw_offset_t cu_offset, uint32_t *idx_ptr = NULL); + DWARFUnit *GetUnitAtOffset(DIERef::Section section, dw_offset_t cu_offset, + uint32_t *idx_ptr = nullptr); DWARFUnit *GetUnitContainingDIEOffset(DIERef::Section section, dw_offset_t die_offset); DWARFUnit *GetUnit(const DIERef &die_ref); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 7dd3eef2f4629..aba80705ba9da 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -51,7 +51,7 @@ bool DWARFDebugInfoEntry::FastExtract( const DWARFAbbreviationDeclaration *abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(m_abbr_idx); - if (abbrevDecl == NULL) { + if (abbrevDecl == nullptr) { cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError( "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " "attach the file at the start of this error message", @@ -451,13 +451,13 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( } break; case DW_AT_name: - if (name == NULL) + if (name == nullptr) name = form_value.AsCString(); break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: - if (mangled == NULL) + if (mangled == nullptr) mangled = form_value.AsCString(); break; @@ -551,7 +551,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( frame_base->SetLocationListSlide(lowest_range_pc - cu->GetBaseAddress()); } - if (ranges.IsEmpty() || name == NULL || mangled == NULL) { + if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) { for (const DIERef &die_ref : die_refs) { if (die_ref.die_offset != DW_INVALID_OFFSET) { DWARFDIE die = dwarf2Data->GetDIE(die_ref); @@ -1223,7 +1223,7 @@ DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu, storage.append(name); } if (storage.empty()) - return NULL; + return nullptr; return storage.c_str(); } @@ -1385,13 +1385,14 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, switch (m_tag) { case DW_TAG_compile_unit: // File case DW_TAG_partial_unit: // File - check_children = ((function_die != NULL) || (block_die != NULL)); + check_children = + ((function_die != nullptr) || (block_die != nullptr)); break; case DW_TAG_subprogram: // Function if (function_die) *function_die = this; - check_children = (block_die != NULL); + check_children = (block_die != nullptr); break; case DW_TAG_inlined_subroutine: // Inlined Function @@ -1411,9 +1412,9 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, // Compile units may not have a valid high/low pc when there // are address gaps in subroutines so we must always search // if there is no valid high and low PC. - check_children = (m_tag == DW_TAG_compile_unit || - m_tag == DW_TAG_partial_unit) && - ((function_die != NULL) || (block_die != NULL)); + check_children = + (m_tag == DW_TAG_compile_unit || m_tag == DW_TAG_partial_unit) && + ((function_die != nullptr) || (block_die != nullptr)); } } else { DWARFFormValue form_value; @@ -1430,13 +1431,14 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, switch (m_tag) { case DW_TAG_compile_unit: // File case DW_TAG_partial_unit: // File - check_children = ((function_die != NULL) || (block_die != NULL)); + check_children = + ((function_die != nullptr) || (block_die != nullptr)); break; case DW_TAG_subprogram: // Function if (function_die) *function_die = this; - check_children = (block_die != NULL); + check_children = (block_die != nullptr); break; case DW_TAG_inlined_subroutine: // Inlined Function @@ -1500,7 +1502,7 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr( } } offset = DW_INVALID_OFFSET; - return NULL; + return nullptr; } bool DWARFDebugInfoEntry::OffsetLessThan(const DWARFDebugInfoEntry &a, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 6c1057a0cf026..caf2915cc74d1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -143,12 +143,11 @@ class DWARFDebugInfoEntry { lldb::offset_t *offset_ptr, lldb_private::Stream &s, dw_attr_t attr, DWARFFormValue &form_value); - bool - GetDIENamesAndRanges(const DWARFUnit *cu, const char *&name, - const char *&mangled, DWARFRangeList &rangeList, - int &decl_file, int &decl_line, int &decl_column, - int &call_file, int &call_line, int &call_column, - lldb_private::DWARFExpression *frame_base = NULL) const; + bool GetDIENamesAndRanges( + const DWARFUnit *cu, const char *&name, const char *&mangled, + DWARFRangeList &rangeList, int &decl_file, int &decl_line, + int &decl_column, int &call_file, int &call_line, int &call_column, + lldb_private::DWARFExpression *frame_base = nullptr) const; const DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu, @@ -167,27 +166,27 @@ class DWARFDebugInfoEntry { // We know we are kept in a vector of contiguous entries, so we know // our parent will be some index behind "this". DWARFDebugInfoEntry *GetParent() { - return m_parent_idx > 0 ? this - m_parent_idx : NULL; + return m_parent_idx > 0 ? this - m_parent_idx : nullptr; } const DWARFDebugInfoEntry *GetParent() const { - return m_parent_idx > 0 ? this - m_parent_idx : NULL; + return m_parent_idx > 0 ? this - m_parent_idx : nullptr; } // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". DWARFDebugInfoEntry *GetSibling() { - return m_sibling_idx > 0 ? this + m_sibling_idx : NULL; + return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; } const DWARFDebugInfoEntry *GetSibling() const { - return m_sibling_idx > 0 ? this + m_sibling_idx : NULL; + return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; } // We know we are kept in a vector of contiguous entries, so we know // we don't need to store our child pointer, if we have a child it will // be the next entry in the list... DWARFDebugInfoEntry *GetFirstChild() { - return HasChildren() ? this + 1 : NULL; + return HasChildren() ? this + 1 : nullptr; } const DWARFDebugInfoEntry *GetFirstChild() const { - return HasChildren() ? this + 1 : NULL; + return HasChildren() ? this + 1 : nullptr; } std::vector GetDeclContextDIEs(DWARFUnit *cu) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp index 0a7a44ac28296..953089fee22b5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp @@ -38,7 +38,7 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) { while (debug_line_data.ValidOffset(offset)) { const lldb::offset_t debug_line_offset = offset; - if (line_table_sp.get() == NULL) + if (line_table_sp.get() == nullptr) break; if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 5e2646a0ced79..cb7f26264a498 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -105,7 +105,7 @@ void DWARFDebugRanges::Dump(Stream &s, dw_addr_t begin_addr = begin + base_addr; dw_addr_t end_addr = end + base_addr; - s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL); + s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), nullptr); } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp index 455cb01e71a4a..a664314035e4d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp @@ -29,7 +29,7 @@ const char *DWARFDeclContext::GetQualifiedName() const { for (pos = begin; pos != end; ++pos) { if (pos != begin) m_qualified_name.append("::"); - if (pos->name == NULL) { + if (pos->name == nullptr) { if (pos->tag == DW_TAG_namespace) m_qualified_name.append("(anonymous namespace)"); else if (pos->tag == DW_TAG_class_type) @@ -47,7 +47,7 @@ const char *DWARFDeclContext::GetQualifiedName() const { } } if (m_qualified_name.empty()) - return NULL; + return nullptr; return m_qualified_name.c_str(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 9f5e28eb747d6..d0d70dd5123e1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -23,7 +23,7 @@ class DWARFDeclContext { public: struct Entry { - Entry() : tag(0), name(NULL) {} + Entry() : tag(0), name(nullptr) {} Entry(dw_tag_t t, const char *n) : tag(t), name(n) {} bool NameMatches(const Entry &rhs) const { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 5e2caed4d4662..9b5faa6ed9bd6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -120,7 +120,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, bool indirect = false; bool is_block = false; - m_value.data = NULL; + m_value.data = nullptr; uint8_t ref_addr_size; // Read the value for the form into value and follow and DW_FORM_indirect // instances we run into @@ -223,7 +223,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data, if (is_block) { m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); - if (m_value.data != NULL) { + if (m_value.data != nullptr) { *offset_ptr += m_value.value.uval; } } @@ -687,7 +687,7 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value, return 0; else if (a_string && b_string) return strcmp(a_string, b_string); - else if (a_string == NULL) + else if (a_string == nullptr) return -1; // A string is NULL, and B is valid else return 1; // A string valid, and B is NULL diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 668bd5a568afe..2143921587f5c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -19,7 +19,7 @@ class DWARFDIE; class DWARFFormValue { public: typedef struct ValueTypeTag { - ValueTypeTag() : value(), data(NULL) { value.uval = 0; } + ValueTypeTag() : value(), data(nullptr) { value.uval = 0; } union { uint64_t uval; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 59202061436ff..65a1fbf74f822 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -502,7 +502,7 @@ void DWARFUnit::ParseProducerInfo() { if (die) { const char *producer_cstr = - die->GetAttributeValueAsString(this, DW_AT_producer, NULL); + die->GetAttributeValueAsString(this, DW_AT_producer, nullptr); if (producer_cstr) { RegularExpression llvm_gcc_regex( llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " @@ -653,7 +653,7 @@ void DWARFUnit::ComputeCompDirAndGuessPathStyle() { return; llvm::StringRef comp_dir = removeHostnameFromPathname( - die->GetAttributeValueAsString(this, DW_AT_comp_dir, NULL)); + die->GetAttributeValueAsString(this, DW_AT_comp_dir, nullptr)); if (!comp_dir.empty()) { FileSpec::Style comp_dir_style = FileSpec::GuessPathStyle(comp_dir).getValueOr(FileSpec::Style::native); @@ -661,7 +661,8 @@ void DWARFUnit::ComputeCompDirAndGuessPathStyle() { } else { // Try to detect the style based on the DW_AT_name attribute, but just store // the detected style in the m_comp_dir field. - const char *name = die->GetAttributeValueAsString(this, DW_AT_name, NULL); + const char *name = + die->GetAttributeValueAsString(this, DW_AT_name, nullptr); m_comp_dir = FileSpec( "", FileSpec::GuessPathStyle(name).getValueOr(FileSpec::Style::native)); } @@ -674,7 +675,7 @@ SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { - if (m_func_aranges_up == NULL) { + if (m_func_aranges_up == nullptr) { m_func_aranges_up.reset(new DWARFDebugAranges()); const DWARFDebugInfoEntry *die = DIEPtr(); if (die) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index 333e203c92890..2cd7c92f1ca81 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -264,7 +264,7 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data, return false; for (size_t i = 0; i < num_atoms; ++i) { - DWARFFormValue form_value(NULL, header_data.atoms[i].form); + DWARFFormValue form_value(nullptr, header_data.atoms[i].form); if (!form_value.ExtractValue(data, offset_ptr)) return false; @@ -341,7 +341,7 @@ DWARFMappedHash::MemoryTable::GetHashDataForName( // There definitely should be a string for this string offset, if there // isn't, there is something wrong, return and error const char *strp_cstr = m_string_table.PeekCStr(pair.key); - if (strp_cstr == NULL) { + if (strp_cstr == nullptr) { *hash_data_offset_ptr = UINT32_MAX; return eResultError; } @@ -408,7 +408,7 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression( // There definitely should be a string for this string offset, if there // isn't, there is something wrong, return and error const char *strp_cstr = m_string_table.PeekCStr(pair.key); - if (strp_cstr == NULL) + if (strp_cstr == nullptr) return eResultError; const uint32_t count = m_data.GetU32(hash_data_offset_ptr); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index cefe81bb176bb..a6fae61a6a4fc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -141,8 +141,8 @@ void ManualDWARFIndex::IndexUnitImpl( } DWARFAttributes attributes; - const char *name = NULL; - const char *mangled_cstr = NULL; + const char *name = nullptr; + const char *mangled_cstr = nullptr; bool is_declaration = false; // bool is_artificial = false; bool has_address = false; @@ -194,7 +194,7 @@ void ManualDWARFIndex::IndexUnitImpl( has_location_or_const_value = true; if (tag == DW_TAG_variable) { const DWARFDebugInfoEntry *parent_die = die.GetParent(); - while (parent_die != NULL) { + while (parent_die != nullptr) { switch (parent_die->Tag()) { case DW_TAG_subprogram: case DW_TAG_lexical_block: @@ -219,13 +219,13 @@ void ManualDWARFIndex::IndexUnitImpl( // } // } // } - parent_die = NULL; // Terminate the while loop. + parent_die = nullptr; // Terminate the while loop. break; case DW_TAG_compile_unit: case DW_TAG_partial_unit: is_global_or_static_variable = true; - parent_die = NULL; // Terminate the while loop. + parent_die = nullptr; // Terminate the while loop. break; default: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index f639b031b1206..c692e8bf18d08 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -292,14 +292,14 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope, ASSERT_MODULE_LOCK(this); TypeSet type_set; - CompileUnit *comp_unit = NULL; - DWARFUnit *dwarf_cu = NULL; + CompileUnit *comp_unit = nullptr; + DWARFUnit *dwarf_cu = nullptr; if (sc_scope) comp_unit = sc_scope->CalculateSymbolContextCompileUnit(); if (comp_unit) { dwarf_cu = GetDWARFCompileUnit(comp_unit); - if (dwarf_cu == 0) + if (dwarf_cu == nullptr) return 0; GetTypes(dwarf_cu->DIE(), dwarf_cu->GetOffset(), dwarf_cu->GetNextUnitOffset(), type_mask, type_set); @@ -355,7 +355,7 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile, UserID(0x7fffffff00000000), // Used by SymbolFileDWARFDebugMap to // when this class parses .o files to // contain the .o file index/ID - m_debug_map_module_wp(), m_debug_map_symfile(NULL), + m_debug_map_module_wp(), m_debug_map_symfile(nullptr), m_context(objfile->GetModule()->GetSectionList(), dwo_section_list), m_data_debug_loc(), m_data_debug_ranges(), m_data_debug_rnglists(), m_abbr(), m_info(), m_line(), m_fetched_external_modules(false), @@ -433,10 +433,10 @@ bool SymbolFileDWARF::SupportedVersion(uint16_t version) { uint32_t SymbolFileDWARF::CalculateAbilities() { uint32_t abilities = 0; - if (m_obj_file != NULL) { - const Section *section = NULL; + if (m_obj_file != nullptr) { + const Section *section = nullptr; const SectionList *section_list = m_obj_file->GetSectionList(); - if (section_list == NULL) + if (section_list == nullptr) return 0; uint64_t debug_abbrev_file_size = 0; @@ -450,7 +450,7 @@ uint32_t SymbolFileDWARF::CalculateAbilities() { section = section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true).get(); - if (section != NULL) { + if (section != nullptr) { debug_info_file_size = section->GetFileSize(); section = @@ -587,7 +587,7 @@ const DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() const { } DWARFDebugInfo *SymbolFileDWARF::DebugInfo() { - if (m_info == NULL) { + if (m_info == nullptr) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast(this)); @@ -612,15 +612,15 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) { if (info) { // The compile unit ID is the index of the DWARF unit. DWARFUnit *dwarf_cu = info->GetUnitAtIndex(comp_unit->GetID()); - if (dwarf_cu && dwarf_cu->GetUserData() == NULL) + if (dwarf_cu && dwarf_cu->GetUserData() == nullptr) dwarf_cu->SetUserData(comp_unit); return dwarf_cu; } - return NULL; + return nullptr; } DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() { - if (m_ranges == NULL) { + if (m_ranges == nullptr) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION, static_cast(this)); @@ -905,7 +905,7 @@ static void ParseDWARFLineTableCallback(dw_offset_t offset, bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) { ASSERT_MODULE_LOCK(this); - if (comp_unit.GetLineTable() != NULL) + if (comp_unit.GetLineTable() != nullptr) return true; DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); @@ -1022,7 +1022,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: case DW_TAG_lexical_block: { - Block *block = NULL; + Block *block = nullptr; if (tag == DW_TAG_subprogram) { // Skip any DW_TAG_subprogram DIEs that are inside of a normal or // inlined functions. These will be parsed on their own as separate @@ -1038,8 +1038,8 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( block = block_sp.get(); } DWARFRangeList ranges; - const char *name = NULL; - const char *mangled_name = NULL; + const char *name = nullptr; + const char *mangled_name = nullptr; int decl_file = 0; int decl_line = 0; @@ -1087,7 +1087,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( block->FinalizeRanges(); if (tag != DW_TAG_subprogram && - (name != NULL || mangled_name != NULL)) { + (name != nullptr || mangled_name != nullptr)) { std::unique_ptr decl_up; if (decl_file != 0 || decl_line != 0 || decl_column != 0) decl_up.reset(new Declaration( @@ -1312,7 +1312,7 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die, } return ResolveType(die); } - return NULL; + return nullptr; } // This function is used when SymbolFileDWARFDebugMap owns a bunch of @@ -1409,7 +1409,7 @@ CompileUnit * SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu, uint32_t cu_idx) { // Check if the symbol vendor already knows about this compile unit? - if (dwarf_cu->GetUserData() == NULL) { + if (dwarf_cu->GetUserData() == nullptr) { // The symbol vendor doesn't know about this compile unit, we need to parse // and add it to the symbol vendor object. return ParseCompileUnit(dwarf_cu, cu_idx).get(); @@ -1432,7 +1432,7 @@ bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) { sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); - if (sc.function == NULL) + if (sc.function == nullptr) sc.function = ParseFunction(*sc.comp_unit, die); if (sc.function) { @@ -1573,7 +1573,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { } Status error = ModuleList::GetSharedModule( - dwo_module_spec, module_sp, NULL, NULL, NULL); + dwo_module_spec, module_sp, nullptr, nullptr, nullptr); if (!module_sp) { GetObjectFile()->GetModule()->ReportWarning( "0x%8.8x: unable to locate module needed for external types: " @@ -1703,7 +1703,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, if (function_die) { sc.function = sc.comp_unit->FindFunctionByUID(function_die.GetID()).get(); - if (sc.function == NULL) + if (sc.function == nullptr) sc.function = ParseFunction(*sc.comp_unit, function_die); if (sc.function && (resolve_scope & eSymbolContextBlock)) @@ -1718,7 +1718,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, force_check_line_table = true; } - if (sc.function != NULL) { + if (sc.function != nullptr) { resolved |= eSymbolContextFunction; if (resolve_scope & eSymbolContextBlock) { @@ -1737,7 +1737,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, if ((resolve_scope & eSymbolContextLineEntry) || force_check_line_table) { LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table != NULL) { + if (line_table != nullptr) { // And address that makes it into this function should be in // terms of this debug file if there is no debug map, or it // will be an address in the .o file which needs to be fixed up @@ -1761,7 +1761,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, // only happen when there aren't other functions from other // compile units in these gaps. This helps keep the size of the // aranges down. - sc.comp_unit = NULL; + sc.comp_unit = nullptr; resolved &= ~eSymbolContextCompUnit; } } else { @@ -1787,14 +1787,15 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, DWARFDebugInfo *debug_info = DebugInfo(); if (debug_info) { uint32_t cu_idx; - DWARFUnit *dwarf_cu = NULL; + DWARFUnit *dwarf_cu = nullptr; - for (cu_idx = 0; (dwarf_cu = debug_info->GetUnitAtIndex(cu_idx)) != NULL; + for (cu_idx = 0; + (dwarf_cu = debug_info->GetUnitAtIndex(cu_idx)) != nullptr; ++cu_idx) { CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); const bool full_match = (bool)file_spec.GetDirectory(); bool file_spec_matches_cu_file_spec = - dc_cu != NULL && FileSpec::Equal(file_spec, *dc_cu, full_match); + dc_cu != nullptr && FileSpec::Equal(file_spec, *dc_cu, full_match); if (check_inlines || file_spec_matches_cu_file_spec) { SymbolContext sc(m_obj_file->GetModule()); sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); @@ -1813,7 +1814,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, if (line != 0) { LineTable *line_table = sc.comp_unit->GetLineTable(); - if (line_table != NULL && line != 0) { + if (line_table != nullptr && line != 0) { // We will have already looked up the file index if we are // searching for inline entries. if (!check_inlines) @@ -1827,8 +1828,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, found_line = sc.line_entry.line; while (line_idx != UINT32_MAX) { - sc.function = NULL; - sc.block = NULL; + sc.function = nullptr; + sc.block = nullptr; if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) { const lldb::addr_t file_vm_addr = @@ -1842,7 +1843,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, sc.comp_unit ->FindFunctionByUID(function_die.GetID()) .get(); - if (sc.function == NULL) + if (sc.function == nullptr) sc.function = ParseFunction(*sc.comp_unit, function_die); @@ -1852,7 +1853,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, function_die.LookupDeepestBlock(file_vm_addr); } - if (sc.function != NULL) { + if (sc.function != nullptr) { Block &block = sc.function->GetBlock(true); if (block_die) @@ -1947,7 +1948,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables( return 0; DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; // Remember how many variables are in the list before we search. @@ -2050,7 +2051,7 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, } DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; // Remember how many variables are in the list before we search. @@ -2120,12 +2121,12 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, if (inlined_die) { Block &function_block = sc.function->GetBlock(true); sc.block = function_block.FindBlockByID(inlined_die.GetID()); - if (sc.block == NULL) + if (sc.block == nullptr) sc.block = function_block.FindBlockByID(inlined_die.GetOffset()); - if (sc.block == NULL || !sc.block->GetStartAddress(addr)) + if (sc.block == nullptr || !sc.block->GetStartAddress(addr)) addr.Clear(); } else { - sc.block = NULL; + sc.block = nullptr; addr = sc.function->GetAddressRange().GetBaseAddress(); } @@ -2196,7 +2197,7 @@ uint32_t SymbolFileDWARF::FindFunctions( const uint32_t original_size = sc_list.GetSize(); DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; llvm::DenseSet resolved_dies; @@ -2319,7 +2320,7 @@ uint32_t SymbolFileDWARF::FindTypes( searched_symbol_files.insert(this); DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -2513,7 +2514,7 @@ TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die, TypeSP type_sp; if (die) { Type *type_ptr = GetDIEToType().lookup(die.GetDIE()); - if (type_ptr == NULL) { + if (type_ptr == nullptr) { CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU()); assert(lldb_cu); SymbolContext sc(lldb_cu); @@ -2528,7 +2529,7 @@ TypeSP SymbolFileDWARF::GetTypeForDIE(const DWARFDIE &die, !GetFunction(DWARFDIE(die.GetCU(), parent_die), sc)) sc = sc_backup; - type_sp = ParseType(sc, die, NULL); + type_sp = ParseType(sc, die, nullptr); } else if (type_ptr != DIE_IS_BEING_PARSED) { // Grab the existing type from the master types lists type_sp = type_ptr->shared_from_this(); @@ -2591,7 +2592,7 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) { Symbol * SymbolFileDWARF::GetObjCClassSymbol(ConstString objc_class_name) { - Symbol *objc_class_symbol = NULL; + Symbol *objc_class_symbol = nullptr; if (m_obj_file) { Symtab *symtab = m_obj_file->GetSymtab(); if (symtab) { @@ -3026,9 +3027,9 @@ size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) { size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { ASSERT_MODULE_LOCK(this); - if (sc.comp_unit != NULL) { + if (sc.comp_unit != nullptr) { DWARFDebugInfo *info = DebugInfo(); - if (info == NULL) + if (info == nullptr) return 0; if (sc.function) { @@ -3047,13 +3048,13 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { } else if (sc.comp_unit) { DWARFUnit *dwarf_cu = info->GetUnitAtIndex(sc.comp_unit->GetID()); - if (dwarf_cu == NULL) + if (dwarf_cu == nullptr) return 0; uint32_t vars_added = 0; VariableListSP variables(sc.comp_unit->GetVariableList(false)); - if (variables.get() == NULL) { + if (variables.get() == nullptr) { variables = std::make_shared(); sc.comp_unit->SetVariableList(variables); @@ -3105,8 +3106,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, const size_t num_attributes = die.GetAttributes(attributes); DWARFDIE spec_die; if (num_attributes > 0) { - const char *name = NULL; - const char *mangled = NULL; + const char *name = nullptr; + const char *mangled = nullptr; Declaration decl; uint32_t i; DWARFFormValue type_die_form; @@ -3288,7 +3289,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, ValueType scope = eValueTypeInvalid; const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die); - SymbolContextScope *symbol_context_scope = NULL; + SymbolContextScope *symbol_context_scope = nullptr; bool has_explicit_mangled = mangled != nullptr; if (!mangled) { @@ -3334,7 +3335,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (op_error) { StreamString strm; location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0, - NULL); + nullptr); GetObjectFile()->GetModule()->ReportError( "0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetData()); @@ -3437,7 +3438,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, } } - if (symbol_context_scope == NULL) { + if (symbol_context_scope == nullptr) { switch (parent_tag) { case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: @@ -3445,7 +3446,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (sc.function) { symbol_context_scope = sc.function->GetBlock(true).FindBlockByID( sc_parent_die.GetID()); - if (symbol_context_scope == NULL) + if (symbol_context_scope == nullptr) symbol_context_scope = sc.function; } break; @@ -3557,15 +3558,15 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, // We haven't already parsed it, lets do that now. if ((tag == DW_TAG_variable) || (tag == DW_TAG_constant) || (tag == DW_TAG_formal_parameter && sc.function)) { - if (variable_list_sp.get() == NULL) { + if (variable_list_sp.get() == nullptr) { DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die); dw_tag_t parent_tag = sc_parent_die.Tag(); switch (parent_tag) { case DW_TAG_compile_unit: case DW_TAG_partial_unit: - if (sc.comp_unit != NULL) { + if (sc.comp_unit != nullptr) { variable_list_sp = sc.comp_unit->GetVariableList(false); - if (variable_list_sp.get() == NULL) { + if (variable_list_sp.get() == nullptr) { variable_list_sp = std::make_shared(); } } else { @@ -3581,13 +3582,13 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: case DW_TAG_lexical_block: - if (sc.function != NULL) { + if (sc.function != nullptr) { // Check to see if we already have parsed the variables for the // given scope Block *block = sc.function->GetBlock(true).FindBlockByID( sc_parent_die.GetID()); - if (block == NULL) { + if (block == nullptr) { // This must be a specification or abstract origin with a // concrete block counterpart in the current function. We need // to find the concrete block so we can correctly add the @@ -3601,10 +3602,10 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, concrete_block_die.GetID()); } - if (block != NULL) { + if (block != nullptr) { const bool can_create = false; variable_list_sp = block->GetBlockVariableList(can_create); - if (variable_list_sp.get() == NULL) { + if (variable_list_sp.get() == nullptr) { variable_list_sp = std::make_shared(); block->SetVariableList(variable_list_sp); } @@ -3633,7 +3634,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, } } - bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram); + bool skip_children = (sc.function == nullptr && tag == DW_TAG_subprogram); if (!skip_children && parse_children && die.HasChildren()) { vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, @@ -3718,7 +3719,7 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { } SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { - if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) { + if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 426719bf0b293..d3272454d0a5e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -364,7 +364,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile, const DWARFDIE &orig_die, const lldb::addr_t func_low_pc, bool parse_siblings, bool parse_children, - lldb_private::VariableList *cc_variable_list = NULL); + lldb_private::VariableList *cc_variable_list = nullptr); bool ClassOrStructIsVirtual(const DWARFDIE &die); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index e5bc63b3cb85b..8ec64dbaf7641 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -175,7 +175,7 @@ class DebugMapModule : public Module { SymbolVendor * GetSymbolVendor(bool can_create = true, - lldb_private::Stream *feedback_strm = NULL) override { + lldb_private::Stream *feedback_strm = nullptr) override { // Scope for locker if (m_symfile_up.get() || !can_create) return m_symfile_up.get(); @@ -197,7 +197,7 @@ class DebugMapModule : public Module { symbol_vendor->GetSymbolFile()); if (!oso_symfile) - return NULL; + return nullptr; ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor(); @@ -213,7 +213,7 @@ class DebugMapModule : public Module { } } } - return NULL; + return nullptr; } protected: @@ -368,12 +368,12 @@ void SymbolFileDWARFDebugMap::InitOSO() { oso_symbol->GetName().GetCString()); } } else { - if (oso_symbol == NULL) + if (oso_symbol == nullptr) m_obj_file->GetModule()->ReportError( "N_OSO symbol[%u] can't be found, please file a bug and attach " "the binary listed in this error", oso_idx); - else if (so_symbol == NULL) + else if (so_symbol == nullptr) m_obj_file->GetModule()->ReportError( "N_SO not found for N_OSO symbol[%u], please file a bug and " "attach the binary listed in this error", @@ -398,7 +398,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) { const uint32_t cu_count = GetNumCompileUnits(); if (oso_idx < cu_count) return GetModuleByCompUnitInfo(&m_compile_unit_infos[oso_idx]); - return NULL; + return nullptr; } Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( @@ -428,7 +428,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( ") since this executable was linked, file will be ignored", oso_file.GetPath().c_str(), llvm::to_string(oso_mod_time).c_str(), llvm::to_string(comp_unit_info->oso_mod_time).c_str()); - return NULL; + return nullptr; } } else { @@ -436,7 +436,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( if (!ObjectFile::SplitArchivePathWithObject(oso_path, oso_file, oso_object, must_exist)) { - return NULL; + return nullptr; } } // Always create a new module for .o files. Why? Because we use the debug @@ -462,7 +462,7 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo( } if (comp_unit_info->oso_sp) return comp_unit_info->oso_sp->module_sp.get(); - return NULL; + return nullptr; } bool SymbolFileDWARFDebugMap::GetFileSpecForSO(uint32_t oso_idx, @@ -480,7 +480,7 @@ ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx) { Module *oso_module = GetModuleByOSOIndex(oso_idx); if (oso_module) return oso_module->GetObjectFile(); - return NULL; + return nullptr; } SymbolFileDWARF * @@ -493,7 +493,7 @@ SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit &comp_unit) { CompileUnitInfo *comp_unit_info = GetCompUnitInfo(comp_unit); if (comp_unit_info) return GetSymbolFileByCompUnitInfo(comp_unit_info); - return NULL; + return nullptr; } ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo( @@ -501,7 +501,7 @@ ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo( Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info); if (oso_module) return oso_module->GetObjectFile(); - return NULL; + return nullptr; } uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex( @@ -521,7 +521,7 @@ SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) { unsigned size = m_compile_unit_infos.size(); if (oso_idx < size) return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]); - return NULL; + return nullptr; } SymbolFileDWARF * @@ -529,7 +529,7 @@ SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) { if (sym_file && sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic()) return (SymbolFileDWARF *)sym_file; - return NULL; + return nullptr; } SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( @@ -540,7 +540,7 @@ SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo( if (sym_vendor) return GetSymbolFileAsSymbolFileDWARF(sym_vendor->GetSymbolFile()); } - return NULL; + return nullptr; } uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() { @@ -609,7 +609,7 @@ SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) { if (comp_unit == m_compile_unit_infos[i].compile_unit_sp.get()) return &m_compile_unit_infos[i]; } - return NULL; + return nullptr; } size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule( @@ -706,7 +706,7 @@ Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (oso_dwarf) return oso_dwarf->ResolveTypeUID(type_uid); - return NULL; + return nullptr; } llvm::Optional @@ -750,7 +750,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, sc.symbol = symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex()); - if (sc.symbol != NULL) { + if (sc.symbol != nullptr) { resolved_flags |= eSymbolContextSymbol; uint32_t oso_idx = 0; @@ -930,7 +930,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo * SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex( uint32_t symbol_idx, uint32_t *oso_idx_ptr) { const uint32_t oso_index_count = m_compile_unit_infos.size(); - CompileUnitInfo *comp_unit_info = NULL; + CompileUnitInfo *comp_unit_info = nullptr; if (oso_index_count) { comp_unit_info = (CompileUnitInfo *)bsearch( &symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(), @@ -939,7 +939,7 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex( } if (oso_idx_ptr) { - if (comp_unit_info != NULL) + if (comp_unit_info != nullptr) *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0]; else *oso_idx_ptr = UINT32_MAX; @@ -951,7 +951,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo * SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID( user_id_t symbol_id, uint32_t *oso_idx_ptr) { const uint32_t oso_index_count = m_compile_unit_infos.size(); - CompileUnitInfo *comp_unit_info = NULL; + CompileUnitInfo *comp_unit_info = nullptr; if (oso_index_count) { comp_unit_info = (CompileUnitInfo *)::bsearch( &symbol_id, &m_compile_unit_infos[0], m_compile_unit_infos.size(), @@ -960,7 +960,7 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID( } if (oso_idx_ptr) { - if (comp_unit_info != NULL) + if (comp_unit_info != nullptr) *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0]; else *oso_idx_ptr = UINT32_MAX; @@ -1058,7 +1058,7 @@ size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope, type_mask); uint32_t initial_size = type_list.GetSize(); - SymbolFileDWARF *oso_dwarf = NULL; + SymbolFileDWARF *oso_dwarf = nullptr; if (sc_scope) { SymbolContext sc; sc_scope->CalculateSymbolContext(&sc); @@ -1103,7 +1103,7 @@ bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type( m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo; ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { if (skip_dwarf_oso != oso_dwarf && - oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(NULL)) { + oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) { m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes; return true; } @@ -1122,7 +1122,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( // contain the implementation definition since it will be scoped inside the // N_SO and we can then locate the SymbolFileDWARF that corresponds to that // N_SO. - SymbolFileDWARF *oso_dwarf = NULL; + SymbolFileDWARF *oso_dwarf = nullptr; TypeSP type_sp; ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile(); if (module_objfile) { @@ -1143,7 +1143,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( if (source_file_symbol_idx != UINT32_MAX) { CompileUnitInfo *compile_unit_info = GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx, - NULL); + nullptr); if (compile_unit_info) { oso_dwarf = GetSymbolFileByCompUnitInfo(compile_unit_info); if (oso_dwarf) { @@ -1268,7 +1268,7 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf) { } } } - return NULL; + return nullptr; } void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf, @@ -1414,7 +1414,7 @@ LineTable *SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF *oso_dwarf, CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_dwarf); if (cu_info) return line_table->LinkLineTable(cu_info->GetFileRangeMap(this)); - return NULL; + return nullptr; } size_t diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 0f5262d2f4542..8da7e22262664 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -39,12 +39,12 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, case DW_TAG_namespace: { const char *parent_arg_die_name = parent_arg_die.GetName(); if (parent_arg_die_name == - NULL) // Anonymous (i.e. no-name) struct + nullptr) // Anonymous (i.e. no-name) struct { match = false; } else { const char *parent_pos_die_name = parent_pos_die.GetName(); - if (parent_pos_die_name == NULL || + if (parent_pos_die_name == nullptr || ((parent_arg_die_name != parent_pos_die_name) && strcmp(parent_arg_die_name, parent_pos_die_name))) match = false; diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 7fa3a1c5d6509..a1b21e51b0fe5 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -139,8 +139,8 @@ size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { size_t num_added = 0; // We must at least have a valid compile unit const Symtab *symtab = m_obj_file->GetSymtab(); - const Symbol *curr_symbol = NULL; - const Symbol *next_symbol = NULL; + const Symbol *curr_symbol = nullptr; + const Symbol *next_symbol = nullptr; // const char *prefix = m_obj_file->SymbolPrefix(); // if (prefix == NULL) // prefix == ""; @@ -188,10 +188,10 @@ size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) { LLDB_INVALID_UID, // We don't have any type info // for this function curr_symbol->GetMangled(), // Linker/mangled name - NULL, // no return type for a code symbol... + nullptr, // no return type for a code symbol... func_range)); // first address range - if (func_sp.get() != NULL) { + if (func_sp.get() != nullptr) { comp_unit.AddFunction(func_sp); ++num_added; } @@ -230,7 +230,7 @@ size_t SymbolFileSymtab::ParseVariablesForContext(const SymbolContext &sc) { } Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) { - return NULL; + return nullptr; } llvm::Optional @@ -246,7 +246,7 @@ bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) { uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr, SymbolContextItem resolve_scope, SymbolContext &sc) { - if (m_obj_file->GetSymtab() == NULL) + if (m_obj_file->GetSymtab() == nullptr) return 0; uint32_t resolved_flags = 0; diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index 1efbeab934c44..f279af61a1315 100644 --- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -59,20 +59,20 @@ SymbolVendor * SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm) { if (!module_sp) - return NULL; + return nullptr; ObjectFile *obj_file = module_sp->GetObjectFile(); if (!obj_file) - return NULL; + return nullptr; static ConstString obj_file_elf("elf"); ConstString obj_name = obj_file->GetPluginName(); if (obj_name != obj_file_elf) - return NULL; + return nullptr; lldb_private::UUID uuid = obj_file->GetUUID(); if (!uuid) - return NULL; + return nullptr; // Get the .gnu_debuglink file (if specified). FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths(); @@ -84,7 +84,7 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, // If we have no debug symbol files, then nothing to do. if (file_spec_list.IsEmpty()) - return NULL; + return nullptr; static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "SymbolVendorELF::CreateInstance (module = %s)", @@ -153,7 +153,7 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp, } } } - return NULL; + return nullptr; } // PluginInterface protocol diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp index 00b2826e1f021..c97eb98557a79 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp @@ -143,7 +143,7 @@ lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction( // function: if (!m_get_item_info_impl_code) { - if (g_get_item_info_function_code != NULL) { + if (g_get_item_info_function_code != nullptr) { Status error; m_get_item_info_impl_code.reset( exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp index ddd3cb5d7cbae..12fad7f561b03 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp @@ -147,7 +147,7 @@ lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction( // First stage is to make the ClangUtility to hold our injected function: if (!m_get_pending_items_impl_code) { - if (g_get_pending_items_function_code != NULL) { + if (g_get_pending_items_function_code != nullptr) { Status error; m_get_pending_items_impl_code.reset( exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( @@ -347,7 +347,7 @@ AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue, options.SetIsForUtilityExpr(true); thread.CalculateExecutionContext(exe_ctx); - if (get_pending_items_caller == NULL) { + if (get_pending_items_caller == nullptr) { error.SetErrorString("Unable to compile function to call " "__introspection_dispatch_queue_get_pending_items"); return return_value; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp index 2b6c553dd435e..e1dabae0d587a 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp @@ -158,7 +158,7 @@ AppleGetQueuesHandler::SetupGetQueuesFunction(Thread &thread, // First stage is to make the ClangUtility to hold our injected function: if (!m_get_queues_impl_code_up) { - if (g_get_current_queues_function_code != NULL) { + if (g_get_current_queues_function_code != nullptr) { Status error; m_get_queues_impl_code_up.reset( exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( @@ -335,7 +335,7 @@ AppleGetQueuesHandler::GetCurrentQueues(Thread &thread, addr_t page_to_free, FunctionCaller *get_queues_caller = m_get_queues_impl_code_up->GetFunctionCaller(); - if (get_queues_caller == NULL) { + if (get_queues_caller == nullptr) { error.SetErrorString( "Unable to get caller for call __introspection_dispatch_get_queues"); return return_value; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp index f409b674c531e..7d0cbc0c100b4 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -154,7 +154,7 @@ lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction( if (!m_get_thread_item_info_impl_code) { Status error; - if (g_get_thread_item_info_function_code != NULL) { + if (g_get_thread_item_info_function_code != nullptr) { m_get_thread_item_info_impl_code.reset( exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( g_get_thread_item_info_function_code, eLanguageTypeC, diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp index 82be85699b2c3..91a60b17fc9b0 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -70,7 +70,7 @@ SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) { if (create) return new SystemRuntimeMacOSX(process); - return NULL; + return nullptr; } // Constructor @@ -106,7 +106,7 @@ void SystemRuntimeMacOSX::Clear(bool clear_process) { m_process->ClearBreakpointSiteByID(m_break_id); if (clear_process) - m_process = NULL; + m_process = nullptr; m_break_id = LLDB_INVALID_BREAK_ID; } @@ -266,7 +266,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() { static ConstString g_dispatch_queue_offsets_symbol_name( "dispatch_queue_offsets"); - const Symbol *dispatch_queue_offsets_symbol = NULL; + const Symbol *dispatch_queue_offsets_symbol = nullptr; // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 // ("Snow Leopard") @@ -279,7 +279,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() { // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") // and later - if (dispatch_queue_offsets_symbol == NULL) { + if (dispatch_queue_offsets_symbol == nullptr) { ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib")); module_sp = m_process->GetTarget().GetImages().FindFirstModule( libdispatch_module_spec); @@ -322,7 +322,7 @@ void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() { static ConstString g_libpthread_layout_offsets_symbol_name( "pthread_layout_offsets"); - const Symbol *libpthread_layout_offsets_symbol = NULL; + const Symbol *libpthread_layout_offsets_symbol = nullptr; ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib")); ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( @@ -370,7 +370,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() { static ConstString g_libdispatch_tsd_indexes_symbol_name( "dispatch_tsd_indexes"); - const Symbol *libdispatch_tsd_indexes_symbol = NULL; + const Symbol *libdispatch_tsd_indexes_symbol = nullptr; ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib")); ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( @@ -726,7 +726,8 @@ void SystemRuntimeMacOSX::PopulateQueueList( for (ThreadSP thread_sp : m_process->Threads()) { if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) { if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) { - if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() == NULL) { + if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() == + nullptr) { QueueSP queue_sp(new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName())); @@ -933,7 +934,7 @@ void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR( offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset; const char *queue_label = extractor.GetCStr(&offset); - if (queue_label == NULL) + if (queue_label == nullptr) queue_label = ""; offset_t start_of_next_item = start_of_this_item + offset_to_next; diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 70c1318218304..4aa9fb634b61a 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -67,8 +67,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( const bool prefer_file_cache = true; DisassemblerSP disasm_sp(Disassembler::DisassembleBytes( - m_arch, NULL, NULL, range.GetBaseAddress(), opcode_data, opcode_size, - 99999, prefer_file_cache)); + m_arch, nullptr, nullptr, range.GetBaseAddress(), opcode_data, + opcode_size, 99999, prefer_file_cache)); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); @@ -213,7 +213,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( lldb_private::FormatEntity::Entry format; FormatEntity::Parse("${frame.pc}: ", format); inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize(), show_address, - show_bytes, NULL, NULL, NULL, &format, 0); + show_bytes, nullptr, nullptr, nullptr, &format, 0); log->PutString(strm.GetString()); } @@ -296,11 +296,11 @@ UnwindAssembly * UnwindAssemblyInstEmulation::CreateInstance(const ArchSpec &arch) { std::unique_ptr inst_emulator_up( EmulateInstruction::FindPlugin(arch, eInstructionTypePrologueEpilogue, - NULL)); + nullptr)); // Make sure that all prologue instructions are handled if (inst_emulator_up) return new UnwindAssemblyInstEmulation(arch, inst_emulator_up.release()); - return NULL; + return nullptr; } // PluginInterface protocol in UnwindAssemblyParser_x86 diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h index 5232d08332192..9125bd5b1fe3c 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h @@ -65,7 +65,7 @@ class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly { UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch, lldb_private::EmulateInstruction *inst_emulator) : UnwindAssembly(arch), m_inst_emulator_up(inst_emulator), - m_range_ptr(NULL), m_unwind_plan_ptr(NULL), m_curr_row(), + m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), m_curr_row(), m_cfa_reg_info(), m_fp_is_cfa(false), m_register_values(), m_pushed_regs(), m_curr_row_modified(false), m_forward_branch_offset(0) { diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index 2157855009d28..ce168f0210471 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -239,7 +239,7 @@ UnwindAssembly *UnwindAssembly_x86::CreateInstance(const ArchSpec &arch) { const llvm::Triple::ArchType cpu = arch.GetMachine(); if (cpu == llvm::Triple::x86 || cpu == llvm::Triple::x86_64) return new UnwindAssembly_x86(arch); - return NULL; + return nullptr; } // PluginInterface protocol in UnwindAssemblyParser_x86 diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 72a33739245cf..62321d135646e 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -6894,7 +6894,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( } else { child_is_deref_of_parent = true; const char *parent_name = - valobj ? valobj->GetName().GetCString() : NULL; + valobj ? valobj->GetName().GetCString() : nullptr; if (parent_name) { child_name.assign(1, '*'); child_name += parent_name; @@ -6975,7 +6975,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( child_is_deref_of_parent = true; const char *parent_name = - valobj ? valobj->GetName().GetCString() : NULL; + valobj ? valobj->GetName().GetCString() : nullptr; if (parent_name) { child_name.assign(1, '*'); child_name += parent_name; @@ -7012,7 +7012,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( language_flags); } else { const char *parent_name = - valobj ? valobj->GetName().GetCString() : NULL; + valobj ? valobj->GetName().GetCString() : nullptr; if (parent_name) { child_name.assign(1, '&'); child_name += parent_name; @@ -7842,7 +7842,7 @@ clang::EnumDecl *ClangASTContext::GetAsEnumDecl(const CompilerType &type) { llvm::dyn_cast(ClangUtil::GetCanonicalQualType(type)); if (enutype) return enutype->getDecl(); - return NULL; + return nullptr; } clang::RecordDecl *ClangASTContext::GetAsRecordDecl(const CompilerType &type) { @@ -8261,7 +8261,7 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( if (is_attr_used) cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext())); - if (mangled_name != NULL) { + if (mangled_name != nullptr) { cxx_method_decl->addAttr( clang::AsmLabelAttr::CreateImplicit(*getASTContext(), mangled_name)); } @@ -9868,7 +9868,7 @@ clang::ClassTemplateDecl *ClangASTContext::ParseClassTemplateDecl( template_basename.c_str(), tag_decl_kind, template_param_infos); } - return NULL; + return nullptr; } void ClangASTContext::CompleteTagDecl(void *baton, clang::TagDecl *decl) { diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp index fa37ba316cf8b..3a9a8f3c4cd83 100644 --- a/lldb/source/Symbol/ClangASTImporter.cpp +++ b/lldb/source/Symbol/ClangASTImporter.cpp @@ -346,7 +346,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) { const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); if (cxx_record_decl) { - if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) + if (ResolveDeclOrigin(cxx_record_decl, nullptr, nullptr)) return true; } } break; @@ -355,7 +355,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) { clang::EnumDecl *enum_decl = llvm::cast(qual_type)->getDecl(); if (enum_decl) { - if (ResolveDeclOrigin(enum_decl, NULL, NULL)) + if (ResolveDeclOrigin(enum_decl, nullptr, nullptr)) return true; } } break; @@ -370,7 +370,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) { // We currently can't complete objective C types through the newly added // ASTContext because it only supports TagDecl objects right now... if (class_interface_decl) { - if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) + if (ResolveDeclOrigin(class_interface_decl, nullptr, nullptr)) return true; } } @@ -422,7 +422,7 @@ bool ClangASTImporter::Import(const CompilerType &type) { const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); if (cxx_record_decl) { - if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) + if (ResolveDeclOrigin(cxx_record_decl, nullptr, nullptr)) return CompleteAndFetchChildren(qual_type); } } break; @@ -431,7 +431,7 @@ bool ClangASTImporter::Import(const CompilerType &type) { clang::EnumDecl *enum_decl = llvm::cast(qual_type)->getDecl(); if (enum_decl) { - if (ResolveDeclOrigin(enum_decl, NULL, NULL)) + if (ResolveDeclOrigin(enum_decl, nullptr, nullptr)) return CompleteAndFetchChildren(qual_type); } } break; @@ -446,7 +446,7 @@ bool ClangASTImporter::Import(const CompilerType &type) { // We currently can't complete objective C types through the newly added // ASTContext because it only supports TagDecl objects right now... if (class_interface_decl) { - if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) + if (ResolveDeclOrigin(class_interface_decl, nullptr, nullptr)) return CompleteAndFetchChildren(qual_type); } } diff --git a/lldb/source/Symbol/CompactUnwindInfo.cpp b/lldb/source/Symbol/CompactUnwindInfo.cpp index d2e176b141f22..3a2a4d3a09e62 100644 --- a/lldb/source/Symbol/CompactUnwindInfo.cpp +++ b/lldb/source/Symbol/CompactUnwindInfo.cpp @@ -186,7 +186,7 @@ bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr, if (log && log->GetVerbose()) { StreamString strm; addr.Dump( - &strm, NULL, + &strm, nullptr, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index a727568d75b13..98061d2d33439 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -995,7 +995,7 @@ bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx, return false; auto byte_size = - GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); if (!byte_size) return false; @@ -1040,7 +1040,7 @@ bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx, return false; auto byte_size = - GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); if (!byte_size) return false; diff --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp index 033594bae350b..bfdb6e705f4a0 100644 --- a/lldb/source/Symbol/LocateSymbolFile.cpp +++ b/lldb/source/Symbol/LocateSymbolFile.cpp @@ -55,9 +55,10 @@ static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec, bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); UNUSED_IF_ASSERT_DISABLED(got_spec); assert(got_spec); - if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && - (arch == NULL || (spec.GetArchitecturePtr() && - spec.GetArchitecture().IsCompatibleMatch(*arch)))) { + if ((uuid == nullptr || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && + (arch == nullptr || + (spec.GetArchitecturePtr() && + spec.GetArchitecture().IsCompatibleMatch(*arch)))) { return true; } } diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index 187a7b17215ab..1b7b3ce54865b 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -501,7 +501,7 @@ bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc, } #ifdef LLDB_CONFIGURATION_DEBUG else { - ObjectFile *objfile = NULL; + ObjectFile *objfile = nullptr; if (module_sp) { SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); if (symbol_vendor) { diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index 4670d7738c3af..f5861c291f2f6 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -1149,5 +1149,5 @@ const Symbol *Symtab::GetParent(Symbol *child_symbol) const { return symbol; } } - return NULL; + return nullptr; } diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 35c1a265f829e..4ee8330ce288f 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -978,7 +978,7 @@ TypeSystem *TypeImpl::GetTypeSystem(bool prefer_dynamic) { } return m_static_type.GetTypeSystem(); } - return NULL; + return nullptr; } bool TypeImpl::GetDescription(lldb_private::Stream &strm, diff --git a/lldb/source/Target/CPPLanguageRuntime.cpp b/lldb/source/Target/CPPLanguageRuntime.cpp index ef1202170052c..70e5aee3e45b1 100644 --- a/lldb/source/Target/CPPLanguageRuntime.cpp +++ b/lldb/source/Target/CPPLanguageRuntime.cpp @@ -214,7 +214,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( return llvm::Regex::escape(first_template_parameter.str()) + R"(::operator\(\)\(.*\))"; - if (symbol != NULL && + if (symbol != nullptr && symbol->GetName().GetStringRef().contains("__invoke")) { llvm::StringRef symbol_name = symbol->GetName().GetStringRef(); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 2be3774d076a8..b018a3115a026 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1425,7 +1425,7 @@ Status Process::ResumeSynchronous(Stream *stream) { Status error = PrivateResume(); if (error.Success()) { StateType state = - WaitForProcessToStop(llvm::None, NULL, true, listener_sp, stream); + WaitForProcessToStop(llvm::None, nullptr, true, listener_sp, stream); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) @@ -3638,7 +3638,7 @@ void Process::ControlPrivateStateThread(uint32_t signal) { } if (signal == eBroadcastInternalStateControlStop) { - thread_result_t result = NULL; + thread_result_t result = nullptr; m_private_state_thread.Join(&result); m_private_state_thread.Reset(); } @@ -3913,7 +3913,7 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { // it was doing yet, so don't try to change it on the way out. if (!is_secondary_thread) m_public_run_lock.SetStopped(); - return NULL; + return nullptr; } // Process Event Data diff --git a/lldb/source/Target/SectionLoadHistory.cpp b/lldb/source/Target/SectionLoadHistory.cpp index 391a6c22f7f58..ec16b58b4451c 100644 --- a/lldb/source/Target/SectionLoadHistory.cpp +++ b/lldb/source/Target/SectionLoadHistory.cpp @@ -97,7 +97,7 @@ SectionLoadList &SectionLoadHistory::GetCurrentSectionLoadList() { std::lock_guard guard(m_mutex); SectionLoadList *section_load_list = GetSectionLoadListForStopID(eStopIDNow, read_only); - assert(section_load_list != NULL); + assert(section_load_list != nullptr); return *section_load_list; } diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index 8f0ab34dbd1ec..6db0c2b037e9b 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -1196,7 +1196,7 @@ StopInfo::GetCrashingDereference(StopInfoSP &stop_info_sp, address_loc += (sizeof(address_string) - 1); - uint64_t address = strtoull(address_loc, 0, 0); + uint64_t address = strtoull(address_loc, nullptr, 0); if (crashing_address) { *crashing_address = address; } diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index 111c5b4f6114b..a0b7072a10719 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -130,7 +130,7 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( "Queueing StepInRange plan to step through line 0 code."); return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange( - false, range, sc, NULL, eOnlyDuringStepping, status, + false, range, sc, nullptr, eOnlyDuringStepping, status, eLazyBoolCalculate, eLazyBoolNo); } } diff --git a/lldb/tools/lldb-mi/MICmdCmdExec.cpp b/lldb/tools/lldb-mi/MICmdCmdExec.cpp index fd13a919242bd..ffdf171aef08a 100644 --- a/lldb/tools/lldb-mi/MICmdCmdExec.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdExec.cpp @@ -983,13 +983,13 @@ bool CMICmdCmdExecArguments::Execute() { } lldb::SBLaunchInfo sbLaunchInfo = sbTarget.GetLaunchInfo(); - sbLaunchInfo.SetArguments(NULL, false); + sbLaunchInfo.SetArguments(nullptr, false); CMIUtilString strArg; size_t nArgIndex = 0; while (pArgArguments->GetExpectedOption( strArg, nArgIndex)) { - const char *argv[2] = {strArg.c_str(), NULL}; + const char *argv[2] = {strArg.c_str(), nullptr}; sbLaunchInfo.SetArguments(argv, true); ++nArgIndex; } diff --git a/lldb/tools/lldb-mi/MICmdCmdTarget.cpp b/lldb/tools/lldb-mi/MICmdCmdTarget.cpp index b3e0beac8d47b..18ce038b16858 100644 --- a/lldb/tools/lldb-mi/MICmdCmdTarget.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdTarget.cpp @@ -265,7 +265,7 @@ bool CMICmdCmdTargetAttach::Execute() { // If the current target is invalid, create one lldb::SBTarget target = rSessionInfo.GetTarget(); if (!target.IsValid()) { - target = rSessionInfo.GetDebugger().CreateTarget(NULL); + target = rSessionInfo.GetDebugger().CreateTarget(nullptr); if (!target.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); diff --git a/lldb/tools/lldb-mi/MICmnBase.cpp b/lldb/tools/lldb-mi/MICmnBase.cpp index 72096d56febec..9d87064aa64cf 100644 --- a/lldb/tools/lldb-mi/MICmnBase.cpp +++ b/lldb/tools/lldb-mi/MICmnBase.cpp @@ -32,7 +32,7 @@ CMICmnBase::CMICmnBase() // Return: None. // Throws: None. //-- -CMICmnBase::~CMICmnBase() { m_pLog = NULL; } +CMICmnBase::~CMICmnBase() { m_pLog = nullptr; } //++ // Details: Retrieve whether *this object has an error description set. diff --git a/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp b/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp index 6cef283512809..59856a6f165e7 100644 --- a/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp +++ b/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp @@ -53,7 +53,7 @@ MapOutOfBandToText(CMICmnMIOutOfBandRecord::OutOfBand_e veType) { return ""; } assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e"); - return NULL; + return nullptr; } static const char * @@ -95,7 +95,7 @@ MapOutOfBandToToken(CMICmnMIOutOfBandRecord::OutOfBand_e veType) { return "&"; } assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e"); - return NULL; + return nullptr; } //++ diff --git a/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp b/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp index 00d1ce13d3457..93bb5a60ec3dc 100644 --- a/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp +++ b/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp @@ -34,7 +34,7 @@ MapResultClassToResultClassText(CMICmnMIResultRecord::ResultClass_e veType) { return "exit"; } assert(false && "unknown CMICmnMIResultRecord::ResultClass_e"); - return NULL; + return nullptr; } //++ diff --git a/lldb/tools/lldb-mi/MIDriver.cpp b/lldb/tools/lldb-mi/MIDriver.cpp index 02361f4ccb97d..3bf888e303d41 100644 --- a/lldb/tools/lldb-mi/MIDriver.cpp +++ b/lldb/tools/lldb-mi/MIDriver.cpp @@ -51,7 +51,7 @@ const CMIUtilString CMIDriver::ms_constAppNameLong(MIRSRC(IDS_MI_APPNAME_LONG)); //-- CMIDriver::CMIDriver() : m_bFallThruToOtherDriverEnabled(false), m_bDriverIsExiting(false), - m_handleMainThread(0), m_rStdin(CMICmnStreamStdin::Instance()), + m_handleMainThread(nullptr), m_rStdin(CMICmnStreamStdin::Instance()), m_rLldbDebugger(CMICmnLLDBDebugger::Instance()), m_rStdOut(CMICmnStreamStdout::Instance()), m_eCurrentDriverState(eDriverState_NotRunning), @@ -737,7 +737,7 @@ FILE *CMIDriver::GetStdout() const { // available before *this driver has been initialized! Flaw? // Do not want to pass through driver to write to stdout - return NULL; + return nullptr; } //++ diff --git a/lldb/tools/lldb-mi/MIDriverBase.cpp b/lldb/tools/lldb-mi/MIDriverBase.cpp index 9958770ff42d0..b8844e288430f 100644 --- a/lldb/tools/lldb-mi/MIDriverBase.cpp +++ b/lldb/tools/lldb-mi/MIDriverBase.cpp @@ -30,7 +30,7 @@ CMIDriverBase::CMIDriverBase() // Return: None. // Throws: None. //-- -CMIDriverBase::~CMIDriverBase() { m_pDriverFallThru = NULL; } +CMIDriverBase::~CMIDriverBase() { m_pDriverFallThru = nullptr; } //++ // Details: This function allows *this driver to call on another driver to diff --git a/lldb/tools/lldb-mi/MIDriverMgr.cpp b/lldb/tools/lldb-mi/MIDriverMgr.cpp index 26c4add8e3f9d..26195cdb74141 100644 --- a/lldb/tools/lldb-mi/MIDriverMgr.cpp +++ b/lldb/tools/lldb-mi/MIDriverMgr.cpp @@ -135,7 +135,7 @@ bool CMIDriverMgr::UnregisterDriverAll() { } m_mapDriverIdToDriver.clear(); - m_pDriverCurrent = NULL; + m_pDriverCurrent = nullptr; return MIstatus::success; } diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index a0bc5f2c68ea9..b479c2197bffa 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -87,22 +87,22 @@ static int g_verbose = 0; static struct option g_long_options[] = { {"debug", no_argument, &g_debug, 1}, {"verbose", no_argument, &g_verbose, 1}, - {"log-file", required_argument, NULL, 'l'}, - {"log-channels", required_argument, NULL, 'c'}, - {"attach", required_argument, NULL, 'a'}, - {"named-pipe", required_argument, NULL, 'N'}, - {"pipe", required_argument, NULL, 'U'}, - {"native-regs", no_argument, NULL, + {"log-file", required_argument, nullptr, 'l'}, + {"log-channels", required_argument, nullptr, 'c'}, + {"attach", required_argument, nullptr, 'a'}, + {"named-pipe", required_argument, nullptr, 'N'}, + {"pipe", required_argument, nullptr, 'U'}, + {"native-regs", no_argument, nullptr, 'r'}, // Specify to use the native registers instead of the gdb defaults // for the architecture. NOTE: this is a do-nothing arg as it's // behavior is default now. FIXME remove call from lldb-platform. - {"reverse-connect", no_argument, NULL, + {"reverse-connect", no_argument, nullptr, 'R'}, // Specifies that llgs attaches to the client address:port rather // than llgs listening for a connection from address on port. - {"setsid", no_argument, NULL, + {"setsid", no_argument, nullptr, 'S'}, // Call setsid() to make llgs run in its own session. - {"fd", required_argument, NULL, 'F'}, - {NULL, 0, NULL, 0}}; + {"fd", required_argument, nullptr, 'F'}, + {nullptr, 0, nullptr, 0}}; // Watch for signals static int g_sighup_received_count = 0; diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index 595a0e82da205..af78f624073e2 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -48,16 +48,16 @@ static int g_server = 0; static struct option g_long_options[] = { {"debug", no_argument, &g_debug, 1}, {"verbose", no_argument, &g_verbose, 1}, - {"log-file", required_argument, NULL, 'l'}, - {"log-channels", required_argument, NULL, 'c'}, - {"listen", required_argument, NULL, 'L'}, - {"port-offset", required_argument, NULL, 'p'}, - {"gdbserver-port", required_argument, NULL, 'P'}, - {"min-gdbserver-port", required_argument, NULL, 'm'}, - {"max-gdbserver-port", required_argument, NULL, 'M'}, - {"socket-file", required_argument, NULL, 'f'}, + {"log-file", required_argument, nullptr, 'l'}, + {"log-channels", required_argument, nullptr, 'c'}, + {"listen", required_argument, nullptr, 'L'}, + {"port-offset", required_argument, nullptr, 'p'}, + {"gdbserver-port", required_argument, nullptr, 'P'}, + {"min-gdbserver-port", required_argument, nullptr, 'm'}, + {"max-gdbserver-port", required_argument, nullptr, 'M'}, + {"socket-file", required_argument, nullptr, 'f'}, {"server", no_argument, &g_server, 1}, - {NULL, 0, NULL, 0}}; + {nullptr, 0, nullptr, 0}}; #if defined(__APPLE__) #define LOW_PORT (IPPORT_RESERVED) diff --git a/lldb/unittests/Utility/StringExtractorTest.cpp b/lldb/unittests/Utility/StringExtractorTest.cpp index 6a67a8c3a1505..b86e4660257ae 100644 --- a/lldb/unittests/Utility/StringExtractorTest.cpp +++ b/lldb/unittests/Utility/StringExtractorTest.cpp @@ -318,7 +318,7 @@ TEST_F(StringExtractorTest, GetHexBytes_Underflow) { ASSERT_EQ(UINT64_MAX, ex.GetFilePos()); ASSERT_EQ(false, ex.Empty()); ASSERT_EQ(0u, ex.GetBytesLeft()); - ASSERT_EQ(0, ex.Peek()); + ASSERT_EQ(nullptr, ex.Peek()); } TEST_F(StringExtractorTest, GetHexBytes_Partial) { diff --git a/lldb/unittests/tools/lldb-server/inferior/thread_inferior.cpp b/lldb/unittests/tools/lldb-server/inferior/thread_inferior.cpp index 79d5f91f340be..278b975dd91e5 100644 --- a/lldb/unittests/tools/lldb-server/inferior/thread_inferior.cpp +++ b/lldb/unittests/tools/lldb-server/inferior/thread_inferior.cpp @@ -28,7 +28,7 @@ int main(int argc, char* argv[]) { } // Cause a break. - volatile char *p = NULL; + volatile char *p = nullptr; *p = 'a'; delay.store(false); diff --git a/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp b/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp index 3cc0830dd3daf..de4c46b32b432 100644 --- a/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp +++ b/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp @@ -154,10 +154,10 @@ Expected RegisterInfoParser::create(StringRef Response) { LLDB_INVALID_REGNUM, // process plugin reg num LLDB_INVALID_REGNUM // native register number }, - NULL, - NULL, - NULL, // Dwarf expression opcode bytes pointer - 0 // Dwarf expression opcode bytes length + nullptr, + nullptr, + nullptr, // Dwarf expression opcode bytes pointer + 0 // Dwarf expression opcode bytes length }; Info.name = ConstString(Elements["name"]).GetCString(); if (!Info.name) diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h index e7cd370df6ff2..a05cf8130d3cf 100644 --- a/llvm/include/llvm/ADT/DenseMap.h +++ b/llvm/include/llvm/ADT/DenseMap.h @@ -63,7 +63,7 @@ struct DenseMapPair : public std::pair { template DenseMapPair(AltPairT &&AltPair, typename std::enable_if>::value>::type * = 0) + AltPairT, std::pair>::value>::type * = nullptr) : std::pair(std::forward(AltPair)) {} KeyT &getFirst() { return std::pair::first; } diff --git a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h index 6638cb8e721f9..dde9ae7bca636 100644 --- a/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h +++ b/llvm/include/llvm/Demangle/MicrosoftDemangleNodes.h @@ -513,7 +513,7 @@ struct NodeArrayNode : public Node { void output(OutputStream &OS, OutputFlags Flags, StringView Separator) const; - Node **Nodes = 0; + Node **Nodes = nullptr; size_t Count = 0; }; From 46165b24093af151bfa72ae6415a599635ad383f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 23 May 2019 11:27:28 +0000 Subject: [PATCH 0021/1176] [AMDGPU] Regenerate vector sub tests llvm-svn: 361485 --- llvm/test/CodeGen/AMDGPU/sub.v2i16.ll | 656 +++++++++++++++++++++----- 1 file changed, 525 insertions(+), 131 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/sub.v2i16.ll b/llvm/test/CodeGen/AMDGPU/sub.v2i16.ll index 442193f72295d..c7a08a6651156 100644 --- a/llvm/test/CodeGen/AMDGPU/sub.v2i16.ll +++ b/llvm/test/CodeGen/AMDGPU/sub.v2i16.ll @@ -1,16 +1,56 @@ -; RUN: llc -march=amdgcn -mcpu=gfx900 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GFX9,GFX89,GCN %s -; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=VI,GFX89,GCN %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -march=amdgcn -mcpu=gfx900 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck %s -enable-var-scope -check-prefixes=GCN,GFX89,GFX9 +; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck %s -enable-var-scope -check-prefixes=GCN,GFX89,VI ; FIXME: Need to handle non-uniform case for function below (load without gep). -; GCN-LABEL: {{^}}v_test_sub_v2i16: -; GFX89: {{flat|global}}_load_dword -; GFX89: {{flat|global}}_load_dword - -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} - -; VI-DAG: v_sub_u16_e32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} -; VI-DAG: v_sub_u16_sdwa v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 define amdgpu_kernel void @v_test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0, <2 x i16> addrspace(1)* %in1) #1 { +; GFX9-LABEL: v_test_sub_v2i16: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; GFX9-NEXT: s_mov_b32 s3, 0xf000 +; GFX9-NEXT: s_mov_b32 s2, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s6, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v3, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: global_load_dword v1, v[2:3], off +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, v1 +; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_mov_b32 s3, 0xf000 +; VI-NEXT: s_mov_b32 s2, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s7 +; VI-NEXT: v_add_u32_e32 v0, vcc, s6, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: flat_load_dword v1, v[2:3] +; VI-NEXT: s_mov_b32 s0, s4 +; VI-NEXT: s_mov_b32 s1, s5 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_sub_u16_e32 v2, v0, v1 +; VI-NEXT: v_sub_u16_sdwa v0, v0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: v_or_b32_e32 v0, v2, v0 +; VI-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -22,15 +62,46 @@ define amdgpu_kernel void @v_test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i ret void } -; GCN-LABEL: {{^}}s_test_sub_v2i16: -; GFX9: s_load_dword [[VAL0:s[0-9]+]] -; GFX9: s_load_dword [[VAL1:s[0-9]+]] -; GFX9: v_mov_b32_e32 [[VVAL1:v[0-9]+]] -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, [[VAL0]], [[VVAL1]] - -; VI: s_sub_i32 -; VI: s_sub_i32 define amdgpu_kernel void @s_test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(4)* %in0, <2 x i16> addrspace(4)* %in1) #1 { +; GFX9-LABEL: s_test_sub_v2i16: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; GFX9-NEXT: s_mov_b32 s3, 0xf000 +; GFX9-NEXT: s_mov_b32 s2, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dword s6, s[6:7], 0x0 +; GFX9-NEXT: s_load_dword s7, s[0:1], 0x0 +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, s7 +; GFX9-NEXT: v_pk_sub_i16 v0, s6, v0 +; GFX9-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: s_test_sub_v2i16: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; VI-NEXT: s_mov_b32 s3, 0xf000 +; VI-NEXT: s_mov_b32 s2, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_load_dword s6, s[6:7], 0x0 +; VI-NEXT: s_load_dword s7, s[0:1], 0x0 +; VI-NEXT: s_mov_b32 s0, s4 +; VI-NEXT: s_mov_b32 s1, s5 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_lshr_b32 s4, s6, 16 +; VI-NEXT: s_lshr_b32 s5, s7, 16 +; VI-NEXT: s_sub_i32 s4, s4, s5 +; VI-NEXT: s_sub_i32 s6, s6, s7 +; VI-NEXT: s_and_b32 s5, s6, 0xffff +; VI-NEXT: s_lshl_b32 s4, s4, 16 +; VI-NEXT: s_or_b32 s4, s5, s4 +; VI-NEXT: v_mov_b32_e32 v0, s4 +; VI-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; VI-NEXT: s_endpgm %a = load <2 x i16>, <2 x i16> addrspace(4)* %in0 %b = load <2 x i16>, <2 x i16> addrspace(4)* %in1 %add = sub <2 x i16> %a, %b @@ -38,10 +109,16 @@ define amdgpu_kernel void @s_test_sub_v2i16(<2 x i16> addrspace(1)* %out, <2 x i ret void } -; GCN-LABEL: {{^}}s_test_sub_self_v2i16: -; GCN: v_mov_b32_e32 [[ZERO:v[0-9]+]] -; GCN: buffer_store_dword [[ZERO]] define amdgpu_kernel void @s_test_sub_self_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(4)* %in0) #1 { +; GCN-LABEL: s_test_sub_self_v2i16: +; GCN: ; %bb.0: +; GCN-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GCN-NEXT: s_mov_b32 s3, 0xf000 +; GCN-NEXT: s_mov_b32 s2, -1 +; GCN-NEXT: v_mov_b32_e32 v0, 0 +; GCN-NEXT: s_waitcnt lgkmcnt(0) +; GCN-NEXT: buffer_store_dword v0, off, s[0:3], 0 +; GCN-NEXT: s_endpgm %a = load <2 x i16>, <2 x i16> addrspace(4)* %in0 %add = sub <2 x i16> %a, %a store <2 x i16> %add, <2 x i16> addrspace(1)* %out @@ -49,33 +126,83 @@ define amdgpu_kernel void @s_test_sub_self_v2i16(<2 x i16> addrspace(1)* %out, < } ; FIXME: VI should not scalarize arg access. -; GCN-LABEL: {{^}}s_test_sub_v2i16_kernarg: -; GCN: s_load_dword s -; GCN: s_load_dword s - -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, s{{[0-9]+}}, v{{[0-9]+}} - -; VI: s_sub_i32 -; VI: s_sub_i32 -; VI: s_lshl_b32 -; VI: s_and_b32 define amdgpu_kernel void @s_test_sub_v2i16_kernarg(<2 x i16> addrspace(1)* %out, <2 x i16> %a, <2 x i16> %b) #1 { +; GFX9-LABEL: s_test_sub_v2i16_kernarg: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x24 +; GFX9-NEXT: s_load_dword s2, s[0:1], 0x2c +; GFX9-NEXT: s_load_dword s0, s[0:1], 0x30 +; GFX9-NEXT: s_mov_b32 s7, 0xf000 +; GFX9-NEXT: s_mov_b32 s6, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v0, s0 +; GFX9-NEXT: v_pk_sub_i16 v0, s2, v0 +; GFX9-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: s_test_sub_v2i16_kernarg: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x24 +; VI-NEXT: s_load_dword s2, s[0:1], 0x2c +; VI-NEXT: s_load_dword s0, s[0:1], 0x30 +; VI-NEXT: s_mov_b32 s7, 0xf000 +; VI-NEXT: s_mov_b32 s6, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: s_lshr_b32 s1, s2, 16 +; VI-NEXT: s_lshr_b32 s3, s0, 16 +; VI-NEXT: s_sub_i32 s1, s1, s3 +; VI-NEXT: s_sub_i32 s0, s2, s0 +; VI-NEXT: s_lshl_b32 s1, s1, 16 +; VI-NEXT: s_and_b32 s0, s0, 0xffff +; VI-NEXT: s_or_b32 s0, s0, s1 +; VI-NEXT: v_mov_b32_e32 v0, s0 +; VI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; VI-NEXT: s_endpgm %add = sub <2 x i16> %a, %b store <2 x i16> %add, <2 x i16> addrspace(1)* %out ret void } -; GCN-LABEL: {{^}}v_test_sub_v2i16_constant: -; GFX89-DAG: {{flat|global}}_load_dword - -; GFX9-DAG: s_mov_b32 [[CONST:s[0-9]+]], 0x1c8007b{{$}} -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, v{{[0-9]+}}, [[CONST]] - -; VI-DAG: v_mov_b32_e32 [[K:v[0-9]+]], 0xfffffe38 -; VI-DAG: v_add_u16_e32 v{{[0-9]+}}, 0xffffff85, v{{[0-9]+}} -; VI-DAG: v_add_u16_sdwa v{{[0-9]+}}, v{{[0-9]+}}, [[K]] dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD -; VI: v_or_b32 define amdgpu_kernel void @v_test_sub_v2i16_constant(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0) #1 { +; GFX9-LABEL: v_test_sub_v2i16_constant: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX9-NEXT: s_mov_b32 s8, 0x1c8007b +; GFX9-NEXT: s_mov_b32 s7, 0xf000 +; GFX9-NEXT: s_mov_b32 s6, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s3 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s2, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, s0 +; GFX9-NEXT: s_mov_b32 s5, s1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, s8 +; GFX9-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_constant: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; VI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; VI-NEXT: v_mov_b32_e32 v2, 0xfffffe38 +; VI-NEXT: s_mov_b32 s7, 0xf000 +; VI-NEXT: s_mov_b32 s6, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: s_mov_b32 s4, s0 +; VI-NEXT: s_mov_b32 s5, s1 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u16_e32 v1, 0xffffff85, v0 +; VI-NEXT: v_add_u16_sdwa v0, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD +; VI-NEXT: v_or_b32_e32 v0, v1, v0 +; VI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -86,14 +213,46 @@ define amdgpu_kernel void @v_test_sub_v2i16_constant(<2 x i16> addrspace(1)* %ou } ; FIXME: Need to handle non-uniform case for function below (load without gep). -; GCN-LABEL: {{^}}v_test_sub_v2i16_neg_constant: -; GFX9: s_mov_b32 [[CONST:s[0-9]+]], 0xfc21fcb3{{$}} -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, v{{[0-9]+}}, [[CONST]] - -; VI-DAG: v_mov_b32_e32 [[K:v[0-9]+]], 0x3df -; VI-DAG: v_add_u16_sdwa v{{[0-9]+}}, v{{[0-9]+}}, [[K]] -; VI-DAG: v_add_u16_e32 v{{[0-9]+}}, 0x34d, v{{[0-9]+}} define amdgpu_kernel void @v_test_sub_v2i16_neg_constant(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0) #1 { +; GFX9-LABEL: v_test_sub_v2i16_neg_constant: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX9-NEXT: s_mov_b32 s8, 0xfc21fcb3 +; GFX9-NEXT: s_mov_b32 s7, 0xf000 +; GFX9-NEXT: s_mov_b32 s6, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s3 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s2, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, s0 +; GFX9-NEXT: s_mov_b32 s5, s1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, s8 +; GFX9-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_neg_constant: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; VI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; VI-NEXT: v_mov_b32_e32 v2, 0x3df +; VI-NEXT: s_mov_b32 s7, 0xf000 +; VI-NEXT: s_mov_b32 s6, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: s_mov_b32 s4, s0 +; VI-NEXT: s_mov_b32 s5, s1 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u16_e32 v1, 0x34d, v0 +; VI-NEXT: v_add_u16_sdwa v0, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD +; VI-NEXT: v_or_b32_e32 v0, v1, v0 +; VI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -103,15 +262,45 @@ define amdgpu_kernel void @v_test_sub_v2i16_neg_constant(<2 x i16> addrspace(1)* ret void } -; GCN-LABEL: {{^}}v_test_sub_v2i16_inline_neg1: -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, v{{[0-9]+}}, -1 op_sel_hi:[1,0]{{$}} - -; VI-DAG: v_mov_b32_e32 [[ONE:v[0-9]+]], 1 -; VI-DAG: flat_load_dword [[LOAD:v[0-9]+]] -; VI-DAG: v_add_u16_sdwa v{{[0-9]+}}, [[LOAD]], [[ONE]] dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD -; VI-DAG: v_add_u16_e32 v{{[0-9]+}}, 1, [[LOAD]] -; VI: v_or_b32_e32 define amdgpu_kernel void @v_test_sub_v2i16_inline_neg1(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0) #1 { +; GFX9-LABEL: v_test_sub_v2i16_inline_neg1: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX9-NEXT: s_mov_b32 s7, 0xf000 +; GFX9-NEXT: s_mov_b32 s6, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s3 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s2, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, s0 +; GFX9-NEXT: s_mov_b32 s5, s1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, -1 op_sel_hi:[1,0] +; GFX9-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_inline_neg1: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; VI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; VI-NEXT: v_mov_b32_e32 v2, 1 +; VI-NEXT: s_mov_b32 s7, 0xf000 +; VI-NEXT: s_mov_b32 s6, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: s_mov_b32 s4, s0 +; VI-NEXT: s_mov_b32 s5, s1 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u16_e32 v1, 1, v0 +; VI-NEXT: v_add_u16_sdwa v0, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD +; VI-NEXT: v_or_b32_e32 v0, v1, v0 +; VI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -121,14 +310,44 @@ define amdgpu_kernel void @v_test_sub_v2i16_inline_neg1(<2 x i16> addrspace(1)* ret void } -; GCN-LABEL: {{^}}v_test_sub_v2i16_inline_lo_zero_hi: -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, v{{[0-9]+}}, 32{{$}} - -; VI: flat_load_dword [[LOAD:v[0-9]+]] -; VI-DAG: v_and_b32_e32 [[AND:v[0-9]+]], 0xffff0000, [[LOAD]] -; VI-DAG: v_add_u16_e32 [[ADD:v[0-9]+]], 0xffffffe0, [[LOAD]] -; VI: v_or_b32_e32 v{{[0-9]+}}, [[ADD]], [[AND]] define amdgpu_kernel void @v_test_sub_v2i16_inline_lo_zero_hi(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0) #1 { +; GFX9-LABEL: v_test_sub_v2i16_inline_lo_zero_hi: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX9-NEXT: s_mov_b32 s7, 0xf000 +; GFX9-NEXT: s_mov_b32 s6, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s3 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s2, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, s0 +; GFX9-NEXT: s_mov_b32 s5, s1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, 32 +; GFX9-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_inline_lo_zero_hi: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; VI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; VI-NEXT: s_mov_b32 s7, 0xf000 +; VI-NEXT: s_mov_b32 s6, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: s_mov_b32 s4, s0 +; VI-NEXT: s_mov_b32 s5, s1 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_and_b32_e32 v1, 0xffff0000, v0 +; VI-NEXT: v_add_u16_e32 v0, 0xffffffe0, v0 +; VI-NEXT: v_or_b32_e32 v0, v0, v1 +; VI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -139,17 +358,45 @@ define amdgpu_kernel void @v_test_sub_v2i16_inline_lo_zero_hi(<2 x i16> addrspac } ; The high element gives fp -; GCN-LABEL: {{^}}v_test_sub_v2i16_inline_fp_split: -; GFX9: s_mov_b32 [[K:s[0-9]+]], 1.0 -; GFX9: v_pk_sub_i16 v{{[0-9]+}}, v{{[0-9]+}}, [[K]] - -; VI-NOT: v_subrev_i16 -; VI: v_mov_b32_e32 [[K:v[0-9]+]], 0xffffc080 -; VI: flat_load_dword -; VI: v_add_u16_sdwa [[ADD:v[0-9]+]], v{{[0-9]+}}, [[K]] dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD -; VI-NOT: v_subrev_i16 -; VI: v_or_b32_sdwa v{{[0-9]+}}, v{{[0-9]+}}, [[ADD]] dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD define amdgpu_kernel void @v_test_sub_v2i16_inline_fp_split(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0) #1 { +; GFX9-LABEL: v_test_sub_v2i16_inline_fp_split: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; GFX9-NEXT: s_mov_b32 s8, 1.0 +; GFX9-NEXT: s_mov_b32 s7, 0xf000 +; GFX9-NEXT: s_mov_b32 s6, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s3 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s2, v0 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s4, s0 +; GFX9-NEXT: s_mov_b32 s5, s1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, s8 +; GFX9-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_inline_fp_split: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x24 +; VI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; VI-NEXT: v_mov_b32_e32 v2, 0xffffc080 +; VI-NEXT: s_mov_b32 s7, 0xf000 +; VI-NEXT: s_mov_b32 s6, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s3 +; VI-NEXT: v_add_u32_e32 v0, vcc, s2, v0 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: s_mov_b32 s4, s0 +; VI-NEXT: s_mov_b32 s5, s1 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_add_u16_sdwa v1, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD +; VI-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; VI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -160,22 +407,55 @@ define amdgpu_kernel void @v_test_sub_v2i16_inline_fp_split(<2 x i16> addrspace( } ; FIXME: Need to handle non-uniform case for function below (load without gep). -; GCN-LABEL: {{^}}v_test_sub_v2i16_zext_to_v2i32: -; GFX9: global_load_dword [[A:v[0-9]+]] -; GFX9: global_load_dword [[B:v[0-9]+]] - -; GFX9: v_pk_sub_i16 [[ADD:v[0-9]+]], [[A]], [[B]] -; GFX9-DAG: v_and_b32_e32 v[[ELT0:[0-9]+]], 0xffff, [[ADD]] -; GFX9-DAG: v_lshrrev_b32_e32 v[[ELT1:[0-9]+]], 16, [[ADD]] -; GFX9: buffer_store_dwordx2 v{{\[}}[[ELT0]]:[[ELT1]]{{\]}} - -; VI: flat_load_dword v[[A:[0-9]+]] -; VI: flat_load_dword v[[B:[0-9]+]] - -; VI: v_sub_u16_e32 v[[ADD_LO:[0-9]+]], v[[A]], v[[B]] -; VI-NEXT: v_sub_u16_sdwa v[[ADD_HI:[0-9]+]], v[[A]], v[[B]] dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 -; VI-NEXT: buffer_store_dwordx2 v{{\[}}[[ADD_LO]]:[[ADD_HI]]{{\]}} define amdgpu_kernel void @v_test_sub_v2i16_zext_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0, <2 x i16> addrspace(1)* %in1) #1 { +; GFX9-LABEL: v_test_sub_v2i16_zext_to_v2i32: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; GFX9-NEXT: s_mov_b32 s3, 0xf000 +; GFX9-NEXT: s_mov_b32 s2, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s6, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v3, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: global_load_dword v1, v[2:3], off +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, v1 +; GFX9-NEXT: v_lshrrev_b32_e32 v1, 16, v0 +; GFX9-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GFX9-NEXT: buffer_store_dwordx2 v[0:1], off, s[0:3], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_zext_to_v2i32: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_mov_b32 s3, 0xf000 +; VI-NEXT: s_mov_b32 s2, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s7 +; VI-NEXT: v_add_u32_e32 v0, vcc, s6, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: flat_load_dword v1, v[0:1] +; VI-NEXT: flat_load_dword v2, v[2:3] +; VI-NEXT: s_mov_b32 s0, s4 +; VI-NEXT: s_mov_b32 s1, s5 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_sub_u16_e32 v0, v1, v2 +; VI-NEXT: v_sub_u16_sdwa v1, v1, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: buffer_store_dwordx2 v[0:1], off, s[0:3], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i32>, <2 x i32> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -189,21 +469,59 @@ define amdgpu_kernel void @v_test_sub_v2i16_zext_to_v2i32(<2 x i32> addrspace(1) } ; FIXME: Need to handle non-uniform case for function below (load without gep). -; GCN-LABEL: {{^}}v_test_sub_v2i16_zext_to_v2i64: -; GFX9: global_load_dword [[A:v[0-9]+]] -; GFX9: global_load_dword [[B:v[0-9]+]] - -; GFX9: v_pk_sub_i16 [[ADD:v[0-9]+]], [[A]], [[B]] -; GFX9-DAG: v_and_b32_e32 v[[ELT0:[0-9]+]], 0xffff, [[ADD]] -; GFX9-DAG: v_lshrrev_b32_e32 v[[ELT1:[0-9]+]], 16, [[ADD]] -; GFX9: buffer_store_dwordx4 - -; VI: flat_load_dword [[A:v[0-9]+]] -; VI: flat_load_dword [[B:v[0-9]+]] -; VI: v_sub_u16_e32 v[[ADD_LO:[0-9]+]], [[A]], [[B]] -; VI: v_sub_u16_sdwa v[[ADD_HI:[0-9]+]], [[A]], [[B]] dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 -; VI: buffer_store_dwordx4 define amdgpu_kernel void @v_test_sub_v2i16_zext_to_v2i64(<2 x i64> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0, <2 x i16> addrspace(1)* %in1) #1 { +; GFX9-LABEL: v_test_sub_v2i16_zext_to_v2i64: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; GFX9-NEXT: s_mov_b32 s3, 0xf000 +; GFX9-NEXT: s_mov_b32 s2, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s6, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v3, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: global_load_dword v1, v[2:3], off +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v1, v0, v1 +; GFX9-NEXT: v_and_b32_e32 v0, 0xffff, v1 +; GFX9-NEXT: v_lshrrev_b32_e32 v2, 16, v1 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: buffer_store_dwordx4 v[0:3], off, s[0:3], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_zext_to_v2i64: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; VI-NEXT: v_lshlrev_b32_e32 v0, 2, v0 +; VI-NEXT: v_mov_b32_e32 v1, 0 +; VI-NEXT: s_mov_b32 s3, 0xf000 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v3, s7 +; VI-NEXT: v_add_u32_e32 v2, vcc, s6, v0 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: v_mov_b32_e32 v5, s1 +; VI-NEXT: v_add_u32_e32 v4, vcc, s0, v0 +; VI-NEXT: v_addc_u32_e32 v5, vcc, 0, v5, vcc +; VI-NEXT: flat_load_dword v2, v[2:3] +; VI-NEXT: flat_load_dword v4, v[4:5] +; VI-NEXT: s_mov_b32 s2, -1 +; VI-NEXT: s_mov_b32 s0, s4 +; VI-NEXT: s_mov_b32 s1, s5 +; VI-NEXT: v_mov_b32_e32 v3, v1 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_sub_u16_e32 v0, v2, v4 +; VI-NEXT: v_sub_u16_sdwa v2, v2, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: buffer_store_dwordx4 v[0:3], off, s[0:3], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i64>, <2 x i64> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -217,22 +535,57 @@ define amdgpu_kernel void @v_test_sub_v2i16_zext_to_v2i64(<2 x i64> addrspace(1) } ; FIXME: Need to handle non-uniform case for function below (load without gep). -; GCN-LABEL: {{^}}v_test_sub_v2i16_sext_to_v2i32: -; GFX9: global_load_dword [[A:v[0-9]+]] -; GFX9: global_load_dword [[B:v[0-9]+]] - -; GFX9: v_pk_sub_i16 [[ADD:v[0-9]+]], [[A]], [[B]] -; GFX9-DAG: v_bfe_i32 v[[ELT0:[0-9]+]], [[ADD]], 0, 16 -; GFX9-DAG: v_ashrrev_i32_e32 v[[ELT1:[0-9]+]], 16, [[ADD]] -; GFX9: buffer_store_dwordx2 v{{\[}}[[ELT0]]:[[ELT1]]{{\]}} - -; VI: flat_load_dword -; VI: flat_load_dword -; VI-DAG: v_sub_u16_sdwa v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 -; VI-DAG: v_sub_u16_e32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} - -; VI: buffer_store_dwordx2 define amdgpu_kernel void @v_test_sub_v2i16_sext_to_v2i32(<2 x i32> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0, <2 x i16> addrspace(1)* %in1) #1 { +; GFX9-LABEL: v_test_sub_v2i16_sext_to_v2i32: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; GFX9-NEXT: s_mov_b32 s3, 0xf000 +; GFX9-NEXT: s_mov_b32 s2, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s6, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v3, vcc +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: global_load_dword v1, v[2:3], off +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v0, v0, v1 +; GFX9-NEXT: v_ashrrev_i32_e32 v1, 16, v0 +; GFX9-NEXT: v_bfe_i32 v0, v0, 0, 16 +; GFX9-NEXT: buffer_store_dwordx2 v[0:1], off, s[0:3], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_sext_to_v2i32: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_mov_b32 s3, 0xf000 +; VI-NEXT: s_mov_b32 s2, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s7 +; VI-NEXT: v_add_u32_e32 v0, vcc, s6, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: flat_load_dword v1, v[2:3] +; VI-NEXT: s_mov_b32 s0, s4 +; VI-NEXT: s_mov_b32 s1, s5 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_sub_u16_sdwa v2, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: v_sub_u16_e32 v0, v0, v1 +; VI-NEXT: v_bfe_i32 v0, v0, 0, 16 +; VI-NEXT: v_bfe_i32 v1, v2, 0, 16 +; VI-NEXT: buffer_store_dwordx2 v[0:1], off, s[0:3], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i32>, <2 x i32> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid @@ -246,21 +599,62 @@ define amdgpu_kernel void @v_test_sub_v2i16_sext_to_v2i32(<2 x i32> addrspace(1) } ; FIXME: Need to handle non-uniform case for function below (load without gep). -; GCN-LABEL: {{^}}v_test_sub_v2i16_sext_to_v2i64: -; GCN: {{flat|global}}_load_dword -; GCN: {{flat|global}}_load_dword - -; GFX9: v_pk_sub_i16 -; GFX9: v_lshrrev_b32_e32 v{{[0-9]+}}, 16, v{{[0-9]+}} - -; VI: v_sub_u16_sdwa v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 -; VI: v_sub_u16_e32 - -; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 16 -; GCN: v_bfe_i32 v{{[0-9]+}}, v{{[0-9]+}}, 0, 16 -; GCN: v_ashrrev_i32_e32 v{{[0-9]+}}, 31, v{{[0-9]+}} -; GCN: v_ashrrev_i32_e32 v{{[0-9]+}}, 31, v{{[0-9]+}} define amdgpu_kernel void @v_test_sub_v2i16_sext_to_v2i64(<2 x i64> addrspace(1)* %out, <2 x i16> addrspace(1)* %in0, <2 x i16> addrspace(1)* %in1) #1 { +; GFX9-LABEL: v_test_sub_v2i16_sext_to_v2i64: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; GFX9-NEXT: s_mov_b32 s3, 0xf000 +; GFX9-NEXT: s_mov_b32 s2, -1 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-NEXT: v_add_co_u32_e32 v0, vcc, s6, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v2 +; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v3, vcc +; GFX9-NEXT: global_load_dword v2, v[2:3], off +; GFX9-NEXT: global_load_dword v0, v[0:1], off +; GFX9-NEXT: s_mov_b32 s0, s4 +; GFX9-NEXT: s_mov_b32 s1, s5 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_pk_sub_i16 v1, v0, v2 +; GFX9-NEXT: v_lshrrev_b32_e32 v2, 16, v1 +; GFX9-NEXT: v_bfe_i32 v0, v1, 0, 16 +; GFX9-NEXT: v_bfe_i32 v2, v2, 0, 16 +; GFX9-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v2 +; GFX9-NEXT: buffer_store_dwordx4 v[0:3], off, s[0:3], 0 +; GFX9-NEXT: s_endpgm +; +; VI-LABEL: v_test_sub_v2i16_sext_to_v2i64: +; VI: ; %bb.0: +; VI-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x24 +; VI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x34 +; VI-NEXT: v_lshlrev_b32_e32 v2, 2, v0 +; VI-NEXT: s_mov_b32 s3, 0xf000 +; VI-NEXT: s_mov_b32 s2, -1 +; VI-NEXT: s_waitcnt lgkmcnt(0) +; VI-NEXT: v_mov_b32_e32 v1, s7 +; VI-NEXT: v_add_u32_e32 v0, vcc, s6, v2 +; VI-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; VI-NEXT: v_mov_b32_e32 v3, s1 +; VI-NEXT: v_add_u32_e32 v2, vcc, s0, v2 +; VI-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; VI-NEXT: flat_load_dword v2, v[2:3] +; VI-NEXT: flat_load_dword v0, v[0:1] +; VI-NEXT: s_mov_b32 s0, s4 +; VI-NEXT: s_mov_b32 s1, s5 +; VI-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; VI-NEXT: v_sub_u16_sdwa v1, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:WORD_1 +; VI-NEXT: v_sub_u16_e32 v0, v0, v2 +; VI-NEXT: v_bfe_i32 v2, v1, 0, 16 +; VI-NEXT: v_bfe_i32 v0, v0, 0, 16 +; VI-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; VI-NEXT: v_ashrrev_i32_e32 v3, 31, v2 +; VI-NEXT: buffer_store_dwordx4 v[0:3], off, s[0:3], 0 +; VI-NEXT: s_endpgm %tid = call i32 @llvm.amdgcn.workitem.id.x() %gep.out = getelementptr inbounds <2 x i64>, <2 x i64> addrspace(1)* %out, i32 %tid %gep.in0 = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %in0, i32 %tid From 7d230d2661bfd4fdb41caf2d34e923b42c758e9f Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Thu, 23 May 2019 11:58:03 +0000 Subject: [PATCH 0022/1176] [clangd] Bump vscode extension version llvm-svn: 361486 --- clang-tools-extra/clangd/clients/clangd-vscode/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package.json b/clang-tools-extra/clangd/clients/clangd-vscode/package.json index b8125808d53af..1a423292d8afd 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/package.json +++ b/clang-tools-extra/clangd/clients/clangd-vscode/package.json @@ -2,7 +2,7 @@ "name": "vscode-clangd", "displayName": "vscode-clangd", "description": "Clang Language Server", - "version": "0.0.12", + "version": "0.0.13", "publisher": "llvm-vs-code-extensions", "homepage": "https://clang.llvm.org/extra/clangd.html", "engines": { From 1520dafa20ede121c950652141a7f0d639d308fc Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Thu, 23 May 2019 12:01:26 +0000 Subject: [PATCH 0023/1176] [clang-tidy] New check calling out uses of +new in Objective-C code Summary: Google's Objective-C style guide forbids calling or overriding +new to instantiate objects. This check warns on violations. Style guide reference: https://google.github.io/styleguide/objcguide.html#do-not-use-new Patch by Michael Wyman. Reviewers: benhamilton, aaron.ballman, JonasToth, gribozavr, ilya-biryukov, stephanemoore, mwyman Reviewed By: aaron.ballman, gribozavr, stephanemoore, mwyman Subscribers: stephanemoore, xazax.hun, Eugene.Zelenko, mgorny, cfe-commits Tags: #clang, #clang-tools-extra Differential Revision: https://reviews.llvm.org/D61350 llvm-svn: 361487 --- .../google/AvoidNSObjectNewCheck.cpp | 130 ++++++++++++++++++ .../clang-tidy/google/AvoidNSObjectNewCheck.h | 38 +++++ .../clang-tidy/google/CMakeLists.txt | 1 + .../clang-tidy/google/GoogleTidyModule.cpp | 3 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../checks/google-objc-avoid-nsobject-new.rst | 29 ++++ .../docs/clang-tidy/checks/list.rst | 1 + .../google-objc-avoid-nsobject-new.m | 80 +++++++++++ 8 files changed, 288 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst create mode 100644 clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m diff --git a/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp new file mode 100644 index 0000000000000..1b147ace89868 --- /dev/null +++ b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.cpp @@ -0,0 +1,130 @@ +//===--- AvoidNSObjectNewCheck.cpp - clang-tidy ---------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "AvoidNSObjectNewCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/FormatVariadic.h" +#include +#include + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace google { +namespace objc { + +static bool isMessageExpressionInsideMacro(const ObjCMessageExpr *Expr) { + SourceLocation ReceiverLocation = Expr->getReceiverRange().getBegin(); + if (ReceiverLocation.isMacroID()) + return true; + + SourceLocation SelectorLocation = Expr->getSelectorStartLoc(); + if (SelectorLocation.isMacroID()) + return true; + + return false; +} + +// Walk up the class hierarchy looking for an -init method, returning true +// if one is found and has not been marked unavailable. +static bool isInitMethodAvailable(const ObjCInterfaceDecl *ClassDecl) { + while (ClassDecl != nullptr) { + for (const auto *MethodDecl : ClassDecl->instance_methods()) { + if (MethodDecl->getSelector().getAsString() == "init") + return !MethodDecl->isUnavailable(); + } + ClassDecl = ClassDecl->getSuperClass(); + } + + // No -init method found in the class hierarchy. This should occur only rarely + // in Objective-C code, and only really applies to classes not derived from + // NSObject. + return false; +} + +// Returns the string for the Objective-C message receiver. Keeps any generics +// included in the receiver class type, which are stripped if the class type is +// used. While the generics arguments will not make any difference to the +// returned code at this time, the style guide allows them and they should be +// left in any fix-it hint. +static StringRef getReceiverString(SourceRange ReceiverRange, + const SourceManager &SM, + const LangOptions &LangOpts) { + CharSourceRange CharRange = Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(ReceiverRange), SM, LangOpts); + return Lexer::getSourceText(CharRange, SM, LangOpts); +} + +static FixItHint getCallFixItHint(const ObjCMessageExpr *Expr, + const SourceManager &SM, + const LangOptions &LangOpts) { + // Check whether the messaged class has a known factory method to use instead + // of -init. + StringRef Receiver = + getReceiverString(Expr->getReceiverRange(), SM, LangOpts); + // Some classes should use standard factory methods instead of alloc/init. + std::map ClassToFactoryMethodMap = {{"NSDate", "date"}, + {"NSNull", "null"}}; + auto FoundClassFactory = ClassToFactoryMethodMap.find(Receiver); + if (FoundClassFactory != ClassToFactoryMethodMap.end()) { + StringRef ClassName = FoundClassFactory->first; + StringRef FactorySelector = FoundClassFactory->second; + std::string NewCall = + llvm::formatv("[{0} {1}]", ClassName, FactorySelector); + return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall); + } + + if (isInitMethodAvailable(Expr->getReceiverInterface())) { + std::string NewCall = llvm::formatv("[[{0} alloc] init]", Receiver); + return FixItHint::CreateReplacement(Expr->getSourceRange(), NewCall); + } + + return {}; // No known replacement available. +} + +void AvoidNSObjectNewCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().ObjC) + return; + + // Add two matchers, to catch calls to +new and implementations of +new. + Finder->addMatcher( + objcMessageExpr(isClassMessage(), hasSelector("new")).bind("new_call"), + this); + Finder->addMatcher( + objcMethodDecl(isClassMethod(), isDefinition(), hasName("new")) + .bind("new_override"), + this); +} + +void AvoidNSObjectNewCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *CallExpr = + Result.Nodes.getNodeAs("new_call")) { + // Don't warn if the call expression originates from a macro expansion. + if (isMessageExpressionInsideMacro(CallExpr)) + return; + + diag(CallExpr->getExprLoc(), "do not create objects with +new") + << getCallFixItHint(CallExpr, *Result.SourceManager, + Result.Context->getLangOpts()); + } + + if (const auto *DeclExpr = + Result.Nodes.getNodeAs("new_override")) { + diag(DeclExpr->getBeginLoc(), "classes should not override +new"); + } +} + +} // namespace objc +} // namespace google +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h new file mode 100644 index 0000000000000..97988c903e8e5 --- /dev/null +++ b/clang-tools-extra/clang-tidy/google/AvoidNSObjectNewCheck.h @@ -0,0 +1,38 @@ +//===--- AvoidNSObjectNewCheck.h - clang-tidy -------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDNSOBJECTNEWCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDNSOBJECTNEWCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace google { +namespace objc { + +/// This check finds Objective-C code that uses +new to create object instances, +/// or overrides +new in classes. Both are forbidden by Google's Objective-C +/// style guide. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/google-avoid-nsobject-new.html +class AvoidNSObjectNewCheck : public ClangTidyCheck { +public: + AvoidNSObjectNewCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace objc +} // namespace google +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDNSOBJECTNEWCHECK_H diff --git a/clang-tools-extra/clang-tidy/google/CMakeLists.txt b/clang-tools-extra/clang-tidy/google/CMakeLists.txt index 4d0a326f73b16..b78088cf06bab 100644 --- a/clang-tools-extra/clang-tidy/google/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/google/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyGoogleModule AvoidCStyleCastsCheck.cpp + AvoidNSObjectNewCheck.cpp AvoidThrowingObjCExceptionCheck.cpp AvoidUnderscoreInGoogletestNameCheck.cpp DefaultArgumentsCheck.cpp diff --git a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp index c2a9ec5edbc48..1e3410fb8a5ef 100644 --- a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp @@ -13,6 +13,7 @@ #include "../readability/FunctionSizeCheck.h" #include "../readability/NamespaceCommentCheck.h" #include "AvoidCStyleCastsCheck.h" +#include "AvoidNSObjectNewCheck.h" #include "AvoidThrowingObjCExceptionCheck.h" #include "AvoidUnderscoreInGoogletestNameCheck.h" #include "DefaultArgumentsCheck.h" @@ -49,6 +50,8 @@ class GoogleModule : public ClangTidyModule { "google-explicit-constructor"); CheckFactories.registerCheck( "google-global-names-in-headers"); + CheckFactories.registerCheck( + "google-objc-avoid-nsobject-new"); CheckFactories.registerCheck( "google-objc-avoid-throwing-exception"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f1ee2fe44e9aa..4c709f0370df9 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -122,6 +122,12 @@ Improvements to clang-tidy Checks whether there are underscores in googletest test and test case names in test macros, which is prohibited by the Googletest FAQ. +- New :doc:`google-objc-avoid-nsobject-new + ` check. + + Checks for calls to ``+new`` or overrides of it, which are prohibited by the + Google Objective-C style guide. + - New :doc:`objc-super-self ` check. Finds invocations of ``-self`` on super instances in initializers of diff --git a/clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst b/clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst new file mode 100644 index 0000000000000..4eae4470c872b --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/google-objc-avoid-nsobject-new.rst @@ -0,0 +1,29 @@ +.. title:: clang-tidy - google-objc-avoid-nsobject-new + +google-objc-avoid-nsobject-new +============================== + +Finds calls to ``+new`` or overrides of it, which are prohibited by the +Google Objective-C style guide. + +The Google Objective-C style guide forbids calling ``+new`` or overriding it in +class implementations, preferring ``+alloc`` and ``-init`` methods to +instantiate objects. + +An example: + +.. code-block:: objc + + NSDate *now = [NSDate new]; + Foo *bar = [Foo new]; + +Instead, code should use ``+alloc``/``-init`` or class factory methods. + +.. code-block:: objc + + NSDate *now = [NSDate date]; + Foo *bar = [[Foo alloc] init]; + +This check corresponds to the Google Objective-C Style Guide rule +`Do Not Use +new +`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 74bf2a87e190a..7a0ebc292e468 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -135,6 +135,7 @@ Clang-Tidy Checks google-default-arguments google-explicit-constructor google-global-names-in-headers + google-objc-avoid-nsobject-new google-objc-avoid-throwing-exception google-objc-function-naming google-objc-global-variable-declaration diff --git a/clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m b/clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m new file mode 100644 index 0000000000000..f8b1d20f4f6da --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/google-objc-avoid-nsobject-new.m @@ -0,0 +1,80 @@ +// RUN: %check_clang_tidy %s google-objc-avoid-nsobject-new %t + +@interface NSObject ++ (instancetype)new; ++ (instancetype)alloc; +- (instancetype)init; +@end + +@interface NSProxy // Root class with no -init method. +@end + +// NSDate provides a specific factory method. +@interface NSDate : NSObject ++ (instancetype)date; +@end + +// For testing behavior with Objective-C Generics. +@interface NSMutableDictionary<__covariant KeyType, __covariant ObjectType> : NSObject +@end + +@class NSString; + +#define ALLOCATE_OBJECT(_Type) [_Type new] + +void CheckSpecificInitRecommendations(void) { + NSObject *object = [NSObject new]; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: do not create objects with +new [google-objc-avoid-nsobject-new] + // CHECK-FIXES: [NSObject alloc] init]; + + NSDate *correctDate = [NSDate date]; + NSDate *incorrectDate = [NSDate new]; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: do not create objects with +new [google-objc-avoid-nsobject-new] + // CHECK-FIXES: [NSDate date]; + + NSObject *macroCreated = ALLOCATE_OBJECT(NSObject); // Shouldn't warn on macros. + + NSMutableDictionary *dict = [NSMutableDictionary new]; + // CHECK-MESSAGES: [[@LINE-1]]:31: warning: do not create objects with +new [google-objc-avoid-nsobject-new] + // CHECK-FIXES: [NSMutableDictionary alloc] init]; +} + +@interface Foo : NSObject ++ (instancetype)new; // Declare again to suppress warning. +- (instancetype)initWithInt:(int)anInt; +- (instancetype)init __attribute__((unavailable)); + +- (id)new; +@end + +@interface Baz : Foo // Check unavailable -init through inheritance. +@end + +@interface ProxyFoo : NSProxy ++ (instancetype)new; +@end + +void CallNewWhenInitUnavailable(void) { + Foo *foo = [Foo new]; + // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new] + + Baz *baz = [Baz new]; + // CHECK-MESSAGES: [[@LINE-1]]:14: warning: do not create objects with +new [google-objc-avoid-nsobject-new] + + // Instance method -new calls may be weird, but are not strictly forbidden. + Foo *bar = [[Foo alloc] initWithInt:4]; + [bar new]; + + ProxyFoo *proxy = [ProxyFoo new]; + // CHECK-MESSAGES: [[@LINE-1]]:21: warning: do not create objects with +new [google-objc-avoid-nsobject-new] +} + +@interface HasNewOverride : NSObject +@end + +@implementation HasNewOverride ++ (instancetype)new { + return [[self alloc] init]; +} +// CHECK-MESSAGES: [[@LINE-3]]:1: warning: classes should not override +new [google-objc-avoid-nsobject-new] +@end From fb6ee67ab14805aa75cb11404d426535242bff55 Mon Sep 17 00:00:00 2001 From: Kadir Cetinkaya Date: Thu, 23 May 2019 12:02:14 +0000 Subject: [PATCH 0024/1176] [clangd] Also update package-lock.json llvm-svn: 361488 --- .../clangd/clients/clangd-vscode/package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json b/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json index 47373624481ae..8108e789b2e36 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json +++ b/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-clangd", - "version": "0.0.12", + "version": "0.0.13", "lockfileVersion": 1, "requires": true, "dependencies": { From 903f5b05e264cca4bb24296f012854afe3102f6e Mon Sep 17 00:00:00 2001 From: James Henderson Date: Thu, 23 May 2019 12:30:39 +0000 Subject: [PATCH 0025/1176] [llvm-objdump][test] Improve testing of some switches #3 This is the third commit in a series of patches to improve test coverage of llvm-objdump. In this patch I have added a number of tests testing various aspects of disassembly. Reviewed by: MaskRay, grimar, rupprecht Differential Revision: https://reviews.llvm.org/D62255 llvm-svn: 361489 --- .../disasm-specific-funcs-mangled-name.test | 27 +++++ .../X86/disasm-specific-funcs.test | 44 ++++---- .../disassemble-invalid-byte-sequences.test | 20 ++++ .../X86/disassemble-long-instructions.test | 17 +++ .../X86/elf-disassemble-dynamic-symbols.test | 99 +++++++++++++++++ .../X86/elf-disassemble-no-symtab.test | 24 +++++ .../X86/elf-disassemble-relocs.test | 42 ++++++++ .../elf-disassemble-symbol-labels-exec.test | 54 ++++++++++ .../elf-disassemble-symbol-labels-rel.test | 58 ++++++++++ .../elf-disassemble-symbol-references.yaml | 101 ++++++++++++++++++ .../llvm-objdump/X86/elf-disassemble.test | 50 +++++++++ ...start-stop-address-relocatable-object.test | 46 ++++++++ .../llvm-objdump/X86/start-stop-address.test | 46 +++++++- .../llvm-objdump/X86/stripped-shared.test | 10 -- 14 files changed, 604 insertions(+), 34 deletions(-) create mode 100644 llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs-mangled-name.test create mode 100644 llvm/test/tools/llvm-objdump/X86/disassemble-invalid-byte-sequences.test create mode 100644 llvm/test/tools/llvm-objdump/X86/disassemble-long-instructions.test create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble-no-symtab.test create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-exec.test create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-references.yaml create mode 100644 llvm/test/tools/llvm-objdump/X86/elf-disassemble.test create mode 100644 llvm/test/tools/llvm-objdump/X86/start-stop-address-relocatable-object.test delete mode 100644 llvm/test/tools/llvm-objdump/X86/stripped-shared.test diff --git a/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs-mangled-name.test b/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs-mangled-name.test new file mode 100644 index 0000000000000..c3f243c6d3dfe --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs-mangled-name.test @@ -0,0 +1,27 @@ +## Show that the --disassemble-functions switch takes mangled names, not +## demangled names. + +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump -d --disassemble-functions=_Z3foov %t.o | FileCheck %s +# RUN: llvm-objdump -d --disassemble-functions='foo()' %t.o | FileCheck %s --check-prefix=NOFOO +# RUN: llvm-objdump -d -C --disassemble-functions='foo()' %t.o | FileCheck %s --check-prefix=NOFOO +# RUN: llvm-objdump -d --disassemble-functions=foo %t.o | FileCheck %s --check-prefix=NOFOO + +# CHECK: _Z3foov: + +# NOFOO-NOT: foo + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '90' +Symbols: + - Name: _Z3foov + Section: .text diff --git a/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs.test b/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs.test index 8e6155710a46b..988afb37b77b7 100644 --- a/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs.test +++ b/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs.test @@ -1,21 +1,25 @@ -// RUN: yaml2obj -o %t.out %p/Inputs/simple-executable-x86_64.yaml -// RUN: llvm-objdump -d %t.out -disassemble-functions=main | FileCheck %s +## Show that the --diassemble-functions switch disassembles only the specified +## functions. -// CHECK: Disassembly of section .anothertext: -// CHECK-EMPTY: -// CHECK-NEXT: main: -// CHECK-NEXT: 10: 55 pushq %rbp -// CHECK-NEXT: 11: 48 89 e5 movq %rsp, %rbp -// CHECK-NEXT: 14: 48 83 ec 20 subq $32, %rsp -// CHECK-NEXT: 18: 48 8d 04 25 a8 00 00 00 leaq 168, %rax -// CHECK-NEXT: 20: c7 45 fc 00 00 00 00 movl $0, -4(%rbp) -// CHECK-NEXT: 27: 48 89 45 f0 movq %rax, -16(%rbp) -// CHECK-NEXT: 2b: 48 8b 45 f0 movq -16(%rbp), %rax -// CHECK-NEXT: 2f: 8b 08 movl (%rax), %ecx -// CHECK-NEXT: 31: 89 4d ec movl %ecx, -20(%rbp) -// CHECK-NEXT: 34: e8 c7 ff ff ff callq -57 -// CHECK-NEXT: 39: 8b 4d ec movl -20(%rbp), %ecx -// CHECK-NEXT: 3c: 01 c1 addl %eax, %ecx -// CHECK-NEXT: 3e: 89 c8 movl %ecx, %eax -// CHECK-NEXT: 40: 48 83 c4 20 addq $32, %rsp -// CHECK-NEXT: 44: 5d popq %rbp +# RUN: yaml2obj -o %t.out %p/Inputs/simple-executable-x86_64.yaml +# RUN: llvm-objdump -d %t.out --disassemble-functions=main \ +# RUN: | FileCheck %s --check-prefix=MAIN --implicit-check-not=foo --implicit-check-not=somedata +# RUN: llvm-objdump -d %t.out --disassemble-functions=main,foo \ +# RUN: | FileCheck %s --check-prefixes=MAIN,FOO --implicit-check-not=somedata + +# FOO: foo: +# MAIN: main: + +## Unknown symbol name. +# RUN: llvm-objdump -d %t.out --disassemble-functions=baz \ +# RUN: | FileCheck %s --implicit-check-not=Disassembly + +## Data symbol. +# RUN: llvm-objdump -d %t.out --disassemble-functions=a \ +# RUN: | FileCheck %s --implicit-check-not=Disassembly + +## Data symbol + --disassemble-all. +# RUN: llvm-objdump -D %t.out --disassemble-functions=a \ +# RUN: | FileCheck %s --check-prefix=DATA + +# DATA: a: diff --git a/llvm/test/tools/llvm-objdump/X86/disassemble-invalid-byte-sequences.test b/llvm/test/tools/llvm-objdump/X86/disassemble-invalid-byte-sequences.test new file mode 100644 index 0000000000000..a9d7f6ac0e48e --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/disassemble-invalid-byte-sequences.test @@ -0,0 +1,20 @@ +## Show that llvm-objdump handles invalid byte sequences, and continues. + +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump %t.o -d | FileCheck %s + +# CHECK: 0000000000000000 .text: +# CHECK: 0: d9 e2 +# CHECK-NEXT: 2: 90 nop + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'd9e290' diff --git a/llvm/test/tools/llvm-objdump/X86/disassemble-long-instructions.test b/llvm/test/tools/llvm-objdump/X86/disassemble-long-instructions.test new file mode 100644 index 0000000000000..9596c01e460d6 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/disassemble-long-instructions.test @@ -0,0 +1,17 @@ +## This test shows that llvm-objdump can disassemble a long instruction. +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump -d %t.o | FileCheck %s --strict-whitespace + +# CHECK: 0: 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:(%rax,%rax) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '6666666666662E0F1F840000000000' # 15-byte nop diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test new file mode 100644 index 0000000000000..94efd7e583844 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-dynamic-symbols.test @@ -0,0 +1,99 @@ +## Show the disassembly behaviour when dynamic symbols are present. +# RUN: yaml2obj %s -o %t + +## Case 1: Both static and dynamic symbols are present. Only static +## symbols are displayed. +# RUN: llvm-objdump -d %t | FileCheck %s --check-prefixes=CHECK,STATIC + +## Case 2: Only the dynamic symbols are present. These should be displayed, if +## they meet the necessary criteria. +# RUN: llvm-objcopy --strip-all %t %t2 +# RUN: llvm-objdump -d %t2 | FileCheck %s --check-prefixes=CHECK,DYN + +# CHECK: Disassembly of section .text: +# CHECK-EMPTY: +# STATIC-NEXT: 0000000000001000 .text: +# DYN-NEXT: 0000000000001000 only_dyn: +# CHECK-NEXT: 1000: +# CHECK-EMPTY: +# STATIC-NEXT: 0000000000001001 both_static: +# DYN-NEXT: 0000000000001001 both_dyn: +# CHECK-NEXT: 1001: +# STATIC-EMPTY: +# STATIC-NEXT: 0000000000001002 only_static: +# CHECK-NEXT: 1002: +# CHECK-NEXT: 1003: +# CHECK-NEXT: 1004: +# CHECK-NEXT: 1005:{{.*}} +# CHECK-NOT: {{.}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Address: 0x1000 + Content: 909090909090 +ProgramHeaders: + - Type: PT_LOAD + VAddr: 0x1000 + Sections: + - Section: .text +Symbols: + - Name: both_static + Value: 0x1001 + Section: .text + Binding: STB_GLOBAL + - Name: only_static + Value: 0x1002 + Section: .text + Binding: STB_GLOBAL +DynamicSymbols: + - Name: only_dyn + Value: 0x1000 + Section: .text + Size: 1 + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: both_dyn + Value: 0x1001 + Section: .text + Size: 1 + Type: STT_FUNC + Binding: STB_GLOBAL + ## The rest of the dynamic symbols won't be used for various reasons. + ## FIXME: the first two symbols here should be dumped. + ## See https://bugs.llvm.org/show_bug.cgi?id=41947 + - Name: not_func + Value: 0x1003 + Section: .text + Type: STT_OBJECT + Binding: STB_GLOBAL + - Name: zero_sized + Value: 0x1004 + Section: .text + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: '' # No name + Value: 0x1005 + Section: .text + Size: 1 + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: absolute + Value: 0x1005 + Index: SHN_ABS + Size: 1 + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: undefined + Value: 0x1005 + Index: SHN_UNDEF + Size: 1 + Type: STT_FUNC + Binding: STB_GLOBAL diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-no-symtab.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-no-symtab.test new file mode 100644 index 0000000000000..b45c905bb3db9 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-no-symtab.test @@ -0,0 +1,24 @@ +## Show that llvm-objdump can handle a missing symbol table when printing +## references and labels. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy -R .symtab %t +# RUN: llvm-objdump %t -d | FileCheck %s + +# CHECK: Disassembly of section .text: +# CHECK-EMPTY: +# CHECK-NEXT: 0000000000004000 .text: +# CHECK-NEXT: 4000: e8 42 00 00 00 callq 66 <.text+0x47> + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Address: 0x4000 + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'e842000000' diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test new file mode 100644 index 0000000000000..04390eb4e3084 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test @@ -0,0 +1,42 @@ +## Show that --disassemble + --reloc prints relocations inline and does not dump +## the relocation sections. + +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump %t.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS" + +# CHECK: 0: e8 00 00 00 00 callq 0 <.text+0x5> +# CHECK-NEXT: 0000000000000001: R_X86_64_PC32 foo-4 +# CHECK-NEXT: 0000000000000002: R_X86_64_NONE bar+8 +# CHECK-NEXT: 5: e8 00 00 00 00 callq 0 <.text+0xa> +# CHECK-NEXT: 0000000000000006: R_X86_64_PLT32 foo+1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'e800000000e800000000' + - Name: .rela.text + Type: SHT_RELA + Info: .text + Relocations: + - Offset: 1 + Symbol: foo + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 2 + Symbol: bar + Type: R_X86_64_NONE + Addend: 8 + - Offset: 6 + Symbol: foo + Type: R_X86_64_PLT32 + Addend: 1 +Symbols: + - Name: foo + - Name: bar diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-exec.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-exec.test new file mode 100644 index 0000000000000..548ee4b182dd1 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-exec.test @@ -0,0 +1,54 @@ +## Show which labels are printed in disassembly of an executable. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump %t -d | FileCheck %s --implicit-check-not=stt_section \ +# RUN: --implicit-check-not=fourth \ +# RUN: --implicit-check-not=absolute \ +# RUN: --implicit-check-not=other + +# CHECK: 0000000000004000 first: +# CHECK: 0000000000004001 second: +# CHECK: 0000000000004002 third: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Address: 0x4000 + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '9090909090' + - Name: .text2 + Type: SHT_PROGBITS + Address: 0x4004 + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Size: 0 +Symbols: + - Name: first # Shows, with second, that symbol sizes are not used to delineate functions. + Value: 0x4000 + Section: .text + Size: 0x2 + - Name: second + Value: 0x4001 + Size: 0x1 + Section: .text + - Name: third # Shows, with fourth, that first symbol is picked. + Value: 0x4002 + Section: .text + - Name: fourth + Value: 0x4002 + Section: .text + - Name: stt_section # Shows that STT_SECTION symbols are ignored even if no other symbol present. + Value: 0x4003 + Type: STT_SECTION + Section: .text + - Name: absolute # Show that absolute symbols are ignored. + Value: 0x4004 + Index: SHN_ABS + - Name: other # Show that symbols from other sections are ignored. + Value: 0x4004 + Section: .text2 diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test new file mode 100644 index 0000000000000..d2377f44621f4 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test @@ -0,0 +1,58 @@ +## Show which labels are printed in disassembly of a relocatable object. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-objdump %t -d | FileCheck %s --implicit-check-not=stt_section \ +# RUN: --implicit-check-not=first \ +# RUN: --implicit-check-not=second \ +# RUN: --implicit-check-not=third \ +# RUN: --implicit-check-not=fourth \ +# RUN: --implicit-check-not=absolute \ +# RUN: --implicit-check-not=other + +# CHECK: Disassembly of section .text: +# CHECK: 0000000000000000 first: +# CHECK: 0000000000000001 second: +# CHECK: 0000000000000002 third: +# CHECK: Disassembly of section .text2: +# CHECK: 0000000000000004 other: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '909090909090' + - Name: .text2 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '9090909090' +Symbols: + - Name: first + Value: 0 + Section: .text + Size: 2 + - Name: second # Shows, with first, that symbol sizes are not used to delineate functions. + Value: 1 + Size: 1 + Section: .text + - Name: third # Shows, with fourth, that first symbol is picked. + Value: 2 + Section: .text + - Name: fourth + Value: 2 + Section: .text + - Name: stt_section # Shows that STT_SECTION symbols are ignored even if no other symbol present. + Value: 3 + Type: STT_SECTION + Section: .text + - Name: absolute # Show that absolute symbols are ignored. + Value: 4 + Index: SHN_ABS + - Name: other # Show that symbols in other sections are ignored. + Value: 4 + Section: .text2 diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-references.yaml b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-references.yaml new file mode 100644 index 0000000000000..d627b207a23da --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-references.yaml @@ -0,0 +1,101 @@ +## Show that references in disassembly are labelled with the correct symbol. +# RUN: yaml2obj %s --docnum=1 -o %t +# RUN: llvm-objdump %t -d | FileCheck %s --check-prefix=EXEC + +# EXEC: Disassembly of section .text1: +# EXEC: 4000: e8 00 00 00 00 callq 0 +# EXEC: Disassembly of section .text2: +# EXEC: 4005: e8 12 34 56 78 callq 2018915346 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text1 + Type: SHT_PROGBITS + Address: 0x4000 + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'e800000000' # Case 1: Referencing an address with a symbol. + - Name: .text2 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Address: 0x4005 + Content: 'e812345678' # Case 2: Referencing an address without a symbol. + - Name: .text3 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Address: 0x400A +Symbols: + - Name: first + Section: .text1 + Value: 0x4000 + - Name: second + Section: .text1 + Value: 0x4005 + - Name: third + Section: .text2 + Value: 0x4005 + - Name: fourth + Section: .text3 + Value: 0x400A + +# RUN: yaml2obj %s --docnum=2 -o %t.o +# RUN: llvm-objdump %t.o -d | FileCheck %s --check-prefix=REL + +# REL: Disassembly of section .text1: +# REL-EMPTY: +# REL-NEXT: 0000000000000000 .text1: +# REL-NEXT: 0: e8 00 00 00 00 callq 0 <.text1+0x5> +# REL-EMPTY: +# REL-NEXT: Disassembly of section .text2: +# REL-EMPTY: +# REL-NEXT: 0000000000000000 .text2: +# REL-NEXT: 0: e8 00 00 00 00 callq 0 +# REL-EMPTY: +# REL-NEXT: Disassembly of section .text3: +# REL-EMPTY: +# REL-NEXT: 0000000000000000 .text3: +# REL-NEXT: 0: e8 00 00 00 00 callq 0 <.text3+0x5> + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text1 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'e800000000' # Case 1: Instruction is patched by a relocation. + - Name: .rela.text1 + Type: SHT_RELA + Info: .text1 + Relocations: + - Offset: 1 + Type: R_X86_64_PC32 + Symbol: sym3 + - Name: .text2 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'e800000000' # Case 2: Referencing an address with a matching symbol in that section. + - Name: .text3 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'e800000000' # Case 3: Referencing an address without a matching symbol in that section. + - Name: .other + Type: SHT_PROGBITS +Symbols: + # Shouldn't be picked, despite matching value, as not in right section. + - Name: sym1 + Section: .other + Value: 5 + # Symbol in correct section, with right value should be picked for disassembly of .text2. + - Name: sym2 + Section: .text2 + Value: 5 + # Symbol referenced by relocation could be picked for disassembly of .text1, but isn't. + - Name: sym3 diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test new file mode 100644 index 0000000000000..4db8d32947fd6 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble.test @@ -0,0 +1,50 @@ +## Show that disassembly is printed correctly, for only the desired sections. +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump %t.o --disassemble | FileCheck %s --implicit-check-not=Disassembly +# RUN: llvm-objdump %t.o --disassemble-all | FileCheck %s --check-prefixes=CHECK,ALL + +# CHECK: Disassembly of section .executable: +# CHECK-EMPTY: +# CHECK-NEXT: 0000000000001000 .executable: +# CHECK-NEXT: 0: 90 nop +# ALL-EMPTY: +# ALL-NEXT: Disassembly of section .writable: +# ALL-EMPTY: +# ALL-NEXT: 0000000000002000 .writable: +# ALL-NEXT: 0: c3 retq +# ALL-EMPTY: +# ALL-NEXT: Disassembly of section .readonly: +# ALL-EMPTY: +# ALL-NEXT: 0000000000003000 .readonly: +# ALL-NEXT: 0: 01 00 addl %eax, (%rax) +# ALL-EMPTY: +# ALL-NEXT: Disassembly of section .nobits: +# ALL-EMPTY: +# ALL-NEXT: 0000000000004000 .nobits: +# ALL-NEXT: ... + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .executable + Type: SHT_PROGBITS + Address: 0x1000 + Flags: [SHF_EXECINSTR] + Content: '90' + - Name: .writable + Type: SHT_PROGBITS + Address: 0x2000 + Flags: [SHF_WRITE] + Content: 'c3' + - Name: .readonly + Type: SHT_PROGBITS + Address: 0x3000 + Content: '0100' + - Name: .nobits + Type: SHT_NOBITS + Address: 0x4000 + Size: 4 diff --git a/llvm/test/tools/llvm-objdump/X86/start-stop-address-relocatable-object.test b/llvm/test/tools/llvm-objdump/X86/start-stop-address-relocatable-object.test new file mode 100644 index 0000000000000..37b522052607e --- /dev/null +++ b/llvm/test/tools/llvm-objdump/X86/start-stop-address-relocatable-object.test @@ -0,0 +1,46 @@ +## Show how --start-address and --stop-address work in a relocatable object. +## They limit the disassembly to the relative offset ranges within sections. +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump -d %t.o --start-address=1 --stop-address=2 | FileCheck %s --check-prefix=COMMON +# RUN: llvm-objdump -d %t.o --start-address=1 | FileCheck %s --check-prefixes=START,COMMON +# RUN: llvm-objdump -d %t.o --stop-address=2 | FileCheck %s --check-prefixes=STOP,COMMON + +# COMMON: Disassembly of section .text: +# COMMON-EMPTY: +# COMMON-NEXT: 0000000000000000 .text: +# STOP-NEXT: 0: 90 nop +# COMMON-NEXT: 1: 90 nop +# START-NEXT: 2: 90 nop +# COMMON-EMPTY: +# COMMON-NEXT: Disassembly of section .text2: +# COMMON-EMPTY: +# COMMON-NEXT: 0000000000000000 .text2: +# STOP-NEXT: 0: c3 retq +# COMMON-NEXT: 1: c3 retq +# START-NEXT: 2: c3 retq +# STOP-EMPTY: +# STOP-NEXT: Disassembly of section .text3: +# STOP-EMPTY: +# STOP-NEXT: 0000000000000000 .text3: +# STOP-NEXT: 0: cc int3 +# COMMON-NOT: {{.}} + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '909090' + - Name: .text2 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'c3c3c3' + - Name: .text3 + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: 'cc' diff --git a/llvm/test/tools/llvm-objdump/X86/start-stop-address.test b/llvm/test/tools/llvm-objdump/X86/start-stop-address.test index 4df49a92818ec..e8b390f25f0b8 100644 --- a/llvm/test/tools/llvm-objdump/X86/start-stop-address.test +++ b/llvm/test/tools/llvm-objdump/X86/start-stop-address.test @@ -1,8 +1,12 @@ // RUN: yaml2obj -o %t.out %p/Inputs/simple-executable-x86_64.yaml // RUN: llvm-objdump -d %t.out --start-address=0x18 --stop-address=0x2f | FileCheck %s -// RUN: llvm-objdump -d %t.out --start-address=0xc --stop-address=0x11 | FileCheck %s --check-prefix "CROSSSECTION" -// RUN: llvm-objdump -d %t.out --start-address=0x40 --stop-address=0x47 | FileCheck %s --check-prefix "CROSSDATA" +// RUN: llvm-objdump -d %t.out --start-address=0xc --stop-address=0x11 | FileCheck %s --check-prefix CROSSSECTION +// RUN: llvm-objdump -d %t.out --start-address=0x40 --stop-address=0x47 | FileCheck %s --check-prefix CROSSDATA +// RUN: llvm-objdump -d %t.out --start-address=0x40 | FileCheck %s --check-prefix START +// RUN: llvm-objdump -d %t.out --stop-address=0x11 | FileCheck %s --check-prefix STOP +// RUN: llvm-objdump -d %t.out --start-address=0xffffffff | FileCheck %s --check-prefix OUT-OF-RANGE +// CHECK-NOT: Disassembly // CHECK: Disassembly of section .anothertext: // CHECK-EMPTY: // CHECK-NEXT: main: @@ -10,8 +14,9 @@ // CHECK-NEXT: 20: c7 45 fc 00 00 00 00 movl $0, -4(%rbp) // CHECK-NEXT: 27: 48 89 45 f0 movq %rax, -16(%rbp) // CHECK-NEXT: 2b: 48 8b 45 f0 movq -16(%rbp), %rax -// CHECK-NOT: 2f: +// CHECK-NOT: {{.}} +// CROSSECTION-NOT: Disassembly // CROSSSECTION: Disassembly of section .text: // CROSSSECTION-EMPTY: // CROSSSECTION-NEXT: foo: @@ -22,12 +27,45 @@ // CROSSSECTION-EMPTY: // CROSSSECTION-NEXT: main: // CROSSSECTION-NEXT: 10: 55 pushq %rbp -// CROSSSECTION-NOT: 11: +// CROSSSECTION-NOT: {{.}} +// CROSSDATA-NOT: Disassembly // CROSSDATA: Disassembly of section .anothertext: // CROSSDATA: main: // CROSSDATA: 40: 48 83 c4 20 addq $32, %rsp // CROSSDATA: 44: 5d popq %rbp // CROSSDATA-DAG: somedata: // CROSSDATA-NEXT: 45: 74 65 te +// CROSSDATA-NOT: {{.}} +// START-NOT: Disassembly +// START: Disassembly of section .anothertext: +// START-EMPTY: +// START-NEXT: 0000000000000010 main: +// START-NEXT: 40: 48 83 c4 20 addq $32, %rsp +// START-NEXT: 44: 5d popq %rbp +// START-EMPTY: +// START-NEXT: 0000000000000045 somedata: +// START-NEXT: 45: 74 65 73 74 20 73 74 72 test str +// START-NEXT: 4d: 00 c3 .. + +// STOP: Disassembly of section .text: +// STOP-EMPTY: +// STOP-NEXT: 0000000000000000 foo: +// STOP-NEXT: 0: 55 pushq %rbp +// STOP-NEXT: 1: 48 89 e5 movq %rsp, %rbp +// STOP-NEXT: 4: 8b 04 25 a8 00 00 00 movl 168, %eax +// STOP-NEXT: b: 5d popq %rbp +// STOP-NEXT: c: c3 retq +// STOP-NEXT: d: 0f 1f 00 nopl (%rax) +// STOP-EMPTY: +// STOP-NEXT: Disassembly of section .anothertext: +// STOP-EMPTY: +// STOP-NEXT: 0000000000000010 main: +// STOP-NEXT: 10: 55 pushq %rbp +// STOP-NOT: {{.}} + +// OUT-OF-RANGE-NOT: Disassembly + +// RUN: not llvm-objdump -d %t.out --start-address=0x40 --stop-address=0x3f 2>&1 | FileCheck %s --check-prefix ERRMSG +// ERRMSG: error: Start address should be less than stop address. diff --git a/llvm/test/tools/llvm-objdump/X86/stripped-shared.test b/llvm/test/tools/llvm-objdump/X86/stripped-shared.test deleted file mode 100644 index c57155f4cd7ba..0000000000000 --- a/llvm/test/tools/llvm-objdump/X86/stripped-shared.test +++ /dev/null @@ -1,10 +0,0 @@ -// This test checks that dynamic symbols are used when disassembling elf files. -// RUN: llvm-objdump -d %p/Inputs/stripped-elf.so | FileCheck %s - -# CHECK: .init -# CHECK: .plt -# CHECK: .text -# CHECK: func0 -# CHECK: func1 -# CHECK: func2 -# CHECK: .fini From 43882b16a343fc848a9485d59479f48a34abdbdc Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Thu, 23 May 2019 12:35:26 +0000 Subject: [PATCH 0026/1176] [MergeICmps] Make the pass compatible with the new pass manager. Reviewers: gchatelet, spatel Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62287 llvm-svn: 361490 --- llvm/include/llvm/InitializePasses.h | 2 +- llvm/include/llvm/LinkAllPasses.h | 2 +- llvm/include/llvm/Transforms/Scalar.h | 2 +- .../llvm/Transforms/Scalar/MergeICmps.h | 25 +++ llvm/lib/CodeGen/TargetPassConfig.cpp | 2 +- llvm/lib/Passes/PassBuilder.cpp | 1 + llvm/lib/Passes/PassRegistry.def | 1 + llvm/lib/Transforms/Scalar/MergeICmps.cpp | 148 +++++++++--------- llvm/lib/Transforms/Scalar/Scalar.cpp | 2 +- .../MergeICmps/X86/pair-int32-int32.ll | 2 +- 10 files changed, 110 insertions(+), 77 deletions(-) create mode 100644 llvm/include/llvm/Transforms/Scalar/MergeICmps.h diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index f60a99c62051b..fa7909f14cd3d 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -279,7 +279,7 @@ void initializeMemorySSAPrinterLegacyPassPass(PassRegistry&); void initializeMemorySSAWrapperPassPass(PassRegistry&); void initializeMemorySanitizerLegacyPassPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); -void initializeMergeICmpsPass(PassRegistry&); +void initializeMergeICmpsLegacyPassPass(PassRegistry &); void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&); void initializeMetaRenamerPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index fb3b19e2dab95..a8354125c9d38 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -191,7 +191,7 @@ namespace { (void) llvm::createPostOrderFunctionAttrsLegacyPass(); (void) llvm::createReversePostOrderFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); - (void) llvm::createMergeICmpsPass(); + (void) llvm::createMergeICmpsLegacyPass(); (void) llvm::createExpandMemCmpPass(); std::string buf; llvm::raw_string_ostream os(buf); diff --git a/llvm/include/llvm/Transforms/Scalar.h b/llvm/include/llvm/Transforms/Scalar.h index 8f9d337e385bd..f9360b5ee2c82 100644 --- a/llvm/include/llvm/Transforms/Scalar.h +++ b/llvm/include/llvm/Transforms/Scalar.h @@ -371,7 +371,7 @@ Pass *createLowerWidenableConditionPass(); // // MergeICmps - Merge integer comparison chains into a memcmp // -Pass *createMergeICmpsPass(); +Pass *createMergeICmpsLegacyPass(); //===----------------------------------------------------------------------===// // diff --git a/llvm/include/llvm/Transforms/Scalar/MergeICmps.h b/llvm/include/llvm/Transforms/Scalar/MergeICmps.h new file mode 100644 index 0000000000000..63bdbf8f4d095 --- /dev/null +++ b/llvm/include/llvm/Transforms/Scalar/MergeICmps.h @@ -0,0 +1,25 @@ +//===- MergeICmps.h -----------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_MERGEICMPS_H +#define LLVM_TRANSFORMS_SCALAR_MERGEICMPS_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Function; + +struct MergeICmpsPass + : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_MERGEICMPS_H diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 09ae7bc02e454..1b7d6be4d7b8e 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -646,7 +646,7 @@ void TargetPassConfig::addIRPasses() { // into optimally-sized loads and compares. The transforms are enabled by a // target lowering hook. if (!DisableMergeICmps) - addPass(createMergeICmpsPass()); + addPass(createMergeICmpsLegacyPass()); addPass(createExpandMemCmpPass()); } diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index e4d15277899be..c7976ce2702d2 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -142,6 +142,7 @@ #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" +#include "llvm/Transforms/Scalar/MergeICmps.h" #include "llvm/Transforms/Scalar/NaryReassociate.h" #include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 0d614d1d69b62..cf601ec9ebc54 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -190,6 +190,7 @@ FUNCTION_PASS("loop-sink", LoopSinkPass()) FUNCTION_PASS("lowerinvoke", LowerInvokePass()) FUNCTION_PASS("mem2reg", PromotePass()) FUNCTION_PASS("memcpyopt", MemCpyOptPass()) +FUNCTION_PASS("mergeicmps", MergeICmpsPass()) FUNCTION_PASS("mldst-motion", MergedLoadStoreMotionPass()) FUNCTION_PASS("nary-reassociate", NaryReassociatePass()) FUNCTION_PASS("newgvn", NewGVNPass()) diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp index b55d28c3455b3..086c2f33afb6f 100644 --- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp +++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp @@ -41,6 +41,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Scalar/MergeICmps.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/Loads.h" @@ -214,19 +215,19 @@ class BCECmpBlock { // Returns true if the non-BCE-cmp instructions can be separated from BCE-cmp // instructions in the block. - bool canSplit(AliasAnalysis *AA) const; + bool canSplit(AliasAnalysis &AA) const; // Return true if this all the relevant instructions in the BCE-cmp-block can // be sunk below this instruction. By doing this, we know we can separate the // BCE-cmp-block instructions from the non-BCE-cmp-block instructions in the // block. bool canSinkBCECmpInst(const Instruction *, DenseSet &, - AliasAnalysis *AA) const; + AliasAnalysis &AA) const; // We can separate the BCE-cmp-block instructions and the non-BCE-cmp-block // instructions. Split the old block and move all non-BCE-cmp-insts into the // new parent block. - void split(BasicBlock *NewParent, AliasAnalysis *AA) const; + void split(BasicBlock *NewParent, AliasAnalysis &AA) const; // The basic block where this comparison happens. BasicBlock *BB = nullptr; @@ -245,7 +246,7 @@ class BCECmpBlock { bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst, DenseSet &BlockInsts, - AliasAnalysis *AA) const { + AliasAnalysis &AA) const { // If this instruction has side effects and its in middle of the BCE cmp block // instructions, then bail for now. if (Inst->mayHaveSideEffects()) { @@ -255,9 +256,9 @@ bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst, // Disallow stores that might alias the BCE operands MemoryLocation LLoc = MemoryLocation::get(Lhs_.LoadI); MemoryLocation RLoc = MemoryLocation::get(Rhs_.LoadI); - if (isModSet(AA->getModRefInfo(Inst, LLoc)) || - isModSet(AA->getModRefInfo(Inst, RLoc))) - return false; + if (isModSet(AA.getModRefInfo(Inst, LLoc)) || + isModSet(AA.getModRefInfo(Inst, RLoc))) + return false; } // Make sure this instruction does not use any of the BCE cmp block // instructions as operand. @@ -268,7 +269,7 @@ bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst, return true; } -void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis *AA) const { +void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis &AA) const { DenseSet BlockInsts( {Lhs_.GEP, Rhs_.GEP, Lhs_.LoadI, Rhs_.LoadI, CmpI, BranchI}); llvm::SmallVector OtherInsts; @@ -288,7 +289,7 @@ void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis *AA) const { } } -bool BCECmpBlock::canSplit(AliasAnalysis *AA) const { +bool BCECmpBlock::canSplit(AliasAnalysis &AA) const { DenseSet BlockInsts( {Lhs_.GEP, Rhs_.GEP, Lhs_.LoadI, Rhs_.LoadI, CmpI, BranchI}); for (Instruction &Inst : *BB) { @@ -404,16 +405,16 @@ static inline void enqueueBlock(std::vector &Comparisons, // A chain of comparisons. class BCECmpChain { public: - BCECmpChain(const std::vector &Blocks, PHINode &Phi, - AliasAnalysis *AA); + BCECmpChain(const std::vector &Blocks, PHINode &Phi, + AliasAnalysis &AA); - int size() const { return Comparisons_.size(); } + int size() const { return Comparisons_.size(); } #ifdef MERGEICMPS_DOT_ON void dump() const; #endif // MERGEICMPS_DOT_ON - bool simplify(const TargetLibraryInfo *const TLI, AliasAnalysis *AA, + bool simplify(const TargetLibraryInfo &TLI, AliasAnalysis &AA, DomTreeUpdater &DTU); private: @@ -432,7 +433,7 @@ class BCECmpChain { }; BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, - AliasAnalysis *AA) + AliasAnalysis &AA) : Phi_(Phi) { assert(!Blocks.empty() && "a chain should have at least one block"); // Now look inside blocks to check for BCE comparisons. @@ -604,9 +605,8 @@ class MergedBlockName { static BasicBlock *mergeComparisons(ArrayRef Comparisons, BasicBlock *const InsertBefore, BasicBlock *const NextCmpBlock, - PHINode &Phi, - const TargetLibraryInfo *const TLI, - AliasAnalysis *AA, DomTreeUpdater &DTU) { + PHINode &Phi, const TargetLibraryInfo &TLI, + AliasAnalysis &AA, DomTreeUpdater &DTU) { assert(!Comparisons.empty() && "merging zero comparisons"); LLVMContext &Context = NextCmpBlock->getContext(); const BCECmpBlock &FirstCmp = Comparisons[0]; @@ -652,7 +652,7 @@ static BasicBlock *mergeComparisons(ArrayRef Comparisons, Value *const MemCmpCall = emitMemCmp( Lhs, Rhs, ConstantInt::get(DL.getIntPtrType(Context), TotalSizeBits / 8), Builder, - DL, TLI); + DL, &TLI); IsEqual = Builder.CreateICmpEQ( MemCmpCall, ConstantInt::get(Type::getInt32Ty(Context), 0)); } @@ -674,8 +674,8 @@ static BasicBlock *mergeComparisons(ArrayRef Comparisons, return BB; } -bool BCECmpChain::simplify(const TargetLibraryInfo *const TLI, - AliasAnalysis *AA, DomTreeUpdater &DTU) { +bool BCECmpChain::simplify(const TargetLibraryInfo &TLI, AliasAnalysis &AA, + DomTreeUpdater &DTU) { assert(Comparisons_.size() >= 2 && "simplifying trivial BCECmpChain"); // First pass to check if there is at least one merge. If not, we don't do // anything and we keep analysis passes intact. @@ -694,9 +694,9 @@ bool BCECmpChain::simplify(const TargetLibraryInfo *const TLI, // Effectively merge blocks. We go in the reverse direction from the phi block // so that the next block is always available to branch to. - const auto mergeRange = [this, TLI, AA, &DTU](int I, int Num, - BasicBlock *InsertBefore, - BasicBlock *Next) { + const auto mergeRange = [this, &TLI, &AA, &DTU](int I, int Num, + BasicBlock *InsertBefore, + BasicBlock *Next) { return mergeComparisons(makeArrayRef(Comparisons_).slice(I, Num), InsertBefore, Next, Phi_, TLI, AA, DTU); }; @@ -790,8 +790,8 @@ std::vector getOrderedBlocks(PHINode &Phi, return Blocks; } -bool processPhi(PHINode &Phi, const TargetLibraryInfo *const TLI, - AliasAnalysis *AA, DomTreeUpdater &DTU) { +bool processPhi(PHINode &Phi, const TargetLibraryInfo &TLI, AliasAnalysis &AA, + DomTreeUpdater &DTU) { LLVM_DEBUG(dbgs() << "processPhi()\n"); if (Phi.getNumIncomingValues() <= 1) { LLVM_DEBUG(dbgs() << "skip: only one incoming value in phi\n"); @@ -859,12 +859,40 @@ bool processPhi(PHINode &Phi, const TargetLibraryInfo *const TLI, return CmpChain.simplify(TLI, AA, DTU); } -class MergeICmps : public FunctionPass { - public: +static bool runImpl(Function &F, const TargetLibraryInfo &TLI, + const TargetTransformInfo &TTI, AliasAnalysis &AA, + DominatorTree *DT) { + LLVM_DEBUG(dbgs() << "MergeICmpsLegacyPass: " << F.getName() << "\n"); + + // We only try merging comparisons if the target wants to expand memcmp later. + // The rationale is to avoid turning small chains into memcmp calls. + if (!TTI.enableMemCmpExpansion(true)) + return false; + + // If we don't have memcmp avaiable we can't emit calls to it. + if (!TLI.has(LibFunc_memcmp)) + return false; + + DomTreeUpdater DTU(DT, /*PostDominatorTree*/ nullptr, + DomTreeUpdater::UpdateStrategy::Eager); + + bool MadeChange = false; + + for (auto BBIt = ++F.begin(); BBIt != F.end(); ++BBIt) { + // A Phi operation is always first in a basic block. + if (auto *const Phi = dyn_cast(&*BBIt->begin())) + MadeChange |= processPhi(*Phi, TLI, AA, DTU); + } + + return MadeChange; +} + +class MergeICmpsLegacyPass : public FunctionPass { +public: static char ID; - MergeICmps() : FunctionPass(ID) { - initializeMergeICmpsPass(*PassRegistry::getPassRegistry()); + MergeICmpsLegacyPass() : FunctionPass(ID) { + initializeMergeICmpsLegacyPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override { @@ -874,12 +902,8 @@ class MergeICmps : public FunctionPass { // MergeICmps does not need the DominatorTree, but we update it if it's // already available. auto *DTWP = getAnalysisIfAvailable(); - DomTreeUpdater DTU(DTWP ? &DTWP->getDomTree() : nullptr, - /*PostDominatorTree*/ nullptr, - DomTreeUpdater::UpdateStrategy::Eager); - AliasAnalysis *AA = &getAnalysis().getAAResults(); - auto PA = runImpl(F, &TLI, &TTI, AA, DTU); - return !PA.areAllPreserved(); + auto &AA = getAnalysis().getAAResults(); + return runImpl(F, TLI, TTI, AA, DTWP ? &DTWP->getDomTree() : nullptr); } private: @@ -890,50 +914,32 @@ class MergeICmps : public FunctionPass { AU.addPreserved(); AU.addPreserved(); } - - PreservedAnalyses runImpl(Function &F, const TargetLibraryInfo *TLI, - const TargetTransformInfo *TTI, AliasAnalysis *AA, - DomTreeUpdater &DTU); }; -PreservedAnalyses MergeICmps::runImpl(Function &F, const TargetLibraryInfo *TLI, - const TargetTransformInfo *TTI, - AliasAnalysis *AA, DomTreeUpdater &DTU) { - LLVM_DEBUG(dbgs() << "MergeICmpsPass: " << F.getName() << "\n"); - - // We only try merging comparisons if the target wants to expand memcmp later. - // The rationale is to avoid turning small chains into memcmp calls. - if (!TTI->enableMemCmpExpansion(true)) return PreservedAnalyses::all(); +} // namespace - // If we don't have memcmp avaiable we can't emit calls to it. - if (!TLI->has(LibFunc_memcmp)) - return PreservedAnalyses::all(); +char MergeICmpsLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(MergeICmpsLegacyPass, "mergeicmps", + "Merge contiguous icmps into a memcmp", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) +INITIALIZE_PASS_END(MergeICmpsLegacyPass, "mergeicmps", + "Merge contiguous icmps into a memcmp", false, false) - bool MadeChange = false; +Pass *llvm::createMergeICmpsLegacyPass() { return new MergeICmpsLegacyPass(); } - for (auto BBIt = ++F.begin(); BBIt != F.end(); ++BBIt) { - // A Phi operation is always first in a basic block. - if (auto *const Phi = dyn_cast(&*BBIt->begin())) - MadeChange |= processPhi(*Phi, TLI, AA, DTU); - } - - if (!MadeChange) +PreservedAnalyses MergeICmpsPass::run(Function &F, + FunctionAnalysisManager &AM) { + auto &TLI = AM.getResult(F); + auto &TTI = AM.getResult(F); + auto &AA = AM.getResult(F); + auto *DT = AM.getCachedResult(F); + const bool MadeChanges = runImpl(F, TLI, TTI, AA, DT); + if (!MadeChanges) return PreservedAnalyses::all(); PreservedAnalyses PA; PA.preserve(); PA.preserve(); return PA; } - -} // namespace - -char MergeICmps::ID = 0; -INITIALIZE_PASS_BEGIN(MergeICmps, "mergeicmps", - "Merge contiguous icmps into a memcmp", false, false) -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(MergeICmps, "mergeicmps", - "Merge contiguous icmps into a memcmp", false, false) - -Pass *llvm::createMergeICmpsPass() { return new MergeICmps(); } diff --git a/llvm/lib/Transforms/Scalar/Scalar.cpp b/llvm/lib/Transforms/Scalar/Scalar.cpp index 2584cf04c9337..869cf00e0a89c 100644 --- a/llvm/lib/Transforms/Scalar/Scalar.cpp +++ b/llvm/lib/Transforms/Scalar/Scalar.cpp @@ -83,7 +83,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeLowerGuardIntrinsicLegacyPassPass(Registry); initializeLowerWidenableConditionLegacyPassPass(Registry); initializeMemCpyOptLegacyPassPass(Registry); - initializeMergeICmpsPass(Registry); + initializeMergeICmpsLegacyPassPass(Registry); initializeMergedLoadStoreMotionLegacyPassPass(Registry); initializeNaryReassociateLegacyPassPass(Registry); initializePartiallyInlineLibCallsLegacyPassPass(Registry); diff --git a/llvm/test/Transforms/MergeICmps/X86/pair-int32-int32.ll b/llvm/test/Transforms/MergeICmps/X86/pair-int32-int32.ll index c4f0ea8ee54e3..66ba101cdb25e 100644 --- a/llvm/test/Transforms/MergeICmps/X86/pair-int32-int32.ll +++ b/llvm/test/Transforms/MergeICmps/X86/pair-int32-int32.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -mergeicmps -verify-dom-info -mtriple=x86_64-unknown-unknown -S | FileCheck %s --check-prefix=X86 +; RUN: opt < %s -passes='require,mergeicmps,verify' -mtriple=x86_64-unknown-unknown -S | FileCheck %s --check-prefix=X86 ; RUN: opt < %s -mergeicmps -verify-dom-info -mtriple=x86_64-unknown-unknown -S -disable-simplify-libcalls | FileCheck %s --check-prefix=X86-NOBUILTIN %S = type { i32, i32 } From 591c793b48e487382c30e352c0c3b7ae60b45a87 Mon Sep 17 00:00:00 2001 From: James Henderson Date: Thu, 23 May 2019 12:38:06 +0000 Subject: [PATCH 0027/1176] [llvm-objdump][test] Make test names consistent This change renames a number of the disassembly tests to standardise disasm/diassemble/disassembly to disassemble. Requested in https://reviews.llvm.org/D62255. llvm-svn: 361491 --- ...-mangled-name.test => disassemble-functions-mangled-name.test} | 0 .../{disasm-specific-funcs.test => disassemble-functions.test} | 0 .../X86/{disassembly-show-raw.test => disassemble-show-raw.test} | 0 .../llvm-objdump/X86/{disasm-text.test => disassemble-text.test} | 0 ...eroes-relocations.test => disassemble-zeroes-relocations.test} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename llvm/test/tools/llvm-objdump/X86/{disasm-specific-funcs-mangled-name.test => disassemble-functions-mangled-name.test} (100%) rename llvm/test/tools/llvm-objdump/X86/{disasm-specific-funcs.test => disassemble-functions.test} (100%) rename llvm/test/tools/llvm-objdump/X86/{disassembly-show-raw.test => disassemble-show-raw.test} (100%) rename llvm/test/tools/llvm-objdump/X86/{disasm-text.test => disassemble-text.test} (100%) rename llvm/test/tools/llvm-objdump/X86/{disasm-zeroes-relocations.test => disassemble-zeroes-relocations.test} (100%) diff --git a/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs-mangled-name.test b/llvm/test/tools/llvm-objdump/X86/disassemble-functions-mangled-name.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs-mangled-name.test rename to llvm/test/tools/llvm-objdump/X86/disassemble-functions-mangled-name.test diff --git a/llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs.test b/llvm/test/tools/llvm-objdump/X86/disassemble-functions.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/disasm-specific-funcs.test rename to llvm/test/tools/llvm-objdump/X86/disassemble-functions.test diff --git a/llvm/test/tools/llvm-objdump/X86/disassembly-show-raw.test b/llvm/test/tools/llvm-objdump/X86/disassemble-show-raw.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/disassembly-show-raw.test rename to llvm/test/tools/llvm-objdump/X86/disassemble-show-raw.test diff --git a/llvm/test/tools/llvm-objdump/X86/disasm-text.test b/llvm/test/tools/llvm-objdump/X86/disassemble-text.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/disasm-text.test rename to llvm/test/tools/llvm-objdump/X86/disassemble-text.test diff --git a/llvm/test/tools/llvm-objdump/X86/disasm-zeroes-relocations.test b/llvm/test/tools/llvm-objdump/X86/disassemble-zeroes-relocations.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/disasm-zeroes-relocations.test rename to llvm/test/tools/llvm-objdump/X86/disassemble-zeroes-relocations.test From a4c7873dac5f416ff3f03f627484fbcfe49f654e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 23 May 2019 12:43:08 +0000 Subject: [PATCH 0028/1176] [llvm-objdump][test] Make MachO test names consistent We have macho-disassembl{e,y}-*. Rename macho-disassembly-* to macho-disassemble-* for consistency. llvm-svn: 361492 --- ...acho-disassembly-g-dsym.test => macho-disassemble-g-dsym.test} | 0 ...assembly-kextbundle.test => macho-disassemble-kextbundle.test} | 0 ...-disassembly-stripped.test => macho-disassemble-stripped.test} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename llvm/test/tools/llvm-objdump/X86/{macho-disassembly-g-dsym.test => macho-disassemble-g-dsym.test} (100%) rename llvm/test/tools/llvm-objdump/X86/{macho-disassembly-kextbundle.test => macho-disassemble-kextbundle.test} (100%) rename llvm/test/tools/llvm-objdump/X86/{macho-disassembly-stripped.test => macho-disassemble-stripped.test} (100%) diff --git a/llvm/test/tools/llvm-objdump/X86/macho-disassembly-g-dsym.test b/llvm/test/tools/llvm-objdump/X86/macho-disassemble-g-dsym.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/macho-disassembly-g-dsym.test rename to llvm/test/tools/llvm-objdump/X86/macho-disassemble-g-dsym.test diff --git a/llvm/test/tools/llvm-objdump/X86/macho-disassembly-kextbundle.test b/llvm/test/tools/llvm-objdump/X86/macho-disassemble-kextbundle.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/macho-disassembly-kextbundle.test rename to llvm/test/tools/llvm-objdump/X86/macho-disassemble-kextbundle.test diff --git a/llvm/test/tools/llvm-objdump/X86/macho-disassembly-stripped.test b/llvm/test/tools/llvm-objdump/X86/macho-disassemble-stripped.test similarity index 100% rename from llvm/test/tools/llvm-objdump/X86/macho-disassembly-stripped.test rename to llvm/test/tools/llvm-objdump/X86/macho-disassemble-stripped.test From 5dabe03b4178c8d276cc1732fed2813418513dce Mon Sep 17 00:00:00 2001 From: Alex Bradbury Date: Thu, 23 May 2019 12:43:13 +0000 Subject: [PATCH 0029/1176] [RISCV][NFC] Add nounwind attribute to functions missing it in test/CodeGen/RISCV r360897 was incomplete, must have applied an old/wip patch. This is in preparation for emitting CFI directives. llvm-svn: 361493 --- .../test/CodeGen/RISCV/addc-adde-sube-subc.ll | 4 +- llvm/test/CodeGen/RISCV/addcarry.ll | 2 +- llvm/test/CodeGen/RISCV/alu64.ll | 20 +++---- .../test/CodeGen/RISCV/atomic-cmpxchg-flag.ll | 2 +- llvm/test/CodeGen/RISCV/bare-select.ll | 4 +- llvm/test/CodeGen/RISCV/branch-relaxation.ll | 4 +- llvm/test/CodeGen/RISCV/branch.ll | 2 +- .../CodeGen/RISCV/get-setcc-result-type.ll | 2 +- .../CodeGen/RISCV/hoist-global-addr-base.ll | 17 +++--- llvm/test/CodeGen/RISCV/inline-asm.ll | 8 +-- llvm/test/CodeGen/RISCV/jumptable.ll | 2 +- llvm/test/CodeGen/RISCV/legalize-fneg.ll | 6 +- llvm/test/CodeGen/RISCV/rotl-rotr.ll | 4 +- .../test/CodeGen/RISCV/rv64i-tricky-shifts.ll | 6 +- llvm/test/CodeGen/RISCV/select-cc.ll | 2 +- llvm/test/CodeGen/RISCV/sext-zext-trunc.ll | 60 +++++++++---------- llvm/test/CodeGen/RISCV/tail-calls.ll | 18 +++--- .../CodeGen/RISCV/zext-with-load-is-free.ll | 4 +- 18 files changed, 83 insertions(+), 84 deletions(-) diff --git a/llvm/test/CodeGen/RISCV/addc-adde-sube-subc.ll b/llvm/test/CodeGen/RISCV/addc-adde-sube-subc.ll index 7c28df4c30ff3..068e52f6175eb 100644 --- a/llvm/test/CodeGen/RISCV/addc-adde-sube-subc.ll +++ b/llvm/test/CodeGen/RISCV/addc-adde-sube-subc.ll @@ -4,7 +4,7 @@ ; Ensure that the ISDOpcodes ADDC, ADDE, SUBC, SUBE are handled correctly -define i64 @addc_adde(i64 %a, i64 %b) { +define i64 @addc_adde(i64 %a, i64 %b) nounwind { ; RV32I-LABEL: addc_adde: ; RV32I: # %bb.0: ; RV32I-NEXT: add a1, a1, a3 @@ -17,7 +17,7 @@ define i64 @addc_adde(i64 %a, i64 %b) { ret i64 %1 } -define i64 @subc_sube(i64 %a, i64 %b) { +define i64 @subc_sube(i64 %a, i64 %b) nounwind { ; RV32I-LABEL: subc_sube: ; RV32I: # %bb.0: ; RV32I-NEXT: sub a1, a1, a3 diff --git a/llvm/test/CodeGen/RISCV/addcarry.ll b/llvm/test/CodeGen/RISCV/addcarry.ll index f409dac1a71a5..15fe53e9f24a7 100644 --- a/llvm/test/CodeGen/RISCV/addcarry.ll +++ b/llvm/test/CodeGen/RISCV/addcarry.ll @@ -6,7 +6,7 @@ declare i64 @llvm.smul.fix.i64 (i64, i64, i32) -define i64 @addcarry(i64 %x, i64 %y) { +define i64 @addcarry(i64 %x, i64 %y) nounwind { ; RISCV32-LABEL: addcarry: ; RISCV32: # %bb.0: ; RISCV32-NEXT: mul a4, a0, a3 diff --git a/llvm/test/CodeGen/RISCV/alu64.ll b/llvm/test/CodeGen/RISCV/alu64.ll index fcf695ff2504b..0a44a380df72e 100644 --- a/llvm/test/CodeGen/RISCV/alu64.ll +++ b/llvm/test/CodeGen/RISCV/alu64.ll @@ -375,7 +375,7 @@ define i64 @and(i64 %a, i64 %b) nounwind { ; RV64I-only instructions -define signext i32 @addiw(i32 signext %a) { +define signext i32 @addiw(i32 signext %a) nounwind { ; RV64I-LABEL: addiw: ; RV64I: # %bb.0: ; RV64I-NEXT: addiw a0, a0, 123 @@ -389,7 +389,7 @@ define signext i32 @addiw(i32 signext %a) { ret i32 %1 } -define signext i32 @slliw(i32 signext %a) { +define signext i32 @slliw(i32 signext %a) nounwind { ; RV64I-LABEL: slliw: ; RV64I: # %bb.0: ; RV64I-NEXT: slliw a0, a0, 17 @@ -403,7 +403,7 @@ define signext i32 @slliw(i32 signext %a) { ret i32 %1 } -define signext i32 @srliw(i32 %a) { +define signext i32 @srliw(i32 %a) nounwind { ; RV64I-LABEL: srliw: ; RV64I: # %bb.0: ; RV64I-NEXT: srliw a0, a0, 8 @@ -417,7 +417,7 @@ define signext i32 @srliw(i32 %a) { ret i32 %1 } -define signext i32 @sraiw(i32 %a) { +define signext i32 @sraiw(i32 %a) nounwind { ; RV64I-LABEL: sraiw: ; RV64I: # %bb.0: ; RV64I-NEXT: sraiw a0, a0, 9 @@ -431,7 +431,7 @@ define signext i32 @sraiw(i32 %a) { ret i32 %1 } -define signext i32 @sextw(i32 zeroext %a) { +define signext i32 @sextw(i32 zeroext %a) nounwind { ; RV64I-LABEL: sextw: ; RV64I: # %bb.0: ; RV64I-NEXT: sext.w a0, a0 @@ -443,7 +443,7 @@ define signext i32 @sextw(i32 zeroext %a) { ret i32 %a } -define signext i32 @addw(i32 signext %a, i32 signext %b) { +define signext i32 @addw(i32 signext %a, i32 signext %b) nounwind { ; RV64I-LABEL: addw: ; RV64I: # %bb.0: ; RV64I-NEXT: addw a0, a0, a1 @@ -457,7 +457,7 @@ define signext i32 @addw(i32 signext %a, i32 signext %b) { ret i32 %1 } -define signext i32 @subw(i32 signext %a, i32 signext %b) { +define signext i32 @subw(i32 signext %a, i32 signext %b) nounwind { ; RV64I-LABEL: subw: ; RV64I: # %bb.0: ; RV64I-NEXT: subw a0, a0, a1 @@ -471,7 +471,7 @@ define signext i32 @subw(i32 signext %a, i32 signext %b) { ret i32 %1 } -define signext i32 @sllw(i32 signext %a, i32 zeroext %b) { +define signext i32 @sllw(i32 signext %a, i32 zeroext %b) nounwind { ; RV64I-LABEL: sllw: ; RV64I: # %bb.0: ; RV64I-NEXT: sllw a0, a0, a1 @@ -485,7 +485,7 @@ define signext i32 @sllw(i32 signext %a, i32 zeroext %b) { ret i32 %1 } -define signext i32 @srlw(i32 signext %a, i32 zeroext %b) { +define signext i32 @srlw(i32 signext %a, i32 zeroext %b) nounwind { ; RV64I-LABEL: srlw: ; RV64I: # %bb.0: ; RV64I-NEXT: srlw a0, a0, a1 @@ -499,7 +499,7 @@ define signext i32 @srlw(i32 signext %a, i32 zeroext %b) { ret i32 %1 } -define signext i32 @sraw(i64 %a, i32 zeroext %b) { +define signext i32 @sraw(i64 %a, i32 zeroext %b) nounwind { ; RV64I-LABEL: sraw: ; RV64I: # %bb.0: ; RV64I-NEXT: sraw a0, a0, a1 diff --git a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll index e5d619dc369b3..b331b4b9926b6 100644 --- a/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll +++ b/llvm/test/CodeGen/RISCV/atomic-cmpxchg-flag.ll @@ -7,7 +7,7 @@ ; higher bits were masked to zero for the comparison. define i1 @cmpxchg_i32_seq_cst_seq_cst(i32* %ptr, i32 signext %cmp, - i32 signext %val) { + i32 signext %val) nounwind { ; RV64IA-LABEL: cmpxchg_i32_seq_cst_seq_cst: ; RV64IA: # %bb.0: # %entry ; RV64IA-NEXT: .LBB0_1: # %entry diff --git a/llvm/test/CodeGen/RISCV/bare-select.ll b/llvm/test/CodeGen/RISCV/bare-select.ll index 59add65d1db78..1b8f2f63e99d5 100644 --- a/llvm/test/CodeGen/RISCV/bare-select.ll +++ b/llvm/test/CodeGen/RISCV/bare-select.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck %s -check-prefix=RV32I -define i32 @bare_select(i1 %a, i32 %b, i32 %c) { +define i32 @bare_select(i1 %a, i32 %b, i32 %c) nounwind { ; RV32I-LABEL: bare_select: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -16,7 +16,7 @@ define i32 @bare_select(i1 %a, i32 %b, i32 %c) { ret i32 %1 } -define float @bare_select_float(i1 %a, float %b, float %c) { +define float @bare_select_float(i1 %a, float %b, float %c) nounwind { ; RV32I-LABEL: bare_select_float: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 diff --git a/llvm/test/CodeGen/RISCV/branch-relaxation.ll b/llvm/test/CodeGen/RISCV/branch-relaxation.ll index 2be50d10ae948..cd589dd9cab37 100644 --- a/llvm/test/CodeGen/RISCV/branch-relaxation.ll +++ b/llvm/test/CodeGen/RISCV/branch-relaxation.ll @@ -3,7 +3,7 @@ ; RUN: -o /dev/null 2>&1 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s | FileCheck %s -define void @relax_bcc(i1 %a) { +define void @relax_bcc(i1 %a) nounwind { ; CHECK-LABEL: relax_bcc: ; CHECK: # %bb.0: ; CHECK-NEXT: andi a0, a0, 1 @@ -25,7 +25,7 @@ tail: ret void } -define i32 @relax_jal(i1 %a) { +define i32 @relax_jal(i1 %a) nounwind { ; CHECK-LABEL: relax_jal: ; CHECK: # %bb.0: ; CHECK-NEXT: andi a0, a0, 1 diff --git a/llvm/test/CodeGen/RISCV/branch.ll b/llvm/test/CodeGen/RISCV/branch.ll index 71daf0e57b90e..e834499280328 100644 --- a/llvm/test/CodeGen/RISCV/branch.ll +++ b/llvm/test/CodeGen/RISCV/branch.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV32I %s -define void @foo(i32 %a, i32 *%b, i1 %c) { +define void @foo(i32 %a, i32 *%b, i1 %c) nounwind { ; RV32I-LABEL: foo: ; RV32I: # %bb.0: ; RV32I-NEXT: lw a3, 0(a1) diff --git a/llvm/test/CodeGen/RISCV/get-setcc-result-type.ll b/llvm/test/CodeGen/RISCV/get-setcc-result-type.ll index 507f04822b865..fe326b383ec0a 100644 --- a/llvm/test/CodeGen/RISCV/get-setcc-result-type.ll +++ b/llvm/test/CodeGen/RISCV/get-setcc-result-type.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV32I %s -define void @getSetCCResultType(<4 x i32>* %p, <4 x i32>* %q) { +define void @getSetCCResultType(<4 x i32>* %p, <4 x i32>* %q) nounwind { ; RV32I-LABEL: getSetCCResultType: ; RV32I: # %bb.0: # %entry ; RV32I-NEXT: lw a1, 12(a0) diff --git a/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll b/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll index 2a1d5ed1a0844..b00873ce486d6 100644 --- a/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll +++ b/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll @@ -7,7 +7,7 @@ @g = global [1048576 x i8] zeroinitializer, align 1 -define dso_local void @multiple_stores() local_unnamed_addr { +define dso_local void @multiple_stores() local_unnamed_addr nounwind { ; CHECK-LABEL: multiple_stores: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lui a0, %hi(s) @@ -23,7 +23,7 @@ entry: ret void } -define dso_local void @control_flow_with_mem_access() local_unnamed_addr #0 { +define dso_local void @control_flow_with_mem_access() local_unnamed_addr nounwind { ; CHECK-LABEL: control_flow_with_mem_access: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lui a0, %hi(s) @@ -57,7 +57,7 @@ if.end: ; preds = %if.then, %entry ; lui a0, 18 ---> offset ; addi a0, a0, -160 ; add a0, a0, a1 ---> base + offset. -define i8* @big_offset_neg_addi() { +define i8* @big_offset_neg_addi() nounwind { ; CHECK-LABEL: big_offset_neg_addi: ; CHECK: # %bb.0: ; CHECK-NEXT: lui a0, %hi(g+73568) @@ -72,7 +72,7 @@ define i8* @big_offset_neg_addi() { ; addi a0, a0, %lo(g) ; lui a1, 128 ---> offset ; add a0, a0, a1 ---> base + offset. -define i8* @big_offset_lui_tail() { +define i8* @big_offset_lui_tail() nounwind { ; CHECK-LABEL: big_offset_lui_tail: ; CHECK: # %bb.0: ; CHECK-NEXT: lui a0, %hi(g+524288) @@ -81,7 +81,7 @@ define i8* @big_offset_lui_tail() { ret i8* getelementptr inbounds ([1048576 x i8], [1048576 x i8]* @g, i32 0, i32 524288) } -define dso_local i32* @big_offset_one_use() local_unnamed_addr { +define dso_local i32* @big_offset_one_use() local_unnamed_addr nounwind { ; CHECK-LABEL: big_offset_one_use: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lui a0, %hi(s+16572) @@ -91,7 +91,7 @@ entry: ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 5) } -define dso_local i32* @small_offset_one_use() local_unnamed_addr { +define dso_local i32* @small_offset_one_use() local_unnamed_addr nounwind { ; CHECK-LABEL: small_offset_one_use: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lui a0, %hi(s+160) @@ -101,8 +101,7 @@ entry: ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1) } -; Function Attrs: norecurse nounwind optsize readonly -define dso_local i32* @control_flow_no_mem(i32 %n) local_unnamed_addr #1 { +define dso_local i32* @control_flow_no_mem(i32 %n) local_unnamed_addr nounwind { ; CHECK-LABEL: control_flow_no_mem: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lui a0, %hi(s) @@ -156,7 +155,7 @@ if.end: declare void @abort() -define dso_local void @one_store() local_unnamed_addr { +define dso_local void @one_store() local_unnamed_addr nounwind { ; CHECK-LABEL: one_store: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lui a0, %hi(s+160) diff --git a/llvm/test/CodeGen/RISCV/inline-asm.ll b/llvm/test/CodeGen/RISCV/inline-asm.ll index f17852cff25ae..5096d45e3ca08 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm.ll @@ -6,7 +6,7 @@ @gi = external global i32 -define i32 @constraint_r(i32 %a) { +define i32 @constraint_r(i32 %a) nounwind { ; RV32I-LABEL: constraint_r: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a1, %hi(gi) @@ -29,7 +29,7 @@ define i32 @constraint_r(i32 %a) { ret i32 %2 } -define i32 @constraint_i(i32 %a) { +define i32 @constraint_i(i32 %a) nounwind { ; RV32I-LABEL: constraint_i: ; RV32I: # %bb.0: ; RV32I-NEXT: #APP @@ -48,7 +48,7 @@ define i32 @constraint_i(i32 %a) { ret i32 %2 } -define void @constraint_m(i32* %a) { +define void @constraint_m(i32* %a) nounwind { ; RV32I-LABEL: constraint_m: ; RV32I: # %bb.0: ; RV32I-NEXT: #APP @@ -64,7 +64,7 @@ define void @constraint_m(i32* %a) { ret void } -define i32 @constraint_m2(i32* %a) { +define i32 @constraint_m2(i32* %a) nounwind { ; RV32I-LABEL: constraint_m2: ; RV32I: # %bb.0: ; RV32I-NEXT: #APP diff --git a/llvm/test/CodeGen/RISCV/jumptable.ll b/llvm/test/CodeGen/RISCV/jumptable.ll index f849dc959abc4..5a5f5b65111a1 100644 --- a/llvm/test/CodeGen/RISCV/jumptable.ll +++ b/llvm/test/CodeGen/RISCV/jumptable.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ ; RUN: | FileCheck %s -check-prefix=RV32I -define void @jt(i32 %in, i32* %out) { +define void @jt(i32 %in, i32* %out) nounwind { ; RV32I-LABEL: jt: ; RV32I: # %bb.0: # %entry ; RV32I-NEXT: addi a2, zero, 2 diff --git a/llvm/test/CodeGen/RISCV/legalize-fneg.ll b/llvm/test/CodeGen/RISCV/legalize-fneg.ll index 42440e4cb445f..d2d0b9ea6c2c6 100644 --- a/llvm/test/CodeGen/RISCV/legalize-fneg.ll +++ b/llvm/test/CodeGen/RISCV/legalize-fneg.ll @@ -4,7 +4,7 @@ ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV64 %s -define void @test1(float* %a, float* %b) { +define void @test1(float* %a, float* %b) nounwind { ; RV32-LABEL: test1: ; RV32: # %bb.0: # %entry ; RV32-NEXT: lw a1, 0(a1) @@ -28,7 +28,7 @@ entry: ret void } -define void @test2(double* %a, double* %b) { +define void @test2(double* %a, double* %b) nounwind { ; RV32-LABEL: test2: ; RV32: # %bb.0: # %entry ; RV32-NEXT: lw a2, 4(a1) @@ -54,7 +54,7 @@ entry: ret void } -define void @test3(fp128* %a, fp128* %b) { +define void @test3(fp128* %a, fp128* %b) nounwind { ; RV32-LABEL: test3: ; RV32: # %bb.0: # %entry ; RV32-NEXT: lw a2, 12(a1) diff --git a/llvm/test/CodeGen/RISCV/rotl-rotr.ll b/llvm/test/CodeGen/RISCV/rotl-rotr.ll index 49b540eb2b1b3..d3f08804a3d4d 100644 --- a/llvm/test/CodeGen/RISCV/rotl-rotr.ll +++ b/llvm/test/CodeGen/RISCV/rotl-rotr.ll @@ -5,7 +5,7 @@ ; These IR sequences will generate ISD::ROTL and ISD::ROTR nodes, that the ; RISC-V backend must be able to select -define i32 @rotl(i32 %x, i32 %y) { +define i32 @rotl(i32 %x, i32 %y) nounwind { ; RV32I-LABEL: rotl: ; RV32I: # %bb.0: ; RV32I-NEXT: addi a2, zero, 32 @@ -21,7 +21,7 @@ define i32 @rotl(i32 %x, i32 %y) { ret i32 %d } -define i32 @rotr(i32 %x, i32 %y) { +define i32 @rotr(i32 %x, i32 %y) nounwind { ; RV32I-LABEL: rotr: ; RV32I: # %bb.0: ; RV32I-NEXT: addi a2, zero, 32 diff --git a/llvm/test/CodeGen/RISCV/rv64i-tricky-shifts.ll b/llvm/test/CodeGen/RISCV/rv64i-tricky-shifts.ll index 73eeed7553cce..b01833152ef41 100644 --- a/llvm/test/CodeGen/RISCV/rv64i-tricky-shifts.ll +++ b/llvm/test/CodeGen/RISCV/rv64i-tricky-shifts.ll @@ -7,7 +7,7 @@ ; patterns might make the mistake of assuming that a (sext_inreg foo, i32) can ; only be produced when sign-extending an i32 type. -define i64 @tricky_shl(i64 %a, i64 %b) { +define i64 @tricky_shl(i64 %a, i64 %b) nounwind { ; RV64I-LABEL: tricky_shl: ; RV64I: # %bb.0: ; RV64I-NEXT: sll a0, a0, a1 @@ -19,7 +19,7 @@ define i64 @tricky_shl(i64 %a, i64 %b) { ret i64 %3 } -define i64 @tricky_lshr(i64 %a, i64 %b) { +define i64 @tricky_lshr(i64 %a, i64 %b) nounwind { ; RV64I-LABEL: tricky_lshr: ; RV64I: # %bb.0: ; RV64I-NEXT: slli a0, a0, 32 @@ -31,7 +31,7 @@ define i64 @tricky_lshr(i64 %a, i64 %b) { ret i64 %2 } -define i64 @tricky_ashr(i64 %a, i64 %b) { +define i64 @tricky_ashr(i64 %a, i64 %b) nounwind { ; RV64I-LABEL: tricky_ashr: ; RV64I: # %bb.0: ; RV64I-NEXT: sext.w a0, a0 diff --git a/llvm/test/CodeGen/RISCV/select-cc.ll b/llvm/test/CodeGen/RISCV/select-cc.ll index 96eb6ff101070..7faad3bbc095e 100644 --- a/llvm/test/CodeGen/RISCV/select-cc.ll +++ b/llvm/test/CodeGen/RISCV/select-cc.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple=riscv32 -disable-block-placement -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefix=RV32I %s -define i32 @foo(i32 %a, i32 *%b) { +define i32 @foo(i32 %a, i32 *%b) nounwind { ; RV32I-LABEL: foo: ; RV32I: # %bb.0: ; RV32I-NEXT: lw a2, 0(a1) diff --git a/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll b/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll index 280c68e2ab496..53e68f5e95d73 100644 --- a/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll +++ b/llvm/test/CodeGen/RISCV/sext-zext-trunc.ll @@ -4,7 +4,7 @@ ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ ; RUN: | FileCheck %s -check-prefix=RV64I -define i8 @sext_i1_to_i8(i1 %a) { +define i8 @sext_i1_to_i8(i1 %a) nounwind { ; RV32I-LABEL: sext_i1_to_i8: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -20,7 +20,7 @@ define i8 @sext_i1_to_i8(i1 %a) { ret i8 %1 } -define i16 @sext_i1_to_i16(i1 %a) { +define i16 @sext_i1_to_i16(i1 %a) nounwind { ; RV32I-LABEL: sext_i1_to_i16: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -36,7 +36,7 @@ define i16 @sext_i1_to_i16(i1 %a) { ret i16 %1 } -define i32 @sext_i1_to_i32(i1 %a) { +define i32 @sext_i1_to_i32(i1 %a) nounwind { ; RV32I-LABEL: sext_i1_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -52,7 +52,7 @@ define i32 @sext_i1_to_i32(i1 %a) { ret i32 %1 } -define i64 @sext_i1_to_i64(i1 %a) { +define i64 @sext_i1_to_i64(i1 %a) nounwind { ; RV32I-LABEL: sext_i1_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -69,7 +69,7 @@ define i64 @sext_i1_to_i64(i1 %a) { ret i64 %1 } -define i16 @sext_i8_to_i16(i8 %a) { +define i16 @sext_i8_to_i16(i8 %a) nounwind { ; RV32I-LABEL: sext_i8_to_i16: ; RV32I: # %bb.0: ; RV32I-NEXT: slli a0, a0, 24 @@ -85,7 +85,7 @@ define i16 @sext_i8_to_i16(i8 %a) { ret i16 %1 } -define i32 @sext_i8_to_i32(i8 %a) { +define i32 @sext_i8_to_i32(i8 %a) nounwind { ; RV32I-LABEL: sext_i8_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: slli a0, a0, 24 @@ -101,7 +101,7 @@ define i32 @sext_i8_to_i32(i8 %a) { ret i32 %1 } -define i64 @sext_i8_to_i64(i8 %a) { +define i64 @sext_i8_to_i64(i8 %a) nounwind { ; RV32I-LABEL: sext_i8_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: slli a1, a0, 24 @@ -118,7 +118,7 @@ define i64 @sext_i8_to_i64(i8 %a) { ret i64 %1 } -define i32 @sext_i16_to_i32(i16 %a) { +define i32 @sext_i16_to_i32(i16 %a) nounwind { ; RV32I-LABEL: sext_i16_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: slli a0, a0, 16 @@ -134,7 +134,7 @@ define i32 @sext_i16_to_i32(i16 %a) { ret i32 %1 } -define i64 @sext_i16_to_i64(i16 %a) { +define i64 @sext_i16_to_i64(i16 %a) nounwind { ; RV32I-LABEL: sext_i16_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: slli a1, a0, 16 @@ -151,7 +151,7 @@ define i64 @sext_i16_to_i64(i16 %a) { ret i64 %1 } -define i64 @sext_i32_to_i64(i32 %a) { +define i64 @sext_i32_to_i64(i32 %a) nounwind { ; RV32I-LABEL: sext_i32_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: srai a1, a0, 31 @@ -165,7 +165,7 @@ define i64 @sext_i32_to_i64(i32 %a) { ret i64 %1 } -define i8 @zext_i1_to_i8(i1 %a) { +define i8 @zext_i1_to_i8(i1 %a) nounwind { ; RV32I-LABEL: zext_i1_to_i8: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -179,7 +179,7 @@ define i8 @zext_i1_to_i8(i1 %a) { ret i8 %1 } -define i16 @zext_i1_to_i16(i1 %a) { +define i16 @zext_i1_to_i16(i1 %a) nounwind { ; RV32I-LABEL: zext_i1_to_i16: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -193,7 +193,7 @@ define i16 @zext_i1_to_i16(i1 %a) { ret i16 %1 } -define i32 @zext_i1_to_i32(i1 %a) { +define i32 @zext_i1_to_i32(i1 %a) nounwind { ; RV32I-LABEL: zext_i1_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -207,7 +207,7 @@ define i32 @zext_i1_to_i32(i1 %a) { ret i32 %1 } -define i64 @zext_i1_to_i64(i1 %a) { +define i64 @zext_i1_to_i64(i1 %a) nounwind { ; RV32I-LABEL: zext_i1_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 1 @@ -222,7 +222,7 @@ define i64 @zext_i1_to_i64(i1 %a) { ret i64 %1 } -define i16 @zext_i8_to_i16(i8 %a) { +define i16 @zext_i8_to_i16(i8 %a) nounwind { ; RV32I-LABEL: zext_i8_to_i16: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 255 @@ -236,7 +236,7 @@ define i16 @zext_i8_to_i16(i8 %a) { ret i16 %1 } -define i32 @zext_i8_to_i32(i8 %a) { +define i32 @zext_i8_to_i32(i8 %a) nounwind { ; RV32I-LABEL: zext_i8_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 255 @@ -250,7 +250,7 @@ define i32 @zext_i8_to_i32(i8 %a) { ret i32 %1 } -define i64 @zext_i8_to_i64(i8 %a) { +define i64 @zext_i8_to_i64(i8 %a) nounwind { ; RV32I-LABEL: zext_i8_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: andi a0, a0, 255 @@ -265,7 +265,7 @@ define i64 @zext_i8_to_i64(i8 %a) { ret i64 %1 } -define i32 @zext_i16_to_i32(i16 %a) { +define i32 @zext_i16_to_i32(i16 %a) nounwind { ; RV32I-LABEL: zext_i16_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a1, 16 @@ -283,7 +283,7 @@ define i32 @zext_i16_to_i32(i16 %a) { ret i32 %1 } -define i64 @zext_i16_to_i64(i16 %a) { +define i64 @zext_i16_to_i64(i16 %a) nounwind { ; RV32I-LABEL: zext_i16_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: lui a1, 16 @@ -302,7 +302,7 @@ define i64 @zext_i16_to_i64(i16 %a) { ret i64 %1 } -define i64 @zext_i32_to_i64(i32 %a) { +define i64 @zext_i32_to_i64(i32 %a) nounwind { ; RV32I-LABEL: zext_i32_to_i64: ; RV32I: # %bb.0: ; RV32I-NEXT: mv a1, zero @@ -317,7 +317,7 @@ define i64 @zext_i32_to_i64(i32 %a) { ret i64 %1 } -define i1 @trunc_i8_to_i1(i8 %a) { +define i1 @trunc_i8_to_i1(i8 %a) nounwind { ; RV32I-LABEL: trunc_i8_to_i1: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -329,7 +329,7 @@ define i1 @trunc_i8_to_i1(i8 %a) { ret i1 %1 } -define i1 @trunc_i16_to_i1(i16 %a) { +define i1 @trunc_i16_to_i1(i16 %a) nounwind { ; RV32I-LABEL: trunc_i16_to_i1: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -341,7 +341,7 @@ define i1 @trunc_i16_to_i1(i16 %a) { ret i1 %1 } -define i1 @trunc_i32_to_i1(i32 %a) { +define i1 @trunc_i32_to_i1(i32 %a) nounwind { ; RV32I-LABEL: trunc_i32_to_i1: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -353,7 +353,7 @@ define i1 @trunc_i32_to_i1(i32 %a) { ret i1 %1 } -define i1 @trunc_i64_to_i1(i64 %a) { +define i1 @trunc_i64_to_i1(i64 %a) nounwind { ; RV32I-LABEL: trunc_i64_to_i1: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -365,7 +365,7 @@ define i1 @trunc_i64_to_i1(i64 %a) { ret i1 %1 } -define i8 @trunc_i16_to_i8(i16 %a) { +define i8 @trunc_i16_to_i8(i16 %a) nounwind { ; RV32I-LABEL: trunc_i16_to_i8: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -377,7 +377,7 @@ define i8 @trunc_i16_to_i8(i16 %a) { ret i8 %1 } -define i8 @trunc_i32_to_i8(i32 %a) { +define i8 @trunc_i32_to_i8(i32 %a) nounwind { ; RV32I-LABEL: trunc_i32_to_i8: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -389,7 +389,7 @@ define i8 @trunc_i32_to_i8(i32 %a) { ret i8 %1 } -define i8 @trunc_i64_to_i8(i64 %a) { +define i8 @trunc_i64_to_i8(i64 %a) nounwind { ; RV32I-LABEL: trunc_i64_to_i8: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -401,7 +401,7 @@ define i8 @trunc_i64_to_i8(i64 %a) { ret i8 %1 } -define i16 @trunc_i32_to_i16(i32 %a) { +define i16 @trunc_i32_to_i16(i32 %a) nounwind { ; RV32I-LABEL: trunc_i32_to_i16: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -413,7 +413,7 @@ define i16 @trunc_i32_to_i16(i32 %a) { ret i16 %1 } -define i16 @trunc_i64_to_i16(i64 %a) { +define i16 @trunc_i64_to_i16(i64 %a) nounwind { ; RV32I-LABEL: trunc_i64_to_i16: ; RV32I: # %bb.0: ; RV32I-NEXT: ret @@ -425,7 +425,7 @@ define i16 @trunc_i64_to_i16(i64 %a) { ret i16 %1 } -define i32 @trunc_i64_to_i32(i64 %a) { +define i32 @trunc_i64_to_i32(i64 %a) nounwind { ; RV32I-LABEL: trunc_i64_to_i32: ; RV32I: # %bb.0: ; RV32I-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/tail-calls.ll b/llvm/test/CodeGen/RISCV/tail-calls.ll index 4d7db01d1fb7f..dea1521b05c49 100644 --- a/llvm/test/CodeGen/RISCV/tail-calls.ll +++ b/llvm/test/CodeGen/RISCV/tail-calls.ll @@ -3,7 +3,7 @@ ; Perform tail call optimization for global address. declare i32 @callee_tail(i32 %i) -define i32 @caller_tail(i32 %i) { +define i32 @caller_tail(i32 %i) nounwind { ; CHECK-LABEL: caller_tail ; CHECK: tail callee_tail entry: @@ -26,7 +26,7 @@ entry: ; Perform indirect tail call optimization (for function pointer call). declare void @callee_indirect1() declare void @callee_indirect2() -define void @caller_indirect_tail(i32 %a) { +define void @caller_indirect_tail(i32 %a) nounwind { ; CHECK-LABEL: caller_indirect_tail ; CHECK-NOT: call callee_indirect1 ; CHECK-NOT: call callee_indirect2 @@ -49,7 +49,7 @@ entry: ; Do not tail call optimize functions with varargs. declare i32 @callee_varargs(i32, ...) -define void @caller_varargs(i32 %a, i32 %b) { +define void @caller_varargs(i32 %a, i32 %b) nounwind { ; CHECK-LABEL: caller_varargs ; CHECK-NOT: tail callee_varargs ; CHECK: call callee_varargs @@ -60,7 +60,7 @@ entry: ; Do not tail call optimize if stack is used to pass parameters. declare i32 @callee_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) -define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) { +define i32 @caller_args(i32 %a, i32 %b, i32 %c, i32 %dd, i32 %e, i32 %ff, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n) nounwind { ; CHECK-LABEL: caller_args ; CHECK-NOT: tail callee_args ; CHECK: call callee_args @@ -71,7 +71,7 @@ entry: ; Do not tail call optimize if parameters need to be passed indirectly. declare i32 @callee_indirect_args(fp128 %a) -define void @caller_indirect_args() { +define void @caller_indirect_args() nounwind { ; CHECK-LABEL: caller_indirect_args ; CHECK-NOT: tail callee_indirect_args ; CHECK: call callee_indirect_args @@ -85,7 +85,7 @@ entry: ; calls) is implementation-defined, so we cannot rely on the linker replacing ; the tail call with a return. declare extern_weak void @callee_weak() -define void @caller_weak() { +define void @caller_weak() nounwind { ; CHECK-LABEL: caller_weak ; CHECK-NOT: tail callee_weak ; CHECK: call callee_weak @@ -112,7 +112,7 @@ attributes #0 = { "interrupt"="machine" } ; we want to reuse during a tail call. Do not tail call optimize functions with ; byval parameters. declare i32 @callee_byval(i32** byval %a) -define i32 @caller_byval() { +define i32 @caller_byval() nounwind { ; CHECK-LABEL: caller_byval ; CHECK-NOT: tail callee_byval ; CHECK: call callee_byval @@ -127,7 +127,7 @@ entry: @a = global %struct.A zeroinitializer declare void @callee_struct(%struct.A* sret %a) -define void @caller_nostruct() { +define void @caller_nostruct() nounwind { ; CHECK-LABEL: caller_nostruct ; CHECK-NOT: tail callee_struct ; CHECK: call callee_struct @@ -138,7 +138,7 @@ entry: ; Do not tail call optimize if caller uses structret semantics. declare void @callee_nostruct() -define void @caller_struct(%struct.A* sret %a) { +define void @caller_struct(%struct.A* sret %a) nounwind { ; CHECK-LABEL: caller_struct ; CHECK-NOT: tail callee_nostruct ; CHECK: call callee_nostruct diff --git a/llvm/test/CodeGen/RISCV/zext-with-load-is-free.ll b/llvm/test/CodeGen/RISCV/zext-with-load-is-free.ll index 9ea4c36a866e3..12c7796995a81 100644 --- a/llvm/test/CodeGen/RISCV/zext-with-load-is-free.ll +++ b/llvm/test/CodeGen/RISCV/zext-with-load-is-free.ll @@ -6,7 +6,7 @@ @bytes = global [5 x i8] zeroinitializer, align 1 -define i32 @test_zext_i8() { +define i32 @test_zext_i8() nounwind { ; RV32I-LABEL: test_zext_i8: ; RV32I: # %bb.0: # %entry ; RV32I-NEXT: lui a0, %hi(bytes) @@ -41,7 +41,7 @@ if.end: @shorts = global [5 x i16] zeroinitializer, align 2 -define i32 @test_zext_i16() { +define i32 @test_zext_i16() nounwind { ; RV32I-LABEL: test_zext_i16: ; RV32I: # %bb.0: # %entry ; RV32I-NEXT: lui a0, %hi(shorts) From 6b48742e43f603b6458ed02dd4dc5d8021922a21 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 23 May 2019 13:11:00 +0000 Subject: [PATCH 0030/1176] [libcxx][tests] Fix order checking in unordered_multiset tests. Some tests assume that iteration through an unordered multiset elements will return them in the same order as at the container creation. This assumption is not true since the container is unordered, so that no specific order of elements is ever guaranteed for such container. This patch introduces checks verifying that any iteration will return elements exactly from a set of valid values and without repetition, but in no particular order. Thanks to Andrey Maksimov for the patch. Differential Revision: https://reviews.llvm.org/D56500 llvm-svn: 361494 --- .../unord.multiset.cnstr/assign_copy.pass.cpp | 49 +++++-------------- .../unord.multiset.cnstr/assign_move.pass.cpp | 17 ++----- .../unord.multiset.cnstr/copy.pass.cpp | 49 +++++-------------- .../unord.multiset.cnstr/copy_alloc.pass.cpp | 33 ++++--------- .../unord.multiset.cnstr/move_alloc.pass.cpp | 17 ++----- 5 files changed, 45 insertions(+), 120 deletions(-) diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp index 1fcd71002e955..1f8cc68b38235 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_copy.pass.cpp @@ -22,6 +22,7 @@ #include #include "test_macros.h" +#include "../../../check_consecutive.h" #include "../../../test_compare.h" #include "../../../test_hash.h" #include "test_allocator.h" @@ -61,18 +62,10 @@ int main(int, char**) c = c0; LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == A(4)); @@ -133,18 +126,10 @@ int main(int, char**) c = c0; assert(c.bucket_count() >= 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == A(10)); @@ -187,18 +172,10 @@ int main(int, char**) c = c0; LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == A()); diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_move.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_move.pass.cpp index 1ed77851cf3f2..f375baeaf2c61 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_move.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/assign_move.pass.cpp @@ -23,6 +23,7 @@ #include #include "test_macros.h" +#include "../../../check_consecutive.h" #include "../../../test_compare.h" #include "../../../test_hash.h" #include "test_allocator.h" @@ -62,18 +63,10 @@ int main(int, char**) c = std::move(c0); LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == A(4)); diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy.pass.cpp index f3ca15241ad9d..aa2edf1de4415 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy.pass.cpp @@ -21,6 +21,7 @@ #include #include "test_macros.h" +#include "../../../check_consecutive.h" #include "../../../test_compare.h" #include "../../../test_hash.h" #include "test_allocator.h" @@ -53,18 +54,10 @@ int main(int, char**) C c = c0; LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == test_allocator(10)); @@ -100,18 +93,10 @@ int main(int, char**) C c = c0; LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == other_allocator(-2)); @@ -146,18 +131,10 @@ int main(int, char**) C c = c0; LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == min_allocator()); diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy_alloc.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy_alloc.pass.cpp index 4e99490ea6111..d0579292af401 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy_alloc.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/copy_alloc.pass.cpp @@ -21,6 +21,7 @@ #include #include "test_macros.h" +#include "../../../check_consecutive.h" #include "../../../test_compare.h" #include "../../../test_hash.h" #include "test_allocator.h" @@ -53,18 +54,10 @@ int main(int, char**) C c(c0, test_allocator(5)); LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == test_allocator(5)); @@ -100,18 +93,10 @@ int main(int, char**) C c(c0, min_allocator()); LIBCPP_ASSERT(c.bucket_count() == 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == min_allocator()); diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/move_alloc.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/move_alloc.pass.cpp index eb567a9da7533..3ed04574bb0f1 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/move_alloc.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/move_alloc.pass.cpp @@ -23,6 +23,7 @@ #include #include "test_macros.h" +#include "../../../check_consecutive.h" #include "../../../test_compare.h" #include "../../../test_hash.h" #include "test_allocator.h" @@ -56,18 +57,10 @@ int main(int, char**) C c(std::move(c0), A(12)); assert(c.bucket_count() >= 7); assert(c.size() == 6); - C::const_iterator i = c.cbegin(); - assert(*i == 1); - ++i; - assert(*i == 1); - ++i; - assert(*i == 2); - ++i; - assert(*i == 2); - ++i; - assert(*i == 3); - ++i; - assert(*i == 4); + CheckConsecutiveValues(c.find(1), c.end(), 1, 2); + CheckConsecutiveValues(c.find(2), c.end(), 2, 2); + CheckConsecutiveValues(c.find(3), c.end(), 3, 1); + CheckConsecutiveValues(c.find(4), c.end(), 4, 1); assert(c.hash_function() == test_hash >(8)); assert(c.key_eq() == test_compare >(9)); assert(c.get_allocator() == A(12)); From 46806749ac3a334bdcabb59b7082471aaf19a28a Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 23 May 2019 13:30:10 +0000 Subject: [PATCH 0031/1176] [X86] Regenerate LZCNT tests on x86/x32/x64 targets llvm-svn: 361495 --- llvm/test/CodeGen/X86/lzcnt.ll | 171 +++++++++++++++++++++++++++++---- 1 file changed, 154 insertions(+), 17 deletions(-) diff --git a/llvm/test/CodeGen/X86/lzcnt.ll b/llvm/test/CodeGen/X86/lzcnt.ll index 1f0c6b3da2bf5..b85c1c388e467 100644 --- a/llvm/test/CodeGen/X86/lzcnt.ll +++ b/llvm/test/CodeGen/X86/lzcnt.ll @@ -1,4 +1,7 @@ -; RUN: llc < %s -mtriple=x86_64-- -mattr=+lzcnt | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-- -mattr=+lzcnt | FileCheck %s --check-prefixes=CHECK,X86 +; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -mattr=+lzcnt | FileCheck %s --check-prefixes=CHECK,X32 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+lzcnt | FileCheck %s --check-prefixes=CHECK,X64 declare i8 @llvm.ctlz.i8(i8, i1) nounwind readnone declare i16 @llvm.ctlz.i16(i16, i1) nounwind readnone @@ -6,57 +9,191 @@ declare i32 @llvm.ctlz.i32(i32, i1) nounwind readnone declare i64 @llvm.ctlz.i64(i64, i1) nounwind readnone define i8 @t1(i8 %x) nounwind { +; X86-LABEL: t1: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: lzcntl %eax, %eax +; X86-NEXT: addl $-24, %eax +; X86-NEXT: # kill: def $al killed $al killed $eax +; X86-NEXT: retl +; +; X32-LABEL: t1: +; X32: # %bb.0: +; X32-NEXT: movzbl %dil, %eax +; X32-NEXT: lzcntl %eax, %eax +; X32-NEXT: addl $-24, %eax +; X32-NEXT: # kill: def $al killed $al killed $eax +; X32-NEXT: retq +; +; X64-LABEL: t1: +; X64: # %bb.0: +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: lzcntl %eax, %eax +; X64-NEXT: addl $-24, %eax +; X64-NEXT: # kill: def $al killed $al killed $eax +; X64-NEXT: retq %tmp = tail call i8 @llvm.ctlz.i8( i8 %x, i1 false ) ret i8 %tmp -; CHECK-LABEL: t1: -; CHECK: lzcntl } define i16 @t2(i16 %x) nounwind { +; X86-LABEL: t2: +; X86: # %bb.0: +; X86-NEXT: lzcntw {{[0-9]+}}(%esp), %ax +; X86-NEXT: retl +; +; X32-LABEL: t2: +; X32: # %bb.0: +; X32-NEXT: lzcntw %di, %ax +; X32-NEXT: retq +; +; X64-LABEL: t2: +; X64: # %bb.0: +; X64-NEXT: lzcntw %di, %ax +; X64-NEXT: retq %tmp = tail call i16 @llvm.ctlz.i16( i16 %x, i1 false ) ret i16 %tmp -; CHECK-LABEL: t2: -; CHECK: lzcntw } define i32 @t3(i32 %x) nounwind { +; X86-LABEL: t3: +; X86: # %bb.0: +; X86-NEXT: lzcntl {{[0-9]+}}(%esp), %eax +; X86-NEXT: retl +; +; X32-LABEL: t3: +; X32: # %bb.0: +; X32-NEXT: lzcntl %edi, %eax +; X32-NEXT: retq +; +; X64-LABEL: t3: +; X64: # %bb.0: +; X64-NEXT: lzcntl %edi, %eax +; X64-NEXT: retq %tmp = tail call i32 @llvm.ctlz.i32( i32 %x, i1 false ) ret i32 %tmp -; CHECK-LABEL: t3: -; CHECK: lzcntl } define i64 @t4(i64 %x) nounwind { +; X86-LABEL: t4: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: jne .LBB3_1 +; X86-NEXT: # %bb.2: +; X86-NEXT: lzcntl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $32, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; X86-NEXT: .LBB3_1: +; X86-NEXT: lzcntl %eax, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X32-LABEL: t4: +; X32: # %bb.0: +; X32-NEXT: lzcntq %rdi, %rax +; X32-NEXT: retq +; +; X64-LABEL: t4: +; X64: # %bb.0: +; X64-NEXT: lzcntq %rdi, %rax +; X64-NEXT: retq %tmp = tail call i64 @llvm.ctlz.i64( i64 %x, i1 false ) ret i64 %tmp -; CHECK-LABEL: t4: -; CHECK: lzcntq } define i8 @t5(i8 %x) nounwind { +; X86-LABEL: t5: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: lzcntl %eax, %eax +; X86-NEXT: addl $-24, %eax +; X86-NEXT: # kill: def $al killed $al killed $eax +; X86-NEXT: retl +; +; X32-LABEL: t5: +; X32: # %bb.0: +; X32-NEXT: movzbl %dil, %eax +; X32-NEXT: lzcntl %eax, %eax +; X32-NEXT: addl $-24, %eax +; X32-NEXT: # kill: def $al killed $al killed $eax +; X32-NEXT: retq +; +; X64-LABEL: t5: +; X64: # %bb.0: +; X64-NEXT: movzbl %dil, %eax +; X64-NEXT: lzcntl %eax, %eax +; X64-NEXT: addl $-24, %eax +; X64-NEXT: # kill: def $al killed $al killed $eax +; X64-NEXT: retq %tmp = tail call i8 @llvm.ctlz.i8( i8 %x, i1 true ) ret i8 %tmp -; CHECK-LABEL: t5: -; CHECK: lzcntl } define i16 @t6(i16 %x) nounwind { +; X86-LABEL: t6: +; X86: # %bb.0: +; X86-NEXT: lzcntw {{[0-9]+}}(%esp), %ax +; X86-NEXT: retl +; +; X32-LABEL: t6: +; X32: # %bb.0: +; X32-NEXT: lzcntw %di, %ax +; X32-NEXT: retq +; +; X64-LABEL: t6: +; X64: # %bb.0: +; X64-NEXT: lzcntw %di, %ax +; X64-NEXT: retq %tmp = tail call i16 @llvm.ctlz.i16( i16 %x, i1 true ) ret i16 %tmp -; CHECK-LABEL: t6: -; CHECK: lzcntw } define i32 @t7(i32 %x) nounwind { +; X86-LABEL: t7: +; X86: # %bb.0: +; X86-NEXT: lzcntl {{[0-9]+}}(%esp), %eax +; X86-NEXT: retl +; +; X32-LABEL: t7: +; X32: # %bb.0: +; X32-NEXT: lzcntl %edi, %eax +; X32-NEXT: retq +; +; X64-LABEL: t7: +; X64: # %bb.0: +; X64-NEXT: lzcntl %edi, %eax +; X64-NEXT: retq %tmp = tail call i32 @llvm.ctlz.i32( i32 %x, i1 true ) ret i32 %tmp -; CHECK-LABEL: t7: -; CHECK: lzcntl } define i64 @t8(i64 %x) nounwind { +; X86-LABEL: t8: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: jne .LBB7_1 +; X86-NEXT: # %bb.2: +; X86-NEXT: lzcntl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $32, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; X86-NEXT: .LBB7_1: +; X86-NEXT: lzcntl %eax, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: retl +; +; X32-LABEL: t8: +; X32: # %bb.0: +; X32-NEXT: lzcntq %rdi, %rax +; X32-NEXT: retq +; +; X64-LABEL: t8: +; X64: # %bb.0: +; X64-NEXT: lzcntq %rdi, %rax +; X64-NEXT: retq %tmp = tail call i64 @llvm.ctlz.i64( i64 %x, i1 true ) ret i64 %tmp -; CHECK-LABEL: t8: -; CHECK: lzcntq } From dd0d9e01eeaab849701cce1a22342b04e79df54b Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Thu, 23 May 2019 13:42:47 +0000 Subject: [PATCH 0032/1176] [MCA] Introduce class LSUnitBase and let LSUnit derive from it. Class LSUnitBase provides a abstract interface for all the concrete LS units in llvm-mca. Methods exposed by the public abstract LSUnitBase interface are: - Status isAvailable(const InstRef&); - void dispatch(const InstRef &); - const InstRef &isReady(const InstRef &); LSUnitBase standardises the API, but not the data structures internally used by LS units. This allows for more flexibility. Previously, only method `isReady()` was declared virtual by class LSUnit. Also, derived classes had to inherit all the internal data members of LSUnit. No functional change intended. llvm-svn: 361496 --- llvm/include/llvm/MCA/HardwareUnits/LSUnit.h | 174 +++++++++++++------ llvm/lib/MCA/HardwareUnits/LSUnit.cpp | 131 +++++++------- llvm/lib/MCA/HardwareUnits/Scheduler.cpp | 17 +- 3 files changed, 196 insertions(+), 126 deletions(-) diff --git a/llvm/include/llvm/MCA/HardwareUnits/LSUnit.h b/llvm/include/llvm/MCA/HardwareUnits/LSUnit.h index c9e1cc3cdc4f1..e2ba9cbbf8bee 100644 --- a/llvm/include/llvm/MCA/HardwareUnits/LSUnit.h +++ b/llvm/include/llvm/MCA/HardwareUnits/LSUnit.h @@ -18,13 +18,83 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/MC/MCSchedule.h" #include "llvm/MCA/HardwareUnits/HardwareUnit.h" +#include "llvm/MCA/Instruction.h" namespace llvm { namespace mca { -class InstRef; class Scheduler; +/// Abstract base interface for LS (load/store) units in llvm-mca. +class LSUnitBase : public HardwareUnit { + /// Load queue size. + /// + /// A value of zero for this field means that the load queue is unbounded. + /// Processor models can declare the size of a load queue via tablegen (see + /// the definition of tablegen class LoadQueue in + /// llvm/Target/TargetSchedule.td). + unsigned LQSize; + + /// Load queue size. + /// + /// A value of zero for this field means that the store queue is unbounded. + /// Processor models can declare the size of a store queue via tablegen (see + /// the definition of tablegen class StoreQueue in + /// llvm/Target/TargetSchedule.td). + unsigned SQSize; + + /// True if loads don't alias with stores. + /// + /// By default, the LS unit assumes that loads and stores don't alias with + /// eachother. If this field is set to false, then loads are always assumed to + /// alias with stores. + const bool NoAlias; + +public: + LSUnitBase(const MCSchedModel &SM, unsigned LoadQueueSize, + unsigned StoreQueueSize, bool AssumeNoAlias); + + virtual ~LSUnitBase(); + + /// Returns the total number of entries in the load queue. + unsigned getLoadQueueSize() const { return LQSize; } + + /// Returns the total number of entries in the store queue. + unsigned getStoreQueueSize() const { return SQSize; } + + bool assumeNoAlias() const { return NoAlias; } + + enum Status { + LSU_AVAILABLE = 0, + LSU_LQUEUE_FULL, // Load Queue unavailable + LSU_SQUEUE_FULL // Store Queue unavailable + }; + + /// This method checks the availability of the load/store buffers. + /// + /// Returns LSU_AVAILABLE if there are enough load/store queue entries to + /// accomodate instruction IR. By default, LSU_AVAILABLE is returned if IR is + /// not a memory operation. + virtual Status isAvailable(const InstRef &IR) const = 0; + + /// Allocates LS resources for instruction IR. + /// + /// This method assumes that a previous call to `isAvailable(IR)` succeeded + /// with a LSUnitBase::Status value of LSU_AVAILABLE. + virtual void dispatch(const InstRef &IR) = 0; + + /// Check if a peviously dispatched instruction IR is now ready for execution. + /// + /// Instruction IR is assumed to be a memory operation. If IR is still waiting + /// on another memory instruction M, then M is returned to the caller. If IR + /// depends on more than one memory operations, then this method returns one + /// of them. + /// + /// Derived classes can implement memory consistency rules for simulated + /// processor within this member function. + virtual const InstRef &isReady(const InstRef &IR) const = 0; +}; + /// A Load/Store Unit implementing a load and store queues. /// /// This class implements a load queue and a store queue to emulate the @@ -88,18 +158,7 @@ class Scheduler; /// A load/store barrier is "executed" when it becomes the oldest entry in /// the load/store queue(s). That also means, all the older loads/stores have /// already been executed. -class LSUnit : public HardwareUnit { - // Load queue size. - // LQ_Size == 0 means that there are infinite slots in the load queue. - unsigned LQ_Size; - - // Store queue size. - // SQ_Size == 0 means that there are infinite slots in the store queue. - unsigned SQ_Size; - - // If true, loads will never alias with stores. This is the default. - bool NoAlias; - +class LSUnit : public LSUnitBase { // When a `MayLoad` instruction is dispatched to the schedulers for execution, // the LSUnit reserves an entry in the `LoadQueue` for it. // @@ -138,68 +197,75 @@ class LSUnit : public HardwareUnit { // alternative approaches that let instructions specify the number of // load/store queue entries which they consume at dispatch stage (See // PR39830). - SmallSet LoadQueue; - SmallSet StoreQueue; + SmallSet LoadQueue; + SmallSet StoreQueue; - void assignLQSlot(unsigned Index); - void assignSQSlot(unsigned Index); + void assignLQSlot(const InstRef &IR); + void assignSQSlot(const InstRef &IR); // An instruction that both 'mayStore' and 'HasUnmodeledSideEffects' is // conservatively treated as a store barrier. It forces older store to be // executed before newer stores are issued. - SmallSet StoreBarriers; + SmallSet StoreBarriers; // An instruction that both 'MayLoad' and 'HasUnmodeledSideEffects' is // conservatively treated as a load barrier. It forces older loads to execute // before newer loads are issued. - SmallSet LoadBarriers; + SmallSet LoadBarriers; bool isSQEmpty() const { return StoreQueue.empty(); } bool isLQEmpty() const { return LoadQueue.empty(); } - bool isSQFull() const { return SQ_Size != 0 && StoreQueue.size() == SQ_Size; } - bool isLQFull() const { return LQ_Size != 0 && LoadQueue.size() == LQ_Size; } + bool isSQFull() const { + return getStoreQueueSize() != 0 && StoreQueue.size() == getStoreQueueSize(); + } + bool isLQFull() const { + return getLoadQueueSize() != 0 && LoadQueue.size() == getLoadQueueSize(); + } public: - LSUnit(const MCSchedModel &SM, unsigned LQ = 0, unsigned SQ = 0, - bool AssumeNoAlias = false); + LSUnit(const MCSchedModel &SM) + : LSUnit(SM, /* LQSize */ 0, /* SQSize */ 0, /* NoAlias */ false) {} + LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ) + : LSUnit(SM, LQ, SQ, /* NoAlias */ false) {} + LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ, bool AssumeNoAlias) + : LSUnitBase(SM, LQ, SQ, AssumeNoAlias) {} #ifndef NDEBUG void dump() const; #endif - enum Status { LSU_AVAILABLE = 0, LSU_LQUEUE_FULL, LSU_SQUEUE_FULL }; + /// Returns LSU_AVAILABLE if there are enough load/store queue entries to + /// accomodate instruction IR. + Status isAvailable(const InstRef &IR) const override; - // Returns LSU_AVAILABLE if there are enough load/store queue entries to serve - // IR. It also returns LSU_AVAILABLE if IR is not a memory operation. - Status isAvailable(const InstRef &IR) const; + /// Allocates LS resources for instruction IR. + /// + /// This method assumes that a previous call to `isAvailable(IR)` succeeded + /// returning LSU_AVAILABLE. + void dispatch(const InstRef &IR) override; - // Allocates load/store queue resources for IR. - // - // This method assumes that a previous call to `isAvailable(IR)` returned - // LSU_AVAILABLE, and that IR is a memory operation. - void dispatch(const InstRef &IR); - - // By default, rules are: - // 1. A store may not pass a previous store. - // 2. A load may not pass a previous store unless flag 'NoAlias' is set. - // 3. A load may pass a previous load. - // 4. A store may not pass a previous load (regardless of flag 'NoAlias'). - // 5. A load has to wait until an older load barrier is fully executed. - // 6. A store has to wait until an older store barrier is fully executed. - // - // Returns an instruction identifier. If IR is ready, then this method returns - // `IR.getSourceIndex()`. Otherwise it returns the instruction ID of the - // dependent (i.e. conflicting) memory instruction. - virtual unsigned isReady(const InstRef &IR) const; - - // Load and store instructions are tracked by their corresponding queues from - // dispatch until the "instruction executed" event. - // Only when a load instruction reaches the 'Executed' stage, its value - // becomes available to the users. At that point, the load no longer needs to - // be tracked by the load queue. - // FIXME: For simplicity, we optimistically assume a similar behavior for - // store instructions. In practice, store operations don't tend to leave the - // store queue until they reach the 'Retired' stage (See PR39830). + /// Check if a peviously dispatched instruction IR is now ready for execution. + /// + /// Rules are: + /// By default, rules are: + /// 1. A store may not pass a previous store. + /// 2. A load may not pass a previous store unless flag 'NoAlias' is set. + /// 3. A load may pass a previous load. + /// 4. A store may not pass a previous load (regardless of flag 'NoAlias'). + /// 5. A load has to wait until an older load barrier is fully executed. + /// 6. A store has to wait until an older store barrier is fully executed. + const InstRef &isReady(const InstRef &IR) const override; + + /// Instruction executed event handler. + /// + /// Load and store instructions are tracked by their corresponding queues from + /// dispatch until "instruction executed" event. + /// When a load instruction Ld reaches the 'Executed' stage, its value + /// is propagated to all the dependent users, and the LS unit stops tracking + /// Ld. + /// FIXME: For simplicity, we optimistically assume a similar behavior for + /// store instructions. In practice, store operations don't tend to leave the + /// store queue until they reach the 'Retired' stage (See PR39830). void onInstructionExecuted(const InstRef &IR); }; diff --git a/llvm/lib/MCA/HardwareUnits/LSUnit.cpp b/llvm/lib/MCA/HardwareUnits/LSUnit.cpp index 4f49fbd2bb401..c3866d6bba7a0 100644 --- a/llvm/lib/MCA/HardwareUnits/LSUnit.cpp +++ b/llvm/lib/MCA/HardwareUnits/LSUnit.cpp @@ -21,48 +21,48 @@ namespace llvm { namespace mca { -LSUnit::LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ, - bool AssumeNoAlias) - : LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) { +LSUnitBase::LSUnitBase(const MCSchedModel &SM, unsigned LQ, unsigned SQ, + bool AssumeNoAlias) + : LQSize(LQ), SQSize(SQ), NoAlias(AssumeNoAlias) { if (SM.hasExtraProcessorInfo()) { const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo(); - if (!LQ_Size && EPI.LoadQueueID) { + if (!LQSize && EPI.LoadQueueID) { const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID); - LQ_Size = LdQDesc.BufferSize; + LQSize = LdQDesc.BufferSize; } - if (!SQ_Size && EPI.StoreQueueID) { + if (!SQSize && EPI.StoreQueueID) { const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID); - SQ_Size = StQDesc.BufferSize; + SQSize = StQDesc.BufferSize; } } } +LSUnitBase::~LSUnitBase() {} + #ifndef NDEBUG void LSUnit::dump() const { - dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n'; - dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n'; + dbgs() << "[LSUnit] LQ_Size = " << getLoadQueueSize() << '\n'; + dbgs() << "[LSUnit] SQ_Size = " << getStoreQueueSize() << '\n'; dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n'; dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n'; } #endif -void LSUnit::assignLQSlot(unsigned Index) { - assert(!isLQFull()); - assert(LoadQueue.count(Index) == 0); +void LSUnit::assignLQSlot(const InstRef &IR) { + assert(!isLQFull() && "Load Queue is full!"); - LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot \n"); - LoadQueue.insert(Index); + LoadQueue.insert(IR); } -void LSUnit::assignSQSlot(unsigned Index) { - assert(!isSQFull()); - assert(StoreQueue.count(Index) == 0); +void LSUnit::assignSQSlot(const InstRef &IR) { + assert(!isSQFull() && "Store Queue is full!"); - LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot \n"); - StoreQueue.insert(Index); + StoreQueue.insert(IR); } void LSUnit::dispatch(const InstRef &IR) { @@ -70,17 +70,16 @@ void LSUnit::dispatch(const InstRef &IR) { unsigned IsMemBarrier = Desc.HasSideEffects; assert((Desc.MayLoad || Desc.MayStore) && "Not a memory operation!"); - const unsigned Index = IR.getSourceIndex(); if (Desc.MayLoad) { if (IsMemBarrier) - LoadBarriers.insert(Index); - assignLQSlot(Index); + LoadBarriers.insert(IR); + assignLQSlot(IR); } if (Desc.MayStore) { if (IsMemBarrier) - StoreBarriers.insert(Index); - assignSQSlot(Index); + StoreBarriers.insert(IR); + assignSQSlot(IR); } } @@ -93,65 +92,67 @@ LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const { return LSUnit::LSU_AVAILABLE; } -unsigned LSUnit::isReady(const InstRef &IR) const { +const InstRef &LSUnit::isReady(const InstRef &IR) const { const InstrDesc &Desc = IR.getInstruction()->getDesc(); const unsigned Index = IR.getSourceIndex(); bool IsALoad = Desc.MayLoad; bool IsAStore = Desc.MayStore; assert((IsALoad || IsAStore) && "Not a memory operation!"); - assert((!IsALoad || LoadQueue.count(Index) == 1) && "Load not in queue!"); - assert((!IsAStore || StoreQueue.count(Index) == 1) && "Store not in queue!"); if (IsALoad && !LoadBarriers.empty()) { - unsigned LoadBarrierIndex = *LoadBarriers.begin(); + const InstRef &LoadBarrier = *LoadBarriers.begin(); // A younger load cannot pass a older load barrier. - if (Index > LoadBarrierIndex) - return LoadBarrierIndex; + if (Index > LoadBarrier.getSourceIndex()) + return LoadBarrier; // A load barrier cannot pass a older load. - if (Index == LoadBarrierIndex && Index != *LoadQueue.begin()) - return *LoadQueue.begin(); + if (Index == LoadBarrier.getSourceIndex()) { + const InstRef &Load = *LoadQueue.begin(); + if (Index != Load.getSourceIndex()) + return Load; + } } if (IsAStore && !StoreBarriers.empty()) { - unsigned StoreBarrierIndex = *StoreBarriers.begin(); + const InstRef &StoreBarrier = *StoreBarriers.begin(); // A younger store cannot pass a older store barrier. - if (Index > StoreBarrierIndex) - return StoreBarrierIndex; + if (Index > StoreBarrier.getSourceIndex()) + return StoreBarrier; // A store barrier cannot pass a older store. - if (Index == StoreBarrierIndex && Index != *StoreQueue.begin()) - return *StoreQueue.begin(); + if (Index == StoreBarrier.getSourceIndex()) { + const InstRef &Store = *StoreQueue.begin(); + if (Index != Store.getSourceIndex()) + return Store; + } } // A load may not pass a previous store unless flag 'NoAlias' is set. // A load may pass a previous load. - if (NoAlias && IsALoad) - return Index; + if (assumeNoAlias() && IsALoad) + return IR; if (StoreQueue.size()) { // A load may not pass a previous store. // A store may not pass a previous store. - if (Index > *StoreQueue.begin()) - return *StoreQueue.begin(); + const InstRef &Store = *StoreQueue.begin(); + if (Index > Store.getSourceIndex()) + return Store; } // Okay, we are older than the oldest store in the queue. - // If there are no pending loads, then we can say for sure that this - // instruction is ready. if (isLQEmpty()) - return Index; + return IR; // Check if there are no older loads. - if (Index <= *LoadQueue.begin()) - return Index; + const InstRef &Load = *LoadQueue.begin(); + if (Index <= Load.getSourceIndex()) + return IR; - // There is at least one younger load. - // // A load may pass a previous load. if (IsALoad) - return Index; + return IR; // A store may not pass a previous load. - return *LoadQueue.begin(); + return Load; } void LSUnit::onInstructionExecuted(const InstRef &IR) { @@ -161,29 +162,35 @@ void LSUnit::onInstructionExecuted(const InstRef &IR) { bool IsAStore = Desc.MayStore; if (IsALoad) { - if (LoadQueue.erase(Index)) { + if (LoadQueue.erase(IR)) { LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index << " has been removed from the load queue.\n"); } - if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) { - LLVM_DEBUG( - dbgs() << "[LSUnit]: Instruction idx=" << Index - << " has been removed from the set of load barriers.\n"); - LoadBarriers.erase(Index); + if (!LoadBarriers.empty()) { + const InstRef &LoadBarrier = *LoadBarriers.begin(); + if (Index == LoadBarrier.getSourceIndex()) { + LLVM_DEBUG( + dbgs() << "[LSUnit]: Instruction idx=" << Index + << " has been removed from the set of load barriers.\n"); + LoadBarriers.erase(IR); + } } } if (IsAStore) { - if (StoreQueue.erase(Index)) { + if (StoreQueue.erase(IR)) { LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index << " has been removed from the store queue.\n"); } - if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) { - LLVM_DEBUG( - dbgs() << "[LSUnit]: Instruction idx=" << Index - << " has been removed from the set of store barriers.\n"); - StoreBarriers.erase(Index); + if (!StoreBarriers.empty()) { + const InstRef &StoreBarrier = *StoreBarriers.begin(); + if (Index == StoreBarrier.getSourceIndex()) { + LLVM_DEBUG( + dbgs() << "[LSUnit]: Instruction idx=" << Index + << " has been removed from the set of store barriers.\n"); + StoreBarriers.erase(IR); + } } } } diff --git a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp index 9eeea9d011340..bf48d9288994c 100644 --- a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp +++ b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp @@ -119,9 +119,9 @@ bool Scheduler::promoteToReadySet(SmallVectorImpl &Ready) { // Check if there are still unsolved memory dependencies. Instruction &IS = *IR.getInstruction(); if (IS.isMemOp()) { - unsigned CriticalMemDep = LSU.isReady(IR); - if (CriticalMemDep != IR.getSourceIndex()) { - IS.setCriticalMemDep(CriticalMemDep); + const InstRef &CriticalMemDep = LSU.isReady(IR); + if (CriticalMemDep != IR) { + IS.setCriticalMemDep(CriticalMemDep.getSourceIndex()); ++I; continue; } @@ -158,7 +158,7 @@ bool Scheduler::promoteToPendingSet(SmallVectorImpl &Pending) { break; // Check if this instruction is now ready. In case, force - // a transition in state using method 'update()'. + // a transition in state using method 'updateDispatched()'. Instruction &IS = *IR.getInstruction(); if (IS.isDispatched() && !IS.updateDispatched()) { ++I; @@ -242,12 +242,10 @@ void Scheduler::analyzeDataDependencies(SmallVectorImpl &RegDeps, if (Resources->checkAvailability(IS.getDesc())) continue; - if (IS.isReady() || - (IS.isMemOp() && LSU.isReady(IR) != IR.getSourceIndex())) { + if (IS.isReady() || (IS.isMemOp() && LSU.isReady(IR) != IR)) MemDeps.emplace_back(IR); - } else { + else RegDeps.emplace_back(IR); - } } } @@ -304,8 +302,7 @@ bool Scheduler::dispatch(const InstRef &IR) { // Memory operations that are not in a ready state are initially assigned to // the WaitSet. - if (!IS.isReady() || - (IS.isMemOp() && LSU.isReady(IR) != IR.getSourceIndex())) { + if (!IS.isReady() || (IS.isMemOp() && LSU.isReady(IR) != IR)) { LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n"); WaitSet.push_back(IR); return false; From aa28b6d198a6dcf4f2c53676259b0f91e0babc35 Mon Sep 17 00:00:00 2001 From: Petar Jovanovic Date: Thu, 23 May 2019 13:49:06 +0000 Subject: [PATCH 0033/1176] [LiveDebugValues] Rename 'DMI' into 'DebugInstr' (NFC) This will improve code readability. Patch by Djordje Todorovic. Differential Revision: https://reviews.llvm.org/D62295 llvm-svn: 361497 --- llvm/lib/CodeGen/LiveDebugValues.cpp | 70 +++++++++++++++------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp index c062542e9c8b5..c56ba124a8de3 100644 --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues.cpp @@ -425,17 +425,17 @@ void LiveDebugValues::insertTransferDebugPair( MachineInstr &MI, OpenRangesSet &OpenRanges, TransferMap &Transfers, VarLocMap &VarLocIDs, unsigned OldVarID, TransferKind Kind, unsigned NewReg) { - const MachineInstr *DMI = &VarLocIDs[OldVarID].MI; + const MachineInstr *DebugInstr = &VarLocIDs[OldVarID].MI; MachineFunction *MF = MI.getParent()->getParent(); - MachineInstr *NewDMI; + MachineInstr *NewDebugInstr; auto ProcessVarLoc = [&MI, &OpenRanges, &Transfers, - &VarLocIDs](VarLoc &VL, MachineInstr *NewDMI) { + &VarLocIDs](VarLoc &VL, MachineInstr *NewDebugInstr) { unsigned LocId = VarLocIDs.insert(VL); OpenRanges.insert(LocId, VL.Var); - // The newly created DBG_VALUE instruction NewDMI must be inserted after - // MI. Keep track of the pairing. - TransferDebugPair MIP = {&MI, NewDMI}; + // The newly created DBG_VALUE instruction NewDebugInstr must be inserted + // after MI. Keep track of the pairing. + TransferDebugPair MIP = {&MI, NewDebugInstr}; Transfers.push_back(MIP); }; @@ -447,31 +447,33 @@ void LiveDebugValues::insertTransferDebugPair( "No register supplied when handling a copy of a debug value"); // Create a DBG_VALUE instruction to describe the Var in its new // register location. - NewDMI = BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), - DMI->isIndirectDebugValue(), NewReg, - DMI->getDebugVariable(), DMI->getDebugExpression()); - if (DMI->isIndirectDebugValue()) - NewDMI->getOperand(1).setImm(DMI->getOperand(1).getImm()); - VarLoc VL(*NewDMI, LS); - ProcessVarLoc(VL, NewDMI); + NewDebugInstr = BuildMI( + *MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(), + DebugInstr->isIndirectDebugValue(), NewReg, + DebugInstr->getDebugVariable(), DebugInstr->getDebugExpression()); + if (DebugInstr->isIndirectDebugValue()) + NewDebugInstr->getOperand(1).setImm(DebugInstr->getOperand(1).getImm()); + VarLoc VL(*NewDebugInstr, LS); + ProcessVarLoc(VL, NewDebugInstr); LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register copy: "; - NewDMI->print(dbgs(), false, false, false, TII)); + NewDebugInstr->print(dbgs(), false, false, false, TII)); return; } case TransferKind::TransferSpill: { // Create a DBG_VALUE instruction to describe the Var in its spilled // location. VarLoc::SpillLoc SpillLocation = extractSpillBaseRegAndOffset(MI); - auto *SpillExpr = DIExpression::prepend(DMI->getDebugExpression(), + auto *SpillExpr = DIExpression::prepend(DebugInstr->getDebugExpression(), DIExpression::ApplyOffset, SpillLocation.SpillOffset); - NewDMI = - BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), true, - SpillLocation.SpillBase, DMI->getDebugVariable(), SpillExpr); - VarLoc VL(*NewDMI, SpillLocation.SpillBase, SpillLocation.SpillOffset, LS); - ProcessVarLoc(VL, NewDMI); + NewDebugInstr = BuildMI( + *MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(), true, + SpillLocation.SpillBase, DebugInstr->getDebugVariable(), SpillExpr); + VarLoc VL(*NewDebugInstr, SpillLocation.SpillBase, + SpillLocation.SpillOffset, LS); + ProcessVarLoc(VL, NewDebugInstr); LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: "; - NewDMI->print(dbgs(), false, false, false, TII)); + NewDebugInstr->print(dbgs(), false, false, false, TII)); return; } case TransferKind::TransferRestore: { @@ -479,12 +481,13 @@ void LiveDebugValues::insertTransferDebugPair( "No register supplied when handling a restore of a debug value"); MachineFunction *MF = MI.getMF(); DIBuilder DIB(*const_cast(MF->getFunction()).getParent()); - NewDMI = BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), false, NewReg, - DMI->getDebugVariable(), DIB.createExpression()); - VarLoc VL(*NewDMI, LS); - ProcessVarLoc(VL, NewDMI); + NewDebugInstr = + BuildMI(*MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(), false, + NewReg, DebugInstr->getDebugVariable(), DIB.createExpression()); + VarLoc VL(*NewDebugInstr, LS); + ProcessVarLoc(VL, NewDebugInstr); LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register restore: "; - NewDMI->print(dbgs(), false, false, false, TII)); + NewDebugInstr->print(dbgs(), false, false, false, TII)); return; } } @@ -805,13 +808,14 @@ bool LiveDebugValues::join( // new range is started for the var from the mbb's beginning by inserting // a new DBG_VALUE. process() will end this range however appropriate. const VarLoc &DiffIt = VarLocIDs[ID]; - const MachineInstr *DMI = &DiffIt.MI; - MachineInstr *MI = - BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(), - DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), - DMI->getDebugVariable(), DMI->getDebugExpression()); - if (DMI->isIndirectDebugValue()) - MI->getOperand(1).setImm(DMI->getOperand(1).getImm()); + const MachineInstr *DebugInstr = &DiffIt.MI; + MachineInstr *MI = BuildMI( + MBB, MBB.instr_begin(), DebugInstr->getDebugLoc(), + DebugInstr->getDesc(), DebugInstr->isIndirectDebugValue(), + DebugInstr->getOperand(0).getReg(), DebugInstr->getDebugVariable(), + DebugInstr->getDebugExpression()); + if (DebugInstr->isIndirectDebugValue()) + MI->getOperand(1).setImm(DebugInstr->getOperand(1).getImm()); LLVM_DEBUG(dbgs() << "Inserted: "; MI->dump();); ILS.set(ID); ++NumInserted; From 465868d63273e317ec1bab0624c8c84038701086 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 23 May 2019 13:59:44 +0000 Subject: [PATCH 0034/1176] gn build: Merge r361487 llvm-svn: 361498 --- .../gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn index 1dcccc71d9a67..2efa42a124eec 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn @@ -13,6 +13,7 @@ static_library("google") { ] sources = [ "AvoidCStyleCastsCheck.cpp", + "AvoidNSObjectNewCheck.cpp", "AvoidThrowingObjCExceptionCheck.cpp", "AvoidUnderscoreInGoogletestNameCheck.cpp", "DefaultArgumentsCheck.cpp", From 74927554e22b3164e536a3e1a0ea4b70314b18e2 Mon Sep 17 00:00:00 2001 From: Lewis Revill Date: Thu, 23 May 2019 14:46:27 +0000 Subject: [PATCH 0035/1176] [RISCV] Support assembling TLS LA pseudo instructions This patch adds the pseudo instructions la.tls.ie and la.tls.gd, used in the initial-exec and global-dynamic TLS models respectively when addressing a global. The pseudo instructions are expanded in the assembly parser. llvm-svn: 361499 --- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 43 ++++++++ llvm/lib/Target/RISCV/RISCVInstrInfo.td | 10 ++ llvm/test/MC/RISCV/rvi-pseudos.s | 101 ++++++++++++++---- 3 files changed, 133 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index a1d0854e20263..bac43187ca770 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -93,6 +93,14 @@ class RISCVAsmParser : public MCTargetAsmParser { // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing. void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS + // addressing. + void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + + // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS + // addressing. + void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + // Helper to emit pseudo load/store instruction with a symbol. void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out, bool HasTmpReg); @@ -1590,6 +1598,35 @@ void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc, emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out); } +void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out) { + // The load TLS IE address pseudo-instruction "la.tls.ie" is used in + // initial-exec TLS model addressing of global symbols: + // la.tls.ie rdest, symbol + // expands to + // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol) + // Lx rdest, %pcrel_lo(TmpLabel)(rdest) + MCOperand DestReg = Inst.getOperand(0); + const MCExpr *Symbol = Inst.getOperand(1).getExpr(); + unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; + emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI, + SecondOpcode, IDLoc, Out); +} + +void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out) { + // The load TLS GD address pseudo-instruction "la.tls.gd" is used in + // global-dynamic TLS model addressing of global symbols: + // la.tls.gd rdest, symbol + // expands to + // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol) + // ADDI rdest, rdest, %pcrel_lo(TmpLabel) + MCOperand DestReg = Inst.getOperand(0); + const MCExpr *Symbol = Inst.getOperand(1).getExpr(); + emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI, + RISCV::ADDI, IDLoc, Out); +} + void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out, bool HasTmpReg) { @@ -1657,6 +1694,12 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case RISCV::PseudoLA: emitLoadAddress(Inst, IDLoc, Out); return false; + case RISCV::PseudoLA_TLS_IE: + emitLoadTLSIEAddress(Inst, IDLoc, Out); + return false; + case RISCV::PseudoLA_TLS_GD: + emitLoadTLSGDAddress(Inst, IDLoc, Out); + return false; case RISCV::PseudoLB: emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false); return false; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 99002386281a6..d7bcc21f3b49d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -926,6 +926,16 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], "la", "$dst, $src">; +let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, + isAsmParserOnly = 1 in +def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], + "la.tls.ie", "$dst, $src">; + +let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, + isAsmParserOnly = 1 in +def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], + "la.tls.gd", "$dst, $src">; + /// Loads multiclass LdPat { diff --git a/llvm/test/MC/RISCV/rvi-pseudos.s b/llvm/test/MC/RISCV/rvi-pseudos.s index 41e6e9c31850b..7ecdb8fb4ce10 100644 --- a/llvm/test/MC/RISCV/rvi-pseudos.s +++ b/llvm/test/MC/RISCV/rvi-pseudos.s @@ -1,9 +1,11 @@ -# RUN: llvm-mc %s -triple=riscv32 | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC -# RUN: llvm-mc %s -triple=riscv64 | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC +# RUN: llvm-mc %s -triple=riscv32 \ +# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC,CHECK-RV32 +# RUN: llvm-mc %s -triple=riscv64 \ +# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC,CHECK-RV64 # RUN: llvm-mc %s -triple=riscv32 -position-independent \ -# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-PIC-RV32 +# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-RV32,CHECK-PIC-RV32 # RUN: llvm-mc %s -triple=riscv64 -position-independent \ -# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-PIC-RV64 +# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-RV64,CHECK-PIC-RV64 # CHECK: .Lpcrel_hi0: # CHECK: auipc a0, %pcrel_hi(a_symbol) @@ -73,47 +75,104 @@ la a3, ra la a4, f1 # CHECK: .Lpcrel_hi10: +# CHECK: auipc a0, %tls_ie_pcrel_hi(a_symbol) +# CHECK-RV32: lw a0, %pcrel_lo(.Lpcrel_hi10)(a0) +# CHECK-RV64: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0) +la.tls.ie a0, a_symbol + +# CHECK: .Lpcrel_hi11: +# CHECK: auipc a1, %tls_ie_pcrel_hi(another_symbol) +# CHECK-RV32: lw a1, %pcrel_lo(.Lpcrel_hi11)(a1) +# CHECK-RV64: ld a1, %pcrel_lo(.Lpcrel_hi11)(a1) +la.tls.ie a1, another_symbol + +# Check that we can load the address of symbols that are spelled like a register +# CHECK: .Lpcrel_hi12: +# CHECK: auipc a2, %tls_ie_pcrel_hi(zero) +# CHECK-RV32: lw a2, %pcrel_lo(.Lpcrel_hi12)(a2) +# CHECK-RV64: ld a2, %pcrel_lo(.Lpcrel_hi12)(a2) +la.tls.ie a2, zero + +# CHECK: .Lpcrel_hi13: +# CHECK: auipc a3, %tls_ie_pcrel_hi(ra) +# CHECK-RV32: lw a3, %pcrel_lo(.Lpcrel_hi13)(a3) +# CHECK-RV64: ld a3, %pcrel_lo(.Lpcrel_hi13)(a3) +la.tls.ie a3, ra + +# CHECK: .Lpcrel_hi14: +# CHECK: auipc a4, %tls_ie_pcrel_hi(f1) +# CHECK-RV32: lw a4, %pcrel_lo(.Lpcrel_hi14)(a4) +# CHECK-RV64: ld a4, %pcrel_lo(.Lpcrel_hi14)(a4) +la.tls.ie a4, f1 + +# CHECK: .Lpcrel_hi15: +# CHECK: auipc a0, %tls_gd_pcrel_hi(a_symbol) +# CHECK: addi a0, a0, %pcrel_lo(.Lpcrel_hi15) +la.tls.gd a0, a_symbol + +# CHECK: .Lpcrel_hi16: +# CHECK: auipc a1, %tls_gd_pcrel_hi(another_symbol) +# CHECK: addi a1, a1, %pcrel_lo(.Lpcrel_hi16) +la.tls.gd a1, another_symbol + +# Check that we can load the address of symbols that are spelled like a register +# CHECK: .Lpcrel_hi17: +# CHECK: auipc a2, %tls_gd_pcrel_hi(zero) +# CHECK: addi a2, a2, %pcrel_lo(.Lpcrel_hi17) +la.tls.gd a2, zero + +# CHECK: .Lpcrel_hi18: +# CHECK: auipc a3, %tls_gd_pcrel_hi(ra) +# CHECK: addi a3, a3, %pcrel_lo(.Lpcrel_hi18) +la.tls.gd a3, ra + +# CHECK: .Lpcrel_hi19: +# CHECK: auipc a4, %tls_gd_pcrel_hi(f1) +# CHECK: addi a4, a4, %pcrel_lo(.Lpcrel_hi19) +la.tls.gd a4, f1 + +# CHECK: .Lpcrel_hi20: # CHECK: auipc a0, %pcrel_hi(a_symbol) -# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi10)(a0) +# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi20)(a0) lb a0, a_symbol -# CHECK: .Lpcrel_hi11: +# CHECK: .Lpcrel_hi21: # CHECK: auipc a1, %pcrel_hi(a_symbol) -# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi11)(a1) +# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi21)(a1) lh a1, a_symbol -# CHECK: .Lpcrel_hi12: +# CHECK: .Lpcrel_hi22: # CHECK: auipc a2, %pcrel_hi(a_symbol) -# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi12)(a2) +# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi22)(a2) lhu a2, a_symbol -# CHECK: .Lpcrel_hi13: +# CHECK: .Lpcrel_hi23: # CHECK: auipc a3, %pcrel_hi(a_symbol) -# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi13)(a3) +# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi23)(a3) lw a3, a_symbol -# CHECK: .Lpcrel_hi14: +# CHECK: .Lpcrel_hi24: # CHECK: auipc a4, %pcrel_hi(a_symbol) -# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi14)(a4) +# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi24)(a4) sb a3, a_symbol, a4 -# CHECK: .Lpcrel_hi15: +# CHECK: .Lpcrel_hi25: # CHECK: auipc a4, %pcrel_hi(a_symbol) -# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi15)(a4) +# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi25)(a4) sh a3, a_symbol, a4 -# CHECK: .Lpcrel_hi16: +# CHECK: .Lpcrel_hi26: # CHECK: auipc a4, %pcrel_hi(a_symbol) -# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi16)(a4) +# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi26)(a4) sw a3, a_symbol, a4 # Check that we can load the address of symbols that are spelled like a register -# CHECK: .Lpcrel_hi17: +# CHECK: .Lpcrel_hi27: # CHECK: auipc a2, %pcrel_hi(zero) -# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi17)(a2) +# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi27)(a2) lw a2, zero -# CHECK: .Lpcrel_hi18: +# CHECK: .Lpcrel_hi28: # CHECK: auipc a4, %pcrel_hi(zero) -# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi18)(a4) +# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi28)(a4) sw a3, zero, a4 From 1312225f8c46efe24a1f80b3935a72d172c2f61f Mon Sep 17 00:00:00 2001 From: Cameron McInally Date: Thu, 23 May 2019 14:53:42 +0000 Subject: [PATCH 0036/1176] [NFC][InstCombine] Add unary FNeg tests to maximum.ll/minimum.ll llvm-svn: 361500 --- llvm/test/Transforms/InstCombine/maximum.ll | 71 +++++++++++++++++++++ llvm/test/Transforms/InstCombine/minimum.ll | 71 +++++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/maximum.ll b/llvm/test/Transforms/InstCombine/maximum.ll index bd97a3794d45b..d02cb99e27812 100644 --- a/llvm/test/Transforms/InstCombine/maximum.ll +++ b/llvm/test/Transforms/InstCombine/maximum.ll @@ -226,6 +226,18 @@ define <2 x float> @neg_neg(<2 x float> %x, <2 x float> %y) { ret <2 x float> %r } +define <2 x float> @unary_neg_neg(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @unary_neg_neg( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.minimum.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> , [[TMP1]] +; CHECK-NEXT: ret <2 x float> [[R]] +; + %negx = fneg <2 x float> %x + %negy = fneg <2 x float> %y + %r = call <2 x float> @llvm.maximum.v2f32(<2 x float> %negx, <2 x float> %negy) + ret <2 x float> %r +} + ; FMF is not required, but it should be propagated from the intrinsic (not the fnegs). define float @neg_neg_vec_fmf(float %x, float %y) { @@ -240,6 +252,18 @@ define float @neg_neg_vec_fmf(float %x, float %y) { ret float %r } +define float @unary_neg_neg_vec_fmf(float %x, float %y) { +; CHECK-LABEL: @unary_neg_neg_vec_fmf( +; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.minimum.f32(float [[X:%.*]], float [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub fast float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: ret float [[R]] +; + %negx = fneg arcp float %x + %negy = fneg afn float %y + %r = call fast float @llvm.maximum.f32(float %negx, float %negy) + ret float %r +} + ; 1 extra use of an intermediate value should still allow the fold, ; but 2 would require more instructions than we started with. @@ -259,6 +283,21 @@ define float @neg_neg_extra_use_x(float %x, float %y) { ret float %r } +define float @unary_neg_neg_extra_use_x(float %x, float %y) { +; CHECK-LABEL: @unary_neg_neg_extra_use_x( +; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X]], float [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: call void @use(float [[NEGX]]) +; CHECK-NEXT: ret float [[R]] +; + %negx = fneg float %x + %negy = fneg float %y + %r = call float @llvm.maximum.f32(float %negx, float %negy) + call void @use(float %negx) + ret float %r +} + define float @neg_neg_extra_use_y(float %x, float %y) { ; CHECK-LABEL: @neg_neg_extra_use_y( ; CHECK-NEXT: [[NEGY:%.*]] = fsub float -0.000000e+00, [[Y:%.*]] @@ -274,6 +313,21 @@ define float @neg_neg_extra_use_y(float %x, float %y) { ret float %r } +define float @unary_neg_neg_extra_use_y(float %x, float %y) { +; CHECK-LABEL: @unary_neg_neg_extra_use_y( +; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.minimum.f32(float [[X:%.*]], float [[Y]]) +; CHECK-NEXT: [[R:%.*]] = fsub float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: call void @use(float [[NEGY]]) +; CHECK-NEXT: ret float [[R]] +; + %negx = fneg float %x + %negy = fneg float %y + %r = call float @llvm.maximum.f32(float %negx, float %negy) + call void @use(float %negy) + ret float %r +} + define float @neg_neg_extra_use_x_and_y(float %x, float %y) { ; CHECK-LABEL: @neg_neg_extra_use_x_and_y( ; CHECK-NEXT: [[NEGX:%.*]] = fsub float -0.000000e+00, [[X:%.*]] @@ -290,3 +344,20 @@ define float @neg_neg_extra_use_x_and_y(float %x, float %y) { call void @use(float %negy) ret float %r } + +define float @unary_neg_neg_extra_use_x_and_y(float %x, float %y) { +; CHECK-LABEL: @unary_neg_neg_extra_use_x_and_y( +; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]] +; CHECK-NEXT: [[NEGY:%.*]] = fneg float [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float [[NEGX]], float [[NEGY]]) +; CHECK-NEXT: call void @use(float [[NEGX]]) +; CHECK-NEXT: call void @use(float [[NEGY]]) +; CHECK-NEXT: ret float [[R]] +; + %negx = fneg float %x + %negy = fneg float %y + %r = call float @llvm.maximum.f32(float %negx, float %negy) + call void @use(float %negx) + call void @use(float %negy) + ret float %r +} diff --git a/llvm/test/Transforms/InstCombine/minimum.ll b/llvm/test/Transforms/InstCombine/minimum.ll index 32aae6417eba4..9ef9cb75137f0 100644 --- a/llvm/test/Transforms/InstCombine/minimum.ll +++ b/llvm/test/Transforms/InstCombine/minimum.ll @@ -250,6 +250,18 @@ define double @neg_neg(double %x, double %y) { ret double %r } +define double @unary_neg_neg(double %x, double %y) { +; CHECK-LABEL: @unary_neg_neg( +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximum.f64(double [[X:%.*]], double [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: ret double [[R]] +; + %negx = fneg double %x + %negy = fneg double %y + %r = call double @llvm.minimum.f64(double %negx, double %negy) + ret double %r +} + ; FMF is not required, but it should be propagated from the intrinsic (not the fnegs). ; Also, make sure this works with vectors. @@ -265,6 +277,18 @@ define <2 x double> @neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) { ret <2 x double> %r } +define <2 x double> @unary_neg_neg_vec_fmf(<2 x double> %x, <2 x double> %y) { +; CHECK-LABEL: @unary_neg_neg_vec_fmf( +; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf <2 x double> @llvm.maximum.v2f64(<2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub nnan ninf <2 x double> , [[TMP1]] +; CHECK-NEXT: ret <2 x double> [[R]] +; + %negx = fneg reassoc <2 x double> %x + %negy = fneg fast <2 x double> %y + %r = call nnan ninf <2 x double> @llvm.minimum.v2f64(<2 x double> %negx, <2 x double> %negy) + ret <2 x double> %r +} + ; 1 extra use of an intermediate value should still allow the fold, ; but 2 would require more instructions than we started with. @@ -284,6 +308,21 @@ define double @neg_neg_extra_use_x(double %x, double %y) { ret double %r } +define double @unary_neg_neg_extra_use_x(double %x, double %y) { +; CHECK-LABEL: @unary_neg_neg_extra_use_x( +; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximum.f64(double [[X]], double [[Y:%.*]]) +; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: call void @use(double [[NEGX]]) +; CHECK-NEXT: ret double [[R]] +; + %negx = fneg double %x + %negy = fneg double %y + %r = call double @llvm.minimum.f64(double %negx, double %negy) + call void @use(double %negx) + ret double %r +} + define double @neg_neg_extra_use_y(double %x, double %y) { ; CHECK-LABEL: @neg_neg_extra_use_y( ; CHECK-NEXT: [[NEGY:%.*]] = fsub double -0.000000e+00, [[Y:%.*]] @@ -299,6 +338,21 @@ define double @neg_neg_extra_use_y(double %x, double %y) { ret double %r } +define double @unary_neg_neg_extra_use_y(double %x, double %y) { +; CHECK-LABEL: @unary_neg_neg_extra_use_y( +; CHECK-NEXT: [[NEGY:%.*]] = fneg double [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.maximum.f64(double [[X:%.*]], double [[Y]]) +; CHECK-NEXT: [[R:%.*]] = fsub double -0.000000e+00, [[TMP1]] +; CHECK-NEXT: call void @use(double [[NEGY]]) +; CHECK-NEXT: ret double [[R]] +; + %negx = fneg double %x + %negy = fneg double %y + %r = call double @llvm.minimum.f64(double %negx, double %negy) + call void @use(double %negy) + ret double %r +} + define double @neg_neg_extra_use_x_and_y(double %x, double %y) { ; CHECK-LABEL: @neg_neg_extra_use_x_and_y( ; CHECK-NEXT: [[NEGX:%.*]] = fsub double -0.000000e+00, [[X:%.*]] @@ -315,3 +369,20 @@ define double @neg_neg_extra_use_x_and_y(double %x, double %y) { call void @use(double %negy) ret double %r } + +define double @unary_neg_neg_extra_use_x_and_y(double %x, double %y) { +; CHECK-LABEL: @unary_neg_neg_extra_use_x_and_y( +; CHECK-NEXT: [[NEGX:%.*]] = fneg double [[X:%.*]] +; CHECK-NEXT: [[NEGY:%.*]] = fneg double [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = call double @llvm.minimum.f64(double [[NEGX]], double [[NEGY]]) +; CHECK-NEXT: call void @use(double [[NEGX]]) +; CHECK-NEXT: call void @use(double [[NEGY]]) +; CHECK-NEXT: ret double [[R]] +; + %negx = fneg double %x + %negy = fneg double %y + %r = call double @llvm.minimum.f64(double %negx, double %negy) + call void @use(double %negx) + call void @use(double %negy) + ret double %r +} From 0857a4ec20db4b038fb5346ed09e3253842f0169 Mon Sep 17 00:00:00 2001 From: Don Hinton Date: Thu, 23 May 2019 15:03:22 +0000 Subject: [PATCH 0037/1176] [cmake] When getting Ninja version, don't include CMakeNinjaFindMake which doesn't play well with passing CMAKE_MAKE_PROGRAM from the commandline without a path. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a bug introduced in r361280. Thanks to Mikael Holmén for reporting this! llvm-svn: 361501 --- llvm/cmake/config-ix.cmake | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 36ec98a938623..e1e5cd3198b22 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -555,14 +555,11 @@ set(LLVM_BINUTILS_INCDIR "" CACHE PATH "PATH to binutils/include containing plugin-api.h for gold plugin.") if(CMAKE_GENERATOR STREQUAL "Ninja") - include(CMakeNinjaFindMake OPTIONAL) - if(CMAKE_MAKE_PROGRAM) - execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} --version - OUTPUT_VARIABLE NINJA_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - set(NINJA_VERSION ${NINJA_VERSION} CACHE STRING "Ninja version number" FORCE) - message(STATUS "Ninja version: ${NINJA_VERSION}") - endif() + execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} --version + OUTPUT_VARIABLE NINJA_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(NINJA_VERSION ${NINJA_VERSION} CACHE STRING "Ninja version number" FORCE) + message(STATUS "Ninja version: ${NINJA_VERSION}") endif() if(CMAKE_GENERATOR STREQUAL "Ninja" AND From c63b37dd408eb49ed056e97e50a275026b2545b9 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Thu, 23 May 2019 15:07:46 +0000 Subject: [PATCH 0038/1176] Work around a Visual C++ bug. Using a static function as a template parameter gets a bogus compile-time error with Visual Studio 2017, prior to version 15.8. Our current minimum-version requirement is a particular update to VS2015, and we assume all Visual Studio 2017 versions are usable. This patch makes the code buildable with older versions of VS2017, and can be reverted after we upgrade the minimum version sometime in the future. Description of the Microsoft bug: https://developercommunity.visualstudio.com/content/problem/25334/error-code-c2971-when-specifying-a-function-as-the.html Differential Revision: https://reviews.llvm.org/D62202 llvm-svn: 361502 --- .../lib/Tooling/Refactoring/RangeSelector.cpp | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/clang/lib/Tooling/Refactoring/RangeSelector.cpp b/clang/lib/Tooling/Refactoring/RangeSelector.cpp index 23479c58fdf99..92426db3a5ebe 100644 --- a/clang/lib/Tooling/Refactoring/RangeSelector.cpp +++ b/clang/lib/Tooling/Refactoring/RangeSelector.cpp @@ -218,37 +218,47 @@ class RelativeSelector { }; } // namespace +// FIXME: Change the following functions from being in an anonymous namespace +// to static functions, after the minimum Visual C++ has _MSC_VER >= 1915 +// (equivalent to Visual Studio 2017 v15.8 or higher). Using the anonymous +// namespace works around a bug in earlier versions. +namespace { // Returns the range of the statements (all source between the braces). -static CharSourceRange getStatementsRange(const MatchResult &, - const CompoundStmt &CS) { +CharSourceRange getStatementsRange(const MatchResult &, + const CompoundStmt &CS) { return CharSourceRange::getCharRange(CS.getLBracLoc().getLocWithOffset(1), CS.getRBracLoc()); } +} // namespace RangeSelector tooling::statements(StringRef ID) { return RelativeSelector(ID); } +namespace { // Returns the range of the source between the call's parentheses. -static CharSourceRange getCallArgumentsRange(const MatchResult &Result, - const CallExpr &CE) { +CharSourceRange getCallArgumentsRange(const MatchResult &Result, + const CallExpr &CE) { return CharSourceRange::getCharRange( findOpenParen(CE, *Result.SourceManager, Result.Context->getLangOpts()) .getLocWithOffset(1), CE.getRParenLoc()); } +} // namespace RangeSelector tooling::callArgs(StringRef ID) { return RelativeSelector(ID); } +namespace { // Returns the range of the elements of the initializer list. Includes all // source between the braces. -static CharSourceRange getElementsRange(const MatchResult &, - const InitListExpr &E) { +CharSourceRange getElementsRange(const MatchResult &, + const InitListExpr &E) { return CharSourceRange::getCharRange(E.getLBraceLoc().getLocWithOffset(1), E.getRBraceLoc()); } +} // namespace RangeSelector tooling::initListElements(StringRef ID) { return RelativeSelector(ID); From 85200645c6e86fb684b6e10eb8193f460e31c18d Mon Sep 17 00:00:00 2001 From: Konrad Kleine Date: Thu, 23 May 2019 15:17:39 +0000 Subject: [PATCH 0039/1176] [lldb] fix cannot convert from 'nullptr' to 'lldb::thread_result_t' Summary: On Windows `lldb::thread_result_t` resolves to `typedef unsigned thread_result_t;` and on other platforms it resolves to `typedef void *thread_result_t;`. Therefore one cannot use `nullptr` when returning from a function that returns `thread_result_t`. I've made this change because a windows build bot fails with these errors: ``` E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Core\Communication.cpp(362): error C2440: 'return': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Core\Communication.cpp(362): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type ``` and ``` E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Core\Debugger.cpp(1619): error C2440: 'return': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Core\Debugger.cpp(1619): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Core\Debugger.cpp(1664): error C2440: 'return': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Core\Debugger.cpp(1664): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type ``` This is the failing build: http://lab.llvm.org:8011/builders/lldb-x64-windows-ninja/builds/5035/steps/build/logs/stdio Reviewers: JDevlieghere, teemperor, jankratochvil, labath, clayborg, RKSimon, courbet, jhenderson Reviewed By: labath, clayborg Subscribers: labath, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D62305 llvm-svn: 361503 --- lldb/source/Core/Communication.cpp | 2 +- lldb/source/Core/Debugger.cpp | 4 ++-- lldb/source/Host/common/TaskPool.cpp | 2 +- lldb/source/Host/windows/HostProcessWindows.cpp | 2 +- .../Plugins/Process/Windows/Common/DebuggerThread.cpp | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp index f2919d807d596..c39976d6556b1 100644 --- a/lldb/source/Core/Communication.cpp +++ b/lldb/source/Core/Communication.cpp @@ -359,7 +359,7 @@ lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) { // Let clients know that this thread is exiting comm->BroadcastEvent(eBroadcastBitNoMorePendingInput); comm->BroadcastEvent(eBroadcastBitReadThreadDidExit); - return nullptr; + return {}; } void Communication::SetReadThreadBytesReceivedCallback( diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 79402813e845f..0afdf0690214d 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1616,7 +1616,7 @@ void Debugger::DefaultEventHandler() { lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) { ((Debugger *)arg)->DefaultEventHandler(); - return nullptr; + return {}; } bool Debugger::StartEventHandlerThread() { @@ -1661,7 +1661,7 @@ lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) { Debugger *debugger = (Debugger *)arg; debugger->ExecuteIOHandlers(); debugger->StopEventHandlerThread(); - return nullptr; + return {}; } bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } diff --git a/lldb/source/Host/common/TaskPool.cpp b/lldb/source/Host/common/TaskPool.cpp index d63d9f35d1e21..dcc4363078da0 100644 --- a/lldb/source/Host/common/TaskPool.cpp +++ b/lldb/source/Host/common/TaskPool.cpp @@ -73,7 +73,7 @@ void TaskPoolImpl::AddTask(std::function &&task_fn) { lldb::thread_result_t TaskPoolImpl::WorkerPtr(void *pool) { Worker((TaskPoolImpl *)pool); - return nullptr; + return {}; } void TaskPoolImpl::Worker(TaskPoolImpl *pool) { diff --git a/lldb/source/Host/windows/HostProcessWindows.cpp b/lldb/source/Host/windows/HostProcessWindows.cpp index 6b016bf53dab0..573218ed8f623 100644 --- a/lldb/source/Host/windows/HostProcessWindows.cpp +++ b/lldb/source/Host/windows/HostProcessWindows.cpp @@ -109,7 +109,7 @@ lldb::thread_result_t HostProcessWindows::MonitorThread(void *thread_arg) { ::CloseHandle(info->process_handle); delete (info); } - return 0; + return {}; } void HostProcessWindows::Close() { diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp index ad7feaa2d3703..104ac229f2f41 100644 --- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp @@ -132,7 +132,7 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( else m_debug_delegate->OnDebuggerError(error, 0); - return 0; + return {}; } lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( @@ -148,7 +148,7 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( if (!DebugActiveProcess((DWORD)pid)) { Status error(::GetLastError(), eErrorTypeWin32); m_debug_delegate->OnDebuggerError(error, 0); - return 0; + return {}; } // The attach was successful, enter the debug loop. From here on out, this @@ -156,7 +156,7 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( // in DebugLaunch should apply from this point out. DebugLoop(); - return 0; + return {}; } Status DebuggerThread::StopDebugging(bool terminate) { From 762d008a7c35c84468f713b93748190a52f0dfe5 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 23 May 2019 15:23:16 +0000 Subject: [PATCH 0040/1176] [Driver] Try normalized triple when looking for C++ libraries This addresses the issue introduced in r361432 where we would only try effective triple but not the normalized one as we do for other runtimes. Differential Revision: https://reviews.llvm.org/D62286 llvm-svn: 361504 --- clang/lib/Driver/ToolChain.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 3b0e8f2dbaa85..08d1ebb75d7bc 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -80,6 +80,11 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T, llvm::sys::path::append(P, "..", "lib", D.getTargetTriple(), "c++"); if (getVFS().exists(P)) getLibraryPaths().push_back(P.str()); + + P.assign(D.Dir); + llvm::sys::path::append(P, "..", "lib", Triple.str(), "c++"); + if (getVFS().exists(P)) + getLibraryPaths().push_back(P.str()); } P.assign(D.ResourceDir); From 8cffa848509f3a16a863a31ce51e226fcf79875e Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 23 May 2019 15:49:04 +0000 Subject: [PATCH 0041/1176] [analyzer][NFC] Prettify some RUN: lines in test files. This is a test commit in disguise. llvm-svn: 361505 --- clang/test/Analysis/bsd-string.c | 6 ++- clang/test/Analysis/bstring.c | 31 ++++++++++++-- clang/test/Analysis/cstring-plist.c | 4 +- clang/test/Analysis/null-deref-ps-region.c | 6 ++- clang/test/Analysis/string.c | 48 +++++++++++++++++++--- 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/clang/test/Analysis/bsd-string.c b/clang/test/Analysis/bsd-string.c index 4fbfd48ad8aef..6e04a62ecfec5 100644 --- a/clang/test/Analysis/bsd-string.c +++ b/clang/test/Analysis/bsd-string.c @@ -1,4 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring.NullArg,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring.NullArg \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection #define NULL ((void *)0) diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c index f472a3e0111ae..beabb0f0241e4 100644 --- a/clang/test/Analysis/bstring.c +++ b/clang/test/Analysis/bstring.c @@ -1,7 +1,30 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -verify %s \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -DUSE_BUILTINS \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -DVARIANT \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -DUSE_BUILTINS -DVARIANT \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false //===----------------------------------------------------------------------=== // Declarations diff --git a/clang/test/Analysis/cstring-plist.c b/clang/test/Analysis/cstring-plist.c index c527564d49e37..65fa9fe74d1d3 100644 --- a/clang/test/Analysis/cstring-plist.c +++ b/clang/test/Analysis/cstring-plist.c @@ -1,6 +1,8 @@ // RUN: rm -f %t // RUN: %clang_analyze_cc1 -fblocks \ -// RUN: -analyzer-checker=core,unix.Malloc,unix.cstring.NullArg \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-checker=unix.cstring.NullArg \ // RUN: -analyzer-disable-checker=alpha.unix.cstring.OutOfBounds \ // RUN: -analyzer-output=plist -o %t %s // RUN: FileCheck -input-file %t %s diff --git a/clang/test/Analysis/null-deref-ps-region.c b/clang/test/Analysis/null-deref-ps-region.c index 2bc338cd3f2a7..71b7a1ddb0502 100644 --- a/clang/test/Analysis/null-deref-ps-region.c +++ b/clang/test/Analysis/null-deref-ps-region.c @@ -1,4 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,unix,alpha.unix -std=gnu99 -analyzer-store=region -verify %s +// RUN: %clang_analyze_cc1 -verify %s -std=gnu99 \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=alpha.core \ +// RUN: -analyzer-checker=unix \ +// RUN: -analyzer-checker=alpha.unix #include "Inputs/system-header-simulator.h" diff --git a/clang/test/Analysis/string.c b/clang/test/Analysis/string.c index 107c199c68dc2..d3b131ec9a64f 100644 --- a/clang/test/Analysis/string.c +++ b/clang/test/Analysis/string.c @@ -1,8 +1,46 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=alpha.security.taint,core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -Wno-null-dereference -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference -DUSE_BUILTINS \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference -DVARIANT \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \ +// RUN: -DUSE_BUILTINS -DVARIANT \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=alpha.security.taint \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-checker=alpha.unix.cstring \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false +// +// RUN: %clang_analyze_cc1 -verify %s -Wno-null-dereference \ +// RUN: -DSUPPRESS_OUT_OF_BOUND \ +// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=unix.Malloc \ +// RUN: -analyzer-checker=alpha.unix.cstring.BufferOverlap \ +// RUN: -analyzer-checker=alpha.unix.cstring.NotNullTerminated \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config eagerly-assume=false //===----------------------------------------------------------------------=== // Declarations From 6aebd8394a2bb9e514d0eaf8c8124b79974a2ba8 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 23 May 2019 16:01:59 +0000 Subject: [PATCH 0042/1176] [Object] object::ELFObjectFile::symbol_begin(): skip symbol index 0 For clients iterating the symbol table, none expects to handle index 0 (STN_UNDEF). Skip it to improve consistency with other binary formats. Clients that need STN_UNDEF (e.g. lld) can use getSectionContentsAsArray(). A test will be added in D62148. Reviewed By: mtrent Differential Revision: https://reviews.llvm.org/D62296 llvm-svn: 361506 --- llvm/include/llvm/Object/ELFObjectFile.h | 4 +++- llvm/tools/llvm-objdump/llvm-objdump.cpp | 5 ----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index 0aa6c935a8354..ed54ad02ccff7 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -982,7 +982,9 @@ ELFObjectFile::ELFObjectFile(ELFObjectFile &&Other) template basic_symbol_iterator ELFObjectFile::symbol_begin() const { - DataRefImpl Sym = toDRI(DotSymtabSec, 0); + DataRefImpl Sym = + toDRI(DotSymtabSec, + DotSymtabSec && DotSymtabSec->sh_size >= sizeof(Elf_Sym) ? 1 : 0); return basic_symbol_iterator(SymbolRef(Sym, this)); } diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 318e0ade9425c..1312ea8bbd1ba 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1643,11 +1643,6 @@ void printSymbolTable(const ObjectFile *O, StringRef ArchiveName, const StringRef FileName = O->getFileName(); for (auto I = O->symbol_begin(), E = O->symbol_end(); I != E; ++I) { - // Skip printing the special zero symbol when dumping an ELF file. - // This makes the output consistent with the GNU objdump. - if (I == O->symbol_begin() && isa(O)) - continue; - const SymbolRef &Symbol = *I; uint64_t Address = unwrapOrError(Symbol.getAddress(), ArchiveName, FileName, ArchitectureName); From 000228183bf17a0f64afccdda35867553c9b75f6 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 23 May 2019 16:05:21 +0000 Subject: [PATCH 0043/1176] Ensure builtins use the target default Calling Convention r355317 changed builtins/allocation functions to use the default calling convention in order to support platforms that use non-cdecl calling conventions by default. However the default calling convention is overridable on Windows 32 bit implementations with some of the /G options. The intent is to permit the user to set the calling convention of normal functions, however it should NOT apply to builtins and C++ allocation functions. This patch ensures that the builtin/allocation functions always use the Target specific Calling Convention, ignoring the user overridden version of said default. llvm-svn: 361507 --- clang/include/clang/AST/ASTContext.h | 3 +- clang/lib/AST/ASTContext.cpp | 57 ++++++++++--------- clang/lib/Sema/SemaExprCXX.cpp | 2 +- .../test/CodeGenCXX/builtin-calling-conv.cpp | 11 ++++ 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 5cb4a82ced198..6856cb6585f82 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2395,7 +2395,8 @@ class ASTContext : public RefCountedBase { /// Retrieves the default calling convention for the current target. CallingConv getDefaultCallingConvention(bool IsVariadic, - bool IsCXXMethod) const; + bool IsCXXMethod, + bool IsBuiltin = false) const; /// Retrieves the "canonical" template name that refers to a /// given template. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 71745042fd890..c3a09723ef189 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9627,8 +9627,8 @@ QualType ASTContext::GetBuiltinType(unsigned Id, bool Variadic = (TypeStr[0] == '.'); - FunctionType::ExtInfo EI( - getDefaultCallingConvention(Variadic, /*IsCXXMethod=*/false)); + FunctionType::ExtInfo EI(getDefaultCallingConvention( + Variadic, /*IsCXXMethod=*/false, /*IsBuiltin=*/true)); if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true); @@ -10005,34 +10005,39 @@ void ASTContext::forEachMultiversionedFunctionVersion( } CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, - bool IsCXXMethod) const { + bool IsCXXMethod, + bool IsBuiltin) const { // Pass through to the C++ ABI object if (IsCXXMethod) return ABI->getDefaultMethodCallConv(IsVariadic); - switch (LangOpts.getDefaultCallingConv()) { - case LangOptions::DCC_None: - break; - case LangOptions::DCC_CDecl: - return CC_C; - case LangOptions::DCC_FastCall: - if (getTargetInfo().hasFeature("sse2") && !IsVariadic) - return CC_X86FastCall; - break; - case LangOptions::DCC_StdCall: - if (!IsVariadic) - return CC_X86StdCall; - break; - case LangOptions::DCC_VectorCall: - // __vectorcall cannot be applied to variadic functions. - if (!IsVariadic) - return CC_X86VectorCall; - break; - case LangOptions::DCC_RegCall: - // __regcall cannot be applied to variadic functions. - if (!IsVariadic) - return CC_X86RegCall; - break; + // Builtins ignore user-specified default calling convention and remain the + // Target's default calling convention. + if (!IsBuiltin) { + switch (LangOpts.getDefaultCallingConv()) { + case LangOptions::DCC_None: + break; + case LangOptions::DCC_CDecl: + return CC_C; + case LangOptions::DCC_FastCall: + if (getTargetInfo().hasFeature("sse2") && !IsVariadic) + return CC_X86FastCall; + break; + case LangOptions::DCC_StdCall: + if (!IsVariadic) + return CC_X86StdCall; + break; + case LangOptions::DCC_VectorCall: + // __vectorcall cannot be applied to variadic functions. + if (!IsVariadic) + return CC_X86VectorCall; + break; + case LangOptions::DCC_RegCall: + // __regcall cannot be applied to variadic functions. + if (!IsVariadic) + return CC_X86RegCall; + break; + } } return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 87dc3a9a54a9a..455a71bd0ac0a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2816,7 +2816,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, } FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/false)); + /*IsVariadic=*/false, /*IsCXXMethod=*/false, /*IsBuiltin=*/true)); QualType BadAllocType; bool HasBadAllocExceptionSpec diff --git a/clang/test/CodeGenCXX/builtin-calling-conv.cpp b/clang/test/CodeGenCXX/builtin-calling-conv.cpp index 6fdeca0d2c473..f7759e3e8cad6 100644 --- a/clang/test/CodeGenCXX/builtin-calling-conv.cpp +++ b/clang/test/CodeGenCXX/builtin-calling-conv.cpp @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple spir-unknown-unknown -DREDECL -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR // RUN: %clang_cc1 -triple x86_64-linux-pc -emit-llvm %s -o - | FileCheck %s -check-prefix LINUX // RUN: %clang_cc1 -triple spir-unknown-unknown -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR +// RUN: %clang_cc1 -triple i386-windows-pc -fdefault-calling-conv=stdcall -emit-llvm %s -o - | FileCheck %s -check-prefix WIN32 #ifdef REDECL namespace std { @@ -40,3 +41,13 @@ void user() { // SPIR: declare spir_func noalias i8* @_Znwj(i32) // SPIR: declare spir_func float @atan2f(float, float) // SPIR: declare spir_func void @_Z3foov() + +// Note: Windows /G options should not change the platform default calling +// convention of builtins. +// WIN32: define dso_local x86_stdcallcc void @"?user@@YGXXZ"() +// WIN32: call i8* @"??2@YAPAXI@Z" +// WIN32: call float @atan2f +// WIN32: call x86_stdcallcc void @"?foo@@YGXXZ" +// WIN32: declare dso_local noalias i8* @"??2@YAPAXI@Z"( +// WIN32: declare dso_local float @atan2f(float, float) +// WIN32: declare dso_local x86_stdcallcc void @"?foo@@YGXXZ"() From 87226a720293281f49a312fe8342d1fdd0aa38ca Mon Sep 17 00:00:00 2001 From: Shoaib Meenai Date: Thu, 23 May 2019 16:29:09 +0000 Subject: [PATCH 0044/1176] [AsmPrinter] Treat a narrowing PtrToInt like Trunc When printing assembly for PtrToInt, AsmPrinter::lowerConstant incorrectly assumed that if PtrToInt was not converting to an int with exactly the same number of bits, it must be widening to a larger int. But this isn't necessarily true; PtrToInt can also shrink the size, which is useful when you want to produce a known 32-bit pointer on a 64-bit platform (on x86_64 ELF this yields a R_X86_64_32 relocation). The old behavior of falling through to the widening case for a narrowing PtrToInt yields bogus assembly code like this, which fails to assemble because the no-op bit and it accidentally creates is not a valid relocation: ``` .long a&-1 ``` The fix is to treat a narrowing PtrToInt exactly the same as it already treats Trunc: just emit the expression and let the assembler deal with truncating it in the appropriate way. Patch by Mat Hostetter . Differential Revision: https://reviews.llvm.org/D61325 llvm-svn: 361508 --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 5 ++++- llvm/test/CodeGen/X86/ptrtoint-narrow.ll | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/X86/ptrtoint-narrow.ll diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index b57eac3d72e97..bf7776b1dc000 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2231,7 +2231,10 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { // We can emit the pointer value into this slot if the slot is an // integer slot equal to the size of the pointer. - if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType())) + // + // If the pointer is larger than the resultant integer, then + // as with Trunc just depend on the assembler to truncate it. + if (DL.getTypeAllocSize(Ty) <= DL.getTypeAllocSize(Op->getType())) return OpExpr; // Otherwise the pointer is smaller than the resultant integer, mask off diff --git a/llvm/test/CodeGen/X86/ptrtoint-narrow.ll b/llvm/test/CodeGen/X86/ptrtoint-narrow.ll new file mode 100644 index 0000000000000..c34e7b1ec51de --- /dev/null +++ b/llvm/test/CodeGen/X86/ptrtoint-narrow.ll @@ -0,0 +1,6 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s + +@ptr = external global i8, align 1 +@ref = constant i32 ptrtoint (i8* @ptr to i32), align 4 + +; CHECK: .long ptr{{$}} From 27b3b5d952c5981bb850832c86c797616ece8dd6 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Thu, 23 May 2019 16:32:19 +0000 Subject: [PATCH 0045/1176] [MCA] Add the ability to compute critical register dependency of an instruction. This patch adds the methods `getCriticalRegDep()` and `computeCriticalRegDep()` to class InstructionBase. The goal is to allow users to obtain information about the critical register dependency that most affects the latency of an instruction. These methods are currently unused. However, the long term plan is to use them in order to allow the computation of a critical-path as part of the bottleneck analysis. So, this is yet another step towards fixing PR37494. llvm-svn: 361509 --- llvm/include/llvm/MCA/Instruction.h | 43 ++++++++++++++++++++--------- llvm/lib/MCA/Instruction.cpp | 34 ++++++++++++++++++++++- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h index a7a47fd3645ed..c4d0f6aace35a 100644 --- a/llvm/include/llvm/MCA/Instruction.h +++ b/llvm/include/llvm/MCA/Instruction.h @@ -80,6 +80,16 @@ struct ReadDescriptor { class ReadState; +/// Longest register dependency. +/// +/// Used internally by WriteState/ReadState/InstructionBase to help with the +/// computation of the longest register dependency for an instruction. +struct CriticalRegDep { + unsigned IID; + unsigned RegID; + unsigned Cycles; +}; + /// Tracks uses of a register definition (e.g. register write). /// /// Each implicit/explicit register write is associated with an instance of @@ -123,9 +133,11 @@ class WriteState { // A partial write that is in a false dependency with this write. WriteState *PartialWrite; - unsigned DependentWriteCyclesLeft; + // Critical register dependency for this write. + CriticalRegDep CRD; + // A list of dependent reads. Users is a set of dependent // reads. A dependent read is added to the set only if CyclesLeft // is "unknown". As soon as CyclesLeft is 'known', each user in the set @@ -140,7 +152,7 @@ class WriteState { : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0), ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero), IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr), - DependentWriteCyclesLeft(0) {} + DependentWriteCyclesLeft(0), CRD() {} WriteState(const WriteState &Other) = default; WriteState &operator=(const WriteState &Other) = default; @@ -150,7 +162,11 @@ class WriteState { unsigned getRegisterID() const { return RegisterID; } unsigned getRegisterFileID() const { return PRFID; } unsigned getLatency() const { return WD->Latency; } + unsigned getDependentWriteCyclesLeft() const { + return DependentWriteCyclesLeft; + } const WriteState *getDependentWrite() const { return DependentWrite; } + const CriticalRegDep &getCriticalRegDep() const { return CRD; } // This method adds Use to the set of data dependent reads. IID is the // instruction identifier associated with this write. ReadAdvance is the @@ -162,10 +178,6 @@ class WriteState { // write. IID is the instruction identifier associated with this write. void addUser(unsigned IID, WriteState *Use); - unsigned getDependentWriteCyclesLeft() const { - return DependentWriteCyclesLeft; - } - unsigned getNumUsers() const { unsigned NumUsers = Users.size(); if (PartialWrite) @@ -189,11 +201,7 @@ class WriteState { } void setDependentWrite(const WriteState *Other) { DependentWrite = Other; } - void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { - DependentWriteCyclesLeft = Cycles; - DependentWrite = nullptr; - } - + void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles); void setWriteZero() { WritesZero = true; } void setEliminated() { assert(Users.empty() && "Write is in an inconsistent state."); @@ -235,6 +243,8 @@ class ReadState { // dependent writes (i.e. field DependentWrite) is zero, this value is // propagated to field CyclesLeft. unsigned TotalCycles; + // Longest register dependency. + CriticalRegDep CRD; // This field is set to true only if there are no dependent writes, and // there are no `CyclesLeft' to wait. bool IsReady; @@ -246,13 +256,14 @@ class ReadState { public: ReadState(const ReadDescriptor &Desc, unsigned RegID) : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), - CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true), - IsZero(false), IndependentFromDef(false) {} + CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), + IsReady(true), IsZero(false), IndependentFromDef(false) {} const ReadDescriptor &getDescriptor() const { return *RD; } unsigned getSchedClass() const { return RD->SchedClassID; } unsigned getRegisterID() const { return RegisterID; } unsigned getRegisterFileID() const { return PRFID; } + const CriticalRegDep &getCriticalRegDep() const { return CRD; } bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; } bool isReady() const { return IsReady; } @@ -394,6 +405,9 @@ class InstructionBase { // One entry per each implicit and explicit register use. SmallVector Uses; + // Critical register dependency. + CriticalRegDep CRD; + public: InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {} @@ -405,6 +419,9 @@ class InstructionBase { unsigned getLatency() const { return Desc.MaxLatency; } + const CriticalRegDep &getCriticalRegDep() const { return CRD; } + const CriticalRegDep &computeCriticalRegDep(); + bool hasDependentUsers() const { return any_of(Defs, [](const WriteState &Def) { return Def.getNumUsers() > 0; }); diff --git a/llvm/lib/MCA/Instruction.cpp b/llvm/lib/MCA/Instruction.cpp index 58f0250313784..5e2fb771e4f5f 100644 --- a/llvm/lib/MCA/Instruction.cpp +++ b/llvm/lib/MCA/Instruction.cpp @@ -18,6 +18,14 @@ namespace llvm { namespace mca { +void WriteState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { + CRD.IID = IID; + CRD.RegID = RegID; + CRD.Cycles = Cycles; + DependentWriteCyclesLeft = Cycles; + DependentWrite = nullptr; +} + void ReadState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { assert(DependentWrites); assert(CyclesLeft == UNKNOWN_CYCLES); @@ -28,7 +36,12 @@ void ReadState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) { // The HW is forced to do some extra bookkeeping to track of all the // dependent writes, and implement a merging scheme for the partial writes. --DependentWrites; - TotalCycles = std::max(TotalCycles, Cycles); + if (TotalCycles < Cycles) { + CRD.IID = IID; + CRD.RegID = RegID; + CRD.Cycles = Cycles; + TotalCycles = Cycles; + } if (!DependentWrites) { CyclesLeft = TotalCycles; @@ -121,6 +134,25 @@ void WriteRef::dump() const { } #endif +const CriticalRegDep &InstructionBase::computeCriticalRegDep() { + if (CRD.Cycles || (Defs.empty() && Uses.empty())) + return CRD; + unsigned MaxLatency = 0; + for (const WriteState &WS : Defs) { + const CriticalRegDep &WriteCRD = WS.getCriticalRegDep(); + if (WriteCRD.Cycles > MaxLatency) + CRD = WriteCRD; + } + + for (const ReadState &RS : Uses) { + const CriticalRegDep &ReadCRD = RS.getCriticalRegDep(); + if (ReadCRD.Cycles > MaxLatency) + CRD = ReadCRD; + } + + return CRD; +} + void Instruction::dispatch(unsigned RCUToken) { assert(Stage == IS_INVALID); Stage = IS_DISPATCHED; From fd11a5f47d00dd6176938a3767fd902742617a1e Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Thu, 23 May 2019 16:39:26 +0000 Subject: [PATCH 0046/1176] [CodeComplete] Only show lambda completions if patterns are requested This is a trivial follow-up to r361461, so sending without review. llvm-svn: 361510 --- clang/lib/Sema/SemaCodeComplete.cpp | 2 ++ clang/test/CodeCompletion/lambdas.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index e6093141ab76c..e6c0b68b8d5fd 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -4134,6 +4134,8 @@ static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) { static void AddLambdaCompletion(ResultBuilder &Results, llvm::ArrayRef Parameters, const LangOptions &LangOpts) { + if (!Results.includeCodePatterns()) + return; CodeCompletionBuilder Completion(Results.getAllocator(), Results.getCodeCompletionTUInfo()); // []() {} diff --git a/clang/test/CodeCompletion/lambdas.cpp b/clang/test/CodeCompletion/lambdas.cpp index 3467cec0e3bdc..1ab804ad818e6 100644 --- a/clang/test/CodeCompletion/lambdas.cpp +++ b/clang/test/CodeCompletion/lambdas.cpp @@ -51,3 +51,12 @@ void test4() { // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:50:35 %s -o - | FileCheck -check-prefix=CHECK-6 %s // CHECK-6-NOT: COMPLETION: Pattern : [<#= } + +void test5() { + // Completions are only added when -code-completion-patterns are enabled. + function b = {}; + // RUN: %clang_cc1 -fsyntax-only -code-completion-patterns -code-completion-at=%s:57:24 %s -o - | FileCheck -check-prefix=CHECK-7 %s + // CHECK-7: COMPLETION: Pattern : [<#= + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:57:24 %s -o - | FileCheck -check-prefix=CHECK-8 %s + // CHECK-8-NOT: COMPLETION: Pattern : [<#= +} From 346758407e1dabb0d68af6bae7fba131b74e4e54 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Thu, 23 May 2019 16:48:47 +0000 Subject: [PATCH 0047/1176] [Index] Fix reported references in presence of template type aliases Summary: See the added test for an example. Reviewers: kadircet Reviewed By: kadircet Subscribers: jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62303 llvm-svn: 361511 --- .../clangd/unittests/XRefsTests.cpp | 11 +++++ clang/lib/Index/IndexTypeSourceInfo.cpp | 44 ++++++++++++------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index 77fa042c5277b..2badcffd04c87 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -497,6 +497,17 @@ TEST(LocateSymbol, Ambiguous) { ElementsAre(Sym("Foo"), Sym("Foo"))); } +TEST(LocateSymbol, TemplateTypedefs) { + auto T = Annotations(R"cpp( + template struct function {}; + template using callback = function; + + c^allback foo; + )cpp"); + auto AST = TestTU::withCode(T.code()).build(); + EXPECT_THAT(locateSymbolAt(AST, T.point()), ElementsAre(Sym("callback"))); +} + TEST(LocateSymbol, RelPathsInCompileCommand) { // The source is in "/clangd-test/src". // We build in "/clangd-test/build". diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp index 9f9740b607975..959d5f1197fee 100644 --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -133,29 +133,41 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - template - bool HandleTemplateSpecializationTypeLoc(TypeLocType TL) { - if (const auto *T = TL.getTypePtr()) { - if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { - if (!RD->isImplicit() || IndexCtx.shouldIndexImplicitInstantiation()) { - IndexCtx.handleReference(RD, TL.getTemplateNameLoc(), Parent, - ParentDC, SymbolRoleSet(), Relations); - return true; - } - } - if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl()) - IndexCtx.handleReference(D, TL.getTemplateNameLoc(), Parent, ParentDC, - SymbolRoleSet(), Relations); + void HandleTemplateSpecializationTypeLoc(TemplateName TemplName, + SourceLocation TemplNameLoc, + CXXRecordDecl *ResolvedClass, + bool IsTypeAlias) { + // In presence of type aliases, the resolved class was never written in + // the code so don't report it. + if (!IsTypeAlias && ResolvedClass && + (!ResolvedClass->isImplicit() || + IndexCtx.shouldIndexImplicitInstantiation())) { + IndexCtx.handleReference(ResolvedClass, TemplNameLoc, Parent, ParentDC, + SymbolRoleSet(), Relations); + } else if (const TemplateDecl *D = TemplName.getAsTemplateDecl()) { + IndexCtx.handleReference(D, TemplNameLoc, Parent, ParentDC, + SymbolRoleSet(), Relations); } - return true; } bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { - return HandleTemplateSpecializationTypeLoc(TL); + auto *T = TL.getTypePtr(); + if (!T) + return true; + HandleTemplateSpecializationTypeLoc( + T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(), + T->isTypeAlias()); + return true; } bool VisitDeducedTemplateSpecializationTypeLoc(DeducedTemplateSpecializationTypeLoc TL) { - return HandleTemplateSpecializationTypeLoc(TL); + auto *T = TL.getTypePtr(); + if (!T) + return true; + HandleTemplateSpecializationTypeLoc( + T->getTemplateName(), TL.getTemplateNameLoc(), T->getAsCXXRecordDecl(), + /*IsTypeAlias=*/false); + return true; } bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { From 7bbefb13ee521c2385788fa3e2f1aac4c36c313d Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 23 May 2019 17:03:43 +0000 Subject: [PATCH 0048/1176] Transforms: lower fadd and fsub atomicrmw instructions `fadd` and `fsub` have recently (r351850) been added as `atomicrmw` operations. This diff adds lowering cases for them to the LowerAtomic transform. Patch by Josh Berdine! llvm-svn: 361512 --- llvm/lib/Transforms/Scalar/LowerAtomic.cpp | 6 +++++ .../Transforms/LowerAtomic/atomic-load.ll | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/llvm/lib/Transforms/Scalar/LowerAtomic.cpp b/llvm/lib/Transforms/Scalar/LowerAtomic.cpp index f39ca23964468..e076424d90425 100644 --- a/llvm/lib/Transforms/Scalar/LowerAtomic.cpp +++ b/llvm/lib/Transforms/Scalar/LowerAtomic.cpp @@ -86,6 +86,12 @@ static bool LowerAtomicRMWInst(AtomicRMWInst *RMWI) { Res = Builder.CreateSelect(Builder.CreateICmpULT(Orig, Val), Orig, Val); break; + case AtomicRMWInst::FAdd: + Res = Builder.CreateFAdd(Orig, Val); + break; + case AtomicRMWInst::FSub: + Res = Builder.CreateFSub(Orig, Val); + break; } Builder.CreateStore(Res, Ptr); RMWI->replaceAllUsesWith(Orig); diff --git a/llvm/test/Transforms/LowerAtomic/atomic-load.ll b/llvm/test/Transforms/LowerAtomic/atomic-load.ll index e73417f3d407a..f4988c20b6a42 100644 --- a/llvm/test/Transforms/LowerAtomic/atomic-load.ll +++ b/llvm/test/Transforms/LowerAtomic/atomic-load.ll @@ -35,3 +35,25 @@ define i8 @min() { ret i8 %j ; CHECK: ret i8 [[INST]] } + +define float @fadd() { +; CHECK-LABEL: @fadd( + %i = alloca float + %j = atomicrmw fadd float* %i, float 42.0 monotonic +; CHECK: [[INST:%[a-z0-9]+]] = load +; CHECK-NEXT: fadd +; CHECK-NEXT: store + ret float %j +; CHECK: ret float [[INST]] +} + +define float @fsub() { +; CHECK-LABEL: @fsub( + %i = alloca float + %j = atomicrmw fsub float* %i, float 42.0 monotonic +; CHECK: [[INST:%[a-z0-9]+]] = load +; CHECK-NEXT: fsub +; CHECK-NEXT: store + ret float %j +; CHECK: ret float [[INST]] +} From c5ec2a2bc1980e21910ca5c649cc0c3346979fa7 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Thu, 23 May 2019 17:06:46 +0000 Subject: [PATCH 0049/1176] [CMake] Copy C++ headers before configuring runtimes build Summary: On some platforms C++ headers are packaged with the compiler not the sysroot. If you don't copy C++ headers into the build include directory during configuraiton of the outer build the C++ check during the runtime configuration may get inaccurate results. Reviewers: phosek, compnerd, smeenai, EricWF Reviewed By: compnerd Subscribers: EricWF, christof, libcxx-commits, mgorny, llvm-commits Tags: #llvm, #libc Differential Revision: https://reviews.llvm.org/D62155 llvm-svn: 361513 --- libcxx/include/CMakeLists.txt | 30 +++++++++++++++++++----------- llvm/runtimes/CMakeLists.txt | 17 +++++++++++++---- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 9880115c86a4c..6f8f0a59bf034 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -208,6 +208,14 @@ else() ) endif() +# In some build configuraitons (like boostrapping clang), we need to be able to +# install the libcxx headers before CMake configuraiton for libcxx runs. Making +# the name of this target configurable allows LLVM/runtimes/CMakeLists.txt to +# add this subdirectory to the LLVM build to put libcxx's headers in place +# before libcxx's build configuration is run. +if (NOT CXX_HEADER_TARGET) + set(CXX_HEADER_TARGET cxx-headers) +endif() if(NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR) set(output_dir ${LIBCXX_HEADER_DIR}/include/c++/v1) @@ -233,18 +241,18 @@ if(NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR) list(APPEND out_files ${dst}) endif() - add_custom_target(cxx-headers ALL DEPENDS ${out_files} ${LIBCXX_CXX_ABI_HEADER_TARGET}) + add_custom_target(${CXX_HEADER_TARGET} ALL DEPENDS ${out_files} ${LIBCXX_CXX_ABI_HEADER_TARGET}) else() - add_custom_target(cxx-headers) + add_custom_target(${CXX_HEADER_TARGET}) endif() -set_target_properties(cxx-headers PROPERTIES FOLDER "Misc") +set_target_properties(${CXX_HEADER_TARGET} PROPERTIES FOLDER "Misc") if (LIBCXX_INSTALL_HEADERS) foreach(file ${files}) get_filename_component(dir ${file} DIRECTORY) install(FILES ${file} DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dir} - COMPONENT cxx-headers + COMPONENT ${CXX_HEADER_TARGET} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) endforeach() @@ -255,19 +263,19 @@ if (LIBCXX_INSTALL_HEADERS) DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1 PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ RENAME __config - COMPONENT cxx-headers) + COMPONENT ${CXX_HEADER_TARGET}) endif() if (NOT CMAKE_CONFIGURATION_TYPES) - add_custom_target(install-cxx-headers - DEPENDS cxx-headers ${generated_config_deps} + add_custom_target(install-${CXX_HEADER_TARGET} + DEPENDS ${CXX_HEADER_TARGET} ${generated_config_deps} COMMAND "${CMAKE_COMMAND}" - -DCMAKE_INSTALL_COMPONENT=cxx-headers + -DCMAKE_INSTALL_COMPONENT=${CXX_HEADER_TARGET} -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") # Stripping is a no-op for headers - add_custom_target(install-cxx-headers-stripped DEPENDS install-cxx-headers) + add_custom_target(install-${CXX_HEADER_TARGET}-stripped DEPENDS install-${CXX_HEADER_TARGET}) - add_custom_target(install-libcxx-headers DEPENDS install-cxx-headers) - add_custom_target(install-libcxx-headers-stripped DEPENDS install-cxx-headers-stripped) + add_custom_target(install-libcxx-headers DEPENDS install-${CXX_HEADER_TARGET}) + add_custom_target(install-libcxx-headers-stripped DEPENDS install-${CXX_HEADER_TARGET}-stripped) endif() endif() diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt index 285e1fcae1d35..b9436025f5cd1 100644 --- a/llvm/runtimes/CMakeLists.txt +++ b/llvm/runtimes/CMakeLists.txt @@ -4,8 +4,12 @@ # should be built with the LLVM toolchain from the build directory. This file is # a first step to formalizing runtime build interfaces. -# In the current state this file only works with compiler-rt, other runtimes -# will work as the runtime build interface standardizes. +# Setting CMake minimum required version should be at the very top of the file +# if this is the entry point. +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + cmake_minimum_required(VERSION 3.4.3) + project(Runtimes C CXX ASM) +endif() # Find all subdirectories containing CMake projects file(GLOB entries *) @@ -205,6 +209,11 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) else() # if this is included from LLVM's CMake include(LLVMExternalProjectUtils) + if (LLVM_EXTERNAL_LIBCXX_SOURCE_DIR) + set(LIBCXX_HEADER_DIR ${LLVM_INCLUDE_DIR}/c++/v1/) + set(CXX_HEADER_TARGET runtime-libcxx-headers) + add_subdirectory(${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR}/include ${CXX_HEADER_TARGET}) + endif() if(NOT LLVM_BUILD_RUNTIMES) set(EXTRA_ARGS EXCLUDE_FROM_ALL) @@ -354,7 +363,7 @@ else() # if this is included from LLVM's CMake llvm_ExternalProject_Add(runtimes ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${ARG_DEPENDS} + DEPENDS ${ARG_DEPENDS} runtime-libcxx-headers # Builtins were built separately above CMAKE_ARGS -DCOMPILER_RT_BUILD_BUILTINS=Off -DLLVM_INCLUDE_TESTS=${LLVM_INCLUDE_TESTS} @@ -445,7 +454,7 @@ else() # if this is included from LLVM's CMake llvm_ExternalProject_Add(runtimes-${name} ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${${name}_deps} + DEPENDS ${${name}_deps} runtime-libcxx-headers # Builtins were built separately above CMAKE_ARGS -DCOMPILER_RT_BUILD_BUILTINS=Off -DLLVM_INCLUDE_TESTS=${LLVM_INCLUDE_TESTS} From aa7a2c547e2802f15c9346bff18c5d5c585ab882 Mon Sep 17 00:00:00 2001 From: Yitzhak Mandelbaum Date: Thu, 23 May 2019 17:11:33 +0000 Subject: [PATCH 0050/1176] [LibTooling] Fix dangling references in RangeSelector. Summary: RangeSelector had a number of cases of capturing a StringRef in a lambda, which lead to dangling references. This change converts all uses in the API of `StringRef` to `std::string` to avoid this problem. `std::string` in the API is a reasonable choice, because the combinators are always storing the string beyond the life of the combinator construction. Reviewers: ilya-biryukov, gribozavr Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62328 llvm-svn: 361514 --- .../clang/Tooling/Refactoring/RangeSelector.h | 18 ++++++------- .../lib/Tooling/Refactoring/RangeSelector.cpp | 26 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Tooling/Refactoring/RangeSelector.h b/clang/include/clang/Tooling/Refactoring/RangeSelector.h index d1d6bc8b6a4a9..2d878b90aa5e8 100644 --- a/clang/include/clang/Tooling/Refactoring/RangeSelector.h +++ b/clang/include/clang/Tooling/Refactoring/RangeSelector.h @@ -17,9 +17,9 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include +#include namespace clang { namespace tooling { @@ -35,19 +35,19 @@ inline RangeSelector charRange(CharSourceRange R) { RangeSelector range(RangeSelector Begin, RangeSelector End); /// Convenience version of \c range where end-points are bound nodes. -RangeSelector range(StringRef BeginID, StringRef EndID); +RangeSelector range(std::string BeginID, std::string EndID); /// Selects a node, including trailing semicolon (for non-expression /// statements). \p ID is the node's binding in the match result. -RangeSelector node(StringRef ID); +RangeSelector node(std::string ID); /// Selects a node, including trailing semicolon (always). Useful for selecting /// expression statements. \p ID is the node's binding in the match result. -RangeSelector statement(StringRef ID); +RangeSelector statement(std::string ID); /// Given a \c MemberExpr, selects the member token. \p ID is the node's /// binding in the match result. -RangeSelector member(StringRef ID); +RangeSelector member(std::string ID); /// Given a node with a "name", (like \c NamedDecl, \c DeclRefExpr or \c /// CxxCtorInitializer) selects the name's token. Only selects the final @@ -56,19 +56,19 @@ RangeSelector member(StringRef ID); /// it selects only `baz`. /// /// \param ID is the node's binding in the match result. -RangeSelector name(StringRef ID); +RangeSelector name(std::string ID); // Given a \c CallExpr (bound to \p ID), selects the arguments' source text (all // source between the call's parentheses). -RangeSelector callArgs(StringRef ID); +RangeSelector callArgs(std::string ID); // Given a \c CompoundStmt (bound to \p ID), selects the source of the // statements (all source between the braces). -RangeSelector statements(StringRef ID); +RangeSelector statements(std::string ID); // Given a \c InitListExpr (bound to \p ID), selects the range of the elements // (all source between the braces). -RangeSelector initListElements(StringRef ID); +RangeSelector initListElements(std::string ID); /// Selects the range from which `S` was expanded (possibly along with other /// source), if `S` is an expansion, and `S` itself, otherwise. Corresponds to diff --git a/clang/lib/Tooling/Refactoring/RangeSelector.cpp b/clang/lib/Tooling/Refactoring/RangeSelector.cpp index 92426db3a5ebe..d5f82d4262bec 100644 --- a/clang/lib/Tooling/Refactoring/RangeSelector.cpp +++ b/clang/lib/Tooling/Refactoring/RangeSelector.cpp @@ -104,7 +104,7 @@ static SourceLocation findOpenParen(const CallExpr &E, const SourceManager &SM, return findPreviousTokenKind(EndLoc, SM, LangOpts, tok::TokenKind::l_paren); } -RangeSelector tooling::node(StringRef ID) { +RangeSelector tooling::node(std::string ID) { return [ID](const MatchResult &Result) -> Expected { Expected Node = getNode(Result.Nodes, ID); if (!Node) @@ -115,7 +115,7 @@ RangeSelector tooling::node(StringRef ID) { }; } -RangeSelector tooling::statement(StringRef ID) { +RangeSelector tooling::statement(std::string ID) { return [ID](const MatchResult &Result) -> Expected { Expected Node = getNode(Result.Nodes, ID); if (!Node) @@ -143,11 +143,11 @@ RangeSelector tooling::range(RangeSelector Begin, RangeSelector End) { }; } -RangeSelector tooling::range(StringRef BeginID, StringRef EndID) { - return tooling::range(node(BeginID), node(EndID)); +RangeSelector tooling::range(std::string BeginID, std::string EndID) { + return tooling::range(node(std::move(BeginID)), node(std::move(EndID))); } -RangeSelector tooling::member(StringRef ID) { +RangeSelector tooling::member(std::string ID) { return [ID](const MatchResult &Result) -> Expected { Expected Node = getNode(Result.Nodes, ID); if (!Node) @@ -159,7 +159,7 @@ RangeSelector tooling::member(StringRef ID) { }; } -RangeSelector tooling::name(StringRef ID) { +RangeSelector tooling::name(std::string ID) { return [ID](const MatchResult &Result) -> Expected { Expected N = getNode(Result.Nodes, ID); if (!N) @@ -205,7 +205,7 @@ class RelativeSelector { std::string ID; public: - RelativeSelector(StringRef ID) : ID(ID) {} + RelativeSelector(std::string ID) : ID(std::move(ID)) {} Expected operator()(const MatchResult &Result) { Expected N = getNode(Result.Nodes, ID); @@ -231,8 +231,8 @@ CharSourceRange getStatementsRange(const MatchResult &, } } // namespace -RangeSelector tooling::statements(StringRef ID) { - return RelativeSelector(ID); +RangeSelector tooling::statements(std::string ID) { + return RelativeSelector(std::move(ID)); } namespace { @@ -246,8 +246,8 @@ CharSourceRange getCallArgumentsRange(const MatchResult &Result, } } // namespace -RangeSelector tooling::callArgs(StringRef ID) { - return RelativeSelector(ID); +RangeSelector tooling::callArgs(std::string ID) { + return RelativeSelector(std::move(ID)); } namespace { @@ -260,8 +260,8 @@ CharSourceRange getElementsRange(const MatchResult &, } } // namespace -RangeSelector tooling::initListElements(StringRef ID) { - return RelativeSelector(ID); +RangeSelector tooling::initListElements(std::string ID) { + return RelativeSelector(std::move(ID)); } RangeSelector tooling::expansion(RangeSelector S) { From 7b7683d7a6c4b3839629403a85dc0bd5b9a502b6 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Thu, 23 May 2019 17:19:36 +0000 Subject: [PATCH 0051/1176] [FileCheck] Remove llvm:: prefix Summary: Remove all llvm:: prefixes in FileCheck library header and implementation except for calls to make_unique and make_shared since both files already use the llvm namespace. Reviewers: jhenderson, jdenny, probinson, arichardson Subscribers: hiraditya, arichardson, probinson, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62323 llvm-svn: 361515 --- llvm/include/llvm/Support/FileCheck.h | 14 ++++---- llvm/lib/Support/FileCheck.cpp | 48 +++++++++++++-------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/Support/FileCheck.h b/llvm/include/llvm/Support/FileCheck.h index 087cc2d8bbd4c..25b3af501687d 100644 --- a/llvm/include/llvm/Support/FileCheck.h +++ b/llvm/include/llvm/Support/FileCheck.h @@ -48,7 +48,7 @@ class FileCheckNumericVariable { StringRef Name; /// Value of numeric variable, if defined, or None otherwise. - llvm::Optional Value; + Optional Value; public: /// Constructor for numeric variable \p Name with a known \p Value at parse @@ -60,7 +60,7 @@ class FileCheckNumericVariable { StringRef getName() const { return Name; } /// \returns value of this numeric variable. - llvm::Optional getValue() const { return Value; } + Optional getValue() const { return Value; } /// Sets value of this numeric variable if not defined. \returns whether the /// variable was already defined. @@ -96,7 +96,7 @@ class FileCheckNumExpr { /// Evaluates the value of this numeric expression, using EvalBinop to /// perform the binary operation it consists of. \returns None if the numeric /// variable used is undefined, or the expression value otherwise. - llvm::Optional eval() const; + Optional eval() const; /// \returns the name of the undefined variable used in this expression if /// any or an empty string otherwise. @@ -139,7 +139,7 @@ class FileCheckSubstitution { /// \returns a string containing the result of the substitution represented /// by this class instance or None if substitution failed. - virtual llvm::Optional getResult() const = 0; + virtual Optional getResult() const = 0; /// \returns the name of the variable used in this substitution if undefined, /// or an empty string otherwise. @@ -154,7 +154,7 @@ class FileCheckStringSubstitution : public FileCheckSubstitution { /// \returns the text that the string variable in this substitution matched /// when defined, or None if the variable is undefined. - llvm::Optional getResult() const override; + Optional getResult() const override; /// \returns the name of the string variable used in this substitution if /// undefined, or an empty string otherwise. @@ -174,7 +174,7 @@ class FileCheckNumericSubstitution : public FileCheckSubstitution { /// \returns a string containing the result of evaluating the numeric /// expression in this substitution, or None if evaluation failed. - llvm::Optional getResult() const override; + Optional getResult() const override; /// \returns the name of the numeric variable used in this substitution if /// undefined, or an empty string otherwise. @@ -268,7 +268,7 @@ class FileCheckPatternContext { public: /// \returns the value of string variable \p VarName or None if no such /// variable has been defined. - llvm::Optional getPatternVarValue(StringRef VarName); + Optional getPatternVarValue(StringRef VarName); /// Defines string and numeric variables from definitions given on the /// command line, passed as a vector of [#]VAR=VAL strings in diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp index a2b0f84e2c96f..1263ec5e02840 100644 --- a/llvm/lib/Support/FileCheck.cpp +++ b/llvm/lib/Support/FileCheck.cpp @@ -34,15 +34,15 @@ bool FileCheckNumericVariable::setValue(uint64_t NewValue) { bool FileCheckNumericVariable::clearValue() { if (!Value) return true; - Value = llvm::None; + Value = None; return false; } -llvm::Optional FileCheckNumExpr::eval() const { - llvm::Optional LeftOp = this->LeftOp->getValue(); +Optional FileCheckNumExpr::eval() const { + Optional LeftOp = this->LeftOp->getValue(); // Variable is undefined. if (!LeftOp) - return llvm::None; + return None; return EvalBinop(*LeftOp, RightOp); } @@ -52,18 +52,18 @@ StringRef FileCheckNumExpr::getUndefVarName() const { return StringRef(); } -llvm::Optional FileCheckNumericSubstitution::getResult() const { - llvm::Optional EvaluatedValue = NumExpr->eval(); +Optional FileCheckNumericSubstitution::getResult() const { + Optional EvaluatedValue = NumExpr->eval(); if (!EvaluatedValue) - return llvm::None; + return None; return utostr(*EvaluatedValue); } -llvm::Optional FileCheckStringSubstitution::getResult() const { +Optional FileCheckStringSubstitution::getResult() const { // Look up the value and escape it so that we can put it into the regex. - llvm::Optional VarVal = Context->getPatternVarValue(FromStr); + Optional VarVal = Context->getPatternVarValue(FromStr); if (!VarVal) - return llvm::None; + return None; return Regex::escape(*VarVal); } @@ -472,7 +472,7 @@ size_t FileCheckPattern::match(StringRef Buffer, size_t &MatchLen) const { // handled by back-references. for (const auto &Substitution : Substitutions) { // Substitute and check for failure (e.g. use of undefined variable). - llvm::Optional Value = Substitution->getResult(); + Optional Value = Substitution->getResult(); if (!Value) return StringRef::npos; @@ -533,7 +533,7 @@ void FileCheckPattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer, for (const auto &Substitution : Substitutions) { SmallString<256> Msg; raw_svector_ostream OS(Msg); - llvm::Optional MatchedValue = Substitution->getResult(); + Optional MatchedValue = Substitution->getResult(); // Substitution failed or is not known at match time, print the undefined // variable it uses. @@ -625,11 +625,11 @@ void FileCheckPattern::printFuzzyMatch( } } -llvm::Optional +Optional FileCheckPatternContext::getPatternVarValue(StringRef VarName) { auto VarIter = GlobalVariableTable.find(VarName); if (VarIter == GlobalVariableTable.end()) - return llvm::None; + return None; return VarIter->second; } @@ -703,9 +703,8 @@ size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { return StringRef::npos; } -StringRef -llvm::FileCheck::CanonicalizeFile(MemoryBuffer &MB, - SmallVectorImpl &OutputBuffer) { +StringRef FileCheck::CanonicalizeFile(MemoryBuffer &MB, + SmallVectorImpl &OutputBuffer) { OutputBuffer.reserve(MB.getBufferSize()); for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd(); @@ -923,9 +922,8 @@ FindFirstMatchingPrefix(Regex &PrefixRE, StringRef &Buffer, return {StringRef(), StringRef()}; } -bool llvm::FileCheck::ReadCheckFile( - SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, - std::vector &CheckStrings) { +bool FileCheck::ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, + std::vector &CheckStrings) { if (PatternContext.defineCmdlineVariables(Req.GlobalDefines, SM)) return true; @@ -1499,7 +1497,7 @@ static bool ValidateCheckPrefix(StringRef CheckPrefix) { return Validator.match(CheckPrefix); } -bool llvm::FileCheck::ValidateCheckPrefixes() { +bool FileCheck::ValidateCheckPrefixes() { StringSet<> PrefixSet; for (StringRef Prefix : Req.CheckPrefixes) { @@ -1517,7 +1515,7 @@ bool llvm::FileCheck::ValidateCheckPrefixes() { return true; } -Regex llvm::FileCheck::buildCheckPrefixRegex() { +Regex FileCheck::buildCheckPrefixRegex() { // I don't think there's a way to specify an initial value for cl::list, // so if nothing was specified, add the default if (Req.CheckPrefixes.empty()) @@ -1682,9 +1680,9 @@ void FileCheckPatternContext::clearLocalVars() { GlobalNumericVariableTable.erase(Var); } -bool llvm::FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer, - ArrayRef CheckStrings, - std::vector *Diags) { +bool FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer, + ArrayRef CheckStrings, + std::vector *Diags) { bool ChecksFailed = false; unsigned i = 0, j = 0, e = CheckStrings.size(); From eafe8ef6f2b44baf5a84658caca90c2f9c1849ca Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 23 May 2019 17:26:47 +0000 Subject: [PATCH 0052/1176] [WebAssembly] Add multivalue and tail-call target features Summary: These features will both be implemented soon, so I thought I would save time by adding the boilerplate for both of them at the same time. Reviewers: aheejin Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D62047 llvm-svn: 361516 --- clang/include/clang/Driver/Options.td | 4 +++ clang/lib/Basic/Targets/WebAssembly.cpp | 26 +++++++++++++++++ clang/lib/Basic/Targets/WebAssembly.h | 2 ++ .../test/Preprocessor/wasm-target-features.c | 22 +++++++++++++++ llvm/lib/Target/WebAssembly/WebAssembly.td | 11 ++++++++ .../WebAssembly/WebAssemblyInstrInfo.td | 14 +++++----- .../Target/WebAssembly/WebAssemblySubtarget.h | 4 +++ llvm/test/CodeGen/WebAssembly/multivalue.ll | 28 +++++++++++++++++++ llvm/test/CodeGen/WebAssembly/tailcall.ll | 21 ++++++++++++++ 9 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 llvm/test/CodeGen/WebAssembly/multivalue.ll create mode 100644 llvm/test/CodeGen/WebAssembly/tailcall.ll diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 26a06a6556a95..68f415fb31d63 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2185,6 +2185,10 @@ def mbulk_memory : Flag<["-"], "mbulk-memory">, Group; def mno_bulk_memory : Flag<["-"], "mno-bulk-memory">, Group; def mmutable_globals : Flag<["-"], "mmutable-globals">, Group; def mno_mutable_globals : Flag<["-"], "mno-mutable-globals">, Group; +def mmultivalue : Flag<["-"], "mmultivalue">, Group; +def mno_multivalue : Flag<["-"], "mno-multivalue">, Group; +def mtail_call : Flag<["-"], "mtail-call">, Group; +def mno_tail_call : Flag<["-"], "mno-tail-call">, Group; def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">, Flags<[HelpHidden]>, diff --git a/clang/lib/Basic/Targets/WebAssembly.cpp b/clang/lib/Basic/Targets/WebAssembly.cpp index 2fceed2ad1f00..b16442b99b625 100644 --- a/clang/lib/Basic/Targets/WebAssembly.cpp +++ b/clang/lib/Basic/Targets/WebAssembly.cpp @@ -43,6 +43,8 @@ bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const { .Case("bulk-memory", HasBulkMemory) .Case("atomics", HasAtomics) .Case("mutable-globals", HasMutableGlobals) + .Case("multivalue", HasMultivalue) + .Case("tail-call", HasTailCall) .Default(false); } @@ -74,6 +76,10 @@ void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__wasm_atomics__"); if (HasMutableGlobals) Builder.defineMacro("__wasm_mutable_globals__"); + if (HasMultivalue) + Builder.defineMacro("__wasm_multivalue__"); + if (HasTailCall) + Builder.defineMacro("__wasm_tail_call__"); } void WebAssemblyTargetInfo::setSIMDLevel(llvm::StringMap &Features, @@ -116,6 +122,10 @@ bool WebAssemblyTargetInfo::initFeatureMap( Features["atomics"] = true; if (HasMutableGlobals) Features["mutable-globals"] = true; + if (HasMultivalue) + Features["multivalue"] = true; + if (HasTailCall) + Features["tail-call"] = true; return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); } @@ -187,6 +197,22 @@ bool WebAssemblyTargetInfo::handleTargetFeatures( HasMutableGlobals = false; continue; } + if (Feature == "+multivalue") { + HasMultivalue = true; + continue; + } + if (Feature == "-multivalue") { + HasMultivalue = false; + continue; + } + if (Feature == "+tail-call") { + HasTailCall = true; + continue; + } + if (Feature == "-tail-call") { + HasTailCall = false; + continue; + } Diags.Report(diag::err_opt_not_valid_with_opt) << Feature << "-target-feature"; diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index a0516da286c14..9665156b143f1 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -36,6 +36,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo { bool HasBulkMemory = false; bool HasAtomics = false; bool HasMutableGlobals = false; + bool HasMultivalue = false; + bool HasTailCall = false; public: explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &) diff --git a/clang/test/Preprocessor/wasm-target-features.c b/clang/test/Preprocessor/wasm-target-features.c index 2bf94398a1dc3..41681123f2068 100644 --- a/clang/test/Preprocessor/wasm-target-features.c +++ b/clang/test/Preprocessor/wasm-target-features.c @@ -79,6 +79,24 @@ // // MUTABLE-GLOBALS:#define __wasm_mutable_globals__ 1{{$}} +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target wasm32-unknown-unknown -mmultivalue \ +// RUN: | FileCheck %s -check-prefix=MULTIVALUE +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target wasm64-unknown-unknown -mmultivalue \ +// RUN: | FileCheck %s -check-prefix=MULTIVALUE +// +// MULTIVALUE:#define __wasm_multivalue__ 1{{$}} + +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target wasm32-unknown-unknown -mtail-call \ +// RUN: | FileCheck %s -check-prefix=TAIL-CALL +// RUN: %clang -E -dM %s -o - 2>&1 \ +// RUN: -target wasm64-unknown-unknown -mtail-call \ +// RUN: | FileCheck %s -check-prefix=TAIL-CALL +// +// TAIL-CALL:#define __wasm_tail_call__ 1{{$}} + // RUN: %clang -E -dM %s -o - 2>&1 \ // RUN: -target wasm32-unknown-unknown -mcpu=mvp \ // RUN: | FileCheck %s -check-prefix=MVP @@ -94,6 +112,8 @@ // MVP-NOT:#define __wasm_bulk_memory__ // MVP-NOT:#define __wasm_atomics__ // MVP-NOT:#define __wasm_mutable_globals__ +// MVP-NOT:#define __wasm_multivalue__ +// MVP-NOT:#define __wasm_tail_call__ // RUN: %clang -E -dM %s -o - 2>&1 \ // RUN: -target wasm32-unknown-unknown -mcpu=bleeding-edge \ @@ -108,6 +128,8 @@ // BLEEDING-EDGE-DAG:#define __wasm_atomics__ 1{{$}} // BLEEDING-EDGE-DAG:#define __wasm_mutable_globals__ 1{{$}} // BLEEDING-EDGE-NOT:#define __wasm_unimplemented_simd128__ 1{{$}} +// BLEEDING-EDGE-NOT:#define __wasm_multivalue__ 1{{$}} +// BLEEDING-EDGE-NOT:#define __wasm_tail_call__ 1{{$}} // RUN: %clang -E -dM %s -o - 2>&1 \ // RUN: -target wasm32-unknown-unknown -mcpu=bleeding-edge -mno-simd128 \ diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.td b/llvm/lib/Target/WebAssembly/WebAssembly.td index 813c7e652e4a3..b0b8a9b996a37 100644 --- a/llvm/lib/Target/WebAssembly/WebAssembly.td +++ b/llvm/lib/Target/WebAssembly/WebAssembly.td @@ -33,6 +33,7 @@ def FeatureUnimplementedSIMD128 : def FeatureAtomics : SubtargetFeature<"atomics", "HasAtomics", "true", "Enable Atomics">; + def FeatureNontrappingFPToInt : SubtargetFeature<"nontrapping-fptoint", "HasNontrappingFPToInt", "true", @@ -43,6 +44,11 @@ def FeatureSignExt : "HasSignExt", "true", "Enable sign extension operators">; +def FeatureTailCall : + SubtargetFeature<"tail-call", + "HasTailCall", "true", + "Enable tail call instructions">; + def FeatureExceptionHandling : SubtargetFeature<"exception-handling", "HasExceptionHandling", "true", "Enable Wasm exception handling">; @@ -51,6 +57,11 @@ def FeatureBulkMemory : SubtargetFeature<"bulk-memory", "HasBulkMemory", "true", "Enable bulk memory operations">; +def FeatureMultivalue : + SubtargetFeature<"multivalue", + "HasMultivalue", "true", + "Enable multivalue blocks, instructions, and functions">; + def FeatureMutableGlobals : SubtargetFeature<"mutable-globals", "HasMutableGlobals", "true", "Enable mutable globals">; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td index 40a8f6089c2af..a15bb2cce0bba 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -34,6 +34,10 @@ def HasAtomics : Predicate<"Subtarget->hasAtomics()">, AssemblerPredicate<"FeatureAtomics", "atomics">; +def HasMultivalue : + Predicate<"Subtarget->hasMultivalue()">, + AssemblerPredicate<"FeatureMultivalue", "multivalue">; + def HasNontrappingFPToInt : Predicate<"Subtarget->hasNontrappingFPToInt()">, AssemblerPredicate<"FeatureNontrappingFPToInt", "nontrapping-fptoint">; @@ -46,18 +50,14 @@ def HasSignExt : Predicate<"Subtarget->hasSignExt()">, AssemblerPredicate<"FeatureSignExt", "sign-ext">; -def NotHasSignExt : - Predicate<"!Subtarget->hasSignExt()">, - AssemblerPredicate<"!FeatureSignExt", "sign-ext">; +def HasTailCall : + Predicate<"Subtarget->hasTailCall()">, + AssemblerPredicate<"FeatureTailCall", "tail-call">; def HasExceptionHandling : Predicate<"Subtarget->hasExceptionHandling()">, AssemblerPredicate<"FeatureExceptionHandling", "exception-handling">; -def NotHasExceptionHandling : - Predicate<"!Subtarget->hasExceptionHandling()">, - AssemblerPredicate<"!FeatureExceptionHandling", "exception-handling">; - def HasBulkMemory : Predicate<"Subtarget->hasBulkMemory()">, AssemblerPredicate<"FeatureBulkMemory", "bulk-memory">; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h index 22e11726f33e7..c5d9cf1eb953e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h @@ -44,7 +44,9 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool HasSignExt = false; bool HasExceptionHandling = false; bool HasBulkMemory = false; + bool HasMultivalue = false; bool HasMutableGlobals = false; + bool HasTailCall = false; /// String name of used CPU. std::string CPUString; @@ -98,7 +100,9 @@ class WebAssemblySubtarget final : public WebAssemblyGenSubtargetInfo { bool hasSignExt() const { return HasSignExt; } bool hasExceptionHandling() const { return HasExceptionHandling; } bool hasBulkMemory() const { return HasBulkMemory; } + bool hasMultivalue() const { return HasMultivalue; } bool hasMutableGlobals() const { return HasMutableGlobals; } + bool hasTailCall() const { return HasTailCall; } /// Parses features string setting specified subtarget options. Definition of /// function is auto generated by tblgen. diff --git a/llvm/test/CodeGen/WebAssembly/multivalue.ll b/llvm/test/CodeGen/WebAssembly/multivalue.ll new file mode 100644 index 0000000000000..cbf8d4e0a0d0c --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/multivalue.ll @@ -0,0 +1,28 @@ +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+multivalue | FileCheck %s + +; Test that the multivalue attribute is accepted +; TODO(tlively): implement multivalue + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +%pair = type { i32, i32 } +%packed_pair = type <{ i32, i32 }> + +; CHECK-LABEL: sret: +; CHECK-NEXT: sret (i32, i32, i32) -> () +define %pair @sret(%pair %p) { + ret %pair %p +} + +; CHECK-LABEL: packed_sret: +; CHECK-NEXT: packed_sret (i32, i32, i32) -> () +define %packed_pair @packed_sret(%packed_pair %p) { + ret %packed_pair %p +} + +; CHECK-LABEL: .section .custom_section.target_features +; CHECK-NEXT: .int8 1 +; CHECK-NEXT: .int8 43 +; CHECK-NEXT: .int8 10 +; CHECK-NEXT: .ascii "multivalue" diff --git a/llvm/test/CodeGen/WebAssembly/tailcall.ll b/llvm/test/CodeGen/WebAssembly/tailcall.ll new file mode 100644 index 0000000000000..809d46ae4a4a3 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/tailcall.ll @@ -0,0 +1,21 @@ +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+tail-call | FileCheck %s + +; Test that the tail-call attribute is accepted +; TODO(tlively): implement tail call + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +; CHECK-LABEL: recursive_tail: +; CHECK: i32.call $push[[L0:[0-9]+]]=, recursive_tail{{$}} +; CHECK-NEXT: return $pop[[L0]]{{$}} +define i32 @recursive_tail() { + %v = tail call i32 @recursive_tail() + ret i32 %v +} + +; CHECK-LABEL: .section .custom_section.target_features +; CHECK-NEXT: .int8 1 +; CHECK-NEXT: .int8 43 +; CHECK-NEXT: .int8 9 +; CHECK-NEXT: .ascii "tail-call" From 2049e4dd8f61100f88f14db33bd95d197bcbfbbc Mon Sep 17 00:00:00 2001 From: Kit Barton Date: Thu, 23 May 2019 17:56:35 +0000 Subject: [PATCH 0053/1176] [LOOPINFO] Extend Loop object to add utilities to get the loop bounds, step, induction variable, and guard branch. Summary: This PR extends the loop object with more utilities to get loop bounds, step, induction variable, and guard branch. There already exists passes which try to obtain the loop induction variable in their own pass, e.g. loop interchange. It would be useful to have a common area to get these information. Moreover, loop fusion (https://reviews.llvm.org/D55851) is planning to use getGuard() to extend the kind of loops it is able to fuse, e.g. rotated loop with non-constant upper bound, which would have a loop guard. /// Example: /// for (int i = lb; i < ub; i+=step) /// /// --- pseudo LLVMIR --- /// beforeloop: /// guardcmp = (lb < ub) /// if (guardcmp) goto preheader; else goto afterloop /// preheader: /// loop: /// i1 = phi[{lb, preheader}, {i2, latch}] /// /// i2 = i1 + step /// latch: /// cmp = (i2 < ub) /// if (cmp) goto loop /// exit: /// afterloop: /// /// getBounds /// getInitialIVValue --> lb /// getStepInst --> i2 = i1 + step /// getStepValue --> step /// getFinalIVValue --> ub /// getCanonicalPredicate --> '<' /// getDirection --> Increasing /// getGuard --> if (guardcmp) goto loop; else goto afterloop /// getInductionVariable --> i1 /// getAuxiliaryInductionVariable --> {i1} /// isCanonical --> false Committed on behalf of @Whitney (Whitney Tsang). Reviewers: kbarton, hfinkel, dmgreen, Meinersbur, jdoerfert, syzaara, fhahn Reviewed By: kbarton Subscribers: tvvikram, bmahjour, etiotto, fhahn, jsji, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60565 llvm-svn: 361517 --- llvm/include/llvm/Analysis/LoopInfo.h | 162 ++++ llvm/lib/Analysis/LoopInfo.cpp | 246 +++++ .../lib/Transforms/Scalar/LoopInterchange.cpp | 29 +- llvm/unittests/Analysis/LoopInfoTest.cpp | 900 ++++++++++++++++++ 4 files changed, 1309 insertions(+), 28 deletions(-) diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index 6b964cdf9eae5..dd789de493875 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -54,9 +54,12 @@ namespace llvm { class DominatorTree; class LoopInfo; class Loop; +class InductionDescriptor; class MDNode; class MemorySSAUpdater; class PHINode; +class PostDominatorTree; +class ScalarEvolution; class raw_ostream; template class DominatorTreeBase; template class LoopInfoBase; @@ -529,6 +532,165 @@ class Loop : public LoopBase { bool getIncomingAndBackEdge(BasicBlock *&Incoming, BasicBlock *&Backedge) const; + /// Below are some utilities to get loop bounds and induction variable, and + /// check if a given phinode is an auxiliary induction variable, as well as + /// checking if the loop is canonical. + /// + /// Here is an example: + /// \code + /// for (int i = lb; i < ub; i+=step) + /// + /// --- pseudo LLVMIR --- + /// beforeloop: + /// guardcmp = (lb < ub) + /// if (guardcmp) goto preheader; else goto afterloop + /// preheader: + /// loop: + /// i_1 = phi[{lb, preheader}, {i_2, latch}] + /// + /// i_2 = i_1 + step + /// latch: + /// cmp = (i_2 < ub) + /// if (cmp) goto loop + /// exit: + /// afterloop: + /// \endcode + /// + /// - getBounds + /// - getInitialIVValue --> lb + /// - getStepInst --> i_2 = i_1 + step + /// - getStepValue --> step + /// - getFinalIVValue --> ub + /// - getCanonicalPredicate --> '<' + /// - getDirection --> Increasing + /// + /// - getInductionVariable --> i_1 + /// - isAuxiliaryInductionVariable(x) --> true if x == i_1 + /// - isCanonical --> false + struct LoopBounds { + /// Return the LoopBounds object if + /// - the given \p IndVar is an induction variable + /// - the initial value of the induction variable can be found + /// - the step instruction of the induction variable can be found + /// - the final value of the induction variable can be found + /// + /// Else None. + static Optional getBounds(const Loop &L, PHINode &IndVar, + ScalarEvolution &SE); + + /// Get the initial value of the loop induction variable. + Value &getInitialIVValue() const { return InitialIVValue; } + + /// Get the instruction that updates the loop induction variable. + Instruction &getStepInst() const { return StepInst; } + + /// Get the step that the loop induction variable gets updated by in each + /// loop iteration. Return nullptr if not found. + Value *getStepValue() const { return StepValue; } + + /// Get the final value of the loop induction variable. + Value &getFinalIVValue() const { return FinalIVValue; } + + /// Return the canonical predicate for the latch compare instruction, if + /// able to be calcuated. Else BAD_ICMP_PREDICATE. + /// + /// A predicate is considered as canonical if requirements below are all + /// satisfied: + /// 1. The first successor of the latch branch is the loop header + /// If not, inverse the predicate. + /// 2. One of the operands of the latch comparison is StepInst + /// If not, and + /// - if the current calcuated predicate is not ne or eq, flip the + /// predicate. + /// - else if the loop is increasing, return slt + /// (notice that it is safe to change from ne or eq to sign compare) + /// - else if the loop is decreasing, return sgt + /// (notice that it is safe to change from ne or eq to sign compare) + /// + /// Here is an example when both (1) and (2) are not satisfied: + /// \code + /// loop.header: + /// %iv = phi [%initialiv, %loop.preheader], [%inc, %loop.header] + /// %inc = add %iv, %step + /// %cmp = slt %iv, %finaliv + /// br %cmp, %loop.exit, %loop.header + /// loop.exit: + /// \endcode + /// - The second successor of the latch branch is the loop header instead + /// of the first successor (slt -> sge) + /// - The first operand of the latch comparison (%cmp) is the IndVar (%iv) + /// instead of the StepInst (%inc) (sge -> sgt) + /// + /// The predicate would be sgt if both (1) and (2) are satisfied. + /// getCanonicalPredicate() returns sgt for this example. + /// Note: The IR is not changed. + ICmpInst::Predicate getCanonicalPredicate() const; + + /// An enum for the direction of the loop + /// - for (int i = 0; i < ub; ++i) --> Increasing + /// - for (int i = ub; i > 0; --i) --> Descresing + /// - for (int i = x; i != y; i+=z) --> Unknown + enum class Direction { Increasing, Decreasing, Unknown }; + + /// Get the direction of the loop. + Direction getDirection() const; + + private: + LoopBounds(const Loop &Loop, Value &I, Instruction &SI, Value *SV, Value &F, + ScalarEvolution &SE) + : L(Loop), InitialIVValue(I), StepInst(SI), StepValue(SV), + FinalIVValue(F), SE(SE) {} + + const Loop &L; + + // The initial value of the loop induction variable + Value &InitialIVValue; + + // The instruction that updates the loop induction variable + Instruction &StepInst; + + // The value that the loop induction variable gets updated by in each loop + // iteration + Value *StepValue; + + // The final value of the loop induction variable + Value &FinalIVValue; + + ScalarEvolution &SE; + }; + + /// Return the struct LoopBounds collected if all struct members are found, + /// else None. + Optional getBounds(ScalarEvolution &SE) const; + + /// Return the loop induction variable if found, else return nullptr. + /// An instruction is considered as the loop induction variable if + /// - it is an induction variable of the loop; and + /// - it is used to determine the condition of the branch in the loop latch + /// + /// Note: the induction variable doesn't need to be canonical, i.e. starts at + /// zero and increments by one each time through the loop (but it can be). + PHINode *getInductionVariable(ScalarEvolution &SE) const; + + /// Get the loop induction descriptor for the loop induction variable. Return + /// true if the loop induction variable is found. + bool getInductionDescriptor(ScalarEvolution &SE, + InductionDescriptor &IndDesc) const; + + /// Return true if the given PHINode \p AuxIndVar is + /// - in the loop header + /// - not used outside of the loop + /// - incremented by a loop invariant step for each loop iteration + /// - step instruction opcode should be add or sub + /// Note: auxiliary induction variable is not required to be used in the + /// conditional branch in the loop latch. (but it can be) + bool isAuxiliaryInductionVariable(PHINode &AuxIndVar, + ScalarEvolution &SE) const; + + /// Return true if the loop induction variable starts at zero and increments + /// by one each time through the loop. + bool isCanonical(ScalarEvolution &SE) const; + /// Return true if the Loop is in LCSSA form. bool isLCSSAForm(DominatorTree &DT) const; diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index aa933d98f249b..50e08e994876a 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -17,10 +17,13 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/IVDescriptors.h" #include "llvm/Analysis/LoopInfoImpl.h" #include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/MemorySSAUpdater.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/CFG.h" @@ -164,6 +167,249 @@ PHINode *Loop::getCanonicalInductionVariable() const { return nullptr; } +/// Return true if V1 and V2 have the same value ignoring bit width. +static bool isEqualIgnoreBitwidth(Value &V1, Value &V2, ScalarEvolution &SE) { + const SCEV *S1 = SE.getSCEV(&V1); + const SCEV *S2 = SE.getSCEV(&V2); + Type *WiderType = SE.getWiderType(S1->getType(), S2->getType()); + S1 = SE.getNoopOrAnyExtend(S1, WiderType); + S2 = SE.getNoopOrAnyExtend(S2, WiderType); + return SE.getMinusSCEV(S1, S2)->isZero(); +} + +/// Get the latch condition instruction. +static ICmpInst *getLatchCmpInst(const Loop &L) { + if (BasicBlock *Latch = L.getLoopLatch()) + if (BranchInst *BI = dyn_cast_or_null(Latch->getTerminator())) + if (BI->isConditional()) + return dyn_cast(BI->getCondition()); + + return nullptr; +} + +/// Return the final value of the loop induction variable if found. +static Value *findFinalIVValue(const Loop &L, const PHINode &IndVar, + const Instruction &StepInst) { + ICmpInst *LatchCmpInst = getLatchCmpInst(L); + if (!LatchCmpInst) + return nullptr; + + Value *Op0 = LatchCmpInst->getOperand(0); + Value *Op1 = LatchCmpInst->getOperand(1); + if (Op0 == &IndVar || Op0 == &StepInst) + return Op1; + + if (Op1 == &IndVar || Op1 == &StepInst) + return Op0; + + return nullptr; +} + +Optional Loop::LoopBounds::getBounds(const Loop &L, + PHINode &IndVar, + ScalarEvolution &SE) { + InductionDescriptor IndDesc; + if (!InductionDescriptor::isInductionPHI(&IndVar, &L, &SE, IndDesc)) + return None; + + Value *InitialIVValue = IndDesc.getStartValue(); + Instruction *StepInst = IndDesc.getInductionBinOp(); + if (!InitialIVValue || !StepInst) + return None; + + const SCEV *Step = IndDesc.getStep(); + Value *StepInstOp1 = StepInst->getOperand(1); + Value *StepInstOp0 = StepInst->getOperand(0); + Value *StepValue = nullptr; + if (SE.getSCEV(StepInstOp1) == Step) + StepValue = StepInstOp1; + else if (SE.getSCEV(StepInstOp0) == Step) + StepValue = StepInstOp0; + + Value *FinalIVValue = findFinalIVValue(L, IndVar, *StepInst); + if (!FinalIVValue) + return None; + + return LoopBounds(L, *InitialIVValue, *StepInst, StepValue, *FinalIVValue, + SE); +} + +using Direction = Loop::LoopBounds::Direction; + +ICmpInst::Predicate Loop::LoopBounds::getCanonicalPredicate() const { + BasicBlock *Latch = L.getLoopLatch(); + assert(Latch && "Expecting valid latch"); + + BranchInst *BI = dyn_cast_or_null(Latch->getTerminator()); + assert(BI && BI->isConditional() && "Expecting conditional latch branch"); + + ICmpInst *LatchCmpInst = dyn_cast(BI->getCondition()); + assert(LatchCmpInst && + "Expecting the latch compare instruction to be a CmpInst"); + + // Need to inverse the predicate when first successor is not the loop + // header + ICmpInst::Predicate Pred = (BI->getSuccessor(0) == L.getHeader()) + ? LatchCmpInst->getPredicate() + : LatchCmpInst->getInversePredicate(); + + if (LatchCmpInst->getOperand(0) == &getFinalIVValue()) + Pred = ICmpInst::getSwappedPredicate(Pred); + + // Need to flip strictness of the predicate when the latch compare instruction + // is not using StepInst + if (LatchCmpInst->getOperand(0) == &getStepInst() || + LatchCmpInst->getOperand(1) == &getStepInst()) + return Pred; + + // Cannot flip strictness of NE and EQ + if (Pred != ICmpInst::ICMP_NE && Pred != ICmpInst::ICMP_EQ) + return ICmpInst::getFlippedStrictnessPredicate(Pred); + + Direction D = getDirection(); + if (D == Direction::Increasing) + return ICmpInst::ICMP_SLT; + + if (D == Direction::Decreasing) + return ICmpInst::ICMP_SGT; + + // If cannot determine the direction, then unable to find the canonical + // predicate + return ICmpInst::BAD_ICMP_PREDICATE; +} + +Direction Loop::LoopBounds::getDirection() const { + if (const SCEVAddRecExpr *StepAddRecExpr = + dyn_cast(SE.getSCEV(&getStepInst()))) + if (const SCEV *StepRecur = StepAddRecExpr->getStepRecurrence(SE)) { + if (SE.isKnownPositive(StepRecur)) + return Direction::Increasing; + if (SE.isKnownNegative(StepRecur)) + return Direction::Decreasing; + } + + return Direction::Unknown; +} + +Optional Loop::getBounds(ScalarEvolution &SE) const { + if (PHINode *IndVar = getInductionVariable(SE)) + return LoopBounds::getBounds(*this, *IndVar, SE); + + return None; +} + +PHINode *Loop::getInductionVariable(ScalarEvolution &SE) const { + if (!isLoopSimplifyForm()) + return nullptr; + + BasicBlock *Header = getHeader(); + assert(Header && "Expected a valid loop header"); + BasicBlock *Latch = getLoopLatch(); + assert(Latch && "Expected a valid loop latch"); + ICmpInst *CmpInst = getLatchCmpInst(*this); + if (!CmpInst) + return nullptr; + + // case 1: + // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}] + // StepInst = IndVar + step + // cmp = StepInst < FinalValue + Instruction *LatchCmpOp0 = dyn_cast(CmpInst->getOperand(0)); + Instruction *LatchCmpOp1 = dyn_cast(CmpInst->getOperand(1)); + // Loop over all of the PHI nodes in loop header, store the PHI node that has + // incoming value from latch equals to the StepInst + BinaryOperator *StepInst = nullptr; + PHINode *IndVar = nullptr; + for (PHINode &PN : Header->phis()) { + Value *IncomingValue = PN.getIncomingValueForBlock(Latch); + assert(IncomingValue && "Expecting valid incoming value from latch"); + if (IncomingValue == LatchCmpOp0 || IncomingValue == LatchCmpOp1) { + IndVar = &PN; + StepInst = dyn_cast(IncomingValue); + if (StepInst) + if (isEqualIgnoreBitwidth(*StepInst->getOperand(0), *IndVar, SE) || + isEqualIgnoreBitwidth(*StepInst->getOperand(1), *IndVar, SE)) + return IndVar; + } + } + + // case 2: + // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}] + // StepInst = IndVar + step + // cmp = IndVar < FinalValue + for (Value *Op : CmpInst->operands()) { + PHINode *IndVar = dyn_cast(Op); + if (!IndVar) + continue; + + if (IndVar->getParent() != Header) + continue; + + Value *IncomingValue = IndVar->getIncomingValueForBlock(Latch); + assert(IncomingValue && "Expecting valid incoming value from latch"); + StepInst = dyn_cast(IncomingValue); + if (StepInst) + if (StepInst->getOperand(0) == IndVar || + StepInst->getOperand(1) == IndVar) + return IndVar; + } + + return nullptr; +} + +bool Loop::getInductionDescriptor(ScalarEvolution &SE, + InductionDescriptor &IndDesc) const { + if (PHINode *IndVar = getInductionVariable(SE)) + return InductionDescriptor::isInductionPHI(IndVar, this, &SE, IndDesc); + + return false; +} + +bool Loop::isAuxiliaryInductionVariable(PHINode &AuxIndVar, + ScalarEvolution &SE) const { + // Located in the loop header + BasicBlock *Header = getHeader(); + if (AuxIndVar.getParent() != Header) + return false; + + // No uses outside of the loop + for (User *U : AuxIndVar.users()) + if (const Instruction *I = dyn_cast(U)) + if (!contains(I)) + return false; + + InductionDescriptor IndDesc; + if (!InductionDescriptor::isInductionPHI(&AuxIndVar, this, &SE, IndDesc)) + return false; + + // The step instruction opcode should be add or sub. + if (IndDesc.getInductionOpcode() != Instruction::Add && + IndDesc.getInductionOpcode() != Instruction::Sub) + return false; + + // Incremented by a loop invariant step for each loop iteration + return SE.isLoopInvariant(IndDesc.getStep(), this); +} + +bool Loop::isCanonical(ScalarEvolution &SE) const { + InductionDescriptor IndDesc; + if (!getInductionDescriptor(SE, IndDesc)) + return false; + + ConstantInt *Init = dyn_cast_or_null(IndDesc.getStartValue()); + if (!Init || !Init->isZero()) + return false; + + if (IndDesc.getInductionOpcode() != Instruction::Add) + return false; + + ConstantInt *Step = IndDesc.getConstIntStepValue(); + if (!Step || !Step->isOne()) + return false; + + return true; +} + // Check that 'BB' doesn't have any uses outside of the 'L' static bool isBlockInLCSSAForm(const Loop &L, const BasicBlock &BB, DominatorTree &DT) { diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index bec5af584f438..ad7113cb0e9a0 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -292,33 +292,6 @@ static LoopVector populateWorklist(Loop &L) { return LoopList; } -static PHINode *getInductionVariable(Loop *L, ScalarEvolution *SE) { - PHINode *InnerIndexVar = L->getCanonicalInductionVariable(); - if (InnerIndexVar) - return InnerIndexVar; - if (L->getLoopLatch() == nullptr || L->getLoopPredecessor() == nullptr) - return nullptr; - for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) { - PHINode *PhiVar = cast(I); - Type *PhiTy = PhiVar->getType(); - if (!PhiTy->isIntegerTy() && !PhiTy->isFloatingPointTy() && - !PhiTy->isPointerTy()) - return nullptr; - const SCEVAddRecExpr *AddRec = - dyn_cast(SE->getSCEV(PhiVar)); - if (!AddRec || !AddRec->isAffine()) - continue; - const SCEV *Step = AddRec->getStepRecurrence(*SE); - if (!isa(Step)) - continue; - // Found the induction variable. - // FIXME: Handle loops with more than one induction variable. Note that, - // currently, legality makes sure we have only one induction variable. - return PhiVar; - } - return nullptr; -} - namespace { /// LoopInterchangeLegality checks if it is legal to interchange the loop. @@ -1227,7 +1200,7 @@ bool LoopInterchangeTransform::transform() { if (InnerLoop->getSubLoops().empty()) { BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader(); LLVM_DEBUG(dbgs() << "Calling Split Inner Loop\n"); - PHINode *InductionPHI = getInductionVariable(InnerLoop, SE); + PHINode *InductionPHI = InnerLoop->getInductionVariable(*SE); if (!InductionPHI) { LLVM_DEBUG(dbgs() << "Failed to find the point to split loop latch \n"); return false; diff --git a/llvm/unittests/Analysis/LoopInfoTest.cpp b/llvm/unittests/Analysis/LoopInfoTest.cpp index 483532a187527..005e1dc405b75 100644 --- a/llvm/unittests/Analysis/LoopInfoTest.cpp +++ b/llvm/unittests/Analysis/LoopInfoTest.cpp @@ -7,6 +7,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Dominators.h" #include "llvm/Support/SourceMgr.h" @@ -26,6 +30,26 @@ runWithLoopInfo(Module &M, StringRef FuncName, Test(*F, LI); } +/// Build the loop info and scalar evolution for the function and run the Test. +static void runWithLoopInfoPlus( + Module &M, StringRef FuncName, + function_ref + Test) { + auto *F = M.getFunction(FuncName); + ASSERT_NE(F, nullptr) << "Could not find " << FuncName; + + TargetLibraryInfoImpl TLII; + TargetLibraryInfo TLI(TLII); + AssumptionCache AC(*F); + DominatorTree DT(*F); + LoopInfo LI(DT); + ScalarEvolution SE(*F, TLI, AC, DT, LI); + + PostDominatorTree PDT(*F); + Test(*F, LI, SE, PDT); +} + static std::unique_ptr makeLLVMModule(LLVMContext &Context, const char *ModuleStr) { SMDiagnostic Err; @@ -210,3 +234,879 @@ TEST(LoopInfoTest, PreorderTraversals) { EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]); EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]); } + +TEST(LoopInfoTest, CanonicalLoop) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopWithInverseGuardSuccs) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp sge i32 0, %ub\n" + " br i1 %guardcmp, label %for.end, label %for.preheader\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopWithSwappedGuardCmp) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp sgt i32 %ub, 0\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp sge i32 %inc, %ub\n" + " br i1 %cmp, label %for.exit, label %for.body\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopWithInverseLatchSuccs) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp sge i32 %inc, %ub\n" + " br i1 %cmp, label %for.exit, label %for.body\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopWithLatchCmpNE) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp ne i32 %i, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopWithGuardCmpSLE) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %ubPlusOne = add i32 %ub, 1\n" + " %guardcmp = icmp sle i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp ne i32 %i, %ubPlusOne\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ubPlusOne"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopNonConstantStep) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = zext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, %step\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopUnsignedBounds) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp ult i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = zext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add i32 %i, 1\n" + " %cmp = icmp ult i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_ULT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, DecreasingLoop) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ %ub, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = sub nsw i32 %i, 1\n" + " %cmp = icmp sgt i32 %inc, 0\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + EXPECT_EQ(Bounds->getInitialIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_EQ(StepValue, nullptr); + ConstantInt *FinalIVValue = + dyn_cast(&Bounds->getFinalIVValue()); + EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero()); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SGT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Decreasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, CannotFindDirection) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, %step\n" + " %cmp = icmp ne i32 %i, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus(*M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader + // - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), + ICmpInst::BAD_ICMP_PREDICATE); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Unknown); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, ZextIndVar) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %indvars.iv = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next, %for.body ]\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n" + " %inc = add nsw i32 %i, 1\n" + " %wide.trip.count = zext i32 %ub to i64\n" + " %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n" + " br i1 %exitcond, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "indvars.iv.next"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "wide.trip.count"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_NE); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv"); + }); +} + +TEST(LoopInfoTest, UnguardedLoop) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First basic block is entry - skip it. + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, UnguardedLoopWithControlFlow) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" + "entry:\n" + " br i1 %cond, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, LoopNest) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.outer.preheader, label %for.end\n" + "for.outer.preheader:\n" + " br label %for.outer\n" + "for.outer:\n" + " %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]\n" + " br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch\n" + "for.inner.preheader:\n" + " br label %for.inner\n" + "for.inner:\n" + " %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.inner, label %for.inner.exit\n" + "for.inner.exit:\n" + " br label %for.outer.latch\n" + "for.outer.latch:\n" + " %inc.outer = add nsw i32 %j, 1\n" + " %cmp.outer = icmp slt i32 %inc.outer, %ub\n" + " br i1 %cmp.outer, label %for.outer, label %for.outer.exit\n" + "for.outer.exit:\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.outer.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.outer"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc.outer"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j"); + + // Next two basic blocks are for.outer and for.inner.preheader - skip + // them. + ++FI; + Header = &*(++FI); + assert(Header->getName() == "for.inner"); + L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional InnerBounds = L->getBounds(SE); + EXPECT_NE(InnerBounds, None); + InitialIVValue = + dyn_cast(&InnerBounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(InnerBounds->getStepInst().getName(), "inc"); + StepValue = dyn_cast_or_null(InnerBounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(InnerBounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(InnerBounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(InnerBounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + }); +} + +TEST(LoopInfoTest, AuxiliaryIV) { + const char *ModuleStr = + "define void @foo(i32* %A, i32 %ub) {\n" + "entry:\n" + " %guardcmp = icmp slt i32 0, %ub\n" + " br i1 %guardcmp, label %for.preheader, label %for.end\n" + "for.preheader:\n" + " br label %for.body\n" + "for.body:\n" + " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" + " %aux = phi i32 [ 0, %for.preheader ], [ %auxinc, %for.body ]\n" + " %loopvariant = phi i32 [ 0, %for.preheader ], [ %loopvariantinc, %for.body ]\n" + " %usedoutside = phi i32 [ 0, %for.preheader ], [ %usedoutsideinc, %for.body ]\n" + " %mulopcode = phi i32 [ 0, %for.preheader ], [ %mulopcodeinc, %for.body ]\n" + " %idxprom = sext i32 %i to i64\n" + " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" + " store i32 %i, i32* %arrayidx, align 4\n" + " %mulopcodeinc = mul nsw i32 %mulopcode, 5\n" + " %usedoutsideinc = add nsw i32 %usedoutside, 5\n" + " %loopvariantinc = add nsw i32 %loopvariant, %i\n" + " %auxinc = add nsw i32 %aux, 5\n" + " %inc = add nsw i32 %i, 1\n" + " %cmp = icmp slt i32 %inc, %ub\n" + " br i1 %cmp, label %for.body, label %for.exit\n" + "for.exit:\n" + " %lcssa = phi i32 [ %usedoutside, %for.body ]\n" + " br label %for.end\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfoPlus( + *M, "foo", + [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, + PostDominatorTree &PDT) { + Function::iterator FI = F.begin(); + // First two basic block are entry and for.preheader - skip them. + ++FI; + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.body"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + + Optional Bounds = L->getBounds(SE); + EXPECT_NE(Bounds, None); + ConstantInt *InitialIVValue = + dyn_cast(&Bounds->getInitialIVValue()); + EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); + EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); + ConstantInt *StepValue = + dyn_cast_or_null(Bounds->getStepValue()); + EXPECT_TRUE(StepValue && StepValue->isOne()); + EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); + EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); + EXPECT_EQ(Bounds->getDirection(), + Loop::LoopBounds::Direction::Increasing); + EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); + BasicBlock::iterator II = Header->begin(); + PHINode &Instruction_i = cast(*(II)); + EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_i, SE)); + PHINode &Instruction_aux = cast(*(++II)); + EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_aux, SE)); + PHINode &Instruction_loopvariant = cast(*(++II)); + EXPECT_FALSE( + L->isAuxiliaryInductionVariable(Instruction_loopvariant, SE)); + PHINode &Instruction_usedoutside = cast(*(++II)); + EXPECT_FALSE( + L->isAuxiliaryInductionVariable(Instruction_usedoutside, SE)); + PHINode &Instruction_mulopcode = cast(*(++II)); + EXPECT_FALSE( + L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); + }); +} From 9b2830b46e1c8fb1418956d8835d85225949e3c7 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 23 May 2019 17:58:33 +0000 Subject: [PATCH 0054/1176] lld-link, clang: Treat non-existent input files as possible spellos for option flags OptTable treats arguments starting with / that aren't a known option as filenames. This means lld-link's and clang-cl's typo correction for unknown flags didn't do spell checking for misspelled options that start with /. I first tried changing OptTable, but that got pretty messy, see PR41787 comments 2 and 3. Instead, let lld-link's and clang's (including clang-cl's) "file not found" diagnostic check if a non-existent file looks like it could be a mis-spelled option, and if so add a "did you mean" suggestion to the "file not found" diagnostic. While here, make formatting of a few diagnostics a bit more self-consistent. Fixes PR41787. Differential Revision: https://reviews.llvm.org/D62276 llvm-svn: 361518 --- .../clang/Basic/DiagnosticDriverKinds.td | 12 +++--- clang/include/clang/Driver/Driver.h | 8 ++++ clang/lib/Driver/Driver.cpp | 41 ++++++++++++++----- clang/test/Driver/unknown-arg.c | 37 +++++++++-------- clang/test/Driver/unsupported-option.c | 2 +- clang/test/Frontend/unknown-arg.c | 2 +- lld/COFF/Driver.cpp | 17 ++++++-- lld/COFF/DriverUtils.cpp | 3 +- lld/test/COFF/color-diagnostics.test | 4 +- lld/test/COFF/could-not-open.test | 2 +- lld/test/COFF/driver.test | 12 +++++- lld/test/COFF/error-limit.test | 20 ++++----- lld/test/COFF/nodefaultlib.test | 4 +- lld/test/COFF/responsefile.test | 6 +-- 14 files changed, 112 insertions(+), 58 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 9ce7def88e522..2ece1f0f57890 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -9,9 +9,11 @@ let Component = "Driver" in { def err_drv_no_such_file : Error<"no such file or directory: '%0'">; +def err_drv_no_such_file_with_suggestion : Error< + "no such file or directory: '%0'; did you mean '%1'?">; def err_drv_unsupported_opt : Error<"unsupported option '%0'">; -def err_drv_unsupported_opt_with_suggestion - : Error<"unsupported option '%0', did you mean '%1'?">; +def err_drv_unsupported_opt_with_suggestion : Error< + "unsupported option '%0'; did you mean '%1'?">; def err_drv_unsupported_opt_for_target : Error< "unsupported option '%0' for target '%1'">; def err_drv_unsupported_option_argument : Error< @@ -166,13 +168,13 @@ def err_arch_unsupported_isa def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; def err_drv_unknown_argument : Error<"unknown argument: '%0'">; -def err_drv_unknown_argument_with_suggestion - : Error<"unknown argument '%0', did you mean '%1'?">; +def err_drv_unknown_argument_with_suggestion : Error< + "unknown argument '%0'; did you mean '%1'?">; def warn_drv_unknown_argument_clang_cl : Warning< "unknown argument ignored in clang-cl: '%0'">, InGroup; def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning< - "unknown argument ignored in clang-cl '%0' (did you mean '%1'?)">, + "unknown argument ignored in clang-cl '%0'; did you mean '%1'?">, InGroup; def warn_drv_ycyu_different_arg_clang_cl : Warning< diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 03e6458a5e5d5..244a0f3276c69 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -394,6 +394,14 @@ class Driver { void BuildUniversalActions(Compilation &C, const ToolChain &TC, const InputList &BAInputs) const; + /// Check that the file referenced by Value exists. If it doesn't, + /// issue a diagnostic and return false. + /// If TypoCorrect is true and the file does not exist, see if it looks + /// like a likely typo for a flag and if so print a "did you mean" blurb. + bool DiagnoseInputExistence(const llvm::opt::DerivedArgList &Args, + StringRef Value, types::ID Ty, + bool TypoCorrect) const; + /// BuildJobs - Bind actions to concrete tools and translate /// arguments to form the list of jobs to run. /// diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 06c0e3bdb3777..0f7bbb6eb0fbc 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1975,11 +1975,9 @@ void Driver::BuildUniversalActions(Compilation &C, const ToolChain &TC, } } -/// Check that the file referenced by Value exists. If it doesn't, -/// issue a diagnostic and return false. -static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, - StringRef Value, types::ID Ty) { - if (!D.getCheckInputsExist()) +bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, + types::ID Ty, bool TypoCorrect) const { + if (!getCheckInputsExist()) return true; // stdin always exists. @@ -1995,10 +1993,10 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, } } - if (D.getVFS().exists(Path)) + if (getVFS().exists(Path)) return true; - if (D.IsCLMode()) { + if (IsCLMode()) { if (!llvm::sys::path::is_absolute(Twine(Path)) && llvm::sys::Process::FindInEnvPath("LIB", Value)) return true; @@ -2011,7 +2009,26 @@ static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args, } } - D.Diag(clang::diag::err_drv_no_such_file) << Path; + if (TypoCorrect) { + // Check if the filename is a typo for an option flag. OptTable thinks + // that all args that are not known options and that start with / are + // filenames, but e.g. `/diagnostic:caret` is more likely a typo for + // the option `/diagnostics:caret` than a reference to a file in the root + // directory. + unsigned IncludedFlagsBitmask; + unsigned ExcludedFlagsBitmask; + std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = + getIncludeExcludeOptionFlagMasks(IsCLMode()); + std::string Nearest; + if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmask) <= 1) { + Diag(clang::diag::err_drv_no_such_file_with_suggestion) + << Path << Nearest; + return false; + } + } + + Diag(clang::diag::err_drv_no_such_file) << Path; return false; } @@ -2128,19 +2145,21 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } } - if (DiagnoseInputExistence(*this, Args, Value, Ty)) + if (DiagnoseInputExistence(Args, Value, Ty, /*TypoCorrect=*/true)) Inputs.push_back(std::make_pair(Ty, A)); } else if (A->getOption().matches(options::OPT__SLASH_Tc)) { StringRef Value = A->getValue(); - if (DiagnoseInputExistence(*this, Args, Value, types::TY_C)) { + if (DiagnoseInputExistence(Args, Value, types::TY_C, + /*TypoCorrect=*/false)) { Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue()); Inputs.push_back(std::make_pair(types::TY_C, InputArg)); } A->claim(); } else if (A->getOption().matches(options::OPT__SLASH_Tp)) { StringRef Value = A->getValue(); - if (DiagnoseInputExistence(*this, Args, Value, types::TY_CXX)) { + if (DiagnoseInputExistence(Args, Value, types::TY_CXX, + /*TypoCorrect=*/false)) { Arg *InputArg = MakeInputArg(Args, *Opts, A->getValue()); Inputs.push_back(std::make_pair(types::TY_CXX, InputArg)); } diff --git a/clang/test/Driver/unknown-arg.c b/clang/test/Driver/unknown-arg.c index 4ea43278b7ea8..074a57bb6f8ef 100644 --- a/clang/test/Driver/unknown-arg.c +++ b/clang/test/Driver/unknown-arg.c @@ -1,23 +1,25 @@ // RUN: not %clang %s -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -ifoo -imultilib dir -### 2>&1 | \ -// RUN: FileCheck %s +// RUN: FileCheck %s // RUN: %clang %s -imultilib dir -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=MULTILIB +// RUN: FileCheck %s --check-prefix=MULTILIB // RUN: not %clang %s -stdlibs=foo -hell -version -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN +// RUN: FileCheck %s --check-prefix=DID-YOU-MEAN // RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -### -c -- %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CL +// RUN: FileCheck %s --check-prefix=CL // RUN: %clang_cl -Brepo -### -- %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CL-DID-YOU-MEAN +// RUN: FileCheck %s --check-prefix=CL-DID-YOU-MEAN +// RUN: %clang_cl /Brepo -### -- %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CL-DID-YOU-MEAN-SLASH // RUN: not %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Werror=unknown-argument -### -- %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CL-ERROR +// RUN: FileCheck %s --check-prefix=CL-ERROR // RUN: not %clang_cl -helo -Werror=unknown-argument -### -- %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CL-ERROR-DID-YOU-MEAN +// RUN: FileCheck %s --check-prefix=CL-ERROR-DID-YOU-MEAN // RUN: %clang_cl -cake-is-lie -%0 -%d -HHHH -munknown-to-clang-option -print-stats -funknown-to-clang-option -c -Wno-unknown-argument -### -- %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=SILENT +// RUN: FileCheck %s --check-prefix=SILENT // RUN: not %clang -cc1as -hell --version 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN +// RUN: FileCheck %s --check-prefix=CC1AS-DID-YOU-MEAN // RUN: not %clang -cc1asphalt -help 2>&1 | \ -// RUN: FileCheck %s --check-prefix=UNKNOWN-INTEGRATED +// RUN: FileCheck %s --check-prefix=UNKNOWN-INTEGRATED // CHECK: error: unknown argument: '-cake-is-lie' // CHECK: error: unknown argument: '-%0' @@ -28,9 +30,9 @@ // CHECK: error: unknown argument: '-funknown-to-clang-option' // CHECK: error: unknown argument: '-ifoo' // MULTILIB: warning: argument unused during compilation: '-imultilib dir' -// DID-YOU-MEAN: error: unknown argument '-stdlibs=foo', did you mean '-stdlib=foo'? -// DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'? -// DID-YOU-MEAN: error: unknown argument '-version', did you mean '--version'? +// DID-YOU-MEAN: error: unknown argument '-stdlibs=foo'; did you mean '-stdlib=foo'? +// DID-YOU-MEAN: error: unknown argument '-hell'; did you mean '-help'? +// DID-YOU-MEAN: error: unknown argument '-version'; did you mean '--version'? // CL: warning: unknown argument ignored in clang-cl: '-cake-is-lie' // CL: warning: unknown argument ignored in clang-cl: '-%0' // CL: warning: unknown argument ignored in clang-cl: '-%d' @@ -38,7 +40,8 @@ // CL: warning: unknown argument ignored in clang-cl: '-munknown-to-clang-option' // CL: warning: unknown argument ignored in clang-cl: '-print-stats' // CL: warning: unknown argument ignored in clang-cl: '-funknown-to-clang-option' -// CL-DID-YOU-MEAN: warning: unknown argument ignored in clang-cl '-Brepo' (did you mean '-Brepro'?) +// CL-DID-YOU-MEAN: warning: unknown argument ignored in clang-cl '-Brepo'; did you mean '-Brepro'? +// CL-DID-YOU-MEAN-SLASH: error: no such file or directory: '/Brepo'; did you mean '/Brepro'? // CL-ERROR: error: unknown argument ignored in clang-cl: '-cake-is-lie' // CL-ERROR: error: unknown argument ignored in clang-cl: '-%0' // CL-ERROR: error: unknown argument ignored in clang-cl: '-%d' @@ -46,11 +49,11 @@ // CL-ERROR: error: unknown argument ignored in clang-cl: '-munknown-to-clang-option' // CL-ERROR: error: unknown argument ignored in clang-cl: '-print-stats' // CL-ERROR: error: unknown argument ignored in clang-cl: '-funknown-to-clang-option' -// CL-ERROR-DID-YOU-MEAN: error: unknown argument ignored in clang-cl '-helo' (did you mean '-help'?) +// CL-ERROR-DID-YOU-MEAN: error: unknown argument ignored in clang-cl '-helo'; did you mean '-help'? // SILENT-NOT: error: // SILENT-NOT: warning: -// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell', did you mean '-help'? -// CC1AS-DID-YOU-MEAN: error: unknown argument '--version', did you mean '-version'? +// CC1AS-DID-YOU-MEAN: error: unknown argument '-hell'; did you mean '-help'? +// CC1AS-DID-YOU-MEAN: error: unknown argument '--version'; did you mean '-version'? // UNKNOWN-INTEGRATED: error: unknown integrated tool 'asphalt'. Valid tools include '-cc1' and '-cc1as'. // RUN: %clang -S %s -o %t.s -Wunknown-to-clang-option 2>&1 | FileCheck --check-prefix=IGNORED %s diff --git a/clang/test/Driver/unsupported-option.c b/clang/test/Driver/unsupported-option.c index 39f135e683485..d0611977a99e1 100644 --- a/clang/test/Driver/unsupported-option.c +++ b/clang/test/Driver/unsupported-option.c @@ -4,4 +4,4 @@ // RUN: FileCheck %s --check-prefix=DID-YOU-MEAN // CHECK: error: unsupported option '--hedonism' -// DID-YOU-MEAN: error: unsupported option '--hell', did you mean '--help'? +// DID-YOU-MEAN: error: unsupported option '--hell'; did you mean '--help'? diff --git a/clang/test/Frontend/unknown-arg.c b/clang/test/Frontend/unknown-arg.c index 00f2da6242c7c..eb2fb1aee2dd5 100644 --- a/clang/test/Frontend/unknown-arg.c +++ b/clang/test/Frontend/unknown-arg.c @@ -6,4 +6,4 @@ // RUN: FileCheck %s --check-prefix=DID-YOU-MEAN // CHECK: error: unknown argument: '--helium' -// DID-YOU-MEAN: error: unknown argument '--hel[', did you mean '--help'? +// DID-YOU-MEAN: error: unknown argument '--hel['; did you mean '--help'? diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 605f52e11a293..39d476c5079b6 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -203,9 +203,20 @@ void LinkerDriver::enqueuePath(StringRef Path, bool WholeArchive) { std::string PathStr = Path; enqueueTask([=]() { auto MBOrErr = Future->get(); - if (MBOrErr.second) - error("could not open " + PathStr + ": " + MBOrErr.second.message()); - else + if (MBOrErr.second) { + std::string Error = + "could not open '" + PathStr + "': " + MBOrErr.second.message(); + // Check if the filename is a typo for an option flag. OptTable thinks + // that all args that are not known options and that start with / are + // filenames, but e.g. `/nodefaultlibs` is more likely a typo for + // the option `/nodefaultlib` than a reference to a file in the root + // directory. + std::string Nearest; + if (COFFOptTable().findNearest(PathStr, Nearest) > 1) + error(Error); + else + error(Error + "; did you mean '" + Nearest + "'"); + } else Driver->addBuffer(std::move(MBOrErr.first), WholeArchive); }); } diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 4a99cd6f2e836..f689cd1d4193f 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -833,7 +833,8 @@ opt::InputArgList ArgParser::parse(ArrayRef Argv) { // Expand response files (arguments in the form of @) // and then parse the argument again. - SmallVector ExpandedArgv(Argv.data(), Argv.data() + Argv.size()); + SmallVector ExpandedArgv(Argv.data(), + Argv.data() + Argv.size()); cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), ExpandedArgv); Args = Table.ParseArgs(makeArrayRef(ExpandedArgv).drop_front(), MissingIndex, MissingCount); diff --git a/lld/test/COFF/color-diagnostics.test b/lld/test/COFF/color-diagnostics.test index 9cb145a335ef2..11cf8aff7a0ae 100644 --- a/lld/test/COFF/color-diagnostics.test +++ b/lld/test/COFF/color-diagnostics.test @@ -7,7 +7,7 @@ # RUN: | FileCheck -check-prefix=COLOR %s # COLOR: {{lld-link: .\[0;1;35mwarning: .\[0mignoring unknown argument '-xyz'}} -# COLOR: {{lld-link: .\[0;1;31merror: .\[0mcould not open /nosuchfile}} +# COLOR: {{lld-link: .\[0;1;31merror: .\[0mcould not open '/nosuchfile'}} # RUN: not lld-link /nosuchfile 2>&1 | FileCheck -check-prefix=NOCOLOR %s # RUN: not lld-link -color-diagnostics=never /nosuchfile 2>&1 \ @@ -15,4 +15,4 @@ # RUN: not lld-link -color-diagnostics=always -no-color-diagnostics \ # RUN: /nosuchfile 2>&1 | FileCheck -check-prefix=NOCOLOR %s -# NOCOLOR: lld-link: error: could not open /nosuchfile +# NOCOLOR: lld-link: error: could not open '/nosuchfile' diff --git a/lld/test/COFF/could-not-open.test b/lld/test/COFF/could-not-open.test index 87f11c34e7d45..91fe9ea617978 100644 --- a/lld/test/COFF/could-not-open.test +++ b/lld/test/COFF/could-not-open.test @@ -1,5 +1,5 @@ RUN: not lld-link 01 2>&1 | FileCheck %s -CHECK: could not open 01 +CHECK: could not open '01' CHECK-NOT: /machine is not specified CHECK-NOT: subsystem must be defined diff --git a/lld/test/COFF/driver.test b/lld/test/COFF/driver.test index f4d0e6ae1c900..44abe4d63ee1d 100644 --- a/lld/test/COFF/driver.test +++ b/lld/test/COFF/driver.test @@ -1,6 +1,6 @@ # RUN: not lld-link nosuchfile.obj >& %t.log # RUN: FileCheck -check-prefix=MISSING %s < %t.log -MISSING: nosuchfile.obj: {{[Nn]}}o such file or directory +MISSING: 'nosuchfile.obj': {{[Nn]}}o such file or directory # RUN: lld-link --version | FileCheck -check-prefix=VERSION %s VERSION: {{LLD [0-9]+\.[0-9]+}} @@ -27,3 +27,13 @@ SPELLVERSION: no input files # RUN: not lld-link -nodefaultlibs 2>&1 | FileCheck -check-prefix=SPELLNODEFAULTLIB %s SPELLNODEFAULTLIB: ignoring unknown argument '-nodefaultlibs', did you mean '-nodefaultlib' SPELLNODEFAULTLIB: no input files + +# RUN: not lld-link /nodefaultlibs 2>&1 | FileCheck -check-prefix=SPELLNODEFAULTLIB_SLASH %s +SPELLNODEFAULTLIB_SLASH: could not open '/nodefaultlibs': {{.*}}; did you mean '/nodefaultlib' +SPELLNODEFAULTLIB_SLASH-NOT: no input files + +# Getting flags as typo corrections for normal input files is a side effect +# of how spell checking for /-style flags is implemented. +# RUN: not lld-link force 2>&1 | FileCheck -check-prefix=SPELLFORCE %s +SPELLFORCE: could not open 'force': {{.*}}; did you mean '/force' +SPELLFORCE-NOT: no input files diff --git a/lld/test/COFF/error-limit.test b/lld/test/COFF/error-limit.test index 09c3b9d07f30e..eddd2ab9a64dc 100644 --- a/lld/test/COFF/error-limit.test +++ b/lld/test/COFF/error-limit.test @@ -1,26 +1,26 @@ RUN: not lld-link 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 \ RUN: 21 22 2>&1 | FileCheck -check-prefix=DEFAULT %s -DEFAULT: could not open 01 -DEFAULT: could not open 20 +DEFAULT: could not open '01' +DEFAULT: could not open '20' DEFAULT-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors) -DEFAULT-NOT: could not open 21 +DEFAULT-NOT: could not open '21' RUN: not lld-link /errorlimit:5 01 02 03 04 05 06 07 08 09 10 2>&1 \ RUN: | FileCheck -check-prefix=LIMIT5 %s -LIMIT5: could not open 01 -LIMIT5: could not open 05 +LIMIT5: could not open '01' +LIMIT5: could not open '05' LIMIT5-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors) -LIMIT5-NOT: could not open 06 +LIMIT5-NOT: could not open '06' RUN: not lld-link /errorlimit:0 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 \ RUN: 16 17 18 19 20 21 22 2>&1 | FileCheck -check-prefix=UNLIMITED %s -UNLIMITED: could not open 01 -UNLIMITED: could not open 20 -UNLIMITED: could not open 21 -UNLIMITED: could not open 22 +UNLIMITED: could not open '01' +UNLIMITED: could not open '20' +UNLIMITED: could not open '21' +UNLIMITED: could not open '22' UNLIMITED-NOT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors) RUN: not lld-link /errorlimit:XYZ 01 02 03 04 05 06 07 08 09 10 11 12 13 14 \ diff --git a/lld/test/COFF/nodefaultlib.test b/lld/test/COFF/nodefaultlib.test index 8f4da3a21efee..2a6bec933f438 100644 --- a/lld/test/COFF/nodefaultlib.test +++ b/lld/test/COFF/nodefaultlib.test @@ -19,8 +19,8 @@ # RUN: /nodefaultlib:std64.lib >& %t.log || true # RUN: FileCheck -check-prefix=CHECK3 %s < %t.log -CHECK1: error: could not open hello64.obj: {{[Nn]}}o such file or directory -CHECK2: error: could not open hello64: {{[Nn]}}o such file or directory +CHECK1: error: could not open 'hello64.obj': {{[Nn]}}o such file or directory +CHECK2: error: could not open 'hello64': {{[Nn]}}o such file or directory CHECK3: error: undefined symbol: MessageBoxA CHECK3-NEXT: >>> referenced by {{.*}}hello64.obj:(main) diff --git a/lld/test/COFF/responsefile.test b/lld/test/COFF/responsefile.test index 3ad15bb418151..1480406d3486d 100644 --- a/lld/test/COFF/responsefile.test +++ b/lld/test/COFF/responsefile.test @@ -12,14 +12,14 @@ INVRSP: invalid response file quoting: foobar # RUN: echo "blah\foo" > %t.rsp # RUN: not lld-link @%t.rsp 2>&1 | \ # RUN: FileCheck --check-prefix=DEFRSP %s -DEFRSP: error: could not open blah\foo +DEFRSP: error: could not open 'blah\foo' # RUN: echo "blah\foo" > %t.rsp # RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \ # RUN: FileCheck --check-prefix=WINRSP %s -WINRSP: error: could not open blah\foo +WINRSP: error: could not open 'blah\foo' # RUN: echo "blah\foo" > %t.rsp # RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \ # RUN: FileCheck --check-prefix=POSRSP %s -POSRSP: error: could not open blahfoo +POSRSP: error: could not open 'blahfoo' From 0f3ba44b57b0033a92a04530bcecd1b965adcd4b Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 23 May 2019 17:58:48 +0000 Subject: [PATCH 0055/1176] AMDGPU/GlobalISel: Legality for integer min/max llvm-svn: 361519 --- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 14 +- .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 23 + .../Target/AMDGPU/AMDGPURegisterBankInfo.cpp | 7 + .../AMDGPU/GlobalISel/legalize-smax.mir | 423 ++++++++++++++++++ .../AMDGPU/GlobalISel/legalize-smin.mir | 423 ++++++++++++++++++ .../AMDGPU/GlobalISel/legalize-umax.mir | 413 +++++++++++++++++ .../AMDGPU/GlobalISel/legalize-umin.mir | 413 +++++++++++++++++ .../AMDGPU/GlobalISel/regbankselect-smax.mir | 73 +++ .../AMDGPU/GlobalISel/regbankselect-smin.mir | 73 +++ .../AMDGPU/GlobalISel/regbankselect-umax.mir | 73 +++ .../AMDGPU/GlobalISel/regbankselect-umin.mir | 73 +++ 11 files changed, 2007 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smax.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smin.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umax.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umin.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smax.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smin.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umax.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umin.mir diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index aed1e4c590de6..f9e8c835662dc 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1083,6 +1083,8 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { case TargetOpcode::G_SDIV: case TargetOpcode::G_SREM: + case TargetOpcode::G_SMIN: + case TargetOpcode::G_SMAX: Observer.changingInstr(MI); widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT); widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT); @@ -1111,6 +1113,8 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { return Legalized; case TargetOpcode::G_UDIV: case TargetOpcode::G_UREM: + case TargetOpcode::G_UMIN: + case TargetOpcode::G_UMAX: Observer.changingInstr(MI); widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT); @@ -2207,6 +2211,10 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, case G_FSQRT: case G_BSWAP: case G_SDIV: + case G_SMIN: + case G_SMAX: + case G_UMIN: + case G_UMAX: return fewerElementsVectorBasic(MI, TypeIdx, NarrowTy); case G_SHL: case G_LSHR: @@ -2494,7 +2502,11 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, } case TargetOpcode::G_AND: case TargetOpcode::G_OR: - case TargetOpcode::G_XOR: { + case TargetOpcode::G_XOR: + case TargetOpcode::G_SMIN: + case TargetOpcode::G_SMAX: + case TargetOpcode::G_UMIN: + case TargetOpcode::G_UMAX: { Observer.changingInstr(MI); moreElementsVectorSrc(MI, MoreTy, 1); moreElementsVectorSrc(MI, MoreTy, 2); diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index c4ca42e6af3c0..f93b61035ff6f 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -353,6 +353,29 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST, .clampScalar(0, S32, S32) .scalarize(0); + if (ST.has16BitInsts()) { + if (ST.hasVOP3PInsts()) { + getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) + .legalFor({S32, S16, V2S16}) + .moreElementsIf(isSmallOddVector(0), oneMoreElement(0)) + .clampMaxNumElements(0, S16, 2) + .clampScalar(0, S16, S32) + .widenScalarToNextPow2(0) + .scalarize(0); + } else { + getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) + .legalFor({S32, S16}) + .widenScalarToNextPow2(0) + .clampScalar(0, S16, S32) + .scalarize(0); + } + } else { + getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) + .legalFor({S32}) + .clampScalar(0, S32, S32) + .widenScalarToNextPow2(0) + .scalarize(0); + } auto smallerThan = [](unsigned TypeIdx0, unsigned TypeIdx1) { return [=](const LegalityQuery &Query) { diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp index a6d68f3cd0cd5..1f2b551e1af53 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp @@ -1055,6 +1055,13 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { return getDefaultMappingSOP(MI); LLVM_FALLTHROUGH; + case AMDGPU::G_SMIN: + case AMDGPU::G_SMAX: + case AMDGPU::G_UMIN: + case AMDGPU::G_UMAX: + // TODO: min/max can be scalar, but requires expanding as a compare and + // select. + case AMDGPU::G_FADD: case AMDGPU::G_FSUB: case AMDGPU::G_FPTOSI: diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smax.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smax.mir new file mode 100644 index 0000000000000..678c3d1e7594c --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smax.mir @@ -0,0 +1,423 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=SI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=VI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: test_smax_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smax_s32 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[SMAX]](s32) + ; VI-LABEL: name: test_smax_s32 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[SMAX]](s32) + ; GFX9-LABEL: name: test_smax_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SMAX]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_SMAX %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_smax_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smax_s16 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; SI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; SI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[ASHR1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMAX]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_smax_s16 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; VI: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[TRUNC]], [[TRUNC1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMAX]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_smax_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMAX]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_SMAX %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_smax_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smax_s8 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; SI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; SI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[ASHR1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMAX]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_smax_s8 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[C]](s32) + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; VI: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[TRUNC1]], [[TRUNC]](s16) + ; VI: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SHL]], [[TRUNC]](s16) + ; VI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; VI: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[TRUNC2]], [[TRUNC]](s16) + ; VI: [[ASHR1:%[0-9]+]]:_(s16) = G_ASHR [[SHL1]], [[TRUNC]](s16) + ; VI: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[ASHR]], [[ASHR1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMAX]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_smax_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[C]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[TRUNC1]], [[TRUNC]](s16) + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SHL]], [[TRUNC]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[TRUNC2]], [[TRUNC]](s16) + ; GFX9: [[ASHR1:%[0-9]+]]:_(s16) = G_ASHR [[SHL1]], [[TRUNC]](s16) + ; GFX9: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[ASHR]], [[ASHR1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMAX]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_SMAX %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_smax_s17 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smax_s17 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; SI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; SI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[ASHR1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMAX]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_smax_s17 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; VI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; VI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; VI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[ASHR1]] + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMAX]](s32) + ; VI: $vgpr0 = COPY [[COPY4]](s32) + ; GFX9-LABEL: name: test_smax_s17 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; GFX9: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; GFX9: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; GFX9: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[ASHR]], [[ASHR1]] + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMAX]](s32) + ; GFX9: $vgpr0 = COPY [[COPY4]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s17) = G_TRUNC %0 + %3:_(s17) = G_TRUNC %1 + %4:_(s17) = G_SMAX %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_smax_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_smax_v2s32 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; SI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[UV]], [[UV2]] + ; SI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[UV1]], [[UV3]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SMAX]](s32), [[SMAX1]](s32) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; VI-LABEL: name: test_smax_v2s32 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; VI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; VI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[UV]], [[UV2]] + ; VI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SMAX]](s32), [[SMAX1]](s32) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; GFX9-LABEL: name: test_smax_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[UV]], [[UV2]] + ; GFX9: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SMAX]](s32), [[SMAX1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_SMAX %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: test_smax_v3s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; SI-LABEL: name: test_smax_v3s32 + ; SI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; SI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; SI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[UV]], [[UV3]] + ; SI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[UV1]], [[UV4]] + ; SI: [[SMAX2:%[0-9]+]]:_(s32) = G_SMAX [[UV2]], [[UV5]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[SMAX]](s32), [[SMAX1]](s32), [[SMAX2]](s32) + ; SI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; VI-LABEL: name: test_smax_v3s32 + ; VI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; VI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; VI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; VI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[UV]], [[UV3]] + ; VI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[UV1]], [[UV4]] + ; VI: [[SMAX2:%[0-9]+]]:_(s32) = G_SMAX [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[SMAX]](s32), [[SMAX1]](s32), [[SMAX2]](s32) + ; VI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; GFX9-LABEL: name: test_smax_v3s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; GFX9: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[UV]], [[UV3]] + ; GFX9: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[UV1]], [[UV4]] + ; GFX9: [[SMAX2:%[0-9]+]]:_(s32) = G_SMAX [[UV2]], [[UV5]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[SMAX]](s32), [[SMAX1]](s32), [[SMAX2]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + %0:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(<3 x s32>) = G_SMAX %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... + +--- +name: test_smax_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smax_v2s16 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; SI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; SI: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[UV]](s16) + ; SI: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[UV2]](s16) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[SEXT]], [[SEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX]](s32) + ; SI: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT [[UV1]](s16) + ; SI: [[SEXT3:%[0-9]+]]:_(s32) = G_SEXT [[UV3]](s16) + ; SI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[SEXT2]], [[SEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX1]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16) + ; SI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; VI-LABEL: name: test_smax_v2s16 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; VI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; VI: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[UV]], [[UV2]] + ; VI: [[SMAX1:%[0-9]+]]:_(s16) = G_SMAX [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SMAX]](s16), [[SMAX1]](s16) + ; VI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; GFX9-LABEL: name: test_smax_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[SMAX:%[0-9]+]]:_(<2 x s16>) = G_SMAX [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SMAX]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_SMAX %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_smax_v3s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smax_v3s16 + ; SI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; SI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; SI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; SI: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[UV]](s16) + ; SI: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[UV3]](s16) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[SEXT]], [[SEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX]](s32) + ; SI: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT [[UV1]](s16) + ; SI: [[SEXT3:%[0-9]+]]:_(s32) = G_SEXT [[UV4]](s16) + ; SI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[SEXT2]], [[SEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX1]](s32) + ; SI: [[SEXT4:%[0-9]+]]:_(s32) = G_SEXT [[UV2]](s16) + ; SI: [[SEXT5:%[0-9]+]]:_(s32) = G_SEXT [[UV5]](s16) + ; SI: [[SMAX2:%[0-9]+]]:_(s32) = G_SMAX [[SEXT4]], [[SEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX2]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16) + ; SI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; VI-LABEL: name: test_smax_v3s16 + ; VI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; VI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; VI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; VI: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[UV]], [[UV3]] + ; VI: [[SMAX1:%[0-9]+]]:_(s16) = G_SMAX [[UV1]], [[UV4]] + ; VI: [[SMAX2:%[0-9]+]]:_(s16) = G_SMAX [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SMAX]](s16), [[SMAX1]](s16), [[SMAX2]](s16) + ; VI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; GFX9-LABEL: name: test_smax_v3s16 + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; GFX9: [[DEF2:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF2]], [[EXTRACT]](<3 x s16>), 0 + ; GFX9: [[DEF3:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT1:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF3]], [[EXTRACT1]](<3 x s16>), 0 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT1]](<4 x s16>) + ; GFX9: [[SMAX:%[0-9]+]]:_(<2 x s16>) = G_SMAX [[UV]], [[UV2]] + ; GFX9: [[SMAX1:%[0-9]+]]:_(<2 x s16>) = G_SMAX [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[SMAX]](<2 x s16>), [[SMAX1]](<2 x s16>) + ; GFX9: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 + ; GFX9: S_NOP 0, implicit [[EXTRACT2]](<3 x s16>) + %0:_(<3 x s16>) = G_IMPLICIT_DEF + %1:_(<3 x s16>) = G_IMPLICIT_DEF + %2:_(<3 x s16>) = G_SMAX %0, %1 + S_NOP 0, implicit %2 +... + +--- +name: test_smax_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_smax_v4s16 + ; SI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; SI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; SI: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[UV]](s16) + ; SI: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[UV4]](s16) + ; SI: [[SMAX:%[0-9]+]]:_(s32) = G_SMAX [[SEXT]], [[SEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX]](s32) + ; SI: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT [[UV1]](s16) + ; SI: [[SEXT3:%[0-9]+]]:_(s32) = G_SEXT [[UV5]](s16) + ; SI: [[SMAX1:%[0-9]+]]:_(s32) = G_SMAX [[SEXT2]], [[SEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX1]](s32) + ; SI: [[SEXT4:%[0-9]+]]:_(s32) = G_SEXT [[UV2]](s16) + ; SI: [[SEXT5:%[0-9]+]]:_(s32) = G_SEXT [[UV6]](s16) + ; SI: [[SMAX2:%[0-9]+]]:_(s32) = G_SMAX [[SEXT4]], [[SEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX2]](s32) + ; SI: [[SEXT6:%[0-9]+]]:_(s32) = G_SEXT [[UV3]](s16) + ; SI: [[SEXT7:%[0-9]+]]:_(s32) = G_SEXT [[UV7]](s16) + ; SI: [[SMAX3:%[0-9]+]]:_(s32) = G_SMAX [[SEXT6]], [[SEXT7]] + ; SI: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[SMAX3]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; VI-LABEL: name: test_smax_v4s16 + ; VI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; VI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; VI: [[SMAX:%[0-9]+]]:_(s16) = G_SMAX [[UV]], [[UV4]] + ; VI: [[SMAX1:%[0-9]+]]:_(s16) = G_SMAX [[UV1]], [[UV5]] + ; VI: [[SMAX2:%[0-9]+]]:_(s16) = G_SMAX [[UV2]], [[UV6]] + ; VI: [[SMAX3:%[0-9]+]]:_(s16) = G_SMAX [[UV3]], [[UV7]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SMAX]](s16), [[SMAX1]](s16), [[SMAX2]](s16), [[SMAX3]](s16) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; GFX9-LABEL: name: test_smax_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[SMAX:%[0-9]+]]:_(<2 x s16>) = G_SMAX [[UV]], [[UV2]] + ; GFX9: [[SMAX1:%[0-9]+]]:_(<2 x s16>) = G_SMAX [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[SMAX]](<2 x s16>), [[SMAX1]](<2 x s16>) + ; GFX9: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_SMAX %0, %1 + $vgpr0_vgpr1 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smin.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smin.mir new file mode 100644 index 0000000000000..594483448c03a --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-smin.mir @@ -0,0 +1,423 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=SI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=VI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: test_smin_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smin_s32 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[SMIN]](s32) + ; VI-LABEL: name: test_smin_s32 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[SMIN]](s32) + ; GFX9-LABEL: name: test_smin_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SMIN]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_SMIN %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_smin_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smin_s16 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; SI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; SI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[ASHR]], [[ASHR1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMIN]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_smin_s16 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; VI: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[TRUNC]], [[TRUNC1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMIN]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_smin_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMIN]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_SMIN %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_smin_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smin_s8 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; SI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; SI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[ASHR]], [[ASHR1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMIN]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_smin_s8 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[C]](s32) + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; VI: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[TRUNC1]], [[TRUNC]](s16) + ; VI: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SHL]], [[TRUNC]](s16) + ; VI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; VI: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[TRUNC2]], [[TRUNC]](s16) + ; VI: [[ASHR1:%[0-9]+]]:_(s16) = G_ASHR [[SHL1]], [[TRUNC]](s16) + ; VI: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[ASHR]], [[ASHR1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMIN]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_smin_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[C]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[TRUNC1]], [[TRUNC]](s16) + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SHL]], [[TRUNC]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[TRUNC2]], [[TRUNC]](s16) + ; GFX9: [[ASHR1:%[0-9]+]]:_(s16) = G_ASHR [[SHL1]], [[TRUNC]](s16) + ; GFX9: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[ASHR]], [[ASHR1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SMIN]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_SMIN %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_smin_s17 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smin_s17 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; SI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; SI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[ASHR]], [[ASHR1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMIN]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_smin_s17 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; VI: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; VI: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; VI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[ASHR]], [[ASHR1]] + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMIN]](s32) + ; VI: $vgpr0 = COPY [[COPY4]](s32) + ; GFX9-LABEL: name: test_smin_s17 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY2]], [[C]](s32) + ; GFX9: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32) + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY3]], [[C]](s32) + ; GFX9: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) + ; GFX9: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[ASHR]], [[ASHR1]] + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[SMIN]](s32) + ; GFX9: $vgpr0 = COPY [[COPY4]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s17) = G_TRUNC %0 + %3:_(s17) = G_TRUNC %1 + %4:_(s17) = G_SMIN %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_smin_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_smin_v2s32 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; SI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[UV]], [[UV2]] + ; SI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[UV1]], [[UV3]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SMIN]](s32), [[SMIN1]](s32) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; VI-LABEL: name: test_smin_v2s32 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; VI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; VI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[UV]], [[UV2]] + ; VI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SMIN]](s32), [[SMIN1]](s32) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; GFX9-LABEL: name: test_smin_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[UV]], [[UV2]] + ; GFX9: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SMIN]](s32), [[SMIN1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_SMIN %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: test_smin_v3s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; SI-LABEL: name: test_smin_v3s32 + ; SI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; SI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; SI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[UV]], [[UV3]] + ; SI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[UV1]], [[UV4]] + ; SI: [[SMIN2:%[0-9]+]]:_(s32) = G_SMIN [[UV2]], [[UV5]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[SMIN]](s32), [[SMIN1]](s32), [[SMIN2]](s32) + ; SI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; VI-LABEL: name: test_smin_v3s32 + ; VI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; VI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; VI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; VI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[UV]], [[UV3]] + ; VI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[UV1]], [[UV4]] + ; VI: [[SMIN2:%[0-9]+]]:_(s32) = G_SMIN [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[SMIN]](s32), [[SMIN1]](s32), [[SMIN2]](s32) + ; VI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; GFX9-LABEL: name: test_smin_v3s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; GFX9: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[UV]], [[UV3]] + ; GFX9: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[UV1]], [[UV4]] + ; GFX9: [[SMIN2:%[0-9]+]]:_(s32) = G_SMIN [[UV2]], [[UV5]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[SMIN]](s32), [[SMIN1]](s32), [[SMIN2]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + %0:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(<3 x s32>) = G_SMIN %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... + +--- +name: test_smin_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smin_v2s16 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; SI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; SI: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[UV]](s16) + ; SI: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[UV2]](s16) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[SEXT]], [[SEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN]](s32) + ; SI: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT [[UV1]](s16) + ; SI: [[SEXT3:%[0-9]+]]:_(s32) = G_SEXT [[UV3]](s16) + ; SI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[SEXT2]], [[SEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN1]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16) + ; SI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; VI-LABEL: name: test_smin_v2s16 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; VI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; VI: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[UV]], [[UV2]] + ; VI: [[SMIN1:%[0-9]+]]:_(s16) = G_SMIN [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SMIN]](s16), [[SMIN1]](s16) + ; VI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; GFX9-LABEL: name: test_smin_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[SMIN:%[0-9]+]]:_(<2 x s16>) = G_SMIN [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SMIN]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_SMIN %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_smin_v3s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_smin_v3s16 + ; SI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; SI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; SI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; SI: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[UV]](s16) + ; SI: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[UV3]](s16) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[SEXT]], [[SEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN]](s32) + ; SI: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT [[UV1]](s16) + ; SI: [[SEXT3:%[0-9]+]]:_(s32) = G_SEXT [[UV4]](s16) + ; SI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[SEXT2]], [[SEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN1]](s32) + ; SI: [[SEXT4:%[0-9]+]]:_(s32) = G_SEXT [[UV2]](s16) + ; SI: [[SEXT5:%[0-9]+]]:_(s32) = G_SEXT [[UV5]](s16) + ; SI: [[SMIN2:%[0-9]+]]:_(s32) = G_SMIN [[SEXT4]], [[SEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN2]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16) + ; SI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; VI-LABEL: name: test_smin_v3s16 + ; VI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; VI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; VI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; VI: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[UV]], [[UV3]] + ; VI: [[SMIN1:%[0-9]+]]:_(s16) = G_SMIN [[UV1]], [[UV4]] + ; VI: [[SMIN2:%[0-9]+]]:_(s16) = G_SMIN [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SMIN]](s16), [[SMIN1]](s16), [[SMIN2]](s16) + ; VI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; GFX9-LABEL: name: test_smin_v3s16 + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; GFX9: [[DEF2:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF2]], [[EXTRACT]](<3 x s16>), 0 + ; GFX9: [[DEF3:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT1:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF3]], [[EXTRACT1]](<3 x s16>), 0 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT1]](<4 x s16>) + ; GFX9: [[SMIN:%[0-9]+]]:_(<2 x s16>) = G_SMIN [[UV]], [[UV2]] + ; GFX9: [[SMIN1:%[0-9]+]]:_(<2 x s16>) = G_SMIN [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[SMIN]](<2 x s16>), [[SMIN1]](<2 x s16>) + ; GFX9: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 + ; GFX9: S_NOP 0, implicit [[EXTRACT2]](<3 x s16>) + %0:_(<3 x s16>) = G_IMPLICIT_DEF + %1:_(<3 x s16>) = G_IMPLICIT_DEF + %2:_(<3 x s16>) = G_SMIN %0, %1 + S_NOP 0, implicit %2 +... + +--- +name: test_smin_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_smin_v4s16 + ; SI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; SI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; SI: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[UV]](s16) + ; SI: [[SEXT1:%[0-9]+]]:_(s32) = G_SEXT [[UV4]](s16) + ; SI: [[SMIN:%[0-9]+]]:_(s32) = G_SMIN [[SEXT]], [[SEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN]](s32) + ; SI: [[SEXT2:%[0-9]+]]:_(s32) = G_SEXT [[UV1]](s16) + ; SI: [[SEXT3:%[0-9]+]]:_(s32) = G_SEXT [[UV5]](s16) + ; SI: [[SMIN1:%[0-9]+]]:_(s32) = G_SMIN [[SEXT2]], [[SEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN1]](s32) + ; SI: [[SEXT4:%[0-9]+]]:_(s32) = G_SEXT [[UV2]](s16) + ; SI: [[SEXT5:%[0-9]+]]:_(s32) = G_SEXT [[UV6]](s16) + ; SI: [[SMIN2:%[0-9]+]]:_(s32) = G_SMIN [[SEXT4]], [[SEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN2]](s32) + ; SI: [[SEXT6:%[0-9]+]]:_(s32) = G_SEXT [[UV3]](s16) + ; SI: [[SEXT7:%[0-9]+]]:_(s32) = G_SEXT [[UV7]](s16) + ; SI: [[SMIN3:%[0-9]+]]:_(s32) = G_SMIN [[SEXT6]], [[SEXT7]] + ; SI: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[SMIN3]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; VI-LABEL: name: test_smin_v4s16 + ; VI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; VI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; VI: [[SMIN:%[0-9]+]]:_(s16) = G_SMIN [[UV]], [[UV4]] + ; VI: [[SMIN1:%[0-9]+]]:_(s16) = G_SMIN [[UV1]], [[UV5]] + ; VI: [[SMIN2:%[0-9]+]]:_(s16) = G_SMIN [[UV2]], [[UV6]] + ; VI: [[SMIN3:%[0-9]+]]:_(s16) = G_SMIN [[UV3]], [[UV7]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SMIN]](s16), [[SMIN1]](s16), [[SMIN2]](s16), [[SMIN3]](s16) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; GFX9-LABEL: name: test_smin_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[SMIN:%[0-9]+]]:_(<2 x s16>) = G_SMIN [[UV]], [[UV2]] + ; GFX9: [[SMIN1:%[0-9]+]]:_(<2 x s16>) = G_SMIN [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[SMIN]](<2 x s16>), [[SMIN1]](<2 x s16>) + ; GFX9: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_SMIN %0, %1 + $vgpr0_vgpr1 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umax.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umax.mir new file mode 100644 index 0000000000000..1d9b6cd2f9fd2 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umax.mir @@ -0,0 +1,413 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=SI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=VI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: test_umax_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umax_s32 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[UMAX]](s32) + ; VI-LABEL: name: test_umax_s32 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[UMAX]](s32) + ; GFX9-LABEL: name: test_umax_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[UMAX]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_UMAX %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_umax_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umax_s16 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[AND]], [[AND1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMAX]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_umax_s16 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; VI: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[TRUNC]], [[TRUNC1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMAX]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_umax_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMAX]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_UMAX %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_umax_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umax_s8 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[AND]], [[AND1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMAX]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_umax_s8 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[C]](s32) + ; VI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[COPY3]] + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[AND]](s32) + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[COPY3]] + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[AND1]](s32) + ; VI: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[TRUNC]], [[TRUNC1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMAX]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_umax_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[C]](s32) + ; GFX9: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[COPY3]] + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[AND]](s32) + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[COPY3]] + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[AND1]](s32) + ; GFX9: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMAX]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_UMAX %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_umax_s17 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umax_s17 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 131071 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[AND]], [[AND1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMAX]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_umax_s17 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 131071 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; VI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[AND]], [[AND1]] + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMAX]](s32) + ; VI: $vgpr0 = COPY [[COPY4]](s32) + ; GFX9-LABEL: name: test_umax_s17 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 131071 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; GFX9: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[AND]], [[AND1]] + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMAX]](s32) + ; GFX9: $vgpr0 = COPY [[COPY4]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s17) = G_TRUNC %0 + %3:_(s17) = G_TRUNC %1 + %4:_(s17) = G_UMAX %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_umax_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_umax_v2s32 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; SI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[UV]], [[UV2]] + ; SI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[UV1]], [[UV3]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UMAX]](s32), [[UMAX1]](s32) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; VI-LABEL: name: test_umax_v2s32 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; VI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; VI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[UV]], [[UV2]] + ; VI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UMAX]](s32), [[UMAX1]](s32) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; GFX9-LABEL: name: test_umax_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[UV]], [[UV2]] + ; GFX9: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UMAX]](s32), [[UMAX1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_UMAX %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: test_umax_v3s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; SI-LABEL: name: test_umax_v3s32 + ; SI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; SI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; SI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[UV]], [[UV3]] + ; SI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[UV1]], [[UV4]] + ; SI: [[UMAX2:%[0-9]+]]:_(s32) = G_UMAX [[UV2]], [[UV5]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[UMAX]](s32), [[UMAX1]](s32), [[UMAX2]](s32) + ; SI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; VI-LABEL: name: test_umax_v3s32 + ; VI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; VI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; VI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; VI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[UV]], [[UV3]] + ; VI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[UV1]], [[UV4]] + ; VI: [[UMAX2:%[0-9]+]]:_(s32) = G_UMAX [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[UMAX]](s32), [[UMAX1]](s32), [[UMAX2]](s32) + ; VI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; GFX9-LABEL: name: test_umax_v3s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; GFX9: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[UV]], [[UV3]] + ; GFX9: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[UV1]], [[UV4]] + ; GFX9: [[UMAX2:%[0-9]+]]:_(s32) = G_UMAX [[UV2]], [[UV5]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[UMAX]](s32), [[UMAX1]](s32), [[UMAX2]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + %0:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(<3 x s32>) = G_UMAX %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... + +--- +name: test_umax_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umax_v2s16 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; SI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s16) + ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UV2]](s16) + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT]], [[ZEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX]](s32) + ; SI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[UV1]](s16) + ; SI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[UV3]](s16) + ; SI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT2]], [[ZEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX1]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16) + ; SI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; VI-LABEL: name: test_umax_v2s16 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; VI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; VI: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[UV]], [[UV2]] + ; VI: [[UMAX1:%[0-9]+]]:_(s16) = G_UMAX [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UMAX]](s16), [[UMAX1]](s16) + ; VI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; GFX9-LABEL: name: test_umax_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[UMAX:%[0-9]+]]:_(<2 x s16>) = G_UMAX [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[UMAX]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_UMAX %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_umax_v3s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umax_v3s16 + ; SI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; SI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; SI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s16) + ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UV3]](s16) + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT]], [[ZEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX]](s32) + ; SI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[UV1]](s16) + ; SI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[UV4]](s16) + ; SI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT2]], [[ZEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX1]](s32) + ; SI: [[ZEXT4:%[0-9]+]]:_(s32) = G_ZEXT [[UV2]](s16) + ; SI: [[ZEXT5:%[0-9]+]]:_(s32) = G_ZEXT [[UV5]](s16) + ; SI: [[UMAX2:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT4]], [[ZEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX2]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16) + ; SI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; VI-LABEL: name: test_umax_v3s16 + ; VI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; VI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; VI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; VI: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[UV]], [[UV3]] + ; VI: [[UMAX1:%[0-9]+]]:_(s16) = G_UMAX [[UV1]], [[UV4]] + ; VI: [[UMAX2:%[0-9]+]]:_(s16) = G_UMAX [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UMAX]](s16), [[UMAX1]](s16), [[UMAX2]](s16) + ; VI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; GFX9-LABEL: name: test_umax_v3s16 + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; GFX9: [[DEF2:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF2]], [[EXTRACT]](<3 x s16>), 0 + ; GFX9: [[DEF3:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT1:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF3]], [[EXTRACT1]](<3 x s16>), 0 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT1]](<4 x s16>) + ; GFX9: [[UMAX:%[0-9]+]]:_(<2 x s16>) = G_UMAX [[UV]], [[UV2]] + ; GFX9: [[UMAX1:%[0-9]+]]:_(<2 x s16>) = G_UMAX [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[UMAX]](<2 x s16>), [[UMAX1]](<2 x s16>) + ; GFX9: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 + ; GFX9: S_NOP 0, implicit [[EXTRACT2]](<3 x s16>) + %0:_(<3 x s16>) = G_IMPLICIT_DEF + %1:_(<3 x s16>) = G_IMPLICIT_DEF + %2:_(<3 x s16>) = G_UMAX %0, %1 + S_NOP 0, implicit %2 +... + +--- +name: test_umax_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_umax_v4s16 + ; SI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; SI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s16) + ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UV4]](s16) + ; SI: [[UMAX:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT]], [[ZEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX]](s32) + ; SI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[UV1]](s16) + ; SI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[UV5]](s16) + ; SI: [[UMAX1:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT2]], [[ZEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX1]](s32) + ; SI: [[ZEXT4:%[0-9]+]]:_(s32) = G_ZEXT [[UV2]](s16) + ; SI: [[ZEXT5:%[0-9]+]]:_(s32) = G_ZEXT [[UV6]](s16) + ; SI: [[UMAX2:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT4]], [[ZEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX2]](s32) + ; SI: [[ZEXT6:%[0-9]+]]:_(s32) = G_ZEXT [[UV3]](s16) + ; SI: [[ZEXT7:%[0-9]+]]:_(s32) = G_ZEXT [[UV7]](s16) + ; SI: [[UMAX3:%[0-9]+]]:_(s32) = G_UMAX [[ZEXT6]], [[ZEXT7]] + ; SI: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[UMAX3]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; VI-LABEL: name: test_umax_v4s16 + ; VI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; VI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; VI: [[UMAX:%[0-9]+]]:_(s16) = G_UMAX [[UV]], [[UV4]] + ; VI: [[UMAX1:%[0-9]+]]:_(s16) = G_UMAX [[UV1]], [[UV5]] + ; VI: [[UMAX2:%[0-9]+]]:_(s16) = G_UMAX [[UV2]], [[UV6]] + ; VI: [[UMAX3:%[0-9]+]]:_(s16) = G_UMAX [[UV3]], [[UV7]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UMAX]](s16), [[UMAX1]](s16), [[UMAX2]](s16), [[UMAX3]](s16) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; GFX9-LABEL: name: test_umax_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[UMAX:%[0-9]+]]:_(<2 x s16>) = G_UMAX [[UV]], [[UV2]] + ; GFX9: [[UMAX1:%[0-9]+]]:_(<2 x s16>) = G_UMAX [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[UMAX]](<2 x s16>), [[UMAX1]](<2 x s16>) + ; GFX9: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_UMAX %0, %1 + $vgpr0_vgpr1 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umin.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umin.mir new file mode 100644 index 0000000000000..d9775a54719cb --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-umin.mir @@ -0,0 +1,413 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=SI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=VI %s +# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: test_umin_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umin_s32 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[UMIN]](s32) + ; VI-LABEL: name: test_umin_s32 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[UMIN]](s32) + ; GFX9-LABEL: name: test_umin_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[UMIN]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_UMIN %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_umin_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umin_s16 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[AND]], [[AND1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMIN]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_umin_s16 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; VI: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[TRUNC]], [[TRUNC1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMIN]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_umin_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMIN]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_UMIN %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_umin_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umin_s8 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[AND]], [[AND1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMIN]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_umin_s8 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[C]](s32) + ; VI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[COPY3]] + ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[AND]](s32) + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[COPY3]] + ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[AND1]](s32) + ; VI: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[TRUNC]], [[TRUNC1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMIN]](s16) + ; VI: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: test_umin_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[C]](s32) + ; GFX9: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[COPY3]] + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[AND]](s32) + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY4]], [[COPY3]] + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[AND1]](s32) + ; GFX9: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UMIN]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_UMIN %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_umin_s17 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umin_s17 + ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; SI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 131071 + ; SI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; SI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; SI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; SI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[AND]], [[AND1]] + ; SI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMIN]](s32) + ; SI: $vgpr0 = COPY [[COPY4]](s32) + ; VI-LABEL: name: test_umin_s17 + ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; VI: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 131071 + ; VI: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; VI: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; VI: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; VI: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; VI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[AND]], [[AND1]] + ; VI: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMIN]](s32) + ; VI: $vgpr0 = COPY [[COPY4]](s32) + ; GFX9-LABEL: name: test_umin_s17 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 131071 + ; GFX9: [[COPY2:%[0-9]+]]:_(s32) = COPY [[COPY]](s32) + ; GFX9: [[AND:%[0-9]+]]:_(s32) = G_AND [[COPY2]], [[C]] + ; GFX9: [[COPY3:%[0-9]+]]:_(s32) = COPY [[COPY1]](s32) + ; GFX9: [[AND1:%[0-9]+]]:_(s32) = G_AND [[COPY3]], [[C]] + ; GFX9: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[AND]], [[AND1]] + ; GFX9: [[COPY4:%[0-9]+]]:_(s32) = COPY [[UMIN]](s32) + ; GFX9: $vgpr0 = COPY [[COPY4]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s17) = G_TRUNC %0 + %3:_(s17) = G_TRUNC %1 + %4:_(s17) = G_UMIN %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: test_umin_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_umin_v2s32 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; SI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[UV]], [[UV2]] + ; SI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[UV1]], [[UV3]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UMIN]](s32), [[UMIN1]](s32) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; VI-LABEL: name: test_umin_v2s32 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; VI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; VI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[UV]], [[UV2]] + ; VI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UMIN]](s32), [[UMIN1]](s32) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; GFX9-LABEL: name: test_umin_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[UV]], [[UV2]] + ; GFX9: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UMIN]](s32), [[UMIN1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_UMIN %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: test_umin_v3s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; SI-LABEL: name: test_umin_v3s32 + ; SI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; SI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; SI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[UV]], [[UV3]] + ; SI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[UV1]], [[UV4]] + ; SI: [[UMIN2:%[0-9]+]]:_(s32) = G_UMIN [[UV2]], [[UV5]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[UMIN]](s32), [[UMIN1]](s32), [[UMIN2]](s32) + ; SI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; VI-LABEL: name: test_umin_v3s32 + ; VI: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; VI: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; VI: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; VI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[UV]], [[UV3]] + ; VI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[UV1]], [[UV4]] + ; VI: [[UMIN2:%[0-9]+]]:_(s32) = G_UMIN [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[UMIN]](s32), [[UMIN1]](s32), [[UMIN2]](s32) + ; VI: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + ; GFX9-LABEL: name: test_umin_v3s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<3 x s32>) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<3 x s32>) + ; GFX9: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[UV]], [[UV3]] + ; GFX9: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[UV1]], [[UV4]] + ; GFX9: [[UMIN2:%[0-9]+]]:_(s32) = G_UMIN [[UV2]], [[UV5]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[UMIN]](s32), [[UMIN1]](s32), [[UMIN2]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<3 x s32>) + %0:_(<3 x s32>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s32>) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(<3 x s32>) = G_UMIN %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... + +--- +name: test_umin_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umin_v2s16 + ; SI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; SI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; SI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s16) + ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UV2]](s16) + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT]], [[ZEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN]](s32) + ; SI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[UV1]](s16) + ; SI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[UV3]](s16) + ; SI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT2]], [[ZEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN1]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16) + ; SI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; VI-LABEL: name: test_umin_v2s16 + ; VI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; VI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; VI: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; VI: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[UV]], [[UV2]] + ; VI: [[UMIN1:%[0-9]+]]:_(s16) = G_UMIN [[UV1]], [[UV3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UMIN]](s16), [[UMIN1]](s16) + ; VI: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) + ; GFX9-LABEL: name: test_umin_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[UMIN:%[0-9]+]]:_(<2 x s16>) = G_UMIN [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[UMIN]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_UMIN %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: test_umin_v3s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; SI-LABEL: name: test_umin_v3s16 + ; SI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; SI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; SI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; SI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s16) + ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UV3]](s16) + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT]], [[ZEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN]](s32) + ; SI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[UV1]](s16) + ; SI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[UV4]](s16) + ; SI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT2]], [[ZEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN1]](s32) + ; SI: [[ZEXT4:%[0-9]+]]:_(s32) = G_ZEXT [[UV2]](s16) + ; SI: [[ZEXT5:%[0-9]+]]:_(s32) = G_ZEXT [[UV5]](s16) + ; SI: [[UMIN2:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT4]], [[ZEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN2]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16) + ; SI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; VI-LABEL: name: test_umin_v3s16 + ; VI: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; VI: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; VI: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT]](<3 x s16>) + ; VI: [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[EXTRACT1]](<3 x s16>) + ; VI: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[UV]], [[UV3]] + ; VI: [[UMIN1:%[0-9]+]]:_(s16) = G_UMIN [[UV1]], [[UV4]] + ; VI: [[UMIN2:%[0-9]+]]:_(s16) = G_UMIN [[UV2]], [[UV5]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UMIN]](s16), [[UMIN1]](s16), [[UMIN2]](s16) + ; VI: S_NOP 0, implicit [[BUILD_VECTOR]](<3 x s16>) + ; GFX9-LABEL: name: test_umin_v3s16 + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[DEF1:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT1:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF1]](<4 x s16>), 0 + ; GFX9: [[DEF2:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF2]], [[EXTRACT]](<3 x s16>), 0 + ; GFX9: [[DEF3:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[INSERT1:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF3]], [[EXTRACT1]](<3 x s16>), 0 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT1]](<4 x s16>) + ; GFX9: [[UMIN:%[0-9]+]]:_(<2 x s16>) = G_UMIN [[UV]], [[UV2]] + ; GFX9: [[UMIN1:%[0-9]+]]:_(<2 x s16>) = G_UMIN [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[UMIN]](<2 x s16>), [[UMIN1]](<2 x s16>) + ; GFX9: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 + ; GFX9: S_NOP 0, implicit [[EXTRACT2]](<3 x s16>) + %0:_(<3 x s16>) = G_IMPLICIT_DEF + %1:_(<3 x s16>) = G_IMPLICIT_DEF + %2:_(<3 x s16>) = G_UMIN %0, %1 + S_NOP 0, implicit %2 +... + +--- +name: test_umin_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; SI-LABEL: name: test_umin_v4s16 + ; SI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; SI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; SI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; SI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UV]](s16) + ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UV4]](s16) + ; SI: [[UMIN:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT]], [[ZEXT1]] + ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN]](s32) + ; SI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[UV1]](s16) + ; SI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[UV5]](s16) + ; SI: [[UMIN1:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT2]], [[ZEXT3]] + ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN1]](s32) + ; SI: [[ZEXT4:%[0-9]+]]:_(s32) = G_ZEXT [[UV2]](s16) + ; SI: [[ZEXT5:%[0-9]+]]:_(s32) = G_ZEXT [[UV6]](s16) + ; SI: [[UMIN2:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT4]], [[ZEXT5]] + ; SI: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN2]](s32) + ; SI: [[ZEXT6:%[0-9]+]]:_(s32) = G_ZEXT [[UV3]](s16) + ; SI: [[ZEXT7:%[0-9]+]]:_(s32) = G_ZEXT [[UV7]](s16) + ; SI: [[UMIN3:%[0-9]+]]:_(s32) = G_UMIN [[ZEXT6]], [[ZEXT7]] + ; SI: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[UMIN3]](s32) + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[TRUNC3]](s16) + ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; VI-LABEL: name: test_umin_v4s16 + ; VI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; VI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; VI: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; VI: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; VI: [[UMIN:%[0-9]+]]:_(s16) = G_UMIN [[UV]], [[UV4]] + ; VI: [[UMIN1:%[0-9]+]]:_(s16) = G_UMIN [[UV1]], [[UV5]] + ; VI: [[UMIN2:%[0-9]+]]:_(s16) = G_UMIN [[UV2]], [[UV6]] + ; VI: [[UMIN3:%[0-9]+]]:_(s16) = G_UMIN [[UV3]], [[UV7]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UMIN]](s16), [[UMIN1]](s16), [[UMIN2]](s16), [[UMIN3]](s16) + ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; GFX9-LABEL: name: test_umin_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[UMIN:%[0-9]+]]:_(<2 x s16>) = G_UMIN [[UV]], [[UV2]] + ; GFX9: [[UMIN1:%[0-9]+]]:_(<2 x s16>) = G_UMIN [[UV1]], [[UV3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[UMIN]](<2 x s16>), [[UMIN1]](<2 x s16>) + ; GFX9: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_UMIN %0, %1 + $vgpr0_vgpr1 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smax.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smax.mir new file mode 100644 index 0000000000000..144c82530bcee --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smax.mir @@ -0,0 +1,73 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-fast | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-greedy | FileCheck %s + +--- +name: smax_ss +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: smax_ss + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[SMAX:%[0-9]+]]:vgpr(s32) = G_SMAX [[COPY]], [[COPY2]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s32) = G_SMAX %0, %1 +... + +--- +name: smax_sv +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: smax_sv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[SMAX:%[0-9]+]]:vgpr(s32) = G_SMAX [[COPY]], [[COPY1]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = G_SMAX %0, %1 +... + +--- +name: smax_vs +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: smax_vs + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[SMAX:%[0-9]+]]:vgpr(s32) = G_SMAX [[COPY]], [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = G_SMAX %0, %1 +... + +--- +name: smax_vv +legalized: true + +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: smax_vv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[SMAX:%[0-9]+]]:vgpr(s32) = G_SMAX [[COPY]], [[COPY1]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_SMAX %0, %1 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smin.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smin.mir new file mode 100644 index 0000000000000..5fa5ef4276eba --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-smin.mir @@ -0,0 +1,73 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-fast | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-greedy | FileCheck %s + +--- +name: smin_ss +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: smin_ss + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[SMIN:%[0-9]+]]:vgpr(s32) = G_SMIN [[COPY]], [[COPY2]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s32) = G_SMIN %0, %1 +... + +--- +name: smin_sv +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: smin_sv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[SMIN:%[0-9]+]]:vgpr(s32) = G_SMIN [[COPY]], [[COPY1]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = G_SMIN %0, %1 +... + +--- +name: smin_vs +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: smin_vs + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[SMIN:%[0-9]+]]:vgpr(s32) = G_SMIN [[COPY]], [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = G_SMIN %0, %1 +... + +--- +name: smin_vv +legalized: true + +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: smin_vv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[SMIN:%[0-9]+]]:vgpr(s32) = G_SMIN [[COPY]], [[COPY1]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_SMIN %0, %1 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umax.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umax.mir new file mode 100644 index 0000000000000..123c12b5ddce5 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umax.mir @@ -0,0 +1,73 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-fast | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-greedy | FileCheck %s + +--- +name: umax_ss +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: umax_ss + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[UMAX:%[0-9]+]]:vgpr(s32) = G_UMAX [[COPY]], [[COPY2]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s32) = G_UMAX %0, %1 +... + +--- +name: umax_sv +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: umax_sv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[UMAX:%[0-9]+]]:vgpr(s32) = G_UMAX [[COPY]], [[COPY1]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = G_UMAX %0, %1 +... + +--- +name: umax_vs +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: umax_vs + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[UMAX:%[0-9]+]]:vgpr(s32) = G_UMAX [[COPY]], [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = G_UMAX %0, %1 +... + +--- +name: umax_vv +legalized: true + +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: umax_vv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[UMAX:%[0-9]+]]:vgpr(s32) = G_UMAX [[COPY]], [[COPY1]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_UMAX %0, %1 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umin.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umin.mir new file mode 100644 index 0000000000000..f78cfecacabef --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-umin.mir @@ -0,0 +1,73 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-fast | FileCheck %s +# RUN: llc -march=amdgcn -mcpu=fiji -run-pass=regbankselect %s -verify-machineinstrs -o - -regbankselect-greedy | FileCheck %s + +--- +name: umin_ss +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $sgpr1 + + ; CHECK-LABEL: name: umin_ss + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr1 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[UMIN:%[0-9]+]]:vgpr(s32) = G_UMIN [[COPY]], [[COPY2]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $sgpr1 + %2:_(s32) = G_UMIN %0, %1 +... + +--- +name: umin_sv +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: umin_sv + ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[UMIN:%[0-9]+]]:vgpr(s32) = G_UMIN [[COPY]], [[COPY1]] + %0:_(s32) = COPY $sgpr0 + %1:_(s32) = COPY $vgpr0 + %2:_(s32) = G_UMIN %0, %1 +... + +--- +name: umin_vs +legalized: true + +body: | + bb.0: + liveins: $sgpr0, $vgpr0 + + ; CHECK-LABEL: name: umin_vs + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr0 + ; CHECK: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) + ; CHECK: [[UMIN:%[0-9]+]]:vgpr(s32) = G_UMIN [[COPY]], [[COPY2]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $sgpr0 + %2:_(s32) = G_UMIN %0, %1 +... + +--- +name: umin_vv +legalized: true + +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; CHECK-LABEL: name: umin_vv + ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 + ; CHECK: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 + ; CHECK: [[UMIN:%[0-9]+]]:vgpr(s32) = G_UMIN [[COPY]], [[COPY1]] + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_UMIN %0, %1 +... From 4d7054615cc3cfe3e715111edf8a54b65074fba3 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 23 May 2019 18:01:16 +0000 Subject: [PATCH 0056/1176] gn build: Merge r361418 more llvm-svn: 361520 --- .../gn/secondary/clang-tools-extra/clang-tidy/utils/BUILD.gn | 1 + .../gn/secondary/clang-tools-extra/unittests/clang-tidy/BUILD.gn | 1 + 2 files changed, 2 insertions(+) diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/utils/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/utils/BUILD.gn index ea5783ff566df..2deb47501ce6c 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/utils/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/utils/BUILD.gn @@ -7,6 +7,7 @@ static_library("utils") { "//clang/lib/ASTMatchers", "//clang/lib/Basic", "//clang/lib/Lex", + "//clang/lib/Tooling/Refactoring", "//llvm/lib/Support", ] sources = [ diff --git a/llvm/utils/gn/secondary/clang-tools-extra/unittests/clang-tidy/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/unittests/clang-tidy/BUILD.gn index 12ea944e3b25b..7d1f256458957 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/unittests/clang-tidy/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/unittests/clang-tidy/BUILD.gn @@ -18,6 +18,7 @@ unittest("ClangTidyTests") { "//clang/lib/Serialization", "//clang/lib/Tooling", "//clang/lib/Tooling/Core", + "//clang/lib/Tooling/Refactoring", "//llvm/lib/Support", ] include_dirs = [ "//clang-tools-extra/clang-tidy" ] From d19a36efd14f1474dd73866cd122e51343d612b3 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 18:08:00 +0000 Subject: [PATCH 0057/1176] UpdateTestChecks: -march=mips/-march=mipsel is mips triple. Again, a mixture of march and triple, with majority being march: llvm/test/CodeGen/Mips$ grep -ri triple | wc -l 818 llvm/test/CodeGen/Mips$ grep -ri march | wc -l 1457 llvm-svn: 361521 --- llvm/utils/UpdateTestChecks/asm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index ccc68d06f5ba5..459aa42381ab7 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -219,6 +219,7 @@ def scrub_asm_wasm32(asm, args): def get_triple_from_march(march): triples = { 'amdgcn': 'amdgcn', + 'mips': 'mips', 'sparc': 'sparc', } for prefix, triple in triples.items(): From 06688fe7158e730d191f21469b410c06c54bfaf2 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 18:08:13 +0000 Subject: [PATCH 0058/1176] [NFC][Mips] Autogenerate msa/arithmetic.ll test Being affected by (sub %x, C) -> add %X, (sub 0, C) 'for vectors' patch. llvm-svn: 361522 --- llvm/test/CodeGen/Mips/msa/arithmetic.ll | 689 +++++++++++------------ 1 file changed, 323 insertions(+), 366 deletions(-) diff --git a/llvm/test/CodeGen/Mips/msa/arithmetic.ll b/llvm/test/CodeGen/Mips/msa/arithmetic.ll index 3ecd0e43589f8..86597d52fda95 100644 --- a/llvm/test/CodeGen/Mips/msa/arithmetic.ll +++ b/llvm/test/CodeGen/Mips/msa/arithmetic.ll @@ -1,726 +1,683 @@ -; RUN: llc -march=mips -mattr=+msa,+fp64 < %s | FileCheck %s -; RUN: llc -march=mipsel -mattr=+msa,+fp64 < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -march=mips -mattr=+msa,+fp64 < %s | FileCheck %s --check-prefixes=ALL,MIPS +; RUN: llc -march=mipsel -mattr=+msa,+fp64 < %s | FileCheck %s --check-prefixes=ALL,MIPSEL define void @add_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: add_v16i8: - +; ALL-LABEL: add_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: addv.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = add <16 x i8> %1, %2 - ; CHECK-DAG: addv.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size add_v16i8 } define void @add_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: add_v8i16: - +; ALL-LABEL: add_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: addv.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = add <8 x i16> %1, %2 - ; CHECK-DAG: addv.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size add_v8i16 } define void @add_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: add_v4i32: - +; ALL-LABEL: add_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: addv.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = add <4 x i32> %1, %2 - ; CHECK-DAG: addv.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size add_v4i32 } define void @add_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: add_v2i64: - +; ALL-LABEL: add_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: addv.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = add <2 x i64> %1, %2 - ; CHECK-DAG: addv.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size add_v2i64 } define void @add_v16i8_i(<16 x i8>* %c, <16 x i8>* %a) nounwind { - ; CHECK: add_v16i8_i: - +; ALL-LABEL: add_v16i8_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($5) +; ALL-NEXT: addvi.b $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = add <16 x i8> %1, - ; CHECK-DAG: addvi.b [[R3:\$w[0-9]+]], [[R1]], 1 + i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> store <16 x i8> %2, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size add_v16i8_i } define void @add_v8i16_i(<8 x i16>* %c, <8 x i16>* %a) nounwind { - ; CHECK: add_v8i16_i: - +; ALL-LABEL: add_v8i16_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($5) +; ALL-NEXT: addvi.h $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = add <8 x i16> %1, - ; CHECK-DAG: addvi.h [[R3:\$w[0-9]+]], [[R1]], 1 + i16 1, i16 1, i16 1, i16 1> store <8 x i16> %2, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size add_v8i16_i } define void @add_v4i32_i(<4 x i32>* %c, <4 x i32>* %a) nounwind { - ; CHECK: add_v4i32_i: - +; ALL-LABEL: add_v4i32_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($5) +; ALL-NEXT: addvi.w $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = add <4 x i32> %1, - ; CHECK-DAG: addvi.w [[R3:\$w[0-9]+]], [[R1]], 1 store <4 x i32> %2, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size add_v4i32_i } define void @add_v2i64_i(<2 x i64>* %c, <2 x i64>* %a) nounwind { - ; CHECK: add_v2i64_i: - +; ALL-LABEL: add_v2i64_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($5) +; ALL-NEXT: addvi.d $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = add <2 x i64> %1, - ; CHECK-DAG: addvi.d [[R3:\$w[0-9]+]], [[R1]], 1 store <2 x i64> %2, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size add_v2i64_i } define void @sub_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: sub_v16i8: - +; ALL-LABEL: sub_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: subv.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = sub <16 x i8> %1, %2 - ; CHECK-DAG: subv.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size sub_v16i8 } define void @sub_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: sub_v8i16: - +; ALL-LABEL: sub_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: subv.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = sub <8 x i16> %1, %2 - ; CHECK-DAG: subv.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size sub_v8i16 } define void @sub_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: sub_v4i32: - +; ALL-LABEL: sub_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: subv.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = sub <4 x i32> %1, %2 - ; CHECK-DAG: subv.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size sub_v4i32 } define void @sub_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: sub_v2i64: - +; ALL-LABEL: sub_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: subv.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = sub <2 x i64> %1, %2 - ; CHECK-DAG: subv.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size sub_v2i64 } define void @sub_v16i8_i(<16 x i8>* %c, <16 x i8>* %a) nounwind { - ; CHECK: sub_v16i8_i: - +; ALL-LABEL: sub_v16i8_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($5) +; ALL-NEXT: subvi.b $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = sub <16 x i8> %1, - ; CHECK-DAG: subvi.b [[R3:\$w[0-9]+]], [[R1]], 1 + i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> store <16 x i8> %2, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size sub_v16i8_i } define void @sub_v8i16_i(<8 x i16>* %c, <8 x i16>* %a) nounwind { - ; CHECK: sub_v8i16_i: - +; ALL-LABEL: sub_v8i16_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($5) +; ALL-NEXT: subvi.h $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = sub <8 x i16> %1, - ; CHECK-DAG: subvi.h [[R3:\$w[0-9]+]], [[R1]], 1 + i16 1, i16 1, i16 1, i16 1> store <8 x i16> %2, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size sub_v8i16_i } define void @sub_v4i32_i(<4 x i32>* %c, <4 x i32>* %a) nounwind { - ; CHECK: sub_v4i32_i: - +; ALL-LABEL: sub_v4i32_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($5) +; ALL-NEXT: subvi.w $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = sub <4 x i32> %1, - ; CHECK-DAG: subvi.w [[R3:\$w[0-9]+]], [[R1]], 1 store <4 x i32> %2, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size sub_v4i32_i } define void @sub_v2i64_i(<2 x i64>* %c, <2 x i64>* %a) nounwind { - ; CHECK: sub_v2i64_i: - +; ALL-LABEL: sub_v2i64_i: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($5) +; ALL-NEXT: subvi.d $w0, $w0, 1 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = sub <2 x i64> %1, - ; CHECK-DAG: subvi.d [[R3:\$w[0-9]+]], [[R1]], 1 store <2 x i64> %2, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size sub_v2i64_i } define void @mul_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: mul_v16i8: - +; ALL-LABEL: mul_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: mulv.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = mul <16 x i8> %1, %2 - ; CHECK-DAG: mulv.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size mul_v16i8 } define void @mul_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: mul_v8i16: - +; ALL-LABEL: mul_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: mulv.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = mul <8 x i16> %1, %2 - ; CHECK-DAG: mulv.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size mul_v8i16 } define void @mul_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: mul_v4i32: - +; ALL-LABEL: mul_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: mulv.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = mul <4 x i32> %1, %2 - ; CHECK-DAG: mulv.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size mul_v4i32 } define void @mul_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: mul_v2i64: - +; ALL-LABEL: mul_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: mulv.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = mul <2 x i64> %1, %2 - ; CHECK-DAG: mulv.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size mul_v2i64 } define void @maddv_v16i8(<16 x i8>* %d, <16 x i8>* %a, <16 x i8>* %b, - <16 x i8>* %c) nounwind { - ; CHECK: maddv_v16i8: - +; ALL-LABEL: maddv_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($7) +; ALL-NEXT: ld.b $w1, 0($6) +; ALL-NEXT: ld.b $w2, 0($5) +; ALL-NEXT: maddv.b $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w2, 0($4) + <16 x i8>* %c) nounwind { %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = load <16 x i8>, <16 x i8>* %c - ; CHECK-DAG: ld.b [[R3:\$w[0-9]+]], 0($7) %4 = mul <16 x i8> %2, %3 %5 = add <16 x i8> %4, %1 - ; CHECK-DAG: maddv.b [[R1]], [[R2]], [[R3]] store <16 x i8> %5, <16 x i8>* %d - ; CHECK-DAG: st.b [[R1]], 0($4) - ret void - ; CHECK: .size maddv_v16i8 } define void @maddv_v8i16(<8 x i16>* %d, <8 x i16>* %a, <8 x i16>* %b, - <8 x i16>* %c) nounwind { - ; CHECK: maddv_v8i16: - +; ALL-LABEL: maddv_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($7) +; ALL-NEXT: ld.h $w1, 0($6) +; ALL-NEXT: ld.h $w2, 0($5) +; ALL-NEXT: maddv.h $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w2, 0($4) + <8 x i16>* %c) nounwind { %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = load <8 x i16>, <8 x i16>* %c - ; CHECK-DAG: ld.h [[R3:\$w[0-9]+]], 0($7) %4 = mul <8 x i16> %2, %3 %5 = add <8 x i16> %4, %1 - ; CHECK-DAG: maddv.h [[R1]], [[R2]], [[R3]] store <8 x i16> %5, <8 x i16>* %d - ; CHECK-DAG: st.h [[R1]], 0($4) - ret void - ; CHECK: .size maddv_v8i16 } define void @maddv_v4i32(<4 x i32>* %d, <4 x i32>* %a, <4 x i32>* %b, - <4 x i32>* %c) nounwind { - ; CHECK: maddv_v4i32: - +; ALL-LABEL: maddv_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($7) +; ALL-NEXT: ld.w $w1, 0($6) +; ALL-NEXT: ld.w $w2, 0($5) +; ALL-NEXT: maddv.w $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w2, 0($4) + <4 x i32>* %c) nounwind { %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = load <4 x i32>, <4 x i32>* %c - ; CHECK-DAG: ld.w [[R3:\$w[0-9]+]], 0($7) %4 = mul <4 x i32> %2, %3 %5 = add <4 x i32> %4, %1 - ; CHECK-DAG: maddv.w [[R1]], [[R2]], [[R3]] store <4 x i32> %5, <4 x i32>* %d - ; CHECK-DAG: st.w [[R1]], 0($4) - ret void - ; CHECK: .size maddv_v4i32 } define void @maddv_v2i64(<2 x i64>* %d, <2 x i64>* %a, <2 x i64>* %b, - <2 x i64>* %c) nounwind { - ; CHECK: maddv_v2i64: - +; ALL-LABEL: maddv_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($7) +; ALL-NEXT: ld.d $w1, 0($6) +; ALL-NEXT: ld.d $w2, 0($5) +; ALL-NEXT: maddv.d $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w2, 0($4) + <2 x i64>* %c) nounwind { %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = load <2 x i64>, <2 x i64>* %c - ; CHECK-DAG: ld.d [[R3:\$w[0-9]+]], 0($7) %4 = mul <2 x i64> %2, %3 %5 = add <2 x i64> %4, %1 - ; CHECK-DAG: maddv.d [[R1]], [[R2]], [[R3]] store <2 x i64> %5, <2 x i64>* %d - ; CHECK-DAG: st.d [[R1]], 0($4) - ret void - ; CHECK: .size maddv_v2i64 } define void @msubv_v16i8(<16 x i8>* %d, <16 x i8>* %a, <16 x i8>* %b, - <16 x i8>* %c) nounwind { - ; CHECK: msubv_v16i8: - +; ALL-LABEL: msubv_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($7) +; ALL-NEXT: ld.b $w1, 0($6) +; ALL-NEXT: ld.b $w2, 0($5) +; ALL-NEXT: msubv.b $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w2, 0($4) + <16 x i8>* %c) nounwind { %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = load <16 x i8>, <16 x i8>* %c - ; CHECK-DAG: ld.b [[R3:\$w[0-9]+]], 0($7) %4 = mul <16 x i8> %2, %3 %5 = sub <16 x i8> %1, %4 - ; CHECK-DAG: msubv.b [[R1]], [[R2]], [[R3]] store <16 x i8> %5, <16 x i8>* %d - ; CHECK-DAG: st.b [[R1]], 0($4) - ret void - ; CHECK: .size msubv_v16i8 } define void @msubv_v8i16(<8 x i16>* %d, <8 x i16>* %a, <8 x i16>* %b, - <8 x i16>* %c) nounwind { - ; CHECK: msubv_v8i16: - +; ALL-LABEL: msubv_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($7) +; ALL-NEXT: ld.h $w1, 0($6) +; ALL-NEXT: ld.h $w2, 0($5) +; ALL-NEXT: msubv.h $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w2, 0($4) + <8 x i16>* %c) nounwind { %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = load <8 x i16>, <8 x i16>* %c - ; CHECK-DAG: ld.h [[R3:\$w[0-9]+]], 0($7) %4 = mul <8 x i16> %2, %3 %5 = sub <8 x i16> %1, %4 - ; CHECK-DAG: msubv.h [[R1]], [[R2]], [[R3]] store <8 x i16> %5, <8 x i16>* %d - ; CHECK-DAG: st.h [[R1]], 0($4) - ret void - ; CHECK: .size msubv_v8i16 } define void @msubv_v4i32(<4 x i32>* %d, <4 x i32>* %a, <4 x i32>* %b, - <4 x i32>* %c) nounwind { - ; CHECK: msubv_v4i32: - +; ALL-LABEL: msubv_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($7) +; ALL-NEXT: ld.w $w1, 0($6) +; ALL-NEXT: ld.w $w2, 0($5) +; ALL-NEXT: msubv.w $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w2, 0($4) + <4 x i32>* %c) nounwind { %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = load <4 x i32>, <4 x i32>* %c - ; CHECK-DAG: ld.w [[R3:\$w[0-9]+]], 0($7) %4 = mul <4 x i32> %2, %3 %5 = sub <4 x i32> %1, %4 - ; CHECK-DAG: msubv.w [[R1]], [[R2]], [[R3]] store <4 x i32> %5, <4 x i32>* %d - ; CHECK-DAG: st.w [[R1]], 0($4) - ret void - ; CHECK: .size msubv_v4i32 } define void @msubv_v2i64(<2 x i64>* %d, <2 x i64>* %a, <2 x i64>* %b, - <2 x i64>* %c) nounwind { - ; CHECK: msubv_v2i64: - +; ALL-LABEL: msubv_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($7) +; ALL-NEXT: ld.d $w1, 0($6) +; ALL-NEXT: ld.d $w2, 0($5) +; ALL-NEXT: msubv.d $w2, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w2, 0($4) + <2 x i64>* %c) nounwind { %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = load <2 x i64>, <2 x i64>* %c - ; CHECK-DAG: ld.d [[R3:\$w[0-9]+]], 0($7) %4 = mul <2 x i64> %2, %3 %5 = sub <2 x i64> %1, %4 - ; CHECK-DAG: msubv.d [[R1]], [[R2]], [[R3]] store <2 x i64> %5, <2 x i64>* %d - ; CHECK-DAG: st.d [[R1]], 0($4) - ret void - ; CHECK: .size msubv_v2i64 } define void @div_s_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: div_s_v16i8: - +; ALL-LABEL: div_s_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: div_s.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = sdiv <16 x i8> %1, %2 - ; CHECK-DAG: div_s.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size div_s_v16i8 } define void @div_s_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: div_s_v8i16: - +; ALL-LABEL: div_s_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: div_s.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = sdiv <8 x i16> %1, %2 - ; CHECK-DAG: div_s.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size div_s_v8i16 } define void @div_s_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: div_s_v4i32: - +; ALL-LABEL: div_s_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: div_s.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = sdiv <4 x i32> %1, %2 - ; CHECK-DAG: div_s.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size div_s_v4i32 } define void @div_s_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: div_s_v2i64: - +; ALL-LABEL: div_s_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: div_s.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = sdiv <2 x i64> %1, %2 - ; CHECK-DAG: div_s.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size div_s_v2i64 } define void @div_u_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: div_u_v16i8: - +; ALL-LABEL: div_u_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: div_u.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = udiv <16 x i8> %1, %2 - ; CHECK-DAG: div_u.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size div_u_v16i8 } define void @div_u_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: div_u_v8i16: - +; ALL-LABEL: div_u_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: div_u.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = udiv <8 x i16> %1, %2 - ; CHECK-DAG: div_u.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size div_u_v8i16 } define void @div_u_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: div_u_v4i32: - +; ALL-LABEL: div_u_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: div_u.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = udiv <4 x i32> %1, %2 - ; CHECK-DAG: div_u.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size div_u_v4i32 } define void @div_u_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: div_u_v2i64: - +; ALL-LABEL: div_u_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: div_u.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = udiv <2 x i64> %1, %2 - ; CHECK-DAG: div_u.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size div_u_v2i64 } define void @mod_s_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: mod_s_v16i8: - +; ALL-LABEL: mod_s_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: mod_s.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = srem <16 x i8> %1, %2 - ; CHECK-DAG: mod_s.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size mod_s_v16i8 } define void @mod_s_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: mod_s_v8i16: - +; ALL-LABEL: mod_s_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: mod_s.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = srem <8 x i16> %1, %2 - ; CHECK-DAG: mod_s.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size mod_s_v8i16 } define void @mod_s_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: mod_s_v4i32: - +; ALL-LABEL: mod_s_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: mod_s.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = srem <4 x i32> %1, %2 - ; CHECK-DAG: mod_s.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size mod_s_v4i32 } define void @mod_s_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: mod_s_v2i64: - +; ALL-LABEL: mod_s_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: mod_s.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = srem <2 x i64> %1, %2 - ; CHECK-DAG: mod_s.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size mod_s_v2i64 } define void @mod_u_v16i8(<16 x i8>* %c, <16 x i8>* %a, <16 x i8>* %b) nounwind { - ; CHECK: mod_u_v16i8: - +; ALL-LABEL: mod_u_v16i8: +; ALL: # %bb.0: +; ALL-NEXT: ld.b $w0, 0($6) +; ALL-NEXT: ld.b $w1, 0($5) +; ALL-NEXT: mod_u.b $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($4) %1 = load <16 x i8>, <16 x i8>* %a - ; CHECK-DAG: ld.b [[R1:\$w[0-9]+]], 0($5) %2 = load <16 x i8>, <16 x i8>* %b - ; CHECK-DAG: ld.b [[R2:\$w[0-9]+]], 0($6) %3 = urem <16 x i8> %1, %2 - ; CHECK-DAG: mod_u.b [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <16 x i8> %3, <16 x i8>* %c - ; CHECK-DAG: st.b [[R3]], 0($4) - ret void - ; CHECK: .size mod_u_v16i8 } define void @mod_u_v8i16(<8 x i16>* %c, <8 x i16>* %a, <8 x i16>* %b) nounwind { - ; CHECK: mod_u_v8i16: - +; ALL-LABEL: mod_u_v8i16: +; ALL: # %bb.0: +; ALL-NEXT: ld.h $w0, 0($6) +; ALL-NEXT: ld.h $w1, 0($5) +; ALL-NEXT: mod_u.h $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($4) %1 = load <8 x i16>, <8 x i16>* %a - ; CHECK-DAG: ld.h [[R1:\$w[0-9]+]], 0($5) %2 = load <8 x i16>, <8 x i16>* %b - ; CHECK-DAG: ld.h [[R2:\$w[0-9]+]], 0($6) %3 = urem <8 x i16> %1, %2 - ; CHECK-DAG: mod_u.h [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <8 x i16> %3, <8 x i16>* %c - ; CHECK-DAG: st.h [[R3]], 0($4) - ret void - ; CHECK: .size mod_u_v8i16 } define void @mod_u_v4i32(<4 x i32>* %c, <4 x i32>* %a, <4 x i32>* %b) nounwind { - ; CHECK: mod_u_v4i32: - +; ALL-LABEL: mod_u_v4i32: +; ALL: # %bb.0: +; ALL-NEXT: ld.w $w0, 0($6) +; ALL-NEXT: ld.w $w1, 0($5) +; ALL-NEXT: mod_u.w $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($4) %1 = load <4 x i32>, <4 x i32>* %a - ; CHECK-DAG: ld.w [[R1:\$w[0-9]+]], 0($5) %2 = load <4 x i32>, <4 x i32>* %b - ; CHECK-DAG: ld.w [[R2:\$w[0-9]+]], 0($6) %3 = urem <4 x i32> %1, %2 - ; CHECK-DAG: mod_u.w [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <4 x i32> %3, <4 x i32>* %c - ; CHECK-DAG: st.w [[R3]], 0($4) - ret void - ; CHECK: .size mod_u_v4i32 } define void @mod_u_v2i64(<2 x i64>* %c, <2 x i64>* %a, <2 x i64>* %b) nounwind { - ; CHECK: mod_u_v2i64: - +; ALL-LABEL: mod_u_v2i64: +; ALL: # %bb.0: +; ALL-NEXT: ld.d $w0, 0($6) +; ALL-NEXT: ld.d $w1, 0($5) +; ALL-NEXT: mod_u.d $w0, $w1, $w0 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($4) %1 = load <2 x i64>, <2 x i64>* %a - ; CHECK-DAG: ld.d [[R1:\$w[0-9]+]], 0($5) %2 = load <2 x i64>, <2 x i64>* %b - ; CHECK-DAG: ld.d [[R2:\$w[0-9]+]], 0($6) %3 = urem <2 x i64> %1, %2 - ; CHECK-DAG: mod_u.d [[R3:\$w[0-9]+]], [[R1]], [[R2]] store <2 x i64> %3, <2 x i64>* %c - ; CHECK-DAG: st.d [[R3]], 0($4) - ret void - ; CHECK: .size mod_u_v2i64 } From a8a470c45b8702f8d41ba59d76600377e23bc5f2 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 18:08:17 +0000 Subject: [PATCH 0059/1176] [NFC][Mips] Autogenerate msa/i5-s.ll test Being affected by (sub %x, C) -> add %X, (sub 0, C) 'for vectors' patch. llvm-svn: 361523 --- llvm/test/CodeGen/Mips/msa/i5-s.ll | 72 ++++++++++++++++++------------ 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/llvm/test/CodeGen/Mips/msa/i5-s.ll b/llvm/test/CodeGen/Mips/msa/i5-s.ll index db331b1476ce5..ce5e4eb091b11 100644 --- a/llvm/test/CodeGen/Mips/msa/i5-s.ll +++ b/llvm/test/CodeGen/Mips/msa/i5-s.ll @@ -1,13 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -march=mips -mattr=+msa,+fp64 < %s | FileCheck %s --check-prefixes=ALL,MIPS +; RUN: llc -march=mipsel -mattr=+msa,+fp64 < %s | FileCheck %s --check-prefixes=ALL,MIPSEL + ; Test the MSA intrinsics that are encoded with the I5 instruction format. ; There are lots of these so this covers those beginning with 's' -; RUN: llc -march=mips -mattr=+msa,+fp64 < %s | FileCheck %s -; RUN: llc -march=mipsel -mattr=+msa,+fp64 < %s | FileCheck %s - @llvm_mips_subvi_b_ARG1 = global <16 x i8> , align 16 @llvm_mips_subvi_b_RES = global <16 x i8> , align 16 define void @llvm_mips_subvi_b_test() nounwind { +; ALL-LABEL: llvm_mips_subvi_b_test: +; ALL: # %bb.0: # %entry +; ALL-NEXT: lui $1, %hi(llvm_mips_subvi_b_RES) +; ALL-NEXT: addiu $1, $1, %lo(llvm_mips_subvi_b_RES) +; ALL-NEXT: lui $2, %hi(llvm_mips_subvi_b_ARG1) +; ALL-NEXT: addiu $2, $2, %lo(llvm_mips_subvi_b_ARG1) +; ALL-NEXT: ld.b $w0, 0($2) +; ALL-NEXT: subvi.b $w0, $w0, 14 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.b $w0, 0($1) entry: %0 = load <16 x i8>, <16 x i8>* @llvm_mips_subvi_b_ARG1 %1 = tail call <16 x i8> @llvm.mips.subvi.b(<16 x i8> %0, i32 14) @@ -17,16 +28,20 @@ entry: declare <16 x i8> @llvm.mips.subvi.b(<16 x i8>, i32) nounwind -; CHECK: llvm_mips_subvi_b_test: -; CHECK: ld.b -; CHECK: subvi.b -; CHECK: st.b -; CHECK: .size llvm_mips_subvi_b_test -; @llvm_mips_subvi_h_ARG1 = global <8 x i16> , align 16 @llvm_mips_subvi_h_RES = global <8 x i16> , align 16 define void @llvm_mips_subvi_h_test() nounwind { +; ALL-LABEL: llvm_mips_subvi_h_test: +; ALL: # %bb.0: # %entry +; ALL-NEXT: lui $1, %hi(llvm_mips_subvi_h_RES) +; ALL-NEXT: addiu $1, $1, %lo(llvm_mips_subvi_h_RES) +; ALL-NEXT: lui $2, %hi(llvm_mips_subvi_h_ARG1) +; ALL-NEXT: addiu $2, $2, %lo(llvm_mips_subvi_h_ARG1) +; ALL-NEXT: ld.h $w0, 0($2) +; ALL-NEXT: subvi.h $w0, $w0, 14 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.h $w0, 0($1) entry: %0 = load <8 x i16>, <8 x i16>* @llvm_mips_subvi_h_ARG1 %1 = tail call <8 x i16> @llvm.mips.subvi.h(<8 x i16> %0, i32 14) @@ -36,16 +51,20 @@ entry: declare <8 x i16> @llvm.mips.subvi.h(<8 x i16>, i32) nounwind -; CHECK: llvm_mips_subvi_h_test: -; CHECK: ld.h -; CHECK: subvi.h -; CHECK: st.h -; CHECK: .size llvm_mips_subvi_h_test -; @llvm_mips_subvi_w_ARG1 = global <4 x i32> , align 16 @llvm_mips_subvi_w_RES = global <4 x i32> , align 16 define void @llvm_mips_subvi_w_test() nounwind { +; ALL-LABEL: llvm_mips_subvi_w_test: +; ALL: # %bb.0: # %entry +; ALL-NEXT: lui $1, %hi(llvm_mips_subvi_w_RES) +; ALL-NEXT: addiu $1, $1, %lo(llvm_mips_subvi_w_RES) +; ALL-NEXT: lui $2, %hi(llvm_mips_subvi_w_ARG1) +; ALL-NEXT: addiu $2, $2, %lo(llvm_mips_subvi_w_ARG1) +; ALL-NEXT: ld.w $w0, 0($2) +; ALL-NEXT: subvi.w $w0, $w0, 14 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.w $w0, 0($1) entry: %0 = load <4 x i32>, <4 x i32>* @llvm_mips_subvi_w_ARG1 %1 = tail call <4 x i32> @llvm.mips.subvi.w(<4 x i32> %0, i32 14) @@ -55,16 +74,20 @@ entry: declare <4 x i32> @llvm.mips.subvi.w(<4 x i32>, i32) nounwind -; CHECK: llvm_mips_subvi_w_test: -; CHECK: ld.w -; CHECK: subvi.w -; CHECK: st.w -; CHECK: .size llvm_mips_subvi_w_test -; @llvm_mips_subvi_d_ARG1 = global <2 x i64> , align 16 @llvm_mips_subvi_d_RES = global <2 x i64> , align 16 define void @llvm_mips_subvi_d_test() nounwind { +; ALL-LABEL: llvm_mips_subvi_d_test: +; ALL: # %bb.0: # %entry +; ALL-NEXT: lui $1, %hi(llvm_mips_subvi_d_RES) +; ALL-NEXT: addiu $1, $1, %lo(llvm_mips_subvi_d_RES) +; ALL-NEXT: lui $2, %hi(llvm_mips_subvi_d_ARG1) +; ALL-NEXT: addiu $2, $2, %lo(llvm_mips_subvi_d_ARG1) +; ALL-NEXT: ld.d $w0, 0($2) +; ALL-NEXT: subvi.d $w0, $w0, 14 +; ALL-NEXT: jr $ra +; ALL-NEXT: st.d $w0, 0($1) entry: %0 = load <2 x i64>, <2 x i64>* @llvm_mips_subvi_d_ARG1 %1 = tail call <2 x i64> @llvm.mips.subvi.d(<2 x i64> %0, i32 14) @@ -73,10 +96,3 @@ entry: } declare <2 x i64> @llvm.mips.subvi.d(<2 x i64>, i32) nounwind - -; CHECK: llvm_mips_subvi_d_test: -; CHECK: ld.d -; CHECK: subvi.d -; CHECK: st.d -; CHECK: .size llvm_mips_subvi_d_test -; From c8364ef567d3168842920b5d39c02fca1742ecff Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 18:08:21 +0000 Subject: [PATCH 0060/1176] [NFC][PPC] Autogenerate vec_add_sub_doubleword.ll test Being affected by (sub %x, C) -> add %X, (sub 0, C) 'for vectors' patch. llvm-svn: 361524 --- .../CodeGen/PowerPC/vec_add_sub_doubleword.ll | 140 ++++++++++++------ 1 file changed, 98 insertions(+), 42 deletions(-) diff --git a/llvm/test/CodeGen/PowerPC/vec_add_sub_doubleword.ll b/llvm/test/CodeGen/PowerPC/vec_add_sub_doubleword.ll index 2c3bee14ccdbd..62f17acb8a749 100644 --- a/llvm/test/CodeGen/PowerPC/vec_add_sub_doubleword.ll +++ b/llvm/test/CodeGen/PowerPC/vec_add_sub_doubleword.ll @@ -1,62 +1,118 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s --check-prefixes=ALL,VSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s --check-prefixes=ALL,NOVSX + ; Check VMX 64-bit integer operations -; -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s define <2 x i64> @test_add(<2 x i64> %x, <2 x i64> %y) nounwind { - %result = add <2 x i64> %x, %y - ret <2 x i64> %result -; CHECK: vaddudm 2, 2, 3 +; ALL-LABEL: test_add: +; ALL: # %bb.0: +; ALL-NEXT: vaddudm 2, 2, 3 +; ALL-NEXT: blr + %result = add <2 x i64> %x, %y + ret <2 x i64> %result } define <2 x i64> @increment_by_one(<2 x i64> %x) nounwind { - %result = add <2 x i64> %x, - ret <2 x i64> %result -; CHECK: vaddudm 2, 2, 3 +; VSX-LABEL: increment_by_one: +; VSX: # %bb.0: +; VSX-NEXT: addis 3, 2, .LCPI1_0@toc@ha +; VSX-NEXT: addi 3, 3, .LCPI1_0@toc@l +; VSX-NEXT: lxvd2x 35, 0, 3 +; VSX-NEXT: vaddudm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: increment_by_one: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addis 3, 2, .LCPI1_0@toc@ha +; NOVSX-NEXT: addi 3, 3, .LCPI1_0@toc@l +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vaddudm 2, 2, 3 +; NOVSX-NEXT: blr + %result = add <2 x i64> %x, + ret <2 x i64> %result } define <2 x i64> @increment_by_val(<2 x i64> %x, i64 %val) nounwind { - %tmpvec = insertelement <2 x i64> , i64 %val, i32 0 - %tmpvec2 = insertelement <2 x i64> %tmpvec, i64 %val, i32 1 - %result = add <2 x i64> %x, %tmpvec2 - ret <2 x i64> %result -; CHECK: vaddudm 2, 2, 3 -; FIXME: This is currently generating the following instruction sequence +; VSX-LABEL: increment_by_val: +; VSX: # %bb.0: +; VSX-NEXT: mtvsrd 0, 5 +; VSX-NEXT: xxspltd 35, 0, 0 +; VSX-NEXT: vaddudm 2, 2, 3 +; VSX-NEXT: blr ; -; std 5, -8(1) -; std 5, -16(1) -; addi 3, 1, -16 -; ori 2, 2, 0 -; lxvd2x 35, 0, 3 -; vaddudm 2, 2, 3 -; blr -; -; This will almost certainly cause a load-hit-store hazard. -; Since val is a value parameter, it should not need to be -; saved onto the stack at all (unless we're using this to set -; up the vector register). Instead, it would be better to splat -; the value into a vector register. +; NOVSX-LABEL: increment_by_val: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addi 3, 1, -16 +; NOVSX-NEXT: std 5, -8(1) +; NOVSX-NEXT: std 5, -16(1) +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vaddudm 2, 2, 3 +; NOVSX-NEXT: blr + %tmpvec = insertelement <2 x i64> , i64 %val, i32 0 + %tmpvec2 = insertelement <2 x i64> %tmpvec, i64 %val, i32 1 + %result = add <2 x i64> %x, %tmpvec2 + ret <2 x i64> %result +; FIXME: This is currently generating the following instruction sequence +; std 5, -8(1) +; std 5, -16(1) +; addi 3, 1, -16 +; ori 2, 2, 0 +; lxvd2x 35, 0, 3 +; vaddudm 2, 2, 3 +; blr +; This will almost certainly cause a load-hit-store hazard. +; Since val is a value parameter, it should not need to be +; saved onto the stack at all (unless we're using this to set +; up the vector register). Instead, it would be better to splat +; the value into a vector register. } define <2 x i64> @test_sub(<2 x i64> %x, <2 x i64> %y) nounwind { - %result = sub <2 x i64> %x, %y - ret <2 x i64> %result -; CHECK: vsubudm 2, 2, 3 +; ALL-LABEL: test_sub: +; ALL: # %bb.0: +; ALL-NEXT: vsubudm 2, 2, 3 +; ALL-NEXT: blr + %result = sub <2 x i64> %x, %y + ret <2 x i64> %result } define <2 x i64> @decrement_by_one(<2 x i64> %x) nounwind { - %result = sub <2 x i64> %x, - ret <2 x i64> %result -; CHECK: vsubudm 2, 2, 3 +; VSX-LABEL: decrement_by_one: +; VSX: # %bb.0: +; VSX-NEXT: vspltisb 3, -1 +; VSX-NEXT: vsubudm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: decrement_by_one: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addis 3, 2, .LCPI4_0@toc@ha +; NOVSX-NEXT: addi 3, 3, .LCPI4_0@toc@l +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vsubudm 2, 2, 3 +; NOVSX-NEXT: blr + %result = sub <2 x i64> %x, + ret <2 x i64> %result } define <2 x i64> @decrement_by_val(<2 x i64> %x, i64 %val) nounwind { - %tmpvec = insertelement <2 x i64> , i64 %val, i32 0 - %tmpvec2 = insertelement <2 x i64> %tmpvec, i64 %val, i32 1 - %result = sub <2 x i64> %x, %tmpvec2 - ret <2 x i64> %result -; CHECK: vsubudm 2, 2, 3 +; VSX-LABEL: decrement_by_val: +; VSX: # %bb.0: +; VSX-NEXT: mtvsrd 0, 5 +; VSX-NEXT: xxspltd 35, 0, 0 +; VSX-NEXT: vsubudm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: decrement_by_val: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addi 3, 1, -16 +; NOVSX-NEXT: std 5, -8(1) +; NOVSX-NEXT: std 5, -16(1) +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vsubudm 2, 2, 3 +; NOVSX-NEXT: blr + %tmpvec = insertelement <2 x i64> , i64 %val, i32 0 + %tmpvec2 = insertelement <2 x i64> %tmpvec, i64 %val, i32 1 + %result = sub <2 x i64> %x, %tmpvec2 + ret <2 x i64> %result } - - - From 702a152e6ad0846c2168d88074c056d37e8a5122 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 18:08:26 +0000 Subject: [PATCH 0061/1176] [NFC][PPC] Autogenerate vec_add_sub_quadword.ll test Being affected by (sub %x, C) -> add %X, (sub 0, C) 'for vectors' patch. llvm-svn: 361525 --- .../CodeGen/PowerPC/vec_add_sub_quadword.ll | 230 +++++++++++------- 1 file changed, 140 insertions(+), 90 deletions(-) diff --git a/llvm/test/CodeGen/PowerPC/vec_add_sub_quadword.ll b/llvm/test/CodeGen/PowerPC/vec_add_sub_quadword.ll index 8f3864ff26836..8ddf0ad9b50d9 100644 --- a/llvm/test/CodeGen/PowerPC/vec_add_sub_quadword.ll +++ b/llvm/test/CodeGen/PowerPC/vec_add_sub_quadword.ll @@ -1,137 +1,187 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s --check-prefixes=ALL,VSX +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s --check-prefixes=ALL,NOVSX + ; Check VMX 128-bit integer operations -; -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 < %s | FileCheck %s -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -mattr=-vsx < %s | FileCheck %s define <1 x i128> @out_of_bounds_insertelement(<1 x i128> %x, i128 %val) nounwind { - %tmpvec = insertelement <1 x i128> , i128 %val, i32 1 - %result = add <1 x i128> %x, %tmpvec - ret <1 x i128> %result -; CHECK-LABEL: @out_of_bounds_insertelement -; CHECK: # %bb.0: -; CHECK-NEXT: blr +; ALL-LABEL: out_of_bounds_insertelement: +; ALL: # %bb.0: +; ALL-NEXT: blr + %tmpvec = insertelement <1 x i128> , i128 %val, i32 1 + %result = add <1 x i128> %x, %tmpvec + ret <1 x i128> %result } define <1 x i128> @test_add(<1 x i128> %x, <1 x i128> %y) nounwind { - %result = add <1 x i128> %x, %y - ret <1 x i128> %result -; CHECK-LABEL: @test_add -; CHECK: vadduqm 2, 2, 3 +; ALL-LABEL: test_add: +; ALL: # %bb.0: +; ALL-NEXT: vadduqm 2, 2, 3 +; ALL-NEXT: blr + %result = add <1 x i128> %x, %y + ret <1 x i128> %result } define <1 x i128> @increment_by_one(<1 x i128> %x) nounwind { - %result = add <1 x i128> %x, - ret <1 x i128> %result -; CHECK-LABEL: @increment_by_one -; CHECK: vadduqm 2, 2, 3 +; VSX-LABEL: increment_by_one: +; VSX: # %bb.0: +; VSX-NEXT: addis 3, 2, .LCPI2_0@toc@ha +; VSX-NEXT: addi 3, 3, .LCPI2_0@toc@l +; VSX-NEXT: lxvd2x 35, 0, 3 +; VSX-NEXT: vadduqm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: increment_by_one: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addis 3, 2, .LCPI2_0@toc@ha +; NOVSX-NEXT: addi 3, 3, .LCPI2_0@toc@l +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vadduqm 2, 2, 3 +; NOVSX-NEXT: blr + %result = add <1 x i128> %x, + ret <1 x i128> %result } define <1 x i128> @increment_by_val(<1 x i128> %x, i128 %val) nounwind { - %tmpvec = insertelement <1 x i128> , i128 %val, i32 0 - %result = add <1 x i128> %x, %tmpvec - ret <1 x i128> %result -; CHECK-LABEL: @increment_by_val -; CHECK: vadduqm 2, 2, 3 +; VSX-LABEL: increment_by_val: +; VSX: # %bb.0: +; VSX-NEXT: mtvsrd 0, 6 +; VSX-NEXT: mtvsrd 1, 5 +; VSX-NEXT: xxmrghd 35, 1, 0 +; VSX-NEXT: vadduqm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: increment_by_val: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addi 3, 1, -16 +; NOVSX-NEXT: std 6, -8(1) +; NOVSX-NEXT: std 5, -16(1) +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vadduqm 2, 2, 3 +; NOVSX-NEXT: blr + %tmpvec = insertelement <1 x i128> , i128 %val, i32 0 + %result = add <1 x i128> %x, %tmpvec + ret <1 x i128> %result } define <1 x i128> @test_sub(<1 x i128> %x, <1 x i128> %y) nounwind { - %result = sub <1 x i128> %x, %y - ret <1 x i128> %result -; CHECK-LABEL: @test_sub -; CHECK: vsubuqm 2, 2, 3 +; ALL-LABEL: test_sub: +; ALL: # %bb.0: +; ALL-NEXT: vsubuqm 2, 2, 3 +; ALL-NEXT: blr + %result = sub <1 x i128> %x, %y + ret <1 x i128> %result } define <1 x i128> @decrement_by_one(<1 x i128> %x) nounwind { - %result = sub <1 x i128> %x, - ret <1 x i128> %result -; CHECK-LABEL: @decrement_by_one -; CHECK: vsubuqm 2, 2, 3 +; VSX-LABEL: decrement_by_one: +; VSX: # %bb.0: +; VSX-NEXT: addis 3, 2, .LCPI5_0@toc@ha +; VSX-NEXT: addi 3, 3, .LCPI5_0@toc@l +; VSX-NEXT: lxvd2x 35, 0, 3 +; VSX-NEXT: vsubuqm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: decrement_by_one: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addis 3, 2, .LCPI5_0@toc@ha +; NOVSX-NEXT: addi 3, 3, .LCPI5_0@toc@l +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vsubuqm 2, 2, 3 +; NOVSX-NEXT: blr + %result = sub <1 x i128> %x, + ret <1 x i128> %result } define <1 x i128> @decrement_by_val(<1 x i128> %x, i128 %val) nounwind { - %tmpvec = insertelement <1 x i128> , i128 %val, i32 0 - %result = sub <1 x i128> %x, %tmpvec - ret <1 x i128> %result -; CHECK-LABEL: @decrement_by_val -; CHECK: vsubuqm 2, 2, 3 +; VSX-LABEL: decrement_by_val: +; VSX: # %bb.0: +; VSX-NEXT: mtvsrd 0, 6 +; VSX-NEXT: mtvsrd 1, 5 +; VSX-NEXT: xxmrghd 35, 1, 0 +; VSX-NEXT: vsubuqm 2, 2, 3 +; VSX-NEXT: blr +; +; NOVSX-LABEL: decrement_by_val: +; NOVSX: # %bb.0: +; NOVSX-NEXT: addi 3, 1, -16 +; NOVSX-NEXT: std 6, -8(1) +; NOVSX-NEXT: std 5, -16(1) +; NOVSX-NEXT: lvx 3, 0, 3 +; NOVSX-NEXT: vsubuqm 2, 2, 3 +; NOVSX-NEXT: blr + %tmpvec = insertelement <1 x i128> , i128 %val, i32 0 + %result = sub <1 x i128> %x, %tmpvec + ret <1 x i128> %result } -declare <1 x i128> @llvm.ppc.altivec.vaddeuqm(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind readnone -declare <1 x i128> @llvm.ppc.altivec.vaddcuq(<1 x i128> %x, - <1 x i128> %y) nounwind readnone -declare <1 x i128> @llvm.ppc.altivec.vaddecuq(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind readnone -declare <1 x i128> @llvm.ppc.altivec.vsubeuqm(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind readnone -declare <1 x i128> @llvm.ppc.altivec.vsubcuq(<1 x i128> %x, - <1 x i128> %y) nounwind readnone -declare <1 x i128> @llvm.ppc.altivec.vsubecuq(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind readnone +declare <1 x i128> @llvm.ppc.altivec.vaddeuqm(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind readnone +declare <1 x i128> @llvm.ppc.altivec.vaddcuq(<1 x i128> %x, <1 x i128> %y) nounwind readnone +declare <1 x i128> @llvm.ppc.altivec.vaddecuq(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind readnone +declare <1 x i128> @llvm.ppc.altivec.vsubeuqm(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind readnone +declare <1 x i128> @llvm.ppc.altivec.vsubcuq(<1 x i128> %x, <1 x i128> %y) nounwind readnone +declare <1 x i128> @llvm.ppc.altivec.vsubecuq(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind readnone -define <1 x i128> @test_vaddeuqm(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind { +define <1 x i128> @test_vaddeuqm(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind { +; ALL-LABEL: test_vaddeuqm: +; ALL: # %bb.0: +; ALL-NEXT: vaddeuqm 2, 2, 3, 4 +; ALL-NEXT: blr %tmp = tail call <1 x i128> @llvm.ppc.altivec.vaddeuqm(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) + <1 x i128> %y, + <1 x i128> %z) ret <1 x i128> %tmp -; CHECK-LABEL: @test_vaddeuqm -; CHECK: vaddeuqm 2, 2, 3, 4 } -define <1 x i128> @test_vaddcuq(<1 x i128> %x, - <1 x i128> %y) nounwind { +define <1 x i128> @test_vaddcuq(<1 x i128> %x, <1 x i128> %y) nounwind { +; ALL-LABEL: test_vaddcuq: +; ALL: # %bb.0: +; ALL-NEXT: vaddcuq 2, 2, 3 +; ALL-NEXT: blr %tmp = tail call <1 x i128> @llvm.ppc.altivec.vaddcuq(<1 x i128> %x, - <1 x i128> %y) + <1 x i128> %y) ret <1 x i128> %tmp -; CHECK-LABEL: @test_vaddcuq -; CHECK: vaddcuq 2, 2, 3 } -define <1 x i128> @test_vaddecuq(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind { +define <1 x i128> @test_vaddecuq(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind { +; ALL-LABEL: test_vaddecuq: +; ALL: # %bb.0: +; ALL-NEXT: vaddecuq 2, 2, 3, 4 +; ALL-NEXT: blr %tmp = tail call <1 x i128> @llvm.ppc.altivec.vaddecuq(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) + <1 x i128> %y, + <1 x i128> %z) ret <1 x i128> %tmp -; CHECK-LABEL: @test_vaddecuq -; CHECK: vaddecuq 2, 2, 3, 4 } -define <1 x i128> @test_vsubeuqm(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind { +define <1 x i128> @test_vsubeuqm(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind { +; ALL-LABEL: test_vsubeuqm: +; ALL: # %bb.0: +; ALL-NEXT: vsubeuqm 2, 2, 3, 4 +; ALL-NEXT: blr %tmp = tail call <1 x i128> @llvm.ppc.altivec.vsubeuqm(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) + <1 x i128> %y, + <1 x i128> %z) ret <1 x i128> %tmp -; CHECK-LABEL: test_vsubeuqm -; CHECK: vsubeuqm 2, 2, 3, 4 } -define <1 x i128> @test_vsubcuq(<1 x i128> %x, - <1 x i128> %y) nounwind { +define <1 x i128> @test_vsubcuq(<1 x i128> %x, <1 x i128> %y) nounwind { +; ALL-LABEL: test_vsubcuq: +; ALL: # %bb.0: +; ALL-NEXT: vsubcuq 2, 2, 3 +; ALL-NEXT: blr %tmp = tail call <1 x i128> @llvm.ppc.altivec.vsubcuq(<1 x i128> %x, - <1 x i128> %y) + <1 x i128> %y) ret <1 x i128> %tmp -; CHECK-LABEL: test_vsubcuq -; CHECK: vsubcuq 2, 2, 3 } -define <1 x i128> @test_vsubecuq(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) nounwind { +define <1 x i128> @test_vsubecuq(<1 x i128> %x, <1 x i128> %y, <1 x i128> %z) nounwind { +; ALL-LABEL: test_vsubecuq: +; ALL: # %bb.0: +; ALL-NEXT: vsubecuq 2, 2, 3, 4 +; ALL-NEXT: blr %tmp = tail call <1 x i128> @llvm.ppc.altivec.vsubecuq(<1 x i128> %x, - <1 x i128> %y, - <1 x i128> %z) + <1 x i128> %y, + <1 x i128> %z) ret <1 x i128> %tmp -; CHECK-LABEL: test_vsubecuq -; CHECK: vsubecuq 2, 2, 3, 4 } - From e18b5c62376ce5258c19ba60358cffd9e8fa67bd Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 23 May 2019 18:09:26 +0000 Subject: [PATCH 0062/1176] [WebAssembly] Implement ReplaceNodeResults to fix a SIMD crash Reviewers: aheejin Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61037 llvm-svn: 361526 --- .../WebAssembly/WebAssemblyISelLowering.cpp | 15 ++++++++++++ .../WebAssembly/WebAssemblyISelLowering.h | 3 +++ .../WebAssembly/simd-illegal-signext.ll | 24 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 1f72c654ee8f0..06aee6e80a04f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -897,6 +897,21 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments( return Chain; } +void WebAssemblyTargetLowering::ReplaceNodeResults( + SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { + switch (N->getOpcode()) { + case ISD::SIGN_EXTEND_INREG: + // Do not add any results, signifying that N should not be custom lowered + // after all. This happens because simd128 turns on custom lowering for + // SIGN_EXTEND_INREG, but for non-vector sign extends the result might be an + // illegal type. + break; + default: + llvm_unreachable( + "ReplaceNodeResults not implemented for this op for WebAssembly!"); + } +} + //===----------------------------------------------------------------------===// // Custom lowering hooks. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h index f899f0feee417..80fca28764724 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -85,6 +85,9 @@ class WebAssemblyTargetLowering final : public TargetLowering { const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const override; + void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, + SelectionDAG &DAG) const override; + // Custom lowering hooks. SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; SDValue LowerFrameIndex(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll b/llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll new file mode 100644 index 0000000000000..20775f0ee3a54 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/simd-illegal-signext.ll @@ -0,0 +1,24 @@ +; RUN: llc < %s -mattr=+simd128 | FileCheck %s + +; Regression test for a crash caused by +; WebAssemblyTargetLowering::ReplaceNodeResults not being +; implemented. Since SIMD is enabled, sign_ext_inreg is custom lowered +; but the result is i16, an illegal value. This requires +; ReplaceNodeResults to resolve, but the default implementation is to +; abort. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-emscripten" + +; CHECK: i32.load8_s +; CHECK-NEXT: i32.store16 +define void @foo() { +entry: + %0 = load i32*, i32** undef, align 4 + %1 = load i32, i32* %0, align 4 + %2 = load i32, i32* undef, align 4 + %conv67 = trunc i32 %2 to i8 + %conv68 = sext i8 %conv67 to i16 + store i16 %conv68, i16* null, align 2 + ret void +} From 170dfeb2ff06d6eb9157054c9b321a5bb2fc10f7 Mon Sep 17 00:00:00 2001 From: Robert Lougher Date: Thu, 23 May 2019 18:15:12 +0000 Subject: [PATCH 0063/1176] Resubmit r360436 "[X86] Avoid SFB - Fix inconsistent codegen with/without debug info" Fixes https://bugs.llvm.org/show_bug.cgi?id=40969 The functions findPotentiallyBlockedCopies and buildCopy are currently not accounting for the presence of debug instructions. In the former this results in the optimization not being trigerred, and in the latter results in inconsistent codegen. This patch enables the optimization to be performed in a debug build and ensures the codegen is consistent with non-debug builds. Patch by Chris Dawson. Differential Revision: https://reviews.llvm.org/D61680 llvm-svn: 361527 --- .../X86/X86AvoidStoreForwardingBlocks.cpp | 14 +- .../CodeGen/X86/avoid-sfb-g-no-change.mir | 222 ++++++++++++++++++ 2 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir diff --git a/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp b/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp index 3ac0b1ae5143d..a9d807b733b7e 100644 --- a/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp +++ b/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp @@ -406,7 +406,10 @@ void X86AvoidSFBPass::buildCopy(MachineInstr *LoadInst, unsigned NLoadOpcode, // If the load and store are consecutive, use the loadInst location to // reduce register pressure. MachineInstr *StInst = StoreInst; - if (StoreInst->getPrevNode() == LoadInst) + auto PrevInstrIt = skipDebugInstructionsBackward( + std::prev(MachineBasicBlock::instr_iterator(StoreInst)), + MBB->instr_begin()); + if (PrevInstrIt.getNodePtr() == LoadInst) StInst = LoadInst; MachineInstr *NewStore = BuildMI(*MBB, StInst, StInst->getDebugLoc(), TII->get(NStoreOpcode)) @@ -491,19 +494,22 @@ void X86AvoidSFBPass::buildCopies(int Size, MachineInstr *LoadInst, static void updateKillStatus(MachineInstr *LoadInst, MachineInstr *StoreInst) { MachineOperand &LoadBase = getBaseOperand(LoadInst); MachineOperand &StoreBase = getBaseOperand(StoreInst); + auto StorePrevNonDbgInstr = skipDebugInstructionsBackward( + std::prev(MachineBasicBlock::instr_iterator(StoreInst)), + LoadInst->getParent()->instr_begin()).getNodePtr(); if (LoadBase.isReg()) { MachineInstr *LastLoad = LoadInst->getPrevNode(); // If the original load and store to xmm/ymm were consecutive // then the partial copies were also created in // a consecutive order to reduce register pressure, // and the location of the last load is before the last store. - if (StoreInst->getPrevNode() == LoadInst) + if (StorePrevNonDbgInstr == LoadInst) LastLoad = LoadInst->getPrevNode()->getPrevNode(); getBaseOperand(LastLoad).setIsKill(LoadBase.isKill()); } if (StoreBase.isReg()) { MachineInstr *StInst = StoreInst; - if (StoreInst->getPrevNode() == LoadInst) + if (StorePrevNonDbgInstr == LoadInst) StInst = LoadInst; getBaseOperand(StInst->getPrevNode()).setIsKill(StoreBase.isKill()); } @@ -530,7 +536,7 @@ void X86AvoidSFBPass::findPotentiallylBlockedCopies(MachineFunction &MF) { if (!isPotentialBlockedMemCpyLd(MI.getOpcode())) continue; int DefVR = MI.getOperand(0).getReg(); - if (!MRI->hasOneUse(DefVR)) + if (!MRI->hasOneNonDBGUse(DefVR)) continue; for (auto UI = MRI->use_nodbg_begin(DefVR), UE = MRI->use_nodbg_end(); UI != UE;) { diff --git a/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir b/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir new file mode 100644 index 0000000000000..82cb9a786c29a --- /dev/null +++ b/llvm/test/CodeGen/X86/avoid-sfb-g-no-change.mir @@ -0,0 +1,222 @@ +# RUN: llc %s -run-pass x86-avoid-SFB -mtriple=x86_64-unknown-linux-gnu -o - | FileCheck %s -check-prefixes DEBUG-LABEL,CHECK +# RUN: llc %s -run-pass x86-avoid-SFB -mtriple=x86_64-unknown-linux-gnu -o - | FileCheck %s -check-prefixes NODEBUG-LABEL,CHECK +# +# This was generated from: +# +# using alpha = float __attribute__((ext_vector_type(4))); +# +# void bravo(alpha * __restrict__ p1, alpha * __restrict__ p2) { +# char *p3 = (char *)p1; +# *p3 = 0; +# alpha t = *p1; +# *p2 = t; +# } +# +# Using the command line: +# clang -g -c 1.cpp -O2 -S -emit-llvm -fno-strict-aliasing --target=x86_64-unknown-unknown -o test.ll +# llc -stop-before=x86-avoid-SFB test.ll -o before.mir + +--- | + ; ModuleID = 'test.ll' + source_filename = "1.cpp" + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-unknown-unknown" + + ; Function Attrs: norecurse nounwind uwtable + define dso_local void @debug(<4 x float>* noalias nocapture %p1, <4 x float>* noalias nocapture %p2) local_unnamed_addr #0 !dbg !10 { + entry: + call void @llvm.dbg.value(metadata <4 x float>* %p1, metadata !21, metadata !DIExpression()), !dbg !25 + call void @llvm.dbg.value(metadata <4 x float>* %p2, metadata !22, metadata !DIExpression()), !dbg !25 + %0 = bitcast <4 x float>* %p1 to i8*, !dbg !26 + call void @llvm.dbg.value(metadata i8* %0, metadata !23, metadata !DIExpression()), !dbg !25 + store i8 0, i8* %0, align 1, !dbg !27 + %1 = load <4 x float>, <4 x float>* %p1, align 16, !dbg !28 + call void @llvm.dbg.value(metadata <4 x float> %1, metadata !24, metadata !DIExpression()), !dbg !25 + store <4 x float> %1, <4 x float>* %p2, align 16, !dbg !29 + ret void, !dbg !30 + } + + ; Function Attrs: norecurse nounwind uwtable + define dso_local void @nodebug(<4 x float>* noalias nocapture %p1, <4 x float>* noalias nocapture %p2) local_unnamed_addr #0 { + entry: + %0 = bitcast <4 x float>* %p1 to i8* + store i8 0, i8* %0, align 1 + %1 = load <4 x float>, <4 x float>* %p1, align 16 + store <4 x float> %1, <4 x float>* %p2, align 16 + ret void + } + + ; Function Attrs: nounwind readnone speculatable + declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + + ; Function Attrs: nounwind + declare void @llvm.stackprotector(i8*, i8**) #2 + + attributes #0 = { norecurse nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } + attributes #1 = { nounwind readnone speculatable } + attributes #2 = { nounwind } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!6, !7, !8} + !llvm.ident = !{!9} + + !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 9.0.0 (https://github.com/llvm/llvm-project.git 9afc4764dd24bd2f23c44e51ad33f8e58234a8b6)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None) + !1 = !DIFile(filename: "1.cpp", directory: "C:\5CUsers\5Cgbdawsoc\5CDocuments\5Cllvm\5Cbg40969") + !2 = !{} + !3 = !{!4} + !4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64) + !5 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) + !6 = !{i32 2, !"Dwarf Version", i32 4} + !7 = !{i32 2, !"Debug Info Version", i32 3} + !8 = !{i32 1, !"wchar_size", i32 4} + !9 = !{!"clang version 9.0.0 (https://github.com/llvm/llvm-project.git 9afc4764dd24bd2f23c44e51ad33f8e58234a8b6)"} + !10 = distinct !DISubprogram(name: "bravo", linkageName: "_Z5bravoPDv4_fS0_", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !20) + !11 = !DISubroutineType(types: !12) + !12 = !{null, !13, !13} + !13 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !14) + !14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) + !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "alpha", file: !1, line: 2, baseType: !16) + !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !17, size: 128, flags: DIFlagVector, elements: !18) + !17 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) + !18 = !{!19} + !19 = !DISubrange(count: 4) + !20 = !{!21, !22, !23, !24} + !21 = !DILocalVariable(name: "p1", arg: 1, scope: !10, file: !1, line: 4, type: !13) + !22 = !DILocalVariable(name: "p2", arg: 2, scope: !10, file: !1, line: 4, type: !13) + !23 = !DILocalVariable(name: "p3", scope: !10, file: !1, line: 5, type: !4) + !24 = !DILocalVariable(name: "t", scope: !10, file: !1, line: 7, type: !15) + !25 = !DILocation(line: 0, scope: !10) + !26 = !DILocation(line: 5, column: 14, scope: !10) + !27 = !DILocation(line: 6, column: 7, scope: !10) + !28 = !DILocation(line: 7, column: 13, scope: !10) + !29 = !DILocation(line: 8, column: 7, scope: !10) + !30 = !DILocation(line: 9, column: 1, scope: !10) + +... +--- +name: debug +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: gr64, preferred-register: '' } + - { id: 2, class: vr128, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$rsi', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + liveins: $rdi, $rsi + + DBG_VALUE $rdi, $noreg, !21, !DIExpression(), debug-location !25 + DBG_VALUE $rsi, $noreg, !22, !DIExpression(), debug-location !25 + %1:gr64 = COPY $rsi + DBG_VALUE %1, $noreg, !22, !DIExpression(), debug-location !25 + %0:gr64 = COPY $rdi + DBG_VALUE %0, $noreg, !21, !DIExpression(), debug-location !25 + DBG_VALUE %0, $noreg, !23, !DIExpression(), debug-location !25 + MOV8mi %0, 1, $noreg, 0, $noreg, 0, debug-location !27 :: (store 1 into %ir.0) + %2:vr128 = MOVAPSrm %0, 1, $noreg, 0, $noreg, debug-location !28 :: (load 16 from %ir.p1) + DBG_VALUE %2, $noreg, !24, !DIExpression(), debug-location !25 + MOVAPSmr %1, 1, $noreg, 0, $noreg, killed %2, debug-location !29 :: (store 16 into %ir.p2) + RET 0, debug-location !30 + +... +--- +name: nodebug +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: gr64, preferred-register: '' } + - { id: 2, class: vr128, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$rsi', virtual-reg: '%1' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + liveins: $rdi, $rsi + + %1:gr64 = COPY $rsi + %0:gr64 = COPY $rdi + MOV8mi %0, 1, $noreg, 0, $noreg, 0 :: (store 1 into %ir.0) + %2:vr128 = MOVAPSrm %0, 1, $noreg, 0, $noreg :: (load 16 from %ir.p1) + MOVAPSmr %1, 1, $noreg, 0, $noreg, killed %2 :: (store 16 into %ir.p2) + RET 0 + + ; DEBUG-LABEL: name: debug + ; NODEBUG-LABEL: name: nodebug + ; CHECK: %1:gr64 = COPY + ; CHECK: %0:gr64 = COPY + ; CHECK: MOV8mi + ; CHECK: %3:gr8 = MOV8rm + ; CHECK: MOV8mr + ; CHECK: %4:gr64 = MOV64rm + ; CHECK: MOV64mr + ; CHECK: %5:gr32 = MOV32rm + ; CHECK: MOV32mr + ; CHECK: %6:gr16 = MOV16rm + ; CHECK: MOV16mr + ; CHECK: %7:gr8 = MOV8rm + ; CHECK: MOV8mr + ; CHECK: RET 0 + ; DEBUG-LABEL: name: nodebug +... From a21d5ab369ead9b9517b13aa8de3606bc641bfa5 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 23 May 2019 18:15:43 +0000 Subject: [PATCH 0064/1176] [HostNativeThreadBase] Undo nullptr changes The thread result type is an unsigned instead of a pointer on windows, so we shouldn't replace 0 with nullptr here. llvm-svn: 361528 --- lldb/source/Host/common/HostNativeThreadBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp index 82f519e14f17b..a5f876a7232af 100644 --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -18,10 +18,10 @@ using namespace lldb; using namespace lldb_private; HostNativeThreadBase::HostNativeThreadBase() - : m_thread(LLDB_INVALID_HOST_THREAD), m_result(nullptr) {} + : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {} HostNativeThreadBase::HostNativeThreadBase(thread_t thread) - : m_thread(thread), m_result(nullptr) {} + : m_thread(thread), m_result(0) {} lldb::thread_t HostNativeThreadBase::GetSystemHandle() const { return m_thread; @@ -37,7 +37,7 @@ bool HostNativeThreadBase::IsJoinable() const { void HostNativeThreadBase::Reset() { m_thread = LLDB_INVALID_HOST_THREAD; - m_result = nullptr; + m_result = 0; } bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { @@ -47,7 +47,7 @@ bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { lldb::thread_t HostNativeThreadBase::Release() { lldb::thread_t result = m_thread; m_thread = LLDB_INVALID_HOST_THREAD; - m_result = nullptr; + m_result = 0; return result; } From 06e80f642612a7f80a15543f1cd84a19d688d3f7 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 23 May 2019 18:19:54 +0000 Subject: [PATCH 0065/1176] [OPENMP]Simplify codegen for the outlined regions. Simplified codegen for the outlined regions, excluding duplication code for handling variables with the reference types. llvm-svn: 361529 --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 59 +++++--------- .../distribute_firstprivate_codegen.cpp | 15 +++- .../OpenMP/distribute_lastprivate_codegen.cpp | 19 +++-- ...bute_parallel_for_firstprivate_codegen.cpp | 15 ++-- ...ibute_parallel_for_lastprivate_codegen.cpp | 20 ++--- ...parallel_for_simd_firstprivate_codegen.cpp | 10 +++ ..._parallel_for_simd_lastprivate_codegen.cpp | 18 ++--- .../distribute_simd_firstprivate_codegen.cpp | 6 +- .../distribute_simd_lastprivate_codegen.cpp | 12 +-- clang/test/OpenMP/for_reduction_codegen.cpp | 13 +++- .../test/OpenMP/for_reduction_codegen_UDR.cpp | 4 + .../OpenMP/parallel_firstprivate_codegen.cpp | 12 +-- clang/test/OpenMP/target_map_codegen.cpp | 8 ++ ..._teams_distribute_firstprivate_codegen.cpp | 9 ++- ...t_teams_distribute_lastprivate_codegen.cpp | 18 ++--- ...bute_parallel_for_firstprivate_codegen.cpp | 15 +++- ...ibute_parallel_for_lastprivate_codegen.cpp | 78 ++++++++++--------- ...parallel_for_simd_firstprivate_codegen.cpp | 7 +- ..._parallel_for_simd_lastprivate_codegen.cpp | 22 +++--- ...s_distribute_simd_firstprivate_codegen.cpp | 4 +- ...ms_distribute_simd_lastprivate_codegen.cpp | 15 ++-- .../teams_distribute_firstprivate_codegen.cpp | 8 +- .../teams_distribute_lastprivate_codegen.cpp | 13 ++-- ...bute_parallel_for_firstprivate_codegen.cpp | 15 ++-- ...ibute_parallel_for_lastprivate_codegen.cpp | 18 +++-- ...parallel_for_simd_firstprivate_codegen.cpp | 14 ++-- ..._parallel_for_simd_lastprivate_codegen.cpp | 18 +++-- ...s_distribute_simd_firstprivate_codegen.cpp | 8 +- ...ms_distribute_simd_lastprivate_codegen.cpp | 13 +++- 29 files changed, 288 insertions(+), 198 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index d27afcdd33068..01194e3a60fa1 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -296,8 +296,7 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, - LValue AddrLV, - bool isReferenceType = false) { + LValue AddrLV) { ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( @@ -306,17 +305,6 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, Address TmpAddr = CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType)) .getAddress(); - - // If we are dealing with references we need to return the address of the - // reference instead of the reference of the value. - if (isReferenceType) { - QualType RefType = Ctx.getLValueReferenceType(DstType); - llvm::Value *RefVal = TmpAddr.getPointer(); - TmpAddr = CGF.CreateMemTemp(RefType, Twine(Name, ".ref")); - LValue TmpLVal = CGF.MakeAddrLValue(TmpAddr, RefType); - CGF.EmitStoreThroughLValue(RValue::get(RefVal), TmpLVal, /*isInit=*/true); - } - return TmpAddr; } @@ -473,14 +461,6 @@ static llvm::Function *emitOutlinedFunctionPrologue( // use the value that we get from the arguments. if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) { const VarDecl *CurVD = I->getCapturedVar(); - // If the variable is a reference we need to materialize it here. - if (CurVD->getType()->isReferenceType()) { - Address RefAddr = CGF.CreateMemTemp( - CurVD->getType(), CGM.getPointerAlign(), ".materialized_ref"); - CGF.EmitStoreOfScalar(LocalAddr.getPointer(), RefAddr, - /*Volatile=*/false, CurVD->getType()); - LocalAddr = RefAddr; - } if (!FO.RegisterCastedArgsOnly) LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}}); ++Cnt; @@ -504,15 +484,12 @@ static llvm::Function *emitOutlinedFunctionPrologue( const VarDecl *Var = I->getCapturedVar(); QualType VarTy = Var->getType(); Address ArgAddr = ArgLVal.getAddress(); - if (!VarTy->isReferenceType()) { - if (ArgLVal.getType()->isLValueReferenceType()) { - ArgAddr = CGF.EmitLoadOfReference(ArgLVal); - } else if (!VarTy->isVariablyModifiedType() || - !VarTy->isPointerType()) { - assert(ArgLVal.getType()->isPointerType()); - ArgAddr = CGF.EmitLoadOfPointer( - ArgAddr, ArgLVal.getType()->castAs()); - } + if (ArgLVal.getType()->isLValueReferenceType()) { + ArgAddr = CGF.EmitLoadOfReference(ArgLVal); + } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) { + assert(ArgLVal.getType()->isPointerType()); + ArgAddr = CGF.EmitLoadOfPointer( + ArgAddr, ArgLVal.getType()->castAs()); } if (!FO.RegisterCastedArgsOnly) { LocalAddrs.insert( @@ -523,14 +500,12 @@ static llvm::Function *emitOutlinedFunctionPrologue( assert(!FD->getType()->isAnyPointerType() && "Not expecting a captured pointer."); const VarDecl *Var = I->getCapturedVar(); - QualType VarTy = Var->getType(); - LocalAddrs.insert( - {Args[Cnt], - {Var, FO.UIntPtrCastRequired - ? castValueFromUintptr(CGF, I->getLocation(), - FD->getType(), Args[Cnt]->getName(), - ArgLVal, VarTy->isReferenceType()) - : ArgLVal.getAddress()}}); + LocalAddrs.insert({Args[Cnt], + {Var, FO.UIntPtrCastRequired + ? castValueFromUintptr( + CGF, I->getLocation(), FD->getType(), + Args[Cnt]->getName(), ArgLVal) + : ArgLVal.getAddress()}}); } else { // If 'this' is captured, load it into CXXThisValue. assert(I->capturesThis()); @@ -566,16 +541,20 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) { Out.str()); llvm::Function *F = emitOutlinedFunctionPrologue(*this, Args, LocalAddrs, VLASizes, CXXThisValue, FO); + CodeGenFunction::OMPPrivateScope LocalScope(*this); for (const auto &LocalAddrPair : LocalAddrs) { if (LocalAddrPair.second.first) { - setAddrOfLocalVar(LocalAddrPair.second.first, - LocalAddrPair.second.second); + LocalScope.addPrivate(LocalAddrPair.second.first, [&LocalAddrPair]() { + return LocalAddrPair.second.second; + }); } } + (void)LocalScope.Privatize(); for (const auto &VLASizePair : VLASizes) VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second; PGO.assignRegionCounters(GlobalDecl(CD), F); CapturedStmtInfo->EmitBody(*this, CD->getBody()); + (void)LocalScope.ForceCleanup(); FinishFunction(CD->getBodyRBrace()); if (!NeedWrapperFunction) return F; diff --git a/clang/test/OpenMP/distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_firstprivate_codegen.cpp index d7fdd1c0acd4b..245d8a544688e 100644 --- a/clang/test/OpenMP/distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_firstprivate_codegen.cpp @@ -86,6 +86,7 @@ int main() { // LAMBDA: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}*, // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca float*, // LAMBDA: [[G1_REF:%.+]] = alloca double*, + // LAMBDA: [[G1_REF1:%.+]] = alloca double*, // Actual private variables to be used in the body (tmp is used for the reference type) // LAMBDA: [[G_PRIVATE:%.+]] = alloca double, @@ -105,9 +106,11 @@ int main() { // LAMBDA-DAG: [[SFVAR_ADDR_VAL:%.+]] = load float*, float** [[SFVAR_ADDR]], // LAMBDA-DAG: [[G1_ADDR_VAL:%.+]] = load double*, double** [[G1_ADDR]], // LAMBDA-DAG: store double* [[G1_ADDR_VAL]], double** [[G1_REF]], + // LAMBDA-DAG: [[G1_ADDR_VAL:%.+]] = load double*, double** [[G1_REF]], + // LAMBDA-DAG: store double* [[G1_ADDR_VAL]], double** [[G1_REF1]], // LAMBDA-DAG: [[G_CONV_VAL:%.+]] = load{{.*}} double, double* [[G_ADDR_VAL]], // LAMBDA-DAG: store double [[G_CONV_VAL]], double* [[G_PRIVATE]], - // LAMBDA-DAG: [[TMP_VAL:%.+]] = load double*, double** [[G1_REF]], + // LAMBDA-DAG: [[TMP_VAL:%.+]] = load double*, double** [[G1_REF1]], // LAMBDA-DAG: [[TMP_VAL_VAL:%.+]] = load{{.*}} double, double* [[TMP_VAL]], // LAMBDA-DAG: store double [[TMP_VAL_VAL]], double* [[G1_PRIVATE]], // LAMBDA-DAG: store double* [[G1_PRIVATE]], double** [[TMP_PRIVATE]], @@ -224,6 +227,7 @@ int main() { // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}*, // CHECK: [[TMP:%.+]] = alloca [[S_FLOAT_TY]]*, +// CHECK: [[TMP1:%.+]] = alloca [[S_FLOAT_TY]]*, // discard omp loop variables // CHECK: {{.*}} = alloca i{{[0-9]+}}, @@ -280,7 +284,9 @@ int main() { // init var // CHECK-DAG: [[VAR_ADDR_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], // CHECK-DAG: store{{.+}} [[VAR_ADDR_VAL]],{{.+}} [[TMP]], -// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK-DAG: [[VAR_ADDR_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK-DAG: store{{.+}} [[VAR_ADDR_VAL]],{{.+}} [[TMP1]], +// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_PRIV]] to{{.+}} // CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to{{.+}} // CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}}) @@ -321,6 +327,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP1:%.+]] = alloca [[S_INT_TY]]*, // discard omp loop variables // CHECK: {{.*}} = alloca i{{[0-9]+}}, @@ -375,7 +382,9 @@ int main() { // init var // CHECK-DAG: [[VAR_ADDR_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR]], // CHECK-DAG: store{{.+}} [[VAR_ADDR_VAL]],{{.+}} [[TMP]], -// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]], +// CHECK-DAG: [[VAR_ADDR_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]], +// CHECK-DAG: store{{.+}} [[VAR_ADDR_VAL]],{{.+}} [[TMP1]], +// CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_PRIV]] to{{.+}} // CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to{{.+}} // CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}}) diff --git a/clang/test/OpenMP/distribute_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_lastprivate_codegen.cpp index 175f3c8bde26f..8d6ceb6ee9352 100644 --- a/clang/test/OpenMP/distribute_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_lastprivate_codegen.cpp @@ -85,6 +85,7 @@ int main() { // LAMBDA: [[SVAR_PRIVATE_ADDR:%.+]] = alloca i{{[0-9]+}}*, // LAMBDA: [[SFVAR_PRIVATE_ADDR:%.+]] = alloca float*, // LAMBDA: [[TMP_G1:%.+]] = alloca double*, + // LAMBDA: [[TMP1_G1:%.+]] = alloca double*, // loop variables // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, @@ -104,11 +105,13 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_IN_REF]], double** [[TMP_G1]], - // LAMBDA: [[TMP_G1_VAL:%.+]] = load double*, double** [[TMP_G1]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[TMP_G1]], + // LAMBDA: store double* [[G1_IN_REF]], double** [[TMP1_G1]], + // LAMBDA: [[TMP_G1_VAL:%.+]] = load double*, double** [[TMP1_G1]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -214,6 +217,7 @@ int main() { // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}*, // CHECK: [[TMP:%.*]] = alloca [[S_FLOAT_TY]]*, +// CHECK: [[TMP1:%.*]] = alloca [[S_FLOAT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -239,11 +243,13 @@ int main() { // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], -// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], +// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store [[S_FLOAT_TY]]* [[VAR_ADDR_REF]], [[S_FLOAT_TY]]** [[TMP]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK: store [[S_FLOAT_TY]]* [[VAR_ADDR_REF]], [[S_FLOAT_TY]]** [[TMP1]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP1]], // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -316,6 +322,7 @@ int main() { // CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, // CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP1:%.+]] = alloca [[S_INT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -344,8 +351,10 @@ int main() { // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], // CHECK-DAG: store [[S_INT_TY]]* [[VAR_ADDR1_REF]], [[S_INT_TY]]** [[TMP]], +// CHECK-DAG: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]], +// CHECK-DAG: store [[S_INT_TY]]* [[VAR_ADDR1_REF]], [[S_INT_TY]]** [[TMP1]], // CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], -// CHECK-DAG: [[TMP_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]], +// CHECK-DAG: [[TMP_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP1]], // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; // CHECK: [[IV_VAL1:%.+]] = diff --git a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp index 705418276856c..9dc38b3ddf488 100644 --- a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp @@ -86,6 +86,7 @@ int main() { // LAMBDA: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}*, // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca float*, // LAMBDA: [[G1_REF:%.+]] = alloca double*, + // LAMBDA: [[G1_REF1:%.+]] = alloca double*, // private alloca's // LAMBDA: [[G_PRIV:%.+]] = alloca double, @@ -111,7 +112,7 @@ int main() { // LAMBDA-DAG: store {{.+}} [[G_ADDR_VAL]], {{.+}}* [[G_PRIV]], // g1 - // LAMBDA-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}** [[G1_REF]], + // LAMBDA-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}** [[G1_REF1]], // LAMBDA-DAG: [[TMP_VAL:%.+]] = load {{.+}}, {{.+}}* [[TMP_REF]], // LAMBDA-DAG: store {{.+}} [[TMP_VAL]], {{.+}}* [[G1_PRIV]] // LAMBDA-DAG: store {{.+}}* [[G1_PRIV]], {{.+}}** [[TMP_PRIV]], @@ -293,6 +294,7 @@ int main() { // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}*, // CHECK: [[TMP:%.+]] = alloca [[S_FLOAT_TY]]*, +// CHECK: [[TMP1:%.+]] = alloca [[S_FLOAT_TY]]*, // skip loop alloca's // CHECK: [[OMP_IV:.omp.iv+]] = alloca i{{[0-9]+}}, @@ -342,7 +344,7 @@ int main() { // CHECK-DAG: [[CPY_DONE]]: // var -// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]], +// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]], @@ -393,6 +395,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[TMP:%.+]] = alloca [[S_FLOAT_TY]]*, // skip loop alloca's // CHECK: [[OMP_IV:.omp.iv+]] = alloca i{{[0-9]+}}, @@ -435,7 +438,7 @@ int main() { // CHECK-DAG: [[CPY_DONE]]: // var -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]], @@ -477,6 +480,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP1:%.+]] = alloca [[S_INT_TY]]*, // skip loop alloca's // CHECK: [[OMP_IV:.omp.iv+]] = alloca i{{[0-9]+}}, @@ -524,7 +528,7 @@ int main() { // CHECK-DAG: [[CPY_DONE]]: // var -// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]], +// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]], @@ -564,6 +568,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP:%.+]] = alloca [[S_INT_TY]]*, // skip loop alloca's // CHECK: [[OMP_IV:.omp.iv+]] = alloca i{{[0-9]+}}, @@ -605,7 +610,7 @@ int main() { // CHECK-DAG: [[CPY_DONE]]: // var -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]], diff --git a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp index b10c02ba7964d..20b233f0bb88b 100644 --- a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp @@ -106,9 +106,9 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_IN_REF]], double** [[TMP_G1]], // LAMBDA: [[TMP_G1_VAL:%.+]] = load double*, double** [[TMP_G1]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], @@ -129,7 +129,7 @@ int main() { // LAMBDA: store{{.*}} double [[G_PRIV_VAL]], double* [[G_IN_REF]], // LAMBDA: [[TMP_G1_PRIV_REF:%.+]] = load double*, double** [[TMP_G1_PRIVATE]], // LAMBDA: [[TMP_G1_PRIV_VAL:%.+]] = load double, double* [[TMP_G1_PRIV_REF]], - // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* [[TMP_G1_VAL]], + // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* % // LAMBDA: [[SVAR_PRIV_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_PRIVATE]], // LAMBDA: store i{{[0-9]+}} [[SVAR_PRIV_VAL]], i{{[0-9]+}}* [[SVAR_IN_REF]], @@ -176,10 +176,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4( @@ -212,7 +212,7 @@ int main() { // LAMBDA: store{{.*}} double [[G_PRIV_VAL]], double* [[G_IN_REF]], // LAMBDA: [[TMP_G1_PRIV_REF:%.+]] = load double*, double** [[TMP_G1_PRIVATE]], // LAMBDA: [[TMP_G1_PRIV_VAL:%.+]] = load double, double* [[TMP_G1_PRIV_REF]], - // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* [[G1_IN_REF]], + // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* % // LAMBDA: [[SVAR_PRIV_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_PRIVATE]], // LAMBDA: store i{{[0-9]+}} [[SVAR_PRIV_VAL]], i{{[0-9]+}}* [[SVAR_IN_REF]], // LAMBDA: [[SFVAR_PRIV_VAL:%.+]] = load float, float* [[SFVAR_PRIVATE]], @@ -311,8 +311,8 @@ int main() { // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], -// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], +// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store [[S_FLOAT_TY]]* [[VAR_ADDR_REF]], [[S_FLOAT_TY]]** [[TMP]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], @@ -327,7 +327,7 @@ int main() { // CHECK: [[S_ARR_DONE:%.+]] = icmp {{.+}} [[S_ARR_NEXT]], [[S_ARR_END]] // CHECK: br i1 [[S_ARR_DONE]], label %[[S_ARR_CST_END:.+]], label %[[S_ARR_CST_LOOP]] // CHECK: [[S_ARR_CST_END]]: -// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // CHECK: call void [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]], @@ -424,7 +424,7 @@ int main() { // CHECK: [[S_ARR_DONE:%.+]] = icmp {{.+}} [[S_ARR_NEXT]], [[S_ARR_END]] // CHECK: br i1 [[S_ARR_DONE]], label %[[S_ARR_CST_END:.+]], label %[[S_ARR_CST_LOOP]] // CHECK: [[S_ARR_CST_END]]: -// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // CHECK: call void [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]], @@ -567,7 +567,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* %{{.+}} to i8* // CHECK: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],{{.+}}) // CHECK: ret void @@ -605,6 +605,7 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], // call constructor for s_arr @@ -618,7 +619,6 @@ int main() { // CHECK: [[S_ARR_DONE:%.+]] = icmp {{.+}} [[S_ARR_NEXT]], [[S_ARR_END]] // CHECK: br i1 [[S_ARR_DONE]], label %[[S_ARR_CST_END:.+]], label %[[S_ARR_CST_LOOP]] // CHECK: [[S_ARR_CST_END]]: -// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR]], // CHECK: call void [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]]) // CHECK: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP_PRIV]], @@ -667,7 +667,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* %{{.+}} to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: ret void diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp index 50e45be0ee287..62e2c8c0b8ecc 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -108,6 +108,8 @@ int main() { // g1 // LAMBDA-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}** [[G1_REF]], + // LAMBDA-DAG: store {{.+}} [[TMP_REF]], {{.+}}* [[TMP:%.+]], + // LAMBDA-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}** [[TMP]], // LAMBDA-DAG: [[TMP_VAL:%.+]] = load {{.+}}, {{.+}}* [[TMP_REF]], // LAMBDA-DAG: store {{.+}} [[TMP_VAL]], {{.+}}* [[G1_PRIV]] // LAMBDA-DAG: store {{.+}}* [[G1_PRIV]], {{.+}}** [[TMP_PRIV]], @@ -341,6 +343,8 @@ int main() { // var // CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]], +// CHECK-DAG: store {{.+}} [[TMP_REF]], {{.+}}* [[TMP1:%.+]], +// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}** [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]], @@ -434,6 +438,8 @@ int main() { // var // CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]], +// CHECK-DAG: store {{.+}} [[VAR_ADDR_REF]], {{.+}}* [[TMP1:%.+]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}** [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]], @@ -523,6 +529,8 @@ int main() { // var // CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}* [[TMP]], +// CHECK-DAG: store {{.+}} [[TMP_REF]], {{.+}}* [[TMP1:%.+]], +// CHECK-DAG: [[TMP_REF:%.+]] = load {{.+}}*, {{.+}}** [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[TMP_REF_BCAST:%.+]] = bitcast {{.+}}* [[TMP_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_REF_BCAST]], @@ -604,6 +612,8 @@ int main() { // var // CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}* [[VAR_ADDR]], +// CHECK-DAG: store {{.+}} [[VAR_ADDR_REF]], {{.+}}* [[TMP1:%.+]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load {{.+}}*, {{.+}}** [[TMP1]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast {{.+}}* [[VAR_PRIV]] to // CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}}* [[VAR_ADDR_REF]] to // CHECK-DAG: call void @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[VAR_ADDR_BCAST]], diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp index c79bceef455fa..516e9c067c56f 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -106,9 +106,9 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_IN_REF]], double** [[TMP_G1]], // LAMBDA: [[TMP_G1_VAL:%.+]] = load double*, double** [[TMP_G1]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], @@ -138,7 +138,7 @@ int main() { // LAMBDA: store{{.*}} double [[G_PRIV_VAL]], double* [[G_IN_REF]], // LAMBDA: [[TMP_G1_PRIV_REF:%.+]] = load double*, double** [[TMP_G1_PRIVATE]], // LAMBDA: [[TMP_G1_PRIV_VAL:%.+]] = load double, double* [[TMP_G1_PRIV_REF]], - // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* [[TMP_G1_VAL]], + // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* % // LAMBDA: [[SVAR_PRIV_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_PRIVATE]], // LAMBDA: store i{{[0-9]+}} [[SVAR_PRIV_VAL]], i{{[0-9]+}}* [[SVAR_IN_REF]], @@ -185,10 +185,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4( @@ -222,7 +222,7 @@ int main() { // LAMBDA: store{{.*}} double [[G_PRIV_VAL]], double* [[G_IN_REF]], // LAMBDA: [[TMP_G1_PRIV_REF:%.+]] = load double*, double** [[TMP_G1_PRIVATE]], // LAMBDA: [[TMP_G1_PRIV_VAL:%.+]] = load double, double* [[TMP_G1_PRIV_REF]], - // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* [[G1_IN_REF]], + // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* % // LAMBDA: [[SVAR_PRIV_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_PRIVATE]], // LAMBDA: store i{{[0-9]+}} [[SVAR_PRIV_VAL]], i{{[0-9]+}}* [[SVAR_IN_REF]], // LAMBDA: [[SFVAR_PRIV_VAL:%.+]] = load float, float* [[SFVAR_PRIVATE]], @@ -321,8 +321,8 @@ int main() { // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], -// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], +// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store [[S_FLOAT_TY]]* [[VAR_ADDR_REF]], [[S_FLOAT_TY]]** [[TMP]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], @@ -337,7 +337,7 @@ int main() { // CHECK: [[S_ARR_DONE:%.+]] = icmp {{.+}} [[S_ARR_NEXT]], [[S_ARR_END]] // CHECK: br i1 [[S_ARR_DONE]], label %[[S_ARR_CST_END:.+]], label %[[S_ARR_CST_LOOP]] // CHECK: [[S_ARR_CST_END]]: -// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // CHECK: call void [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]], @@ -434,7 +434,7 @@ int main() { // CHECK: [[S_ARR_DONE:%.+]] = icmp {{.+}} [[S_ARR_NEXT]], [[S_ARR_END]] // CHECK: br i1 [[S_ARR_DONE]], label %[[S_ARR_CST_END:.+]], label %[[S_ARR_CST_LOOP]] // CHECK: [[S_ARR_CST_END]]: -// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // CHECK: call void [[S_FLOAT_TY_DEF_CONSTR]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // CHECK: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]], @@ -577,7 +577,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* %{{.+}} to i8* // CHECK: [[TMP_VAL_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL_BCAST]],{{.+}}) // CHECK: ret void @@ -628,7 +628,7 @@ int main() { // CHECK: [[S_ARR_DONE:%.+]] = icmp {{.+}} [[S_ARR_NEXT]], [[S_ARR_END]] // CHECK: br i1 [[S_ARR_DONE]], label %[[S_ARR_CST_END:.+]], label %[[S_ARR_CST_LOOP]] // CHECK: [[S_ARR_CST_END]]: -// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void [[S_INT_TY_DEF_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]]) // CHECK: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP_PRIV]], diff --git a/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp index 36bd1456af5b3..858a7b98d25ec 100644 --- a/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp @@ -109,7 +109,7 @@ int main() { // LAMBDA-DAG: [[G_VAL:%.+]] = load{{.+}} double, double* [[G_ADDR_VAL]], // LAMBDA-DAG: store double [[G_VAL]], double* [[G_PRIVATE]], // LAMBDA-DAG: [[G1_VAL_REF:%.+]] = load double*, double** [[G1_REF]], - // LAMBDA-DAG: [[G1_VAL:%.+]] = load{{.+}} double, double* [[G1_VAL_REF]], + // LAMBDA-DAG: [[G1_VAL:%.+]] = load{{.+}} double, double* % // LAMBDA-DAG: store double [[G1_VAL]], double* [[G1_PRIVATE]], // LAMBDA-DAG: store double* [[G1_PRIVATE]], double** [[TMP_PRIVATE]], // LAMBDA-DAG: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_ADDR_VAL]], @@ -284,7 +284,7 @@ int main() { // CHECK-DAG: store{{.+}} [[VAR_ADDR_VAL]],{{.+}} [[TMP]], // CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_PRIV]] to{{.+}} -// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL]] to{{.+}} +// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* %{{.+}} to{{.+}} // CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}}) // CHECK-DAG: store [[S_FLOAT_TY]]* [[VAR_PRIV]], [[S_FLOAT_TY]]** [[TMP_PRIV]], @@ -379,7 +379,7 @@ int main() { // CHECK-DAG: store{{.+}} [[VAR_ADDR_VAL]],{{.+}} [[TMP]], // CHECK-DAG: [[TMP_VAL:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP]], // CHECK-DAG: [[VAR_PRIV_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_PRIV]] to{{.+}} -// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL]] to{{.+}} +// CHECK-DAG: [[TMP_BCAST:%.+]] = bitcast [[S_INT_TY]]* %{{.+}} to{{.+}} // CHECK-DAG: call{{.+}} @llvm.memcpy.{{.+}}({{.+}}* align {{[0-9]+}} [[VAR_PRIV_BCAST]], {{.+}}* align {{[0-9]+}} [[TMP_BCAST]],{{.+}}) // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]** [[TMP_PRIV]], diff --git a/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp index 22a24a66495a5..6bc146f728aea 100644 --- a/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp @@ -104,9 +104,9 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_IN_REF]], double** [[TMP_G1]], // LAMBDA: [[TMP_G1_VAL:%.+]] = load double*, double** [[TMP_G1]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], @@ -151,7 +151,7 @@ int main() { // LAMBDA: store{{.*}} double [[G_PRIV_VAL]], double* [[G_IN_REF]], // LAMBDA: [[TMP_G1_PRIV_REF:%.+]] = load double*, double** [[TMP_G1_PRIVATE]], // LAMBDA: [[TMP_G1_PRIV_VAL:%.+]] = load double, double* [[TMP_G1_PRIV_REF]], - // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* [[TMP_G1_VAL]], + // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* % // LAMBDA: [[SVAR_PRIV_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_PRIVATE]], // LAMBDA: store i{{[0-9]+}} [[SVAR_PRIV_VAL]], i{{[0-9]+}}* [[SVAR_IN_REF]], @@ -250,11 +250,13 @@ int main() { // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], -// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], +// CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store [[S_FLOAT_TY]]* [[VAR_ADDR_REF]], [[S_FLOAT_TY]]** [[TMP]], -// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], // CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP]], +// CHECK: store [[S_FLOAT_TY]]* [[TMP_REF]], [[S_FLOAT_TY]]** [[TMP1:%.+]], +// CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], +// CHECK: [[TMP_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP1]], // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -400,7 +402,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* %{{.+}} to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: ret void diff --git a/clang/test/OpenMP/for_reduction_codegen.cpp b/clang/test/OpenMP/for_reduction_codegen.cpp index 68946a8b4f79b..2e616db1a5553 100644 --- a/clang/test/OpenMP/for_reduction_codegen.cpp +++ b/clang/test/OpenMP/for_reduction_codegen.cpp @@ -292,14 +292,16 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], // CHECK: [[T_VAR_REF:%.+]] = load float*, float** % +// CHECK: [[VAR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // CHECK: [[VAR1_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // CHECK: [[T_VAR1_REF:%.+]] = load float*, float** % // For + reduction operation initial value of private variable is 0. // CHECK: store float 0.0{{.+}}, float* [[T_VAR_PRIV]], -// For & reduction operation initial value of private variable is ones in all bits. // CHECK: [[VAR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % + +// For & reduction operation initial value of private variable is ones in all bits. // CHECK: call {{.*}} [[S_FLOAT_TY_CONSTR:@.+]]([[S_FLOAT_TY]]* [[VAR_PRIV]]) // For && reduction operation initial value of private variable is 1.0. @@ -1101,6 +1103,8 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], +// CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], @@ -1132,6 +1136,8 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], +// CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], @@ -1160,6 +1166,8 @@ int main() { // Reduction list for runtime. // CHECK: [[RED_LIST:%.+]] = alloca [2 x i8*], +// CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], @@ -1194,6 +1202,8 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], +// CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], @@ -1233,6 +1243,7 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], // CHECK: [[T_VAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** % +// CHECK: [[VAR_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: [[VAR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: [[T_VAR1_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** % diff --git a/clang/test/OpenMP/for_reduction_codegen_UDR.cpp b/clang/test/OpenMP/for_reduction_codegen_UDR.cpp index 0eee597d0232b..c7c3f93748734 100644 --- a/clang/test/OpenMP/for_reduction_codegen_UDR.cpp +++ b/clang/test/OpenMP/for_reduction_codegen_UDR.cpp @@ -790,6 +790,8 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], +// CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], @@ -820,6 +822,8 @@ int main() { // CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], +// CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], +// CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], // CHECK: store [4 x [[S_FLOAT_TY]]]* [[VAR3_ORIG]], [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR:%.+]], // CHECK: [[VAR3_ORIG:%.+]] = load [4 x [[S_FLOAT_TY]]]*, [4 x [[S_FLOAT_TY]]]** [[VAR3_ORIG_ADDR]], diff --git a/clang/test/OpenMP/parallel_firstprivate_codegen.cpp b/clang/test/OpenMP/parallel_firstprivate_codegen.cpp index 66964152aa2a2..8aa64668f0525 100644 --- a/clang/test/OpenMP/parallel_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/parallel_firstprivate_codegen.cpp @@ -180,10 +180,10 @@ int main() { // LAMBDA: [[B_PRIV:%.+]] = alloca i{{[0-9]+}}, // LAMBDA: [[C_PRIV:%.+]] = alloca i{{[0-9]+}}, // LAMBDA-64: [[A_CONV:%.+]] = bitcast i64* [[A_PRIV]] to i32* - // LAMBDA-64: store i32* [[A_CONV]], i32** [[REFA:%.+]], - // LAMBDA-32: store i32* [[A_PRIV]], i32** [[REFA:%.+]], // LAMBDA-64: [[B_CONV:%.+]] = bitcast i64* [[B_PRIV]] to i32* // LAMBDA-64: [[C_CONV:%.+]] = bitcast i64* [[C_PRIV]] to i32* + // LAMBDA-64: store i32* [[A_CONV]], i32** [[REFA:%.+]], + // LAMBDA-32: store i32* [[A_PRIV]], i32** [[REFA:%.+]], // LAMBDA-64: store i32* [[C_CONV]], i32** [[REFC:%.+]], // LAMBDA-32: store i32* [[C_PRIV]], i32** [[REFC:%.+]], // LAMBDA-NEXT: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFA]], @@ -303,10 +303,10 @@ int main() { // BLOCKS: [[B_PRIV:%.+]] = alloca i{{[0-9]+}}, // BLOCKS: [[C_PRIV:%.+]] = alloca i{{[0-9]+}}, // BLOCKS-64: [[A_CONV:%.+]] = bitcast i64* [[A_PRIV]] to i32* -// BLOCKS-64: store i32* [[A_CONV]], i32** [[REFA:%.+]], -// BLOCKS-32: store i32* [[A_PRIV]], i32** [[REFA:%.+]], // BLOCKS-64: [[B_CONV:%.+]] = bitcast i64* [[B_PRIV]] to i32* // BLOCKS-64: [[C_CONV:%.+]] = bitcast i64* [[C_PRIV]] to i32* +// BLOCKS-64: store i32* [[A_CONV]], i32** [[REFA:%.+]], +// BLOCKS-32: store i32* [[A_PRIV]], i32** [[REFA:%.+]], // BLOCKS-64: store i32* [[C_CONV]], i32** [[REFC:%.+]], // BLOCKS-32: store i32* [[C_PRIV]], i32** [[REFC:%.+]], // BLOCKS-NEXT: [[A_PRIV:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[REFA]], @@ -452,10 +452,10 @@ int main() { // CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[B_PRIV]] // CHECK: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[C_PRIV]] // CHECK-64: [[A_CONV:%.+]] = bitcast i64* [[A_PRIV:%.+]] to i32* -// CHECK-64: store i32* [[A_CONV]], i32** [[REFA:%.+]], -// CHECK-32: store i32* [[A_PRIV]], i32** [[REFA:%.+]], // CHECK-64: [[B_CONV:%.+]] = bitcast i64* [[B_PRIV:%.+]] to i32* // CHECK-64: [[C_CONV:%.+]] = bitcast i64* [[C_PRIV:%.+]] to i32* +// CHECK-64: store i32* [[A_CONV]], i32** [[REFA:%.+]], +// CHECK-32: store i32* [[A_PRIV]], i32** [[REFA:%.+]], // CHECK-64: store i32* [[C_CONV]], i32** [[REFC:%.+]], // CHECK-32: store i32* [[C_PRIV]], i32** [[REFC:%.+]], // CHECK: bitcast [4 x i{{[0-9]+}}]* [[E_PRIV]] to i8* diff --git a/clang/test/OpenMP/target_map_codegen.cpp b/clang/test/OpenMP/target_map_codegen.cpp index 44d7ffc9cc5e1..8ed201a7ae1ac 100644 --- a/clang/test/OpenMP/target_map_codegen.cpp +++ b/clang/test/OpenMP/target_map_codegen.cpp @@ -4581,12 +4581,16 @@ struct CC { // CK26: define {{.+}}[[CALL00]]({{.*}}i32*{{.*}}[[PVTARG:%.+]]) // CK26: store i32* [[PVTARG]], i32** [[PVTADDR:%.+]], // CK26: [[ADDR:%.+]] = load i32*, i32** [[PVTADDR]], +// CK26: store i32* [[ADDR]], i32** [[PVTADDR:%.+]], +// CK26: [[ADDR:%.+]] = load i32*, i32** [[PVTADDR]], // CK26: [[VAL:%.+]] = load i32, i32* [[ADDR]], // CK26: add nsw i32 [[VAL]], 1 // CK26: define {{.+}}[[CALL01]]({{.*}}float*{{.*}}[[PVTARG:%.+]]) // CK26: store float* [[PVTARG]], float** [[PVTADDR:%.+]], // CK26: [[ADDR:%.+]] = load float*, float** [[PVTADDR]], +// CK26: store float* [[ADDR]], float** [[PVTADDR:%.+]], +// CK26: [[ADDR:%.+]] = load float*, float** [[PVTADDR]], // CK26: [[VAL:%.+]] = load float, float* [[ADDR]], // CK26: [[EXT:%.+]] = fpext float [[VAL]] to double // CK26: fadd double [[EXT]], 1.000000e+00 @@ -4594,12 +4598,16 @@ struct CC { // CK26: define {{.+}}[[CALL02]]({{.*}}i32*{{.*}}[[PVTARG:%.+]]) // CK26: store i32* [[PVTARG]], i32** [[PVTADDR:%.+]], // CK26: [[ADDR:%.+]] = load i32*, i32** [[PVTADDR]], +// CK26: store i32* [[ADDR]], i32** [[PVTADDR:%.+]], +// CK26: [[ADDR:%.+]] = load i32*, i32** [[PVTADDR]], // CK26: [[VAL:%.+]] = load i32, i32* [[ADDR]], // CK26: add nsw i32 [[VAL]], 1 // CK26: define {{.+}}[[CALL03]]({{.*}}float*{{.*}}[[PVTARG:%.+]]) // CK26: store float* [[PVTARG]], float** [[PVTADDR:%.+]], // CK26: [[ADDR:%.+]] = load float*, float** [[PVTADDR]], +// CK26: store float* [[ADDR]], float** [[PVTADDR:%.+]], +// CK26: [[ADDR:%.+]] = load float*, float** [[PVTADDR]], // CK26: [[VAL:%.+]] = load float, float* [[ADDR]], // CK26: [[EXT:%.+]] = fpext float [[VAL]] to double // CK26: fadd double [[EXT]], 1.000000e+00 diff --git a/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp index 5487fa86e8f01..c268b72a25edd 100644 --- a/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp @@ -274,6 +274,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -304,15 +305,17 @@ int main() { // CHECK: store [2 x [[S_INT_TY]]]* {{.+}}, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // CHECK: store [[S_INT_TY]]* {{.+}}, [[S_INT_TY]]** [[VAR_ADDR]], - // T_VAR and preparation variables // CHECK: [[VEC_ADDR_VAL:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32* // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK: store [[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]** [[VAR_ADDR:%.+]], + // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) diff --git a/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp index 26a7c0d61da83..459384f464fdc 100644 --- a/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp @@ -107,15 +107,15 @@ int main() { // LAMBDA-32: store i32 [[SFVAR_IN]], i32* [[SFVAR_PRIVATE_ADDR]], // init private variables - // LAMBDA-64: [[G_IN_REF:%.+]] = bitcast i64* [[G_PRIVATE_ADDR]] to double* // LAMBDA-32: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA-32: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA-32: [[SFVAR_IN_REF:%.+]] = bitcast i32* [[SFVAR_PRIVATE_ADDR]] to float* + // LAMBDA-64: [[G_IN_REF:%.+]] = bitcast i64* [[G_PRIVATE_ADDR]] to double* // LAMBDA-64: [[G1_IN_REF:%.+]] = bitcast i64* [[G1_PRIVATE_ADDR]] to double* - // LAMBDA-64: store double* [[G1_IN_REF]], double** [[G1_IN_ADDR_REF:%.+]], // LAMBDA-64: [[SVAR_IN_REF:%.+]] = bitcast i64* [[SVAR_PRIVATE_ADDR]] to i32* // LAMBDA-64: [[SFVAR_IN_REF:%.+]] = bitcast i64* [[SFVAR_PRIVATE_ADDR]] to float* - // LAMBDA-32: [[SFVAR_IN_REF:%.+]] = bitcast i32* [[SFVAR_PRIVATE_ADDR]] to float* + // LAMBDA-64: store double* [[G1_IN_REF]], double** [[G1_IN_ADDR_REF:%.+]], // LAMBDA-64: [[G1_IN_REF:%.+]] = load double*, double** [[G1_IN_ADDR_REF]], - // LAMBDA-32: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -147,7 +147,7 @@ int main() { // LAMBDA: store{{.*}} double [[G_PRIV_VAL]], double* [[G_IN_REF]], // LAMBDA: [[TMP_G1_PRIV_REF:%.+]] = load double*, double** [[TMP_G1_PRIVATE]], // LAMBDA: [[TMP_G1_PRIV_VAL:%.+]] = load double, double* [[TMP_G1_PRIV_REF]], - // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* [[G1_IN_REF]], + // LAMBDA: store{{.*}} double [[TMP_G1_PRIV_VAL]], double* % // LAMBDA: [[SVAR_PRIV_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SVAR_PRIVATE]], // LAMBDA-64: store i{{[0-9]+}} [[SVAR_PRIV_VAL]], i{{[0-9]+}}* [[SVAR_IN_REF]], @@ -244,9 +244,9 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK-64: [[T_VAR_ADDR_REF:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32* // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK-64: [[SVAR_ADDR_REF:%.+]] = bitcast i64* [[SVAR_ADDR]] to i32* // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -291,7 +291,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* %{{.+}} to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]], @@ -346,8 +346,8 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK-64: [[T_VAR_ADDR_REF1:%.+]] = bitcast i64* [[T_VAR_ADDR1]] to i32* // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -393,7 +393,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* %{{.+}} to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: ret void diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp index 843b667316a56..9c91538ce7e0f 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -391,6 +391,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -426,9 +427,12 @@ int main() { // CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32* // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK: store [[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]** [[VAR_ADDR:%.+]], + // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -487,9 +491,12 @@ int main() { // CHECK-64: [[CONV_TVAR:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32* // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK: store [[S_INT_TY]]* [[VAR_REF]], [[S_INT_TY]]** [[VAR_ADDR:%.+]], + // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp index acb1c0b636ece..c0f9ecaea20fb 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp @@ -83,7 +83,7 @@ int main() { // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}}, - // LAMBDA-64: [[G1_REF:%.+]] = alloca double*, + // LAMBDA: [[G1_REF:%.+]] = alloca double*, // loop variables // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, @@ -91,19 +91,18 @@ int main() { // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}}, - + // LAMBDA-DAG: store {{.+}} [[G_IN]], {{.+}} [[G_ADDR]], // LAMBDA-DAG: store {{.+}} [[G1_IN]], {{.+}} [[G1_ADDR]], // LAMBDA-DAG: store {{.+}} [[SVAR_IN]], {{.+}} [[SVAR_ADDR]], // LAMBDA-DAG: store {{.+}} [[SFVAR_IN]], {{.+}} [[SFVAR_ADDR]], - + // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]], - // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], - // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]], + // LAMBDA-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to - + g1 = 1; svar = 3; sfvar = 4.0; @@ -135,7 +134,7 @@ int main() { // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}}, - // LAMBDA-64: [[G1_REF:%.+]] = alloca double*, + // LAMBDA: [[G1_REF:%.+]] = alloca double*, // loop variables // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, @@ -143,16 +142,15 @@ int main() { // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: [[OMP_IS_LAST:%.+]] = alloca i{{[0-9]+}}, - + // LAMBDA-DAG: store {{.+}} [[G_IN]], {{.+}} [[G_ADDR]], // LAMBDA-DAG: store {{.+}} [[G1_IN]], {{.+}} [[G1_ADDR]], // LAMBDA-DAG: store {{.+}} [[SVAR_IN]], {{.+}} [[SVAR_ADDR]], // LAMBDA-DAG: store {{.+}} [[SFVAR_IN]], {{.+}} [[SFVAR_ADDR]], - + // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]], - // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], - // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]], + // LAMBDA-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to @@ -164,7 +162,7 @@ int main() { // LAMBDA: [[OMP_IS_LAST_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[OMP_IS_LAST]], // LAMBDA: [[IS_LAST_IT:%.+]] = icmp ne i{{[0-9]+}} [[OMP_IS_LAST_VAL]], 0 // LAMBDA: br i1 [[IS_LAST_IT]], label %[[OMP_LASTPRIV_BLOCK:.+]], label %[[OMP_LASTPRIV_DONE:.+]] - + // LAMBDA: [[OMP_LASTPRIV_BLOCK]]: // LAMBDA-DAG: store {{.+}}, {{.+}} [[G_TGT]], // LAMBDA-DAG: store {{.+}}, {{.+}} [[G1_TGT]], @@ -176,26 +174,26 @@ int main() { // LAMBDA: ret [&]() { - // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]]) - // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]], - g = 2; - g1 = 2; - svar = 4; - sfvar = 8.0; - // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]] - // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 - // LAMBDA: [[G_REF:%.+]] = load double*, double** [[G_PTR_REF]] - // LAMBDA: store double 2.0{{.+}}, double* [[G_REF]] - - // LAMBDA: [[TMP_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 - // LAMBDA: [[G1_REF:%.+]] = load double*, double** [[TMP_PTR_REF]] - // LAMBDA: store double 2.0{{.+}}, double* [[G1_REF]], - // LAMBDA: [[SVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 - // LAMBDA: [[SVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PTR_REF]] - // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SVAR_REF]] - // LAMBDA: [[SFVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 - // LAMBDA: [[SFVAR_REF:%.+]] = load float*, float** [[SFVAR_PTR_REF]] - // LAMBDA: store float 8.0{{.+}}, float* [[SFVAR_REF]] + // LAMBDA: define {{.+}} void [[INNER_LAMBDA]](%{{.+}}* [[ARG_PTR:%.+]]) + // LAMBDA: store %{{.+}}* [[ARG_PTR]], %{{.+}}** [[ARG_PTR_REF:%.+]], + g = 2; + g1 = 2; + svar = 4; + sfvar = 8.0; + // LAMBDA: [[ARG_PTR:%.+]] = load %{{.+}}*, %{{.+}}** [[ARG_PTR_REF]] + // LAMBDA: [[G_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 0 + // LAMBDA: [[G_REF:%.+]] = load double*, double** [[G_PTR_REF]] + // LAMBDA: store double 2.0{{.+}}, double* [[G_REF]] + + // LAMBDA: [[TMP_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 1 + // LAMBDA: [[G1_REF:%.+]] = load double*, double** [[TMP_PTR_REF]] + // LAMBDA: store double 2.0{{.+}}, double* [[G1_REF]], + // LAMBDA: [[SVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 2 + // LAMBDA: [[SVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PTR_REF]] + // LAMBDA: store i{{[0-9]+}} 4, i{{[0-9]+}}* [[SVAR_REF]] + // LAMBDA: [[SFVAR_PTR_REF:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}}* [[ARG_PTR]], i{{[0-9]+}} 0, i{{[0-9]+}} 3 + // LAMBDA: [[SFVAR_REF:%.+]] = load float*, float** [[SFVAR_PTR_REF]] + // LAMBDA: store float 8.0{{.+}}, float* [[SFVAR_REF]] }(); } }(); @@ -237,6 +235,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -256,7 +255,7 @@ int main() { // CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR]], // CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // the distribute loop @@ -295,6 +294,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -314,7 +314,7 @@ int main() { // CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR]], // CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // the distribute loop @@ -360,6 +360,7 @@ int main() { // CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -378,7 +379,7 @@ int main() { // CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR1]], // CHECK: call void @__kmpc_for_static_init_4( // CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to @@ -397,7 +398,7 @@ int main() { // CHECK-DAG: {{.+}} = getelementptr {{.+}} [[S_ARR_TGT]], // CHECK: call void @llvm.memcpy.{{.+}}( // CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to -// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]], +// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]], // CHECK: ret void // CHECK: define internal void [[TPAR_OUTL:@.+]](i{{[0-9]+}}* noalias [[GTID_ADDR1:%.+]], i{{[0-9]+}}* noalias %{{.+}}, {{.+}}, {{.+}}, [2 x i{{[0-9]+}}]*{{.+}} [[VEC_IN1:%.+]], i{{[0-9]+}}{{.+}} [[T_VAR_IN1:%.+]], [2 x [[S_INT_TY]]]*{{.+}} [[S_ARR_IN1:%.+]], [[S_INT_TY]]*{{.+}} [[VAR_IN1:%.+]]) @@ -411,6 +412,7 @@ int main() { // CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -429,7 +431,7 @@ int main() { // CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR1]], // CHECK: call void @__kmpc_for_static_init_4( // skip body: code generation routine is same as distribute parallel for lastprivate @@ -448,7 +450,7 @@ int main() { // CHECK-DAG: {{.+}} = getelementptr {{.+}} [[S_ARR_TGT]], // CHECK: call void @llvm.memcpy.{{.+}}( // CHECK-DAG: [[VAR_ADDR_BCAST:%.+]] = bitcast {{.+}} [[VAR_TGT]] to -// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]], +// CHECK-DAG: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_BCAST]], // CHECK: ret void #endif diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp index 0b09cc6c4027b..978e90dec5432 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -391,6 +391,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -402,6 +403,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -444,7 +446,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) @@ -463,6 +465,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -505,7 +508,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp index c3d38612d63d9..ca09990fbaf62 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -83,7 +83,7 @@ int main() { // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}}, - // LAMBDA-64: [[G1_REF:%.+]] = alloca double*, + // LAMBDA: [[G1_REF:%.+]] = alloca double*, // loop variables // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, @@ -99,8 +99,7 @@ int main() { // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]], - // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], - // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]], + // LAMBDA-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to @@ -136,7 +135,7 @@ int main() { // LAMBDA: [[SVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[SFVAR_ADDR:%.+]] = alloca {{.+}}, // LAMBDA: [[G_ADDR:%.+]] = alloca {{.+}}, - // LAMBDA-64: [[G1_REF:%.+]] = alloca double*, + // LAMBDA: [[G1_REF:%.+]] = alloca double*, // loop variables // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, // LAMBDA: {{.+}} = alloca i{{[0-9]+}}, @@ -152,8 +151,7 @@ int main() { // LAMBDA-64-DAG: [[G_TGT:%.+]] = bitcast {{.+}} [[G_ADDR]] to // LAMBDA-32-DAG: [[G_TGT:%.+]] = load {{.+}}, {{.+}} [[G_ADDR]], - // LAMBDA-64-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], - // LAMBDA-32-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_ADDR]], + // LAMBDA-DAG: [[G1_TGT:%.+]] = load {{.+}}, {{.+}} [[G1_REF]], // LAMBDA-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // LAMBDA-DAG: [[SFVAR_TGT:%.+]] = bitcast {{.+}} [[SFVAR_ADDR]] to @@ -239,6 +237,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -258,7 +257,7 @@ int main() { // CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR]], // CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // the distribute loop @@ -297,6 +296,7 @@ int main() { // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // CHECK: [[SVAR_ADDR:%.+]] = alloca i{{[0-9]+}}, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_FLOAT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -316,7 +316,7 @@ int main() { // CHECK-64-DAG: [[TVAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR]], // CHECK-64-DAG: [[SVAR_TGT:%.+]] = bitcast {{.+}} [[SVAR_ADDR]] to // the distribute loop @@ -362,6 +362,7 @@ int main() { // CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -380,7 +381,7 @@ int main() { // CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR1]], // CHECK: call void @__kmpc_for_static_init_4( // CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[TPAR_OUTL:.+]] to @@ -413,6 +414,7 @@ int main() { // CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -431,7 +433,7 @@ int main() { // CHECK-64-DAG: [[T_VAR_TGT:%.+]] = bitcast {{.+}} [[T_VAR_ADDR1]] to // CHECK-DAG: [[VEC_TGT:%.+]] = load {{.+}}, {{.+}} [[VEC_ADDR1]], // CHECK-DAG: [[S_ARR_TGT:%.+]] = load {{.+}}, {{.+}} [[S_ARR_ADDR1]], -// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR1]], +// CHECK-DAG: [[VAR_TGT:%.+]] = load {{.+}}, {{.+}} [[TMP_VAR_ADDR1]], // CHECK: call void @__kmpc_for_static_init_4( // skip body: code generation routine is same as distribute parallel for lastprivate diff --git a/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp index 463a6afd2d604..05ea0e897a4b5 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp @@ -274,6 +274,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -285,6 +286,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -328,7 +330,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) diff --git a/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp index fdf6d2f3a7dc0..6fae7829874f9 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp @@ -110,12 +110,13 @@ int main() { // LAMBDA-64: [[G_IN_REF:%.+]] = bitcast i64* [[G_PRIVATE_ADDR]] to double* // LAMBDA-32: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], // LAMBDA-64: [[G1_IN_REF:%.+]] = bitcast i64* [[G1_PRIVATE_ADDR]] to double* - // LAMBDA-64: store double* [[G1_IN_REF]], double** [[G1_IN_ADDR_REF:%.+]], + // LAMBDA-32: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA-64: [[SVAR_IN_REF:%.+]] = bitcast i64* [[SVAR_PRIVATE_ADDR]] to i32* // LAMBDA-64: [[SFVAR_IN_REF:%.+]] = bitcast i64* [[SFVAR_PRIVATE_ADDR]] to float* // LAMBDA-32: [[SFVAR_IN_REF:%.+]] = bitcast i32* [[SFVAR_PRIVATE_ADDR]] to float* + // LAMBDA-64: store double* [[G1_IN_REF]], double** [[G1_IN_ADDR_REF:%.+]], // LAMBDA-64: [[G1_IN_REF:%.+]] = load double*, double** [[G1_IN_ADDR_REF]], - // LAMBDA-32: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA-32: [[G1_IN_REF:%.+]] = load double*, double** % // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -245,9 +246,10 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK-64: [[T_VAR_ADDR_REF:%.+]] = bitcast i64* [[T_VAR_ADDR]] to i32* // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK-64: [[SVAR_ADDR_REF:%.+]] = bitcast i64* [[SVAR_ADDR]] to i32* // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[TMP_VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -292,7 +294,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAR_ADDR_REF]] to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]], @@ -347,8 +349,9 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK-64: [[T_VAR_ADDR_REF1:%.+]] = bitcast i64* [[T_VAR_ADDR1]] to i32* // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[TMP_VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -394,7 +397,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAR_ADDR1_REF]] to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: ret void diff --git a/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp index 562e986df034c..672ed8e1b1690 100644 --- a/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp @@ -277,6 +277,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -288,6 +289,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -314,8 +316,8 @@ int main() { // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -331,7 +333,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) diff --git a/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp index 883234185aae8..581bb1d15cc9e 100644 --- a/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp @@ -101,9 +101,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** % // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -232,9 +233,10 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[TMP_VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -278,7 +280,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[TMP_PRIV]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[VAR_ADDR_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAR_ADDR_REF]] to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_FLOAT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: [[SVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[S_VAR_PRIV]], @@ -332,8 +334,9 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK: [[T_VAR_ADDR_REF1:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR1]], // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[TMP_VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -378,7 +381,7 @@ int main() { // CHECK: br i1 [[CPY_IS_FINISHED]], label %[[S_ARR_COPY_DONE]], label %[[S_ARR_COPY_BLOCK]] // CHECK: [[S_ARR_COPY_DONE]]: // CHECK: [[TMP_VAL1:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP_PRIV1]], -// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[VAR_ADDR1_REF]] to i8* +// CHECK: [[VAR_ADDR_REF_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAR_ADDR1_REF]] to i8* // CHECK: [[TMP_VAL1_BCAST:%.+]] = bitcast [[S_INT_TY]]* [[TMP_VAL1]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VAR_ADDR_REF_BCAST]], i8* align {{[0-9]+}} [[TMP_VAL1_BCAST]],{{.+}}) // CHECK: ret void diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp index 7e161b1d2a62a..14bccc0c53cc4 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -367,6 +367,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -378,6 +379,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -403,8 +405,8 @@ int main() { // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -420,7 +422,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) @@ -439,6 +441,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -464,8 +467,8 @@ int main() { // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -481,7 +484,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp index 451dc0579cd32..bc0b210718372 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp @@ -101,9 +101,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** % // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -156,9 +157,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** % // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4( @@ -286,9 +288,10 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to @@ -365,9 +368,10 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( @@ -466,8 +470,9 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK: [[T_VAR_ADDR_REF1:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR1]], // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( @@ -543,8 +548,9 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK: [[T_VAR_ADDR_REF1:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR1]], // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp index 68b0016a97462..6e8c0d18a73fe 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -370,6 +370,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -381,6 +382,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -406,8 +408,8 @@ int main() { // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -423,7 +425,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) @@ -467,8 +469,8 @@ int main() { // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -484,7 +486,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp index c9141b01494fd..4d21a05b1be01 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -101,9 +101,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** % // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -157,9 +158,10 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** % // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], // LAMBDA: call {{.*}}void @__kmpc_for_static_init_4( @@ -293,9 +295,10 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // CHECK: call void {{.*}} @__kmpc_fork_call({{.+}}, {{.+}}, {{.+}} @[[PAR_OUTL:.+]] to @@ -372,9 +375,10 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], // CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** % // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( @@ -476,8 +480,9 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK: [[T_VAR_ADDR_REF1:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR1]], // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( @@ -553,8 +558,9 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK: [[T_VAR_ADDR_REF1:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR1]], // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( diff --git a/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp index ec0b006a37743..f76e2c71ec606 100644 --- a/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp @@ -277,6 +277,7 @@ int main() { // CHECK-DAG: [[TS_ARR_TE_PAR:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[TS_ARR_PRIV]], // CHECK-DAG: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TVAR_PRIV]], +// CHECK: [[TVAR_TE_PAR:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** % // CHECK: call void {{.+}} @__kmpc_fork_teams({{.+}}, i32 4, {{.+}} @[[TOUTL1:.+]] to {{.+}}, [2 x i{{[0-9]+}}]* [[TVEC_TE_PAR]], i{{[0-9]+}} [[TT_VAR_TE_PAR]], [2 x [[S_INT_TY]]]* [[TS_ARR_TE_PAR]], [[S_INT_TY]]* [[TVAR_TE_PAR]]) // CHECK: ret void @@ -288,6 +289,7 @@ int main() { // CHECK: [[T_VAR_ADDR:%.+]] = alloca i{{[0-9]+}}, // CHECK: [[S_ARR_ADDR:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP_VAR_ADDR:%.+]] = alloca [[S_INT_TY]]*, // Skip temp vars for loop // CHECK: alloca i{{[0-9]+}}, // CHECK: alloca i{{[0-9]+}}, @@ -314,8 +316,8 @@ int main() { // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR]], // firstprivate vec(vec): copy from *_addr into priv1 and then from priv1 into priv2 -// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* -// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* +// CHECK-DAG: [[VEC_DEST_PRIV:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_PRIV]] to i8* +// CHECK-DAG: [[VEC_SRC:%.+]] = bitcast [2 x i{{[0-9]+}}]* [[VEC_ADDR_VAL]] to i8* // CHECK: call void @llvm.memcpy.{{.+}}(i8* align {{[0-9]+}} [[VEC_DEST_PRIV]], i8* align {{[0-9]+}} [[VEC_SRC]], {{.+}}) // firstprivate(s_arr) @@ -331,7 +333,7 @@ int main() { // CHECK-DAG: [[S_ARR_SRC]] = getelementptr {{.+}} [[S_ARR_SRC_COPY]], // firstprivate(var) -// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[VAR_ADDR]], +// CHECK-DAG: [[VAR_ADDR_REF:%.+]] = load{{.+}} [[TMP_VAR_ADDR]], // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[VAR_PRIV]], {{.+}} [[VAR_ADDR_REF]], {{.+}} [[AGG_TMP2]]) // CHECK-DAG: call void @{{.+}}({{.+}} [[AGG_TMP2]]) diff --git a/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp index 86cfd00f8c7a3..c7b507f254bcc 100644 --- a/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp @@ -101,9 +101,11 @@ int main() { // init private variables // LAMBDA: [[G_IN_REF:%.+]] = load double*, double** [[G_PRIVATE_ADDR]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], // LAMBDA: [[SVAR_IN_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_PRIVATE_ADDR]], // LAMBDA: [[SFVAR_IN_REF:%.+]] = load float*, float** [[SFVAR_PRIVATE_ADDR]], - // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[G1_PRIVATE_ADDR]], + // LAMBDA: store double* [[G1_IN_REF]], double** [[TMP:%.+]], + // LAMBDA: [[G1_IN_REF:%.+]] = load double*, double** [[TMP]], // LAMBDA: store double* [[G1_PRIVATE]], double** [[TMP_G1_PRIVATE]], g = 1; g1 = 1; @@ -233,9 +235,11 @@ int main() { // CHECK: [[VEC_ADDR_REF:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR]], // CHECK: [[T_VAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR]], // CHECK: [[S_ARR_ADDR_REF:%.+]] = load [2 x [[S_FLOAT_TY]]]*, [2 x [[S_FLOAT_TY]]]** [[S_ARR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]** [[VAR_ADDR]], // CHECK: [[SVAR_ADDR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SVAR_ADDR]], +// CHECK: store [[S_FLOAT_TY]]* [[VAR_ADDR_REF]], [[S_FLOAT_TY]]** [[TMP:%.+]], // CHECK: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST]], -// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[VAR_ADDR]], +// CHECK: [[VAR_ADDR_REF:%.+]] = load {{.+}}, {{.+}} [[TMP]], // the distribute loop // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; @@ -307,6 +311,7 @@ int main() { // CHECK: [[T_VAR_ADDR1:%.+]] = alloca i{{[0-9]+}}*, // CHECK: [[S_ARR_ADDR1:%.+]] = alloca [2 x [[S_INT_TY]]]*, // CHECK: [[VAR_ADDR1:%.+]] = alloca [[S_INT_TY]]*, +// CHECK: [[TMP1:%.+]] = alloca [[S_INT_TY]]*, // skip loop variables // CHECK: {{.+}} = alloca i{{[0-9]+}}, // CHECK: {{.+}} = alloca i{{[0-9]+}}, @@ -333,8 +338,10 @@ int main() { // CHECK: [[VEC_ADDR_REF1:%.+]] = load [2 x i{{[0-9]+}}]*, [2 x i{{[0-9]+}}]** [[VEC_ADDR1]], // CHECK: [[T_VAR_ADDR_REF1:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[T_VAR_ADDR1]], // CHECK: [[S_ARR_ADDR_REF1:%.+]] = load [2 x [[S_INT_TY]]]*, [2 x [[S_INT_TY]]]** [[S_ARR_ADDR1]], -// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], // CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[VAR_ADDR1]], +// CHECK: store [[S_INT_TY]]* [[VAR_ADDR1_REF]], [[S_INT_TY]]** [[TMP1]], +// CHECK-DAG: store i{{[0-9]+}} 0, i{{[0-9]+}}* [[OMP_IS_LAST1]], +// CHECK: [[VAR_ADDR1_REF:%.+]] = load [[S_INT_TY]]*, [[S_INT_TY]]** [[TMP1]], // CHECK-DAG: store [[S_INT_TY]]* [[VAR_PRIV1]], [[S_INT_TY]]** [[TMP_PRIV1]], // CHECK: call void @__kmpc_for_static_init_4( // assignment: vec[i] = t_var; From 549ed544c3b37f45a8e0c26d18468339e0b7bd7e Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 23 May 2019 18:35:43 +0000 Subject: [PATCH 0066/1176] [Driver] Move the "-o OUT -x TYPE SRC.c" flags to the end of -cc1 New -cc1 arguments, such as -faddrsig, have started appearing after the input name. I personally find it convenient for the input to be the last argument to the compile command line, since I often need to edit it when running crash reproduction scripts. Differential Revision: https://reviews.llvm.org/D62270 llvm-svn: 361530 --- clang/lib/Driver/ToolChains/Clang.cpp | 50 +++++----- clang/test/Driver/cuda-options.cu | 6 +- clang/test/Driver/hip-toolchain-no-rdc.hip | 4 +- clang/test/Driver/openmp-offload.c | 102 +++++++++++---------- 4 files changed, 84 insertions(+), 78 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index d0ec3289acc86..d76e175959835 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5215,30 +5215,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, isa(JA)) CmdArgs.push_back("-disable-llvm-passes"); - if (Output.getType() == types::TY_Dependencies) { - // Handled with other dependency code. - } else if (Output.isFilename()) { - CmdArgs.push_back("-o"); - CmdArgs.push_back(Output.getFilename()); - } else { - assert(Output.isNothing() && "Invalid output."); - } - - addDashXForInput(Args, Input, CmdArgs); - - ArrayRef FrontendInputs = Input; - if (IsHeaderModulePrecompile) - FrontendInputs = ModuleHeaderInputs; - else if (Input.isNothing()) - FrontendInputs = {}; - - for (const InputInfo &Input : FrontendInputs) { - if (Input.isFilename()) - CmdArgs.push_back(Input.getFilename()); - else - Input.getInputArg().renderAsInput(Args, CmdArgs); - } - Args.AddAllArgs(CmdArgs, options::OPT_undef); const char *Exec = D.getClangProgramPath(); @@ -5436,6 +5412,32 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, TC.useIntegratedAs())) CmdArgs.push_back("-faddrsig"); + // Add the "-o out -x type src.c" flags last. This is done primarily to make + // the -cc1 command easier to edit when reproducing compiler crashes. + if (Output.getType() == types::TY_Dependencies) { + // Handled with other dependency code. + } else if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + addDashXForInput(Args, Input, CmdArgs); + + ArrayRef FrontendInputs = Input; + if (IsHeaderModulePrecompile) + FrontendInputs = ModuleHeaderInputs; + else if (Input.isNothing()) + FrontendInputs = {}; + + for (const InputInfo &Input : FrontendInputs) { + if (Input.isFilename()) + CmdArgs.push_back(Input.getFilename()); + else + Input.getInputArg().renderAsInput(Args, CmdArgs); + } + // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback) && Output.getType() == types::TY_Object && diff --git a/clang/test/Driver/cuda-options.cu b/clang/test/Driver/cuda-options.cu index 73190fd5741a1..175e4b877ce94 100644 --- a/clang/test/Driver/cuda-options.cu +++ b/clang/test/Driver/cuda-options.cu @@ -253,14 +253,14 @@ // HOST: "-cc1" "-triple" "x86_64-unknown-linux-gnu" // HOST-SAME: "-aux-triple" "nvptx64-nvidia-cuda" // HOST-NOT: "-fcuda-is-device" -// HOST-SAME: "-o" "[[HOSTOUTPUT:[^"]*]]" -// HOST-NOSAVE-SAME: "-x" "cuda" -// HOST-SAVE-SAME: "-x" "cuda-cpp-output" // There is only one GPU binary after combining it with fatbinary! // INCLUDES-DEVICE2-NOT: "-fcuda-include-gpubinary" // INCLUDES-DEVICE-SAME: "-fcuda-include-gpubinary" "[[FATBINARY]]" // There is only one GPU binary after combining it with fatbinary. // INCLUDES-DEVICE2-NOT: "-fcuda-include-gpubinary" +// HOST-SAME: "-o" "[[HOSTOUTPUT:[^"]*]]" +// HOST-NOSAVE-SAME: "-x" "cuda" +// HOST-SAVE-SAME: "-x" "cuda-cpp-output" // Match external assembler that uses compilation output. // HOST-AS: "-o" "{{.*}}.o" "[[HOSTOUTPUT]]" diff --git a/clang/test/Driver/hip-toolchain-no-rdc.hip b/clang/test/Driver/hip-toolchain-no-rdc.hip index d5e1e7dd87859..229839db6c85d 100644 --- a/clang/test/Driver/hip-toolchain-no-rdc.hip +++ b/clang/test/Driver/hip-toolchain-no-rdc.hip @@ -80,9 +80,9 @@ // CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" // CHECK-SAME: "-emit-obj" // CHECK-SAME: {{.*}} "-main-file-name" "a.cu" +// CHECK-SAME: {{.*}} "-fcuda-include-gpubinary" "[[BUNDLE_A]]" // CHECK-SAME: {{.*}} "-o" [[A_OBJ_HOST:".*o"]] "-x" "hip" // CHECK-SAME: {{.*}} [[A_SRC]] -// CHECK-SAME: {{.*}} "-fcuda-include-gpubinary" "[[BUNDLE_A]]" // // Compile device code in b.hip to code object for gfx803. @@ -152,9 +152,9 @@ // CHECK-SAME: "-aux-triple" "amdgcn-amd-amdhsa" // CHECK-SAME: "-emit-obj" // CHECK-SAME: {{.*}} "-main-file-name" "b.hip" +// CHECK-SAME: {{.*}} "-fcuda-include-gpubinary" "[[BUNDLE_A]]" // CHECK-SAME: {{.*}} "-o" [[B_OBJ_HOST:".*o"]] "-x" "hip" // CHECK-SAME: {{.*}} [[B_SRC]] -// CHECK-SAME: {{.*}} "-fcuda-include-gpubinary" "[[BUNDLE_A]]" // // Link host objects. diff --git a/clang/test/Driver/openmp-offload.c b/clang/test/Driver/openmp-offload.c index aee7e0dbb1d18..413e24bce110f 100644 --- a/clang/test/Driver/openmp-offload.c +++ b/clang/test/Driver/openmp-offload.c @@ -294,26 +294,29 @@ // // Generate host BC file. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-o" " +// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" +// CHK-COMMANDS-SAME: "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-COMMANDS-SAME: "-o" " // CHK-COMMANDS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" " -// CHK-COMMANDS-SAME: [[INPUT:[^\\/]+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-COMMANDS-SAME: [[INPUT:[^\\/]+\.c]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" " // CHK-COMMANDS-ST-SAME: [[INPUT:[^\\/]+\.c]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-COMMANDS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-COMMANDS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // // Compile for the powerpc device. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" +// CHK-COMMANDS-SAME: "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-COMMANDS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" // CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-COMMANDS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " @@ -323,14 +326,15 @@ // // Compile for the x86 device. // -// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-COMMANDS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" +// CHK-COMMANDS-SAME: "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-COMMANDS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" // CHK-COMMANDS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-COMMANDS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-pic-level" "2" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-COMMANDS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-COMMANDS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-COMMANDS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " @@ -443,35 +447,35 @@ // RUN: | FileCheck -check-prefix=CHK-BUJOBS-ST %s // Create host BC. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " // CHK-BUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "c" " -// CHK-BUJOBS-SAME: [[INPUT:[^\\/]+\.c]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-BUJOBS-SAME: [[INPUT:[^\\/]+\.c]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[HOSTPP:[^\\/]+\.i]]" "-x" "c" " // CHK-BUJOBS-ST-SAME: [[INPUT:[^\\/]+\.c]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-BUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // Create target 1 object. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // Create target 2 object. -// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-BUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "c" "{{.*}}[[INPUT]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-E" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2PP:[^\\/]+\.i]]" "-x" "c" "{{.*}}[[INPUT]]" -// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-BUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-BUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-BUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " @@ -509,23 +513,23 @@ // CHK-UBJOBS-SAME: [[HOSTPP:[^\\/]+\.i]], // CHK-UBJOBS-SAME: [[T1PP:[^\\/]+\.i]], // CHK-UBJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // CHK-UBJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs= // CHK-UBJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs= // CHK-UBJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]], // CHK-UBJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]], // CHK-UBJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // Create target 1 object. -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" // CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T1BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T1OBJ]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " @@ -534,12 +538,12 @@ // CHK-UBJOBS-ST-SAME: [[T1BIN:[^\\/]+\.out-openmp-powerpc64le-ibm-linux-gnu]]" {{.*}}"{{.*}}[[T1OBJ]]" // Create target 2 object. -// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-UBJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" // CHK-UBJOBS: ld{{(\.exe)?}}" {{.*}}"-o" " // CHK-UBJOBS-SAME: [[T2BIN:[^\\/]+\.out]]" {{.*}}"{{.*}}[[T2OBJ]]" -// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-UBJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " @@ -605,32 +609,32 @@ // CHK-UBUJOBS-SAME: [[HOSTPP:[^\\/]+\.i]], // CHK-UBUJOBS-SAME: [[T1PP:[^\\/]+\.i]], // CHK-UBUJOBS-SAME: [[T2PP:[^\\/]+\.i]]" "-unbundle" -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBUJOBS-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // CHK-UBUJOBS-ST: clang-offload-bundler{{.*}}" "-type=i" "-targets=host-powerpc64le-unknown-linux,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu" "-inputs= // CHK-UBUJOBS-ST-SAME: [[INPUT:[^\\/]+\.i]]" "-outputs= // CHK-UBUJOBS-ST-SAME: [[HOSTPP:[^\\/,]+\.i]], // CHK-UBUJOBS-ST-SAME: [[T1PP:[^\\/,]+\.i]], // CHK-UBUJOBS-ST-SAME: [[T2PP:[^\\/,]+\.i]]" "-unbundle" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" "-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-targets=powerpc64le-ibm-linux-gnu,x86_64-pc-linux-gnu" {{.*}}"-o" " +// CHK-UBUJOBS-ST-SAME: [[HOSTBC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[HOSTPP]]" // Create target 1 object. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS-SAME: [[T1OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS-ST-SAME: [[T1BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T1PP]]" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "powerpc64le-ibm-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T1BC]]" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "powerpc64le-ibm-linux-gnu" "-filetype" "obj" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T1OBJ:[^\\/]+\.o]]" "{{.*}}[[T1ASM]]" // Create target 2 object. -// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" -// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-o" " -// CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" +// CHK-UBUJOBS: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-obj" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS-SAME: [[T2OBJ:[^\\/]+\.o]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" +// CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-emit-llvm-bc" {{.*}}"-fopenmp" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" "{{.*}}[[HOSTBC]]" {{.*}}"-o" " +// CHK-UBUJOBS-ST-SAME: [[T2BC:[^\\/]+\.bc]]" "-x" "cpp-output" "{{.*}}[[T2PP]]" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1" "-triple" "x86_64-pc-linux-gnu" "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-S" {{.*}}"-fopenmp" {{.*}}"-o" " // CHK-UBUJOBS-ST-SAME: [[T2ASM:[^\\/]+\.s]]" "-x" "ir" "{{.*}}[[T2BC]]" // CHK-UBUJOBS-ST: clang{{.*}}" "-cc1as" "-triple" "x86_64-pc-linux-gnu" "-filetype" "obj" {{.*}}"-o" " @@ -654,4 +658,4 @@ // RUN: %clang -### -no-canonical-prefixes -target powerpc64le-linux -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHK-FOPENMP-IS-DEVICE %s -// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}.c" "-fopenmp-is-device" "-fopenmp-host-ir-file-path" +// CHK-FOPENMP-IS-DEVICE: clang{{.*}} "-aux-triple" "powerpc64le-unknown-linux" {{.*}}"-fopenmp-is-device" "-fopenmp-host-ir-file-path" {{.*}}.c" From 517e3cb0a57d0df784a4d246edda36ec2cc2c254 Mon Sep 17 00:00:00 2001 From: Antonio Afonso Date: Thu, 23 May 2019 18:35:54 +0000 Subject: [PATCH 0067/1176] Test commit access by removing a empty line llvm-svn: 361531 --- lldb/source/Core/ModuleList.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index e02c6e5af27b6..fd943d7fc1d63 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -114,7 +114,6 @@ bool ModuleListProperties::SetClangModulesCachePath(llvm::StringRef path) { nullptr, ePropertyClangModulesCachePath, path); } - ModuleList::ModuleList() : m_modules(), m_modules_mutex(), m_notifier(nullptr) {} From 4fb41a24bcf281afcbed45fff7fdd1129c3ea0d5 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Thu, 23 May 2019 18:43:19 +0000 Subject: [PATCH 0068/1176] [git] Be more specific when looking for llvm-svn Summary: A commit may, for some reason, have `llvm-svn:` in it multiple times. It may even take up the whole line and look identical to what gets added automatically when svn commits land in github. To workaround this, make changes to both lookups: 1) When doing the git -> svn lookup, make sure to go through the whole message, and: a) Only look for llvm-svn starting at the beginning of the line (excluding the whitespace that `git log` adds). b) Take the last one (at the end of the commit message), if there are multiple matches. 2) When doing the svn -> git lookup, look through a sizeable but still reasonably small number of git commits (10k, about 4-5 months right now), and: a) Only consider commits with the '^llvm-svn: NNNNNN' we expect, and b) Only consider those that also follow the same git -> svn matching above. (Error if it's not exactly one commit). Reviewers: jyknight Reviewed By: jyknight Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60017 llvm-svn: 361532 --- llvm/utils/git-svn/git-llvm | 62 +++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/llvm/utils/git-svn/git-llvm b/llvm/utils/git-svn/git-llvm index 28a0a9bbf4d16..53abc538ccaf3 100755 --- a/llvm/utils/git-svn/git-llvm +++ b/llvm/utils/git-svn/git-llvm @@ -413,12 +413,22 @@ def cmd_push(args): def lookup_llvm_svn_id(git_commit_hash): - commit_msg = git('log', '-1', git_commit_hash, ignore_errors=True) + # Use --format=%b to get the raw commit message, without any extra + # whitespace. + commit_msg = git('log', '-1', '--format=%b', git_commit_hash, + ignore_errors=True) if len(commit_msg) == 0: die("Can't find git commit " + git_commit_hash) - svn_match = re.search('llvm-svn: (\d{5,7})$', commit_msg) + # If a commit has multiple "llvm-svn:" lines (e.g. if the commit is + # reverting/quoting a previous commit), choose the last one, which should + # be the authoritative one. + svn_match_iter = re.finditer('^llvm-svn: (\d{5,7})$', commit_msg, + re.MULTILINE) + svn_match = None + for m in svn_match_iter: + svn_match = m.group(1) if svn_match: - return int(svn_match.group(1)) + return int(svn_match) die("Can't find svn revision in git commit " + git_commit_hash) @@ -437,6 +447,28 @@ def cmd_svn_lookup(args): log('r' + str(lookup_llvm_svn_id(args.git_commit_hash))) +def git_hash_by_svn_rev(svn_rev): + '''Find the git hash for a given svn revision. + + This check is paranoid: 'llvm-svn: NNNNNN' could exist on its own line + somewhere else in the commit message. Look in the full log message to see + if it's actually on the last line. + + Since this check is expensive (we're searching every single commit), limit + to the past 10k commits (about 5 months). + ''' + possible_hashes = git( + 'log', '--format=%H', '--grep', '^llvm-svn: %d$' % svn_rev, + 'HEAD~10000...HEAD').split('\n') + matching_hashes = [h for h in possible_hashes + if lookup_llvm_svn_id(h) == svn_rev] + if len(matching_hashes) > 1: + die("svn revision r%d has ambiguous commits: %s" % ( + svn_rev, ', '.join(matching_hashes))) + elif len(matching_hashes) < 1: + die("svn revision r%d matches no commits" % svn_rev) + return matching_hashes[0] + def cmd_revert(args): '''Revert a commit by either SVN id (rNNNNNN) or git hash. This also populates the git commit message with both the SVN revision and git hash of @@ -459,24 +491,28 @@ def cmd_revert(args): # the git commit. svn_match = re.match('^r(\d{5,7})$', args.revision) if svn_match: - svn_rev = svn_match.group(1) + # If the revision looks like rNNNNNN, use that as the svn revision, and + # grep through git commits to find which one corresponds to that svn + # revision. + svn_rev = int(svn_match.group(1)) + git_hash = git_hash_by_svn_rev(svn_rev) else: - svn_rev = str(lookup_llvm_svn_id(args.revision)) + # Otherwise, this looks like a git hash, so we just need to grab the svn + # revision from the end of the commit message. + # Get the actual git hash in case the revision is something like "HEAD~1" + git_hash = git('rev-parse', '--verify', args.revision + '^{commit}') + svn_rev = lookup_llvm_svn_id(git_hash) - oneline = git('log', '--all', '-1', '--format=%H %s', '--grep', - 'llvm-svn: ' + svn_rev) - if len(oneline) == 0: - die("Can't find svn revision r" + svn_rev) - (git_hash, msg) = oneline.split(' ', 1) + msg = git('log', '-1', '--format=%s', git_hash) - log_verbose('Ready to revert r%s/%s: "%s"' % (svn_rev, git_hash, msg)) + log_verbose('Ready to revert r%d (%s): "%s"' % (svn_rev, git_hash, msg)) revert_args = ['revert', '--no-commit', git_hash] # TODO: Running --edit doesn't seem to work, with errors that stdin is not # a tty. commit_args = [ 'commit', '-m', 'Revert ' + msg, - '-m', 'This reverts r%s (git commit %s)' % (svn_rev, git_hash)] + '-m', 'This reverts r%d (git commit %s)' % (svn_rev, git_hash)] if args.dry_run: log("Would have run the following commands, if this weren't a dry run:\n" '1) git %s\n2) git %s' % ( @@ -487,7 +523,7 @@ def cmd_revert(args): git(*revert_args) commit_log = git(*commit_args) - log('Created revert of r%s: %s' % (svn_rev, commit_log)) + log('Created revert of r%d: %s' % (svn_rev, commit_log)) log("Run 'git llvm push -n' to inspect your changes and " "run 'git llvm push' when ready") From 3249be1e03c672ffe68f5ad8e0e31cdcb8e441f8 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 23 May 2019 18:46:03 +0000 Subject: [PATCH 0069/1176] [InstCombine] be more careful when transforming a shuffle mask This is reduced from a fuzzer test: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14890 Usually, demanded elements should be able to simplify shuffle mask elements that are pointing to undef elements of its source operands, but that doesn't happen in the test case. llvm-svn: 361533 --- .../InstCombine/InstCombineVectorOps.cpp | 25 ++++++++++++++++--- .../Transforms/InstCombine/vec_shuffle.ll | 17 +++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index ecc4df179efd4..c2ea0733a48e4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -1635,8 +1635,8 @@ static Instruction *foldIdentityPaddedShuffles(ShuffleVectorInst &Shuf) { // We limit this transform to power-of-2 types because we expect that the // backend can convert the simplified IR patterns to identical nodes as the // original IR. - // TODO: If we can verify that behavior for arbitrary types, the power-of-2 - // checks can be removed. + // TODO: If we can verify the same behavior for arbitrary types, the + // power-of-2 checks can be removed. Value *X = Shuffle0->getOperand(0); Value *Y = Shuffle1->getOperand(0); if (X->getType() != Y->getType() || @@ -1663,10 +1663,27 @@ static Instruction *foldIdentityPaddedShuffles(ShuffleVectorInst &Shuf) { for (int i = 0, e = Mask.size(); i != e; ++i) { if (Mask[i] == -1) continue; - if (Mask[i] < WideElts) + + // If this shuffle is choosing an undef element from 1 of the sources, that + // element is undef. + if (Mask[i] < WideElts) { + if (Shuffle0->getMaskValue(Mask[i]) == -1) + continue; + } else { + if (Shuffle1->getMaskValue(Mask[i] - WideElts) == -1) + continue; + } + + // If this shuffle is choosing from the 1st narrow op, the mask element is + // the same. If this shuffle is choosing from the 2nd narrow op, the mask + // element is offset down to adjust for the narrow vector widths. + if (Mask[i] < WideElts) { + assert(Mask[i] < NarrowElts && "Unexpected shuffle mask"); NewMask[i] = ConstantInt::get(I32Ty, Mask[i]); - else + } else { + assert(Mask[i] < (WideElts + NarrowElts) && "Unexpected shuffle mask"); NewMask[i] = ConstantInt::get(I32Ty, Mask[i] - (WideElts - NarrowElts)); + } } return new ShuffleVectorInst(X, Y, ConstantVector::get(NewMask)); } diff --git a/llvm/test/Transforms/InstCombine/vec_shuffle.ll b/llvm/test/Transforms/InstCombine/vec_shuffle.ll index 3dcd7d7bf335f..65af43ea2a1fa 100644 --- a/llvm/test/Transforms/InstCombine/vec_shuffle.ll +++ b/llvm/test/Transforms/InstCombine/vec_shuffle.ll @@ -1235,3 +1235,20 @@ define <4 x double> @not_insert_subvector_shuffles_with_same_size(<2 x double> % %s3 = shufflevector <4 x double> %s2, <4 x double> %s1, <4 x i32> ret <4 x double> %s3 } + +; Demanded vector elements may not be able to simplify a shuffle mask +; before we try to narrow it. This used to crash. + +define <4 x float> @insert_subvector_crash_invalid_mask_elt(<2 x float> %x, <4 x float>* %p) { +; CHECK-LABEL: @insert_subvector_crash_invalid_mask_elt( +; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <2 x float> [[X:%.*]], <2 x float> undef, <4 x i32> +; CHECK-NEXT: [[I:%.*]] = shufflevector <2 x float> [[X]], <2 x float> undef, <4 x i32> +; CHECK-NEXT: store <4 x float> [[I]], <4 x float>* [[P:%.*]], align 16 +; CHECK-NEXT: ret <4 x float> [[WIDEN]] +; + %widen = shufflevector <2 x float> %x, <2 x float> undef, <4 x i32> + %ext2 = extractelement <2 x float> %x, i32 0 + %I = insertelement <4 x float> %widen, float %ext2, i16 0 + store <4 x float> %I, <4 x float>* %p + ret <4 x float> %widen +} From 267ac925fb4ed2dad94177807d9a38ba83f2f4f0 Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Thu, 23 May 2019 18:51:02 +0000 Subject: [PATCH 0070/1176] [NewPassManager] Add tuning option: SLPVectorization [clang-change] Summary: NewPassManager is not using CodeGenOpts values before this patch. [to be coupled with D61616] Reviewers: chandlerc Subscribers: jlebar, cfe-commits, llvm-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D61617 llvm-svn: 361534 --- clang/lib/CodeGen/BackendUtil.cpp | 9 ++++++++- clang/test/CodeGen/loop-vectorize.c | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/loop-vectorize.c diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 32eb776a6d218..1dbeec1c17833 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1050,7 +1050,14 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( CodeGenOpts.DebugInfoForProfiling); } - PassBuilder PB(TM.get(), PipelineTuningOptions(), PGOOpt); + PipelineTuningOptions PTO; + // For historical reasons, loop interleaving is set to mirror setting for loop + // unrolling. + PTO.LoopInterleaving = CodeGenOpts.UnrollLoops; + PTO.LoopVectorization = CodeGenOpts.VectorizeLoop; + PTO.SLPVectorization = CodeGenOpts.VectorizeSLP; + + PassBuilder PB(TM.get(), PTO, PGOOpt); // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { diff --git a/clang/test/CodeGen/loop-vectorize.c b/clang/test/CodeGen/loop-vectorize.c new file mode 100644 index 0000000000000..28bd50bbd2e92 --- /dev/null +++ b/clang/test/CodeGen/loop-vectorize.c @@ -0,0 +1,25 @@ +// RUN: %clang -target x86_64 -S -c -O1 -fvectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-ENABLE-VECT +// RUN: %clang -target x86_64 -S -c -O1 -fno-vectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DISABLE-VECT +// RUN: %clang -target x86_64 -fexperimental-new-pass-manager -S -c -O1 -fvectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-ENABLE-VECT +// RUN: %clang -target x86_64 -fexperimental-new-pass-manager -S -c -O1 -fno-vectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DISABLE-VECT + +// CHECK-ENABLE-VECT-LABEL: @for_test() +// CHECK-ENABLE-VECT: fmul <{{[0-9]+}} x double> + +// CHECK-DISABLE-VECT-LABEL: @for_test() +// CHECK-DISABLE-VECT: fmul double +// CHECK-DISABLE-VECT-NOT: fmul <{{[0-9]+}} x double> + +#include + +void for_test() { + double A[1000], B[1000]; + int L = 500; + for (int i = 0; i < L; i++) { + A[i] = i; + } + for (int i = 0; i < L; i++) { + B[i] = A[i]*5; + } + printf("%lf %lf\n", A[0], B[0]); +} From e836096f01f1b9d63359c5b781fcfb9d1e3c39d8 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Thu, 23 May 2019 18:51:52 +0000 Subject: [PATCH 0071/1176] [CMake] Fixing errors in r361513 Summary: I somehow messed this up. libcxx appends the subdirectories itself, so we don't need to add them here. Also, r361513 broke the "projects" build of libcxx because it always included the extra targets. Reviewers: lebedev.ri, mclow.lists Subscribers: mgorny, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62336 llvm-svn: 361535 --- llvm/runtimes/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt index b9436025f5cd1..9016efe600e79 100644 --- a/llvm/runtimes/CMakeLists.txt +++ b/llvm/runtimes/CMakeLists.txt @@ -209,7 +209,7 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) else() # if this is included from LLVM's CMake include(LLVMExternalProjectUtils) - if (LLVM_EXTERNAL_LIBCXX_SOURCE_DIR) + if (LLVM_EXTERNAL_LIBCXX_SOURCE_DIR AND "libcxx" IN_LIST LLVM_ENABLE_RUNTIMES) set(LIBCXX_HEADER_DIR ${LLVM_INCLUDE_DIR}/c++/v1/) set(CXX_HEADER_TARGET runtime-libcxx-headers) add_subdirectory(${LLVM_EXTERNAL_LIBCXX_SOURCE_DIR}/include ${CXX_HEADER_TARGET}) From a8e0d49c0ce0f1015cc20d3fcac823facc69df66 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 23 May 2019 18:55:00 +0000 Subject: [PATCH 0072/1176] Fix unresolved symbols when linking tools/clang/unittests/Tooling/ToolingTests Summary: Add correct cmake dependencies so that `ToolingTests` link successfully. Patch by Guanzhong Chen Reviewers: tlively, aheejin Reviewed By: tlively Subscribers: mgorny, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62333 llvm-svn: 361536 --- clang/unittests/Tooling/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt index af8a35d92517d..111e07e8c907f 100644 --- a/clang/unittests/Tooling/CMakeLists.txt +++ b/clang/unittests/Tooling/CMakeLists.txt @@ -71,6 +71,7 @@ target_link_libraries(ToolingTests clangToolingCore clangToolingInclusions clangToolingRefactor + LLVMTestingSupport ) From 63729b0c49d29ea96cb89c54187f5a3d2e1a0602 Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Thu, 23 May 2019 19:07:41 +0000 Subject: [PATCH 0073/1176] [SLPVectorizer] Set flag to previous default. Summary: The refactoring in r360276 moved the `RunSLPVectorization` flag and added the default explicitly. The default should have been `false`, as before. The new pass manager used to have SLPVectorization on by default, now it's off in opt, and needs D61617 checked in to enable it in clang. Reviewers: chandlerc Subscribers: mehdi_amini, jlebar, eraman, steven_wu, dexonsmith, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61955 llvm-svn: 361537 --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 2 +- llvm/test/Other/new-pm-defaults.ll | 1 - llvm/test/Other/new-pm-thinlto-defaults.ll | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 5b40e5ef1f08a..c0c2c85b8f483 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -106,7 +106,7 @@ using namespace slpvectorizer; STATISTIC(NumVectorInstructions, "Number of vector instructions generated"); cl::opt - llvm::RunSLPVectorization("vectorize-slp", cl::init(true), cl::Hidden, + llvm::RunSLPVectorization("vectorize-slp", cl::init(false), cl::Hidden, cl::desc("Run the SLP vectorization passes")); static cl::opt diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll index 317bffcefdc12..d29c127d98453 100644 --- a/llvm/test/Other/new-pm-defaults.ll +++ b/llvm/test/Other/new-pm-defaults.ll @@ -243,7 +243,6 @@ ; CHECK-O-NEXT: Running analysis: LoopAccessAnalysis ; CHECK-O-NEXT: Running pass: InstCombinePass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass -; CHECK-O-NEXT: Running pass: SLPVectorizerPass ; CHECK-O-NEXT: Running pass: InstCombinePass ; CHECK-O-NEXT: Running pass: LoopUnrollPass ; CHECK-O-NEXT: Running pass: WarnMissedTransformationsPass diff --git a/llvm/test/Other/new-pm-thinlto-defaults.ll b/llvm/test/Other/new-pm-thinlto-defaults.ll index 079cea9255e5b..8dc6bf7a239c2 100644 --- a/llvm/test/Other/new-pm-thinlto-defaults.ll +++ b/llvm/test/Other/new-pm-thinlto-defaults.ll @@ -217,7 +217,6 @@ ; CHECK-POSTLINK-O-NEXT: Running analysis: LoopAccessAnalysis ; CHECK-POSTLINK-O-NEXT: Running pass: InstCombinePass ; CHECK-POSTLINK-O-NEXT: Running pass: SimplifyCFGPass -; CHECK-POSTLINK-O-NEXT: Running pass: SLPVectorizerPass ; CHECK-POSTLINK-O-NEXT: Running pass: InstCombinePass ; CHECK-POSTLINK-O-NEXT: Running pass: LoopUnrollPass ; CHECK-POSTLINK-O-NEXT: Running pass: WarnMissedTransformationsPass From cb64cd9b6041c2c8aaca6d01023e5d7963873701 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 19:15:05 +0000 Subject: [PATCH 0074/1176] [NFC] UpdateTestChecks: asm.py: fix whitespace issue llvm-svn: 361538 --- llvm/utils/UpdateTestChecks/asm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index 459aa42381ab7..78da89d2730ca 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -29,7 +29,7 @@ class string: ASM_FUNCTION_AARCH64_RE = re.compile( r'^_?(?P[^:]+):[ \t]*\/\/[ \t]*@(?P=func)\n' - r'(?:[ \t]+.cfi_startproc\n)?' # drop optional cfi noise + r'(?:[ \t]+.cfi_startproc\n)?' # drop optional cfi noise r'(?P.*?)\n' # This list is incomplete r'.Lfunc_end[0-9]+:\n', From a83bf477702e96f2ca9e1e21a59704b11f58f958 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 23 May 2019 19:32:46 +0000 Subject: [PATCH 0075/1176] [gdb-remote] Fix more issues with thread_result_t More fixes needed to un-break the Windows bot. llvm-svn: 361539 --- .../Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp | 6 +++--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 9c3a02e77e58a..3886b6cfe009e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -541,7 +541,7 @@ bool GDBRemoteCommunication::DecompressPacket() { #if defined(HAVE_LIBCOMPRESSION) if (m_compression_type == CompressionType::ZlibDeflate || m_compression_type == CompressionType::LZFSE || - m_compression_type == CompressionType::LZ4 || + m_compression_type == CompressionType::LZ4 || m_compression_type == CompressionType::LZMA) { compression_algorithm compression_type; if (m_compression_type == CompressionType::LZFSE) @@ -578,7 +578,7 @@ bool GDBRemoteCommunication::DecompressPacket() { if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) { decompressed_bytes = compression_decode_buffer( decompressed_buffer, decompressed_bufsize, - (uint8_t *)unescaped_content.data(), unescaped_content.size(), + (uint8_t *)unescaped_content.data(), unescaped_content.size(), m_decompression_scratch, compression_type); } } @@ -925,7 +925,7 @@ GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) { eConnectionStatusSuccess) comm->SetConnection(nullptr); } - return nullptr; + return {}; } Status GDBRemoteCommunication::StartDebugserverProcess( diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 422b092895592..c4df4e716d0df 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3913,7 +3913,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ") thread exiting...", __FUNCTION__, arg, process->GetID()); - return nullptr; + return {}; } // uint32_t From e4b27869c60cb1311c4396e057c21573e19e62cd Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Thu, 23 May 2019 19:35:40 +0000 Subject: [PATCH 0076/1176] [NewPassManager] Add tuning option: LoopUnrolling [NFC]. Summary: Mirror tuning option from old pass manager in new pass manager. Reviewers: chandlerc Subscribers: jlebar, dmgreen, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61618 llvm-svn: 361540 --- llvm/include/llvm/Passes/PassBuilder.h | 3 +++ llvm/lib/Passes/PassBuilder.cpp | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 69756dd9b46f6..383f49e0d7585 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -85,6 +85,9 @@ class PipelineTuningOptions { /// is that of the flag: `vectorize-slp`. bool SLPVectorization; + /// Tuning option to enable/disable loop unrolling. Its default value is true. + bool LoopUnrolling; + /// Tuning option to cap the number of calls to retrive clobbering accesses in /// MemorySSA, in LICM. unsigned LicmMssaOptCap; diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index c7976ce2702d2..1d17f91d5a8d3 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -217,6 +217,7 @@ PipelineTuningOptions::PipelineTuningOptions() { LoopInterleaving = EnableLoopInterleaving; LoopVectorization = EnableLoopVectorization; SLPVectorization = RunSLPVectorization; + LoopUnrolling = true; LicmMssaOptCap = SetLicmMssaOptCap; LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap; } @@ -459,8 +460,9 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, // Do not enable unrolling in PreLinkThinLTO phase during sample PGO // because it changes IR to makes profile annotation in back compile // inaccurate. - if (Phase != ThinLTOPhase::PreLink || !PGOOpt || - PGOOpt->Action != PGOOptions::SampleUse) + if ((Phase != ThinLTOPhase::PreLink || !PGOOpt || + PGOOpt->Action != PGOOptions::SampleUse) && + PTO.LoopUnrolling) LPM2.addPass(LoopFullUnrollPass(Level)); for (auto &C : LoopOptimizerEndEPCallbacks) @@ -907,7 +909,8 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( OptimizePM.addPass( createFunctionToLoopPassAdaptor(LoopUnrollAndJamPass(Level))); } - OptimizePM.addPass(LoopUnrollPass(LoopUnrollOptions(Level))); + if (PTO.LoopUnrolling) + OptimizePM.addPass(LoopUnrollPass(LoopUnrollOptions(Level))); OptimizePM.addPass(WarnMissedTransformationsPass()); OptimizePM.addPass(InstCombinePass()); OptimizePM.addPass(RequireAnalysisPass()); From 5c714cbdd83166e10b27b8e5ea2700654da2e90b Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 23 May 2019 19:38:14 +0000 Subject: [PATCH 0077/1176] AMDGPU: Correct maximum possible private allocation size We were assuming a much larger possible per-wave visible stack allocation than is possible: https://github.com/RadeonOpenCompute/ROCR-Runtime/blob/faa3ae51388517353afcdaf9c16621f879ef0a59/src/core/runtime/amd_gpu_agent.cpp#L70 Based on this, we can assume the high 15 bits of a frame index or sret are 0. The frame index value is the per-lane offset, so the maximum frame index value is MAX_WAVE_SCRATCH / wavesize. Remove the corresponding subtarget feature and option that made this configurable. llvm-svn: 361541 --- llvm/lib/Target/AMDGPU/AMDGPU.td | 7 ----- llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp | 1 - llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h | 13 +++++--- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 21 ++++--------- .../CodeGen/AMDGPU/frame-index-elimination.ll | 6 ++-- llvm/test/CodeGen/AMDGPU/function-returns.ll | 20 ++++++++++++ .../CodeGen/AMDGPU/huge-private-buffer.ll | 31 +++++++++++++------ 7 files changed, 58 insertions(+), 41 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td index 341ef73a21c91..9938eeaa528eb 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -458,13 +458,6 @@ def FeatureMaxPrivateElementSize4 : FeatureMaxPrivateElementSize<4>; def FeatureMaxPrivateElementSize8 : FeatureMaxPrivateElementSize<8>; def FeatureMaxPrivateElementSize16 : FeatureMaxPrivateElementSize<16>; -def FeatureEnableHugePrivateBuffer : SubtargetFeature< - "huge-private-buffer", - "EnableHugePrivateBuffer", - "true", - "Enable private/scratch buffer sizes greater than 128 GB" ->; - def FeatureDumpCode : SubtargetFeature <"DumpCode", "DumpCode", "true", diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp index a88218f68b543..09b806bd06a55 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -190,7 +190,6 @@ GCNSubtarget::GCNSubtarget(const Triple &TT, StringRef GPU, StringRef FS, EnableCuMode(false), TrapHandler(false), - EnableHugePrivateBuffer(false), EnableLoadStoreOpt(false), EnableUnsafeDSOffsetFolding(false), EnableSIScheduler(false), diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h index 1ef72622980bf..34166aacf41a1 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -299,7 +299,6 @@ class GCNSubtarget : public AMDGPUGenSubtargetInfo, bool TrapHandler; // Used as options. - bool EnableHugePrivateBuffer; bool EnableLoadStoreOpt; bool EnableUnsafeDSOffsetFolding; bool EnableSIScheduler; @@ -377,6 +376,9 @@ class GCNSubtarget : public AMDGPUGenSubtargetInfo, SITargetLowering TLInfo; SIFrameLowering FrameLowering; + // See COMPUTE_TMPRING_SIZE.WAVESIZE, 13-bit field in units of 256-dword. + static const unsigned MaxWaveScratchSize = (256 * 4) * ((1 << 13) - 1); + public: GCNSubtarget(const Triple &TT, StringRef GPU, StringRef FS, const GCNTargetMachine &TM); @@ -436,6 +438,11 @@ class GCNSubtarget : public AMDGPUGenSubtargetInfo, return Log2_32(WavefrontSize); } + /// Return the number of high bits known to be zero fror a frame index. + unsigned getKnownHighZeroBitsForFrameIndex() const { + return countLeadingZeros(MaxWaveScratchSize) + getWavefrontSizeLog2(); + } + int getLDSBankCount() const { return LDSBankCount; } @@ -526,10 +533,6 @@ class GCNSubtarget : public AMDGPUGenSubtargetInfo, return isAmdHsaOS() ? TrapHandlerAbiHsa : TrapHandlerAbiNone; } - bool enableHugePrivateBuffer() const { - return EnableHugePrivateBuffer; - } - bool unsafeDSOffsetFoldingEnabled() const { return EnableUnsafeDSOffsetFolding; } diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index c4c0e4047fcfb..c2cda5ef4d7ce 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -93,12 +93,6 @@ static cl::opt EnableVGPRIndexMode( cl::desc("Use GPR indexing mode instead of movrel for vector indexing"), cl::init(false)); -static cl::opt AssumeFrameIndexHighZeroBits( - "amdgpu-frame-index-zero-bits", - cl::desc("High bits of frame index assumed to be zero"), - cl::init(5), - cl::ReallyHidden); - static cl::opt DisableLoopAlignment( "amdgpu-disable-loop-alignment", cl::desc("Do not align and prefetch loops"), @@ -2059,13 +2053,14 @@ SDValue SITargetLowering::LowerFormalArguments( Reg = MF.addLiveIn(Reg, RC); SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, VT); - if (Arg.Flags.isSRet() && !getSubtarget()->enableHugePrivateBuffer()) { + if (Arg.Flags.isSRet()) { // The return object should be reasonably addressable. // FIXME: This helps when the return is a real sret. If it is a // automatically inserted sret (i.e. CanLowerReturn returns false), an // extra copy is inserted in SelectionDAGBuilder which obscures this. - unsigned NumBits = 32 - AssumeFrameIndexHighZeroBits; + unsigned NumBits + = 32 - getSubtarget()->getKnownHighZeroBitsForFrameIndex(); Val = DAG.getNode(ISD::AssertZext, DL, VT, Val, DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), NumBits))); } @@ -9970,14 +9965,10 @@ void SITargetLowering::computeKnownBitsForFrameIndex(const SDValue Op, TargetLowering::computeKnownBitsForFrameIndex(Op, Known, DemandedElts, DAG, Depth); - if (getSubtarget()->enableHugePrivateBuffer()) - return; - - // Technically it may be possible to have a dispatch with a single workitem - // that uses the full private memory size, but that's not really useful. We - // can't use vaddr in MUBUF instructions if we don't know the address + // Set the high bits to zero based on the maximum allowed scratch size per + // wave. We can't use vaddr in MUBUF instructions if we don't know the address // calculation won't overflow, so assume the sign bit is never set. - Known.Zero.setHighBits(AssumeFrameIndexHighZeroBits); + Known.Zero.setHighBits(getSubtarget()->getKnownHighZeroBitsForFrameIndex()); } unsigned SITargetLowering::getPrefLoopAlignment(MachineLoop *ML) const { diff --git a/llvm/test/CodeGen/AMDGPU/frame-index-elimination.ll b/llvm/test/CodeGen/AMDGPU/frame-index-elimination.ll index 28521af83e04d..92a255ceae6de 100644 --- a/llvm/test/CodeGen/AMDGPU/frame-index-elimination.ll +++ b/llvm/test/CodeGen/AMDGPU/frame-index-elimination.ll @@ -60,7 +60,7 @@ define void @func_add_constant_to_fi_i32() #0 { ; GFX9-NEXT: v_lshrrev_b32_e64 [[SCALED:v[0-9]+]], 6, s6 ; GFX9-NEXT: v_add_u32_e32 v0, 4, [[SCALED]] -; GCN-NEXT: v_mul_lo_u32 v0, v0, 9 +; GCN-NEXT: v_mul_u32_u24_e32 v0, 9, v0 ; GCN-NOT: v_mov ; GCN: ds_write_b32 v0, v0 define void @func_other_fi_user_i32() #0 { @@ -172,7 +172,7 @@ ret: ; GFX9-DAG: v_lshrrev_b32_e64 [[SCALED:v[0-9]+]], 6, s6 ; GFX9: v_add_u32_e32 [[VZ:v[0-9]+]], s6, [[SCALED]] -; GCN: v_mul_lo_u32 [[VZ]], [[VZ]], 9 +; GCN: v_mul_u32_u24_e32 [[VZ]], 9, [[VZ]] ; GCN: ds_write_b32 v0, [[VZ]] define void @func_other_fi_user_non_inline_imm_offset_i32() #0 { %alloca0 = alloca [128 x i32], align 4, addrspace(5) @@ -196,7 +196,7 @@ define void @func_other_fi_user_non_inline_imm_offset_i32() #0 { ; GFX9-DAG: v_lshrrev_b32_e64 [[SCALED:v[0-9]+]], 6, [[DIFF]] ; GFX9: v_add_u32_e32 [[VZ:v[0-9]+]], [[OFFSET]], [[SCALED]] -; GCN: v_mul_lo_u32 [[VZ]], [[VZ]], 9 +; GCN: v_mul_u32_u24_e32 [[VZ]], 9, [[VZ]] ; GCN: ds_write_b32 v0, [[VZ]] define void @func_other_fi_user_non_inline_imm_offset_i32_vcc_live() #0 { %alloca0 = alloca [128 x i32], align 4, addrspace(5) diff --git a/llvm/test/CodeGen/AMDGPU/function-returns.ll b/llvm/test/CodeGen/AMDGPU/function-returns.ll index f9631e615c9db..8e73ee3c1f105 100644 --- a/llvm/test/CodeGen/AMDGPU/function-returns.ll +++ b/llvm/test/CodeGen/AMDGPU/function-returns.ll @@ -570,4 +570,24 @@ define { <3 x float>, i32 } @v3f32_struct_func_void_wasted_reg() #0 { ret { <3 x float>, i32 } %insert.4 } +; GCN-LABEL: {{^}}void_func_sret_max_known_zero_bits: +; GCN: v_lshrrev_b32_e32 [[LSHR16:v[0-9]+]], 16, v0 +; GCN: ds_write_b32 {{v[0-9]+}}, [[LSHR16]] + +; GCN: v_mov_b32_e32 [[HIGH_BITS:v[0-9]+]], 0 +; GCN: ds_write_b32 {{v[0-9]+}}, [[HIGH_BITS]] +; GCN-NEXT: ds_write_b32 {{v[0-9]+}}, [[HIGH_BITS]] +define void @void_func_sret_max_known_zero_bits(i8 addrspace(5)* sret %arg0) #0 { + %arg0.int = ptrtoint i8 addrspace(5)* %arg0 to i32 + + %lshr0 = lshr i32 %arg0.int, 16 + %lshr1 = lshr i32 %arg0.int, 17 + %lshr2 = lshr i32 %arg0.int, 18 + + store volatile i32 %lshr0, i32 addrspace(3)* undef + store volatile i32 %lshr1, i32 addrspace(3)* undef + store volatile i32 %lshr2, i32 addrspace(3)* undef + ret void +} + attributes #0 = { nounwind } diff --git a/llvm/test/CodeGen/AMDGPU/huge-private-buffer.ll b/llvm/test/CodeGen/AMDGPU/huge-private-buffer.ll index 8e54dcbd16934..dfd75235f808e 100644 --- a/llvm/test/CodeGen/AMDGPU/huge-private-buffer.ll +++ b/llvm/test/CodeGen/AMDGPU/huge-private-buffer.ll @@ -1,31 +1,42 @@ ; RUN: llc -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GCN %s -; GCN-LABEL: {{^}}scratch_buffer_known_high_bit_small: +; GCN-LABEL: {{^}}scratch_buffer_known_high_masklo16: +; GCN: v_mov_b32_e32 [[FI:v[0-9]+]], 4 +; GCN: v_and_b32_e32 [[MASKED:v[0-9]+]], 0xfffc, [[FI]] +; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[MASKED]] +define amdgpu_kernel void @scratch_buffer_known_high_masklo16() #0 { + %alloca = alloca i32, align 4, addrspace(5) + store volatile i32 0, i32 addrspace(5)* %alloca + %toint = ptrtoint i32 addrspace(5)* %alloca to i32 + %masked = and i32 %toint, 65535 + store volatile i32 %masked, i32 addrspace(1)* undef + ret void +} + +; GCN-LABEL: {{^}}scratch_buffer_known_high_masklo17: ; GCN: v_mov_b32_e32 [[FI:v[0-9]+]], 4 ; GCN-NOT: [[FI]] ; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[FI]] -define amdgpu_kernel void @scratch_buffer_known_high_bit_small() #0 { +define amdgpu_kernel void @scratch_buffer_known_high_masklo17() #0 { %alloca = alloca i32, align 4, addrspace(5) store volatile i32 0, i32 addrspace(5)* %alloca %toint = ptrtoint i32 addrspace(5)* %alloca to i32 - %masked = and i32 %toint, 2147483647 + %masked = and i32 %toint, 131071 store volatile i32 %masked, i32 addrspace(1)* undef ret void } -; GCN-LABEL: {{^}}scratch_buffer_known_high_bit_huge: +; GCN-LABEL: {{^}}scratch_buffer_known_high_mask18: ; GCN: v_mov_b32_e32 [[FI:v[0-9]+]], 4 -; GCN-DAG: buffer_store_dword -; GCN-DAG: v_and_b32_e32 [[MASKED:v[0-9]+]], 0x7ffffffc, [[FI]] -; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[MASKED]] -define amdgpu_kernel void @scratch_buffer_known_high_bit_huge() #1 { +; GCN-NOT: [[FI]] +; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[FI]] +define amdgpu_kernel void @scratch_buffer_known_high_mask18() #0 { %alloca = alloca i32, align 4, addrspace(5) store volatile i32 0, i32 addrspace(5)* %alloca %toint = ptrtoint i32 addrspace(5)* %alloca to i32 - %masked = and i32 %toint, 2147483647 + %masked = and i32 %toint, 262143 store volatile i32 %masked, i32 addrspace(1)* undef ret void } attributes #0 = { nounwind } -attributes #1 = { nounwind "target-features"="+huge-private-buffer" } From 9925ef78ce2c5d464a9148493892847ee505853a Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Thu, 23 May 2019 19:51:16 +0000 Subject: [PATCH 0078/1176] Update breaking test. llvm-svn: 361542 --- clang/test/CodeGen/loop-vectorize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeGen/loop-vectorize.c b/clang/test/CodeGen/loop-vectorize.c index 28bd50bbd2e92..8c81fbebecb8c 100644 --- a/clang/test/CodeGen/loop-vectorize.c +++ b/clang/test/CodeGen/loop-vectorize.c @@ -10,7 +10,7 @@ // CHECK-DISABLE-VECT: fmul double // CHECK-DISABLE-VECT-NOT: fmul <{{[0-9]+}} x double> -#include +int printf(const char * restrict format, ...); void for_test() { double A[1000], B[1000]; From f81ebfb045b8b85b460a51d48f652741cce303a3 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Thu, 23 May 2019 19:54:41 +0000 Subject: [PATCH 0079/1176] UpdateTestChecks: ppc32 triple support Summary: Appears identical to powerpc64{,le}. Regenerate test that is being affected by upcoming patch. Reviewers: RKSimon Reviewed By: RKSimon Subscribers: nemanjai, jsji, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62339 llvm-svn: 361543 --- llvm/test/CodeGen/PowerPC/vec_splat.ll | 292 ++++++++++++++++++++----- llvm/utils/UpdateTestChecks/asm.py | 7 +- 2 files changed, 245 insertions(+), 54 deletions(-) diff --git a/llvm/test/CodeGen/PowerPC/vec_splat.ll b/llvm/test/CodeGen/PowerPC/vec_splat.ll index 7829f6fbede34..7c048ff371085 100644 --- a/llvm/test/CodeGen/PowerPC/vec_splat.ll +++ b/llvm/test/CodeGen/PowerPC/vec_splat.ll @@ -1,71 +1,261 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- -mcpu=g3 | FileCheck %s --check-prefixes=ALL,G3 +; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- -mcpu=g5 | FileCheck %s --check-prefixes=ALL,G5 + ; Test that vectors are scalarized/lowered correctly. -; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- -mcpu=g3 | \ -; RUN: grep stfs | count 4 -; RUN: llc -verify-machineinstrs < %s -mtriple=ppc32-- -mcpu=g5 -o %t -; RUN: grep vspltw %t | count 2 -; RUN: grep vsplti %t | count 3 -; RUN: grep vsplth %t | count 1 - %f4 = type <4 x float> - %i4 = type <4 x i32> +%f4 = type <4 x float> +%i4 = type <4 x i32> define void @splat(%f4* %P, %f4* %Q, float %X) nounwind { - %tmp = insertelement %f4 undef, float %X, i32 0 ; <%f4> [#uses=1] - %tmp2 = insertelement %f4 %tmp, float %X, i32 1 ; <%f4> [#uses=1] - %tmp4 = insertelement %f4 %tmp2, float %X, i32 2 ; <%f4> [#uses=1] - %tmp6 = insertelement %f4 %tmp4, float %X, i32 3 ; <%f4> [#uses=1] - %q = load %f4, %f4* %Q ; <%f4> [#uses=1] - %R = fadd %f4 %q, %tmp6 ; <%f4> [#uses=1] - store %f4 %R, %f4* %P - ret void +; G3-LABEL: splat: +; G3: # %bb.0: +; G3-NEXT: lfs 0, 0(4) +; G3-NEXT: lfs 2, 8(4) +; G3-NEXT: lfs 3, 4(4) +; G3-NEXT: lfs 4, 12(4) +; G3-NEXT: fadds 0, 0, 1 +; G3-NEXT: fadds 2, 2, 1 +; G3-NEXT: fadds 3, 3, 1 +; G3-NEXT: fadds 1, 4, 1 +; G3-NEXT: stfs 1, 12(3) +; G3-NEXT: stfs 2, 8(3) +; G3-NEXT: stfs 3, 4(3) +; G3-NEXT: stfs 0, 0(3) +; G3-NEXT: blr +; +; G5-LABEL: splat: +; G5: # %bb.0: +; G5-NEXT: stwu 1, -32(1) +; G5-NEXT: stfs 1, 16(1) +; G5-NEXT: addi 5, 1, 16 +; G5-NEXT: lvx 2, 0, 5 +; G5-NEXT: lvx 3, 0, 4 +; G5-NEXT: vspltw 2, 2, 0 +; G5-NEXT: vaddfp 2, 3, 2 +; G5-NEXT: stvx 2, 0, 3 +; G5-NEXT: addi 1, 1, 32 +; G5-NEXT: blr + %tmp = insertelement %f4 undef, float %X, i32 0 ; <%f4> [#uses=1] + %tmp2 = insertelement %f4 %tmp, float %X, i32 1 ; <%f4> [#uses=1] + %tmp4 = insertelement %f4 %tmp2, float %X, i32 2 ; <%f4> [#uses=1] + %tmp6 = insertelement %f4 %tmp4, float %X, i32 3 ; <%f4> [#uses=1] + %q = load %f4, %f4* %Q ; <%f4> [#uses=1] + %R = fadd %f4 %q, %tmp6 ; <%f4> [#uses=1] + store %f4 %R, %f4* %P + ret void } define void @splat_i4(%i4* %P, %i4* %Q, i32 %X) nounwind { - %tmp = insertelement %i4 undef, i32 %X, i32 0 ; <%i4> [#uses=1] - %tmp2 = insertelement %i4 %tmp, i32 %X, i32 1 ; <%i4> [#uses=1] - %tmp4 = insertelement %i4 %tmp2, i32 %X, i32 2 ; <%i4> [#uses=1] - %tmp6 = insertelement %i4 %tmp4, i32 %X, i32 3 ; <%i4> [#uses=1] - %q = load %i4, %i4* %Q ; <%i4> [#uses=1] - %R = add %i4 %q, %tmp6 ; <%i4> [#uses=1] - store %i4 %R, %i4* %P - ret void +; G3-LABEL: splat_i4: +; G3: # %bb.0: +; G3-NEXT: lwz 6, 0(4) +; G3-NEXT: lwz 7, 8(4) +; G3-NEXT: lwz 8, 4(4) +; G3-NEXT: lwz 4, 12(4) +; G3-NEXT: add 6, 6, 5 +; G3-NEXT: add 8, 8, 5 +; G3-NEXT: add 7, 7, 5 +; G3-NEXT: add 4, 4, 5 +; G3-NEXT: stw 4, 12(3) +; G3-NEXT: stw 7, 8(3) +; G3-NEXT: stw 8, 4(3) +; G3-NEXT: stw 6, 0(3) +; G3-NEXT: blr +; +; G5-LABEL: splat_i4: +; G5: # %bb.0: +; G5-NEXT: stwu 1, -32(1) +; G5-NEXT: stw 5, 16(1) +; G5-NEXT: addi 5, 1, 16 +; G5-NEXT: lvx 2, 0, 5 +; G5-NEXT: lvx 3, 0, 4 +; G5-NEXT: vspltw 2, 2, 0 +; G5-NEXT: vadduwm 2, 3, 2 +; G5-NEXT: stvx 2, 0, 3 +; G5-NEXT: addi 1, 1, 32 +; G5-NEXT: blr + %tmp = insertelement %i4 undef, i32 %X, i32 0 ; <%i4> [#uses=1] + %tmp2 = insertelement %i4 %tmp, i32 %X, i32 1 ; <%i4> [#uses=1] + %tmp4 = insertelement %i4 %tmp2, i32 %X, i32 2 ; <%i4> [#uses=1] + %tmp6 = insertelement %i4 %tmp4, i32 %X, i32 3 ; <%i4> [#uses=1] + %q = load %i4, %i4* %Q ; <%i4> [#uses=1] + %R = add %i4 %q, %tmp6 ; <%i4> [#uses=1] + store %i4 %R, %i4* %P + ret void } define void @splat_imm_i32(%i4* %P, %i4* %Q, i32 %X) nounwind { - %q = load %i4, %i4* %Q ; <%i4> [#uses=1] - %R = add %i4 %q, < i32 -1, i32 -1, i32 -1, i32 -1 > ; <%i4> [#uses=1] - store %i4 %R, %i4* %P - ret void +; G3-LABEL: splat_imm_i32: +; G3: # %bb.0: +; G3-NEXT: lwz 5, 0(4) +; G3-NEXT: lwz 6, 8(4) +; G3-NEXT: lwz 7, 4(4) +; G3-NEXT: lwz 4, 12(4) +; G3-NEXT: addi 5, 5, -1 +; G3-NEXT: addi 7, 7, -1 +; G3-NEXT: addi 6, 6, -1 +; G3-NEXT: addi 4, 4, -1 +; G3-NEXT: stw 4, 12(3) +; G3-NEXT: stw 6, 8(3) +; G3-NEXT: stw 7, 4(3) +; G3-NEXT: stw 5, 0(3) +; G3-NEXT: blr +; +; G5-LABEL: splat_imm_i32: +; G5: # %bb.0: +; G5-NEXT: lvx 2, 0, 4 +; G5-NEXT: vspltisb 3, -1 +; G5-NEXT: vadduwm 2, 2, 3 +; G5-NEXT: stvx 2, 0, 3 +; G5-NEXT: blr + %q = load %i4, %i4* %Q ; <%i4> [#uses=1] + %R = add %i4 %q, < i32 -1, i32 -1, i32 -1, i32 -1 > ; <%i4> [#uses=1] + store %i4 %R, %i4* %P + ret void } define void @splat_imm_i16(%i4* %P, %i4* %Q, i32 %X) nounwind { - %q = load %i4, %i4* %Q ; <%i4> [#uses=1] - %R = add %i4 %q, < i32 65537, i32 65537, i32 65537, i32 65537 > ; <%i4> [#uses=1] - store %i4 %R, %i4* %P - ret void +; G3-LABEL: splat_imm_i16: +; G3: # %bb.0: +; G3-NEXT: lwz 5, 0(4) +; G3-NEXT: lwz 6, 8(4) +; G3-NEXT: lwz 7, 4(4) +; G3-NEXT: lwz 4, 12(4) +; G3-NEXT: addi 5, 5, 1 +; G3-NEXT: addi 7, 7, 1 +; G3-NEXT: addi 6, 6, 1 +; G3-NEXT: addi 4, 4, 1 +; G3-NEXT: addis 5, 5, 1 +; G3-NEXT: addis 7, 7, 1 +; G3-NEXT: addis 6, 6, 1 +; G3-NEXT: addis 4, 4, 1 +; G3-NEXT: stw 4, 12(3) +; G3-NEXT: stw 6, 8(3) +; G3-NEXT: stw 7, 4(3) +; G3-NEXT: stw 5, 0(3) +; G3-NEXT: blr +; +; G5-LABEL: splat_imm_i16: +; G5: # %bb.0: +; G5-NEXT: lvx 2, 0, 4 +; G5-NEXT: vspltish 3, 1 +; G5-NEXT: vadduwm 2, 2, 3 +; G5-NEXT: stvx 2, 0, 3 +; G5-NEXT: blr + %q = load %i4, %i4* %Q ; <%i4> [#uses=1] + %R = add %i4 %q, < i32 65537, i32 65537, i32 65537, i32 65537 > ; <%i4> [#uses=1] + store %i4 %R, %i4* %P + ret void } define void @splat_h(i16 %tmp, <16 x i8>* %dst) nounwind { - %tmp.upgrd.1 = insertelement <8 x i16> undef, i16 %tmp, i32 0 - %tmp72 = insertelement <8 x i16> %tmp.upgrd.1, i16 %tmp, i32 1 - %tmp73 = insertelement <8 x i16> %tmp72, i16 %tmp, i32 2 - %tmp74 = insertelement <8 x i16> %tmp73, i16 %tmp, i32 3 - %tmp75 = insertelement <8 x i16> %tmp74, i16 %tmp, i32 4 - %tmp76 = insertelement <8 x i16> %tmp75, i16 %tmp, i32 5 - %tmp77 = insertelement <8 x i16> %tmp76, i16 %tmp, i32 6 - %tmp78 = insertelement <8 x i16> %tmp77, i16 %tmp, i32 7 - %tmp78.upgrd.2 = bitcast <8 x i16> %tmp78 to <16 x i8> - store <16 x i8> %tmp78.upgrd.2, <16 x i8>* %dst - ret void +; G3-LABEL: splat_h: +; G3: # %bb.0: +; G3-NEXT: sth 3, 14(4) +; G3-NEXT: sth 3, 12(4) +; G3-NEXT: sth 3, 10(4) +; G3-NEXT: sth 3, 8(4) +; G3-NEXT: sth 3, 6(4) +; G3-NEXT: sth 3, 4(4) +; G3-NEXT: sth 3, 2(4) +; G3-NEXT: sth 3, 0(4) +; G3-NEXT: blr +; +; G5-LABEL: splat_h: +; G5: # %bb.0: +; G5-NEXT: stwu 1, -32(1) +; G5-NEXT: sth 3, 16(1) +; G5-NEXT: addi 3, 1, 16 +; G5-NEXT: lvx 2, 0, 3 +; G5-NEXT: vsplth 2, 2, 0 +; G5-NEXT: stvx 2, 0, 4 +; G5-NEXT: addi 1, 1, 32 +; G5-NEXT: blr + %tmp.upgrd.1 = insertelement <8 x i16> undef, i16 %tmp, i32 0 + %tmp72 = insertelement <8 x i16> %tmp.upgrd.1, i16 %tmp, i32 1 + %tmp73 = insertelement <8 x i16> %tmp72, i16 %tmp, i32 2 + %tmp74 = insertelement <8 x i16> %tmp73, i16 %tmp, i32 3 + %tmp75 = insertelement <8 x i16> %tmp74, i16 %tmp, i32 4 + %tmp76 = insertelement <8 x i16> %tmp75, i16 %tmp, i32 5 + %tmp77 = insertelement <8 x i16> %tmp76, i16 %tmp, i32 6 + %tmp78 = insertelement <8 x i16> %tmp77, i16 %tmp, i32 7 + %tmp78.upgrd.2 = bitcast <8 x i16> %tmp78 to <16 x i8> + store <16 x i8> %tmp78.upgrd.2, <16 x i8>* %dst + ret void } define void @spltish(<16 x i8>* %A, <16 x i8>* %B) nounwind { - %tmp = load <16 x i8>, <16 x i8>* %B ; <<16 x i8>> [#uses=1] - %tmp.s = bitcast <16 x i8> %tmp to <16 x i8> ; <<16 x i8>> [#uses=1] - %tmp4 = sub <16 x i8> %tmp.s, bitcast (<8 x i16> < i16 15, i16 15, i16 15, i16 15, i16 15, i16 - 15, i16 15, i16 15 > to <16 x i8>) ; <<16 x i8>> [#uses=1] - %tmp4.u = bitcast <16 x i8> %tmp4 to <16 x i8> ; <<16 x i8>> [#uses=1] - store <16 x i8> %tmp4.u, <16 x i8>* %A - ret void +; G3-LABEL: spltish: +; G3: # %bb.0: +; G3-NEXT: stwu 1, -48(1) +; G3-NEXT: stw 25, 20(1) # 4-byte Folded Spill +; G3-NEXT: stw 26, 24(1) # 4-byte Folded Spill +; G3-NEXT: stw 27, 28(1) # 4-byte Folded Spill +; G3-NEXT: stw 28, 32(1) # 4-byte Folded Spill +; G3-NEXT: stw 29, 36(1) # 4-byte Folded Spill +; G3-NEXT: stw 30, 40(1) # 4-byte Folded Spill +; G3-NEXT: lbz 5, 5(4) +; G3-NEXT: lbz 6, 3(4) +; G3-NEXT: lbz 7, 1(4) +; G3-NEXT: lbz 8, 0(4) +; G3-NEXT: lbz 9, 2(4) +; G3-NEXT: lbz 10, 4(4) +; G3-NEXT: lbz 11, 6(4) +; G3-NEXT: lbz 12, 8(4) +; G3-NEXT: lbz 0, 10(4) +; G3-NEXT: addi 7, 7, -15 +; G3-NEXT: lbz 30, 12(4) +; G3-NEXT: lbz 29, 14(4) +; G3-NEXT: lbz 28, 15(4) +; G3-NEXT: lbz 27, 13(4) +; G3-NEXT: lbz 26, 11(4) +; G3-NEXT: lbz 25, 9(4) +; G3-NEXT: addi 6, 6, -15 +; G3-NEXT: lbz 4, 7(4) +; G3-NEXT: addi 5, 5, -15 +; G3-NEXT: addi 25, 25, -15 +; G3-NEXT: addi 26, 26, -15 +; G3-NEXT: addi 4, 4, -15 +; G3-NEXT: addi 27, 27, -15 +; G3-NEXT: addi 28, 28, -15 +; G3-NEXT: stb 29, 14(3) +; G3-NEXT: stb 30, 12(3) +; G3-NEXT: stb 0, 10(3) +; G3-NEXT: stb 12, 8(3) +; G3-NEXT: stb 11, 6(3) +; G3-NEXT: stb 10, 4(3) +; G3-NEXT: stb 9, 2(3) +; G3-NEXT: stb 8, 0(3) +; G3-NEXT: stb 28, 15(3) +; G3-NEXT: stb 27, 13(3) +; G3-NEXT: stb 26, 11(3) +; G3-NEXT: stb 25, 9(3) +; G3-NEXT: stb 4, 7(3) +; G3-NEXT: stb 5, 5(3) +; G3-NEXT: stb 6, 3(3) +; G3-NEXT: stb 7, 1(3) +; G3-NEXT: lwz 30, 40(1) # 4-byte Folded Reload +; G3-NEXT: lwz 29, 36(1) # 4-byte Folded Reload +; G3-NEXT: lwz 28, 32(1) # 4-byte Folded Reload +; G3-NEXT: lwz 27, 28(1) # 4-byte Folded Reload +; G3-NEXT: lwz 26, 24(1) # 4-byte Folded Reload +; G3-NEXT: lwz 25, 20(1) # 4-byte Folded Reload +; G3-NEXT: addi 1, 1, 48 +; G3-NEXT: blr +; +; G5-LABEL: spltish: +; G5: # %bb.0: +; G5-NEXT: lvx 2, 0, 4 +; G5-NEXT: vspltish 3, 15 +; G5-NEXT: vsububm 2, 2, 3 +; G5-NEXT: stvx 2, 0, 3 +; G5-NEXT: blr + %tmp = load <16 x i8>, <16 x i8>* %B ; <<16 x i8>> [#uses=1] + %tmp.s = bitcast <16 x i8> %tmp to <16 x i8> ; <<16 x i8>> [#uses=1] + %tmp4 = sub <16 x i8> %tmp.s, bitcast (<8 x i16> < i16 15, i16 15, i16 15, i16 15, i16 15, i16 + 15, i16 15, i16 15 > to <16 x i8>) ; <<16 x i8>> [#uses=1] + %tmp4.u = bitcast <16 x i8> %tmp4 to <16 x i8> ; <<16 x i8>> [#uses=1] + store <16 x i8> %tmp4.u, <16 x i8>* %A + ret void } - diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index 78da89d2730ca..07ba2644ef4bd 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -154,7 +154,7 @@ def scrub_asm_arm_eabi(asm, args): asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) return asm -def scrub_asm_powerpc64(asm, args): +def scrub_asm_powerpc(asm, args): # Scrub runs of whitespace out of the assembly, but leave the leading # whitespace in place. asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) @@ -261,8 +261,9 @@ def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, pre 'armv7eb': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), 'armv8a': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE), 'mips': (scrub_asm_mips, ASM_FUNCTION_MIPS_RE), - 'powerpc64': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE), - 'powerpc64le': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE), + 'ppc32': (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE), + 'powerpc64': (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE), + 'powerpc64le': (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE), 'riscv32': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE), 'riscv64': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE), 'sparc': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE), From 266b65f8404fd2dbac6b17ebdb90507273418cb0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 23 May 2019 20:05:21 +0000 Subject: [PATCH 0080/1176] [Utility] Avoid a few unnecessary copies (NFC) Avoid unnecessary copies by either passing by const-reference or moving the argument. llvm-svn: 361544 --- lldb/include/lldb/Utility/Broadcaster.h | 30 +++++++++++++------------ lldb/include/lldb/Utility/Listener.h | 7 +++--- lldb/source/Utility/Broadcaster.cpp | 9 ++++---- lldb/source/Utility/Listener.cpp | 10 ++++----- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/lldb/include/lldb/Utility/Broadcaster.h b/lldb/include/lldb/Utility/Broadcaster.h index df1a6640244e3..1444282c7f7b0 100644 --- a/lldb/include/lldb/Utility/Broadcaster.h +++ b/lldb/include/lldb/Utility/Broadcaster.h @@ -51,7 +51,7 @@ class BroadcastEventSpec { // Tell whether this BroadcastEventSpec is contained in in_spec. That is: (a) // the two spec's share the same broadcaster class (b) the event bits of this // spec are wholly contained in those of in_spec. - bool IsContainedIn(BroadcastEventSpec in_spec) const { + bool IsContainedIn(const BroadcastEventSpec &in_spec) const { if (m_broadcaster_class != in_spec.GetBroadcasterClass()) return false; uint32_t in_bits = in_spec.GetEventBits(); @@ -90,12 +90,13 @@ class BroadcasterManager ~BroadcasterManager() = default; uint32_t RegisterListenerForEvents(const lldb::ListenerSP &listener_sp, - BroadcastEventSpec event_spec); + const BroadcastEventSpec &event_spec); bool UnregisterListenerForEvents(const lldb::ListenerSP &listener_sp, - BroadcastEventSpec event_spec); + const BroadcastEventSpec &event_spec); - lldb::ListenerSP GetListenerForEventSpec(BroadcastEventSpec event_spec) const; + lldb::ListenerSP + GetListenerForEventSpec(const BroadcastEventSpec &event_spec) const; void SignUpListenersForBroadcaster(Broadcaster &broadcaster); @@ -123,7 +124,7 @@ class BroadcasterManager ~BroadcasterClassMatches() = default; - bool operator()(const event_listener_key input) const { + bool operator()(const event_listener_key &input) const { return (input.first.GetBroadcasterClass() == m_broadcaster_class); } @@ -133,12 +134,12 @@ class BroadcasterManager class BroadcastEventSpecMatches { public: - BroadcastEventSpecMatches(BroadcastEventSpec broadcaster_spec) + BroadcastEventSpecMatches(const BroadcastEventSpec &broadcaster_spec) : m_broadcaster_spec(broadcaster_spec) {} ~BroadcastEventSpecMatches() = default; - bool operator()(const event_listener_key input) const { + bool operator()(const event_listener_key &input) const { return (input.first.IsContainedIn(m_broadcaster_spec)); } @@ -148,13 +149,14 @@ class BroadcasterManager class ListenerMatchesAndSharedBits { public: - explicit ListenerMatchesAndSharedBits(BroadcastEventSpec broadcaster_spec, - const lldb::ListenerSP listener_sp) + explicit ListenerMatchesAndSharedBits( + const BroadcastEventSpec &broadcaster_spec, + const lldb::ListenerSP &listener_sp) : m_broadcaster_spec(broadcaster_spec), m_listener_sp(listener_sp) {} ~ListenerMatchesAndSharedBits() = default; - bool operator()(const event_listener_key input) const { + bool operator()(const event_listener_key &input) const { return (input.first.GetBroadcasterClass() == m_broadcaster_spec.GetBroadcasterClass() && (input.first.GetEventBits() & @@ -169,12 +171,12 @@ class BroadcasterManager class ListenerMatches { public: - explicit ListenerMatches(const lldb::ListenerSP in_listener_sp) + explicit ListenerMatches(const lldb::ListenerSP &in_listener_sp) : m_listener_sp(in_listener_sp) {} ~ListenerMatches() = default; - bool operator()(const event_listener_key input) const { + bool operator()(const event_listener_key &input) const { if (input.second == m_listener_sp) return true; else @@ -192,14 +194,14 @@ class BroadcasterManager ~ListenerMatchesPointer() = default; - bool operator()(const event_listener_key input) const { + bool operator()(const event_listener_key &input) const { if (input.second.get() == m_listener) return true; else return false; } - bool operator()(const lldb::ListenerSP input) const { + bool operator()(const lldb::ListenerSP &input) const { if (input.get() == m_listener) return true; else diff --git a/lldb/include/lldb/Utility/Listener.h b/lldb/include/lldb/Utility/Listener.h index 8a8e2755272c4..17fc47880e8f8 100644 --- a/lldb/include/lldb/Utility/Listener.h +++ b/lldb/include/lldb/Utility/Listener.h @@ -58,10 +58,11 @@ class Listener : public std::enable_shared_from_this { const char *GetName() { return m_name.c_str(); } - uint32_t StartListeningForEventSpec(lldb::BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec); + uint32_t + StartListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, + const BroadcastEventSpec &event_spec); - bool StopListeningForEventSpec(lldb::BroadcasterManagerSP manager_sp, + bool StopListeningForEventSpec(const lldb::BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec); uint32_t StartListeningForEvents(Broadcaster *broadcaster, diff --git a/lldb/source/Utility/Broadcaster.cpp b/lldb/source/Utility/Broadcaster.cpp index b42af00b526eb..c0b8567558eb3 100644 --- a/lldb/source/Utility/Broadcaster.cpp +++ b/lldb/source/Utility/Broadcaster.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,7 @@ using namespace lldb_private; Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) : m_broadcaster_sp(std::make_shared(*this)), - m_manager_sp(manager_sp), m_broadcaster_name(name) { + m_manager_sp(std::move(manager_sp)), m_broadcaster_name(name) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log) log->Printf("%p Broadcaster::Broadcaster(\"%s\")", @@ -334,7 +335,7 @@ lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() { } uint32_t BroadcasterManager::RegisterListenerForEvents( - const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { + const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) { std::lock_guard guard(m_manager_mutex); collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); @@ -359,7 +360,7 @@ uint32_t BroadcasterManager::RegisterListenerForEvents( } bool BroadcasterManager::UnregisterListenerForEvents( - const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { + const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) { std::lock_guard guard(m_manager_mutex); bool removed_some = false; @@ -399,7 +400,7 @@ bool BroadcasterManager::UnregisterListenerForEvents( } ListenerSP BroadcasterManager::GetListenerForEventSpec( - BroadcastEventSpec event_spec) const { + const BroadcastEventSpec &event_spec) const { std::lock_guard guard(m_manager_mutex); collection::const_iterator iter, end_iter = m_event_map.end(); diff --git a/lldb/source/Utility/Listener.cpp b/lldb/source/Utility/Listener.cpp index 5b97fbe923dec..50c56406c2ca5 100644 --- a/lldb/source/Utility/Listener.cpp +++ b/lldb/source/Utility/Listener.cpp @@ -27,8 +27,8 @@ namespace { class BroadcasterManagerWPMatcher { public: BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) - : m_manager_sp(manager_sp) {} - bool operator()(const BroadcasterManagerWP input_wp) const { + : m_manager_sp(std::move(manager_sp)) {} + bool operator()(const BroadcasterManagerWP &input_wp) const { BroadcasterManagerSP input_sp = input_wp.lock(); return (input_sp && input_sp == m_manager_sp); } @@ -191,7 +191,7 @@ void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { end_iter = m_broadcaster_managers.end(); BroadcasterManagerWP manager_wp; - BroadcasterManagerWPMatcher matcher(manager_sp); + BroadcasterManagerWPMatcher matcher(std::move(manager_sp)); iter = std::find_if( m_broadcaster_managers.begin(), end_iter, matcher); @@ -424,7 +424,7 @@ size_t Listener::HandleBroadcastEvent(EventSP &event_sp) { } uint32_t -Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp, +Listener::StartListeningForEventSpec(const BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec) { if (!manager_sp) return 0; @@ -452,7 +452,7 @@ Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp, return bits_acquired; } -bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp, +bool Listener::StopListeningForEventSpec(const BroadcasterManagerSP &manager_sp, const BroadcastEventSpec &event_spec) { if (!manager_sp) return false; From 30905a375ea2f7970cc896b89ec4ebf3c812cd4f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Thu, 23 May 2019 20:07:27 +0000 Subject: [PATCH 0081/1176] Fix sphinx unknown document error llvm-svn: 361545 --- clang-tools-extra/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 4c709f0370df9..e998fa1b189a0 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -177,7 +177,7 @@ Improvements to clang-tidy Rewrites function signatures to use a trailing return type. - The :doc:`misc-throw-by-value-catch-by-reference - ` now supports + ` now supports `WarnOnLargeObject` and `MaxSize` options to warn on any large trivial object caught by value. From 56d69ef8ca1f2826b1e7c620b871f5074926a43a Mon Sep 17 00:00:00 2001 From: Jorge Gorbe Moya Date: Thu, 23 May 2019 20:11:17 +0000 Subject: [PATCH 0082/1176] [lldb] Make sure RegularExpression constructors always initialize member variables The copy constructor of RegularExpression doesn't initialize m_comp_err. This causes an use-of-initialized-value error when a RegularExpression is copied: the copy constructor calls Compile, which calls Free to free the existing regex if needed, which in turn reads m_comp_err to check if there's any regex to be freed. This change calls the default constructor from the other constructors to make sure members are always initialized with sensible values. This also avoids duplicating init logic, like the RegularExpression(llvm:StringRef) constructor does, which is error prone. Differential Revision: https://reviews.llvm.org/D62334 llvm-svn: 361546 --- lldb/source/Utility/RegularExpression.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lldb/source/Utility/RegularExpression.cpp b/lldb/source/Utility/RegularExpression.cpp index 71fe301c45117..0192e8b8a01a0 100644 --- a/lldb/source/Utility/RegularExpression.cpp +++ b/lldb/source/Utility/RegularExpression.cpp @@ -29,13 +29,12 @@ RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() { // Constructor that compiles "re" using "flags" and stores the resulting // compiled regular expression into this object. RegularExpression::RegularExpression(llvm::StringRef str) - : m_re(), m_comp_err(1), m_preg() { - memset(&m_preg, 0, sizeof(m_preg)); + : RegularExpression() { Compile(str); } -RegularExpression::RegularExpression(const RegularExpression &rhs) { - memset(&m_preg, 0, sizeof(m_preg)); +RegularExpression::RegularExpression(const RegularExpression &rhs) + : RegularExpression() { Compile(rhs.GetText()); } From 7d6c0bce503fd92fa48db88a944b01fa2e7402b4 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 23 May 2019 20:17:25 +0000 Subject: [PATCH 0083/1176] [DAGCombiner] make folds of binops safe for opcodes that produce >1 value This is no-functional-change-intended currently because the definition of isBinOp() only includes opcodes that produce 1 value. But if we share that implementation with isCommutativeBinOp() as proposed in D62191, then we need to make sure that the callers bail out for opcodes that they are not prepared to handle correctly. llvm-svn: 361547 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0aa481ff2e298..b5bb86580fb61 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1968,7 +1968,8 @@ static ConstantSDNode *getAsNonOpaqueConstant(SDValue N) { } SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) { - assert(TLI.isBinOp(BO->getOpcode()) && "Unexpected binary operator"); + assert(TLI.isBinOp(BO->getOpcode()) && BO->getNumValues() == 1 && + "Unexpected binary operator"); // Don't do this unless the old select is going away. We want to eliminate the // binary operator, not replace a binop with a select. @@ -16172,7 +16173,8 @@ static SDValue scalarizeExtractedBinop(SDNode *ExtElt, SelectionDAG &DAG, SDValue Vec = ExtElt->getOperand(0); SDValue Index = ExtElt->getOperand(1); auto *IndexC = dyn_cast(Index); - if (!IndexC || !TLI.isBinOp(Vec.getOpcode()) || !Vec.hasOneUse()) + if (!IndexC || !TLI.isBinOp(Vec.getOpcode()) || !Vec.hasOneUse() || + Vec.getNode()->getNumValues() != 1) return SDValue(); // Targets may want to avoid this to prevent an expensive register transfer. @@ -17412,7 +17414,7 @@ static SDValue narrowInsertExtractVectorBinOp(SDNode *Extract, SelectionDAG &DAG) { const TargetLowering &TLI = DAG.getTargetLoweringInfo(); SDValue BinOp = Extract->getOperand(0); - if (!TLI.isBinOp(BinOp.getOpcode())) + if (!TLI.isBinOp(BinOp.getOpcode()) || BinOp.getNode()->getNumValues() != 1) return SDValue(); SDValue Bop0 = BinOp.getOperand(0), Bop1 = BinOp.getOperand(1); @@ -17456,7 +17458,7 @@ static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG) { // feeding an extract subvector. const TargetLowering &TLI = DAG.getTargetLoweringInfo(); SDValue BinOp = peekThroughBitcasts(Extract->getOperand(0)); - if (!TLI.isBinOp(BinOp.getOpcode())) + if (!TLI.isBinOp(BinOp.getOpcode()) || BinOp.getNode()->getNumValues() != 1) return SDValue(); // The binop must be a vector type, so we can extract some fraction of it. @@ -18268,7 +18270,7 @@ SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { if (SVN->isSplat() && SVN->getSplatIndex() < (int)NumElts) { int SplatIndex = SVN->getSplatIndex(); if (TLI.isExtractVecEltCheap(VT, SplatIndex) && - TLI.isBinOp(N0.getOpcode())) { + TLI.isBinOp(N0.getOpcode()) && N0.getNode()->getNumValues() == 1) { // splat (vector_bo L, R), Index --> // splat (scalar_bo (extelt L, Index), (extelt R, Index)) SDValue L = N0.getOperand(0), R = N0.getOperand(1); From edb52e2e7d075b1fec13034deaa56d3c32d100ac Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 23 May 2019 20:25:49 +0000 Subject: [PATCH 0084/1176] [Process] Fix another thread_result_t & nullptr incompatibility. llvm-svn: 361548 --- lldb/source/Target/Process.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index b018a3115a026..7c668a216a3a2 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3638,7 +3638,7 @@ void Process::ControlPrivateStateThread(uint32_t signal) { } if (signal == eBroadcastInternalStateControlStop) { - thread_result_t result = nullptr; + thread_result_t result = {}; m_private_state_thread.Join(&result); m_private_state_thread.Reset(); } @@ -3913,7 +3913,7 @@ thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) { // it was doing yet, so don't try to change it on the way out. if (!is_secondary_thread) m_public_run_lock.SetStopped(); - return nullptr; + return {}; } // Process Event Data @@ -4072,15 +4072,15 @@ void Process::ProcessEventData::DoOnRemoval(Event *event_ptr) { // public resume. process_sp->PrivateResume(); } else { - bool hijacked = - process_sp->IsHijackedForEvent(eBroadcastBitStateChanged) - && !process_sp->StateChangedIsHijackedForSynchronousResume(); + bool hijacked = + process_sp->IsHijackedForEvent(eBroadcastBitStateChanged) && + !process_sp->StateChangedIsHijackedForSynchronousResume(); if (!hijacked) { // If we didn't restart, run the Stop Hooks here. // Don't do that if state changed events aren't hooked up to the - // public (or SyncResume) broadcasters. StopHooks are just for - // real public stops. They might also restart the target, + // public (or SyncResume) broadcasters. StopHooks are just for + // real public stops. They might also restart the target, // so watch for that. process_sp->GetTarget().RunStopHooks(); if (process_sp->GetPrivateState() == eStateRunning) From 14f4ff6e8972ddc7755c72f6bfc2ba372ac9638f Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 23 May 2019 20:26:41 +0000 Subject: [PATCH 0085/1176] [COFF] Move KeepUnique bit from Chunk to SectionChunk, NFC The KeepUnique bit is used during ICF, which only operates on SectionChunks, so only SectionChunks need it. This frees up a byte in Chunk, which I plan to use in a follow-up change. llvm-svn: 361549 --- lld/COFF/Chunks.h | 12 +++++------- lld/COFF/Driver.cpp | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index 8525feedf2e67..d15638e7b0cc6 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -122,14 +122,9 @@ class Chunk { protected: Chunk(Kind K = OtherKind) : ChunkKind(K) {} - const Kind ChunkKind; -public: - // Whether this section needs to be kept distinct from other sections during - // ICF. This is set by the driver using address-significance tables. - bool KeepUnique = false; + const Kind ChunkKind; -protected: // The alignment of this chunk, stored in log2 form. The writer uses the // value. uint8_t P2Align = 0; @@ -137,7 +132,6 @@ class Chunk { // The RVA of this chunk in the output. The writer sets a value. uint32_t RVA = 0; -protected: // The output section for this chunk. OutputSection *Out = nullptr; }; @@ -283,6 +277,10 @@ class SectionChunk final : public Chunk { // Used by the garbage collector. bool Live; + // Whether this section needs to be kept distinct from other sections during + // ICF. This is set by the driver using address-significance tables. + bool KeepUnique = false; + // The COMDAT selection if this is a COMDAT chunk. llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 39d476c5079b6..006984309e184 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -858,7 +858,7 @@ static void parseOrderFile(StringRef Arg) { static void markAddrsig(Symbol *S) { if (auto *D = dyn_cast_or_null(S)) - if (Chunk *C = D->getChunk()) + if (SectionChunk *C = dyn_cast_or_null(D->getChunk())) C->KeepUnique = true; } From dab31924e9c790555f916d21e6575e7f1e1cd5b7 Mon Sep 17 00:00:00 2001 From: Tamas Zolnai Date: Thu, 23 May 2019 20:29:04 +0000 Subject: [PATCH 0086/1176] [clang-tidy]: Add cert-oop54-cpp alias for bugprone-unhandled-self-assignment Summary: Added WarnOnlyIfThisHasSuspiciousField option to allow to catch any copy assignment operator independently from the container class's fields. Added the cert alias using this option. Reviewers: aaron.ballman Reviewed By: aaron.ballman Subscribers: mgorny, Eugene.Zelenko, xazax.hun, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62192 llvm-svn: 361550 --- .../bugprone/UnhandledSelfAssignmentCheck.cpp | 61 ++++++++++++------- .../bugprone/UnhandledSelfAssignmentCheck.h | 8 ++- .../clang-tidy/cert/CERTTidyModule.cpp | 4 ++ .../clang-tidy/cert/CMakeLists.txt | 1 + clang-tools-extra/docs/ReleaseNotes.rst | 5 ++ .../bugprone-unhandled-self-assignment.rst | 10 ++- .../docs/clang-tidy/checks/cert-oop54-cpp.rst | 10 +++ .../docs/clang-tidy/checks/list.rst | 1 + ...warn-only-if-this-has-suspicious-field.cpp | 41 +++++++++++++ .../test/clang-tidy/cert-oop54-cpp.cpp | 16 +++++ 10 files changed, 131 insertions(+), 26 deletions(-) create mode 100644 clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst create mode 100644 clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp create mode 100644 clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp index b529f72ddae32..14f5e1532474b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp @@ -16,6 +16,18 @@ namespace clang { namespace tidy { namespace bugprone { +UnhandledSelfAssignmentCheck::UnhandledSelfAssignmentCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + WarnOnlyIfThisHasSuspiciousField( + Options.get("WarnOnlyIfThisHasSuspiciousField", true)) {} + +void UnhandledSelfAssignmentCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "WarnOnlyIfThisHasSuspiciousField", + WarnOnlyIfThisHasSuspiciousField); +} + void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; @@ -61,29 +73,32 @@ void UnhandledSelfAssignmentCheck::registerMatchers(MatchFinder *Finder) { cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl( hasName("operator="), ofClass(equalsBoundNode("class")))))))); - // Matcher for standard smart pointers. - const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType( - recordType(hasDeclaration(classTemplateSpecializationDecl( - hasAnyName("::std::shared_ptr", "::std::unique_ptr", - "::std::weak_ptr", "::std::auto_ptr"), - templateArgumentCountIs(1)))))); - - // We will warn only if the class has a pointer or a C array field which - // probably causes a problem during self-assignment (e.g. first resetting the - // pointer member, then trying to access the object pointed by the pointer, or - // memcpy overlapping arrays). - const auto ThisHasSuspiciousField = cxxMethodDecl(ofClass(cxxRecordDecl( - has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType), - hasType(arrayType()))))))); - - Finder->addMatcher( - cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")), - isCopyAssignmentOperator(), IsUserDefined, - HasReferenceParam, HasNoSelfCheck, - unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy), - HasNoNestedSelfAssign, ThisHasSuspiciousField) - .bind("copyAssignmentOperator"), - this); + DeclarationMatcher AdditionalMatcher = cxxMethodDecl(); + if (WarnOnlyIfThisHasSuspiciousField) { + // Matcher for standard smart pointers. + const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(classTemplateSpecializationDecl( + hasAnyName("::std::shared_ptr", "::std::unique_ptr", + "::std::weak_ptr", "::std::auto_ptr"), + templateArgumentCountIs(1)))))); + + // We will warn only if the class has a pointer or a C array field which + // probably causes a problem during self-assignment (e.g. first resetting + // the pointer member, then trying to access the object pointed by the + // pointer, or memcpy overlapping arrays). + AdditionalMatcher = cxxMethodDecl(ofClass(cxxRecordDecl( + has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType), + hasType(arrayType()))))))); + } + + Finder->addMatcher(cxxMethodDecl(ofClass(cxxRecordDecl().bind("class")), + isCopyAssignmentOperator(), IsUserDefined, + HasReferenceParam, HasNoSelfCheck, + unless(HasNonTemplateSelfCopy), + unless(HasTemplateSelfCopy), + HasNoNestedSelfAssign, AdditionalMatcher) + .bind("copyAssignmentOperator"), + this); } void UnhandledSelfAssignmentCheck::check( diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h index 1747246143552..d7a2b7c619ff8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.h @@ -23,10 +23,14 @@ namespace bugprone { /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-unhandled-self-assignment.html class UnhandledSelfAssignmentCheck : public ClangTidyCheck { public: - UnhandledSelfAssignmentCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + UnhandledSelfAssignmentCheck(StringRef Name, ClangTidyContext *Context); + + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + const bool WarnOnlyIfThisHasSuspiciousField; }; } // namespace bugprone diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp index cd8da0c663643..341968b6fa6b1 100644 --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -9,6 +9,7 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "../bugprone/UnhandledSelfAssignmentCheck.h" #include "../google/UnnamedNamespaceInHeaderCheck.h" #include "../misc/NewDeleteOverloadsCheck.h" #include "../misc/NonCopyableObjects.h" @@ -49,6 +50,8 @@ class CERTModule : public ClangTidyModule { // OOP CheckFactories.registerCheck( "cert-oop11-cpp"); + CheckFactories.registerCheck( + "cert-oop54-cpp"); // ERR CheckFactories.registerCheck( "cert-err09-cpp"); @@ -85,6 +88,7 @@ class CERTModule : public ClangTidyModule { ClangTidyOptions Options; ClangTidyOptions::OptionMap &Opts = Options.CheckOptions; Opts["cert-dcl16-c.NewSuffixes"] = "L;LL;LU;LLU"; + Opts["cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField"] = "0"; return Options; } }; diff --git a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt index b50ddf014c634..474d9356adfbf 100644 --- a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt @@ -20,6 +20,7 @@ add_clang_library(clangTidyCERTModule clangBasic clangLex clangTidy + clangTidyBugproneModule clangTidyGoogleModule clangTidyMiscModule clangTidyPerformanceModule diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index e998fa1b189a0..22acfa33feec4 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -134,6 +134,11 @@ Improvements to clang-tidy subclasses of ``NSObject`` and recommends calling a superclass initializer instead. +- New alias :doc:`cert-oop54-cpp + ` to + :doc:`bugprone-unhandled-self-assignment + ` was added. + - New alias :doc:`cppcoreguidelines-explicit-virtual-functions ` to :doc:`modernize-use-override diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst index 64412ba049437..c4ccdd9579d6a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone-unhandled-self-assignment.rst @@ -3,11 +3,14 @@ bugprone-unhandled-self-assignment ================================== +`cert-oop54-cpp` redirects here as an alias for this check. For the CERT alias, +the `WarnOnlyIfThisHasSuspiciousField` option is set to `0`. + Finds user-defined copy assignment operators which do not protect the code against self-assignment either by checking self-assignment explicitly or using the copy-and-swap or the copy-and-move method. -This check now searches only those classes which have any pointer or C array field +By default, this check searches only those classes which have any pointer or C array field to avoid false positives. In case of a pointer or a C array, it's likely that self-copy assignment breaks the object if the copy assignment operator was not written with care. @@ -114,3 +117,8 @@ temporary object into ``this`` (needs a move assignment operator): return *this; } }; + +.. option:: WarnOnlyIfThisHasSuspiciousField + + When non-zero, the check will warn only if the container class of the copy assignment operator + has any suspicious fields (pointer or C array). This option is set to `1` by default. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst new file mode 100644 index 0000000000000..fe5095211f046 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/cert-oop54-cpp.rst @@ -0,0 +1,10 @@ +.. title:: clang-tidy - cert-oop54-cpp +.. meta:: + :http-equiv=refresh: 5;URL=bugprone-unhandled-self-assignment.html + +cert-oop54-cpp +============== + +The cert-oop54-cpp check is an alias, please see +`bugprone-unhandled-self-assignment `_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 7a0ebc292e468..c860d6a4753c8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -98,6 +98,7 @@ Clang-Tidy Checks cert-msc50-cpp cert-msc51-cpp cert-oop11-cpp (redirects to performance-move-constructor-init) + cert-oop54-cpp (redirects to bugprone-unhandled-self-assignment) cppcoreguidelines-avoid-c-arrays (redirects to modernize-avoid-c-arrays) cppcoreguidelines-avoid-goto cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) diff --git a/clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp b/clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp new file mode 100644 index 0000000000000..0e6ee47478dc1 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/bugprone-unhandled-self-assignment-warn-only-if-this-has-suspicious-field.cpp @@ -0,0 +1,41 @@ +// RUN: %check_clang_tidy %s bugprone-unhandled-self-assignment %t -- \ +// RUN: -config="{CheckOptions: \ +// RUN: [{key: bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField, \ +// RUN: value: 0}]}" + +// Classes with pointer field are still caught. +class PtrField { +public: + PtrField &operator=(const PtrField &object) { + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment] + return *this; + } + +private: + int *p; +}; + +// With the option, check catches classes with trivial fields. +class TrivialFields { +public: + TrivialFields &operator=(const TrivialFields &object) { + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment] + return *this; + } + +private: + int m; + float f; + double d; + bool b; +}; + +// The check warns also when there is no field at all. +// In this case, user-defined copy assignment operator is useless anyway. +class ClassWithoutFields { +public: + ClassWithoutFields &operator=(const ClassWithoutFields &object) { + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: operator=() does not handle self-assignment properly [bugprone-unhandled-self-assignment] + return *this; + } +}; diff --git a/clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp b/clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp new file mode 100644 index 0000000000000..f601e672820b1 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cert-oop54-cpp.cpp @@ -0,0 +1,16 @@ +// RUN: %check_clang_tidy %s cert-oop54-cpp %t + +// Test whether bugprone-unhandled-self-assignment.WarnOnlyIfThisHasSuspiciousField option is set correctly. +class TrivialFields { +public: + TrivialFields &operator=(const TrivialFields &object) { + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: operator=() does not handle self-assignment properly [cert-oop54-cpp] + return *this; + } + +private: + int m; + float f; + double d; + bool b; +}; From e8df27d9256b38ec1a2467a1b9c087b00ffd17cc Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 23 May 2019 20:47:28 +0000 Subject: [PATCH 0087/1176] [analyzer] Add a new frontend flag to display all checker options Add the new frontend flag -analyzer-checker-option-help to display all checker/package options. Differential Revision: https://reviews.llvm.org/D57858 llvm-svn: 361552 --- clang/include/clang/Driver/CC1Options.td | 3 ++ .../StaticAnalyzer/Core/AnalyzerOptions.h | 34 +++++++++++-- .../StaticAnalyzer/Frontend/CheckerRegistry.h | 1 + .../StaticAnalyzer/Frontend/FrontendActions.h | 4 ++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + .../ExecuteCompilerInvocation.cpp | 10 ++++ .../StaticAnalyzer/Core/AnalyzerOptions.cpp | 32 ++++++++++++ .../Frontend/CheckerRegistration.cpp | 51 ++++++------------- .../Frontend/CheckerRegistry.cpp | 51 +++++++++++++++---- .../Analysis/analyzer-checker-option-help.c | 19 +++++++ clang/test/Analysis/analyzer-list-configs.c | 11 ++-- clang/test/Analysis/checker-plugins.c | 9 ++++ 12 files changed, 168 insertions(+), 58 deletions(-) create mode 100644 clang/test/Analysis/analyzer-checker-option-help.c diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index b9b6677853fd4..f7da3746bd4f3 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -143,6 +143,9 @@ def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers def analyzer_config : Separate<["-"], "analyzer-config">, HelpText<"Choose analyzer options to enable">; +def analyzer_checker_option_help : Flag<["-"], "analyzer-checker-option-help">, + HelpText<"Display the list of checker and package options">; + def analyzer_config_compatibility_mode : Separate<["-"], "analyzer-config-compatibility-mode">, HelpText<"Don't emit errors on invalid analyzer-config inputs">; diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 6db3a269a2db8..6a54e157e88e1 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -166,6 +166,29 @@ class AnalyzerOptions : public RefCountedBase { static std::vector getRegisteredCheckers(bool IncludeExperimental = false); + /// Convenience function for printing options or checkers and their + /// description in a formatted manner. If \p MinLineWidth is set to 0, no line + /// breaks are introduced for the description. + /// + /// Format, depending whether the option name's length is less then + /// \p OptionWidth: + /// + /// EntryNameDescription + /// <---------padding--------->Description + /// <---------padding--------->Description + /// + /// VeryVeryLongOptionName + /// <---------padding--------->Description + /// <---------padding--------->Description + /// ^~~~~~~~ InitialPad + /// ^~~~~~~~~~~~~~~~~~~~~~~~~~ EntryWidth + /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MinLineWidth + static void printFormattedEntry( + llvm::raw_ostream &Out, + std::pair EntryDescPair, + size_t EntryWidth, size_t InitialPad, size_t MinLineWidth = 0); + + /// Pair of checker name and enable/disable. std::vector> CheckersControlList; @@ -199,6 +222,7 @@ class AnalyzerOptions : public RefCountedBase { unsigned ShowCheckerHelp : 1; unsigned ShowCheckerHelpHidden : 1; unsigned ShowEnabledCheckerList : 1; + unsigned ShowCheckerOptionList : 1; unsigned ShowConfigOptionsList : 1; unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; @@ -262,11 +286,11 @@ class AnalyzerOptions : public RefCountedBase { AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), ShowCheckerHelpHidden(false), ShowEnabledCheckerList(false), - ShowConfigOptionsList(false), AnalyzeAll(false), - AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), - eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), - visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), - PrintStats(false), NoRetryExhausted(false) { + ShowCheckerOptionList(false), ShowConfigOptionsList(false), + AnalyzeAll(false), AnalyzerDisplayProgress(false), + AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), + TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), + UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) { llvm::sort(AnalyzerConfigCmdFlags); } diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h index 875cb8edb8ed0..3a05c928774c0 100644 --- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h @@ -272,6 +272,7 @@ class CheckerRegistry { void printCheckerWithDescList(raw_ostream &Out, size_t MaxNameChars = 30) const; void printEnabledCheckerList(raw_ostream &Out) const; + void printCheckerOptionList(raw_ostream &Out) const; private: /// Collect all enabled checkers. The returned container preserves the order diff --git a/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index 5f26a4893c6d2..878b65a1b143c 100644 --- a/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -61,6 +61,10 @@ void printEnabledCheckerList(raw_ostream &OS, ArrayRef plugins, DiagnosticsEngine &diags, const LangOptions &LangOpts); void printAnalyzerConfigList(raw_ostream &OS); +void printCheckerConfigList(raw_ostream &OS, ArrayRef plugins, + AnalyzerOptions &opts, + DiagnosticsEngine &diags, + const LangOptions &LangOpts); } // end GR namespace diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 7cdc050e4673d..877e70b6616cb 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -286,6 +286,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); Opts.ShowCheckerHelpHidden = Args.hasArg(OPT_analyzer_checker_help_hidden); + Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help); Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.ShouldEmitErrorsOnInvalidConfigValue = diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index f77a865efa70a..27690be777b8d 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -247,6 +247,16 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { return true; } + // Honor -analyzer-checker-option-help. + if (Clang->getAnalyzerOpts()->ShowCheckerOptionList) { + ento::printCheckerConfigList(llvm::outs(), + Clang->getFrontendOpts().Plugins, + *Clang->getAnalyzerOpts(), + Clang->getDiagnostics(), + Clang->getLangOpts()); + return true; + } + // Honor -analyzer-list-enabled-checkers. if (AnOpts.ShowEnabledCheckerList) { ento::printEnabledCheckerList(llvm::outs(), diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 68b2c052305b5..71abe2ae6c0e8 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -48,6 +49,37 @@ AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) { return Result; } +void AnalyzerOptions::printFormattedEntry( + llvm::raw_ostream &Out, + std::pair EntryDescPair, + size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) { + + llvm::formatted_raw_ostream FOut(Out); + + const size_t PadForDesc = InitialPad + EntryWidth; + + FOut.PadToColumn(InitialPad) << EntryDescPair.first; + // If the buffer's length is greater then PadForDesc, print a newline. + if (FOut.getColumn() > PadForDesc) + FOut << '\n'; + + FOut.PadToColumn(PadForDesc); + + if (MinLineWidth == 0) { + FOut << EntryDescPair.second; + return; + } + + for (char C : EntryDescPair.second) { + if (FOut.getColumn() > MinLineWidth && C == ' ') { + FOut << '\n'; + FOut.PadToColumn(PadForDesc); + continue; + } + FOut << C; + } +} + ExplorationStrategyKind AnalyzerOptions::getExplorationStrategy() const { auto K = diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 4ad362fe1e34e..1e45ee96145ab 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -18,7 +18,6 @@ #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/FormattedStream.h" #include "llvm/Support/raw_ostream.h" #include @@ -65,17 +64,20 @@ void ento::printEnabledCheckerList(raw_ostream &out, .printEnabledCheckerList(out); } +void ento::printCheckerConfigList(raw_ostream &OS, + ArrayRef plugins, + AnalyzerOptions &opts, + DiagnosticsEngine &diags, + const LangOptions &LangOpts) { + CheckerRegistry(plugins, diags, opts, LangOpts) + .printCheckerOptionList(OS); +} + void ento::printAnalyzerConfigList(raw_ostream &out) { out << "OVERVIEW: Clang Static Analyzer -analyzer-config Option List\n\n"; - out << "USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config " - "\n\n"; - out << " clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, " - "-analyzer-config OPTION2=VALUE, ...\n\n"; - out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang" - "\n\n"; - out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang " - "OPTION1=VALUE, -Xclang -analyzer-config -Xclang " - "OPTION2=VALUE, ...\n\n"; + out << "USAGE: -analyzer-config \n\n"; + out << " -analyzer-config OPTION1=VALUE, -analyzer-config " + "OPTION2=VALUE, ...\n\n"; out << "OPTIONS:\n\n"; using OptionAndDescriptionTy = std::pair; @@ -109,31 +111,10 @@ void ento::printAnalyzerConfigList(raw_ostream &out) { return LHS.first < RHS.first; }); - constexpr size_t MinLineWidth = 70; - constexpr size_t PadForOpt = 2; - constexpr size_t OptionWidth = 30; - constexpr size_t PadForDesc = PadForOpt + OptionWidth; - static_assert(MinLineWidth > PadForDesc, "MinLineWidth must be greater!"); - - llvm::formatted_raw_ostream FOut(out); - for (const auto &Pair : PrintableOptions) { - FOut.PadToColumn(PadForOpt) << Pair.first; - - // If the buffer's length is greater then PadForDesc, print a newline. - if (FOut.getColumn() > PadForDesc) - FOut << '\n'; - - FOut.PadToColumn(PadForDesc); - - for (char C : Pair.second) { - if (FOut.getColumn() > MinLineWidth && C == ' ') { - FOut << '\n'; - FOut.PadToColumn(PadForDesc); - continue; - } - FOut << C; - } - FOut << "\n\n"; + AnalyzerOptions::printFormattedEntry(out, Pair, /*InitialPad*/ 2, + /*EntryWidth*/ 30, + /*MinLineWidth*/ 70); + out << "\n\n"; } } diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index d41ca0a8f32f6..d405933ca65c5 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -518,17 +518,8 @@ void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out, if (!AnOpts.ShowCheckerHelpHidden && Checker.IsHidden) continue; - Out.indent(InitialPad) << Checker.FullName; - - int Pad = OptionFieldWidth - Checker.FullName.size(); - - // Break on long option names. - if (Pad < 0) { - Out << '\n'; - Pad = OptionFieldWidth + InitialPad; - } - Out.indent(Pad + 2) << Checker.Desc; - + AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Checker.Desc}, + InitialPad, OptionFieldWidth); Out << '\n'; } } @@ -540,3 +531,41 @@ void CheckerRegistry::printEnabledCheckerList(raw_ostream &Out) const { for (const auto *i : EnabledCheckers) Out << i->FullName << '\n'; } + +void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const { + Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n"; + Out << "USAGE: -analyzer-config \n\n"; + Out << " -analyzer-config OPTION1=VALUE, -analyzer-config " + "OPTION2=VALUE, ...\n\n"; + Out << "OPTIONS:\n\n"; + + std::multimap OptionMap; + + for (const CheckerInfo &Checker : Checkers) { + for (const CmdLineOption &Option : Checker.CmdLineOptions) { + OptionMap.insert({Checker.FullName, Option}); + } + } + + for (const PackageInfo &Package : Packages) { + for (const CmdLineOption &Option : Package.CmdLineOptions) { + OptionMap.insert({Package.FullName, Option}); + } + } + + for (const std::pair &Entry : OptionMap) { + const CmdLineOption &Option = Entry.second; + std::string FullOption = (Entry.first + ":" + Option.OptionName).str(); + + std::string Desc = + ("(" + Option.OptionType + ") " + Option.Description + " (default: " + + (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")") + .str(); + + AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc}, + /*InitialPad*/ 2, + /*EntryWidth*/ 50, + /*MinLineWidth*/ 90); + Out << "\n\n"; + } +} diff --git a/clang/test/Analysis/analyzer-checker-option-help.c b/clang/test/Analysis/analyzer-checker-option-help.c new file mode 100644 index 0000000000000..f59d8515823cc --- /dev/null +++ b/clang/test/Analysis/analyzer-checker-option-help.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -analyzer-checker-option-help 2>&1 | FileCheck %s + +// CHECK: OVERVIEW: Clang Static Analyzer Checker and Package Option List +// +// CHECK: USAGE: -analyzer-config +// +// CHECK: -analyzer-config OPTION1=VALUE, -analyzer-config +// CHECK-SAME: OPTION2=VALUE, ... +// +// CHECK: OPTIONS: +// +// CHECK: alpha.clone.CloneChecker:MinimumCloneComplexity +// CHECK-SAME: (int) Ensures that every clone has at least +// CHECK: the given complexity. Complexity is here +// CHECK: defined as the total amount of children +// CHECK: of a statement. This constraint assumes +// CHECK: the first statement in the group is representative +// CHECK: for all other statements in the group in +// CHECK: terms of complexity. (default: 50) diff --git a/clang/test/Analysis/analyzer-list-configs.c b/clang/test/Analysis/analyzer-list-configs.c index a02b2a9a85454..67fa906429bae 100644 --- a/clang/test/Analysis/analyzer-list-configs.c +++ b/clang/test/Analysis/analyzer-list-configs.c @@ -1,14 +1,11 @@ // RUN: %clang_cc1 -analyzer-config-help 2>&1 | FileCheck %s + // CHECK: OVERVIEW: Clang Static Analyzer -analyzer-config Option List // -// CHECK: USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config -// -// CHECK: clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, -analyzer-config OPTION2=VALUE, ... -// -// CHECK: clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang -// -// CHECK: clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang OPTION1=VALUE, -Xclang -analyzer-config -Xclang OPTION2=VALUE, ... +// CHECK: USAGE: -analyzer-config // +// CHECK: -analyzer-config OPTION1=VALUE, -analyzer-config +// CHECK-SAME: OPTION2=VALUE, ... // // CHECK: OPTIONS: // diff --git a/clang/test/Analysis/checker-plugins.c b/clang/test/Analysis/checker-plugins.c index 2dbebfe29d7e0..b5444fa6cbf7f 100644 --- a/clang/test/Analysis/checker-plugins.c +++ b/clang/test/Analysis/checker-plugins.c @@ -104,3 +104,12 @@ void caller() { // RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-CORRECTED-BOOL-VALUE // CHECK-CORRECTED-BOOL-VALUE: example.MyChecker:ExampleOption = false + +// RUN: %clang_analyze_cc1 %s \ +// RUN: -load %llvmshlibdir/CheckerOptionHandlingAnalyzerPlugin%pluginext\ +// RUN: -analyzer-checker=example.MyChecker \ +// RUN: -analyzer-checker-option-help \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-CHECKER-OPTION-HELP + +// CHECK-CHECKER-OPTION-HELP: example.MyChecker:ExampleOption (bool) This is an +// CHECK-CHECKER-OPTION-HELP-SAME: example checker opt. (default: false) From 987fdfd9a7197d4d1542817fd6c17b5fbb5856d7 Mon Sep 17 00:00:00 2001 From: Kit Barton Date: Thu, 23 May 2019 20:53:05 +0000 Subject: [PATCH 0088/1176] Revert [LOOPINFO] Extend Loop object to add utilities to get the loop bounds, step, induction variable, and guard branch. This reverts r361517 (git commit 2049e4dd8f61100f88f14db33bd95d197bcbfbbc) llvm-svn: 361553 --- llvm/include/llvm/Analysis/LoopInfo.h | 162 ---- llvm/lib/Analysis/LoopInfo.cpp | 246 ----- .../lib/Transforms/Scalar/LoopInterchange.cpp | 29 +- llvm/unittests/Analysis/LoopInfoTest.cpp | 900 ------------------ 4 files changed, 28 insertions(+), 1309 deletions(-) diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index dd789de493875..6b964cdf9eae5 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -54,12 +54,9 @@ namespace llvm { class DominatorTree; class LoopInfo; class Loop; -class InductionDescriptor; class MDNode; class MemorySSAUpdater; class PHINode; -class PostDominatorTree; -class ScalarEvolution; class raw_ostream; template class DominatorTreeBase; template class LoopInfoBase; @@ -532,165 +529,6 @@ class Loop : public LoopBase { bool getIncomingAndBackEdge(BasicBlock *&Incoming, BasicBlock *&Backedge) const; - /// Below are some utilities to get loop bounds and induction variable, and - /// check if a given phinode is an auxiliary induction variable, as well as - /// checking if the loop is canonical. - /// - /// Here is an example: - /// \code - /// for (int i = lb; i < ub; i+=step) - /// - /// --- pseudo LLVMIR --- - /// beforeloop: - /// guardcmp = (lb < ub) - /// if (guardcmp) goto preheader; else goto afterloop - /// preheader: - /// loop: - /// i_1 = phi[{lb, preheader}, {i_2, latch}] - /// - /// i_2 = i_1 + step - /// latch: - /// cmp = (i_2 < ub) - /// if (cmp) goto loop - /// exit: - /// afterloop: - /// \endcode - /// - /// - getBounds - /// - getInitialIVValue --> lb - /// - getStepInst --> i_2 = i_1 + step - /// - getStepValue --> step - /// - getFinalIVValue --> ub - /// - getCanonicalPredicate --> '<' - /// - getDirection --> Increasing - /// - /// - getInductionVariable --> i_1 - /// - isAuxiliaryInductionVariable(x) --> true if x == i_1 - /// - isCanonical --> false - struct LoopBounds { - /// Return the LoopBounds object if - /// - the given \p IndVar is an induction variable - /// - the initial value of the induction variable can be found - /// - the step instruction of the induction variable can be found - /// - the final value of the induction variable can be found - /// - /// Else None. - static Optional getBounds(const Loop &L, PHINode &IndVar, - ScalarEvolution &SE); - - /// Get the initial value of the loop induction variable. - Value &getInitialIVValue() const { return InitialIVValue; } - - /// Get the instruction that updates the loop induction variable. - Instruction &getStepInst() const { return StepInst; } - - /// Get the step that the loop induction variable gets updated by in each - /// loop iteration. Return nullptr if not found. - Value *getStepValue() const { return StepValue; } - - /// Get the final value of the loop induction variable. - Value &getFinalIVValue() const { return FinalIVValue; } - - /// Return the canonical predicate for the latch compare instruction, if - /// able to be calcuated. Else BAD_ICMP_PREDICATE. - /// - /// A predicate is considered as canonical if requirements below are all - /// satisfied: - /// 1. The first successor of the latch branch is the loop header - /// If not, inverse the predicate. - /// 2. One of the operands of the latch comparison is StepInst - /// If not, and - /// - if the current calcuated predicate is not ne or eq, flip the - /// predicate. - /// - else if the loop is increasing, return slt - /// (notice that it is safe to change from ne or eq to sign compare) - /// - else if the loop is decreasing, return sgt - /// (notice that it is safe to change from ne or eq to sign compare) - /// - /// Here is an example when both (1) and (2) are not satisfied: - /// \code - /// loop.header: - /// %iv = phi [%initialiv, %loop.preheader], [%inc, %loop.header] - /// %inc = add %iv, %step - /// %cmp = slt %iv, %finaliv - /// br %cmp, %loop.exit, %loop.header - /// loop.exit: - /// \endcode - /// - The second successor of the latch branch is the loop header instead - /// of the first successor (slt -> sge) - /// - The first operand of the latch comparison (%cmp) is the IndVar (%iv) - /// instead of the StepInst (%inc) (sge -> sgt) - /// - /// The predicate would be sgt if both (1) and (2) are satisfied. - /// getCanonicalPredicate() returns sgt for this example. - /// Note: The IR is not changed. - ICmpInst::Predicate getCanonicalPredicate() const; - - /// An enum for the direction of the loop - /// - for (int i = 0; i < ub; ++i) --> Increasing - /// - for (int i = ub; i > 0; --i) --> Descresing - /// - for (int i = x; i != y; i+=z) --> Unknown - enum class Direction { Increasing, Decreasing, Unknown }; - - /// Get the direction of the loop. - Direction getDirection() const; - - private: - LoopBounds(const Loop &Loop, Value &I, Instruction &SI, Value *SV, Value &F, - ScalarEvolution &SE) - : L(Loop), InitialIVValue(I), StepInst(SI), StepValue(SV), - FinalIVValue(F), SE(SE) {} - - const Loop &L; - - // The initial value of the loop induction variable - Value &InitialIVValue; - - // The instruction that updates the loop induction variable - Instruction &StepInst; - - // The value that the loop induction variable gets updated by in each loop - // iteration - Value *StepValue; - - // The final value of the loop induction variable - Value &FinalIVValue; - - ScalarEvolution &SE; - }; - - /// Return the struct LoopBounds collected if all struct members are found, - /// else None. - Optional getBounds(ScalarEvolution &SE) const; - - /// Return the loop induction variable if found, else return nullptr. - /// An instruction is considered as the loop induction variable if - /// - it is an induction variable of the loop; and - /// - it is used to determine the condition of the branch in the loop latch - /// - /// Note: the induction variable doesn't need to be canonical, i.e. starts at - /// zero and increments by one each time through the loop (but it can be). - PHINode *getInductionVariable(ScalarEvolution &SE) const; - - /// Get the loop induction descriptor for the loop induction variable. Return - /// true if the loop induction variable is found. - bool getInductionDescriptor(ScalarEvolution &SE, - InductionDescriptor &IndDesc) const; - - /// Return true if the given PHINode \p AuxIndVar is - /// - in the loop header - /// - not used outside of the loop - /// - incremented by a loop invariant step for each loop iteration - /// - step instruction opcode should be add or sub - /// Note: auxiliary induction variable is not required to be used in the - /// conditional branch in the loop latch. (but it can be) - bool isAuxiliaryInductionVariable(PHINode &AuxIndVar, - ScalarEvolution &SE) const; - - /// Return true if the loop induction variable starts at zero and increments - /// by one each time through the loop. - bool isCanonical(ScalarEvolution &SE) const; - /// Return true if the Loop is in LCSSA form. bool isLCSSAForm(DominatorTree &DT) const; diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index 50e08e994876a..aa933d98f249b 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -17,13 +17,10 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Analysis/IVDescriptors.h" #include "llvm/Analysis/LoopInfoImpl.h" #include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/MemorySSAUpdater.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/CFG.h" @@ -167,249 +164,6 @@ PHINode *Loop::getCanonicalInductionVariable() const { return nullptr; } -/// Return true if V1 and V2 have the same value ignoring bit width. -static bool isEqualIgnoreBitwidth(Value &V1, Value &V2, ScalarEvolution &SE) { - const SCEV *S1 = SE.getSCEV(&V1); - const SCEV *S2 = SE.getSCEV(&V2); - Type *WiderType = SE.getWiderType(S1->getType(), S2->getType()); - S1 = SE.getNoopOrAnyExtend(S1, WiderType); - S2 = SE.getNoopOrAnyExtend(S2, WiderType); - return SE.getMinusSCEV(S1, S2)->isZero(); -} - -/// Get the latch condition instruction. -static ICmpInst *getLatchCmpInst(const Loop &L) { - if (BasicBlock *Latch = L.getLoopLatch()) - if (BranchInst *BI = dyn_cast_or_null(Latch->getTerminator())) - if (BI->isConditional()) - return dyn_cast(BI->getCondition()); - - return nullptr; -} - -/// Return the final value of the loop induction variable if found. -static Value *findFinalIVValue(const Loop &L, const PHINode &IndVar, - const Instruction &StepInst) { - ICmpInst *LatchCmpInst = getLatchCmpInst(L); - if (!LatchCmpInst) - return nullptr; - - Value *Op0 = LatchCmpInst->getOperand(0); - Value *Op1 = LatchCmpInst->getOperand(1); - if (Op0 == &IndVar || Op0 == &StepInst) - return Op1; - - if (Op1 == &IndVar || Op1 == &StepInst) - return Op0; - - return nullptr; -} - -Optional Loop::LoopBounds::getBounds(const Loop &L, - PHINode &IndVar, - ScalarEvolution &SE) { - InductionDescriptor IndDesc; - if (!InductionDescriptor::isInductionPHI(&IndVar, &L, &SE, IndDesc)) - return None; - - Value *InitialIVValue = IndDesc.getStartValue(); - Instruction *StepInst = IndDesc.getInductionBinOp(); - if (!InitialIVValue || !StepInst) - return None; - - const SCEV *Step = IndDesc.getStep(); - Value *StepInstOp1 = StepInst->getOperand(1); - Value *StepInstOp0 = StepInst->getOperand(0); - Value *StepValue = nullptr; - if (SE.getSCEV(StepInstOp1) == Step) - StepValue = StepInstOp1; - else if (SE.getSCEV(StepInstOp0) == Step) - StepValue = StepInstOp0; - - Value *FinalIVValue = findFinalIVValue(L, IndVar, *StepInst); - if (!FinalIVValue) - return None; - - return LoopBounds(L, *InitialIVValue, *StepInst, StepValue, *FinalIVValue, - SE); -} - -using Direction = Loop::LoopBounds::Direction; - -ICmpInst::Predicate Loop::LoopBounds::getCanonicalPredicate() const { - BasicBlock *Latch = L.getLoopLatch(); - assert(Latch && "Expecting valid latch"); - - BranchInst *BI = dyn_cast_or_null(Latch->getTerminator()); - assert(BI && BI->isConditional() && "Expecting conditional latch branch"); - - ICmpInst *LatchCmpInst = dyn_cast(BI->getCondition()); - assert(LatchCmpInst && - "Expecting the latch compare instruction to be a CmpInst"); - - // Need to inverse the predicate when first successor is not the loop - // header - ICmpInst::Predicate Pred = (BI->getSuccessor(0) == L.getHeader()) - ? LatchCmpInst->getPredicate() - : LatchCmpInst->getInversePredicate(); - - if (LatchCmpInst->getOperand(0) == &getFinalIVValue()) - Pred = ICmpInst::getSwappedPredicate(Pred); - - // Need to flip strictness of the predicate when the latch compare instruction - // is not using StepInst - if (LatchCmpInst->getOperand(0) == &getStepInst() || - LatchCmpInst->getOperand(1) == &getStepInst()) - return Pred; - - // Cannot flip strictness of NE and EQ - if (Pred != ICmpInst::ICMP_NE && Pred != ICmpInst::ICMP_EQ) - return ICmpInst::getFlippedStrictnessPredicate(Pred); - - Direction D = getDirection(); - if (D == Direction::Increasing) - return ICmpInst::ICMP_SLT; - - if (D == Direction::Decreasing) - return ICmpInst::ICMP_SGT; - - // If cannot determine the direction, then unable to find the canonical - // predicate - return ICmpInst::BAD_ICMP_PREDICATE; -} - -Direction Loop::LoopBounds::getDirection() const { - if (const SCEVAddRecExpr *StepAddRecExpr = - dyn_cast(SE.getSCEV(&getStepInst()))) - if (const SCEV *StepRecur = StepAddRecExpr->getStepRecurrence(SE)) { - if (SE.isKnownPositive(StepRecur)) - return Direction::Increasing; - if (SE.isKnownNegative(StepRecur)) - return Direction::Decreasing; - } - - return Direction::Unknown; -} - -Optional Loop::getBounds(ScalarEvolution &SE) const { - if (PHINode *IndVar = getInductionVariable(SE)) - return LoopBounds::getBounds(*this, *IndVar, SE); - - return None; -} - -PHINode *Loop::getInductionVariable(ScalarEvolution &SE) const { - if (!isLoopSimplifyForm()) - return nullptr; - - BasicBlock *Header = getHeader(); - assert(Header && "Expected a valid loop header"); - BasicBlock *Latch = getLoopLatch(); - assert(Latch && "Expected a valid loop latch"); - ICmpInst *CmpInst = getLatchCmpInst(*this); - if (!CmpInst) - return nullptr; - - // case 1: - // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}] - // StepInst = IndVar + step - // cmp = StepInst < FinalValue - Instruction *LatchCmpOp0 = dyn_cast(CmpInst->getOperand(0)); - Instruction *LatchCmpOp1 = dyn_cast(CmpInst->getOperand(1)); - // Loop over all of the PHI nodes in loop header, store the PHI node that has - // incoming value from latch equals to the StepInst - BinaryOperator *StepInst = nullptr; - PHINode *IndVar = nullptr; - for (PHINode &PN : Header->phis()) { - Value *IncomingValue = PN.getIncomingValueForBlock(Latch); - assert(IncomingValue && "Expecting valid incoming value from latch"); - if (IncomingValue == LatchCmpOp0 || IncomingValue == LatchCmpOp1) { - IndVar = &PN; - StepInst = dyn_cast(IncomingValue); - if (StepInst) - if (isEqualIgnoreBitwidth(*StepInst->getOperand(0), *IndVar, SE) || - isEqualIgnoreBitwidth(*StepInst->getOperand(1), *IndVar, SE)) - return IndVar; - } - } - - // case 2: - // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}] - // StepInst = IndVar + step - // cmp = IndVar < FinalValue - for (Value *Op : CmpInst->operands()) { - PHINode *IndVar = dyn_cast(Op); - if (!IndVar) - continue; - - if (IndVar->getParent() != Header) - continue; - - Value *IncomingValue = IndVar->getIncomingValueForBlock(Latch); - assert(IncomingValue && "Expecting valid incoming value from latch"); - StepInst = dyn_cast(IncomingValue); - if (StepInst) - if (StepInst->getOperand(0) == IndVar || - StepInst->getOperand(1) == IndVar) - return IndVar; - } - - return nullptr; -} - -bool Loop::getInductionDescriptor(ScalarEvolution &SE, - InductionDescriptor &IndDesc) const { - if (PHINode *IndVar = getInductionVariable(SE)) - return InductionDescriptor::isInductionPHI(IndVar, this, &SE, IndDesc); - - return false; -} - -bool Loop::isAuxiliaryInductionVariable(PHINode &AuxIndVar, - ScalarEvolution &SE) const { - // Located in the loop header - BasicBlock *Header = getHeader(); - if (AuxIndVar.getParent() != Header) - return false; - - // No uses outside of the loop - for (User *U : AuxIndVar.users()) - if (const Instruction *I = dyn_cast(U)) - if (!contains(I)) - return false; - - InductionDescriptor IndDesc; - if (!InductionDescriptor::isInductionPHI(&AuxIndVar, this, &SE, IndDesc)) - return false; - - // The step instruction opcode should be add or sub. - if (IndDesc.getInductionOpcode() != Instruction::Add && - IndDesc.getInductionOpcode() != Instruction::Sub) - return false; - - // Incremented by a loop invariant step for each loop iteration - return SE.isLoopInvariant(IndDesc.getStep(), this); -} - -bool Loop::isCanonical(ScalarEvolution &SE) const { - InductionDescriptor IndDesc; - if (!getInductionDescriptor(SE, IndDesc)) - return false; - - ConstantInt *Init = dyn_cast_or_null(IndDesc.getStartValue()); - if (!Init || !Init->isZero()) - return false; - - if (IndDesc.getInductionOpcode() != Instruction::Add) - return false; - - ConstantInt *Step = IndDesc.getConstIntStepValue(); - if (!Step || !Step->isOne()) - return false; - - return true; -} - // Check that 'BB' doesn't have any uses outside of the 'L' static bool isBlockInLCSSAForm(const Loop &L, const BasicBlock &BB, DominatorTree &DT) { diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index ad7113cb0e9a0..bec5af584f438 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -292,6 +292,33 @@ static LoopVector populateWorklist(Loop &L) { return LoopList; } +static PHINode *getInductionVariable(Loop *L, ScalarEvolution *SE) { + PHINode *InnerIndexVar = L->getCanonicalInductionVariable(); + if (InnerIndexVar) + return InnerIndexVar; + if (L->getLoopLatch() == nullptr || L->getLoopPredecessor() == nullptr) + return nullptr; + for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) { + PHINode *PhiVar = cast(I); + Type *PhiTy = PhiVar->getType(); + if (!PhiTy->isIntegerTy() && !PhiTy->isFloatingPointTy() && + !PhiTy->isPointerTy()) + return nullptr; + const SCEVAddRecExpr *AddRec = + dyn_cast(SE->getSCEV(PhiVar)); + if (!AddRec || !AddRec->isAffine()) + continue; + const SCEV *Step = AddRec->getStepRecurrence(*SE); + if (!isa(Step)) + continue; + // Found the induction variable. + // FIXME: Handle loops with more than one induction variable. Note that, + // currently, legality makes sure we have only one induction variable. + return PhiVar; + } + return nullptr; +} + namespace { /// LoopInterchangeLegality checks if it is legal to interchange the loop. @@ -1200,7 +1227,7 @@ bool LoopInterchangeTransform::transform() { if (InnerLoop->getSubLoops().empty()) { BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader(); LLVM_DEBUG(dbgs() << "Calling Split Inner Loop\n"); - PHINode *InductionPHI = InnerLoop->getInductionVariable(*SE); + PHINode *InductionPHI = getInductionVariable(InnerLoop, SE); if (!InductionPHI) { LLVM_DEBUG(dbgs() << "Failed to find the point to split loop latch \n"); return false; diff --git a/llvm/unittests/Analysis/LoopInfoTest.cpp b/llvm/unittests/Analysis/LoopInfoTest.cpp index 005e1dc405b75..483532a187527 100644 --- a/llvm/unittests/Analysis/LoopInfoTest.cpp +++ b/llvm/unittests/Analysis/LoopInfoTest.cpp @@ -7,10 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/AssumptionCache.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Dominators.h" #include "llvm/Support/SourceMgr.h" @@ -30,26 +26,6 @@ runWithLoopInfo(Module &M, StringRef FuncName, Test(*F, LI); } -/// Build the loop info and scalar evolution for the function and run the Test. -static void runWithLoopInfoPlus( - Module &M, StringRef FuncName, - function_ref - Test) { - auto *F = M.getFunction(FuncName); - ASSERT_NE(F, nullptr) << "Could not find " << FuncName; - - TargetLibraryInfoImpl TLII; - TargetLibraryInfo TLI(TLII); - AssumptionCache AC(*F); - DominatorTree DT(*F); - LoopInfo LI(DT); - ScalarEvolution SE(*F, TLI, AC, DT, LI); - - PostDominatorTree PDT(*F); - Test(*F, LI, SE, PDT); -} - static std::unique_ptr makeLLVMModule(LLVMContext &Context, const char *ModuleStr) { SMDiagnostic Err; @@ -234,879 +210,3 @@ TEST(LoopInfoTest, PreorderTraversals) { EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]); EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]); } - -TEST(LoopInfoTest, CanonicalLoop) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopWithInverseGuardSuccs) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp sge i32 0, %ub\n" - " br i1 %guardcmp, label %for.end, label %for.preheader\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopWithSwappedGuardCmp) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp sgt i32 %ub, 0\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp sge i32 %inc, %ub\n" - " br i1 %cmp, label %for.exit, label %for.body\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopWithInverseLatchSuccs) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp sge i32 %inc, %ub\n" - " br i1 %cmp, label %for.exit, label %for.body\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopWithLatchCmpNE) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp ne i32 %i, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopWithGuardCmpSLE) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %ubPlusOne = add i32 %ub, 1\n" - " %guardcmp = icmp sle i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp ne i32 %i, %ubPlusOne\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ubPlusOne"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopNonConstantStep) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = zext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, %step\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopUnsignedBounds) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp ult i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = zext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add i32 %i, 1\n" - " %cmp = icmp ult i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_ULT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, DecreasingLoop) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ %ub, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = sub nsw i32 %i, 1\n" - " %cmp = icmp sgt i32 %inc, 0\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - EXPECT_EQ(Bounds->getInitialIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_EQ(StepValue, nullptr); - ConstantInt *FinalIVValue = - dyn_cast(&Bounds->getFinalIVValue()); - EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero()); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SGT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Decreasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, CannotFindDirection) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub, i32 %step) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, %step\n" - " %cmp = icmp ne i32 %i, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus(*M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - // - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - EXPECT_EQ(Bounds->getStepValue()->getName(), "step"); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), - ICmpInst::BAD_ICMP_PREDICATE); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Unknown); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, ZextIndVar) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %indvars.iv = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next, %for.body ]\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n" - " %inc = add nsw i32 %i, 1\n" - " %wide.trip.count = zext i32 %ub to i64\n" - " %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n" - " br i1 %exitcond, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "indvars.iv.next"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "wide.trip.count"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_NE); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv"); - }); -} - -TEST(LoopInfoTest, UnguardedLoop) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First basic block is entry - skip it. - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, UnguardedLoopWithControlFlow) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n" - "entry:\n" - " br i1 %cond, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, LoopNest) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.outer.preheader, label %for.end\n" - "for.outer.preheader:\n" - " br label %for.outer\n" - "for.outer:\n" - " %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]\n" - " br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch\n" - "for.inner.preheader:\n" - " br label %for.inner\n" - "for.inner:\n" - " %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.inner, label %for.inner.exit\n" - "for.inner.exit:\n" - " br label %for.outer.latch\n" - "for.outer.latch:\n" - " %inc.outer = add nsw i32 %j, 1\n" - " %cmp.outer = icmp slt i32 %inc.outer, %ub\n" - " br i1 %cmp.outer, label %for.outer, label %for.outer.exit\n" - "for.outer.exit:\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.outer.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.outer"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc.outer"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j"); - - // Next two basic blocks are for.outer and for.inner.preheader - skip - // them. - ++FI; - Header = &*(++FI); - assert(Header->getName() == "for.inner"); - L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional InnerBounds = L->getBounds(SE); - EXPECT_NE(InnerBounds, None); - InitialIVValue = - dyn_cast(&InnerBounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(InnerBounds->getStepInst().getName(), "inc"); - StepValue = dyn_cast_or_null(InnerBounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(InnerBounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(InnerBounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(InnerBounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - }); -} - -TEST(LoopInfoTest, AuxiliaryIV) { - const char *ModuleStr = - "define void @foo(i32* %A, i32 %ub) {\n" - "entry:\n" - " %guardcmp = icmp slt i32 0, %ub\n" - " br i1 %guardcmp, label %for.preheader, label %for.end\n" - "for.preheader:\n" - " br label %for.body\n" - "for.body:\n" - " %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n" - " %aux = phi i32 [ 0, %for.preheader ], [ %auxinc, %for.body ]\n" - " %loopvariant = phi i32 [ 0, %for.preheader ], [ %loopvariantinc, %for.body ]\n" - " %usedoutside = phi i32 [ 0, %for.preheader ], [ %usedoutsideinc, %for.body ]\n" - " %mulopcode = phi i32 [ 0, %for.preheader ], [ %mulopcodeinc, %for.body ]\n" - " %idxprom = sext i32 %i to i64\n" - " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n" - " store i32 %i, i32* %arrayidx, align 4\n" - " %mulopcodeinc = mul nsw i32 %mulopcode, 5\n" - " %usedoutsideinc = add nsw i32 %usedoutside, 5\n" - " %loopvariantinc = add nsw i32 %loopvariant, %i\n" - " %auxinc = add nsw i32 %aux, 5\n" - " %inc = add nsw i32 %i, 1\n" - " %cmp = icmp slt i32 %inc, %ub\n" - " br i1 %cmp, label %for.body, label %for.exit\n" - "for.exit:\n" - " %lcssa = phi i32 [ %usedoutside, %for.body ]\n" - " br label %for.end\n" - "for.end:\n" - " ret void\n" - "}\n"; - - // Parse the module. - LLVMContext Context; - std::unique_ptr M = makeLLVMModule(Context, ModuleStr); - - runWithLoopInfoPlus( - *M, "foo", - [&](Function &F, LoopInfo &LI, ScalarEvolution &SE, - PostDominatorTree &PDT) { - Function::iterator FI = F.begin(); - // First two basic block are entry and for.preheader - skip them. - ++FI; - BasicBlock *Header = &*(++FI); - assert(Header->getName() == "for.body"); - Loop *L = LI.getLoopFor(Header); - EXPECT_NE(L, nullptr); - - Optional Bounds = L->getBounds(SE); - EXPECT_NE(Bounds, None); - ConstantInt *InitialIVValue = - dyn_cast(&Bounds->getInitialIVValue()); - EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero()); - EXPECT_EQ(Bounds->getStepInst().getName(), "inc"); - ConstantInt *StepValue = - dyn_cast_or_null(Bounds->getStepValue()); - EXPECT_TRUE(StepValue && StepValue->isOne()); - EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub"); - EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT); - EXPECT_EQ(Bounds->getDirection(), - Loop::LoopBounds::Direction::Increasing); - EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i"); - BasicBlock::iterator II = Header->begin(); - PHINode &Instruction_i = cast(*(II)); - EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_i, SE)); - PHINode &Instruction_aux = cast(*(++II)); - EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_aux, SE)); - PHINode &Instruction_loopvariant = cast(*(++II)); - EXPECT_FALSE( - L->isAuxiliaryInductionVariable(Instruction_loopvariant, SE)); - PHINode &Instruction_usedoutside = cast(*(++II)); - EXPECT_FALSE( - L->isAuxiliaryInductionVariable(Instruction_usedoutside, SE)); - PHINode &Instruction_mulopcode = cast(*(++II)); - EXPECT_FALSE( - L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); - }); -} From f53c502e0b5abb5a72bea5f7081baa45a8a99639 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 23 May 2019 21:04:01 +0000 Subject: [PATCH 0089/1176] [TTI] Fix some typos in comments. NFC 'implementaion' -> 'implementation' 'non-unform' -> 'non-uniform' 'mimimum' -> 'minimum' Patch by Pavel Samolysov Differential Revision: https://reviews.llvm.org/D62136 llvm-svn: 361554 --- llvm/include/llvm/Analysis/TargetTransformInfo.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index 75f07989785b5..5a94bfad7e037 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -80,7 +80,7 @@ class TargetTransformInfo { /// API below. /// /// This is used by targets to construct a TTI wrapping their target-specific - /// implementaion that encodes appropriate costs for their target. + /// implementation that encodes appropriate costs for their target. template TargetTransformInfo(T Impl); /// Construct a baseline TTI object using a minimal implementation of @@ -246,7 +246,7 @@ class TargetTransformInfo { ArrayRef Arguments, const User *U = nullptr) const; - /// \Return the expected cost of a memcpy, which could e.g. depend on the + /// \return the expected cost of a memcpy, which could e.g. depend on the /// source/destination type and alignment and the number of bytes copied. int getMemcpyCost(const Instruction *I) const; @@ -304,7 +304,7 @@ class TargetTransformInfo { // Returns true for the target specific // set of operations which produce uniform result - // even taking non-unform arguments + // even taking non-uniform arguments bool isAlwaysUniform(const Value *V) const; /// Returns the address space ID for a target's 'flat' address space. Note @@ -716,7 +716,7 @@ class TargetTransformInfo { bool shouldMaximizeVectorBandwidth(bool OptSize) const; /// \return The minimum vectorization factor for types of given element - /// bit width, or 0 if there is no mimimum VF. The returned value only + /// bit width, or 0 if there is no minimum VF. The returned value only /// applies when shouldMaximizeVectorBandwidth returns true. unsigned getMinimumVF(unsigned ElemWidth) const; From b4cb7d8045e38b7fcca3cf6da254b2a1ba7b5710 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 23 May 2019 21:13:50 +0000 Subject: [PATCH 0090/1176] [NFC] Add blank line (test commit) llvm-svn: 361555 --- lldb/tools/debugserver/source/debugserver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp index 5a0681847a8e1..0698d69375f6c 100644 --- a/lldb/tools/debugserver/source/debugserver.cpp +++ b/lldb/tools/debugserver/source/debugserver.cpp @@ -490,6 +490,7 @@ RNBRunLoopMode HandleProcessStateChange(RNBRemote *remote, bool initialize) { // Catch all... return eRNBRunLoopModeExit; } + // This function handles the case where our inferior program is stopped and // we are waiting for gdb remote protocol packets. When a packet occurs that // makes the inferior run, we need to leave this function with a new state From ca6a8ae0bffe88f3f0974316b2408b2548ff6f77 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 23 May 2019 21:30:30 +0000 Subject: [PATCH 0091/1176] ELF: Remove a comparison against In.EhFrame. NFCI. This won't work once we have multiple .eh_frame sections. Differential Revision: https://reviews.llvm.org/D62280 llvm-svn: 361556 --- lld/ELF/MapFile.cpp | 9 +++++---- lld/ELF/SyntheticSections.h | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index 11720e196d3a9..2f1921ec9837d 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -106,7 +106,7 @@ getSymbolStrings(ArrayRef Syms) { // .eh_frame tend to contain a lot of section pieces that are contiguous // both in input file and output file. Such pieces are squashed before // being displayed to make output compact. -static void printEhFrame(raw_ostream &OS, OutputSection *OSec) { +static void printEhFrame(raw_ostream &OS, const EhFrameSection *Sec) { std::vector Pieces; auto Add = [&](const EhSectionPiece &P) { @@ -123,13 +123,14 @@ static void printEhFrame(raw_ostream &OS, OutputSection *OSec) { }; // Gather section pieces. - for (const CieRecord *Rec : In.EhFrame->getCieRecords()) { + for (const CieRecord *Rec : Sec->getCieRecords()) { Add(*Rec->Cie); for (const EhSectionPiece *Fde : Rec->Fdes) Add(*Fde); } // Print out section pieces. + const OutputSection *OSec = Sec->getOutputSection(); for (EhSectionPiece &P : Pieces) { writeHeader(OS, OSec->Addr + P.OutputOff, OSec->getLMA() + P.OutputOff, P.Size, 1); @@ -179,8 +180,8 @@ void elf::writeMapFile() { for (BaseCommand *Base : OSec->SectionCommands) { if (auto *ISD = dyn_cast(Base)) { for (InputSection *IS : ISD->Sections) { - if (IS == In.EhFrame) { - printEhFrame(OS, OSec); + if (auto *EhSec = dyn_cast(IS)) { + printEhFrame(OS, EhSec); continue; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index e848d0d76ab6a..58a01ea6c54cb 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -69,6 +69,10 @@ class EhFrameSection final : public SyntheticSection { bool isNeeded() const override { return !Sections.empty(); } size_t getSize() const override { return Size; } + static bool classof(const SectionBase *D) { + return SyntheticSection::classof(D) && D->Name == ".eh_frame"; + } + template void addSection(InputSectionBase *S); std::vector Sections; From a85c0fd918749fe88c3a3bbc5ca23061e88b4536 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 23 May 2019 21:34:36 +0000 Subject: [PATCH 0092/1176] [X86] Split multi-line chained assignments into single lines to avoid making clang-format create triangle shaped indentation. Simplify one if statement to remove a bunch of string matches. NFCI We had an if statement that checked over every avx512* feature to see if it should enabled avx512f. Since they are all prefixed with avx512 just check for that instead. llvm-svn: 361557 --- clang/lib/Basic/Targets/X86.cpp | 50 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 44f5fbf5a7d14..7bef7ce9c66e2 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -451,7 +451,9 @@ void X86TargetInfo::setSSELevel(llvm::StringMap &Features, if (Enabled) { switch (Level) { case AVX512F: - Features["avx512f"] = Features["fma"] = Features["f16c"] = true; + Features["avx512f"] = true; + Features["fma"] = true; + Features["f16c"] = true; LLVM_FALLTHROUGH; case AVX2: Features["avx2"] = true; @@ -490,8 +492,8 @@ void X86TargetInfo::setSSELevel(llvm::StringMap &Features, Features["sse"] = false; LLVM_FALLTHROUGH; case SSE2: - Features["sse2"] = Features["pclmul"] = Features["aes"] = Features["sha"] = - Features["gfni"] = false; + Features["sse2"] = Features["pclmul"] = Features["aes"] = false; + Features["sha"] = Features["gfni"] = false; LLVM_FALLTHROUGH; case SSE3: Features["sse3"] = false; @@ -507,21 +509,21 @@ void X86TargetInfo::setSSELevel(llvm::StringMap &Features, Features["sse4.2"] = false; LLVM_FALLTHROUGH; case AVX: - Features["fma"] = Features["avx"] = Features["f16c"] = Features["xsave"] = - Features["xsaveopt"] = Features["vaes"] = Features["vpclmulqdq"] = false; + Features["fma"] = Features["avx"] = Features["f16c"] = false; + Features["xsave"] = Features["xsaveopt"] = Features["vaes"] = false; + Features["vpclmulqdq"] = false; setXOPLevel(Features, FMA4, false); LLVM_FALLTHROUGH; case AVX2: Features["avx2"] = false; LLVM_FALLTHROUGH; case AVX512F: - Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] = - Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] = - Features["avx512vl"] = Features["avx512vbmi"] = - Features["avx512ifma"] = Features["avx512vpopcntdq"] = - Features["avx512bitalg"] = Features["avx512vnni"] = - Features["avx512vbmi2"] = false; - Features["avx512bf16"] = false; + Features["avx512f"] = Features["avx512cd"] = Features["avx512er"] = false; + Features["avx512pf"] = Features["avx512dq"] = Features["avx512bw"] = false; + Features["avx512vl"] = Features["avx512vbmi"] = false; + Features["avx512ifma"] = Features["avx512vpopcntdq"] = false; + Features["avx512bitalg"] = Features["avx512vnni"] = false; + Features["avx512vbmi2"] = Features["avx512bf16"] = false; break; } } @@ -649,24 +651,20 @@ void X86TargetInfo::setFeatureEnabledImpl(llvm::StringMap &Features, setSSELevel(Features, AVX2, Enabled); } else if (Name == "avx512f") { setSSELevel(Features, AVX512F, Enabled); - } else if (Name == "avx512cd" || Name == "avx512er" || Name == "avx512pf" || - Name == "avx512dq" || Name == "avx512bw" || Name == "avx512vl" || - Name == "avx512vbmi" || Name == "avx512ifma" || - Name == "avx512vpopcntdq" || Name == "avx512bitalg" || - Name == "avx512bf16" || - Name == "avx512vnni" || Name == "avx512vbmi2") { + } else if (Name.startswith("avx512")) { if (Enabled) setSSELevel(Features, AVX512F, Enabled); - // Enable BWI instruction if VBMI/VBMI2/BITALG is being enabled. - if ((Name.startswith("avx512vbmi") || Name == "avx512bitalg") && Enabled) + // Enable BWI instruction if certain features are being enabled. + if ((Name == "avx512vbmi" || Name == "avx512vbmi2" || + Name == "avx512bitalg" || Name == "avx512bf16") && Enabled) Features["avx512bw"] = true; - if (Name == "avx512bf16" && Enabled) - Features["avx512bw"] = true; - // Also disable VBMI/VBMI2/BITALG if BWI is being disabled. - if (Name == "avx512bw" && !Enabled) - Features["avx512vbmi"] = Features["avx512vbmi2"] = - Features["avx512bf16"] = + // Also disable some features if BWI is being disabled. + if (Name == "avx512bw" && !Enabled) { + Features["avx512vbmi"] = false; + Features["avx512vbmi2"] = false; Features["avx512bitalg"] = false; + Features["avx512bf16"] = false; + } } else if (Name == "fma") { if (Enabled) setSSELevel(Features, AVX, Enabled); From 5bc40d9b188bb43e2aafafe58d8d169cc7c9b4f1 Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 23 May 2019 21:46:51 +0000 Subject: [PATCH 0093/1176] [analyzer] List checkers in 3 categories: released, alpha, developer Previously, the only way to display the list of available checkers was to invoke the analyzer with -analyzer-checker-help frontend flag. This however wasn't really great from a maintainer standpoint: users came across checkers meant strictly for development purposes that weren't to be tinkered with, or those that were still in development. This patch creates a clearer division in between these categories. From now on, we'll have 3 flags to display the list checkers. These lists are mutually exclusive and can be used in any combination (for example to display both stable and alpha checkers). -analyzer-checker-help: Displays the list for stable, production ready checkers. -analyzer-checker-help-alpha: Displays the list for in development checkers. Enabling is discouraged for non-development purposes. -analyzer-checker-help-developer: Modeling and debug checkers. Modeling checkers shouldn't be enabled/disabled by hand, and debug checkers shouldn't be touched by users. Differential Revision: https://reviews.llvm.org/D62093 llvm-svn: 361558 --- clang/include/clang/Driver/CC1Options.td | 11 +++- .../StaticAnalyzer/Checkers/CheckerBase.td | 4 +- .../StaticAnalyzer/Core/AnalyzerOptions.h | 16 ++--- clang/lib/Frontend/CompilerInvocation.cpp | 4 +- .../ExecuteCompilerInvocation.cpp | 3 +- .../Frontend/CheckerRegistry.cpp | 31 +++++++-- clang/test/Analysis/show-checker-list.c | 63 ++++++++++++++++--- 7 files changed, 107 insertions(+), 25 deletions(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index f7da3746bd4f3..7605b3fc131ac 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -130,9 +130,14 @@ def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">, def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; -def analyzer_checker_help_hidden : Flag<["-"], "analyzer-checker-help-hidden">, - HelpText<"Display the list of analyzer checkers that are available, " - "including modeling checkers">; +def analyzer_checker_help_alpha : Flag<["-"], "analyzer-checker-help-alpha">, + HelpText<"Display the list of in development analyzer checkers. These " + "are NOT considered safe, they are unstable and will emit incorrect " + "reports. Enable ONLY FOR DEVELOPMENT purposes">; + +def analyzer_checker_help_developer : Flag<["-"], "analyzer-checker-help-developer">, + HelpText<"Display the list of developer-only checkers such as modeling " + "and debug checkers">; def analyzer_config_help : Flag<["-"], "analyzer-config-help">, HelpText<"Display the list of -analyzer-config options">; diff --git a/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index c381d4b13ecd4..3c7c6fe9b2abc 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -111,6 +111,6 @@ class Dependencies Deps = []> { list Dependencies = Deps; } -/// Marks a checker or a package hidden. Hidden entries won't be displayed in -/// -analyzer-checker-help, which is desirable for alpha or modeling checkers. +/// Marks a checker or a package hidden. Hidden entries are meant for developers +/// only, and aren't exposed to end users. class Hidden { bit Hidden = 1; } diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 6a54e157e88e1..1c45ffdff89af 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -220,7 +220,8 @@ class AnalyzerOptions : public RefCountedBase { unsigned DisableAllChecks : 1; unsigned ShowCheckerHelp : 1; - unsigned ShowCheckerHelpHidden : 1; + unsigned ShowCheckerHelpAlpha : 1; + unsigned ShowCheckerHelpDeveloper : 1; unsigned ShowEnabledCheckerList : 1; unsigned ShowCheckerOptionList : 1; unsigned ShowConfigOptionsList : 1; @@ -285,12 +286,13 @@ class AnalyzerOptions : public RefCountedBase { AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), - ShowCheckerHelpHidden(false), ShowEnabledCheckerList(false), - ShowCheckerOptionList(false), ShowConfigOptionsList(false), - AnalyzeAll(false), AnalyzerDisplayProgress(false), - AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), - TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), - UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) { + ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), + ShowEnabledCheckerList(false), ShowCheckerOptionList(false), + ShowConfigOptionsList(false), AnalyzeAll(false), + AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false) { llvm::sort(AnalyzerConfigCmdFlags); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 877e70b6616cb..34693af8f4fd3 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -285,7 +285,9 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); - Opts.ShowCheckerHelpHidden = Args.hasArg(OPT_analyzer_checker_help_hidden); + Opts.ShowCheckerHelpAlpha = Args.hasArg(OPT_analyzer_checker_help_alpha); + Opts.ShowCheckerHelpDeveloper = + Args.hasArg(OPT_analyzer_checker_help_developer); Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help); Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 27690be777b8d..ea720c83c2933 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -238,7 +238,8 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { AnalyzerOptions &AnOpts = *Clang->getAnalyzerOpts(); // Honor -analyzer-checker-help and -analyzer-checker-help-hidden. - if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpHidden) { + if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha || + AnOpts.ShowCheckerHelpDeveloper) { ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins, AnOpts, diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index d405933ca65c5..5f96389e597b4 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -514,13 +514,36 @@ void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out, } const size_t InitialPad = 2; - for (const auto &Checker : Checkers) { - if (!AnOpts.ShowCheckerHelpHidden && Checker.IsHidden) - continue; - AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Checker.Desc}, + auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker, + StringRef Description) { + AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description}, InitialPad, OptionFieldWidth); Out << '\n'; + }; + + for (const auto &Checker : Checkers) { + // The order of this if branches is significant, we wouldn't like to display + // developer checkers even in the alpha output. For example, + // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden + // by default, and users (even when the user is a developer of an alpha + // checker) shouldn't normally tinker with whether they should be enabled. + + if (Checker.IsHidden) { + if (AnOpts.ShowCheckerHelpDeveloper) + Print(Out, Checker, Checker.Desc); + continue; + } + + if (Checker.FullName.startswith("alpha")) { + if (AnOpts.ShowCheckerHelpAlpha) + Print(Out, Checker, + ("(Enable only for development!) " + Checker.Desc).str()); + continue; + } + + if (AnOpts.ShowCheckerHelp) + Print(Out, Checker, Checker.Desc); } } diff --git a/clang/test/Analysis/show-checker-list.c b/clang/test/Analysis/show-checker-list.c index 83ed6e4897943..3d354c338b9b3 100644 --- a/clang/test/Analysis/show-checker-list.c +++ b/clang/test/Analysis/show-checker-list.c @@ -1,11 +1,60 @@ // RUN: %clang_cc1 -analyzer-checker-help \ -// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE -// RUN: %clang_cc1 -analyzer-checker-help-hidden \ -// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-HIDDEN +// RUN: %clang_cc1 -analyzer-checker-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-ALPHA -// CHECK: core.DivideZero -// CHECK-HIDDEN: core.DivideZero +// RUN: %clang_cc1 -analyzer-checker-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DEVELOPER -// CHECK-NOT: unix.DynamicMemoryModeling -// CHECK-HIDDEN: unix.DynamicMemoryModeling +// RUN: %clang_cc1 -analyzer-checker-help-developer \ +// RUN: -analyzer-checker-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DEVELOPER-ALPHA + +// RUN: %clang_cc1 -analyzer-checker-help \ +// RUN: -analyzer-checker-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-ALPHA + +// RUN: %clang_cc1 -analyzer-checker-help \ +// RUN: -analyzer-checker-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-DEVELOPER + +// RUN: %clang_cc1 -analyzer-checker-help \ +// RUN: -analyzer-checker-help-alpha \ +// RUN: -analyzer-checker-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-ALPHA-DEVELOPER + +// CHECK-STABLE-NOT: alpha.unix.Chroot +// CHECK-DEVELOPER-NOT: alpha.unix.Chroot +// CHECK-ALPHA: alpha.unix.Chroot + +// Note that alpha.cplusplus.IteratorModeling is not only an alpha, but also a +// hidden checker. In this case, we'd only like to see it in the developer list. +// CHECK-ALPHA-NOT: alpha.cplusplus.IteratorModeling +// CHECK-DEVELOPER: alpha.cplusplus.IteratorModeling + +// CHECK-STABLE: core.DivideZero +// CHECK-DEVELOPER-NOT: core.DivideZero +// CHECK-ALPHA-NOT: core.DivideZero + +// CHECK-STABLE-NOT: debug.ConfigDumper +// CHECK-DEVELOPER: debug.ConfigDumper +// CHECK-ALPHA-NOT: debug.ConfigDumper + + +// CHECK-STABLE-ALPHA: alpha.unix.Chroot +// CHECK-DEVELOPER-ALPHA: alpha.unix.Chroot +// CHECK-STABLE-DEVELOPER-NOT: alpha.unix.Chroot + +// CHECK-STABLE-ALPHA: core.DivideZero +// CHECK-DEVELOPER-ALPHA-NOT: core.DivideZero +// CHECK-STABLE-DEVELOPER: core.DivideZero + +// CHECK-STABLE-ALPHA-NOT: debug.ConfigDumper +// CHECK-DEVELOPER-ALPHA: debug.ConfigDumper +// CHECK-STABLE-DEVELOPER: debug.ConfigDumper + + +// CHECK-STABLE-ALPHA-DEVELOPER: alpha.unix.Chroot +// CHECK-STABLE-ALPHA-DEVELOPER: core.DivideZero +// CHECK-STABLE-ALPHA-DEVELOPER: debug.ConfigDumper From e60cb7d1be4aac850c69486cf69f0c5fe250e3af Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 23 May 2019 21:49:47 +0000 Subject: [PATCH 0094/1176] [InstSimplify] insertelement V, undef, ? --> V This was part of InstCombine, but it's better placed in InstSimplify. InstCombine also had an unreachable but weaker fold for insertelement with undef index, so that is deleted. llvm-svn: 361559 --- llvm/lib/Analysis/InstructionSimplify.cpp | 5 ++++ .../InstCombine/InstCombineVectorOps.cpp | 4 --- .../Transforms/InstCombine/vec_insertelt.ll | 8 ----- .../Transforms/InstSimplify/insertelement.ll | 30 +++++++++++++++---- 4 files changed, 30 insertions(+), 17 deletions(-) delete mode 100644 llvm/test/Transforms/InstCombine/vec_insertelt.ll diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index b71841a1607dc..6e421dcaa737f 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4011,6 +4011,11 @@ Value *llvm::SimplifyInsertElementInst(Value *Vec, Value *Val, Value *Idx, if (isa(Idx)) return UndefValue::get(Vec->getType()); + // Inserting an undef scalar? Assume it is the same value as the existing + // vector element. + if (isa(Val)) + return Vec; + return nullptr; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index c2ea0733a48e4..44130d3246b67 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -863,10 +863,6 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { VecOp, ScalarOp, IdxOp, SQ.getWithInstruction(&IE))) return replaceInstUsesWith(IE, V); - // Inserting an undef or into an undefined place, remove this. - if (isa(ScalarOp) || isa(IdxOp)) - replaceInstUsesWith(IE, VecOp); - // If the vector and scalar are both bitcast from the same element type, do // the insert in that source type followed by bitcast. Value *VecSrc, *ScalarSrc; diff --git a/llvm/test/Transforms/InstCombine/vec_insertelt.ll b/llvm/test/Transforms/InstCombine/vec_insertelt.ll deleted file mode 100644 index 3b949209c4d76..0000000000000 --- a/llvm/test/Transforms/InstCombine/vec_insertelt.ll +++ /dev/null @@ -1,8 +0,0 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s -; CHECK: ret <4 x i32> %A - -; PR1286 -define <4 x i32> @test1(<4 x i32> %A) { - %B = insertelement <4 x i32> %A, i32 undef, i32 1 - ret <4 x i32> %B -} diff --git a/llvm/test/Transforms/InstSimplify/insertelement.ll b/llvm/test/Transforms/InstSimplify/insertelement.ll index 3524f2145acb0..c7db869d056d2 100644 --- a/llvm/test/Transforms/InstSimplify/insertelement.ll +++ b/llvm/test/Transforms/InstSimplify/insertelement.ll @@ -1,31 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -instsimplify < %s | FileCheck %s define <4 x i32> @test1(<4 x i32> %A) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: ret <4 x i32> undef +; %I = insertelement <4 x i32> %A, i32 5, i64 4294967296 - ; CHECK: ret <4 x i32> undef ret <4 x i32> %I } define <4 x i32> @test2(<4 x i32> %A) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: ret <4 x i32> undef +; %I = insertelement <4 x i32> %A, i32 5, i64 4 - ; CHECK: ret <4 x i32> undef ret <4 x i32> %I } define <4 x i32> @test3(<4 x i32> %A) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[I:%.*]] = insertelement <4 x i32> [[A:%.*]], i32 5, i64 1 +; CHECK-NEXT: ret <4 x i32> [[I]] +; %I = insertelement <4 x i32> %A, i32 5, i64 1 - ; CHECK: ret <4 x i32> %I ret <4 x i32> %I } define <4 x i32> @test4(<4 x i32> %A) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: ret <4 x i32> undef +; %I = insertelement <4 x i32> %A, i32 5, i128 100 - ; CHECK: ret <4 x i32> undef ret <4 x i32> %I } define <4 x i32> @test5(<4 x i32> %A) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: ret <4 x i32> undef +; %I = insertelement <4 x i32> %A, i32 5, i64 undef - ; CHECK: ret <4 x i32> undef ret <4 x i32> %I } + +define <4 x i32> @PR1286(<4 x i32> %A) { +; CHECK-LABEL: @PR1286( +; CHECK-NEXT: ret <4 x i32> [[A:%.*]] +; + %B = insertelement <4 x i32> %A, i32 undef, i32 1 + ret <4 x i32> %B +} From d82ddfa7c37d4814c91f1391d42eff87bc75c9dc Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Thu, 23 May 2019 21:52:59 +0000 Subject: [PATCH 0095/1176] [NewPassManager] Add tuning option: ForgetAllSCEVInLoopUnroll [NFC]. Summary: Mirror tuning option from old pass manager in new pass manager. Reviewers: chandlerc Subscribers: mehdi_amini, jlebar, zzheng, dmgreen, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61612 llvm-svn: 361560 --- llvm/include/llvm/Passes/PassBuilder.h | 4 ++++ .../llvm/Transforms/Scalar/LoopUnrollPass.h | 24 +++++++++++++++---- llvm/lib/Passes/PassBuilder.cpp | 7 ++++-- .../lib/Transforms/IPO/PassManagerBuilder.cpp | 7 +----- llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp | 10 ++++++-- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 383f49e0d7585..5e6660599f934 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -88,6 +88,10 @@ class PipelineTuningOptions { /// Tuning option to enable/disable loop unrolling. Its default value is true. bool LoopUnrolling; + /// Tuning option to forget all SCEV loops in LoopUnroll. Its default value + /// is that of the flag: `-forget-scev-loop-unroll`. + bool ForgetAllSCEVInLoopUnroll; + /// Tuning option to cap the number of calls to retrive clobbering accesses in /// MemorySSA, in LICM. unsigned LicmMssaOptCap; diff --git a/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h b/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h index 1445373eb4f2d..a84d889a83ad9 100644 --- a/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h @@ -15,6 +15,8 @@ namespace llvm { +extern cl::opt ForgetSCEVInLoopUnroll; + class Function; class Loop; class LPMUpdater; @@ -28,9 +30,16 @@ class LoopFullUnrollPass : public PassInfoMixin { /// metadata are considered. All other loops are skipped. const bool OnlyWhenForced; + /// If true, forget all loops when unrolling. If false, forget top-most loop + /// of the currently processed loops, which removes one entry at a time from + /// the internal SCEV records. For large loops, the former is faster. + const bool ForgetSCEV; + public: - explicit LoopFullUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false) - : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced) {} + explicit LoopFullUnrollPass(int OptLevel = 2, bool OnlyWhenForced = false, + bool ForgetSCEV = false) + : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), + ForgetSCEV(ForgetSCEV) {} PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U); @@ -60,8 +69,15 @@ struct LoopUnrollOptions { /// metadata are considered. All other loops are skipped. bool OnlyWhenForced; - LoopUnrollOptions(int OptLevel = 2, bool OnlyWhenForced = false) - : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced) {} + /// If true, forget all loops when unrolling. If false, forget top-most loop + /// of the currently processed loops, which removes one entry at a time from + /// the internal SCEV records. For large loops, the former is faster. + const bool ForgetSCEV; + + LoopUnrollOptions(int OptLevel = 2, bool OnlyWhenForced = false, + bool ForgetSCEV = false) + : OptLevel(OptLevel), OnlyWhenForced(OnlyWhenForced), + ForgetSCEV(ForgetSCEV) {} /// Enables or disables partial unrolling. When disabled only full unrolling /// is allowed. diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 1d17f91d5a8d3..3a0d0c29466ab 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -218,6 +218,7 @@ PipelineTuningOptions::PipelineTuningOptions() { LoopVectorization = EnableLoopVectorization; SLPVectorization = RunSLPVectorization; LoopUnrolling = true; + ForgetAllSCEVInLoopUnroll = ForgetSCEVInLoopUnroll; LicmMssaOptCap = SetLicmMssaOptCap; LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap; } @@ -463,7 +464,8 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, if ((Phase != ThinLTOPhase::PreLink || !PGOOpt || PGOOpt->Action != PGOOptions::SampleUse) && PTO.LoopUnrolling) - LPM2.addPass(LoopFullUnrollPass(Level)); + LPM2.addPass( + LoopFullUnrollPass(Level, false, PTO.ForgetAllSCEVInLoopUnroll)); for (auto &C : LoopOptimizerEndEPCallbacks) C(LPM2, Level); @@ -910,7 +912,8 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( createFunctionToLoopPassAdaptor(LoopUnrollAndJamPass(Level))); } if (PTO.LoopUnrolling) - OptimizePM.addPass(LoopUnrollPass(LoopUnrollOptions(Level))); + OptimizePM.addPass(LoopUnrollPass( + LoopUnrollOptions(Level, false, PTO.ForgetAllSCEVInLoopUnroll))); OptimizePM.addPass(WarnMissedTransformationsPass()); OptimizePM.addPass(InstCombinePass()); OptimizePM.addPass(RequireAnalysisPass()); diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 298cf47ed83b3..6ae7c859379a3 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -39,6 +39,7 @@ #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/InstSimplifyPass.h" #include "llvm/Transforms/Scalar/LICM.h" +#include "llvm/Transforms/Scalar/LoopUnrollPass.h" #include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" #include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Vectorize.h" @@ -145,12 +146,6 @@ cl::opt EnableOrderFileInstrumentation( "enable-order-file-instrumentation", cl::init(false), cl::Hidden, cl::desc("Enable order file instrumentation (default = off)")); -cl::opt ForgetSCEVInLoopUnroll( - "forget-scev-loop-unroll", cl::init(false), cl::Hidden, - cl::desc("Forget everything in SCEV when doing LoopUnroll, instead of just" - " the current top-most loop. This is somtimes preferred to reduce" - " compile time.")); - PassManagerBuilder::PassManagerBuilder() { OptLevel = 2; SizeLevel = 0; diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp index 7e9daf0b1fb6c..2fa7436213dd5 100644 --- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -71,6 +71,12 @@ using namespace llvm; #define DEBUG_TYPE "loop-unroll" +cl::opt llvm::ForgetSCEVInLoopUnroll( + "forget-scev-loop-unroll", cl::init(false), cl::Hidden, + cl::desc("Forget everything in SCEV when doing LoopUnroll, instead of just" + " the current top-most loop. This is somtimes preferred to reduce" + " compile time.")); + static cl::opt UnrollThreshold("unroll-threshold", cl::Hidden, cl::desc("The cost threshold for loop unrolling")); @@ -1281,7 +1287,7 @@ PreservedAnalyses LoopFullUnrollPass::run(Loop &L, LoopAnalysisManager &AM, tryToUnrollLoop(&L, AR.DT, &AR.LI, AR.SE, AR.TTI, AR.AC, *ORE, /*BFI*/ nullptr, /*PSI*/ nullptr, /*PreserveLCSSA*/ true, OptLevel, OnlyWhenForced, - /*ForgetAllSCEV*/ false, /*Count*/ None, + ForgetSCEV, /*Count*/ None, /*Threshold*/ None, /*AllowPartial*/ false, /*Runtime*/ false, /*UpperBound*/ false, /*AllowPeeling*/ false) != LoopUnrollResult::Unmodified; @@ -1422,7 +1428,7 @@ PreservedAnalyses LoopUnrollPass::run(Function &F, LoopUnrollResult Result = tryToUnrollLoop( &L, DT, &LI, SE, TTI, AC, ORE, BFI, PSI, /*PreserveLCSSA*/ true, UnrollOpts.OptLevel, UnrollOpts.OnlyWhenForced, - /*ForgetAllSCEV*/ false, /*Count*/ None, + UnrollOpts.ForgetSCEV, /*Count*/ None, /*Threshold*/ None, UnrollOpts.AllowPartial, UnrollOpts.AllowRuntime, UnrollOpts.AllowUpperBound, LocalAllowPeeling); Changed |= Result != LoopUnrollResult::Unmodified; From 7e55ed84d0598f6cbd282985855a6b810025fa93 Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 23 May 2019 22:07:16 +0000 Subject: [PATCH 0096/1176] [analyzer] Hide developer-only checker/package options by default These options are now only visible under -analyzer-checker-option-help-developer. Differential Revision: https://reviews.llvm.org/D61839 llvm-svn: 361561 --- clang/include/clang/Driver/CC1Options.td | 4 ++ .../StaticAnalyzer/Checkers/CheckerBase.td | 17 +++-- .../clang/StaticAnalyzer/Checkers/Checkers.td | 57 ++++++++++----- .../StaticAnalyzer/Core/AnalyzerOptions.h | 4 +- .../StaticAnalyzer/Frontend/CheckerRegistry.h | 10 +-- clang/lib/Frontend/CompilerInvocation.cpp | 2 + .../ExecuteCompilerInvocation.cpp | 2 +- .../Frontend/CheckerRegistry.cpp | 23 ++++--- .../Analysis/analyzer-checker-option-help.c | 6 ++ .../utils/TableGen/ClangSACheckersEmitter.cpp | 69 ++++++++++--------- 10 files changed, 123 insertions(+), 71 deletions(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 7605b3fc131ac..6ebd679ec3c21 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -151,6 +151,10 @@ def analyzer_config : Separate<["-"], "analyzer-config">, def analyzer_checker_option_help : Flag<["-"], "analyzer-checker-option-help">, HelpText<"Display the list of checker and package options">; +def analyzer_checker_option_help_developer : Flag<["-"], "analyzer-checker-option-help-developer">, + HelpText<"Display the list of checker and package options meant for " + "development purposes only">; + def analyzer_config_compatibility_mode : Separate<["-"], "analyzer-config-compatibility-mode">, HelpText<"Don't emit errors on invalid analyzer-config inputs">; diff --git a/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index 3c7c6fe9b2abc..9fb3184cfe2a0 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -25,13 +25,22 @@ class Type { bits<2> Type = val.Type; } +/// Marks the entry hidden. Hidden entries won't be displayed in +/// -analyzer-checker-option-help. +class HiddenEnum { + bit Val = val; +} +def DontHide : HiddenEnum<0>; +def Hide : HiddenEnum<1>; + /// Describes an option for a checker or a package. class CmdLineOption { + string defaultVal, HiddenEnum isHidden = DontHide> { bits<2> Type = type.Type; - string CmdFlag = cmdFlag; - string Desc = desc; - string DefaultVal = defaultVal; + string CmdFlag = cmdFlag; + string Desc = desc; + string DefaultVal = defaultVal; + bit Hidden = isHidden.Val; } /// Describes a list of package options. diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 911edd8066cbc..7669d22310048 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -519,7 +519,8 @@ def UninitializedObjectChecker: Checker<"UninitializedObject">, "for each uninitalized field, as opposed to emitting one " "warning per constructor call, and listing the uninitialized " "fields that belongs to it in notes.", - "false">, + "false", + Hide>, CmdLineOption, "OSObject instances. By default, the checker only checks " "retain-release rules for Objective-C NSObject instances " "and CoreFoundation objects.", - "true">, + "true", + Hide>, CmdLineOption, "(Aggressive) or NonLocalized only if it is not backed by a " "SymRegion (Non-Aggressive), basically leaving only string " "literals as NonLocalized.", - "false"> + "false", + Hide> ]>, Documentation; @@ -1110,67 +1113,83 @@ def AnalysisOrderChecker : Checker<"AnalysisOrder">, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption, + "false", + Hide>, CmdLineOption + "false", + Hide> ]>, Documentation; diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 1c45ffdff89af..c83696d70bfde 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -224,6 +224,7 @@ class AnalyzerOptions : public RefCountedBase { unsigned ShowCheckerHelpDeveloper : 1; unsigned ShowEnabledCheckerList : 1; unsigned ShowCheckerOptionList : 1; + unsigned ShowCheckerOptionDeveloperList : 1; unsigned ShowConfigOptionsList : 1; unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; @@ -287,7 +288,8 @@ class AnalyzerOptions : public RefCountedBase { AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), - ShowEnabledCheckerList(false), ShowCheckerOptionList(false), + ShowEnabledCheckerList(false), + ShowCheckerOptionList(false), ShowCheckerOptionDeveloperList(false), ShowConfigOptionsList(false), AnalyzeAll(false), AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h index 3a05c928774c0..9af8f91e70277 100644 --- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h @@ -98,11 +98,13 @@ class CheckerRegistry { StringRef OptionName; StringRef DefaultValStr; StringRef Description; + bool IsHidden; CmdLineOption(StringRef OptionType, StringRef OptionName, - StringRef DefaultValStr, StringRef Description) + StringRef DefaultValStr, StringRef Description, bool IsHidden) : OptionType(OptionType), OptionName(OptionName), - DefaultValStr(DefaultValStr), Description(Description) { + DefaultValStr(DefaultValStr), Description(Description), + IsHidden(IsHidden) { assert((OptionType == "bool" || OptionType == "string" || OptionType == "int") && @@ -239,7 +241,7 @@ class CheckerRegistry { /// non-compatibility mode. void addCheckerOption(StringRef OptionType, StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description); + StringRef Description, bool IsHidden = false); /// Adds a package to the registry. void addPackage(StringRef FullName); @@ -255,7 +257,7 @@ class CheckerRegistry { /// non-compatibility mode. void addPackageOption(StringRef OptionType, StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description); + StringRef Description, bool IsHidden = false); // FIXME: This *really* should be added to the frontend flag descriptions. /// Initializes a CheckerManager by calling the initialization functions for diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 34693af8f4fd3..36519c6d487a8 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -289,6 +289,8 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.ShowCheckerHelpDeveloper = Args.hasArg(OPT_analyzer_checker_help_developer); Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help); + Opts.ShowCheckerOptionDeveloperList = + Args.hasArg(OPT_analyzer_checker_option_help_developer); Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.ShouldEmitErrorsOnInvalidConfigValue = diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index ea720c83c2933..a5f51ab7ae293 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -249,7 +249,7 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { } // Honor -analyzer-checker-option-help. - if (Clang->getAnalyzerOpts()->ShowCheckerOptionList) { + if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionDeveloperList) { ento::printCheckerConfigList(llvm::outs(), Clang->getFrontendOpts().Plugins, *Clang->getAnalyzerOpts(), diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index 5f96389e597b4..f3a4765c9ee0f 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -180,12 +180,12 @@ CheckerRegistry::CheckerRegistry( addDependency(FULLNAME, DEPENDENCY); #define GET_CHECKER_OPTIONS -#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL) \ - addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC); +#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, IS_HIDDEN) \ + addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, IS_HIDDEN); #define GET_PACKAGE_OPTIONS -#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL) \ - addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC); +#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, IS_HIDDEN) \ + addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, IS_HIDDEN); #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_DEPENDENCY @@ -396,10 +396,10 @@ void CheckerRegistry::addPackageOption(StringRef OptionType, StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description) { + StringRef Description, bool IsHidden) { PackageOptions.emplace_back( - PackageFullName, - CmdLineOption{OptionType, OptionName, DefaultValStr, Description}); + PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr, + Description, IsHidden}); } void CheckerRegistry::addChecker(InitializationFunction Rfn, @@ -421,10 +421,10 @@ void CheckerRegistry::addCheckerOption(StringRef OptionType, StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description) { + StringRef Description, bool IsHidden) { CheckerOptions.emplace_back( - CheckerFullName, - CmdLineOption{OptionType, OptionName, DefaultValStr, Description}); + CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr, + Description, IsHidden}); } void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const { @@ -577,6 +577,9 @@ void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const { } for (const std::pair &Entry : OptionMap) { + if (!AnOpts.ShowCheckerOptionDeveloperList && Entry.second.IsHidden) + continue; + const CmdLineOption &Option = Entry.second; std::string FullOption = (Entry.first + ":" + Option.OptionName).str(); diff --git a/clang/test/Analysis/analyzer-checker-option-help.c b/clang/test/Analysis/analyzer-checker-option-help.c index f59d8515823cc..bc8ed09d43e17 100644 --- a/clang/test/Analysis/analyzer-checker-option-help.c +++ b/clang/test/Analysis/analyzer-checker-option-help.c @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -analyzer-checker-option-help 2>&1 | FileCheck %s +// RUN: %clang_cc1 -analyzer-checker-option-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-HIDDEN + // CHECK: OVERVIEW: Clang Static Analyzer Checker and Package Option List // // CHECK: USAGE: -analyzer-config @@ -17,3 +20,6 @@ // CHECK: the first statement in the group is representative // CHECK: for all other statements in the group in // CHECK: terms of complexity. (default: 50) + +// CHECK-NOT: optin.cplusplus.UninitializedObject:NotesAsWarnings +// CHECK-HIDDEN: optin.cplusplus.UninitializedObject:NotesAsWarnings diff --git a/clang/utils/TableGen/ClangSACheckersEmitter.cpp b/clang/utils/TableGen/ClangSACheckersEmitter.cpp index 428a5c81276b8..7c1827ec2e48a 100644 --- a/clang/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/clang/utils/TableGen/ClangSACheckersEmitter.cpp @@ -113,6 +113,7 @@ static std::string getCheckerOptionType(const Record &R) { static bool isHidden(const Record *R) { if (R->getValueAsBit("Hidden")) return true; + // Not declared as hidden, check the parent package if it is hidden. if (DefInit *DI = dyn_cast(R->getValueInit("ParentPackage"))) return isHidden(DI->getDef()); @@ -121,21 +122,38 @@ static bool isHidden(const Record *R) { } static void printChecker(llvm::raw_ostream &OS, const Record &R) { - OS << "CHECKER(" << "\""; - OS.write_escaped(getCheckerFullName(&R)) << "\", "; - OS << R.getName() << ", "; - OS << "\""; - OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; - OS << "\""; - OS.write_escaped(getCheckerDocs(R)); - OS << "\", "; - - if (!isHidden(&R)) - OS << "false"; - else - OS << "true"; + OS << "CHECKER(" << "\""; + OS.write_escaped(getCheckerFullName(&R)) << "\", "; + OS << R.getName() << ", "; + OS << "\""; + OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; + OS << "\""; + OS.write_escaped(getCheckerDocs(R)); + OS << "\", "; + + if (!isHidden(&R)) + OS << "false"; + else + OS << "true"; + + OS << ")\n"; +} + +static void printOption(llvm::raw_ostream &OS, StringRef FullName, + const Record &R) { + OS << "\""; + OS.write_escaped(getCheckerOptionType(R)) << "\", \""; + OS.write_escaped(FullName) << "\", "; + OS << '\"' << getStringValue(R, "CmdFlag") << "\", "; + OS << '\"'; + OS.write_escaped(getStringValue(R, "Desc")) << "\", "; + OS << '\"'; + OS.write_escaped(getStringValue(R, "DefaultVal")) << "\", "; - OS << ")\n"; + if (!R.getValueAsBit("Hidden")) + OS << "false"; + else + OS << "true"; } namespace clang { @@ -196,14 +214,8 @@ void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) { std::vector PackageOptions = Package ->getValueAsListOfDefs("PackageOptions"); for (Record *PackageOpt : PackageOptions) { - OS << "PACKAGE_OPTION(\""; - OS.write_escaped(getCheckerOptionType(*PackageOpt)) << "\", \""; - OS.write_escaped(getPackageFullName(Package)) << "\", "; - OS << '\"' << getStringValue(*PackageOpt, "CmdFlag") << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*PackageOpt, "Desc")) << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*PackageOpt, "DefaultVal")) << "\""; + OS << "PACKAGE_OPTION("; + printOption(OS, getPackageFullName(Package), *PackageOpt); OS << ")\n"; } } @@ -277,16 +289,9 @@ void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) { std::vector CheckerOptions = Checker ->getValueAsListOfDefs("CheckerOptions"); for (Record *CheckerOpt : CheckerOptions) { - OS << "CHECKER_OPTION(\""; - OS << getCheckerOptionType(*CheckerOpt) << "\", \""; - OS.write_escaped(getCheckerFullName(Checker)) << "\", "; - OS << '\"' << getStringValue(*CheckerOpt, "CmdFlag") << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*CheckerOpt, "Desc")) << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*CheckerOpt, "DefaultVal")) << "\""; - OS << ")"; - OS << '\n'; + OS << "CHECKER_OPTION("; + printOption(OS, getCheckerFullName(Checker), *CheckerOpt); + OS << ")\n"; } } OS << "#endif // GET_CHECKER_OPTIONS\n" From f2e41dd6ed1ac052e89dac224e67218c479cf952 Mon Sep 17 00:00:00 2001 From: Alina Sbirlea Date: Thu, 23 May 2019 22:07:37 +0000 Subject: [PATCH 0097/1176] Use clang_cc1 instead of clang in CodeGen test. llvm-svn: 361562 --- clang/test/CodeGen/loop-vectorize.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/test/CodeGen/loop-vectorize.c b/clang/test/CodeGen/loop-vectorize.c index 8c81fbebecb8c..f1c5c0cee77c6 100644 --- a/clang/test/CodeGen/loop-vectorize.c +++ b/clang/test/CodeGen/loop-vectorize.c @@ -1,7 +1,7 @@ -// RUN: %clang -target x86_64 -S -c -O1 -fvectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-ENABLE-VECT -// RUN: %clang -target x86_64 -S -c -O1 -fno-vectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DISABLE-VECT -// RUN: %clang -target x86_64 -fexperimental-new-pass-manager -S -c -O1 -fvectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-ENABLE-VECT -// RUN: %clang -target x86_64 -fexperimental-new-pass-manager -S -c -O1 -fno-vectorize -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DISABLE-VECT +// RUN: %clang_cc1 -triple x86_64 -target-cpu x86-64 -S -O1 -vectorize-loops -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-ENABLE-VECT +// RUN: %clang_cc1 -triple x86_64 -target-cpu x86-64 -S -O1 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DISABLE-VECT +// RUN: %clang_cc1 -triple x86_64 -target-cpu x86-64 -fexperimental-new-pass-manager -S -O1 -vectorize-loops -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-ENABLE-VECT +// RUN: %clang_cc1 -triple x86_64 -target-cpu x86-64 -fexperimental-new-pass-manager -S -O1 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DISABLE-VECT // CHECK-ENABLE-VECT-LABEL: @for_test() // CHECK-ENABLE-VECT: fmul <{{[0-9]+}} x double> From 5554a5fcbdd7a889e133a80c064e4e553fa4fae4 Mon Sep 17 00:00:00 2001 From: Bob Haarman Date: Thu, 23 May 2019 22:28:18 +0000 Subject: [PATCH 0098/1176] fix accidental implicit matches in elf-disassemble-symbol-labels-rel.test llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test uses --implicit-check-not to verify that certain patterns do not occur in llvm-objdump's output, except in places where they are explicitly checked. Unfortunately, the patterns are generic enough that they may be part of the file name which is also output by llvm-objdump. This change matches the line with the filename explicitly so that the implicit patterns are not applied to it. llvm-svn: 361563 --- .../llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test index d2377f44621f4..189803cbc0968 100644 --- a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test +++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-symbol-labels-rel.test @@ -9,6 +9,7 @@ # RUN: --implicit-check-not=absolute \ # RUN: --implicit-check-not=other +# CHECK: {{.*}}: file format {{.*}} # CHECK: Disassembly of section .text: # CHECK: 0000000000000000 first: # CHECK: 0000000000000001 second: From e0ef04f8cb295a95c49e8436f59d5a4b58e92d15 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 23 May 2019 22:30:43 +0000 Subject: [PATCH 0099/1176] [OPENMP]Do not crash for const firstprivates. If the variable is a firstprivate variable and it was not emitted beause this a constant variable with the constant initializer, we can use the initial value instead of the variable itself. It also fixes the problem with the compiler crash in this case. llvm-svn: 361564 --- clang/lib/CodeGen/CGStmtOpenMP.cpp | 20 ++++++++++++++++++- .../OpenMP/parallel_firstprivate_codegen.cpp | 7 +++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 01194e3a60fa1..6a973cdb57e3a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -758,7 +758,25 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D, DeclRefExpr DRE(getContext(), const_cast(OrigVD), /*RefersToEnclosingVariableOrCapture=*/FD != nullptr, (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc()); - LValue OriginalLVal = EmitLValue(&DRE); + LValue OriginalLVal; + if (!FD) { + // Check if the firstprivate variable is just a constant value. + ConstantEmission CE = tryEmitAsConstant(&DRE); + if (CE && !CE.isReference()) { + // Constant value, no need to create a copy. + ++IRef; + ++InitsRef; + continue; + } + if (CE && CE.isReference()) { + OriginalLVal = CE.getReferenceLValue(*this, &DRE); + } else { + assert(!CE && "Expected non-constant firstprivate."); + OriginalLVal = EmitLValue(&DRE); + } + } else { + OriginalLVal = EmitLValue(&DRE); + } QualType Type = VD->getType(); if (Type->isArrayType()) { // Emit VarDecl with copy init for arrays. diff --git a/clang/test/OpenMP/parallel_firstprivate_codegen.cpp b/clang/test/OpenMP/parallel_firstprivate_codegen.cpp index 8aa64668f0525..2a306d1272f82 100644 --- a/clang/test/OpenMP/parallel_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/parallel_firstprivate_codegen.cpp @@ -335,8 +335,9 @@ int main() { s_arr[0] = var; sivar = 2; } -#pragma omp parallel allocate(omp_default_mem_alloc: t_var) firstprivate(t_var) - {} + const int a = 0; +#pragma omp parallel allocate(omp_default_mem_alloc: t_var) firstprivate(t_var, a) + { t_var = a; } return tmain(); #endif } @@ -346,6 +347,7 @@ int main() { // CHECK: [[T_VAR:%.+]] = alloca i32, // CHECK: [[T_VARCAST:%.+]] = alloca [[iz:i64|i32]], // CHECK: [[SIVARCAST:%.+]] = alloca [[iz]], +// CHECK: [[A:%.+]] = alloca i32, // CHECK: [[T_VARCAST1:%.+]] = alloca [[iz:i64|i32]], // CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]]) // CHECK: [[T_VARVAL:%.+]] = load i32, i32* [[T_VAR]], @@ -420,6 +422,7 @@ int main() { // CHECK-32: [[T_VAR_VAL:%.+]] = load i32, i32* [[T_VAR_ADDR]], // CHECK-64: [[T_VAR_VAL:%.+]] = load i32, i32* [[BC]], // CHECK: store i32 [[T_VAR_VAL]], i32* [[T_VAR_PRIV]], +// CHECK: store i32 0, i32* [[T_VAR_PRIV]], // CHECK: call void @__kmpc_free(i32 [[GTID]], i8* [[T_VAR_VOID_PTR]], i8* inttoptr ([[iz]] 1 to i8*)) // CHECK: ret void From 342571e8d6eb1afb151ae1103431798e3d24054f Mon Sep 17 00:00:00 2001 From: Konrad Kleine Date: Thu, 23 May 2019 22:39:13 +0000 Subject: [PATCH 0100/1176] [lldb] followup fix for https://reviews.llvm.org/D62305 Summary: Fixing this error on windows build bot: ``` E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(21): error C2440: 'initializing': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(21): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(21): error C2439: 'lldb_private::HostNativeThreadBase::m_result': member could not be initialized E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\include\lldb/Host/HostNativeThreadBase.h(48): note: see declaration of 'lldb_private::HostNativeThreadBase::m_result' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(24): error C2440: 'initializing': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(24): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(24): error C2439: 'lldb_private::HostNativeThreadBase::m_result': member could not be initialized E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\include\lldb/Host/HostNativeThreadBase.h(48): note: see declaration of 'lldb_private::HostNativeThreadBase::m_result' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(40): error C2440: '=': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(40): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(50): error C2440: '=': cannot convert from 'nullptr' to 'lldb::thread_result_t' E:\build_slave\lldb-x64-windows-ninja\llvm\tools\lldb\source\Host\common\HostNativeThreadBase.cpp(50): note: A native nullptr can only be converted to bool or, using reinterpret_cast, to an integral type ``` see http://lab.llvm.org:8011/builders/lldb-x64-windows-ninja/builds/5050/steps/build/logs/stdio Reviewers: stella.stamenova, JDevlieghere Reviewed By: JDevlieghere Subscribers: lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D62337 llvm-svn: 361565 --- lldb/source/Host/common/HostNativeThreadBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp index a5f876a7232af..091e7b515a602 100644 --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -18,10 +18,10 @@ using namespace lldb; using namespace lldb_private; HostNativeThreadBase::HostNativeThreadBase() - : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {} + : m_thread(LLDB_INVALID_HOST_THREAD), m_result({}) {} HostNativeThreadBase::HostNativeThreadBase(thread_t thread) - : m_thread(thread), m_result(0) {} + : m_thread(thread), m_result({}) {} lldb::thread_t HostNativeThreadBase::GetSystemHandle() const { return m_thread; @@ -37,7 +37,7 @@ bool HostNativeThreadBase::IsJoinable() const { void HostNativeThreadBase::Reset() { m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; + m_result = {}; } bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { @@ -47,7 +47,7 @@ bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { lldb::thread_t HostNativeThreadBase::Release() { lldb::thread_t result = m_thread; m_thread = LLDB_INVALID_HOST_THREAD; - m_result = 0; + m_result = {}; return result; } From ac95c86511342b5d42c2915f681fe1c15ab8aac9 Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Thu, 23 May 2019 22:52:09 +0000 Subject: [PATCH 0101/1176] [analyzer] List checker/plugin options in 3 categories: released, alpha, developer Same patch as D62093, but for checker/plugin options, the only difference being that options for alpha checkers are implicitly marked as alpha. Differential Revision: https://reviews.llvm.org/D62093 llvm-svn: 361566 --- clang/include/clang/Driver/CC1Options.td | 5 + .../StaticAnalyzer/Checkers/CheckerBase.td | 19 +++- .../clang/StaticAnalyzer/Checkers/Checkers.td | 67 ++++++++++--- .../StaticAnalyzer/Core/AnalyzerOptions.h | 9 +- .../StaticAnalyzer/Frontend/CheckerRegistry.h | 16 ++- clang/lib/Frontend/CompilerInvocation.cpp | 4 + .../ExecuteCompilerInvocation.cpp | 3 +- .../Frontend/CheckerRegistry.cpp | 55 ++++++++--- .../Analysis/analyzer-checker-option-help.c | 98 +++++++++++++++---- .../CheckerOptionHandling.cpp | 3 +- .../utils/TableGen/ClangSACheckersEmitter.cpp | 18 ++++ 11 files changed, 235 insertions(+), 62 deletions(-) diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 6ebd679ec3c21..d2d471089e5e4 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -151,6 +151,11 @@ def analyzer_config : Separate<["-"], "analyzer-config">, def analyzer_checker_option_help : Flag<["-"], "analyzer-checker-option-help">, HelpText<"Display the list of checker and package options">; +def analyzer_checker_option_help_alpha : Flag<["-"], "analyzer-checker-option-help-alpha">, + HelpText<"Display the list of in development checker and package options. " + "These are NOT considered safe, they are unstable and will emit " + "incorrect reports. Enable ONLY FOR DEVELOPMENT purposes">; + def analyzer_checker_option_help_developer : Flag<["-"], "analyzer-checker-option-help-developer">, HelpText<"Display the list of checker and package options meant for " "development purposes only">; diff --git a/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index 9fb3184cfe2a0..6625d79559f56 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -21,10 +21,21 @@ def Integer : CmdLineOptionTypeEnum<0>; def String : CmdLineOptionTypeEnum<1>; def Boolean : CmdLineOptionTypeEnum<2>; -class Type { - bits<2> Type = val.Type; +/// Describes the state of the entry. We wouldn't like to display, for example, +/// developer only entries for a list meant for end users. +class DevelopmentStageEnum val> { + bits<1> Val = val; } +/// Alpha entries are under development, might be incomplet, inkorrekt and +/// unstable. +def InAlpha : DevelopmentStageEnum<0>; + +/// Released entries are stable, produce minimal, if any false positives, +/// and emits reports that explain the occurance of the bug understandably and +/// thoroughly. +def Released : DevelopmentStageEnum<1>; + /// Marks the entry hidden. Hidden entries won't be displayed in /// -analyzer-checker-option-help. class HiddenEnum { @@ -35,11 +46,13 @@ def Hide : HiddenEnum<1>; /// Describes an option for a checker or a package. class CmdLineOption { + string defaultVal, DevelopmentStageEnum stage, + HiddenEnum isHidden = DontHide> { bits<2> Type = type.Type; string CmdFlag = cmdFlag; string Desc = desc; string DefaultVal = defaultVal; + bits<1> DevelopmentStage = stage.Val; bit Hidden = isHidden.Val; } diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 7669d22310048..35beb51f0c47e 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -51,7 +51,8 @@ def Nullability : Package<"nullability">, "concerned with your custom nullability annotations more " "than with following nullability specifications of system " "header functions.", - "false"> + "false", + Released> ]>; def Cplusplus : Package<"cplusplus">; @@ -391,7 +392,8 @@ def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">, "If set to true, the checker assumes that all the " "allocating and deallocating functions are annotated with " "ownership_holds, ownership_takes and ownership_returns.", - "false"> + "false", + InAlpha> ]>, Dependencies<[CStringModeling]>, Documentation, @@ -496,7 +498,8 @@ def MoveChecker: Checker<"Move">, "user has intentionally asked us to completely eliminate " "use-after-move in his code. Values: \"KnownsOnly\", " "\"KnownsAndLocals\", \"All\".", - "KnownsAndLocals"> + "KnownsAndLocals", + Released> ]>, Documentation; @@ -512,7 +515,8 @@ def UninitializedObjectChecker: Checker<"UninitializedObject">, "If set to false, the checker won't emit warnings " "for objects that don't have at least one initialized " "field.", - "false">, + "false", + Released>, CmdLineOption, "warning per constructor call, and listing the uninitialized " "fields that belongs to it in notes.", "false", + Released, Hide>, CmdLineOption, + "false", + InAlpha>, CmdLineOption, + "\"\"", + Released>, CmdLineOption + "false", + InAlpha> ]>, Documentation; @@ -548,7 +556,8 @@ def VirtualCallChecker : Checker<"VirtualCall">, CmdLineOption + "false", + Released> ]>, Documentation; @@ -651,7 +660,8 @@ def PaddingChecker : Checker<"Padding">, "AllowedPad", "Reports are only generated if the excessive padding exceeds " "'AllowedPad' in bytes.", - "24"> + "24", + Released> ]>, Documentation; @@ -768,11 +778,13 @@ def MmapWriteExecChecker : Checker<"MmapWriteExec">, CmdLineOption, + "0x04", + Released>, CmdLineOption + "0x01", + Released> ]>, Documentation; @@ -819,7 +831,8 @@ def NumberObjectConversionChecker : Checker<"NumberObjectConversion">, "Enables detection of more conversion patterns (which are " "most likely more harmless, and therefore are more likely to " "produce false positives).", - "false"> + "false", + Released> ]>, Documentation; @@ -920,6 +933,7 @@ def RetainCountChecker : Checker<"RetainCount">, "retain-release rules for Objective-C NSObject instances " "and CoreFoundation objects.", "true", + InAlpha, Hide>, CmdLineOption, "elsewhere, but also that it fulfills its own retain count " "specification with respect to objects that it receives as " "arguments.", - "false"> + "false", + Released> ]>, Dependencies<[RetainCountBase]>, Documentation; @@ -1049,6 +1064,7 @@ def NonLocalizedStringChecker : Checker<"NonLocalizedStringChecker">, "SymRegion (Non-Aggressive), basically leaving only string " "literals as NonLocalized.", "false", + InAlpha, Hide> ]>, Documentation; @@ -1114,81 +1130,97 @@ def AnalysisOrderChecker : Checker<"AnalysisOrder">, "PreStmtCastExpr", "", "false", + Released, Hide>, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption, CmdLineOption ]>, Documentation; @@ -1272,16 +1304,19 @@ def CloneChecker : Checker<"CloneChecker">, "of a statement. This constraint assumes the first statement " "in the group is representative for all other statements in " "the group in terms of complexity.", - "50">, + "50", + Released>, CmdLineOption, + "true", + Released>, CmdLineOption + "\"\"", + Released> ]>, Documentation; diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index c83696d70bfde..4d81f90961cb9 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -222,9 +222,12 @@ class AnalyzerOptions : public RefCountedBase { unsigned ShowCheckerHelp : 1; unsigned ShowCheckerHelpAlpha : 1; unsigned ShowCheckerHelpDeveloper : 1; - unsigned ShowEnabledCheckerList : 1; + unsigned ShowCheckerOptionList : 1; + unsigned ShowCheckerOptionAlphaList : 1; unsigned ShowCheckerOptionDeveloperList : 1; + + unsigned ShowEnabledCheckerList : 1; unsigned ShowConfigOptionsList : 1; unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; @@ -288,8 +291,8 @@ class AnalyzerOptions : public RefCountedBase { AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), - ShowEnabledCheckerList(false), - ShowCheckerOptionList(false), ShowCheckerOptionDeveloperList(false), + ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false), + ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), ShowConfigOptionsList(false), AnalyzeAll(false), AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h index 9af8f91e70277..bc258160ada49 100644 --- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h @@ -98,13 +98,15 @@ class CheckerRegistry { StringRef OptionName; StringRef DefaultValStr; StringRef Description; + StringRef DevelopmentStatus; bool IsHidden; CmdLineOption(StringRef OptionType, StringRef OptionName, - StringRef DefaultValStr, StringRef Description, bool IsHidden) + StringRef DefaultValStr, StringRef Description, + StringRef DevelopmentStatus, bool IsHidden) : OptionType(OptionType), OptionName(OptionName), DefaultValStr(DefaultValStr), Description(Description), - IsHidden(IsHidden) { + DevelopmentStatus(DevelopmentStatus), IsHidden(IsHidden) { assert((OptionType == "bool" || OptionType == "string" || OptionType == "int") && @@ -120,6 +122,10 @@ class CheckerRegistry { "Invalid value for integer command line option! Maybe incorrect " "parameters to the addCheckerOption or addPackageOption method?"); (void)Tmp; + + assert((DevelopmentStatus == "alpha" || DevelopmentStatus == "beta" || + DevelopmentStatus == "released") && + "Invalid development status!"); } }; @@ -241,7 +247,8 @@ class CheckerRegistry { /// non-compatibility mode. void addCheckerOption(StringRef OptionType, StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description, bool IsHidden = false); + StringRef Description, StringRef DevelopmentStatus, + bool IsHidden = false); /// Adds a package to the registry. void addPackage(StringRef FullName); @@ -257,7 +264,8 @@ class CheckerRegistry { /// non-compatibility mode. void addPackageOption(StringRef OptionType, StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description, bool IsHidden = false); + StringRef Description, StringRef DevelopmentStatus, + bool IsHidden = false); // FIXME: This *really* should be added to the frontend flag descriptions. /// Initializes a CheckerManager by calling the initialization functions for diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 36519c6d487a8..96580804576d3 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -288,9 +288,13 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.ShowCheckerHelpAlpha = Args.hasArg(OPT_analyzer_checker_help_alpha); Opts.ShowCheckerHelpDeveloper = Args.hasArg(OPT_analyzer_checker_help_developer); + Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help); + Opts.ShowCheckerOptionAlphaList = + Args.hasArg(OPT_analyzer_checker_option_help_alpha); Opts.ShowCheckerOptionDeveloperList = Args.hasArg(OPT_analyzer_checker_option_help_developer); + Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.ShouldEmitErrorsOnInvalidConfigValue = diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index a5f51ab7ae293..da7aa7b82a39c 100644 --- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -249,7 +249,8 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) { } // Honor -analyzer-checker-option-help. - if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionDeveloperList) { + if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList || + AnOpts.ShowCheckerOptionDeveloperList) { ento::printCheckerConfigList(llvm::outs(), Clang->getFrontendOpts().Plugins, *Clang->getAnalyzerOpts(), diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index f3a4765c9ee0f..3fd4c36947cbb 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -180,12 +180,12 @@ CheckerRegistry::CheckerRegistry( addDependency(FULLNAME, DEPENDENCY); #define GET_CHECKER_OPTIONS -#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, IS_HIDDEN) \ - addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, IS_HIDDEN); +#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, DEVELOPMENT_STATUS, IS_HIDDEN) \ + addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, DEVELOPMENT_STATUS, IS_HIDDEN); #define GET_PACKAGE_OPTIONS -#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, IS_HIDDEN) \ - addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, IS_HIDDEN); +#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, DEVELOPMENT_STATUS, IS_HIDDEN) \ + addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, DEVELOPMENT_STATUS, IS_HIDDEN); #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_DEPENDENCY @@ -396,10 +396,12 @@ void CheckerRegistry::addPackageOption(StringRef OptionType, StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description, bool IsHidden) { + StringRef Description, + StringRef DevelopmentStatus, + bool IsHidden) { PackageOptions.emplace_back( PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr, - Description, IsHidden}); + Description, DevelopmentStatus, IsHidden}); } void CheckerRegistry::addChecker(InitializationFunction Rfn, @@ -421,10 +423,12 @@ void CheckerRegistry::addCheckerOption(StringRef OptionType, StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description, bool IsHidden) { + StringRef Description, + StringRef DevelopmentStatus, + bool IsHidden) { CheckerOptions.emplace_back( CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr, - Description, IsHidden}); + Description, DevelopmentStatus, IsHidden}); } void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const { @@ -576,10 +580,14 @@ void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const { } } + auto Print = [] (llvm::raw_ostream &Out, StringRef FullOption, StringRef Desc) { + AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc}, + /*InitialPad*/ 2, + /*EntryWidth*/ 50, + /*MinLineWidth*/ 90); + Out << "\n\n"; + }; for (const std::pair &Entry : OptionMap) { - if (!AnOpts.ShowCheckerOptionDeveloperList && Entry.second.IsHidden) - continue; - const CmdLineOption &Option = Entry.second; std::string FullOption = (Entry.first + ":" + Option.OptionName).str(); @@ -588,10 +596,25 @@ void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const { (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")") .str(); - AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc}, - /*InitialPad*/ 2, - /*EntryWidth*/ 50, - /*MinLineWidth*/ 90); - Out << "\n\n"; + // The list of these if branches is significant, we wouldn't like to + // display hidden alpha checker options for + // -analyzer-checker-option-help-alpha. + + if (Option.IsHidden) { + if (AnOpts.ShowCheckerOptionDeveloperList) + Print(Out, FullOption, Desc); + continue; + } + + if (Option.DevelopmentStatus == "alpha" || + Entry.first.startswith("alpha")) { + if (AnOpts.ShowCheckerOptionAlphaList) + Print(Out, FullOption, + llvm::Twine("(Enable only for development!) " + Desc).str()); + continue; + } + + if (AnOpts.ShowCheckerOptionList) + Print(Out, FullOption, Desc); } } diff --git a/clang/test/Analysis/analyzer-checker-option-help.c b/clang/test/Analysis/analyzer-checker-option-help.c index bc8ed09d43e17..5f95569e58498 100644 --- a/clang/test/Analysis/analyzer-checker-option-help.c +++ b/clang/test/Analysis/analyzer-checker-option-help.c @@ -1,25 +1,87 @@ -// RUN: %clang_cc1 -analyzer-checker-option-help 2>&1 | FileCheck %s +// RUN: %clang_cc1 -analyzer-checker-option-help \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE + +// RUN: %clang_cc1 -analyzer-checker-option-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-ALPHA + +// RUN: %clang_cc1 -analyzer-checker-option-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DEVELOPER // RUN: %clang_cc1 -analyzer-checker-option-help-developer \ -// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-HIDDEN +// RUN: -analyzer-checker-option-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DEVELOPER-ALPHA + +// RUN: %clang_cc1 -analyzer-checker-option-help \ +// RUN: -analyzer-checker-option-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-ALPHA -// CHECK: OVERVIEW: Clang Static Analyzer Checker and Package Option List +// RUN: %clang_cc1 -analyzer-checker-option-help \ +// RUN: -analyzer-checker-option-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-DEVELOPER + +// RUN: %clang_cc1 -analyzer-checker-option-help \ +// RUN: -analyzer-checker-option-help-alpha \ +// RUN: -analyzer-checker-option-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-ALPHA-DEVELOPER + +// CHECK-STABLE: OVERVIEW: Clang Static Analyzer Checker and Package Option List // -// CHECK: USAGE: -analyzer-config +// CHECK-STABLE: USAGE: -analyzer-config // -// CHECK: -analyzer-config OPTION1=VALUE, -analyzer-config -// CHECK-SAME: OPTION2=VALUE, ... +// CHECK-STABLE: -analyzer-config OPTION1=VALUE, -analyzer-config +// CHECK-STABLE-SAME: OPTION2=VALUE, ... // -// CHECK: OPTIONS: +// CHECK-STABLE: OPTIONS: // -// CHECK: alpha.clone.CloneChecker:MinimumCloneComplexity -// CHECK-SAME: (int) Ensures that every clone has at least -// CHECK: the given complexity. Complexity is here -// CHECK: defined as the total amount of children -// CHECK: of a statement. This constraint assumes -// CHECK: the first statement in the group is representative -// CHECK: for all other statements in the group in -// CHECK: terms of complexity. (default: 50) - -// CHECK-NOT: optin.cplusplus.UninitializedObject:NotesAsWarnings -// CHECK-HIDDEN: optin.cplusplus.UninitializedObject:NotesAsWarnings +// CHECK-STABLE: cplusplus.Move:WarnOn +// CHECK-STABLE-SAME: (string) In non-aggressive mode, only warn +// CHECK-STABLLE: on use-after-move of local variables (or +// CHECK-STABLLE: local rvalue references) and of STL objects. +// CHECK-STABLLE: The former is possible because local variables +// CHECK-STABLLE: (or local rvalue references) are not tempting +// CHECK-STABLLE: their user to re-use the storage. The latter +// CHECK-STABLLE: is possible because STL objects are known +// CHECK-STABLLE: to end up in a valid but unspecified state +// CHECK-STABLLE: after the move and their state-reset methods +// CHECK-STABLLE: are also known, which allows us to predict +// CHECK-STABLLE: precisely when use-after-move is invalid. +// CHECK-STABLLE: Some STL objects are known to conform to +// CHECK-STABLLE: additional contracts after move, so they +// CHECK-STABLLE: are not tracked. However, smart pointers +// CHECK-STABLLE: specifically are tracked because we can +// CHECK-STABLLE: perform extra checking over them. In aggressive +// CHECK-STABLLE: mode, warn on any use-after-move because +// CHECK-STABLLE: the user has intentionally asked us to completely +// CHECK-STABLLE: eliminate use-after-move in his code. Values: +// CHECK-STABLLE: "KnownsOnly", "KnownsAndLocals", "All". +// CHECK-STABLLE: (default: KnownsAndLocals) + +// CHECK-STABLE-NOT: debug.AnalysisOrder:* +// CHECK-DEVELOPER: debug.AnalysisOrder:* +// CHECK-ALPHA-NOT: debug.AnalysisOrder:* + +// CHECK-STABLE-NOT: optin.cplusplus.UninitializedObject:IgnoreGuardedFields +// CHECK-DEVELOPER-NOT: optin.cplusplus.UninitializedObject:IgnoreGuardedFields +// CHECK-ALPHA: optin.cplusplus.UninitializedObject:IgnoreGuardedFields + +// CHECK-STABLE: optin.performance.Padding:AllowedPad +// CHECK-DEVELOPER-NOT: optin.performance.Padding:AllowedPad +// CHECK-ALPHA-NOT: optin.performance.Padding:AllowedPad + + +// CHECK-STABLE-ALPHA-NOT: debug.AnalysisOrder:* +// CHECK-DEVELOPER-ALPHA: debug.AnalysisOrder:* +// CHECK-STABLE-DEVELOPER: debug.AnalysisOrder:* + +// CHECK-STABLE-ALPHA: optin.cplusplus.UninitializedObject:IgnoreGuardedFields +// CHECK-DEVELOPER-ALPHA: optin.cplusplus.UninitializedObject:IgnoreGuardedFields +// CHECK-STABLE-DEVELOPER-NOT: optin.cplusplus.UninitializedObject:IgnoreGuardedFields + +// CHECK-STABLE-ALPHA: optin.performance.Padding:AllowedPad +// CHECK-DEVELOPER-ALPHA-NOT: optin.performance.Padding:AllowedPad +// CHECK-STABLE-DEVELOPER: optin.performance.Padding:AllowedPad + + +// CHECK-STABLE-ALPHA-DEVELOPER: debug.AnalysisOrder:* +// CHECK-STABLE-ALPHA-DEVELOPER: optin.cplusplus.UninitializedObject:IgnoreGuardedFields +// CHECK-STABLE-ALPHA-DEVELOPER: optin.performance.Padding:AllowedPad diff --git a/clang/test/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp b/clang/test/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp index c06a19df7dfe0..77de3630ae7ec 100644 --- a/clang/test/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp +++ b/clang/test/Analysis/plugins/CheckerOptionHandling/CheckerOptionHandling.cpp @@ -36,7 +36,8 @@ extern "C" void clang_registerCheckers(CheckerRegistry ®istry) { /*CheckerFullName*/ "example.MyChecker", /*OptionName*/ "ExampleOption", /*DefaultValStr*/ "false", - /*Description*/ "This is an example checker opt."); + /*Description*/ "This is an example checker opt.", + /*DevelopmentStage*/ "released"); } extern "C" const char clang_analyzerAPIVersionString[] = diff --git a/clang/utils/TableGen/ClangSACheckersEmitter.cpp b/clang/utils/TableGen/ClangSACheckersEmitter.cpp index 7c1827ec2e48a..7dd0895b76d45 100644 --- a/clang/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/clang/utils/TableGen/ClangSACheckersEmitter.cpp @@ -110,6 +110,22 @@ static std::string getCheckerOptionType(const Record &R) { return ""; } +static std::string getDevelopmentStage(const Record &R) { + if (BitsInit *BI = R.getValueAsBitsInit("DevelopmentStage")) { + switch(getValueFromBitsInit(BI, R)) { + case 0: + return "alpha"; + case 1: + return "released"; + } + } + + PrintFatalError(R.getLoc(), + "unable to parse command line option type for " + + getCheckerFullName(&R)); + return ""; +} + static bool isHidden(const Record *R) { if (R->getValueAsBit("Hidden")) return true; @@ -149,6 +165,8 @@ static void printOption(llvm::raw_ostream &OS, StringRef FullName, OS.write_escaped(getStringValue(R, "Desc")) << "\", "; OS << '\"'; OS.write_escaped(getStringValue(R, "DefaultVal")) << "\", "; + OS << '\"'; + OS << getDevelopmentStage(R) << "\", "; if (!R.getValueAsBit("Hidden")) OS << "false"; From 3e4acaabb9d9d8f56cdbd0aff7d89165cab2320f Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Thu, 23 May 2019 23:02:56 +0000 Subject: [PATCH 0102/1176] Break false dependencies on target libraries Summary: For the most part this consists of replacing ${LLVM_TARGETS_TO_BUILD} with some combination of AllTargets* so that they depend on specific components of a target backend rather than all of it. The overall effect of this is that, for example, tools like opt no longer falsely depend on the disassembler, while tools like llvm-ar no longer depend on the code generator. There's a couple quirks to point out here: * AllTargetsCodeGens is a bit more prevalent than expected. Tools like dsymutil seem to need it which I was surprised by. * llvm-xray linked to all the backends but doesn't seem to need any of them. It builds and passes the tests so that seems to be correct. * I left gold out as it's not built when binutils is not available so I'm unable to test it Reviewers: bogner, JDevlieghere Reviewed By: bogner Subscribers: mehdi_amini, mgorny, steven_wu, dexonsmith, rupprecht, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62331 llvm-svn: 361567 --- llvm/cmake/modules/LLVM-Config.cmake | 7 +++++++ llvm/tools/bugpoint/CMakeLists.txt | 3 ++- llvm/tools/dsymutil/CMakeLists.txt | 5 ++++- llvm/tools/llc/CMakeLists.txt | 3 ++- llvm/tools/llvm-ar/CMakeLists.txt | 4 +++- llvm/tools/llvm-c-test/CMakeLists.txt | 4 +++- llvm/tools/llvm-cxxdump/CMakeLists.txt | 2 +- llvm/tools/llvm-dwp/CMakeLists.txt | 3 ++- llvm/tools/llvm-lto/CMakeLists.txt | 3 ++- llvm/tools/llvm-lto2/CMakeLists.txt | 4 +++- llvm/tools/llvm-rtdyld/CMakeLists.txt | 4 +++- llvm/tools/llvm-xray/CMakeLists.txt | 1 - llvm/tools/lto/CMakeLists.txt | 6 +++++- llvm/tools/opt/CMakeLists.txt | 4 +++- 14 files changed, 40 insertions(+), 13 deletions(-) diff --git a/llvm/cmake/modules/LLVM-Config.cmake b/llvm/cmake/modules/LLVM-Config.cmake index 474a874a4426e..57c02f170e18f 100644 --- a/llvm/cmake/modules/LLVM-Config.cmake +++ b/llvm/cmake/modules/LLVM-Config.cmake @@ -209,6 +209,13 @@ function(llvm_map_components_to_libnames out_libs) # already processed elseif( c STREQUAL "all" ) list(APPEND expanded_components ${LLVM_AVAILABLE_LIBS}) + elseif( c STREQUAL "AllTargetsCodeGens" ) + # Link all the asm printers from all the targets + foreach(t ${LLVM_TARGETS_TO_BUILD}) + if( TARGET LLVM${t}CodeGen) + list(APPEND expanded_components "LLVM${t}CodeGen") + endif() + endforeach(t) elseif( c STREQUAL "AllTargetsAsmPrinters" ) # Link all the asm printers from all the targets foreach(t ${LLVM_TARGETS_TO_BUILD}) diff --git a/llvm/tools/bugpoint/CMakeLists.txt b/llvm/tools/bugpoint/CMakeLists.txt index 654ecc496a919..6ed15a24a2d4d 100644 --- a/llvm/tools/bugpoint/CMakeLists.txt +++ b/llvm/tools/bugpoint/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens Analysis BitWriter CodeGen diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt index 480f78fb1888c..19865e3d20e14 100644 --- a/llvm/tools/dsymutil/CMakeLists.txt +++ b/llvm/tools/dsymutil/CMakeLists.txt @@ -1,5 +1,8 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmPrinters + AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos AsmPrinter DebugInfoDWARF MC diff --git a/llvm/tools/llc/CMakeLists.txt b/llvm/tools/llc/CMakeLists.txt index 4f8181a1b6577..863358b5e71c7 100644 --- a/llvm/tools/llc/CMakeLists.txt +++ b/llvm/tools/llc/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens Analysis AsmPrinter CodeGen diff --git a/llvm/tools/llvm-ar/CMakeLists.txt b/llvm/tools/llvm-ar/CMakeLists.txt index 191c684d5245e..602b4a46ea055 100644 --- a/llvm/tools/llvm-ar/CMakeLists.txt +++ b/llvm/tools/llvm-ar/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsDescs + AllTargetsInfos BinaryFormat Core DlltoolDriver diff --git a/llvm/tools/llvm-c-test/CMakeLists.txt b/llvm/tools/llvm-c-test/CMakeLists.txt index bce0f4a5a4209..78eaafc3b5a40 100644 --- a/llvm/tools/llvm-c-test/CMakeLists.txt +++ b/llvm/tools/llvm-c-test/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDisassemblers BitReader Core MCDisassembler diff --git a/llvm/tools/llvm-cxxdump/CMakeLists.txt b/llvm/tools/llvm-cxxdump/CMakeLists.txt index ada886e888734..519e728e87b6f 100644 --- a/llvm/tools/llvm-cxxdump/CMakeLists.txt +++ b/llvm/tools/llvm-cxxdump/CMakeLists.txt @@ -1,5 +1,5 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsInfos Object Support ) diff --git a/llvm/tools/llvm-dwp/CMakeLists.txt b/llvm/tools/llvm-dwp/CMakeLists.txt index 1b5fbddc1f750..49f40b5c6397b 100644 --- a/llvm/tools/llvm-dwp/CMakeLists.txt +++ b/llvm/tools/llvm-dwp/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens AsmPrinter DebugInfoDWARF MC diff --git a/llvm/tools/llvm-lto/CMakeLists.txt b/llvm/tools/llvm-lto/CMakeLists.txt index f0b385b7993d2..d0222315d25f7 100644 --- a/llvm/tools/llvm-lto/CMakeLists.txt +++ b/llvm/tools/llvm-lto/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens BitReader BitWriter Core diff --git a/llvm/tools/llvm-lto2/CMakeLists.txt b/llvm/tools/llvm-lto2/CMakeLists.txt index 9be12d71ed793..233817a387f9d 100644 --- a/llvm/tools/llvm-lto2/CMakeLists.txt +++ b/llvm/tools/llvm-lto2/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDescs BitReader Core Linker diff --git a/llvm/tools/llvm-rtdyld/CMakeLists.txt b/llvm/tools/llvm-rtdyld/CMakeLists.txt index c1acbe5846bdb..e1738633cfc39 100644 --- a/llvm/tools/llvm-rtdyld/CMakeLists.txt +++ b/llvm/tools/llvm-rtdyld/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsDisassemblers + AllTargetsDescs + AllTargetsInfos DebugInfoDWARF ExecutionEngine MC diff --git a/llvm/tools/llvm-xray/CMakeLists.txt b/llvm/tools/llvm-xray/CMakeLists.txt index 4b056d10758f9..2551b97e550dc 100644 --- a/llvm/tools/llvm-xray/CMakeLists.txt +++ b/llvm/tools/llvm-xray/CMakeLists.txt @@ -1,5 +1,4 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} DebugInfoDWARF Object Support diff --git a/llvm/tools/lto/CMakeLists.txt b/llvm/tools/lto/CMakeLists.txt index 6e913519a809a..20118e029f827 100644 --- a/llvm/tools/lto/CMakeLists.txt +++ b/llvm/tools/lto/CMakeLists.txt @@ -1,5 +1,9 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDescs + AllTargetsDisassemblers + AllTargetsInfos BitReader Core LTO diff --git a/llvm/tools/opt/CMakeLists.txt b/llvm/tools/opt/CMakeLists.txt index f03d11516657f..2f9665c689807 100644 --- a/llvm/tools/opt/CMakeLists.txt +++ b/llvm/tools/opt/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsInfos AggressiveInstCombine Analysis BitWriter From 4d4df6f144d93a901387c66d73183a72e198ee4f Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 23 May 2019 23:33:34 +0000 Subject: [PATCH 0103/1176] [InstCombine] remove redundant fold for insertelement; NFC The out-of-bounds index pattern is handled by InstSimplify. llvm-svn: 361569 --- llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 44130d3246b67..063175b45cba7 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -884,14 +884,10 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { if (match(IdxOp, m_ConstantInt(InsertedIdx)) && match(ScalarOp, m_ExtractElement(m_Value(ExtVecOp), m_ConstantInt(ExtractedIdx)))) { - unsigned NumInsertVectorElts = IE.getType()->getNumElements(); unsigned NumExtractVectorElts = ExtVecOp->getType()->getVectorNumElements(); if (ExtractedIdx >= NumExtractVectorElts) // Out of range extract. return replaceInstUsesWith(IE, VecOp); - if (InsertedIdx >= NumInsertVectorElts) // Out of range insert. - return replaceInstUsesWith(IE, UndefValue::get(IE.getType())); - // If we are extracting a value from a vector, then inserting it right // back into the same place, just use the input vector. if (ExtVecOp == VecOp && ExtractedIdx == InsertedIdx) From 093c922205fe53be35edcf99258aa5a00981c605 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 23 May 2019 23:33:38 +0000 Subject: [PATCH 0104/1176] [InstCombine] remove redundant fold for extractelement; NFC The out-of-bounds index pattern is handled by InstSimplify, so the extractelement should be eliminated next time it is visited. llvm-svn: 361570 --- llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 063175b45cba7..c3fd612a9d007 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -884,10 +884,6 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { if (match(IdxOp, m_ConstantInt(InsertedIdx)) && match(ScalarOp, m_ExtractElement(m_Value(ExtVecOp), m_ConstantInt(ExtractedIdx)))) { - unsigned NumExtractVectorElts = ExtVecOp->getType()->getVectorNumElements(); - if (ExtractedIdx >= NumExtractVectorElts) // Out of range extract. - return replaceInstUsesWith(IE, VecOp); - // If we are extracting a value from a vector, then inserting it right // back into the same place, just use the input vector. if (ExtVecOp == VecOp && ExtractedIdx == InsertedIdx) From ffafdb9afc84126fe3156b8075bc3d7d3dad6dfe Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 23 May 2019 23:34:43 +0000 Subject: [PATCH 0105/1176] Fix hang during constant evaluation of union assignment. HandleUnionActiveMemberChange forgot to walk over a nop implicit conversion node and got stuck in the process. As a cleanup I changed the declaration of `E` so it can't be accidentally accessed after the loop. llvm-svn: 361571 --- clang/lib/AST/ExprConstant.cpp | 5 ++--- clang/test/SemaCXX/constant-expression-cxx2a.cpp | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index dab40cc5754d6..ac21b63cc79bb 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -4994,9 +4994,8 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, llvm::SmallVector, 4> UnionPathLengths; // C++ [class.union]p5: // define the set S(E) of subexpressions of E as follows: - const Expr *E = LHSExpr; unsigned PathLength = LHS.Designator.Entries.size(); - while (E) { + for (const Expr *E = LHSExpr; E != nullptr;) { // -- If E is of the form A.B, S(E) contains the elements of S(A)... if (auto *ME = dyn_cast(E)) { auto *FD = dyn_cast(ME->getMemberDecl()); @@ -5026,6 +5025,7 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, } else if (auto *ICE = dyn_cast(E)) { // Step over a derived-to-base conversion. + E = ICE->getSubExpr(); if (ICE->getCastKind() == CK_NoOp) continue; if (ICE->getCastKind() != CK_DerivedToBase && @@ -5038,7 +5038,6 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, LHS.Designator.Entries[PathLength] .getAsBaseOrMember().getPointer())); } - E = ICE->getSubExpr(); // -- Otherwise, S(E) is empty. } else { diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index a0f92691c27f9..aa534ce592e34 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -513,4 +513,12 @@ namespace Union { static_assert(return_init_all().a.p == 7); // expected-error {{}} expected-note {{read of member 'p' of union with no active member}} static_assert(return_init_all().a.q == 8); // expected-error {{}} expected-note {{read of member 'q' of union with no active member}} constexpr B init_all = return_init_all(); + + constexpr bool test_no_member_change = []{ + union U { char dummy = {}; }; + U u1; + U u2; + u1 = u2; + return true; + }(); } From ae02e8944807c7b611ca3645a983c62d464f27a4 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 23 May 2019 23:46:44 +0000 Subject: [PATCH 0106/1176] P0722R3: Implement library support for destroying delete Summary: This provides the `std::destroying_delete_t` declaration in C++2a and after. (Even when the compiler doesn't support the language feature). However, the feature test macro `__cpp_lib_destroying_delete` is only defined when we have both language support and C++2a. Reviewers: ldionne, ckennelly, serge-sans-paille, EricWF Reviewed By: EricWF Subscribers: dexonsmith, riccibruno, christof, jwakely, jdoerfert, mclow.lists, ldionne, libcxx-commits Differential Revision: https://reviews.llvm.org/D55840 llvm-svn: 361572 --- libcxx/docs/FeatureTestMacroTable.rst | 2 +- libcxx/include/new | 15 +++++ libcxx/include/version | 4 +- .../destroying_delete_t.pass.cpp | 65 +++++++++++++++++++ .../new.version.pass.cpp | 6 +- .../version.version.pass.cpp | 6 +- .../generate_feature_test_macro_components.py | 9 ++- 7 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 0748c4c624d9b..2200a998aa4a1 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -182,7 +182,7 @@ Status ------------------------------------------------- ----------------- ``__cpp_lib_constexpr_swap_algorithms`` *unimplemented* ------------------------------------------------- ----------------- - ``__cpp_lib_destroying_delete`` *unimplemented* + ``__cpp_lib_destroying_delete`` ``201806L`` ------------------------------------------------- ----------------- ``__cpp_lib_erase_if`` ``201811L`` ------------------------------------------------- ----------------- diff --git a/libcxx/include/new b/libcxx/include/new index 4cf4c4c1e7b98..85e4c4b3fcf2a 100644 --- a/libcxx/include/new +++ b/libcxx/include/new @@ -33,6 +33,12 @@ public: }; enum class align_val_t : size_t {}; // C++17 + +struct destroying_delete_t { // C++20 + explicit destroying_delete_t() = default; +}; +inline constexpr destroying_delete_t destroying_delete{}; // C++20 + struct nothrow_t {}; extern const nothrow_t nothrow; typedef void (*new_handler)(); @@ -158,6 +164,15 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 }; #endif #endif +#if _LIBCPP_STD_VER > 17 +// Enable the declaration even if the compiler doesn't support the language +// feature. +struct destroying_delete_t { + explicit destroying_delete_t() = default; +}; +_LIBCPP_INLINE_VAR constexpr destroying_delete_t destroying_delete{}; +#endif // _LIBCPP_STD_VER > 17 + } // std #if defined(_LIBCPP_CXX03_LANG) diff --git a/libcxx/include/version b/libcxx/include/version index 102da672e42dd..fe9cfed876b08 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -220,7 +220,9 @@ __cpp_lib_void_t 201411L // # define __cpp_lib_concepts 201806L // # define __cpp_lib_constexpr_misc 201811L // # define __cpp_lib_constexpr_swap_algorithms 201806L -// # define __cpp_lib_destroying_delete 201806L +# if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L +# define __cpp_lib_destroying_delete 201806L +# endif # define __cpp_lib_erase_if 201811L // # define __cpp_lib_generic_unordered_lookup 201811L # define __cpp_lib_interpolate 201902L diff --git a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp new file mode 100644 index 0000000000000..d544b0e7cab6e --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp @@ -0,0 +1,65 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// struct destroying_delete_t { +// explicit destroying_delete_t() = default; +// }; +// inline constexpr destroying_delete_t destroying_delete{}; + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include + +#include +#include "test_macros.h" + +struct A { + void *data; + A(); + ~A(); + + static A* New(); + void operator delete(A*, std::destroying_delete_t); +}; + +bool A_constructed = false; +bool A_destroyed = false; +bool A_destroying_deleted = false; + +A::A() { + A_constructed = true; +} + +A::~A() { + A_destroyed = true; +} + +A* A::New() { + return new(::operator new(sizeof(A))) A(); +} + +void A::operator delete(A* a, std::destroying_delete_t) { + A_destroying_deleted = true; + ::operator delete(a); +} + +#ifndef __cpp_lib_destroying_delete +#error "Expected __cpp_lib_destroying_delete to be defined" +#elif __cpp_lib_destroying_delete < 201806L +#error "Unexpected value of __cpp_lib_destroying_delete" +#endif + +int main() { + // Ensure that we call the destroying delete and not the destructor. + A* ap = A::New(); + assert(A_constructed); + delete ap; + assert(!A_destroyed); + assert(A_destroying_deleted); +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp index 5f012cd55f6c2..294c29a739ff1 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp @@ -72,16 +72,16 @@ #elif TEST_STD_VER > 17 -# if !defined(_LIBCPP_VERSION) +# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L # ifndef __cpp_lib_destroying_delete # error "__cpp_lib_destroying_delete should be defined in c++2a" # endif # if __cpp_lib_destroying_delete != 201806L # error "__cpp_lib_destroying_delete should have the value 201806L in c++2a" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_destroying_delete -# error "__cpp_lib_destroying_delete should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_destroying_delete should not be defined when TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L is not defined!" # endif # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp index 0ed0a512286dc..3503051afad7f 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -1662,16 +1662,16 @@ # endif # endif -# if !defined(_LIBCPP_VERSION) +# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L # ifndef __cpp_lib_destroying_delete # error "__cpp_lib_destroying_delete should be defined in c++2a" # endif # if __cpp_lib_destroying_delete != 201806L # error "__cpp_lib_destroying_delete should have the value 201806L in c++2a" # endif -# else // _LIBCPP_VERSION +# else # ifdef __cpp_lib_destroying_delete -# error "__cpp_lib_destroying_delete should not be defined because it is unimplemented in libc++!" +# error "__cpp_lib_destroying_delete should not be defined when TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L is not defined!" # endif # endif diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index f5e770de5bb22..0384d32558087 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -483,7 +483,14 @@ def add_version_header(tc): "c++2a": 201806L, }, "headers": ["new"], - "unimplemented": True, + "depends": + "TEST_STD_VER > 17" + " && defined(__cpp_impl_destroying_delete)" + " && __cpp_impl_destroying_delete >= 201806L", + "internal_depends": + "_LIBCPP_STD_VER > 17" + " && defined(__cpp_impl_destroying_delete)" + " && __cpp_impl_destroying_delete >= 201806L", }, {"name": "__cpp_lib_three_way_comparison", "values": { From 11c141eb68531eec30af8ff8f82b8159de99e555 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 24 May 2019 00:02:00 +0000 Subject: [PATCH 0107/1176] [COFF] Remove finalizeContents virtual method from Chunk, NFC This only needs to be done for MergeChunks, so just do that in a separate pass in the Writer. This is one small step towards eliminating the vtable in Chunk. llvm-svn: 361573 --- lld/COFF/Chunks.cpp | 15 ++++++++------- lld/COFF/Chunks.h | 7 ++----- lld/COFF/Writer.cpp | 13 ++++++++++--- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 76b0c8301b904..b016ac1e86d35 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -873,14 +873,15 @@ void MergeChunk::addSection(SectionChunk *C) { } void MergeChunk::finalizeContents() { - if (!Finalized) { - for (SectionChunk *C : Sections) - if (C->Live) - Builder.add(toStringRef(C->getContents())); - Builder.finalize(); - Finalized = true; - } + assert(!Finalized && "should only finalize once"); + for (SectionChunk *C : Sections) + if (C->Live) + Builder.add(toStringRef(C->getContents())); + Builder.finalize(); + Finalized = true; +} +void MergeChunk::assignSubsectionRVAs() { for (SectionChunk *C : Sections) { if (!C->Live) continue; diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index d15638e7b0cc6..672003b31f98f 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -78,10 +78,6 @@ class Chunk { // before calling this function. virtual void writeTo(uint8_t *Buf) const {} - // Called by the writer after an RVA is assigned, but before calling - // getSize(). - virtual void finalizeContents() {} - // The writer sets and uses the addresses. In practice, PE images cannot be // larger than 2GB. Chunks are always laid as part of the image, so Chunk RVAs // can be stored with 32 bits. @@ -320,7 +316,8 @@ class MergeChunk : public Chunk { public: MergeChunk(uint32_t Alignment); static void addSection(SectionChunk *C); - void finalizeContents() override; + void finalizeContents(); + void assignSubsectionRVAs(); uint32_t getOutputCharacteristics() const override; StringRef getSectionName() const override { return ".rdata"; } diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index f629715fbd2ac..d673fc8de8527 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -865,9 +865,12 @@ void Writer::createSections() { } void Writer::createMiscChunks() { - for (MergeChunk *P : MergeChunk::Instances) - if (P) + for (MergeChunk *P : MergeChunk::Instances) { + if (P) { + P->finalizeContents(); RdataSec->addChunk(P); + } + } // Create thunks for locally-dllimported symbols. if (!Symtab->LocalImportChunks.empty()) { @@ -1162,7 +1165,6 @@ void Writer::assignAddresses() { VirtualSize += Padding; VirtualSize = alignTo(VirtualSize, C->getAlignment()); C->setRVA(RVA + VirtualSize); - C->finalizeContents(); VirtualSize += C->getSize(); if (C->hasData()) RawSize = alignTo(VirtualSize, SectorSize); @@ -1177,6 +1179,11 @@ void Writer::assignAddresses() { FileSize += alignTo(RawSize, SectorSize); } SizeOfImage = alignTo(RVA, PageSize); + + // Assign addresses to sections in MergeChunks. + for (MergeChunk *MC : MergeChunk::Instances) + if (MC) + MC->assignSubsectionRVAs(); } template void Writer::writeHeader() { From 3c9c9ea2c98e341a4f39df448f508321ff317ac0 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 24 May 2019 00:10:33 +0000 Subject: [PATCH 0108/1176] Update C++2a status for destroying delete llvm-svn: 361574 --- libcxx/www/cxx2a_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html index 9b06a4e493951..99438fffa0615 100644 --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -91,7 +91,7 @@

Paper Status

P0556R3LWGIntegral power-of-2 operationsRapperswilIn Progress P0619R4LWGReviewing Deprecated Facilities of C++17 for C++20Rapperswil P0646R1LWGImproving the Return Value of Erase-Like AlgorithmsRapperswil - P0722R3CWGEfficient sized delete for variable sized classesRapperswil + P0722R3CWGEfficient sized delete for variable sized classesRapperswilComplete9.0 P0758R1LWGImplicit conversion traits and utility functionsRapperswilComplete P0759R1LWGfpos RequirementsRapperswil P0769R2LWGAdd shift to <algorithm>Rapperswil From 3e15f833819d6e18988c62e877637258e649808c Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 24 May 2019 00:11:23 +0000 Subject: [PATCH 0109/1176] [InstSimplify] add tests for insert-of-extract; NFC llvm-svn: 361575 --- .../Transforms/InstSimplify/insertelement.ll | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/llvm/test/Transforms/InstSimplify/insertelement.ll b/llvm/test/Transforms/InstSimplify/insertelement.ll index c7db869d056d2..6e78ea78a1b98 100644 --- a/llvm/test/Transforms/InstSimplify/insertelement.ll +++ b/llvm/test/Transforms/InstSimplify/insertelement.ll @@ -49,3 +49,25 @@ define <4 x i32> @PR1286(<4 x i32> %A) { %B = insertelement <4 x i32> %A, i32 undef, i32 1 ret <4 x i32> %B } + +define <8 x i8> @extract_insert_same_vec_and_index(<8 x i8> %in) { +; CHECK-LABEL: @extract_insert_same_vec_and_index( +; CHECK-NEXT: [[VAL:%.*]] = extractelement <8 x i8> [[IN:%.*]], i32 5 +; CHECK-NEXT: [[VEC:%.*]] = insertelement <8 x i8> [[IN]], i8 [[VAL]], i32 5 +; CHECK-NEXT: ret <8 x i8> [[VEC]] +; + %val = extractelement <8 x i8> %in, i32 5 + %vec = insertelement <8 x i8> %in, i8 %val, i32 5 + ret <8 x i8> %vec +} + +define <8 x i8> @extract_insert_same_vec_and_index2(<8 x i8> %in, i32 %index) { +; CHECK-LABEL: @extract_insert_same_vec_and_index2( +; CHECK-NEXT: [[VAL:%.*]] = extractelement <8 x i8> [[IN:%.*]], i32 [[INDEX:%.*]] +; CHECK-NEXT: [[VEC:%.*]] = insertelement <8 x i8> [[IN]], i8 [[VAL]], i32 [[INDEX]] +; CHECK-NEXT: ret <8 x i8> [[VEC]] +; + %val = extractelement <8 x i8> %in, i32 %index + %vec = insertelement <8 x i8> %in, i8 %val, i32 %index + ret <8 x i8> %vec +} From 8869a98e82552ef698112df840575693780802a4 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 24 May 2019 00:13:58 +0000 Subject: [PATCH 0110/1176] [InstSimplify] fold insertelement-of-extractelement This was partly handled in InstCombine (only the constant index case), so delete that and zap it more generally in InstSimplify. llvm-svn: 361576 --- llvm/lib/Analysis/InstructionSimplify.cpp | 6 ++++++ llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp | 5 ----- llvm/test/Transforms/InstSimplify/insertelement.ll | 8 ++------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 6e421dcaa737f..1f8245d30f6ff 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4016,6 +4016,12 @@ Value *llvm::SimplifyInsertElementInst(Value *Vec, Value *Val, Value *Idx, if (isa(Val)) return Vec; + // If we are extracting a value from a vector, then inserting it into the same + // place, that's the input vector: + // insertelt Vec, (extractelt Vec, Idx), Idx --> Vec + if (match(Val, m_ExtractElement(m_Specific(Vec), m_Specific(Idx)))) + return Vec; + return nullptr; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index c3fd612a9d007..308569395a9ec 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -884,11 +884,6 @@ Instruction *InstCombiner::visitInsertElementInst(InsertElementInst &IE) { if (match(IdxOp, m_ConstantInt(InsertedIdx)) && match(ScalarOp, m_ExtractElement(m_Value(ExtVecOp), m_ConstantInt(ExtractedIdx)))) { - // If we are extracting a value from a vector, then inserting it right - // back into the same place, just use the input vector. - if (ExtVecOp == VecOp && ExtractedIdx == InsertedIdx) - return replaceInstUsesWith(IE, VecOp); - // TODO: Looking at the user(s) to determine if this insert is a // fold-to-shuffle opportunity does not match the usual instcombine // constraints. We should decide if the transform is worthy based only diff --git a/llvm/test/Transforms/InstSimplify/insertelement.ll b/llvm/test/Transforms/InstSimplify/insertelement.ll index 6e78ea78a1b98..e487eeb96b06c 100644 --- a/llvm/test/Transforms/InstSimplify/insertelement.ll +++ b/llvm/test/Transforms/InstSimplify/insertelement.ll @@ -52,9 +52,7 @@ define <4 x i32> @PR1286(<4 x i32> %A) { define <8 x i8> @extract_insert_same_vec_and_index(<8 x i8> %in) { ; CHECK-LABEL: @extract_insert_same_vec_and_index( -; CHECK-NEXT: [[VAL:%.*]] = extractelement <8 x i8> [[IN:%.*]], i32 5 -; CHECK-NEXT: [[VEC:%.*]] = insertelement <8 x i8> [[IN]], i8 [[VAL]], i32 5 -; CHECK-NEXT: ret <8 x i8> [[VEC]] +; CHECK-NEXT: ret <8 x i8> [[IN:%.*]] ; %val = extractelement <8 x i8> %in, i32 5 %vec = insertelement <8 x i8> %in, i8 %val, i32 5 @@ -63,9 +61,7 @@ define <8 x i8> @extract_insert_same_vec_and_index(<8 x i8> %in) { define <8 x i8> @extract_insert_same_vec_and_index2(<8 x i8> %in, i32 %index) { ; CHECK-LABEL: @extract_insert_same_vec_and_index2( -; CHECK-NEXT: [[VAL:%.*]] = extractelement <8 x i8> [[IN:%.*]], i32 [[INDEX:%.*]] -; CHECK-NEXT: [[VEC:%.*]] = insertelement <8 x i8> [[IN]], i8 [[VAL]], i32 [[INDEX]] -; CHECK-NEXT: ret <8 x i8> [[VEC]] +; CHECK-NEXT: ret <8 x i8> [[IN:%.*]] ; %val = extractelement <8 x i8> %in, i32 %index %vec = insertelement <8 x i8> %in, i8 %val, i32 %index From 55229f6b10276526d76f7f6b900053e3c82b5bf7 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 24 May 2019 00:15:04 +0000 Subject: [PATCH 0111/1176] [WebAssembly] Expand more SIMD float ops Summary: These were previously causing ISel failures. Reviewers: aheejin Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62354 llvm-svn: 361577 --- .../WebAssembly/WebAssemblyISelLowering.cpp | 3 +- llvm/test/CodeGen/WebAssembly/libcalls.ll | 17 +- .../CodeGen/WebAssembly/simd-unsupported.ll | 180 +++++++++++++++++- 3 files changed, 195 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 06aee6e80a04f..65db1ebf50fca 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -182,7 +182,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( // Expand float operations supported for scalars but not SIMD for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, - ISD::FCOPYSIGN}) { + ISD::FCOPYSIGN, ISD::FLOG, ISD::FLOG2, ISD::FLOG10, + ISD::FEXP, ISD::FEXP2, ISD::FRINT}) { setOperationAction(Op, MVT::v4f32, Expand); if (Subtarget->hasUnimplementedSIMD128()) setOperationAction(Op, MVT::v2f64, Expand); diff --git a/llvm/test/CodeGen/WebAssembly/libcalls.ll b/llvm/test/CodeGen/WebAssembly/libcalls.ll index 3849f1978a23f..bccb438f3c088 100644 --- a/llvm/test/CodeGen/WebAssembly/libcalls.ll +++ b/llvm/test/CodeGen/WebAssembly/libcalls.ll @@ -13,6 +13,11 @@ declare fp128 @llvm.pow.f128(fp128, fp128) declare double @llvm.cos.f64(double) declare double @llvm.log10.f64(double) +declare double @llvm.pow.f64(double, double) +declare double @llvm.log.f64(double) +declare double @llvm.exp.f64(double) +declare i32 @llvm.lround(double) + ; CHECK-LABEL: fp128libcalls: @@ -51,12 +56,20 @@ define i128 @i128libcalls(i128 %x, i128 %y) { } ; CHECK-LABEL: f64libcalls: -define double @f64libcalls(double %x, double %y) { +define i32 @f64libcalls(double %x, double %y) { ; CHECK: f64.call $push{{[0-9]}}=, cos %a = call double @llvm.cos.f64(double %x) ; CHECK: f64.call $push{{[0-9]}}=, log10 %b = call double @llvm.log10.f64(double %a) - ret double %b + ; CHECK: f64.call $push{{[0-9]}}=, pow + %c = call double @llvm.pow.f64(double %b, double %y) + ; CHECK: f64.call $push{{[0-9]}}=, log + %d = call double @llvm.log.f64(double %c) + ; CHECK: f64.call $push{{[0-9]}}=, exp + %e = call double @llvm.exp.f64(double %d) + ; CHECK: i32.call $push{{[0-9]}}=, lround + %f = call i32 @llvm.lround(double %e) + ret i32 %f } ; fcmp ord and unord (RTLIB::O_F32 / RTLIB::UO_F32 etc) are a special case (see diff --git a/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll b/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll index 97da90d8bb489..b539c885c087a 100644 --- a/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-unsupported.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+unimplemented-simd128 | FileCheck %s -; Test that operations that are supported by MVP but not SIMD are -; properly unrolled. +; Test that operations that are not supported by SIMD are properly +; unrolled. target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -405,6 +405,94 @@ define <4 x float> @copysign_v4f32(<4 x float> %x, <4 x float> %y) { ret <4 x float> %v } +; CHECK-LABEL: sin_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, sinf +declare <4 x float> @llvm.sin.v4f32(<4 x float>) +define <4 x float> @sin_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.sin.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: cos_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, cosf +declare <4 x float> @llvm.cos.v4f32(<4 x float>) +define <4 x float> @cos_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.cos.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: powi_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, __powisf2 +declare <4 x float> @llvm.powi.v4f32(<4 x float>, i32) +define <4 x float> @powi_v4f32(<4 x float> %x, i32 %y) { + %v = call <4 x float> @llvm.powi.v4f32(<4 x float> %x, i32 %y) + ret <4 x float> %v +} + +; CHECK-LABEL: pow_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, powf +declare <4 x float> @llvm.pow.v4f32(<4 x float>, <4 x float>) +define <4 x float> @pow_v4f32(<4 x float> %x, <4 x float> %y) { + %v = call <4 x float> @llvm.pow.v4f32(<4 x float> %x, <4 x float> %y) + ret <4 x float> %v +} + +; CHECK-LABEL: log_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, logf +declare <4 x float> @llvm.log.v4f32(<4 x float>) +define <4 x float> @log_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.log.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: log2_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, log2f +declare <4 x float> @llvm.log2.v4f32(<4 x float>) +define <4 x float> @log2_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.log2.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: log10_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, log10f +declare <4 x float> @llvm.log10.v4f32(<4 x float>) +define <4 x float> @log10_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.log10.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: exp_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, expf +declare <4 x float> @llvm.exp.v4f32(<4 x float>) +define <4 x float> @exp_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.exp.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: exp2_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, exp2f +declare <4 x float> @llvm.exp2.v4f32(<4 x float>) +define <4 x float> @exp2_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.exp2.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: rint_v4f32: +; CHECK: f32.nearest +declare <4 x float> @llvm.rint.v4f32(<4 x float>) +define <4 x float> @rint_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.rint.v4f32(<4 x float> %x) + ret <4 x float> %v +} + +; CHECK-LABEL: round_v4f32: +; CHECK: f32.call $push[[L:[0-9]+]]=, roundf +declare <4 x float> @llvm.round.v4f32(<4 x float>) +define <4 x float> @round_v4f32(<4 x float> %x) { + %v = call <4 x float> @llvm.round.v4f32(<4 x float> %x) + ret <4 x float> %v +} + ; ============================================================================== ; 2 x f64 ; ============================================================================== @@ -448,3 +536,91 @@ define <2 x double> @copysign_v2f64(<2 x double> %x, <2 x double> %y) { %v = call <2 x double> @llvm.copysign.v2f64(<2 x double> %x, <2 x double> %y) ret <2 x double> %v } + +; CHECK-LABEL: sin_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, sin +declare <2 x double> @llvm.sin.v2f64(<2 x double>) +define <2 x double> @sin_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.sin.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: cos_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, cos +declare <2 x double> @llvm.cos.v2f64(<2 x double>) +define <2 x double> @cos_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.cos.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: powi_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, __powidf2 +declare <2 x double> @llvm.powi.v2f64(<2 x double>, i32) +define <2 x double> @powi_v2f64(<2 x double> %x, i32 %y) { + %v = call <2 x double> @llvm.powi.v2f64(<2 x double> %x, i32 %y) + ret <2 x double> %v +} + +; CHECK-LABEL: pow_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, pow +declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) +define <2 x double> @pow_v2f64(<2 x double> %x, <2 x double> %y) { + %v = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> %y) + ret <2 x double> %v +} + +; CHECK-LABEL: log_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, log +declare <2 x double> @llvm.log.v2f64(<2 x double>) +define <2 x double> @log_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.log.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: log2_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, log2 +declare <2 x double> @llvm.log2.v2f64(<2 x double>) +define <2 x double> @log2_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.log2.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: log10_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, log10 +declare <2 x double> @llvm.log10.v2f64(<2 x double>) +define <2 x double> @log10_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.log10.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: exp_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, exp +declare <2 x double> @llvm.exp.v2f64(<2 x double>) +define <2 x double> @exp_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.exp.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: exp2_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, exp2 +declare <2 x double> @llvm.exp2.v2f64(<2 x double>) +define <2 x double> @exp2_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.exp2.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: rint_v2f64: +; CHECK: f64.nearest +declare <2 x double> @llvm.rint.v2f64(<2 x double>) +define <2 x double> @rint_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.rint.v2f64(<2 x double> %x) + ret <2 x double> %v +} + +; CHECK-LABEL: round_v2f64: +; CHECK: f64.call $push[[L:[0-9]+]]=, round +declare <2 x double> @llvm.round.v2f64(<2 x double>) +define <2 x double> @round_v2f64(<2 x double> %x) { + %v = call <2 x double> @llvm.round.v2f64(<2 x double> %x) + ret <2 x double> %v +} From ab09cca310e8de1b79766f93b3b83897eabb52dd Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 24 May 2019 00:21:46 +0000 Subject: [PATCH 0112/1176] llvm-objcopy: Change sectionWithinSegment() to use virtual addresses instead of file offsets for SHT_NOBITS sections. Without this, sectionWithinSegment() will return the wrong answer for bss sections. This doesn't seem to matter now (for non-broken ELF files), but it will matter with a change that I'm working on. Differential Revision: https://reviews.llvm.org/D58426 llvm-svn: 361578 --- llvm/tools/llvm-objcopy/ELF/Object.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp index 0c80bad6c102d..85e7ffa6d8ecb 100644 --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -809,6 +809,20 @@ static bool sectionWithinSegment(const SectionBase &Section, // segments and ensures that the section "belongs" to the second segment and // not the first. uint64_t SecSize = Section.Size ? Section.Size : 1; + + if (Section.Type == SHT_NOBITS) { + if (!(Section.Flags & SHF_ALLOC)) + return false; + + bool SectionIsTLS = Section.Flags & SHF_TLS; + bool SegmentIsTLS = Segment.Type == PT_TLS; + if (SectionIsTLS != SegmentIsTLS) + return false; + + return Segment.VAddr <= Section.Addr && + Segment.VAddr + Segment.MemSize >= Section.Addr + SecSize; + } + return Segment.Offset <= Section.OriginalOffset && Segment.Offset + Segment.FileSize >= Section.OriginalOffset + SecSize; } From 060f4b48d55c761de2722c0b7387966d1e8ede0c Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Fri, 24 May 2019 00:43:52 +0000 Subject: [PATCH 0113/1176] [libFuzzer] when using data-flow-trace (DFT) only load the DFT for the files present in the corpus llvm-svn: 361579 --- compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp | 16 ++++++++++------ compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h | 4 +++- compiler-rt/lib/fuzzer/FuzzerLoop.cpp | 7 ++++--- compiler-rt/test/fuzzer/dataflow.test | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp index c67238ec28e99..1fba3913c96a2 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.cpp @@ -100,6 +100,7 @@ void DataFlowTrace::ReadCoverage(const std::string &DirPath) { for (auto &SF : Files) { auto Name = Basename(SF.File); if (Name == kFunctionsTxt) continue; + if (!CorporaHashes.count(Name)) continue; std::ifstream IF(SF.File); Coverage.AppendCoverage(IF); } @@ -154,9 +155,8 @@ static bool ParseDFTLine(const std::string &Line, size_t *FunctionNum, return true; } -bool DataFlowTrace::Init(const std::string &DirPath, - std::string *FocusFunction, - Random &Rand) { +bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction, + Vector &CorporaFiles, Random &Rand) { if (DirPath.empty()) return false; Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str()); Vector Files; @@ -165,6 +165,10 @@ bool DataFlowTrace::Init(const std::string &DirPath, size_t FocusFuncIdx = SIZE_MAX; Vector FunctionNames; + // Collect the hashes of the corpus files. + for (auto &SF : CorporaFiles) + CorporaHashes.insert(Hash(FileToVector(SF.File))); + // Read functions.txt std::ifstream IF(DirPlusFile(DirPath, kFunctionsTxt)); size_t NumFunctions = 0; @@ -211,6 +215,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, for (auto &SF : Files) { auto Name = Basename(SF.File); if (Name == kFunctionsTxt) continue; + if (!CorporaHashes.count(Name)) continue; // not in the corpus. NumTraceFiles++; // Printf("=== %s\n", Name.c_str()); std::ifstream IF(SF.File); @@ -231,11 +236,10 @@ bool DataFlowTrace::Init(const std::string &DirPath, } } } - assert(NumTraceFiles == Files.size() - 1); Printf("INFO: DataFlowTrace: %zd trace files, %zd functions, " "%zd traces with focus function\n", NumTraceFiles, NumFunctions, NumTracesWithFocusFunction); - return true; + return NumTraceFiles > 0; } int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, @@ -311,7 +315,7 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, } RemoveFile(Temp); // Write functions.txt if it's currently empty or doesn't exist. - auto FunctionsTxtPath = DirPlusFile(DirPath, "functions.txt"); + auto FunctionsTxtPath = DirPlusFile(DirPath, kFunctionsTxt); if (FileToString(FunctionsTxtPath).empty()) { Command Cmd; Cmd.addArgument(DFTBinary); diff --git a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h index cfb04ad3ad394..022e8543fd865 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h +++ b/compiler-rt/lib/fuzzer/FuzzerDataFlowTrace.h @@ -32,6 +32,7 @@ #include "FuzzerIO.h" #include +#include #include #include @@ -112,7 +113,7 @@ class DataFlowTrace { public: void ReadCoverage(const std::string &DirPath); bool Init(const std::string &DirPath, std::string *FocusFunction, - Random &Rand); + Vector &CorporaFiles, Random &Rand); void Clear() { Traces.clear(); } const Vector *Get(const std::string &InputSha1) const { auto It = Traces.find(InputSha1); @@ -125,6 +126,7 @@ class DataFlowTrace { // Input's sha1 => DFT for the FocusFunction. std::unordered_map > Traces; BlockCoverage Coverage; + std::unordered_set CorporaHashes; }; } // namespace fuzzer diff --git a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp index d7adc90c9961a..7081daa899066 100644 --- a/compiler-rt/lib/fuzzer/FuzzerLoop.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerLoop.cpp @@ -157,9 +157,6 @@ Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, AllocateCurrentUnitData(); CurrentUnitSize = 0; memset(BaseSha1, 0, sizeof(BaseSha1)); - auto FocusFunctionOrAuto = Options.FocusFunction; - DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto , MD.GetRand()); - TPC.SetFocusFunction(FocusFunctionOrAuto); } Fuzzer::~Fuzzer() {} @@ -789,6 +786,10 @@ void Fuzzer::ReadAndExecuteSeedCorpora(Vector &CorporaFiles) { } void Fuzzer::Loop(Vector &CorporaFiles) { + auto FocusFunctionOrAuto = Options.FocusFunction; + DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, + MD.GetRand()); + TPC.SetFocusFunction(FocusFunctionOrAuto); ReadAndExecuteSeedCorpora(CorporaFiles); DFT.Clear(); // No need for DFT any more. TPC.SetPrintNewPCs(Options.PrintNewCovPcs); diff --git a/compiler-rt/test/fuzzer/dataflow.test b/compiler-rt/test/fuzzer/dataflow.test index bc42c7d1dc5f8..9446fe4023f43 100644 --- a/compiler-rt/test/fuzzer/dataflow.test +++ b/compiler-rt/test/fuzzer/dataflow.test @@ -92,7 +92,7 @@ RUN: %t-ThreeFunctionsTest -collect_data_flow=%t-ThreeFunctionsTestDF -data_flo # Test that we can run collect_data_flow on the entire corpus dir RUN: rm -rf %t/OUT RUN: %t-ThreeFunctionsTest -collect_data_flow=%t-ThreeFunctionsTestDF -data_flow_trace=%t/OUT %t/IN -RUN: %t-ThreeFunctionsTest -data_flow_trace=%t/OUT -runs=0 -focus_function=Func2 2>&1 | FileCheck %s --check-prefix=USE_DATA_FLOW_TRACE +RUN: %t-ThreeFunctionsTest -data_flow_trace=%t/OUT -runs=0 -focus_function=Func2 %t/IN 2>&1 | FileCheck %s --check-prefix=USE_DATA_FLOW_TRACE USE_DATA_FLOW_TRACE: INFO: DataFlowTrace: reading from {{.*}}/OUT From 09ad8c8f73dbc64efada18e7ae2f9b64eb1be215 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 24 May 2019 00:44:33 +0000 Subject: [PATCH 0114/1176] Fix integer literals which are cast to bool This change replaces built-in types that are implicitly converted to booleans. Differential revision: https://reviews.llvm.org/D62284 llvm-svn: 361580 --- .../source/Commands/CommandObjectPlatform.cpp | 2 +- lldb/source/Commands/CommandObjectTarget.cpp | 2 +- lldb/source/Commands/CommandObjectThread.cpp | 2 +- lldb/source/Core/Address.cpp | 2 +- lldb/source/Host/macosx/objcxx/Host.mm | 2 +- lldb/source/Interpreter/Options.cpp | 6 ++-- .../ABI/SysV-mips64/ABISysV_mips64.cpp | 30 +++++++++---------- .../Clang/ASTResultSynthesizer.cpp | 2 +- .../ExpressionParser/Clang/ClangASTSource.cpp | 30 ++++++++++--------- .../Clang/ClangExpressionDeclMap.cpp | 4 +-- .../ARM64/EmulateInstructionARM64.cpp | 4 +-- .../AppleObjCClassDescriptorV2.cpp | 4 +-- .../AppleObjCRuntime/AppleObjCDeclVendor.cpp | 6 ++-- .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 2 +- .../MacOSX-Kernel/CommunicationKDP.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 4 +-- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 2 +- lldb/source/Symbol/ClangASTContext.cpp | 6 ++-- lldb/source/Symbol/ClangASTImporter.cpp | 2 +- lldb/source/Symbol/CompilerType.cpp | 2 +- lldb/source/Symbol/Function.cpp | 2 +- lldb/source/Symbol/SymbolContext.cpp | 2 +- lldb/source/Target/Process.cpp | 2 +- lldb/source/Target/Target.cpp | 2 +- lldb/source/Target/Thread.cpp | 8 ++--- lldb/source/Utility/JSON.cpp | 6 ++-- lldb/source/Utility/SelectHelper.cpp | 2 +- lldb/source/Utility/StructuredData.cpp | 4 +-- lldb/tools/debugserver/source/DNB.cpp | 4 +-- lldb/tools/debugserver/source/JSON.cpp | 6 ++-- .../source/MacOSX/MachThreadList.cpp | 2 +- lldb/tools/debugserver/source/RNBRemote.cpp | 6 ++-- lldb/tools/debugserver/source/debugserver.cpp | 2 +- .../debugserver/source/libdebugserver.cpp | 2 +- 34 files changed, 84 insertions(+), 82 deletions(-) diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 0007ae66a85d9..53549cdeee326 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -235,7 +235,7 @@ class CommandObjectPlatformList : public CommandObjectParsed { host_platform_sp->GetDescription()); uint32_t idx; - for (idx = 0; 1; ++idx) { + for (idx = 0; true; ++idx) { const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex(idx); if (plugin_name == nullptr) diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 53e7347d4f65f..c1f5ff0d283ca 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -3740,7 +3740,7 @@ class CommandObjectTargetModulesLookup : public CommandObjectParsed { break; case 'v': - m_verbose = 1; + m_verbose = true; break; case 'A': diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 519a2865fe9d0..3c6088d6e192e 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -482,7 +482,7 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { case 'e': if (option_arg == "block") { - m_end_line_is_block_end = 1; + m_end_line_is_block_end = true; break; } if (option_arg.getAsInteger(0, m_end_line)) diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 9520e43697e8c..0da83eb98edb1 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -161,7 +161,7 @@ static bool ReadAddress(ExecutionContextScope *exe_scope, static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream *strm) { if (exe_scope == nullptr || byte_size == 0) - return 0; + return false; std::vector buf(byte_size, 0); if (ReadBytes(exe_scope, address, &buf[0], buf.size()) == buf.size()) { diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm index 4994c8139780b..99b5601a9b3d1 100644 --- a/lldb/source/Host/macosx/objcxx/Host.mm +++ b/lldb/source/Host/macosx/objcxx/Host.mm @@ -547,7 +547,7 @@ DataExtractor data(arg_data.GetBytes(), arg_data_size, match_info_ptr->GetNameMatchType(), match_info_ptr->GetProcessInfo().GetName())) { // Skip NULLs - while (1) { + while (true) { const uint8_t *p = data.PeekData(offset, 1); if ((p == NULL) || (*p != '\0')) break; diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp index 4ee9c4d7f5431..814998ec68fc3 100644 --- a/lldb/source/Interpreter/Options.cpp +++ b/lldb/source/Interpreter/Options.cpp @@ -1007,7 +1007,7 @@ llvm::Expected Options::ParseAlias(const Args &args, std::unique_lock lock; OptionParser::Prepare(lock); int val; - while (1) { + while (true) { int long_options_index = -1; val = OptionParser::Parse(argv.size(), &*argv.begin(), sstr.GetString(), long_options, &long_options_index); @@ -1160,7 +1160,7 @@ OptionElementVector Options::ParseForCompletion(const Args &args, bool failed_once = false; uint32_t dash_dash_pos = -1; - while (1) { + while (true) { bool missing_argument = false; int long_options_index = -1; @@ -1358,7 +1358,7 @@ llvm::Expected Options::Parse(const Args &args, std::unique_lock lock; OptionParser::Prepare(lock); int val; - while (1) { + while (true) { int long_options_index = -1; val = OptionParser::Parse(argv.size(), &*argv.begin(), sstr.GetString(), long_options, &long_options_index); diff --git a/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index 8856c54d3c928..18011cfb6b9ea 100644 --- a/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/lldb/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -917,15 +917,15 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( uint32_t integer_bytes = 0; // True if return values are in FP return registers. - bool use_fp_regs = 0; + bool use_fp_regs = false; // True if we found any non floating point field in structure. - bool found_non_fp_field = 0; + bool found_non_fp_field = false; // True if return values are in r2 register. - bool use_r2 = 0; + bool use_r2 = false; // True if return values are in r3 register. - bool use_r3 = 0; + bool use_r3 = false; // True if the result is copied into our data buffer - bool sucess = 0; + bool sucess = false; std::string name; bool is_complex; uint32_t count; @@ -943,9 +943,9 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( nullptr, nullptr); if (field_compiler_type.IsFloatingPointType(count, is_complex)) - use_fp_regs = 1; + use_fp_regs = true; else - found_non_fp_field = 1; + found_non_fp_field = true; } if (use_fp_regs && !found_non_fp_field) { @@ -1059,20 +1059,20 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( // structure integer_bytes = integer_bytes + *field_byte_width + padding; // Increase the consumed bytes. - use_r2 = 1; + use_r2 = true; } else { // There isn't enough space left in r2 for this field, so this // will be in r3. integer_bytes = integer_bytes + *field_byte_width + padding; // Increase the consumed bytes. - use_r3 = 1; + use_r3 = true; } } // We already have consumed at-least 8 bytes that means r2 is done, // and this field will be in r3. Check if this field can fit in r3. else if (integer_bytes + *field_byte_width + padding <= 16) { integer_bytes = integer_bytes + *field_byte_width + padding; - use_r3 = 1; + use_r3 = true; } else { // There isn't any space left for this field, this should not // happen as we have already checked the overall size is not @@ -1085,10 +1085,10 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( // Vector types up to 16 bytes are returned in GP return registers if (type_flags & eTypeIsVector) { if (*byte_size <= 8) - use_r2 = 1; + use_r2 = true; else { - use_r2 = 1; - use_r3 = 1; + use_r2 = true; + use_r3 = true; } } @@ -1100,7 +1100,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( error); if (bytes_copied != r2_info->byte_size) return return_valobj_sp; - sucess = 1; + sucess = true; } if (use_r3) { reg_ctx->ReadRegister(r3_info, r3_value); @@ -1110,7 +1110,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( if (bytes_copied != r3_info->byte_size) return return_valobj_sp; - sucess = 1; + sucess = true; } if (sucess) { // The result is in our data buffer. Create a variable object out of diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 5dc39e8dac4d0..526ef90782ef3 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -239,7 +239,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, break; last_expr = implicit_cast->getSubExpr(); - } while (0); + } while (false); // is_lvalue is used to record whether the expression returns an assignable // Lvalue or an Rvalue. This is relevant because they are handled diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 632594f1c460a..e9dd73c5fa640 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -101,7 +101,7 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, break; sources.push_back(runtime_decl_vendor->GetImporterSource()); - } while (0); + } while (false); do { DeclVendor *modules_decl_vendor = @@ -111,7 +111,7 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, break; sources.push_back(modules_decl_vendor->GetImporterSource()); - } while (0); + } while (false); if (!is_shared_context) { // Update the scratch AST context's merger to reflect any new sources we @@ -125,7 +125,9 @@ void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, sources.push_back({*scratch_ast_context->getASTContext(), *scratch_ast_context->getFileManager(), scratch_ast_context->GetOriginMap()}); - } while (0); + } + while (false) + ; m_merger_up = llvm::make_unique(target, sources); @@ -934,7 +936,7 @@ void ClangASTSource::FindExternalVisibleDecls( context.m_found.type = true; } } - } while (0); + } while (false); } if (!context.m_found.type) { @@ -985,10 +987,10 @@ void ClangASTSource::FindExternalVisibleDecls( } context.AddNamedDecl(copied_named_decl); - } while (0); + } while (false); } - } while (0); + } while (false); } template class TaggedASTDecl { @@ -1173,7 +1175,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (FindObjCMethodDeclsWithOrigin(current_id, context, original_interface_decl, "at origin")) return; // found it, no need to look any further - } while (0); + } while (false); StreamString ss; @@ -1278,7 +1280,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { if (*cursor == ' ' || *cursor == '(') sc_list.Append(candidate_sc); } - } while (0); + } while (false); if (sc_list.GetSize()) { // We found a good function symbol. Use that. @@ -1361,7 +1363,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { "in debug info"); return; - } while (0); + } while (false); do { // Check the modules only if the debug information didn't have a complete @@ -1388,7 +1390,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { current_id, context, interface_decl_from_modules, "in modules")) return; } - } while (0); + } while (false); do { // Check the runtime only if the debug information didn't have a complete @@ -1425,7 +1427,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { FindObjCMethodDeclsWithOrigin(current_id, context, runtime_interface_decl, "in runtime"); - } while (0); + } while (false); } static bool FindObjCPropertyAndIvarDeclsWithOrigin( @@ -1544,7 +1546,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { complete_iface_decl); return; - } while (0); + } while (false); do { // Check the modules only if the debug information didn't have a complete @@ -1580,7 +1582,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, interface_decl_from_modules)) return; - } while (0); + } while (false); do { // Check the runtime only if the debug information didn't have a complete @@ -1625,7 +1627,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { if (FindObjCPropertyAndIvarDeclsWithOrigin( current_id, context, *this, interface_decl_from_runtime)) return; - } while (0); + } while (false); } typedef llvm::DenseMap FieldOffsetMap; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 496d5b40e3e79..c2ebfe9ce4e2e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -927,7 +927,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( name.GetCString()); context.AddNamedDecl(parser_named_decl); - } while (0); + } while (false); } if (name.GetCString()[0] == '$' && !namespace_decl) { @@ -1562,7 +1562,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( context.m_found.variable = true; } } - } while (0); + } while (false); } if (target && !context.m_found.variable && !namespace_decl) { diff --git a/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index d835d62ad2e07..d7e8e04913426 100644 --- a/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/lldb/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -657,10 +657,10 @@ bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) { if (sub_op) { operand2 = NOT(operand2); - carry_in = 1; + carry_in = true; imm = -imm; // For the Register plug offset context below } else { - carry_in = 0; + carry_in = false; } ProcState proc_state; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 0e26de569e888..93aa07f89165e 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -334,9 +334,9 @@ bool ClassDescriptorV2::Describe( std::unique_ptr class_rw; if (!Read_objc_class(process, objc_class)) - return 0; + return false; if (!Read_class_row(process, *objc_class, class_ro, class_rw)) - return 0; + return false; static ConstString NSObject_name("NSObject"); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index b5cac92213b29..501114ad02810 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -62,7 +62,7 @@ class lldb_private::AppleObjCExternalASTSource non_const_interface_decl->lookup(name); return (result.size() != 0); - } while (0); + } while (false); SetNoExternalVisibleDeclsForName(decl_ctx, name); return false; @@ -208,7 +208,7 @@ class ObjCRuntimeMethodType { uint32_t stepsLeft = 256; - while (1) { + while (true) { if (--stepsLeft == 0) { m_is_valid = false; return; @@ -647,7 +647,7 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append, decls.push_back(iface_decl); ret++; break; - } while (0); + } while (false); return ret; } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 62991dc2095e8..42c14aa9f50cb 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5038,7 +5038,7 @@ ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header, triple.setEnvironmentName(os_env.environment); return arch; } - } while (0); + } while (false); offset = cmd_offset + load_cmd.cmdsize; } diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index ded0983fac794..1a75326f3b208 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -87,7 +87,7 @@ bool CommunicationKDP::SendRequestAndGetReply( for (uint32_t i = 0; i < num_retries; ++i) { if (SendRequestPacketNoLock(request_packet)) { const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; - while (1) { + while (true) { if (WaitForPacketWithTimeoutMicroSecondsNoLock( reply_packet, std::chrono::microseconds(GetPacketTimeout()).count())) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index def7eb2e1eb28..b3c9367861506 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2664,7 +2664,7 @@ bool DWARFASTParserClang::ParseChildMembers( DelayedPropertyList &delayed_properties, AccessType &default_accessibility, bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) { if (!parent_die) - return 0; + return false; // Get the parent byte size so we can verify any members will fit const uint64_t parent_byte_size = @@ -2679,7 +2679,7 @@ bool DWARFASTParserClang::ParseChildMembers( ClangASTContext *ast = llvm::dyn_cast_or_null(class_clang_type.GetTypeSystem()); if (ast == nullptr) - return 0; + return false; for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index c692e8bf18d08..2871017baeccc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2104,7 +2104,7 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, if (die.Tag() == DW_TAG_inlined_subroutine) { inlined_die = die; - while (1) { + while (true) { die = die.GetParent(); if (die) { diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 62321d135646e..55befb4bbcf3f 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -2457,7 +2457,7 @@ bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl, clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); if (lhs_decl_ctx && rhs_decl_ctx) { - while (1) { + while (true) { if (lhs_decl_ctx && rhs_decl_ctx) { const clang::Decl::Kind lhs_decl_ctx_kind = lhs_decl_ctx->getDeclKind(); @@ -2495,7 +2495,7 @@ bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl, // make sure the names match as well lhs_decl_ctx = lhs_decl->getDeclContext(); rhs_decl_ctx = rhs_decl->getDeclContext(); - while (1) { + while (true) { switch (lhs_decl_ctx->getDeclKind()) { case clang::Decl::TranslationUnit: // We don't care about the translation unit names @@ -9629,7 +9629,7 @@ bool ClangASTContext::DumpTypeValue( break; } } - return 0; + return false; } void ClangASTContext::DumpSummary(lldb::opaque_compiler_type_t type, diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp index 3a9a8f3c4cd83..32d0c47693b0e 100644 --- a/lldb/source/Symbol/ClangASTImporter.cpp +++ b/lldb/source/Symbol/ClangASTImporter.cpp @@ -1018,7 +1018,7 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo( m_source_ctx->getObjCInterfaceType(imported_from_superclass))); - } while (0); + } while (false); } } diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 98061d2d33439..bb9a1a642e422 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -144,7 +144,7 @@ bool CompilerType::IsBlockPointerType( CompilerType *function_pointer_type_ptr) const { if (IsValid()) return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); - return 0; + return false; } bool CompilerType::IsIntegerType(bool &is_signed) const { diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 7b3ea5b27102d..0538a9e351cb9 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -546,7 +546,7 @@ uint32_t Function::GetPrologueByteSize() { // Now calculate the offset to pass the subsequent line 0 entries. uint32_t first_non_zero_line = prologue_end_line_idx; - while (1) { + while (true) { LineEntry line_entry; if (line_table->GetLineEntryAtIndex(first_non_zero_line, line_entry)) { diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index 1b7b3ce54865b..a0b35cf3d0b99 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -729,7 +729,7 @@ bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, uint32_t line_index = 0; bool found = false; - while (1) { + while (true) { LineEntry this_line; line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr, false, &this_line); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 7c668a216a3a2..871eae56d4b49 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -5350,7 +5350,7 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, event_explanation = ts.GetData(); } - } while (0); + } while (false); if (event_explanation) log->Printf("Process::RunThreadPlan(): execution interrupted: %s %s", diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index fd54d4062dfc9..14755f60c5522 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1856,7 +1856,7 @@ size_t Target::ReadCStringFromMemory(const Address &addr, std::string &out_str, out_str.clear(); addr_t curr_addr = addr.GetLoadAddress(this); Address address(addr); - while (1) { + while (true) { size_t length = ReadCStringFromMemory(address, buf, sizeof(buf), error); if (length == 0) break; diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index a8b57c86f5974..39086529c114e 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -853,7 +853,7 @@ bool Thread::ShouldStop(Event *event_ptr) { // Otherwise, don't let the base plan override what the other plans say // to do, since presumably if there were other plans they would know what // to do... - while (1) { + while (true) { if (PlanIsBasePlan(current_plan)) break; @@ -978,7 +978,7 @@ Vote Thread::ShouldReportStop(Event *event_ptr) { } else { Vote thread_vote = eVoteNoOpinion; ThreadPlan *plan_ptr = GetCurrentPlan(); - while (1) { + while (true) { if (plan_ptr->PlanExplainsStop(event_ptr)) { thread_vote = plan_ptr->ShouldReportStop(event_ptr); break; @@ -1298,7 +1298,7 @@ void Thread::DiscardThreadPlans(bool force) { return; } - while (1) { + while (true) { int master_plan_idx; bool discard = true; @@ -1677,7 +1677,7 @@ Status Thread::ReturnFromFrame(lldb::StackFrameSP frame_sp, // FIXME: ValueObject::Cast doesn't currently work correctly, at least not // for scalars. // Turn that back on when that works. - if (/* DISABLES CODE */ (0) && sc.function != nullptr) { + if (/* DISABLES CODE */ (false) && sc.function != nullptr) { Type *function_type = sc.function->GetType(); if (function_type) { CompilerType return_type = diff --git a/lldb/source/Utility/JSON.cpp b/lldb/source/Utility/JSON.cpp index 54b87394505f8..2c3f6229eda11 100644 --- a/lldb/source/Utility/JSON.cpp +++ b/lldb/source/Utility/JSON.cpp @@ -238,7 +238,7 @@ JSONParser::Token JSONParser::GetToken(std::string &value) { break; case '"': { - while (1) { + while (true) { bool was_escaped = false; int escaped_ch = GetEscapedChar(was_escaped); if (escaped_ch == -1) { @@ -453,7 +453,7 @@ JSONValue::SP JSONParser::ParseJSONObject() { std::string value; std::string key; - while (1) { + while (true) { JSONParser::Token token = GetToken(value); if (token == JSONParser::Token::String) { @@ -484,7 +484,7 @@ JSONValue::SP JSONParser::ParseJSONArray() { std::string value; std::string key; - while (1) { + while (true) { JSONValue::SP value_sp = ParseJSONValue(); if (value_sp) array_up->AppendObject(value_sp); diff --git a/lldb/source/Utility/SelectHelper.cpp b/lldb/source/Utility/SelectHelper.cpp index 5b60dea718416..ff21d99e400ab 100644 --- a/lldb/source/Utility/SelectHelper.cpp +++ b/lldb/source/Utility/SelectHelper.cpp @@ -192,7 +192,7 @@ lldb_private::Status SelectHelper::Select() { struct timeval *tv_ptr = nullptr; struct timeval tv = {0, 0}; - while (1) { + while (true) { using namespace std::chrono; // Setup out relative timeout based on the end time if we have one if (m_end_time.hasValue()) { diff --git a/lldb/source/Utility/StructuredData.cpp b/lldb/source/Utility/StructuredData.cpp index c486913d13d6e..0e203f9739d16 100644 --- a/lldb/source/Utility/StructuredData.cpp +++ b/lldb/source/Utility/StructuredData.cpp @@ -51,7 +51,7 @@ static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) { std::string value; std::string key; - while (1) { + while (true) { JSONParser::Token token = json_parser.GetToken(value); if (token == JSONParser::Token::String) { @@ -82,7 +82,7 @@ static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) { std::string value; std::string key; - while (1) { + while (true) { StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); if (value_sp) array_up->AddItem(value_sp); diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index cb02ee0680728..32a734833792c 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -141,7 +141,7 @@ void *kqueue_thread(void *arg) { #endif struct kevent death_event; - while (1) { + while (true) { int n_events = kevent(kq_id, NULL, 0, &death_event, 1, NULL); if (n_events == -1) { if (errno == EINTR) @@ -267,7 +267,7 @@ static void *waitpid_thread(void *arg) { #endif #endif - while (1) { + while (true) { pid_t child_pid = waitpid(pid, &status, 0); DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, " "&status, 0) => %i, status = %i, errno = %i", diff --git a/lldb/tools/debugserver/source/JSON.cpp b/lldb/tools/debugserver/source/JSON.cpp index 548ee14079527..1b37767256d7c 100644 --- a/lldb/tools/debugserver/source/JSON.cpp +++ b/lldb/tools/debugserver/source/JSON.cpp @@ -271,7 +271,7 @@ JSONParser::Token JSONParser::GetToken(std::string &value) { break; case '"': { - while (1) { + while (true) { bool was_escaped = false; int escaped_ch = GetEscapedChar(was_escaped); if (escaped_ch == -1) { @@ -483,7 +483,7 @@ JSONValue::SP JSONParser::ParseJSONObject() { std::string value; std::string key; - while (1) { + while (true) { JSONParser::Token token = GetToken(value); if (token == JSONParser::Token::String) { @@ -515,7 +515,7 @@ JSONValue::SP JSONParser::ParseJSONArray() { std::string value; std::string key; - while (1) { + while (true) { JSONValue::SP value_sp = ParseJSONValue(); if (value_sp) array_up->AppendObject(value_sp); diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index 8d2165b0f2435..0fa4437843a62 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -214,7 +214,7 @@ bool MachThreadList::RestoreRegisterState(nub_thread_t tid, uint32_t save_id) { MachThreadSP thread_sp(GetThreadByID(tid)); if (thread_sp) return thread_sp->RestoreRegisterState(save_id); - return 0; + return false; } nub_size_t MachThreadList::NumThreads() const { diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 16c15f64c25ea..3a4035b0b9b3f 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -4263,7 +4263,7 @@ rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) { } if (interval_usec == 0) { - enable = 0; + enable = false; } DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type); @@ -5174,7 +5174,7 @@ bool get_array_of_ints_value_for_key_name_from_json( while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) c++; - while (1) { + while (true) { if (!isdigit(*c)) { return true; } @@ -6109,7 +6109,7 @@ rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) { cstr = data.GetCStr(&offset); if (cstr) { // Skip NULLs - while (1) { + while (true) { const char *p = data.PeekCStr(offset); if ((p == NULL) || (*p != '\0')) break; diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp index 0698d69375f6c..fa19bba58fa79 100644 --- a/lldb/tools/debugserver/source/debugserver.cpp +++ b/lldb/tools/debugserver/source/debugserver.cpp @@ -96,7 +96,7 @@ RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemote *remote) { RNBContext::event_read_thread_exiting; // Spin waiting to get the A packet. - while (1) { + while (true) { DNBLogThreadedIf(LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", __FUNCTION__, event_mask); diff --git a/lldb/tools/debugserver/source/libdebugserver.cpp b/lldb/tools/debugserver/source/libdebugserver.cpp index 0b40dd9049fd0..0c53fa4039c55 100644 --- a/lldb/tools/debugserver/source/libdebugserver.cpp +++ b/lldb/tools/debugserver/source/libdebugserver.cpp @@ -69,7 +69,7 @@ RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemoteSP &remoteSP) { uint32_t event_mask = RNBContext::event_read_packet_available; // Spin waiting to get the A packet. - while (1) { + while (true) { DNBLogThreadedIf(LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", __FUNCTION__, event_mask); From 052f87ae36163cbd2033617eba655af7f1438733 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 24 May 2019 01:03:51 +0000 Subject: [PATCH 0115/1176] Revert r361460 It regresses https://bugs.llvm.org/show_bug.cgi?id=38309 (represented by the testcase test/Transforms/GlobalOpt/globalsra-multigep.ll). llvm-svn: 361581 --- llvm/lib/Transforms/IPO/GlobalOpt.cpp | 27 +++---------------- .../GlobalOpt/globalsra-multigep.ll | 11 ++------ .../Transforms/GlobalOpt/globalsra-struct.ll | 18 ------------- 3 files changed, 6 insertions(+), 50 deletions(-) delete mode 100644 llvm/test/Transforms/GlobalOpt/globalsra-struct.ll diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index c4f268a6511d7..c4fb3ce77f6ee 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -184,7 +184,7 @@ static bool IsSafeComputationToRemove(Value *V, const TargetLibraryInfo *TLI) { /// This GV is a pointer root. Loop over all users of the global and clean up /// any that obviously don't assign the global a value that isn't dynamically /// allocated. -static bool CleanupPointerRootUsers(Value *V, +static bool CleanupPointerRootUsers(GlobalVariable *GV, const TargetLibraryInfo *TLI) { // A brief explanation of leak checkers. The goal is to find bugs where // pointers are forgotten, causing an accumulating growth in memory @@ -202,7 +202,7 @@ static bool CleanupPointerRootUsers(Value *V, SmallVector, 32> Dead; // Constants can't be pointers to dynamically allocated memory. - for (Value::user_iterator UI = V->user_begin(), E = V->user_end(); + for (Value::user_iterator UI = GV->user_begin(), E = GV->user_end(); UI != E;) { User *U = *UI++; if (StoreInst *SI = dyn_cast(U)) { @@ -232,9 +232,6 @@ static bool CleanupPointerRootUsers(Value *V, Dead.push_back(std::make_pair(I, MTI)); } } else if (ConstantExpr *CE = dyn_cast(U)) { - if (CE->getOpcode() == Instruction::GetElementPtr) { - Changed |= CleanupPointerRootUsers(CE, TLI); - } if (CE->use_empty()) { CE->destroyConstant(); Changed = true; @@ -244,7 +241,7 @@ static bool CleanupPointerRootUsers(Value *V, C->destroyConstant(); // This could have invalidated UI, start over from scratch. Dead.clear(); - CleanupPointerRootUsers(V, TLI); + CleanupPointerRootUsers(GV, TLI); return true; } } @@ -394,22 +391,6 @@ static bool isSafeSROAGEP(User *U) { [](User *UU) { return isSafeSROAElementUse(UU); }); } -/// Return true if the specified GEP is a safe user of a derived -/// expression from a global that we want to SROA. -static bool isSafeSubSROAGEP(User *U) { - - // Check to see if this ConstantExpr GEP is SRA'able. In particular, we - // don't like < 3 operand CE's, and we don't like non-constant integer - // indices. This enforces that all uses are 'gep GV, 0, C, ...' for some - // value of C. - if (U->getNumOperands() < 3 || !isa(U->getOperand(1)) || - !cast(U->getOperand(1))->isNullValue()) - return false; - - return llvm::all_of(U->users(), - [](User *UU) { return isSafeSROAElementUse(UU); }); -} - /// Return true if the specified instruction is a safe user of a derived /// expression from a global that we want to SROA. static bool isSafeSROAElementUse(Value *V) { @@ -428,7 +409,7 @@ static bool isSafeSROAElementUse(Value *V) { return SI->getOperand(0) != V; // Otherwise, it must be a GEP. Check it and its users are safe to SRA. - return isa(I) && isSafeSubSROAGEP(I); + return isa(I) && isSafeSROAGEP(I); } /// Look at all uses of the global and decide whether it is safe for us to diff --git a/llvm/test/Transforms/GlobalOpt/globalsra-multigep.ll b/llvm/test/Transforms/GlobalOpt/globalsra-multigep.ll index c32a620c47624..87a8486d8818a 100644 --- a/llvm/test/Transforms/GlobalOpt/globalsra-multigep.ll +++ b/llvm/test/Transforms/GlobalOpt/globalsra-multigep.ll @@ -4,20 +4,13 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @g_data = internal unnamed_addr global <{ [8 x i16], [8 x i16] }> <{ [8 x i16] [i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16], [8 x i16] zeroinitializer }>, align 16 -; We normally cannot SRA here due to the second gep meaning the access to g_data may be to either element, -; unless the value is always zero. -; CHECK: @g_data.0 = internal unnamed_addr constant [8 x i16] [i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16, i16 16], align 16 +; We cannot SRA here due to the second gep meaning the access to g_data may be to either element +; CHECK: @g_data = internal unnamed_addr constant <{ [8 x i16], [8 x i16] }> define i16 @test(i64 %a1) { entry: %g1 = getelementptr inbounds <{ [8 x i16], [8 x i16] }>, <{ [8 x i16], [8 x i16] }>* @g_data, i64 0, i32 0 %arrayidx.i = getelementptr inbounds [8 x i16], [8 x i16]* %g1, i64 0, i64 %a1 %r = load i16, i16* %arrayidx.i, align 2 - -; CHECK-NOT: getelementptr inbounds <{ [8 x i16], [8 x i16] }>, <{ [8 x i16], [8 x i16] }>* @g_data, i64 0, i32 0 -; CHECK: %arrayidx.i = getelementptr inbounds [8 x i16], [8 x i16]* @g_data.0, i64 0, i64 %a1 - ret i16 %r - - } diff --git a/llvm/test/Transforms/GlobalOpt/globalsra-struct.ll b/llvm/test/Transforms/GlobalOpt/globalsra-struct.ll deleted file mode 100644 index 957fba810687a..0000000000000 --- a/llvm/test/Transforms/GlobalOpt/globalsra-struct.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: opt < %s -globalopt -S | FileCheck %s - -%struct.Expr = type { [1 x i32], i32 } - -@e = internal global %struct.Expr zeroinitializer, align 4 -; CHECK-NOT: @e = internal global %struct.Expr zeroinitializer, align 4 - -define dso_local i32 @foo(i32 %i) { -entry: - %i.addr = alloca i32, align 4 - store i32 %i, i32* %i.addr, align 4 - %0 = load i32, i32* %i.addr, align 4 - %arrayidx = getelementptr inbounds [1 x i32], [1 x i32]* getelementptr inbounds (%struct.Expr, %struct.Expr* @e, i32 0, i32 0), i32 0, i32 %0 - store i32 57005, i32* %arrayidx, align 4 - %1 = load i32, i32* getelementptr inbounds (%struct.Expr, %struct.Expr* @e, i32 0, i32 1), align 4 - ret i32 %1 -; CHECK: ret i32 0 -} From 79872a88a0662ee91cdb194a8ea477c79a824e9f Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Fri, 24 May 2019 01:05:52 +0000 Subject: [PATCH 0116/1176] dwarfdump: Add a bit more DWARF64 support This test case was incorrect because it mixed DWARF32 and DWARF64 for a single unit (DWARF32 unit referencing a DWARF64 str_offsets section). So fix enough of the unit parsing for DWARF64 and make the test valid. (not sure if anyone needs DWARF64 support though - support in libDebugInfoDWARF has been added piecemeal and LLVM doesn't produce it at all) llvm-svn: 361582 --- llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h | 11 +++++++---- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 12 ++++++++---- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 13 +++++-------- llvm/test/DebugInfo/X86/dwarfdump-str-offsets.s | 7 ++++--- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index c89451b20278b..4e92df2fdb14f 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -48,7 +48,7 @@ class DWARFUnitHeader { uint32_t Offset = 0; // Version, address size, and DWARF format. dwarf::FormParams FormParams; - uint32_t Length = 0; + uint64_t Length = 0; uint64_t AbbrOffset = 0; // For DWO units only. @@ -82,7 +82,7 @@ class DWARFUnitHeader { uint8_t getDwarfOffsetByteSize() const { return FormParams.getDwarfOffsetByteSize(); } - uint32_t getLength() const { return Length; } + uint64_t getLength() const { return Length; } uint64_t getAbbrOffset() const { return AbbrOffset; } Optional getDWOId() const { return DWOId; } void setDWOId(uint64_t Id) { @@ -97,8 +97,11 @@ class DWARFUnitHeader { return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type; } uint8_t getSize() const { return Size; } - // FIXME: Support DWARF64. - uint32_t getNextUnitOffset() const { return Offset + Length + 4; } + uint32_t getNextUnitOffset() const { + return Offset + Length + + (FormParams.Format == llvm::dwarf::DwarfFormat::DWARF64 ? 4 : 0) + + FormParams.getDwarfOffsetByteSize(); + } }; const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 65b118f6091ac..7bc5221549063 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -242,16 +242,20 @@ bool DWARFUnitHeader::extract(DWARFContext &Context, if (!IndexEntry && Index) IndexEntry = Index->getFromOffset(*offset_ptr); Length = debug_info.getU32(offset_ptr); - // FIXME: Support DWARF64. - unsigned SizeOfLength = 4; FormParams.Format = DWARF32; + unsigned SizeOfLength = 4; + if (Length == 0xffffffff) { + Length = debug_info.getU64(offset_ptr); + FormParams.Format = DWARF64; + SizeOfLength = 8; + } FormParams.Version = debug_info.getU16(offset_ptr); if (FormParams.Version >= 5) { UnitType = debug_info.getU8(offset_ptr); FormParams.AddrSize = debug_info.getU8(offset_ptr); - AbbrOffset = debug_info.getU32(offset_ptr); + AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr); } else { - AbbrOffset = debug_info.getRelocatedValue(4, offset_ptr); + AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr); FormParams.AddrSize = debug_info.getU8(offset_ptr); // Fake a unit type based on the section type. This isn't perfect, // but distinguishing compile and type units is generally enough. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 8fea97aa3c207..c2b3189514a85 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -100,7 +100,7 @@ bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const { bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, bool &isUnitDWARF64) { - uint32_t AbbrOffset, Length; + uint64_t AbbrOffset, Length; uint8_t AddrSize = 0; uint16_t Version; bool Success = true; @@ -114,22 +114,19 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, uint32_t OffsetStart = *Offset; Length = DebugInfoData.getU32(Offset); if (Length == UINT32_MAX) { + Length = DebugInfoData.getU64(Offset); isUnitDWARF64 = true; - OS << format( - "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n", - UnitIndex); - return false; } Version = DebugInfoData.getU16(Offset); if (Version >= 5) { UnitType = DebugInfoData.getU8(Offset); AddrSize = DebugInfoData.getU8(Offset); - AbbrOffset = DebugInfoData.getU32(Offset); + AbbrOffset = isUnitDWARF64 ? DebugInfoData.getU64(Offset) : DebugInfoData.getU32(Offset); ValidType = dwarf::isUnitType(UnitType); } else { UnitType = 0; - AbbrOffset = DebugInfoData.getU32(Offset); + AbbrOffset = isUnitDWARF64 ? DebugInfoData.getU64(Offset) : DebugInfoData.getU32(Offset); AddrSize = DebugInfoData.getU8(Offset); } @@ -157,7 +154,7 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, if (!ValidAddrSize) note() << "The address size is unsupported.\n"; } - *Offset = OffsetStart + Length + 4; + *Offset = OffsetStart + Length + (isUnitDWARF64 ? 12 : 4); return Success; } diff --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets.s index 230c660850692..064061b5847f6 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets.s @@ -239,18 +239,19 @@ TypeDie: CU1_5_end: # DWARF v5 CU header - .long CU2_5_end-CU2_5_version # Length of Unit + .long 0xffffffff + .quad CU2_5_end-CU2_5_version # Length of Unit CU2_5_version: .short 5 # DWARF version number .byte 1 # DWARF Unit Type .byte 8 # Address Size (in bytes) - .long .debug_abbrev # Offset Into Abbrev. Section + .quad .debug_abbrev # Offset Into Abbrev. Section # The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, # DW_AT_str_offsets and DW_AT_compdir. .byte 1 # Abbreviation code .byte 0 # The index of the producer string .byte 1 # The index of the CU name string - .long .debug_str_offsets_base1 + .quad .debug_str_offsets_base1 .byte 2 # The index of the comp dir string .byte 0 # NULL CU2_5_end: From ecd111533df82d6d39acc7595edcccbe1692d68b Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 24 May 2019 01:08:54 +0000 Subject: [PATCH 0117/1176] Revert "[lldb] followup fix for https://reviews.llvm.org/D62305" This fails on the Windows bot: cannot convert from 'initializer list' to 'lldb::thread_result_t' llvm-svn: 361583 --- lldb/source/Host/common/HostNativeThreadBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp index 091e7b515a602..a5f876a7232af 100644 --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -18,10 +18,10 @@ using namespace lldb; using namespace lldb_private; HostNativeThreadBase::HostNativeThreadBase() - : m_thread(LLDB_INVALID_HOST_THREAD), m_result({}) {} + : m_thread(LLDB_INVALID_HOST_THREAD), m_result(0) {} HostNativeThreadBase::HostNativeThreadBase(thread_t thread) - : m_thread(thread), m_result({}) {} + : m_thread(thread), m_result(0) {} lldb::thread_t HostNativeThreadBase::GetSystemHandle() const { return m_thread; @@ -37,7 +37,7 @@ bool HostNativeThreadBase::IsJoinable() const { void HostNativeThreadBase::Reset() { m_thread = LLDB_INVALID_HOST_THREAD; - m_result = {}; + m_result = 0; } bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { @@ -47,7 +47,7 @@ bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const { lldb::thread_t HostNativeThreadBase::Release() { lldb::thread_t result = m_thread; m_thread = LLDB_INVALID_HOST_THREAD; - m_result = {}; + m_result = 0; return result; } From ed595e8627b37131d1f0146c24655a1825c5cf13 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Fri, 24 May 2019 01:20:34 +0000 Subject: [PATCH 0118/1176] [AArch64] Add nvcast patterns for v2f32 -> v1f64 Summary: Constant stores of f32 values can create such NvCast nodes. Reviewers: t.p.northover Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62285 llvm-svn: 361584 --- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 1 + llvm/test/CodeGen/AArch64/arm64-nvcast.ll | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index f426da4f1c832..8b702901d51a9 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -6203,6 +6203,7 @@ def : Pat<(v4i16 (AArch64NvCast (v2f32 FPR64:$src))), (v4i16 FPR64:$src)>; def : Pat<(v2i32 (AArch64NvCast (v2f32 FPR64:$src))), (v2i32 FPR64:$src)>; def : Pat<(v2f32 (AArch64NvCast (v2f32 FPR64:$src))), (v2f32 FPR64:$src)>; def : Pat<(v1i64 (AArch64NvCast (v2f32 FPR64:$src))), (v1i64 FPR64:$src)>; +def : Pat<(v1f64 (AArch64NvCast (v2f32 FPR64:$src))), (v1f64 FPR64:$src)>; // Natural vector casts (128 bit) def : Pat<(v16i8 (AArch64NvCast (v4i32 FPR128:$src))), (v16i8 FPR128:$src)>; diff --git a/llvm/test/CodeGen/AArch64/arm64-nvcast.ll b/llvm/test/CodeGen/AArch64/arm64-nvcast.ll index d9486127bf11c..59b956c7d90c1 100644 --- a/llvm/test/CodeGen/AArch64/arm64-nvcast.ll +++ b/llvm/test/CodeGen/AArch64/arm64-nvcast.ll @@ -47,3 +47,15 @@ entry: store <2 x float> , <2 x float>* bitcast (%"st1"* @_gv to <2 x float>*), align 8 ret void } + +%struct.Vector3 = type { float, float, float } + +define void @nvcast_v2f32_v1f64(%struct.Vector3*) { +; CHECK-LABEL: _nvcast_v2f32_v1f64 +; CHECK: fmov.2s v[[REG:[0-9]+]], #1.00000000 +; CHECK: str d[[REG]], [x0] +entry: + %a13 = bitcast %struct.Vector3* %0 to <1 x double>* + store <1 x double> , <1 x double>* %a13, align 8 + ret void +} From b7a78c7dff18485e5ac85aa8c902571da4b06a33 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 24 May 2019 01:27:20 +0000 Subject: [PATCH 0119/1176] [AArch64] Preserve X8 for thunks ending in variadic musttail calls Summary: On Windows, X8 may be used to pass in the address of an aggregate that is returned indirectly. Therefore, it should be forwarded to variadic musttail calls and preserved in thunks. Fixes PR41997 Reviewers: mgrang, efriedma Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62344 llvm-svn: 361585 --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 6 ++++++ llvm/test/CodeGen/AArch64/vararg-tallcall.ll | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 4b027e9363346..ac656959bcbaa 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -3207,6 +3207,12 @@ SDValue AArch64TargetLowering::LowerFormalArguments( FuncInfo->getForwardedMustTailRegParms(); CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_AArch64_AAPCS); + + // Conservatively forward X8, since it might be used for aggregate return. + if (!CCInfo.isAllocated(AArch64::X8)) { + unsigned X8VReg = MF.addLiveIn(AArch64::X8, &AArch64::GPR64RegClass); + Forwards.push_back(ForwardedRegister(X8VReg, AArch64::X8, MVT::i64)); + } } } diff --git a/llvm/test/CodeGen/AArch64/vararg-tallcall.ll b/llvm/test/CodeGen/AArch64/vararg-tallcall.ll index 2818222680335..56c56213af354 100644 --- a/llvm/test/CodeGen/AArch64/vararg-tallcall.ll +++ b/llvm/test/CodeGen/AArch64/vararg-tallcall.ll @@ -28,7 +28,7 @@ entry: attributes #1 = { noinline optnone "thunk" } ; CHECK: mov v16.16b, v0.16b -; CHECK: ldr x8, [x0] -; CHECK: ldr x8, [x8] +; CHECK: ldr x9, [x0] +; CHECK: ldr x9, [x9] ; CHECK: mov v0.16b, v16.16b -; CHECK: br x8 +; CHECK: br x9 From 4e53032d9bdb2b24e465aa934e083fc507b58a61 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Fri, 24 May 2019 01:34:22 +0000 Subject: [PATCH 0120/1176] [CFG] NFC: Remove implicit conversion from CFGTerminator to Stmt *. Turn it into a variant class instead. This conversion does indeed save some code but there's a plan to add support for more kinds of terminators that aren't necessarily based on statements, and with those in mind it becomes more and more confusing to have CFGTerminators implicitly convertible to a Stmt *. Differential Revision: https://reviews.llvm.org/D61814 llvm-svn: 361586 --- clang/include/clang/Analysis/CFG.h | 57 ++++++++++++------- clang/include/clang/Analysis/ProgramPoint.h | 2 +- clang/lib/Analysis/CFG.cpp | 29 ++++++---- clang/lib/Analysis/CFGStmtMap.cpp | 2 +- clang/lib/Analysis/Consumed.cpp | 2 +- clang/lib/Analysis/LiveVariables.cpp | 2 +- clang/lib/Analysis/ProgramPoint.cpp | 2 +- clang/lib/Analysis/ReachableCode.cpp | 17 +++--- clang/lib/Analysis/ThreadSafety.cpp | 8 +-- clang/lib/Analysis/UninitializedValues.cpp | 2 +- clang/lib/Sema/AnalysisBasedWarnings.cpp | 14 +++-- .../Checkers/UnreachableCodeChecker.cpp | 4 +- clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 4 +- .../Core/BugReporterVisitors.cpp | 6 +- clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | 4 +- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 8 +-- .../lib/StaticAnalyzer/Core/LoopUnrolling.cpp | 2 +- .../StaticAnalyzer/Core/PathDiagnostic.cpp | 2 +- 18 files changed, 95 insertions(+), 72 deletions(-) diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h index 5722cbee860dc..212fd1baef5d6 100644 --- a/clang/include/clang/Analysis/CFG.h +++ b/clang/include/clang/Analysis/CFG.h @@ -494,33 +494,44 @@ class CFGTemporaryDtor : public CFGImplicitDtor { /// Represents CFGBlock terminator statement. /// -/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch -/// in control flow of destructors of temporaries. In this case terminator -/// statement is the same statement that branches control flow in evaluation -/// of matching full expression. class CFGTerminator { - llvm::PointerIntPair Data; +public: + enum Kind { + /// A branch that corresponds to a statement in the code, + /// such as an if-statement. + StmtBranch, + /// A branch in control flow of destructors of temporaries. In this case + /// terminator statement is the same statement that branches control flow + /// in evaluation of matching full expression. + TemporaryDtorsBranch, + + /// Number of different kinds, for sanity checks. We subtract 1 so that + /// to keep receiving compiler warnings when we don't cover all enum values + /// in a switch. + NumKindsMinusOne = TemporaryDtorsBranch + }; + +private: + static constexpr int KindBits = 1; + static_assert((1 << KindBits) > NumKindsMinusOne, + "Not enough room for kind!"); + llvm::PointerIntPair Data; public: - CFGTerminator() = default; - CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false) - : Data(S, TemporaryDtorsBranch) {} + CFGTerminator() { assert(!isValid()); } + CFGTerminator(Stmt *S, Kind K = StmtBranch) : Data(S, K) {} + bool isValid() const { return Data.getOpaqueValue() != nullptr; } Stmt *getStmt() { return Data.getPointer(); } const Stmt *getStmt() const { return Data.getPointer(); } + Kind getKind() const { return static_cast(Data.getInt()); } - bool isTemporaryDtorsBranch() const { return Data.getInt(); } - - operator Stmt *() { return getStmt(); } - operator const Stmt *() const { return getStmt(); } - - Stmt *operator->() { return getStmt(); } - const Stmt *operator->() const { return getStmt(); } - - Stmt &operator*() { return *getStmt(); } - const Stmt &operator*() const { return *getStmt(); } - - explicit operator bool() const { return getStmt(); } + bool isStmtBranch() const { + return getKind() == StmtBranch; + } + bool isTemporaryDtorsBranch() const { + return getKind() == TemporaryDtorsBranch; + } }; /// Represents a single basic block in a source-level CFG. @@ -836,8 +847,10 @@ class CFGBlock { void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; } void setHasNoReturnElement() { HasNoReturnElement = true; } - CFGTerminator getTerminator() { return Terminator; } - const CFGTerminator getTerminator() const { return Terminator; } + CFGTerminator getTerminator() const { return Terminator; } + + Stmt *getTerminatorStmt() { return Terminator.getStmt(); } + const Stmt *getTerminatorStmt() const { return Terminator.getStmt(); } Stmt *getTerminatorCondition(bool StripParens = true); diff --git a/clang/include/clang/Analysis/ProgramPoint.h b/clang/include/clang/Analysis/ProgramPoint.h index 5b554c150947d..ffc2a82d9e08e 100644 --- a/clang/include/clang/Analysis/ProgramPoint.h +++ b/clang/include/clang/Analysis/ProgramPoint.h @@ -257,7 +257,7 @@ class BlockExit : public ProgramPoint { } const Stmt *getTerminator() const { - return getBlock()->getTerminator(); + return getBlock()->getTerminatorStmt(); } private: diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 0928fa27866d6..915e5cc222f5b 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1956,7 +1956,7 @@ void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk, = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C); for (LocalScope::const_iterator I = B; I != E; ++I) InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I, - Blk->getTerminator()); + Blk->getTerminatorStmt()); } /// prependAutomaticObjLifetimeWithTerminator - Prepend lifetime CFGElements for @@ -1971,8 +1971,10 @@ void CFGBuilder::prependAutomaticObjLifetimeWithTerminator( BumpVectorContext &C = cfg->getBumpVectorContext(); CFGBlock::iterator InsertPos = Blk->beginLifetimeEndsInsert(Blk->end(), B.distance(E), C); - for (LocalScope::const_iterator I = B; I != E; ++I) - InsertPos = Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminator()); + for (LocalScope::const_iterator I = B; I != E; ++I) { + InsertPos = + Blk->insertLifetimeEnds(InsertPos, *I, Blk->getTerminatorStmt()); + } } /// prependAutomaticObjScopeEndWithTerminator - Prepend scope end CFGElements for @@ -1991,7 +1993,7 @@ CFGBuilder::prependAutomaticObjScopeEndWithTerminator( LocalScope::const_iterator PlaceToInsert = B; for (LocalScope::const_iterator I = B; I != E; ++I) PlaceToInsert = I; - Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminator()); + Blk->insertScopeEnd(InsertPos, *PlaceToInsert, Blk->getTerminatorStmt()); return *PlaceToInsert; } @@ -4612,7 +4614,8 @@ void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context, } assert(Context.TerminatorExpr); CFGBlock *Decision = createBlock(false); - Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, true)); + Decision->setTerminator(CFGTerminator(Context.TerminatorExpr, + CFGTerminator::TemporaryDtorsBranch)); addSuccessor(Decision, Block, !Context.KnownExecuted.isFalse()); addSuccessor(Decision, FalseSucc ? FalseSucc : Context.Succ, !Context.KnownExecuted.isTrue()); @@ -4820,7 +4823,7 @@ bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F, // If the 'To' has no label or is labeled but the label isn't a // CaseStmt then filter this edge. if (const SwitchStmt *S = - dyn_cast_or_null(From->getTerminator().getStmt())) { + dyn_cast_or_null(From->getTerminatorStmt())) { if (S->isAllEnumCasesCovered()) { const Stmt *L = To->getLabel(); if (!L || !isa(L)) @@ -5055,9 +5058,15 @@ class CFGBlockTerminatorPrint public: void print(CFGTerminator T) { - if (T.isTemporaryDtorsBranch()) + switch (T.getKind()) { + case CFGTerminator::StmtBranch: + Visit(T.getStmt()); + break; + case CFGTerminator::TemporaryDtorsBranch: OS << "(Temp Dtor) "; - Visit(T.getStmt()); + Visit(T.getStmt()); + break; + } } }; @@ -5366,7 +5375,7 @@ static void print_block(raw_ostream &OS, const CFG* cfg, } // Print the terminator of this block. - if (B.getTerminator()) { + if (B.getTerminator().isValid()) { if (ShowColors) OS.changeColor(raw_ostream::GREEN); @@ -5519,7 +5528,7 @@ void CFGBlock::printTerminator(raw_ostream &OS, } Stmt *CFGBlock::getTerminatorCondition(bool StripParens) { - Stmt *Terminator = this->Terminator; + Stmt *Terminator = getTerminatorStmt(); if (!Terminator) return nullptr; diff --git a/clang/lib/Analysis/CFGStmtMap.cpp b/clang/lib/Analysis/CFGStmtMap.cpp index eab2fafb54699..d1c23e3c879b4 100644 --- a/clang/lib/Analysis/CFGStmtMap.cpp +++ b/clang/lib/Analysis/CFGStmtMap.cpp @@ -70,7 +70,7 @@ static void Accumulate(SMap &SM, CFGBlock *B) { // Finally, look at the terminator. If the terminator was already added // because it is a block-level expression in another block, overwrite // that mapping. - if (Stmt *Term = B->getTerminator()) + if (Stmt *Term = B->getTerminatorStmt()) SM[Term] = B; } diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index 112ef5f91f337..eee36d9caf7f1 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -76,7 +76,7 @@ static SourceLocation getFirstStmtLoc(const CFGBlock *Block) { static SourceLocation getLastStmtLoc(const CFGBlock *Block) { // Find the source location of the last statement in the block, if the block // is not empty. - if (const Stmt *StmtNode = Block->getTerminator()) { + if (const Stmt *StmtNode = Block->getTerminatorStmt()) { return StmtNode->getBeginLoc(); } else { for (CFGBlock::const_reverse_iterator BI = Block->rbegin(), diff --git a/clang/lib/Analysis/LiveVariables.cpp b/clang/lib/Analysis/LiveVariables.cpp index e435ff2ee170c..2cd607d8a4932 100644 --- a/clang/lib/Analysis/LiveVariables.cpp +++ b/clang/lib/Analysis/LiveVariables.cpp @@ -501,7 +501,7 @@ LiveVariablesImpl::runOnBlock(const CFGBlock *block, TransferFunctions TF(*this, val, obs, block); // Visit the terminator (if any). - if (const Stmt *term = block->getTerminator()) + if (const Stmt *term = block->getTerminatorStmt()) TF.Visit(const_cast(term)); // Apply the transfer function for all Stmts in the block. diff --git a/clang/lib/Analysis/ProgramPoint.cpp b/clang/lib/Analysis/ProgramPoint.cpp index 828388716ea0a..697d2e57cedb3 100644 --- a/clang/lib/Analysis/ProgramPoint.cpp +++ b/clang/lib/Analysis/ProgramPoint.cpp @@ -144,7 +144,7 @@ void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B" << E.getDst()->getBlockID() << ')'; - if (const Stmt *T = E.getSrc()->getTerminator()) { + if (const Stmt *T = E.getSrc()->getTerminatorStmt()) { SourceLocation SLoc = T->getBeginLoc(); Out << "\\|Terminator: "; diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp index f3bc0c7d8a531..2fea88ea2eff4 100644 --- a/clang/lib/Analysis/ReachableCode.cpp +++ b/clang/lib/Analysis/ReachableCode.cpp @@ -48,7 +48,7 @@ static bool isTrivialExpression(const Expr *Ex) { static bool isTrivialDoWhile(const CFGBlock *B, const Stmt *S) { // Check if the block ends with a do...while() and see if 'S' is the // condition. - if (const Stmt *Term = B->getTerminator()) { + if (const Stmt *Term = B->getTerminatorStmt()) { if (const DoStmt *DS = dyn_cast(Term)) { const Expr *Cond = DS->getCond()->IgnoreParenCasts(); return Cond == S && isTrivialExpression(Cond); @@ -116,7 +116,7 @@ static bool isDeadReturn(const CFGBlock *B, const Stmt *S) { // the call to the destructor. assert(Current->succ_size() == 2); Current = *(Current->succ_begin() + 1); - } else if (!Current->getTerminator() && Current->succ_size() == 1) { + } else if (!Current->getTerminatorStmt() && Current->succ_size() == 1) { // If there is only one successor, we're not dealing with outgoing control // flow. Thus, look into the next block. Current = *Current->succ_begin(); @@ -292,7 +292,7 @@ static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP) { /// Returns true if we should always explore all successors of a block. static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B, Preprocessor &PP) { - if (const Stmt *Term = B->getTerminator()) { + if (const Stmt *Term = B->getTerminatorStmt()) { if (isa(Term)) return true; // Specially handle '||' and '&&'. @@ -461,12 +461,11 @@ const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) { return S; } - if (CFGTerminator T = Block->getTerminator()) { - if (!T.isTemporaryDtorsBranch()) { - const Stmt *S = T.getStmt(); - if (isValidDeadStmt(S)) - return S; - } + CFGTerminator T = Block->getTerminator(); + if (T.isStmtBranch()) { + const Stmt *S = T.getStmt(); + if (S && isValidDeadStmt(S)) + return S; } return nullptr; diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index bd65ea711b9fb..c7b4c4455664a 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -815,7 +815,7 @@ static void findBlockLocations(CFG *CFGraph, // Find the source location of the last statement in the block, if the // block is not empty. - if (const Stmt *S = CurrBlock->getTerminator()) { + if (const Stmt *S = CurrBlock->getTerminatorStmt()) { CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getBeginLoc(); } else { for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(), @@ -1499,7 +1499,7 @@ void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result, const Stmt *Cond = PredBlock->getTerminatorCondition(); // We don't acquire try-locks on ?: branches, only when its result is used. - if (!Cond || isa(PredBlock->getTerminator())) + if (!Cond || isa(PredBlock->getTerminatorStmt())) return; bool Negate = false; @@ -2402,7 +2402,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { // a difference in locksets is probably due to a bug in that block, rather // than in some other predecessor. In that case, keep the other // predecessor's lockset. - if (const Stmt *Terminator = (*PI)->getTerminator()) { + if (const Stmt *Terminator = (*PI)->getTerminatorStmt()) { if (isa(Terminator) || isa(Terminator)) { SpecialBlocks.push_back(*PI); continue; @@ -2441,7 +2441,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) { // it might also be part of a switch. Also, a subsequent destructor // might add to the lockset, in which case the real issue might be a // double lock on the other path. - const Stmt *Terminator = PrevBlock->getTerminator(); + const Stmt *Terminator = PrevBlock->getTerminatorStmt(); bool IsLoop = Terminator && isa(Terminator); FactSet PrevLockset; diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp index 96f4cc51b7a12..cea401ab5c3f7 100644 --- a/clang/lib/Analysis/UninitializedValues.cpp +++ b/clang/lib/Analysis/UninitializedValues.cpp @@ -651,7 +651,7 @@ class TransferFunctions : public StmtVisitor { // uninitialized. for (const auto *Block : cfg) { unsigned BlockID = Block->getBlockID(); - const Stmt *Term = Block->getTerminator(); + const Stmt *Term = Block->getTerminatorStmt(); if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() && Term) { // This block inevitably leads to the use. If we have an edge from here diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 6c95b6000380b..bac407b832e15 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -398,7 +398,8 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { for (const auto *B : *cfg) { if (!live[B->getBlockID()]) { if (B->pred_begin() == B->pred_end()) { - if (B->getTerminator() && isa(B->getTerminator())) + const Stmt *Term = B->getTerminatorStmt(); + if (Term && isa(Term)) // When not adding EH edges from calls, catch clauses // can otherwise seem dead. Avoid noting them as dead. count += reachable_code::ScanReachableFromBlock(B, live); @@ -446,7 +447,8 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { // No more CFGElements in the block? if (ri == re) { - if (B.getTerminator() && isa(B.getTerminator())) { + const Stmt *Term = B.getTerminatorStmt(); + if (Term && isa(Term)) { HasAbnormalEdge = true; continue; } @@ -1077,7 +1079,7 @@ namespace { BlockQueue.pop_front(); if (!P) continue; - const Stmt *Term = P->getTerminator(); + const Stmt *Term = P->getTerminatorStmt(); if (Term && isa(Term)) continue; // Switch statement, good. @@ -1175,7 +1177,7 @@ namespace { } static const Stmt *getLastStmt(const CFGBlock &B) { - if (const Stmt *Term = B.getTerminator()) + if (const Stmt *Term = B.getTerminatorStmt()) return Term; for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), ElemEnd = B.rend(); @@ -1281,11 +1283,11 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, if (L.isMacroID()) continue; if (S.getLangOpts().CPlusPlus11) { - const Stmt *Term = B->getTerminator(); + const Stmt *Term = B->getTerminatorStmt(); // Skip empty cases. while (B->empty() && !Term && B->succ_size() == 1) { B = *B->succ_begin(); - Term = B->getTerminator(); + Term = B->getTerminatorStmt(); } if (!(B->empty() && Term && isa(Term))) { Preprocessor &PP = S.getPreprocessor(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp index 76854e0382e29..0b0bf8465c9dd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp @@ -204,7 +204,7 @@ const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) { return S->getStmt(); } } - if (const Stmt *S = CB->getTerminator()) + if (const Stmt *S = CB->getTerminatorStmt()) return S; else return nullptr; @@ -250,7 +250,7 @@ bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB, bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) { return CB->getLabel() == nullptr // No labels && CB->size() == 0 // No statements - && !CB->getTerminator(); // No terminator + && !CB->getTerminatorStmt(); // No terminator } void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 168050955f2ef..cc93675344e14 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -678,7 +678,7 @@ void generateMinimalDiagForBlockEdge(const ExplodedNode *N, BlockEdge BE, const LocationContext *LC = N->getLocationContext(); const CFGBlock *Src = BE.getSrc(); const CFGBlock *Dst = BE.getDst(); - const Stmt *T = Src->getTerminator(); + const Stmt *T = Src->getTerminatorStmt(); if (!T) return; @@ -1203,7 +1203,7 @@ static void generatePathDiagnosticsForNode(const ExplodedNode *N, const CFGBlock *BSrc = BE->getSrc(); ParentMap &PM = PDB.getParentMap(); - if (const Stmt *Term = BSrc->getTerminator()) { + if (const Stmt *Term = BSrc->getTerminatorStmt()) { // Are we jumping past the loop body without ever executing the // loop (because the condition was false)? if (isLoop(Term)) { diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 0c48c430a2cec..bc34472020c40 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1494,7 +1494,7 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ, return nullptr; CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap(); - CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminator(); + CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt(); } else { return nullptr; } @@ -1566,7 +1566,7 @@ static const Expr *peelOffOuterExpr(const Expr *Ex, ProgramPoint ProgPoint = NI->getLocation(); if (Optional BE = ProgPoint.getAs()) { const CFGBlock *srcBlk = BE->getSrc(); - if (const Stmt *term = srcBlk->getTerminator()) { + if (const Stmt *term = srcBlk->getTerminatorStmt()) { if (term == CO) { bool TookTrueBranch = (*(srcBlk->succ_begin()) == BE->getDst()); if (TookTrueBranch) @@ -1852,7 +1852,7 @@ ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, // here by looking at the state transition. if (Optional BE = progPoint.getAs()) { const CFGBlock *srcBlk = BE->getSrc(); - if (const Stmt *term = srcBlk->getTerminator()) + if (const Stmt *term = srcBlk->getTerminatorStmt()) return VisitTerminator(term, N, srcBlk, BE->getDst(), BR, BRC); return nullptr; } diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index cbe997669ba73..ca9a48ef9808c 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -275,14 +275,14 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L, } void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) { - if (const Stmt *Term = B->getTerminator()) { + if (const Stmt *Term = B->getTerminatorStmt()) { switch (Term->getStmtClass()) { default: llvm_unreachable("Analysis for this terminator not implemented."); case Stmt::CXXBindTemporaryExprClass: HandleCleanupTemporaryBranch( - cast(B->getTerminator().getStmt()), B, Pred); + cast(Term), B, Pred); return; // Model static initializers. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 1742921884d60..975af4743927c 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1862,7 +1862,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, // other constraints) then consider completely unrolling it. if(AMgr.options.ShouldUnrollLoops) { unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath; - const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator(); + const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt(); if (Term) { ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(), Pred, maxBlockVisitOnPath); @@ -1883,7 +1883,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, unsigned int BlockCount = nodeBuilder.getContext().blockCount(); if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 && AMgr.options.ShouldWidenLoops) { - const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator(); + const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt(); if (!(Term && (isa(Term) || isa(Term) || isa(Term)))) return; @@ -2008,8 +2008,8 @@ static const Stmt *ResolveCondition(const Stmt *Condition, if (!BO || !BO->isLogicalOp()) return Condition; - assert(!B->getTerminator().isTemporaryDtorsBranch() && - "Temporary destructor branches handled by processBindTemporary."); + assert(B->getTerminator().isStmtBranch() && + "Other kinds of branches are handled separately!"); // For logical operations, we still have the case where some branches // use the traditional "merge" approach and others sink the branch diff --git a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp index ae9e073416da6..9838249ae82ca 100644 --- a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp +++ b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp @@ -234,7 +234,7 @@ bool madeNewBranch(ExplodedNode *N, const Stmt *LoopStmt) { ProgramPoint P = N->getLocation(); if (Optional BE = P.getAs()) - S = BE->getBlock()->getTerminator(); + S = BE->getBlock()->getTerminatorStmt(); if (S == LoopStmt) return false; diff --git a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index cc1e7e1798f54..9032068892100 100644 --- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -794,7 +794,7 @@ const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) { if (auto SP = P.getAs()) return SP->getStmt(); if (auto BE = P.getAs()) - return BE->getSrc()->getTerminator(); + return BE->getSrc()->getTerminatorStmt(); if (auto CE = P.getAs()) return CE->getCallExpr(); if (auto CEE = P.getAs()) From 1293de8b1733e85d13960c150b86a1fe3813ae3f Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Fri, 24 May 2019 01:34:26 +0000 Subject: [PATCH 0121/1176] [CFG] NFC: Modernize a test file for constructor initializer CFGs. Move FileCheck directives around so that it was easy to understand what tests what and what effect do changes have. Differential Revision: https://reviews.llvm.org/D61815 llvm-svn: 361587 --- .../test/Analysis/initializers-cfg-output.cpp | 222 ++++++++++++------ 1 file changed, 151 insertions(+), 71 deletions(-) diff --git a/clang/test/Analysis/initializers-cfg-output.cpp b/clang/test/Analysis/initializers-cfg-output.cpp index 8d1039ddf34ed..a69e78faeda08 100644 --- a/clang/test/Analysis/initializers-cfg-output.cpp +++ b/clang/test/Analysis/initializers-cfg-output.cpp @@ -12,22 +12,84 @@ class A { public: + // CHECK: A() + // CHECK: [B1 (ENTRY)] + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 A() {} + + // CHECK: A(int i) + // CHECK: [B1 (ENTRY)] + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 A(int i) {} }; class B : public virtual A { public: + // CHECK: B() + // CHECK: [B2 (ENTRY)] + // CHECK-NEXT: Succs (1): B1 + // CHECK: [B1] + // WARNINGS-NEXT: 1: (CXXConstructExpr, class A) + // ANALYZER-NEXT: 1: (CXXConstructExpr, A() (Base initializer), class A) + // CHECK-NEXT: 2: A([B1.1]) (Base initializer) + // CHECK-NEXT: Preds (1): B2 + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 B() {} + + // CHECK: B(int i) + // CHECK: [B2 (ENTRY)] + // CHECK-NEXT: Succs (1): B1 + // CHECK: [B1] + // CHECK-NEXT: 1: i + // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) + // WARNINGS-NEXT: 3: [B1.2] (CXXConstructExpr, class A) + // ANALYZER-NEXT: 3: [B1.2] (CXXConstructExpr, A([B1.2]) (Base initializer), class A) + // CHECK-NEXT: 4: A([B1.3]) (Base initializer) + // CHECK-NEXT: Preds (1): B2 + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 B(int i) : A(i) {} }; class C : public virtual A { public: + // CHECK: C() + // CHECK: [B2 (ENTRY)] + // CHECK-NEXT: Succs (1): B1 + // CHECK: [B1] + // WARNINGS-NEXT: 1: (CXXConstructExpr, class A) + // ANALYZER-NEXT: 1: (CXXConstructExpr, A() (Base initializer), class A) + // CHECK-NEXT: 2: A([B1.1]) (Base initializer) + // CHECK-NEXT: Preds (1): B2 + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 C() {} + + // CHECK: C(int i) + // CHECK: [B2 (ENTRY)] + // CHECK-NEXT: Succs (1): B1 + // CHECK: [B1] + // CHECK-NEXT: 1: i + // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) + // WARNINGS-NEXT: 3: [B1.2] (CXXConstructExpr, class A) + // ANALYZER-NEXT: 3: [B1.2] (CXXConstructExpr, A([B1.2]) (Base initializer), class A) + // CHECK-NEXT: 4: A([B1.3]) (Base initializer) + // CHECK-NEXT: Preds (1): B2 + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 C(int i) : A(i) {} }; + class TestOrder : public C, public B, public A { int i; int& r; @@ -35,6 +97,34 @@ class TestOrder : public C, public B, public A { TestOrder(); }; +// CHECK: TestOrder::TestOrder() +// CHECK: [B2 (ENTRY)] +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B1] +// WARNINGS-NEXT: 1: (CXXConstructExpr, class A) +// ANALYZER-NEXT: 1: (CXXConstructExpr, A() (Base initializer), class A) +// CHECK-NEXT: 2: A([B1.1]) (Base initializer) +// WARNINGS-NEXT: 3: (CXXConstructExpr, class C) +// ANALYZER-NEXT: 3: (CXXConstructExpr, C() (Base initializer), class C) +// CHECK-NEXT: 4: C([B1.3]) (Base initializer) +// WARNINGS-NEXT: 5: (CXXConstructExpr, class B) +// ANALYZER-NEXT: 5: (CXXConstructExpr, B() (Base initializer), class B) +// CHECK-NEXT: 6: B([B1.5]) (Base initializer) +// WARNINGS-NEXT: 7: (CXXConstructExpr, class A) +// ANALYZER-NEXT: 7: (CXXConstructExpr, A() (Base initializer), class A) +// CHECK-NEXT: 8: A([B1.7]) (Base initializer) +// CHECK-NEXT: 9: /*implicit*/(int)0 +// CHECK-NEXT: 10: i([B1.9]) (Member initializer) +// CHECK-NEXT: 11: this +// CHECK-NEXT: 12: [B1.11]->i +// CHECK-NEXT: 13: r([B1.12]) (Member initializer) +// WARNINGS-NEXT: 14: (CXXConstructExpr, class A) +// ANALYZER-NEXT: 14: (CXXConstructExpr, [B1.15], class A) +// CHECK-NEXT: 15: A a; +// CHECK-NEXT: Preds (1): B2 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 TestOrder::TestOrder() : r(i), B(), i(), C() { A a; @@ -46,6 +136,37 @@ class TestControlFlow { TestControlFlow(bool b); }; +// CHECK: TestControlFlow::TestControlFlow(bool b) +// CHECK: [B5 (ENTRY)] +// CHECK-NEXT: Succs (1): B4 +// CHECK: [B1] +// CHECK-NEXT: 1: [B4.4] ? [B2.1] : [B3.1] +// CHECK-NEXT: 2: y([B1.1]) (Member initializer) +// CHECK-NEXT: 3: this +// CHECK-NEXT: 4: [B1.3]->y +// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: 6: z([B1.5]) (Member initializer) +// CHECK-NEXT: 7: int v; +// CHECK-NEXT: Preds (2): B2 B3 +// CHECK-NEXT: Succs (1): B0 +// CHECK: [B2] +// CHECK-NEXT: 1: 0 +// CHECK-NEXT: Preds (1): B4 +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B3] +// CHECK-NEXT: 1: 1 +// CHECK-NEXT: Preds (1): B4 +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B4] +// CHECK-NEXT: 1: 0 +// CHECK-NEXT: 2: x([B4.1]) (Member initializer) +// CHECK-NEXT: 3: b +// CHECK-NEXT: 4: [B4.3] (ImplicitCastExpr, LValueToRValue, _Bool) +// CHECK-NEXT: T: [B4.4] ? ... : ... +// CHECK-NEXT: Preds (1): B5 +// CHECK-NEXT: Succs (2): B2 B3 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 TestControlFlow::TestControlFlow(bool b) : y(b ? 0 : 1) , x(0) @@ -55,77 +176,36 @@ TestControlFlow::TestControlFlow(bool b) class TestDelegating { int x, z; - public: +public: + + // CHECK: TestDelegating() + // CHECK: [B2 (ENTRY)] + // CHECK-NEXT: Succs (1): B1 + // CHECK: [B1] + // CHECK-NEXT: 1: 2 + // CHECK-NEXT: 2: 3 + // WARNINGS-NEXT: 3: [B1.1], [B1.2] (CXXConstructExpr, class TestDelegating) + // ANALYZER-NEXT: 3: [B1.1], [B1.2] (CXXConstructExpr, TestDelegating([B1.1], [B1.2]) (Delegating initializer), class TestDelegating) + // CHECK-NEXT: 4: TestDelegating([B1.3]) (Delegating initializer) + // CHECK-NEXT: Preds (1): B2 + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 TestDelegating() : TestDelegating(2, 3) {} + + // CHECK: TestDelegating(int x, int z) + // CHECK: [B2 (ENTRY)] + // CHECK-NEXT: Succs (1): B1 + // CHECK: [B1] + // CHECK-NEXT: 1: x + // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int) + // CHECK-NEXT: 3: x([B1.2]) (Member initializer) + // CHECK-NEXT: 4: z + // CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, LValueToRValue, int) + // CHECK-NEXT: 6: z([B1.5]) (Member initializer) + // CHECK-NEXT: Preds (1): B2 + // CHECK-NEXT: Succs (1): B0 + // CHECK: [B0 (EXIT)] + // CHECK-NEXT: Preds (1): B1 TestDelegating(int x, int z) : x(x), z(z) {} }; - -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 -// CHECK: [B1] -// WARNINGS: 1: (CXXConstructExpr, class A) -// ANALYZER: 1: (CXXConstructExpr, A() (Base initializer), class A) -// CHECK: 2: A([B1.1]) (Base initializer) -// WARNINGS: 3: (CXXConstructExpr, class C) -// ANALYZER: 3: (CXXConstructExpr, C() (Base initializer), class C) -// CHECK: 4: C([B1.3]) (Base initializer) -// WARNINGS: 5: (CXXConstructExpr, class B) -// ANALYZER: 5: (CXXConstructExpr, B() (Base initializer), class B) -// CHECK: 6: B([B1.5]) (Base initializer) -// WARNINGS: 7: (CXXConstructExpr, class A) -// ANALYZER: 7: (CXXConstructExpr, A() (Base initializer), class A) -// CHECK: 8: A([B1.7]) (Base initializer) -// CHECK: 9: /*implicit*/(int)0 -// CHECK: 10: i([B1.9]) (Member initializer) -// CHECK: 11: this -// CHECK: 12: [B1.11]->i -// CHECK: 13: r([B1.12]) (Member initializer) -// WARNINGS: 14: (CXXConstructExpr, class A) -// ANALYZER: 14: (CXXConstructExpr, [B1.15], class A) -// CHECK: 15: A a; -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 -// CHECK: [B0 (EXIT)] -// CHECK: Preds (1): B1 -// CHECK: [B5 (ENTRY)] -// CHECK: Succs (1): B4 -// CHECK: [B1] -// CHECK: 1: [B4.4] ? [B2.1] : [B3.1] -// CHECK: 2: y([B1.1]) (Member initializer) -// CHECK: 3: this -// CHECK: 4: [B1.3]->y -// CHECK: 5: [B1.4] (ImplicitCastExpr, LValueToRValue, int) -// CHECK: 6: z([B1.5]) (Member initializer) -// CHECK: 7: int v; -// CHECK: Preds (2): B2 B3 -// CHECK: Succs (1): B0 -// CHECK: [B2] -// CHECK: 1: 0 -// CHECK: Preds (1): B4 -// CHECK: Succs (1): B1 -// CHECK: [B3] -// CHECK: 1: 1 -// CHECK: Preds (1): B4 -// CHECK: Succs (1): B1 -// CHECK: [B4] -// CHECK: 1: 0 -// CHECK: 2: x([B4.1]) (Member initializer) -// CHECK: 3: b -// CHECK: 4: [B4.3] (ImplicitCastExpr, LValueToRValue, _Bool) -// CHECK: T: [B4.4] ? ... : ... -// CHECK: Preds (1): B5 -// CHECK: Succs (2): B2 B3 -// CHECK: [B0 (EXIT)] -// CHECK: Preds (1): B1 -// CHECK: [B2 (ENTRY)] -// CHECK: Succs (1): B1 -// CHECK: [B1] -// CHECK: 1: 2 -// CHECK: 2: 3 -// WARNINGS: 3: [B1.1], [B1.2] (CXXConstructExpr, class TestDelegating) -// ANALYZER: 3: [B1.1], [B1.2] (CXXConstructExpr, TestDelegating([B1.1], [B1.2]) (Delegating initializer), class TestDelegating) -// CHECK: 4: TestDelegating([B1.3]) (Delegating initializer) -// CHECK: Preds (1): B2 -// CHECK: Succs (1): B0 -// CHECK: [B0 (EXIT)] -// CHECK: Preds (1): B1 From 8458c9ef42390b3042765c33b09b4ade0e9c22fc Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 24 May 2019 01:35:07 +0000 Subject: [PATCH 0122/1176] Factor out repeated code to build 'this' expressions and mark them referenced. llvm-svn: 361588 --- clang/include/clang/Sema/Sema.h | 4 ++++ clang/lib/Sema/SemaExprCXX.cpp | 16 +++++++++++++--- clang/lib/Sema/SemaExprMember.cpp | 6 ++---- clang/lib/Sema/SemaOverload.cpp | 6 ++---- clang/lib/Sema/TreeTransform.h | 8 ++++---- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ddf393d46e21f..60480d98bebe3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5223,6 +5223,10 @@ class Sema { //// ActOnCXXThis - Parse 'this' pointer. ExprResult ActOnCXXThis(SourceLocation loc); + /// Build a CXXThisExpr and mark it referenced in the current context. + Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); + void MarkThisReferenced(CXXThisExpr *This); + /// Try to retrieve the type of the 'this' pointer. /// /// \returns The type of 'this', if possible. Otherwise, returns a NULL type. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 455a71bd0ac0a..e3286e8943f2a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1298,10 +1298,20 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { /// which the function is called. QualType ThisTy = getCurrentThisType(); - if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use); + if (ThisTy.isNull()) + return Diag(Loc, diag::err_invalid_this_use); + return BuildCXXThisExpr(Loc, ThisTy, /*isImplicit=*/false); +} + +Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, + bool IsImplicit) { + auto *This = new (Context) CXXThisExpr(Loc, Type, IsImplicit); + MarkThisReferenced(This); + return This; +} - CheckCXXThisCapture(Loc); - return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false); +void Sema::MarkThisReferenced(CXXThisExpr *This) { + CheckCXXThisCapture(This->getExprLoc()); } bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index b07bba5584bdd..3d7b8db2f6710 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1092,8 +1092,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); - CheckCXXThisCapture(Loc); - BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true); + BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*isImplicit=*/true); } // Check the use of this member. @@ -1836,8 +1835,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); - CheckCXXThisCapture(Loc); - baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true); + baseExpr = BuildCXXThisExpr(loc, ThisTy, /*isImplicit=*/true); } return BuildMemberReferenceExpr(baseExpr, ThisTy, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index eadc01e5efb6b..e5cbd1d0a81c0 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -13910,10 +13910,8 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, SourceLocation Loc = MemExpr->getMemberLoc(); if (MemExpr->getQualifier()) Loc = MemExpr->getQualifierLoc().getBeginLoc(); - CheckCXXThisCapture(Loc); - Base = new (Context) CXXThisExpr(Loc, - MemExpr->getBaseType(), - /*isImplicit=*/true); + Base = + BuildCXXThisExpr(Loc, MemExpr->getBaseType(), /*isImplicit=*/true); } } else Base = MemExpr->getBase(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c653fb1d6e2c4..b5114eeef3011 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2697,8 +2697,7 @@ class TreeTransform { ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, QualType ThisType, bool isImplicit) { - getSema().CheckCXXThisCapture(ThisLoc); - return new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, isImplicit); + return getSema().BuildCXXThisExpr(ThisLoc, ThisType, isImplicit); } /// Build a new C++ throw expression. @@ -10355,8 +10354,9 @@ TreeTransform::TransformCXXThisExpr(CXXThisExpr *E) { QualType T = getSema().getCurrentThisType(); if (!getDerived().AlwaysRebuild() && T == E->getType()) { - // Make sure that we capture 'this'. - getSema().CheckCXXThisCapture(E->getBeginLoc()); + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + getSema().MarkThisReferenced(E); return E; } From fc302c2b7f1c224be03caba3a82282a943a31519 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Fri, 24 May 2019 01:41:58 +0000 Subject: [PATCH 0123/1176] dwarfdump: Deterministically... determine whether parsing a DWARF32 or DWARF64 str_offsets header Rather than trying one and then the other - use the kind of the CU to select which kind of header to parse. llvm-svn: 361589 --- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 13 ++++++++++--- .../DebugInfo/X86/dwarfdump-str-offsets-macho.s | 7 ++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 7bc5221549063..fa165cf2d4022 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -811,12 +811,19 @@ DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { auto Offset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base), 0); Optional Descriptor; // Attempt to find a DWARF64 contribution 16 bytes before the base. - if (Offset >= 16) + switch (Header.getFormat()) { + case dwarf::DwarfFormat::DWARF64: + if (Offset < 16) + return None; Descriptor = parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16); - // Try to find a DWARF32 contribution 8 bytes before the base. - if (!Descriptor && Offset >= 8) + break; + case dwarf::DwarfFormat::DWARF32: + if (Offset < 8) + return None; Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8); + break; + } return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor; } diff --git a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-macho.s b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-macho.s index 1332a94ec3c71..10a810a350d19 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-macho.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-str-offsets-macho.s @@ -160,18 +160,19 @@ CU1_5_version: CU1_5_end: # DWARF v5 CU header - .long CU2_5_end-CU2_5_version # Length of Unit + .long 0xffffffff + .quad CU2_5_end-CU2_5_version # Length of Unit CU2_5_version: .short 5 # DWARF version number .byte 1 # DWARF Unit Type .byte 8 # Address Size (in bytes) - .long 0 # Offset Into Abbrev. Section + .quad 0 # Offset Into Abbrev. Section # The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, # DW_AT_str_offsets and DW_AT_compdir. .byte 1 # Abbreviation code .byte 0 # The index of the producer string .byte 1 # The index of the CU name string - .long Ldebug_str_offsets_base1-Ldebug_str_offsets + .quad Ldebug_str_offsets_base1-Ldebug_str_offsets .byte 2 # The index of the comp dir string .byte 0 # NULL CU2_5_end: From 414da9d66a5469e46a804611a2fc2a6fad543484 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 24 May 2019 01:45:47 +0000 Subject: [PATCH 0124/1176] Clarify how musttail can be used to create forwarding thunks llvm-svn: 361590 --- llvm/docs/LangRef.rst | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 5ea27c976d2ae..6311f6f616369 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -10006,12 +10006,16 @@ This instruction requires several arguments: recursive cycle in the call graph. #. Arguments with the :ref:`inalloca ` attribute are forwarded in place. + #. If the musttail call appears in a function with the ``"thunk"`` attribute + and the caller and callee both have varargs, than any unprototyped + arguments in register or memory are forwarded to the callee. Similarly, + the return value of the callee is returned the the caller's caller, even + if a void return type is in use. Both markers imply that the callee does not access allocas from the caller. The ``tail`` marker additionally implies that the callee does not access - varargs from the caller, while ``musttail`` implies that varargs from the - caller are passed to the callee. Calls marked ``musttail`` must obey the - following additional rules: + varargs from the caller. Calls marked ``musttail`` must obey the following + additional rules: - The call must immediately precede a :ref:`ret ` instruction, or a pointer bitcast followed by a ret instruction. From 4cecdaa05f8069aa3d9449f44e1e7c1847850bae Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Fri, 24 May 2019 02:15:27 +0000 Subject: [PATCH 0125/1176] Fix BUILD_SHARED_LIBS builds after r361567 Also fixed a comment I noticed while debugging this build llvm-svn: 361591 --- llvm/cmake/modules/LLVM-Config.cmake | 2 +- llvm/tools/bugpoint/CMakeLists.txt | 2 ++ llvm/tools/llc/CMakeLists.txt | 2 ++ llvm/tools/llvm-c-test/CMakeLists.txt | 2 ++ llvm/tools/llvm-dwp/CMakeLists.txt | 2 ++ llvm/tools/llvm-lto/CMakeLists.txt | 2 ++ llvm/tools/llvm-lto2/CMakeLists.txt | 1 + llvm/tools/opt/CMakeLists.txt | 1 + 8 files changed, 13 insertions(+), 1 deletion(-) diff --git a/llvm/cmake/modules/LLVM-Config.cmake b/llvm/cmake/modules/LLVM-Config.cmake index 57c02f170e18f..be28ca4f052ea 100644 --- a/llvm/cmake/modules/LLVM-Config.cmake +++ b/llvm/cmake/modules/LLVM-Config.cmake @@ -210,7 +210,7 @@ function(llvm_map_components_to_libnames out_libs) elseif( c STREQUAL "all" ) list(APPEND expanded_components ${LLVM_AVAILABLE_LIBS}) elseif( c STREQUAL "AllTargetsCodeGens" ) - # Link all the asm printers from all the targets + # Link all the codegens from all the targets foreach(t ${LLVM_TARGETS_TO_BUILD}) if( TARGET LLVM${t}CodeGen) list(APPEND expanded_components "LLVM${t}CodeGen") diff --git a/llvm/tools/bugpoint/CMakeLists.txt b/llvm/tools/bugpoint/CMakeLists.txt index 6ed15a24a2d4d..031f51480cce7 100644 --- a/llvm/tools/bugpoint/CMakeLists.txt +++ b/llvm/tools/bugpoint/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos Analysis BitWriter CodeGen diff --git a/llvm/tools/llc/CMakeLists.txt b/llvm/tools/llc/CMakeLists.txt index 863358b5e71c7..130f0cd3cb9e8 100644 --- a/llvm/tools/llc/CMakeLists.txt +++ b/llvm/tools/llc/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos Analysis AsmPrinter CodeGen diff --git a/llvm/tools/llvm-c-test/CMakeLists.txt b/llvm/tools/llvm-c-test/CMakeLists.txt index 78eaafc3b5a40..939164e636216 100644 --- a/llvm/tools/llvm-c-test/CMakeLists.txt +++ b/llvm/tools/llvm-c-test/CMakeLists.txt @@ -1,7 +1,9 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens + AllTargetsDescs AllTargetsDisassemblers + AllTargetsInfos BitReader Core MCDisassembler diff --git a/llvm/tools/llvm-dwp/CMakeLists.txt b/llvm/tools/llvm-dwp/CMakeLists.txt index 49f40b5c6397b..bf40768ebd4a5 100644 --- a/llvm/tools/llvm-dwp/CMakeLists.txt +++ b/llvm/tools/llvm-dwp/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos AsmPrinter DebugInfoDWARF MC diff --git a/llvm/tools/llvm-lto/CMakeLists.txt b/llvm/tools/llvm-lto/CMakeLists.txt index d0222315d25f7..69868fb870c04 100644 --- a/llvm/tools/llvm-lto/CMakeLists.txt +++ b/llvm/tools/llvm-lto/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos BitReader BitWriter Core diff --git a/llvm/tools/llvm-lto2/CMakeLists.txt b/llvm/tools/llvm-lto2/CMakeLists.txt index 233817a387f9d..7f2db01c9c916 100644 --- a/llvm/tools/llvm-lto2/CMakeLists.txt +++ b/llvm/tools/llvm-lto2/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens AllTargetsDescs + AllTargetsInfos BitReader Core Linker diff --git a/llvm/tools/opt/CMakeLists.txt b/llvm/tools/opt/CMakeLists.txt index 2f9665c689807..c9e44449dc2fb 100644 --- a/llvm/tools/opt/CMakeLists.txt +++ b/llvm/tools/opt/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS AllTargetsAsmParsers AllTargetsCodeGens + AllTargetsDescs AllTargetsInfos AggressiveInstCombine Analysis From 425e565783ddb7c440953ae74daf6d54f4ee9d74 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Fri, 24 May 2019 02:29:18 +0000 Subject: [PATCH 0126/1176] [analyzer] NFC: Prevent multi-file plist test from spamming up the build folder. It was producing an HTML report with a random name on every tests run and never cleaned those up. llvm-svn: 361592 --- .../Inputs/expected-plists/plist-multi-file.c.plist | 4 ---- clang/test/Analysis/diagnostics/plist-multi-file.c | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist b/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist index 86c203245d4e7..74ccc7903c1f8 100644 --- a/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist +++ b/clang/test/Analysis/diagnostics/Inputs/expected-plists/plist-multi-file.c.plist @@ -184,10 +184,6 @@ col8 file1 - HTMLDiagnostics_files - - report-288847.html - ExecutedLines 0 diff --git a/clang/test/Analysis/diagnostics/plist-multi-file.c b/clang/test/Analysis/diagnostics/plist-multi-file.c index a70c9aa93537f..f6ff8097ff094 100644 --- a/clang/test/Analysis/diagnostics/plist-multi-file.c +++ b/clang/test/Analysis/diagnostics/plist-multi-file.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-html -o %t.plist -verify %s -// RUN: tail -n +11 %t.plist | %diff_plist --ignore-matching-lines=report %S/Inputs/expected-plists/plist-multi-file.c.plist - +// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-output=plist-multi-file -o %t.plist -verify %s +// RUN: tail -n +11 %t.plist | %diff_plist %S/Inputs/expected-plists/plist-multi-file.c.plist - #include "plist-multi-file.h" From e46721a153440646c5a2f0c59700a34e24c26be1 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 24 May 2019 02:46:34 +0000 Subject: [PATCH 0127/1176] fix destroying delete test with older apple compilers llvm-svn: 361593 --- .../destroying_delete_t.pass.cpp | 2 + .../destroying_delete_t_declaration.pass.cpp | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 libcxx/test/std/language.support/support.dynamic/destroying_delete_t_declaration.pass.cpp diff --git a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp index d544b0e7cab6e..a2c9b8b5f42f5 100644 --- a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp @@ -14,6 +14,8 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 +// UNSUPPORTED: apple-clang-9, apple-clang-10 + #include #include diff --git a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t_declaration.pass.cpp b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t_declaration.pass.cpp new file mode 100644 index 0000000000000..b0e42ecfd58c0 --- /dev/null +++ b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t_declaration.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// struct destroying_delete_t { +// explicit destroying_delete_t() = default; +// }; +// inline constexpr destroying_delete_t destroying_delete{}; + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// Test only the library parts of destroying delete in this test. +// Verify that it's properly declared after C++17 and that it's constexpr. +// +// Other tests will check the language side of things -- but those are +// limited to newer compilers. + +#include + +#include +#include "test_macros.h" +#include "test_convertible.hpp" + +#ifdef __cpp_impl_destroying_delete +# ifndef __cpp_lib_destroying_delete +# error "Expected __cpp_lib_destroying_delete to be defined" +# elif __cpp_lib_destroying_delete < 201806L +# error "Unexpected value of __cpp_lib_destroying_delete" +# endif +#else +# ifdef __cpp_lib_destroying_delete +# error "__cpp_lib_destroying_delete should not be defined unless the compiler supports it" +# endif +#endif + +constexpr bool test_constexpr(std::destroying_delete_t) { + return true; +} + +int main() { + static_assert(std::is_default_constructible::value, ""); + static_assert(!test_convertible(), ""); + constexpr std::destroying_delete_t dd{}; + static_assert((dd, true), ""); + static_assert(&dd != &std::destroying_delete, ""); + static_assert(test_constexpr(std::destroying_delete), ""); +} From a38ddc36fdc7a18795e067cb68ec770f3fc5a982 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 24 May 2019 03:15:32 +0000 Subject: [PATCH 0128/1176] fix test for older clang versions llvm-svn: 361594 --- .../support.dynamic/destroying_delete_t.pass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp index a2c9b8b5f42f5..2ca6d19757316 100644 --- a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp @@ -15,6 +15,7 @@ // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 // UNSUPPORTED: apple-clang-9, apple-clang-10 +// UNSUPPORTED: clang-6 #include From 01d6173667f77722a31070fd186a50d3b3740207 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Fri, 24 May 2019 04:02:05 +0000 Subject: [PATCH 0129/1176] [llvm-nm] Fix Bug 41353 - unique symbols printed as D instead of u Summary: https://bugs.llvm.org/show_bug.cgi?id=41353 I'm new to LLVM and C++ so please do not hesitate to iterate with me on this fix. Patch by Mike Pozulp! Reviewers: rupprecht, zbrid, grimar, jhenderson Reviewed By: rupprecht, jhenderson Subscribers: jhenderson, chrisjackson, MaskRay, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61117 llvm-svn: 361595 --- llvm/include/llvm/Object/ELFObjectFile.h | 11 ++++++ llvm/test/tools/llvm-nm/X86/unique.test | 50 ++++++++++++++++++++++++ llvm/tools/llvm-nm/llvm-nm.cpp | 12 ++++-- 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 llvm/test/tools/llvm-nm/X86/unique.test diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index ed54ad02ccff7..d5e9d3638dc3c 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -56,6 +56,7 @@ class ELFObjectFileBase : public ObjectFile { virtual uint16_t getEMachine() const = 0; virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolBinding(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; @@ -145,6 +146,10 @@ class ELFSymbolRef : public SymbolRef { return getObject()->getSymbolSize(getRawDataRefImpl()); } + uint8_t getBinding() const { + return getObject()->getSymbolBinding(getRawDataRefImpl()); + } + uint8_t getOther() const { return getObject()->getSymbolOther(getRawDataRefImpl()); } @@ -252,6 +257,7 @@ template class ELFObjectFile : public ELFObjectFileBase { uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; + uint8_t getSymbolBinding(DataRefImpl Symb) const override; uint8_t getSymbolOther(DataRefImpl Symb) const override; uint8_t getSymbolELFType(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; @@ -553,6 +559,11 @@ uint64_t ELFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { return getSymbol(Symb)->st_size; } +template +uint8_t ELFObjectFile::getSymbolBinding(DataRefImpl Symb) const { + return getSymbol(Symb)->getBinding(); +} + template uint8_t ELFObjectFile::getSymbolOther(DataRefImpl Symb) const { return getSymbol(Symb)->st_other; diff --git a/llvm/test/tools/llvm-nm/X86/unique.test b/llvm/test/tools/llvm-nm/X86/unique.test new file mode 100644 index 0000000000000..a8879d74cf9f2 --- /dev/null +++ b/llvm/test/tools/llvm-nm/X86/unique.test @@ -0,0 +1,50 @@ +## Check that we print 'u' for unique symbols +## and 'U' for a unique symbol without a section. +# RUN: yaml2obj %s | llvm-nm - | FileCheck %s + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .nobits + Type: SHT_NOBITS + - Name: .progbits + Type: SHT_PROGBITS + - Name: .progbits_alloc + Type: SHT_PROGBITS + Flags: [SHF_ALLOC] + - Name: .progbits_alloc_write + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_WRITE] + - Name: .progbits_execinstr + Type: SHT_PROGBITS + Flags: [SHF_EXECINSTR] +Symbols: + - Name: nosection + Binding: STB_GNU_UNIQUE + - Name: nobits + Section: .nobits + Binding: STB_GNU_UNIQUE + - Name: progbits + Section: .progbits + Binding: STB_GNU_UNIQUE + - Name: progbits_alloc + Section: .progbits_alloc + Binding: STB_GNU_UNIQUE + - Name: progbits_alloc_write + Section: .progbits_alloc_write + Binding: STB_GNU_UNIQUE + - Name: progbits_execinstr + Section: .progbits_execinstr + Binding: STB_GNU_UNIQUE +... + +# CHECK: 0000000000000000 u nobits +# CHECK: U nosection +# CHECK: 0000000000000000 u progbits +# CHECK: 0000000000000000 u progbits_alloc +# CHECK: 0000000000000000 u progbits_alloc_write +# CHECK: 0000000000000000 u progbits_execinstr diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index f21978d50cc12..871ca638d9d75 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -894,6 +894,9 @@ static char getSymbolNMTypeChar(ELFObjectFileBase &Obj, return '?'; } + if (SymI->getBinding() == ELF::STB_GNU_UNIQUE) + return 'u'; + elf_section_iterator SecI = *SecIOrErr; if (SecI != Obj.section_end()) { uint32_t Type = SecI->getType(); @@ -1119,10 +1122,13 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, else Ret = getSymbolNMTypeChar(cast(Obj), I); - if (Symflags & object::SymbolRef::SF_Global) - Ret = toupper(Ret); + if (!(Symflags & object::SymbolRef::SF_Global)) + return Ret; + + if (Obj.isELF() && ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE) + return Ret; - return Ret; + return toupper(Ret); } // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname" From c652b3455ec55704f2e7d152fa7e4f45283b3258 Mon Sep 17 00:00:00 2001 From: Yevgeny Rouban Date: Fri, 24 May 2019 04:34:23 +0000 Subject: [PATCH 0130/1176] [NFC] SwitchInst: Introduce wrapper for prof branch_weights handling This patch introduces a wrapper class that re-implements several mutator methods of SwitchInst to handle changes of prof branch_weights metadata along with remove/add switch case methods. Subsequent patches will use this wrapper to implement prof branch_weights metadata handling for SwitchInst. Reviewers: davidx, eraman, reames, chandlerc Reviewed By: davidx Differential Revision: https://reviews.llvm.org/D62122 llvm-svn: 361596 --- llvm/include/llvm/IR/Instructions.h | 46 +++++++++++ llvm/lib/IR/Instructions.cpp | 120 ++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index 3e0c6d803d209..82833658c4182 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -3435,6 +3435,52 @@ class SwitchInst : public Instruction { } }; +/// A wrapper class to simplify modification of SwitchInst cases along with +/// their prof branch_weights metadata. +class SwitchInstProfUpdateWrapper { + SwitchInst &SI; + Optional > Weights; + bool Changed = false; + +protected: + static MDNode *getProfBranchWeightsMD(const SwitchInst &SI); + + MDNode *buildProfBranchWeightsMD(); + + Optional > getProfBranchWeights(); + +public: + using CaseWeightOpt = Optional; + SwitchInst *operator->() { return &SI; } + SwitchInst &operator*() { return SI; } + operator SwitchInst *() { return &SI; } + + SwitchInstProfUpdateWrapper(SwitchInst &SI) + : SI(SI), Weights(getProfBranchWeights()) {} + + ~SwitchInstProfUpdateWrapper() { + if (Changed) + SI.setMetadata(LLVMContext::MD_prof, buildProfBranchWeightsMD()); + } + + /// Delegate the call to the underlying SwitchInst::removeCase() and remove + /// correspondent branch weight. + SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I); + + /// Delegate the call to the underlying SwitchInst::addCase() and set the + /// specified branch weight for the added case. + void addCase(ConstantInt *OnVal, BasicBlock *Dest, CaseWeightOpt W); + + /// Delegate the call to the underlying SwitchInst::eraseFromParent() and mark + /// this object to not touch the underlying SwitchInst in destructor. + SymbolTableList::iterator eraseFromParent(); + + void setSuccessorWeight(unsigned idx, CaseWeightOpt W); + CaseWeightOpt getSuccessorWeight(unsigned idx); + + static CaseWeightOpt getSuccessorWeight(const SwitchInst &SI, unsigned idx); +}; + template <> struct OperandTraits : public HungoffOperandTraits<2> { }; diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 9dc753e960c5b..8812df35e26b2 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -3870,6 +3870,126 @@ void SwitchInst::growOperands() { growHungoffUses(ReservedSpace); } +MDNode * +SwitchInstProfUpdateWrapper::getProfBranchWeightsMD(const SwitchInst &SI) { + if (MDNode *ProfileData = SI.getMetadata(LLVMContext::MD_prof)) + if (auto *MDName = dyn_cast(ProfileData->getOperand(0))) + if (MDName->getString() == "branch_weights") + return ProfileData; + return nullptr; +} + +MDNode *SwitchInstProfUpdateWrapper::buildProfBranchWeightsMD() { + assert(Changed && "called only if metadata has changed"); + + if (!Weights) + return nullptr; + + assert(SI.getNumSuccessors() == Weights->size() && + "num of prof branch_weights must accord with num of successors"); + + bool AllZeroes = + all_of(Weights.getValue(), [](uint32_t W) { return W == 0; }); + + if (AllZeroes || Weights.getValue().size() < 2) + return nullptr; + + return MDBuilder(SI.getParent()->getContext()).createBranchWeights(*Weights); +} + +Optional > +SwitchInstProfUpdateWrapper::getProfBranchWeights() { + MDNode *ProfileData = getProfBranchWeightsMD(SI); + if (!ProfileData) + return None; + + SmallVector Weights; + for (unsigned CI = 1, CE = SI.getNumSuccessors(); CI <= CE; ++CI) { + ConstantInt *C = mdconst::extract(ProfileData->getOperand(CI)); + uint32_t CW = C->getValue().getZExtValue(); + Weights.push_back(CW); + } + return Weights; +} + +SwitchInst::CaseIt +SwitchInstProfUpdateWrapper::removeCase(SwitchInst::CaseIt I) { + if (Weights) { + assert(SI.getNumSuccessors() == Weights->size() && + "num of prof branch_weights must accord with num of successors"); + Changed = true; + // Copy the last case to the place of the removed one and shrink. + // This is tightly coupled with the way SwitchInst::removeCase() removes + // the cases in SwitchInst::removeCase(CaseIt). + Weights.getValue()[I->getCaseIndex() + 1] = Weights.getValue().back(); + Weights.getValue().pop_back(); + } + return SI.removeCase(I); +} + +void SwitchInstProfUpdateWrapper::addCase( + ConstantInt *OnVal, BasicBlock *Dest, + SwitchInstProfUpdateWrapper::CaseWeightOpt W) { + SI.addCase(OnVal, Dest); + + if (!Weights && W && *W) { + Changed = true; + Weights = SmallVector(SI.getNumSuccessors(), 0); + Weights.getValue()[SI.getNumSuccessors() - 1] = *W; + } else if (Weights) { + Changed = true; + Weights.getValue().push_back(W ? *W : 0); + } + if (Weights) + assert(SI.getNumSuccessors() == Weights->size() && + "num of prof branch_weights must accord with num of successors"); +} + +SymbolTableList::iterator +SwitchInstProfUpdateWrapper::eraseFromParent() { + // Instruction is erased. Mark as unchanged to not touch it in the destructor. + Changed = false; + + if (Weights) + Weights->resize(0); + return SI.eraseFromParent(); +} + +SwitchInstProfUpdateWrapper::CaseWeightOpt +SwitchInstProfUpdateWrapper::getSuccessorWeight(unsigned idx) { + if (!Weights) + return None; + return Weights.getValue()[idx]; +} + +void SwitchInstProfUpdateWrapper::setSuccessorWeight( + unsigned idx, SwitchInstProfUpdateWrapper::CaseWeightOpt W) { + if (!W) + return; + + if (!Weights && *W) + Weights = SmallVector(SI.getNumSuccessors(), 0); + + if (Weights) { + auto &OldW = Weights.getValue()[idx]; + if (*W != OldW) { + Changed = true; + OldW = *W; + } + } +} + +SwitchInstProfUpdateWrapper::CaseWeightOpt +SwitchInstProfUpdateWrapper::getSuccessorWeight(const SwitchInst &SI, + unsigned idx) { + if (MDNode *ProfileData = getProfBranchWeightsMD(SI)) + return mdconst::extract(ProfileData->getOperand(idx + 1)) + ->getValue() + .getZExtValue(); + + return None; +} + //===----------------------------------------------------------------------===// // IndirectBrInst Implementation //===----------------------------------------------------------------------===// From 0ee23c958bbcf6955568d5287d1495f485426800 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 24 May 2019 04:41:47 +0000 Subject: [PATCH 0131/1176] [Utility] Small improvements to the Broadcaster class (NFC) I touched the Broadcaster class earlier today (r361544) and noticed a few things that could be improved. This patch includes variety of small fixes: use early returns, use LLDB_LOG macro, use doxygen comments and finally format the class. llvm-svn: 361597 --- lldb/include/lldb/Utility/Broadcaster.h | 121 ++++++++++++------------ lldb/source/Utility/Broadcaster.cpp | 85 ++++++++--------- 2 files changed, 99 insertions(+), 107 deletions(-) diff --git a/lldb/include/lldb/Utility/Broadcaster.h b/lldb/include/lldb/Utility/Broadcaster.h index 1444282c7f7b0..fe4d1ca479b89 100644 --- a/lldb/include/lldb/Utility/Broadcaster.h +++ b/lldb/include/lldb/Utility/Broadcaster.h @@ -29,14 +29,14 @@ class Broadcaster; class EventData; class Listener; class Stream; -} +} // namespace lldb_private namespace lldb_private { -// lldb::BroadcastEventSpec -// -// This class is used to specify a kind of event to register for. The Debugger -// maintains a list of BroadcastEventSpec's and when it is made +/// lldb::BroadcastEventSpec +/// +/// This class is used to specify a kind of event to register for. The +/// Debugger maintains a list of BroadcastEventSpec's and when it is made class BroadcastEventSpec { public: BroadcastEventSpec(ConstString broadcaster_class, uint32_t event_bits) @@ -48,19 +48,19 @@ class BroadcastEventSpec { uint32_t GetEventBits() const { return m_event_bits; } - // Tell whether this BroadcastEventSpec is contained in in_spec. That is: (a) - // the two spec's share the same broadcaster class (b) the event bits of this - // spec are wholly contained in those of in_spec. + /// Tell whether this BroadcastEventSpec is contained in in_spec. That is: + /// (a) the two spec's share the same broadcaster class (b) the event bits of + /// this spec are wholly contained in those of in_spec. bool IsContainedIn(const BroadcastEventSpec &in_spec) const { if (m_broadcaster_class != in_spec.GetBroadcasterClass()) return false; uint32_t in_bits = in_spec.GetEventBits(); if (in_bits == m_event_bits) return true; - else { - if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0) - return true; - } + + if ((m_event_bits & in_bits) != 0 && (m_event_bits & ~in_bits) == 0) + return true; + return false; } @@ -81,10 +81,9 @@ class BroadcasterManager BroadcasterManager(); public: - // Listeners hold onto weak pointers to their broadcaster managers. So they - // must be made into shared pointers, which you do with - // MakeBroadcasterManager. - + /// Listeners hold onto weak pointers to their broadcaster managers. So they + /// must be made into shared pointers, which you do with + /// MakeBroadcasterManager. static lldb::BroadcasterManagerSP MakeBroadcasterManager(); ~BroadcasterManager() = default; @@ -179,8 +178,8 @@ class BroadcasterManager bool operator()(const event_listener_key &input) const { if (input.second == m_listener_sp) return true; - else - return false; + + return false; } private: @@ -197,15 +196,15 @@ class BroadcasterManager bool operator()(const event_listener_key &input) const { if (input.second.get() == m_listener) return true; - else - return false; + + return false; } bool operator()(const lldb::ListenerSP &input) const { if (input.get() == m_listener) return true; - else - return false; + + return false; } private: @@ -413,32 +412,30 @@ class Broadcaster { } /// Restore the state of the Broadcaster from a previous hijack attempt. - /// void RestoreBroadcaster() { m_broadcaster_sp->RestoreBroadcaster(); } - // This needs to be filled in if you are going to register the broadcaster - // with the broadcaster manager and do broadcaster class matching. - // FIXME: Probably should make a ManagedBroadcaster subclass with all the bits - // needed to work - // with the BroadcasterManager, so that it is clearer how to add one. + /// This needs to be filled in if you are going to register the broadcaster + /// with the broadcaster manager and do broadcaster class matching. + /// FIXME: Probably should make a ManagedBroadcaster subclass with all the + /// bits needed to work with the BroadcasterManager, so that it is clearer + /// how to add one. virtual ConstString &GetBroadcasterClass() const; lldb::BroadcasterManagerSP GetManager(); protected: - // BroadcasterImpl contains the actual Broadcaster implementation. The - // Broadcaster makes a BroadcasterImpl which lives as long as it does. The - // Listeners & the Events hold a weak pointer to the BroadcasterImpl, so that - // they can survive if a Broadcaster they were listening to is destroyed w/o - // their being able to unregister from it (which can happen if the - // Broadcasters & Listeners are being destroyed on separate threads - // simultaneously. The Broadcaster itself can't be shared out as a weak - // pointer, because some things that are broadcasters (e.g. the Target and - // the Process) are shared in their own right. - // - // For the most part, the Broadcaster functions dispatch to the - // BroadcasterImpl, and are documented in the public Broadcaster API above. - + /// BroadcasterImpl contains the actual Broadcaster implementation. The + /// Broadcaster makes a BroadcasterImpl which lives as long as it does. The + /// Listeners & the Events hold a weak pointer to the BroadcasterImpl, so + /// that they can survive if a Broadcaster they were listening to is + /// destroyed w/o their being able to unregister from it (which can happen if + /// the Broadcasters & Listeners are being destroyed on separate threads + /// simultaneously. The Broadcaster itself can't be shared out as a weak + /// pointer, because some things that are broadcasters (e.g. the Target and + /// the Process) are shared in their own right. + /// + /// For the most part, the Broadcaster functions dispatch to the + /// BroadcasterImpl, and are documented in the public Broadcaster API above. class BroadcasterImpl { friend class Listener; friend class Broadcaster; @@ -505,7 +502,6 @@ class Broadcaster { const char *GetHijackingListenerName(); - // typedef llvm::SmallVector, 4> collection; typedef std::map event_names_map; @@ -513,22 +509,28 @@ class Broadcaster { llvm::SmallVector, 4> GetListeners(); - Broadcaster &m_broadcaster; ///< The broadcaster that this implements - event_names_map m_event_names; ///< Optionally define event names for - ///readability and logging for each event bit - collection m_listeners; ///< A list of Listener / event_mask pairs that are - ///listening to this broadcaster. - std::recursive_mutex - m_listeners_mutex; ///< A mutex that protects \a m_listeners. - std::vector m_hijacking_listeners; // A simple mechanism - // to intercept events - // from a broadcaster - std::vector m_hijacking_masks; // At some point we may want to - // have a stack or Listener - // collections, but for now this is just for private hijacking. + /// The broadcaster that this implements. + Broadcaster &m_broadcaster; + + /// Optionally define event names for readability and logging for each + /// event bit. + event_names_map m_event_names; + + /// A list of Listener / event_mask pairs that are listening to this + /// broadcaster. + collection m_listeners; + + /// A mutex that protects \a m_listeners. + std::recursive_mutex m_listeners_mutex; + + /// A simple mechanism to intercept events from a broadcaster + std::vector m_hijacking_listeners; + + /// At some point we may want to have a stack or Listener collections, but + /// for now this is just for private hijacking. + std::vector m_hijacking_masks; private: - // For Broadcaster only DISALLOW_COPY_AND_ASSIGN(BroadcasterImpl); }; @@ -540,14 +542,13 @@ class Broadcaster { const char *GetHijackingListenerName() { return m_broadcaster_sp->GetHijackingListenerName(); } - // Classes that inherit from Broadcaster can see and modify these private: - // For Broadcaster only BroadcasterImplSP m_broadcaster_sp; lldb::BroadcasterManagerSP m_manager_sp; - const ConstString - m_broadcaster_name; ///< The name of this broadcaster object. + + /// The name of this broadcaster object. + const ConstString m_broadcaster_name; DISALLOW_COPY_AND_ASSIGN(Broadcaster); }; diff --git a/lldb/source/Utility/Broadcaster.cpp b/lldb/source/Utility/Broadcaster.cpp index c0b8567558eb3..597888cfa0e2e 100644 --- a/lldb/source/Utility/Broadcaster.cpp +++ b/lldb/source/Utility/Broadcaster.cpp @@ -30,9 +30,8 @@ Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) : m_broadcaster_sp(std::make_shared(*this)), m_manager_sp(std::move(manager_sp)), m_broadcaster_name(name) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Broadcaster::Broadcaster(\"%s\")", - static_cast(this), GetBroadcasterName().AsCString()); + LLDB_LOG(log, "{0} Broadcaster::Broadcaster(\"{1}\")", + static_cast(this), GetBroadcasterName().AsCString()); } Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster) @@ -41,9 +40,8 @@ Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster) Broadcaster::~Broadcaster() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p Broadcaster::~Broadcaster(\"%s\")", - static_cast(this), m_broadcaster_name.AsCString()); + LLDB_LOG(log, "{0} Broadcaster::~Broadcaster(\"{1}\")", + static_cast(this), GetBroadcasterName().AsCString()); Clear(); } @@ -213,8 +211,7 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, hijacking_listener_sp.reset(); } - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log) { + if (Log *log = lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)) { StreamString event_description; event_sp->Dump(&event_description); log->Printf("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " @@ -225,18 +222,16 @@ void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, } if (hijacking_listener_sp) { - if (unique && - hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType( - &m_broadcaster, event_type)) + if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType( + &m_broadcaster, event_type)) return; hijacking_listener_sp->AddEvent(event_sp); } else { for (auto &pair : GetListeners()) { if (!(pair.second & event_type)) continue; - if (unique && - pair.first->PeekAtNextEventForBroadcasterWithType(&m_broadcaster, - event_type)) + if (unique && pair.first->PeekAtNextEventForBroadcasterWithType( + &m_broadcaster, event_type)) continue; pair.first->AddEvent(event_sp); @@ -267,11 +262,11 @@ bool Broadcaster::BroadcasterImpl::HijackBroadcaster( std::lock_guard guard(m_listeners_mutex); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log) - log->Printf( - "%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)", - static_cast(this), GetBroadcasterName(), - listener_sp->m_name.c_str(), static_cast(listener_sp.get())); + LLDB_LOG( + log, + "{0} Broadcaster(\"{1}\")::HijackBroadcaster (listener(\"{2}\")={3})", + static_cast(this), GetBroadcasterName(), + listener_sp->m_name.c_str(), static_cast(listener_sp.get())); m_hijacking_listeners.push_back(listener_sp); m_hijacking_masks.push_back(event_mask); return true; @@ -288,24 +283,22 @@ bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) { const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() { if (m_hijacking_listeners.size()) { return m_hijacking_listeners.back()->GetName(); - } else { - return nullptr; } + return nullptr; } void Broadcaster::BroadcasterImpl::RestoreBroadcaster() { std::lock_guard guard(m_listeners_mutex); if (!m_hijacking_listeners.empty()) { + ListenerSP listener_sp = m_hijacking_listeners.back(); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); - if (log) { - ListenerSP listener_sp = m_hijacking_listeners.back(); - log->Printf("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop " - "listener(\"%s\")=%p)", - static_cast(this), GetBroadcasterName(), - listener_sp->m_name.c_str(), - static_cast(listener_sp.get())); - } + LLDB_LOG(log, + "{0} Broadcaster(\"{1}\")::RestoreBroadcaster (about to pop " + "listener(\"{2}\")={3})", + static_cast(this), GetBroadcasterName(), + listener_sp->m_name.c_str(), + static_cast(listener_sp.get())); m_hijacking_listeners.pop_back(); } if (!m_hijacking_masks.empty()) @@ -320,9 +313,8 @@ ConstString &Broadcaster::GetBroadcasterClass() const { bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const { if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) { return GetEventBits() < rhs.GetEventBits(); - } else { - return GetBroadcasterClass() < rhs.GetBroadcasterClass(); } + return GetBroadcasterClass() < rhs.GetBroadcasterClass(); } BroadcastEventSpec &BroadcastEventSpec:: @@ -378,17 +370,16 @@ bool BroadcasterManager::UnregisterListenerForEvents( iter = find_if(m_event_map.begin(), end_iter, predicate); if (iter == end_iter) { break; - } else { - uint32_t iter_event_bits = (*iter).first.GetEventBits(); - removed_some = true; - - if (event_bits_to_remove != iter_event_bits) { - uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; - to_be_readded.push_back(BroadcastEventSpec( - event_spec.GetBroadcasterClass(), new_event_bits)); - } - m_event_map.erase(iter); } + uint32_t iter_event_bits = (*iter).first.GetEventBits(); + removed_some = true; + + if (event_bits_to_remove != iter_event_bits) { + uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; + to_be_readded.push_back( + BroadcastEventSpec(event_spec.GetBroadcasterClass(), new_event_bits)); + } + m_event_map.erase(iter); } // Okay now add back the bits that weren't completely removed: @@ -408,8 +399,8 @@ ListenerSP BroadcasterManager::GetListenerForEventSpec( BroadcastEventSpecMatches(event_spec)); if (iter != end_iter) return (*iter).second; - else - return nullptr; + + return nullptr; } void BroadcasterManager::RemoveListener(Listener *listener) { @@ -427,8 +418,8 @@ void BroadcasterManager::RemoveListener(Listener *listener) { iter = find_if(m_event_map.begin(), end_iter, predicate); if (iter == end_iter) break; - else - m_event_map.erase(iter); + + m_event_map.erase(iter); } } @@ -444,8 +435,8 @@ void BroadcasterManager::RemoveListener(const lldb::ListenerSP &listener_sp) { iter = find_if(m_event_map.begin(), end_iter, predicate); if (iter == end_iter) break; - else - m_event_map.erase(iter); + + m_event_map.erase(iter); } } From 0de4e935bb591b8c9ee41a9acbb5cda02838d8a6 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Fri, 24 May 2019 04:46:22 +0000 Subject: [PATCH 0132/1176] Do not resolve directory junctions for `-fdiagnostics-absolute-paths` on Windows. If the source file path contains directory junctions, and we resolve them when printing diagnostic messages, these paths look independent for an IDE. For example, both Visual Studio and Visual Studio Code open separate editors for such paths, which is not only inconvenient but might even result in losing changes made in one of them. Differential Revision: https://reviews.llvm.org/D59415 llvm-svn: 361598 --- clang/lib/Frontend/TextDiagnostic.cpp | 21 +++++++++++++++++++ .../test/Frontend/absolute-paths-windows.test | 9 ++++++++ clang/test/Frontend/lit.local.cfg | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 clang/test/Frontend/absolute-paths-windows.test diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp index c6ebdcaf9a8fa..d0c91286250e7 100644 --- a/clang/lib/Frontend/TextDiagnostic.cpp +++ b/clang/lib/Frontend/TextDiagnostic.cpp @@ -765,7 +765,28 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) { const DirectoryEntry *Dir = SM.getFileManager().getDirectory( llvm::sys::path::parent_path(Filename)); if (Dir) { + // We want to print a simplified absolute path, i. e. without "dots". + // + // The hardest part here are the paths like "//../". + // On Unix-like systems, we cannot just collapse "/..", because + // paths are resolved sequentially, and, thereby, the path + // "/" may point to a different location. That is why + // we use FileManager::getCanonicalName(), which expands all indirections + // with llvm::sys::fs::real_path() and caches the result. + // + // On the other hand, it would be better to preserve as much of the + // original path as possible, because that helps a user to recognize it. + // real_path() expands all links, which sometimes too much. Luckily, + // on Windows we can just use llvm::sys::path::remove_dots(), because, + // on that system, both aforementioned paths point to the same place. +#ifdef _WIN32 + SmallString<4096> DirName = Dir->getName(); + llvm::sys::fs::make_absolute(DirName); + llvm::sys::path::native(DirName); + llvm::sys::path::remove_dots(DirName, /* remove_dot_dot */ true); +#else StringRef DirName = SM.getFileManager().getCanonicalName(Dir); +#endif llvm::sys::path::append(AbsoluteFilename, DirName, llvm::sys::path::filename(Filename)); Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size()); diff --git a/clang/test/Frontend/absolute-paths-windows.test b/clang/test/Frontend/absolute-paths-windows.test new file mode 100644 index 0000000000000..10741d56452b3 --- /dev/null +++ b/clang/test/Frontend/absolute-paths-windows.test @@ -0,0 +1,9 @@ +// REQUIRES: system-windows +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir\real +// RUN: cmd /c mklink /j %t.dir\junc %t.dir\real +// RUN: echo "wrong code" > %t.dir\real\foo.cpp +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-absolute-paths %t.dir\junc\foo.cpp 2>&1 | FileCheck %s + +// CHECK-NOT: .dir\real\foo.cpp +// CHECK: .dir\junc\foo.cpp diff --git a/clang/test/Frontend/lit.local.cfg b/clang/test/Frontend/lit.local.cfg index 7a05c5dfd2597..835360be27551 100644 --- a/clang/test/Frontend/lit.local.cfg +++ b/clang/test/Frontend/lit.local.cfg @@ -1 +1 @@ -config.suffixes = ['.c', '.cpp', '.m', '.mm', '.ll', '.cl'] +config.suffixes = ['.c', '.cpp', '.m', '.mm', '.ll', '.cl', '.test'] From af0add6c39f7fcc641a2ae38753a9bc4eae47b28 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 24 May 2019 04:46:56 +0000 Subject: [PATCH 0133/1176] [X86] Add test case that was supposed to go with r360102. Found in my working area. Guess I forgot 'git add' before committing. llvm-svn: 361599 --- .../CodeGen/X86/asm-reg-type-mismatch-avx512.ll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 llvm/test/CodeGen/X86/asm-reg-type-mismatch-avx512.ll diff --git a/llvm/test/CodeGen/X86/asm-reg-type-mismatch-avx512.ll b/llvm/test/CodeGen/X86/asm-reg-type-mismatch-avx512.ll new file mode 100644 index 0000000000000..1c5e1ce8a6b99 --- /dev/null +++ b/llvm/test/CodeGen/X86/asm-reg-type-mismatch-avx512.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=avx512f | FileCheck %s + +define i64 @test1() nounwind { +; CHECK-LABEL: test1: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: #APP +; CHECK-NEXT: vmovq {{.*#+}} xmm16 = mem[0],zero +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: vmovq %xmm16, %rax +; CHECK-NEXT: retq +entry: + %0 = tail call i64 asm sideeffect "vmovq $1, $0", "={xmm16},*m,~{dirflag},~{fpsr},~{flags}"(i64* null) nounwind + ret i64 %0 +} From 449bfdd1b02bf441f6862dac1169bb5208eaccbc Mon Sep 17 00:00:00 2001 From: QingShan Zhang Date: Fri, 24 May 2019 05:30:09 +0000 Subject: [PATCH 0134/1176] [Power9] Add a specific heuristic to schedule the addi before the load When we are scheduling the load and addi, if all other heuristic didn't take effect, we will try to schedule the addi before the load, to hide the latency, and avoid the true dependency added by RA. And this only take effects for Power9. Differential Revision: https://reviews.llvm.org/D61930 llvm-svn: 361600 --- .../Target/PowerPC/PPCMachineScheduler.cpp | 51 +++++++++++++++++++ llvm/lib/Target/PowerPC/PPCMachineScheduler.h | 7 +++ .../CodeGen/PowerPC/schedule-addi-load.mir | 19 ++++++- 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/PowerPC/PPCMachineScheduler.cpp b/llvm/lib/Target/PowerPC/PPCMachineScheduler.cpp index 19aa53d54f149..d57e38acef683 100644 --- a/llvm/lib/Target/PowerPC/PPCMachineScheduler.cpp +++ b/llvm/lib/Target/PowerPC/PPCMachineScheduler.cpp @@ -5,9 +5,60 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +#include "PPC.h" #include "PPCMachineScheduler.h" using namespace llvm; +static cl::opt +DisableAddiLoadHeuristic("disable-ppc-sched-addi-load", + cl::desc("Disable scheduling addi instruction before" + "load for ppc"), cl::Hidden); + +bool PPCPreRASchedStrategy::biasAddiLoadCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary &Zone) const { + if (DisableAddiLoadHeuristic) + return false; + + auto isADDIInstr = [&] (const MachineInstr &Inst) { + return Inst.getOpcode() == PPC::ADDI || Inst.getOpcode() == PPC::ADDI8; + }; + + SchedCandidate &FirstCand = Zone.isTop() ? TryCand : Cand; + SchedCandidate &SecondCand = Zone.isTop() ? Cand : TryCand; + if (isADDIInstr(*FirstCand.SU->getInstr()) && + SecondCand.SU->getInstr()->mayLoad()) { + TryCand.Reason = Stall; + return true; + } + if (FirstCand.SU->getInstr()->mayLoad() && + isADDIInstr(*SecondCand.SU->getInstr())) { + TryCand.Reason = NoCand; + return true; + } + + return false; +} + +void PPCPreRASchedStrategy::tryCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary *Zone) const { + GenericScheduler::tryCandidate(Cand, TryCand, Zone); + + if (!Cand.isValid() || !Zone) + return; + + // Add powerpc specific heuristic only when TryCand isn't selected or + // selected as node order. + if (TryCand.Reason != NodeOrder && TryCand.Reason != NoCand) + return; + + // There are some benefits to schedule the ADDI before the load to hide the + // latency, as RA may create a true dependency between the load and addi. + if (biasAddiLoadCandidate(Cand, TryCand, *Zone)) + return; +} + void PPCPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) { // Custom PPC PostRA specific behavior here. PostGenericScheduler::enterMBB(MBB); diff --git a/llvm/lib/Target/PowerPC/PPCMachineScheduler.h b/llvm/lib/Target/PowerPC/PPCMachineScheduler.h index ea6d3ffbb262b..93532d9545a6e 100644 --- a/llvm/lib/Target/PowerPC/PPCMachineScheduler.h +++ b/llvm/lib/Target/PowerPC/PPCMachineScheduler.h @@ -22,6 +22,13 @@ class PPCPreRASchedStrategy : public GenericScheduler { public: PPCPreRASchedStrategy(const MachineSchedContext *C) : GenericScheduler(C) {} +protected: + void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, + SchedBoundary *Zone) const override; +private: + bool biasAddiLoadCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary &Zone) const; }; /// A MachineSchedStrategy implementation for PowerPC post RA scheduling. diff --git a/llvm/test/CodeGen/PowerPC/schedule-addi-load.mir b/llvm/test/CodeGen/PowerPC/schedule-addi-load.mir index f0c9ea66f6b01..f9820062cfdf1 100644 --- a/llvm/test/CodeGen/PowerPC/schedule-addi-load.mir +++ b/llvm/test/CodeGen/PowerPC/schedule-addi-load.mir @@ -1,4 +1,7 @@ # RUN: llc -mcpu=pwr9 -mtriple powerpc64le-unknown-linux-gnu -start-before machine-scheduler -stop-after machine-scheduler -verify-machineinstrs %s -o - | FileCheck %s +# RUN: llc -mcpu=pwr9 -mtriple powerpc64le-unknown-linux-gnu -disable-ppc-sched-addi-load -start-before machine-scheduler -stop-after machine-scheduler \ +# RUN: -verify-machineinstrs %s -o - | FileCheck --check-prefix=CHECK-DISABLE %s +# RUN: llc -mcpu=pwr8 -mtriple powerpc64le-unknown-linux-gnu -start-before machine-scheduler -stop-after machine-scheduler -verify-machineinstrs %s -o - | FileCheck --check-prefix=CHECK-P8 %s # Test that if the scheduler moves the addi before the load. --- | @@ -93,11 +96,25 @@ body: | B %bb.2 ; CHECK-LABEL: foo ; CHECK: %5:g8rc_and_g8rc_nox0 = RLDICL %0, 0, 32 + ; CHECK-NEXT: %9:g8rc = ADDI8 %5, 1 ; CHECK-NEXT: %6:gprc = LBZX %2, %5 :: (load 1 from %ir.arrayidx) ; CHECK-NEXT: %7:gprc = LBZX %3, %5 :: (load 1 from %ir.arrayidx4) - ; CHECK-NEXT: %9:g8rc = ADDI8 %5, 1 ; CHECK-NEXT: %8:crrc = CMPLW %6, %7 ; CHECK-NEXT: BCC 76, %8 + ; CHECK-DISABLE-LABEL: foo + ; CHECK-DISABLE: %5:g8rc_and_g8rc_nox0 = RLDICL %0, 0, 32 + ; CHECK-DISABLE-NEXT: %6:gprc = LBZX %2, %5 :: (load 1 from %ir.arrayidx) + ; CHECK-DISABLE-NEXT: %7:gprc = LBZX %3, %5 :: (load 1 from %ir.arrayidx4) + ; CHECK-DISABLE-NEXT: %9:g8rc = ADDI8 %5, 1 + ; CHECK-DISABLE-NEXT: %8:crrc = CMPLW %6, %7 + ; CHECK-DISABLE-NEXT: BCC 76, %8 + ; CHECK-P8-LABEL: foo + ; CHECK-P8: %5:g8rc_and_g8rc_nox0 = RLDICL %0, 0, 32 + ; CHECK-P8-NEXT: %6:gprc = LBZX %2, %5 :: (load 1 from %ir.arrayidx) + ; CHECK-P8-NEXT: %7:gprc = LBZX %3, %5 :: (load 1 from %ir.arrayidx4) + ; CHECK-P8-NEXT: %8:crrc = CMPLW %6, %7 + ; CHECK-P8-NEXT: %9:g8rc = ADDI8 %5, 1 + ; CHECK-P8-NEXT: BCC 76, %8 bb.2.while.end: $x3 = COPY %0 From b087129b5d3bde08ddaefa021bbefb2f152ed409 Mon Sep 17 00:00:00 2001 From: Matthias Gehre Date: Fri, 24 May 2019 05:46:57 +0000 Subject: [PATCH 0135/1176] [clang-tidy] Add option "LiteralInitializers" to cppcoreguidelines-pro-type-member-init Differential Revision: D24892 llvm-svn: 361601 --- .../ProTypeMemberInitCheck.cpp | 56 ++++++++++++++++++- .../ProTypeMemberInitCheck.h | 5 ++ clang-tools-extra/docs/ReleaseNotes.rst | 5 ++ ...cppcoreguidelines-pro-type-member-init.rst | 4 ++ ...es-pro-type-member-init-use-assignment.cpp | 40 +++++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index c6cfe5ec0002f..fc334fb5b3baf 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -250,7 +250,8 @@ void fixInitializerList(const ASTContext &Context, DiagnosticBuilder &Diag, ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - IgnoreArrays(Options.get("IgnoreArrays", false)) {} + IgnoreArrays(Options.get("IgnoreArrays", false)), + UseAssignment(Options.getLocalOrGlobal("UseAssignment", false)) {} void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) @@ -314,6 +315,7 @@ void ProTypeMemberInitCheck::check(const MatchFinder::MatchResult &Result) { void ProTypeMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IgnoreArrays", IgnoreArrays); + Options.store(Opts, "UseAssignment", UseAssignment); } // FIXME: Copied from clang/lib/Sema/SemaDeclCXX.cpp. @@ -338,6 +340,56 @@ static bool isEmpty(ASTContext &Context, const QualType &Type) { return isIncompleteOrZeroLengthArrayType(Context, Type); } +static const char *getInitializer(QualType QT, bool UseAssignment) { + const char *DefaultInitializer = "{}"; + if (!UseAssignment) + return DefaultInitializer; + + if (QT->isPointerType()) + return " = nullptr"; + + const BuiltinType *BT = + dyn_cast(QT.getCanonicalType().getTypePtr()); + if (!BT) + return DefaultInitializer; + + switch (BT->getKind()) { + case BuiltinType::Bool: + return " = false"; + case BuiltinType::Float: + return " = 0.0F"; + case BuiltinType::Double: + return " = 0.0"; + case BuiltinType::LongDouble: + return " = 0.0L"; + case BuiltinType::SChar: + case BuiltinType::Char_S: + case BuiltinType::WChar_S: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Short: + case BuiltinType::Int: + return " = 0"; + case BuiltinType::UChar: + case BuiltinType::Char_U: + case BuiltinType::WChar_U: + case BuiltinType::UShort: + case BuiltinType::UInt: + return " = 0U"; + case BuiltinType::Long: + return " = 0L"; + case BuiltinType::ULong: + return " = 0UL"; + case BuiltinType::LongLong: + return " = 0LL"; + case BuiltinType::ULongLong: + return " = 0ULL"; + + default: + return DefaultInitializer; + } +} + void ProTypeMemberInitCheck::checkMissingMemberInitializer( ASTContext &Context, const CXXRecordDecl &ClassDecl, const CXXConstructorDecl *Ctor) { @@ -420,7 +472,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer( for (const FieldDecl *Field : FieldsToFix) { Diag << FixItHint::CreateInsertion( getLocationForEndOfToken(Context, Field->getSourceRange().getEnd()), - "{}"); + getInitializer(Field->getType(), UseAssignment)); } } else if (Ctor) { // Otherwise, rewrite the constructor's initializer list. diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h index 807acfe3bb220..2ec8fb16342b5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.h @@ -64,6 +64,11 @@ class ProTypeMemberInitCheck : public ClangTidyCheck { // Whether arrays need to be initialized or not. Default is false. bool IgnoreArrays; + + // Whether fix-its for initialization of fundamental type use assignment + // instead of brace initalization. Only effective in C++11 mode. Default is + // false. + bool UseAssignment; }; } // namespace cppcoreguidelines diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 22acfa33feec4..d14a4938fa55e 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -186,6 +186,11 @@ Improvements to clang-tidy `WarnOnLargeObject` and `MaxSize` options to warn on any large trivial object caught by value. +- Added `UseAssignment` option to :doc:`cppcoreguidelines-pro-type-member-init` + + If set to true, the check will provide fix-its with literal initializers + (``int i = 0;``) instead of curly braces (``int i{};``). + Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst index 2fdb4e3698ab5..5ac0465e5462f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst @@ -33,6 +33,10 @@ Options zero-initialized during construction. For performance critical code, it may be important to not initialize fixed-size array members. Default is `0`. +.. option:: UseAssignment + If set to non-zero, the check will provide fix-its with literal initializers + (``int i = 0;``) instead of curly braces (``int i{};``). + This rule is part of the "Type safety" profile of the C++ Core Guidelines, corresponding to rule Type.6. See https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Pro-type-memberinit. diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp new file mode 100644 index 0000000000000..dd1f9ac4aa9a5 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp @@ -0,0 +1,40 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -config="{CheckOptions: [{key: "cppcoreguidelines-pro-type-member-init.UseAssignment", value: 1}]}" -- -std=c++11 + +struct T { + int i; +}; + +struct S { + bool b; + // CHECK-FIXES: bool b = false; + char c; + // CHECK-FIXES: char c = 0; + signed char sc; + // CHECK-FIXES: signed char sc = 0; + unsigned char uc; + // CHECK-FIXES: unsigned char uc = 0U; + int i; + // CHECK-FIXES: int i = 0; + unsigned u; + // CHECK-FIXES: unsigned u = 0U; + long l; + // CHECK-FIXES: long l = 0L; + unsigned long ul; + // CHECK-FIXES: unsigned long ul = 0UL; + long long ll; + // CHECK-FIXES: long long ll = 0LL; + unsigned long long ull; + // CHECK-FIXES: unsigned long long ull = 0ULL; + float f; + // CHECK-FIXES: float f = 0.0F; + double d; + // CHECK-FIXES: double d = 0.0; + long double ld; + // CHECK-FIXES: double ld = 0.0L; + int *ptr; + // CHECK-FIXES: int *ptr = nullptr; + T t; + // CHECK-FIXES: T t{}; + S() {} + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: +}; From 8ac0bc9832a251837681b3a1cd53085ed8d594dc Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 24 May 2019 08:04:03 +0000 Subject: [PATCH 0136/1176] DWARFContext: Make loading of sections thread-safe Summary: SymbolFileDWARF used to load debug sections in a thread-safe manner. When we moved to DWARFContext, we dropped the thread-safe part, because we thought it was not necessary. It turns out this was only mostly correct. The "mostly" part is there because this is a problem only if we use the manual index, as that is the only source of intra-module paralelism. Also, this only seems to occur for extremely simple files (like the ones I've been creating for tests lately), where we've managed to start indexing before loading the debug_str section. Then, two threads start to load the section simultaneously and produce wrong results. On more complex files, something seems to be loading the debug_str section before we start indexing, as I haven't been able to reproduce this there, but I have not investigated what it is. I've tried to come up with a test for this, but I haven't been able to reproduce the problem reliably. Still, while doing so, I created a way to generate many compile units on demand. Given that most of our tests work with only one or two compile units, it seems like this could be useful anyway. Reviewers: aprantl, JDevlieghere, clayborg Subscribers: arphaman, lldb-commits Differential Revision: https://reviews.llvm.org/D62316 llvm-svn: 361602 --- .../DWARF/parallel-indexing-stress.s | 82 +++++++++++++++++++ .../Plugins/SymbolFile/DWARF/DWARFContext.cpp | 56 ++++++------- .../Plugins/SymbolFile/DWARF/DWARFContext.h | 31 ++++--- 3 files changed, 128 insertions(+), 41 deletions(-) create mode 100644 lldb/lit/SymbolFile/DWARF/parallel-indexing-stress.s diff --git a/lldb/lit/SymbolFile/DWARF/parallel-indexing-stress.s b/lldb/lit/SymbolFile/DWARF/parallel-indexing-stress.s new file mode 100644 index 0000000000000..46e4c5565fd1d --- /dev/null +++ b/lldb/lit/SymbolFile/DWARF/parallel-indexing-stress.s @@ -0,0 +1,82 @@ +# Stress-test the parallel indexing of compile units. + +# RUN: llvm-mc -triple x86_64-pc-linux %s -o %t -filetype=obj +# RUN: %lldb %t -o "target variable A" -b | FileCheck %s + +# CHECK-COUNT-256: A = 47 + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Hand-written DWARF" +.Lname: + .asciz "A" +.Linfo_string4: + .asciz "int" # string offset=95 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + +.macro generate_unit + .data +A\@: + .long 47 + + .section .debug_str,"MS",@progbits,1 + + .section .debug_info,"",@progbits +.Lcu_begin\@: + .long .Ldebug_info_end\@-.Ldebug_info_start\@ # Length of Unit +.Ldebug_info_start\@: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x30 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .byte 2 # Abbrev [2] 0x1e:0x15 DW_TAG_variable + .long .Lname # DW_AT_name + .long .Ltype\@-.Lcu_begin\@ # DW_AT_type + .byte 9 # DW_AT_location + .byte 3 + .quad A\@ +.Ltype\@: + .byte 3 # Abbrev [3] 0x33:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end\@: + +.endm + +.rept 256 +generate_unit +.endr diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp index e5a72f8846556..951c72543b924 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp @@ -27,72 +27,66 @@ static DWARFDataExtractor LoadSection(SectionList *section_list, return data; } -static const DWARFDataExtractor & -LoadOrGetSection(SectionList *section_list, SectionType section_type, - llvm::Optional &extractor) { - if (!extractor) - extractor = LoadSection(section_list, section_type); - return *extractor; +const DWARFDataExtractor & +DWARFContext::LoadOrGetSection(SectionType main_section_type, + llvm::Optional dwo_section_type, + SectionData &data) { + llvm::call_once(data.flag, [&] { + if (dwo_section_type && isDwo()) + data.data = LoadSection(m_dwo_section_list, *dwo_section_type); + else + data.data = LoadSection(m_main_section_list, main_section_type); + }); + return data.data; } const DWARFDataExtractor &DWARFContext::getOrLoadAbbrevData() { - if (isDwo()) - return LoadOrGetSection(m_dwo_section_list, eSectionTypeDWARFDebugAbbrevDwo, - m_data_debug_abbrev); - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugAbbrev, - m_data_debug_abbrev); + return LoadOrGetSection(eSectionTypeDWARFDebugAbbrev, + eSectionTypeDWARFDebugAbbrevDwo, m_data_debug_abbrev); } const DWARFDataExtractor &DWARFContext::getOrLoadArangesData() { - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugAranges, + return LoadOrGetSection(eSectionTypeDWARFDebugAranges, llvm::None, m_data_debug_aranges); } const DWARFDataExtractor &DWARFContext::getOrLoadAddrData() { - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugAddr, + return LoadOrGetSection(eSectionTypeDWARFDebugAddr, llvm::None, m_data_debug_addr); } const DWARFDataExtractor &DWARFContext::getOrLoadDebugInfoData() { - if (isDwo()) - return LoadOrGetSection(m_dwo_section_list, eSectionTypeDWARFDebugInfoDwo, - m_data_debug_info); - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugInfo, - m_data_debug_info); + return LoadOrGetSection(eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugInfoDwo, m_data_debug_info); } const DWARFDataExtractor &DWARFContext::getOrLoadLineData() { - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugLine, + return LoadOrGetSection(eSectionTypeDWARFDebugLine, llvm::None, m_data_debug_line); } const DWARFDataExtractor &DWARFContext::getOrLoadLineStrData() { - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugLineStr, + return LoadOrGetSection(eSectionTypeDWARFDebugLineStr, llvm::None, m_data_debug_line_str); } const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() { - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugMacro, + return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None, m_data_debug_macro); } const DWARFDataExtractor &DWARFContext::getOrLoadStrData() { - if (isDwo()) - return LoadOrGetSection(m_dwo_section_list, eSectionTypeDWARFDebugStrDwo, - m_data_debug_str); - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugStr, - m_data_debug_str); + return LoadOrGetSection(eSectionTypeDWARFDebugStr, + eSectionTypeDWARFDebugStrDwo, m_data_debug_str); } const DWARFDataExtractor &DWARFContext::getOrLoadStrOffsetsData() { - if (isDwo()) - return LoadOrGetSection(m_dwo_section_list, eSectionTypeDWARFDebugStrOffsetsDwo, - m_data_debug_str_offsets); - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugStrOffsets, + return LoadOrGetSection(eSectionTypeDWARFDebugStrOffsets, + eSectionTypeDWARFDebugStrOffsetsDwo, m_data_debug_str_offsets); } const DWARFDataExtractor &DWARFContext::getOrLoadDebugTypesData() { - return LoadOrGetSection(m_main_section_list, eSectionTypeDWARFDebugTypes, + return LoadOrGetSection(eSectionTypeDWARFDebugTypes, llvm::None, m_data_debug_types); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h index b5ef2254e71ec..4234587fa97bc 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h @@ -12,6 +12,7 @@ #include "DWARFDataExtractor.h" #include "lldb/Core/Section.h" #include "llvm/ADT/Optional.h" +#include "llvm/Support/Threading.h" #include namespace lldb_private { @@ -20,19 +21,29 @@ class DWARFContext { SectionList *m_main_section_list; SectionList *m_dwo_section_list; - llvm::Optional m_data_debug_abbrev; - llvm::Optional m_data_debug_addr; - llvm::Optional m_data_debug_aranges; - llvm::Optional m_data_debug_info; - llvm::Optional m_data_debug_line; - llvm::Optional m_data_debug_line_str; - llvm::Optional m_data_debug_macro; - llvm::Optional m_data_debug_str; - llvm::Optional m_data_debug_str_offsets; - llvm::Optional m_data_debug_types; + struct SectionData { + llvm::once_flag flag; + DWARFDataExtractor data; + }; + + SectionData m_data_debug_abbrev; + SectionData m_data_debug_addr; + SectionData m_data_debug_aranges; + SectionData m_data_debug_info; + SectionData m_data_debug_line; + SectionData m_data_debug_line_str; + SectionData m_data_debug_macro; + SectionData m_data_debug_str; + SectionData m_data_debug_str_offsets; + SectionData m_data_debug_types; bool isDwo() { return m_dwo_section_list != nullptr; } + const DWARFDataExtractor & + LoadOrGetSection(lldb::SectionType main_section_type, + llvm::Optional dwo_section_type, + SectionData &data); + public: explicit DWARFContext(SectionList *main_section_list, SectionList *dwo_section_list) From f750842c8b35c56b58402c1842869a885bfcff56 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 24 May 2019 08:11:12 +0000 Subject: [PATCH 0137/1176] DWARF: Implement DW_AT_signature lookup for type unit support Summary: This patch implements the main feature of type units. When completing a type, if we encounter a DW_AT_signature attribute, we use it's value to lookup the complete definition of the type in the relevant type unit. To enable this lookup, we build up a map of all type units in a symbol file when parsing the units. Then we consult this map when resolving the DW_AT_signature attribute. I include add a couple of tests which exercise the type lookup feature, including one that ensure we do something reasonable in case we fail to lookup the type. A lot of the ideas in this patch have been taken from D32167 and D61505. Reviewers: clayborg, JDevlieghere, aprantl, alexshap Subscribers: mgrang, lldb-commits Differential Revision: https://reviews.llvm.org/D62246 llvm-svn: 361603 --- .../DWARF/Inputs/debug-types-basic.cpp | 10 +- .../DWARF/Inputs/debug-types-expressions.cpp | 8 ++ .../SymbolFile/DWARF/debug-types-basic.test | 8 ++ .../DWARF/debug-types-expressions.test | 15 +++ .../DWARF/debug-types-missing-signature.test | 26 ++++ .../DWARF/debug-types-signature-loop.s | 115 ++++++++++++++++++ .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 32 ++--- .../SymbolFile/DWARF/DWARFDebugInfo.cpp | 35 ++++-- .../Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 6 + .../SymbolFile/DWARF/DWARFFormValue.cpp | 8 ++ .../SymbolFile/DWARF/DWARFTypeUnit.cpp | 1 - .../Plugins/SymbolFile/DWARF/DWARFTypeUnit.h | 8 ++ .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 10 ++ .../Plugins/SymbolFile/DWARF/DWARFUnit.h | 8 ++ 14 files changed, 258 insertions(+), 32 deletions(-) create mode 100644 lldb/lit/SymbolFile/DWARF/debug-types-missing-signature.test create mode 100644 lldb/lit/SymbolFile/DWARF/debug-types-signature-loop.s diff --git a/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-basic.cpp b/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-basic.cpp index e28515269b414..defa8ba5c69e7 100644 --- a/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-basic.cpp +++ b/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-basic.cpp @@ -1,13 +1,15 @@ +enum E { e1, e2, e3 }; +enum class EC { e1, e2, e3 }; + struct A { int i; long l; float f; double d; + E e; + EC ec; }; -enum E { e1, e2, e3 }; -enum class EC { e1, e2, e3 }; - -extern constexpr A a{42, 47l, 4.2f, 4.7}; +extern constexpr A a{42, 47l, 4.2f, 4.7, e1, EC::e3}; extern constexpr E e(e2); extern constexpr EC ec(EC::e2); diff --git a/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-expressions.cpp b/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-expressions.cpp index 7bdd79d097359..fe728cf040dc8 100644 --- a/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-expressions.cpp +++ b/lldb/lit/SymbolFile/DWARF/Inputs/debug-types-expressions.cpp @@ -11,11 +11,19 @@ struct B: public A { namespace ns { struct A { int i = 147; + ::A getA(); A(); }; A::A() = default; + +::A A::getA() { + ::A a; + a.i = i - 1; + return a; } +} // namespace ns + int foo(A *a) { return a->f(); } diff --git a/lldb/lit/SymbolFile/DWARF/debug-types-basic.test b/lldb/lit/SymbolFile/DWARF/debug-types-basic.test index 468a4e8567cfc..bf2c9c69d1dbc 100644 --- a/lldb/lit/SymbolFile/DWARF/debug-types-basic.test +++ b/lldb/lit/SymbolFile/DWARF/debug-types-basic.test @@ -19,6 +19,8 @@ type lookup A # CHECK-NEXT: long l; # CHECK-NEXT: float f; # CHECK-NEXT: double d; +# CHECK-NEXT: E e; +# CHECK-NEXT: EC ec; # CHECK-NEXT: } type lookup E @@ -44,3 +46,9 @@ print (E) 1 print (EC) 1 # CHECK-LABEL: print (EC) 1 # CHECK: (EC) $1 = e2 + +target variable a e ec +# CHECK-LABEL: target variable a e ec +# CHECK: (const A) a = (i = 42, l = 47, f = 4.{{[12].*}}, d = 4.{{[67].*}}, e = e1, ec = e3) +# CHECK: (const E) e = e2 +# CHECK: (const EC) ec = e2 diff --git a/lldb/lit/SymbolFile/DWARF/debug-types-expressions.test b/lldb/lit/SymbolFile/DWARF/debug-types-expressions.test index db67f8a39586e..da40269461afe 100644 --- a/lldb/lit/SymbolFile/DWARF/debug-types-expressions.test +++ b/lldb/lit/SymbolFile/DWARF/debug-types-expressions.test @@ -19,6 +19,13 @@ frame variable a # CHECK-LABEL: frame variable a # CHECK: (B *) a = +frame variable *a +# CHECK-LABEL: frame variable *a +# CHECK: (B) *a = { +# CHECK-NEXT: A = (i = 47) +# CHECK-NEXT: j = 42 +# CHECK-NEXT: } + print a->f() # CHECK-LABEL: print a->f() # CHECK: (int) $0 = 47 @@ -26,3 +33,11 @@ print a->f() print ns::A() # CHECK-LABEL: print ns::A() # CHECK: (ns::A) $1 = (i = 147) + +print ns::A().i + a->i +# CHECK-LABEL: print ns::A().i + a->i +# CHECK: (int) $2 = 194 + +print ns::A().getA() +# CHECK-LABEL: ns::A().getA() +# CHECK: (A) $3 = (i = 146) diff --git a/lldb/lit/SymbolFile/DWARF/debug-types-missing-signature.test b/lldb/lit/SymbolFile/DWARF/debug-types-missing-signature.test new file mode 100644 index 0000000000000..ca5c759136b45 --- /dev/null +++ b/lldb/lit/SymbolFile/DWARF/debug-types-missing-signature.test @@ -0,0 +1,26 @@ +Create a dangling DW_AT_signature reference by stripping the debug_types +section, and make sure lldb does something reasonable. +RUN: %clangxx -target x86_64-pc-linux %S/Inputs/debug-types-basic.cpp \ +RUN: -g -gdwarf-4 -fdebug-types-section -c -o %t.o +RUN: llvm-objcopy --remove-section=.debug_types %t.o %t + + +RUN: %lldb %t -b -o "type lookup A" | FileCheck --check-prefix=LOOKUPA %s +LOOKUPA: no type was found matching 'A' + +RUN: %lldb %t -b -o "type lookup E" | FileCheck --check-prefix=LOOKUPE %s +LOOKUPE: no type was found matching 'E' + +RUN: %lldb %t -b -o "type lookup EC" | FileCheck --check-prefix=LOOKUPEC %s +LOOKUPEC: no type was found matching 'EC' + +RUN: %lldb %t -b -o "print (E) 1" 2>&1 | FileCheck --check-prefix=PRINTE %s +PRINTE: use of undeclared identifier 'E' + +RUN: %lldb %t -b -o "print (EC) 1" 2>&1 | FileCheck --check-prefix=PRINTEC %s +PRINTEC: use of undeclared identifier 'EC' + +RUN: %lldb %t -b -o "target variable a e ec" | FileCheck --check-prefix=VARS %s +VARS: (const (anonymous struct)) a = {} +VARS: (const (anonymous enum)) e = 1 +VARS: (const (anonymous enum)) ec = 1 diff --git a/lldb/lit/SymbolFile/DWARF/debug-types-signature-loop.s b/lldb/lit/SymbolFile/DWARF/debug-types-signature-loop.s new file mode 100644 index 0000000000000..d0d0fd5705a45 --- /dev/null +++ b/lldb/lit/SymbolFile/DWARF/debug-types-signature-loop.s @@ -0,0 +1,115 @@ +# REQUIRES: lld + +# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux -o %t.o %s +# RUN: ld.lld %t.o -o %t +# RUN: %lldb %t -o "target variable e" -b | FileCheck %s + +# CHECK: e = + + .type e,@object # @e + .section .rodata,"a",@progbits + .globl e + .p2align 2 +e: + .long 0 # 0x0 + .size e, 4 + +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Hand-written DWARF" +.Linfo_string1: + .asciz "a.cpp" +.Linfo_string3: + .asciz "e" +.Linfo_string4: + .asciz "unsigned int" +.Linfo_string5: + .asciz "e1" +.Linfo_string6: + .asciz "E" + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 4 # DW_TAG_enumeration_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Ltu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5390450678491038984 # Type Signature + .long .LE-.Ltu_begin0 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x1d DW_TAG_type_unit + .short 4 # DW_AT_language +.LE: + .byte 8 # Abbrev [8] 0x23:0xd DW_TAG_enumeration_type + # DW_AT_declaration + .quad 5390450678491038984 # DW_AT_signature +.Lbase: + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 5 # Abbrev [5] 0xc:0x2c DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 4 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long .LE_sig-.Lcu_begin0 # DW_AT_type + .byte 9 # DW_AT_location + .byte 3 + .quad e +.LE_sig: + .byte 8 # Abbrev [8] 0x2e:0x9 DW_TAG_enumeration_type + # DW_AT_declaration + .quad 5390450678491038984 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index b3c9367861506..1e7cc0468f8bb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -237,7 +237,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, AccessType accessibility = eAccessNone; if (!die) return nullptr; - SymbolFileDWARF *dwarf = die.GetDWARF(); if (log) { DWARFDIE context_die; @@ -252,11 +251,27 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, die.GetTagAsCString(), die.GetName()); } + Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE()); if (type_ptr == DIE_IS_BEING_PARSED) return nullptr; if (type_ptr) return type_ptr->shared_from_this(); + // Set a bit that lets us know that we are currently parsing this + dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + + if (DWARFDIE signature_die = + die.GetAttributeValueAsReferenceDIE(DW_AT_signature)) { + if (TypeSP type_sp = + ParseTypeFromDWARF(sc, signature_die, log, type_is_new_ptr)) { + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + if (clang::DeclContext *decl_ctx = + GetCachedClangDeclContextForDIE(signature_die)) + LinkDeclContextToDIE(decl_ctx, die); + return type_sp; + } + return nullptr; + } TypeList *type_list = dwarf->GetTypeList(); if (type_is_new_ptr) @@ -289,9 +304,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_restrict_type: case DW_TAG_volatile_type: case DW_TAG_unspecified_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - const size_t num_attributes = die.GetAttributes(attributes); uint32_t encoding = 0; DWARFFormValue encoding_uid; @@ -540,9 +552,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_class_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - LanguageType class_language = eLanguageTypeUnknown; bool is_complete_objc_class = false; size_t calling_convention = llvm::dwarf::CallingConvention::DW_CC_normal; @@ -974,9 +983,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, } break; case DW_TAG_enumeration_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - bool is_scoped = false; DWARFFormValue encoding_form; @@ -1136,9 +1142,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: case DW_TAG_subroutine_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - DWARFFormValue type_die_form; bool is_variadic = false; bool is_inline = false; @@ -1658,9 +1661,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, } break; case DW_TAG_array_type: { - // Set a bit that lets us know that we are currently parsing this - dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; - DWARFFormValue type_die_form; uint32_t byte_stride = 0; uint32_t bit_stride = 0; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index c81b6ce05f0f7..0810afc8b1a1d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -15,6 +15,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include "llvm/Support/Casting.h" #include "DWARFCompileUnit.h" #include "DWARFContext.h" @@ -74,12 +75,14 @@ llvm::Expected DWARFDebugInfo::GetCompileUnitAranges() { return *m_cu_aranges_up; } -void Parse(SymbolFileDWARF *dwarf, const DWARFDataExtractor &data, - DIERef::Section section, std::vector &units) { +void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) { + DWARFDataExtractor data = section == DIERef::Section::DebugTypes + ? m_context.getOrLoadDebugTypesData() + : m_context.getOrLoadDebugInfoData(); lldb::offset_t offset = 0; while (data.ValidOffset(offset)) { - llvm::Expected unit_sp = - DWARFUnit::extract(dwarf, units.size(), data, section, &offset); + llvm::Expected unit_sp = DWARFUnit::extract( + m_dwarf2Data, m_units.size(), data, section, &offset); if (!unit_sp) { // FIXME: Propagate this error up. @@ -89,10 +92,13 @@ void Parse(SymbolFileDWARF *dwarf, const DWARFDataExtractor &data, // If it didn't return an error, then it should be returning a valid Unit. assert(*unit_sp); - - units.push_back(*unit_sp); - + m_units.push_back(*unit_sp); offset = (*unit_sp)->GetNextUnitOffset(); + + if (auto *type_unit = llvm::dyn_cast(unit_sp->get())) { + m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(), + unit_sp.get()->GetID()); + } } } @@ -102,10 +108,9 @@ void DWARFDebugInfo::ParseUnitHeadersIfNeeded() { if (!m_dwarf2Data) return; - Parse(m_dwarf2Data, m_context.getOrLoadDebugInfoData(), - DIERef::Section::DebugInfo, m_units); - Parse(m_dwarf2Data, m_context.getOrLoadDebugTypesData(), - DIERef::Section::DebugTypes, m_units); + ParseUnitsFor(DIERef::Section::DebugInfo); + ParseUnitsFor(DIERef::Section::DebugTypes); + llvm::sort(m_type_hash_to_unit_index, llvm::less_first()); } size_t DWARFDebugInfo::GetNumUnits() { @@ -169,6 +174,14 @@ DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section, return result; } +DWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) { + auto pos = llvm::lower_bound(m_type_hash_to_unit_index, + std::make_pair(hash, 0u), llvm::less_first()); + if (pos == m_type_hash_to_unit_index.end() || pos->first != hash) + return nullptr; + return llvm::cast(GetUnitAtIndex(pos->second)); +} + DWARFDIE DWARFDebugInfo::GetDIEForDIEOffset(DIERef::Section section, dw_offset_t die_offset) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index 215862c1aa7b4..0fcf72c0bf029 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -13,6 +13,7 @@ #include #include "DWARFDIE.h" +#include "DWARFTypeUnit.h" #include "DWARFUnit.h" #include "SymbolFileDWARF.h" #include "lldb/Core/STLUtils.h" @@ -46,6 +47,7 @@ class DWARFDebugInfo { DWARFUnit *GetUnitContainingDIEOffset(DIERef::Section section, dw_offset_t die_offset); DWARFUnit *GetUnit(const DIERef &die_ref); + DWARFTypeUnit *GetTypeUnitForHash(uint64_t hash); DWARFDIE GetDIEForDIEOffset(DIERef::Section section, dw_offset_t die_offset); DWARFDIE GetDIE(const DIERef &die_ref); @@ -69,11 +71,15 @@ class DWARFDebugInfo { std::unique_ptr m_cu_aranges_up; // A quick address to compile unit table + std::vector> m_type_hash_to_unit_index; + private: // All parsing needs to be done partially any managed by this class as // accessors are called. void ParseUnitHeadersIfNeeded(); + void ParseUnitsFor(DIERef::Section section); + uint32_t FindUnitIndex(DIERef::Section section, dw_offset_t offset); DISALLOW_COPY_AND_ASSIGN(DWARFDebugInfo); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 9b5faa6ed9bd6..ee4759c547549 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -585,6 +585,14 @@ DWARFDIE DWARFFormValue::Reference() const { return ref_cu->GetDIE(value); } + case DW_FORM_ref_sig8: { + DWARFTypeUnit *tu = + m_unit->GetSymbolFileDWARF()->DebugInfo()->GetTypeUnitForHash(value); + if (!tu) + return {}; + return tu->GetDIE(tu->GetTypeOffset()); + } + default: return {}; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp index 45090039196ef..fcc031bf1ea0f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.cpp @@ -14,7 +14,6 @@ using namespace lldb; using namespace lldb_private; - void DWARFTypeUnit::Dump(Stream *s) const { s->Printf("0x%8.8x: Type Unit: length = 0x%8.8x, version = 0x%4.4x, " "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h index e146e6bf50339..aaf94df96b387 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h @@ -18,6 +18,14 @@ class DWARFTypeUnit : public DWARFUnit { void Dump(lldb_private::Stream *s) const override; + uint64_t GetTypeHash() { return m_header.GetTypeHash(); } + + dw_offset_t GetTypeOffset() { return GetOffset() + m_header.GetTypeOffset(); } + + static bool classof(const DWARFUnit *unit) { + return unit->GetUnitType() == DW_UT_type; + } + private: DWARFTypeUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 65a1fbf74f822..7049fe7d280fd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -715,9 +715,16 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile; } + if (header.IsTypeUnit()) { + header.m_type_hash = data.GetU64(offset_ptr); + header.m_type_offset = data.GetDWARFOffset(offset_ptr); + } + bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version); bool addr_size_OK = (header.m_addr_size == 4) || (header.m_addr_size == 8); + bool type_offset_OK = + !header.IsTypeUnit() || (header.m_type_offset <= header.GetLength()); if (!length_OK) return llvm::make_error( @@ -728,6 +735,9 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section if (!addr_size_OK) return llvm::make_error( "Invalid unit address size"); + if (!type_offset_OK) + return llvm::make_error( + "Type offset out of range"); return header; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 927ca2ed8de8b..165f862ed46f9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -41,6 +41,10 @@ class DWARFUnitHeader { dw_offset_t m_abbr_offset = 0; uint8_t m_unit_type = 0; uint8_t m_addr_size = 0; + + uint64_t m_type_hash = 0; + uint32_t m_type_offset = 0; + uint64_t m_dwo_id = 0; DWARFUnitHeader() = default; @@ -52,6 +56,8 @@ class DWARFUnitHeader { dw_offset_t GetLength() const { return m_length; } dw_offset_t GetAbbrOffset() const { return m_abbr_offset; } uint8_t GetUnitType() const { return m_unit_type; } + uint64_t GetTypeHash() const { return m_type_hash; } + dw_offset_t GetTypeOffset() const { return m_type_offset; } bool IsTypeUnit() const { return m_unit_type == DW_UT_type || m_unit_type == DW_UT_split_type; } @@ -205,6 +211,8 @@ class DWARFUnit : public lldb_private::UserID { DIERef::Section GetDebugSection() const { return m_section; } + uint8_t GetUnitType() const { return m_header.GetUnitType(); } + protected: DWARFUnit(SymbolFileDWARF *dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, From 937af54666c4f4f1cb332bb28cecc86d0e1c5de1 Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Fri, 24 May 2019 08:25:02 +0000 Subject: [PATCH 0138/1176] [ARM] ARMExpandPseudoInsts: add debug messages This pass wasn't printing any messages at all, which I find really inconvenient while debugging/tracing things. It now dumps the before and after of expanded instructions. It doesn't do this yet for all instructions, but this is a good start I guess. Differential Revision: https://reviews.llvm.org/D62297 llvm-svn: 361604 --- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 680142c228899..a27f7f157de81 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/Debug.h" using namespace llvm; @@ -469,6 +470,7 @@ static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc, void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) { MachineInstr &MI = *MBBI; MachineBasicBlock &MBB = *MI.getParent(); + LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump()); const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode()); assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed"); @@ -570,8 +572,8 @@ void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) { // Transfer memoperands. MIB.cloneMemRefs(MI); - MI.eraseFromParent(); + LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump();); } /// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register @@ -579,6 +581,7 @@ void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) { void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { MachineInstr &MI = *MBBI; MachineBasicBlock &MBB = *MI.getParent(); + LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump()); const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode()); assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed"); @@ -645,8 +648,8 @@ void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { // Transfer memoperands. MIB.cloneMemRefs(MI); - MI.eraseFromParent(); + LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump();); } /// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ @@ -654,6 +657,7 @@ void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) { MachineInstr &MI = *MBBI; MachineBasicBlock &MBB = *MI.getParent(); + LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump()); const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode()); assert(TableEntry && "NEONLdStTable lookup failed"); @@ -744,6 +748,7 @@ void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI, unsigned Opc, bool IsExt) { MachineInstr &MI = *MBBI; MachineBasicBlock &MBB = *MI.getParent(); + LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump()); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)); unsigned OpIdx = 0; @@ -773,6 +778,7 @@ void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI, MIB.addReg(SrcReg, RegState::Implicit | getKillRegState(SrcIsKill)); TransferImpOps(MI, MIB, MIB); MI.eraseFromParent(); + LLVM_DEBUG(dbgs() << "To: "; MIB.getInstr()->dump();); } static bool IsAnAddressOperand(const MachineOperand &MO) { @@ -829,6 +835,7 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1); bool RequiresBundling = STI->isTargetWindows() && IsAnAddressOperand(MO); MachineInstrBuilder LO16, HI16; + LLVM_DEBUG(dbgs() << "Expanding: "; MI.dump()); if (!STI->hasV6T2Ops() && (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) { @@ -910,6 +917,8 @@ void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, LO16.add(makeImplicit(MI.getOperand(1))); TransferImpOps(MI, LO16, HI16); MI.eraseFromParent(); + LLVM_DEBUG(dbgs() << "To: "; LO16.getInstr()->dump();); + LLVM_DEBUG(dbgs() << "And: "; HI16.getInstr()->dump();); } /// Expand a CMP_SWAP pseudo-inst to an ldrex/strex loop as simply as @@ -1929,11 +1938,16 @@ bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) { TRI = STI->getRegisterInfo(); AFI = MF.getInfo(); + LLVM_DEBUG(dbgs() << "********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n" + << "********** Function: " << MF.getName() << '\n'); + bool Modified = false; for (MachineBasicBlock &MBB : MF) Modified |= ExpandMBB(MBB); if (VerifyARMPseudo) MF.verify(this, "After expanding ARM pseudo instructions."); + + LLVM_DEBUG(dbgs() << "***************************************************\n"); return Modified; } From d63a2bb35fb25ca17b3cb6e82bcb2050179381b0 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Fri, 24 May 2019 08:32:02 +0000 Subject: [PATCH 0139/1176] [DSE] Bugfix to avoid PartialStoreMerging involving non byte-sized stores Summary: The DeadStoreElimination pass now skips doing PartialStoreMerging when stores overlap according to OW_PartialEarlierWithFullLater and at least one of the stores is having a store size that is different from the size of the type being stored. This solves problems seen in https://bugs.llvm.org/show_bug.cgi?id=41949 for which we in the past could end up with mis-compiles or assertions. The content and location of the padding bits is not formally described (or undefined) in the LangRef at the moment. So the solution is chosen based on that we cannot assume anything about the padding bits when having a store that clobbers more memory than indicated by the type of the value that is stored (such as storing an i6 using an 8-bit store instruction). Fixes: https://bugs.llvm.org/show_bug.cgi?id=41949 Reviewers: spatel, efriedma, fhahn Reviewed By: efriedma Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62250 llvm-svn: 361605 --- llvm/include/llvm/IR/DataLayout.h | 8 +++ .../Scalar/DeadStoreElimination.cpp | 5 ++ .../DeadStoreElimination/PartialStore2.ll | 55 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 llvm/test/Transforms/DeadStoreElimination/PartialStore2.ll diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index 05c72f10d3096..ac9770a15120d 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -453,6 +453,14 @@ class DataLayout { return 8 * getTypeStoreSize(Ty); } + /// Returns true if no extra padding bits are needed when storing the + /// specified type. + /// + /// For example, returns false for i19 that has a 24-bit store size. + bool typeSizeEqualsStoreSize(Type *Ty) const { + return getTypeSizeInBits(Ty) == getTypeStoreSizeInBits(Ty); + } + /// Returns the offset in bytes between successive objects of the /// specified type, including alignment padding. /// diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 75206c28dde34..a81645745b487 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1211,12 +1211,17 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA, auto *Earlier = dyn_cast(DepWrite); auto *Later = dyn_cast(Inst); if (Earlier && isa(Earlier->getValueOperand()) && + DL.typeSizeEqualsStoreSize( + Earlier->getValueOperand()->getType()) && Later && isa(Later->getValueOperand()) && + DL.typeSizeEqualsStoreSize( + Later->getValueOperand()->getType()) && memoryIsNotModifiedBetween(Earlier, Later, AA)) { // If the store we find is: // a) partially overwritten by the store to 'Loc' // b) the later store is fully contained in the earlier one and // c) they both have a constant value + // d) none of the two stores need padding // Merge the two stores, replacing the earlier store's value with a // merge of both values. // TODO: Deal with other constant types (vectors, etc), and probably diff --git a/llvm/test/Transforms/DeadStoreElimination/PartialStore2.ll b/llvm/test/Transforms/DeadStoreElimination/PartialStore2.ll new file mode 100644 index 0000000000000..ebcb0c3808a15 --- /dev/null +++ b/llvm/test/Transforms/DeadStoreElimination/PartialStore2.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s --data-layout "e" -dse -enable-dse-partial-store-merging=true -S | FileCheck --check-prefix CHECK --check-prefix CHECK-LE %s +; RUN: opt < %s --data-layout "E" -dse -enable-dse-partial-store-merging=true -S | FileCheck --check-prefix CHECK --check-prefix CHECK-BE %s + +; This test used to hit an assertion (see PR41949). +; +; Better safe than sorry, do not assume anything about the padding for the +; i28 store that has 32 bits as store size. +define void @test1(i32* %p) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[A:%.*]] = alloca i32 +; CHECK-NEXT: [[B:%.*]] = bitcast i32* [[A]] to i28* +; CHECK-NEXT: [[C:%.*]] = bitcast i32* [[A]] to { i16, i16 }* +; CHECK-NEXT: [[C1:%.*]] = getelementptr inbounds { i16, i16 }, { i16, i16 }* [[C]], i32 0, i32 1 +; CHECK-NEXT: store i28 10, i28* [[B]] +; CHECK-NEXT: store i16 20, i16* [[C1]] +; CHECK-NEXT: call void @test1(i32* [[A]]) +; CHECK-NEXT: ret void +; + %a = alloca i32 + %b = bitcast i32* %a to i28* + %c = bitcast i32* %a to { i16, i16 }* + %c1 = getelementptr inbounds { i16, i16 }, { i16, i16 }* %c, i32 0, i32 1 + store i28 10, i28* %b + store i16 20, i16* %c1 + + call void @test1(i32* %a) + ret void +} + + +; This test used to mis-compile (see PR41949). +; +; Better safe than sorry, do not assume anything about the padding for the +; i12 store that has 16 bits as store size. +define void @test2(i32* %p) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: [[U:%.*]] = alloca i32 +; CHECK-NEXT: [[A:%.*]] = bitcast i32* [[U]] to i32* +; CHECK-NEXT: [[B:%.*]] = bitcast i32* [[U]] to i12* +; CHECK-NEXT: store i32 -1, i32* [[A]] +; CHECK-NEXT: store i12 20, i12* [[B]] +; CHECK-NEXT: call void @test2(i32* [[U]]) +; CHECK-NEXT: ret void +; + %u = alloca i32 + %a = bitcast i32* %u to i32* + %b = bitcast i32* %u to i12* + store i32 -1, i32* %a + store i12 20, i12* %b + + call void @test2(i32* %u) + ret void +} + From c1b482f2a5d0b51770276d5bd6cd17b59b5d2dfd Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 24 May 2019 08:39:40 +0000 Subject: [PATCH 0140/1176] [mips] Always check that `shift and add` optimization is efficient. The D45316 introduced the `shouldTransformMulToShiftsAddsSubs` function to check that breaking down constant multiplications into a series of shifts, adds, and subs is efficient. Unfortunately, this function does not check maximum number of steps on all paths of the algorithm. This patch fixes this bug. Fix for PR41929. Differential Revision: https://reviews.llvm.org/D62166 llvm-svn: 361606 --- llvm/lib/Target/Mips/MipsSEISelLowering.cpp | 57 ++-- llvm/test/CodeGen/Mips/const-mult.ll | 311 ++++---------------- 2 files changed, 87 insertions(+), 281 deletions(-) diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp index 6fbdba4c69190..2fe2f1694f109 100644 --- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp @@ -719,8 +719,31 @@ static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, SelectionDAG &DAG, const MipsSubtarget &Subtarget) { // Estimate the number of operations the below transform will turn a - // constant multiply into. The number is approximately how many powers - // of two summed together that the constant can be broken down into. + // constant multiply into. The number is approximately equal to the minimal + // number of powers of two that constant can be broken down to by adding + // or subtracting them. + // + // If we have taken more than 12[1] / 8[2] steps to attempt the + // optimization for a native sized value, it is more than likely that this + // optimization will make things worse. + // + // [1] MIPS64 requires 6 instructions at most to materialize any constant, + // multiplication requires at least 4 cycles, but another cycle (or two) + // to retrieve the result from the HI/LO registers. + // + // [2] For MIPS32, more than 8 steps is expensive as the constant could be + // materialized in 2 instructions, multiplication requires at least 4 + // cycles, but another cycle (or two) to retrieve the result from the + // HI/LO registers. + // + // TODO: + // - MaxSteps needs to consider the `VT` of the constant for the current + // target. + // - Consider to perform this optimization after type legalization. + // That allows to remove a workaround for types not supported natively. + // - Take in account `-Os, -Oz` flags because this optimization + // increases code size. + unsigned MaxSteps = Subtarget.isABI_O32() ? 8 : 12; SmallVector WorkStack(1, C); unsigned Steps = 0; @@ -732,6 +755,9 @@ static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, if (Val == 0 || Val == 1) continue; + if (Steps >= MaxSteps) + return false; + if (Val.isPowerOf2()) { ++Steps; continue; @@ -740,36 +766,15 @@ static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, APInt Floor = APInt(BitWidth, 1) << Val.logBase2(); APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0) : APInt(BitWidth, 1) << C.ceilLogBase2(); - if ((Val - Floor).ule(Ceil - Val)) { WorkStack.push_back(Floor); WorkStack.push_back(Val - Floor); - ++Steps; - continue; + } else { + WorkStack.push_back(Ceil); + WorkStack.push_back(Ceil - Val); } - WorkStack.push_back(Ceil); - WorkStack.push_back(Ceil - Val); ++Steps; - - // If we have taken more than 12[1] / 8[2] steps to attempt the - // optimization for a native sized value, it is more than likely that this - // optimization will make things worse. - // - // [1] MIPS64 requires 6 instructions at most to materialize any constant, - // multiplication requires at least 4 cycles, but another cycle (or two) - // to retrieve the result from the HI/LO registers. - // - // [2] For MIPS32, more than 8 steps is expensive as the constant could be - // materialized in 2 instructions, multiplication requires at least 4 - // cycles, but another cycle (or two) to retrieve the result from the - // HI/LO registers. - - if (Steps > 12 && (Subtarget.isABI_N32() || Subtarget.isABI_N64())) - return false; - - if (Steps > 8 && Subtarget.isABI_O32()) - return false; } // If the value being multiplied is not supported natively, we have to pay diff --git a/llvm/test/CodeGen/Mips/const-mult.ll b/llvm/test/CodeGen/Mips/const-mult.ll index cbb3c91299fa9..dd90971dcee0b 100644 --- a/llvm/test/CodeGen/Mips/const-mult.ll +++ b/llvm/test/CodeGen/Mips/const-mult.ll @@ -212,44 +212,18 @@ entry: define i32 @mul42949673_32(i32 %a) { ; MIPS32-LABEL: mul42949673_32: ; MIPS32: # %bb.0: -; MIPS32-NEXT: sll $1, $4, 3 -; MIPS32-NEXT: addu $1, $1, $4 -; MIPS32-NEXT: sll $2, $4, 5 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 10 -; MIPS32-NEXT: subu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 13 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 15 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 20 -; MIPS32-NEXT: subu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 25 -; MIPS32-NEXT: sll $3, $4, 23 -; MIPS32-NEXT: addu $1, $3, $1 +; MIPS32-NEXT: lui $1, 655 +; MIPS32-NEXT: ori $1, $1, 23593 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $2, $2, $1 +; MIPS32-NEXT: mul $2, $4, $1 ; ; MIPS64-LABEL: mul42949673_32: ; MIPS64: # %bb.0: -; MIPS64-NEXT: sll $1, $4, 0 -; MIPS64-NEXT: sll $2, $1, 3 -; MIPS64-NEXT: addu $2, $2, $1 -; MIPS64-NEXT: sll $3, $1, 5 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 10 -; MIPS64-NEXT: subu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 13 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 15 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 20 -; MIPS64-NEXT: subu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 25 -; MIPS64-NEXT: sll $1, $1, 23 -; MIPS64-NEXT: addu $1, $1, $2 +; MIPS64-NEXT: lui $1, 655 +; MIPS64-NEXT: ori $1, $1, 23593 +; MIPS64-NEXT: sll $2, $4, 0 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: addu $2, $3, $1 +; MIPS64-NEXT: mul $2, $2, $1 %b = mul i32 %a, 42949673 ret i32 %b } @@ -261,45 +235,18 @@ define i64 @mul42949673_64(i64 %a) { ; MIPS32-NEXT: ori $1, $1, 23593 ; MIPS32-NEXT: multu $4, $1 ; MIPS32-NEXT: mflo $2 -; MIPS32-NEXT: mfhi $1 -; MIPS32-NEXT: sll $3, $5, 3 -; MIPS32-NEXT: addu $3, $3, $5 -; MIPS32-NEXT: sll $4, $5, 5 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 10 -; MIPS32-NEXT: subu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 13 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 15 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 20 -; MIPS32-NEXT: subu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 25 -; MIPS32-NEXT: sll $5, $5, 23 -; MIPS32-NEXT: addu $3, $5, $3 -; MIPS32-NEXT: addu $3, $4, $3 +; MIPS32-NEXT: mfhi $3 +; MIPS32-NEXT: mul $1, $5, $1 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $3, $1, $3 +; MIPS32-NEXT: addu $3, $3, $1 ; ; MIPS64-LABEL: mul42949673_64: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: dsll $1, $4, 3 -; MIPS64-NEXT: daddu $1, $1, $4 -; MIPS64-NEXT: dsll $2, $4, 5 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 10 -; MIPS64-NEXT: dsubu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 13 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 15 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 20 -; MIPS64-NEXT: dsubu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 25 -; MIPS64-NEXT: dsll $3, $4, 23 -; MIPS64-NEXT: daddu $1, $3, $1 +; MIPS64-NEXT: lui $1, 655 +; MIPS64-NEXT: ori $1, $1, 23593 +; MIPS64-NEXT: dmult $4, $1 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: daddu $2, $2, $1 +; MIPS64-NEXT: mflo $2 entry: %b = mul i64 %a, 42949673 ret i64 %b @@ -308,54 +255,18 @@ entry: define i32 @mul22224078_32(i32 %a) { ; MIPS32-LABEL: mul22224078_32: ; MIPS32: # %bb.0: # %entry -; MIPS32-NEXT: sll $1, $4, 1 -; MIPS32-NEXT: sll $2, $4, 4 -; MIPS32-NEXT: subu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 6 -; MIPS32-NEXT: subu $1, $1, $2 -; MIPS32-NEXT: sll $2, $4, 8 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 10 -; MIPS32-NEXT: subu $1, $1, $2 -; MIPS32-NEXT: sll $2, $4, 13 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 16 -; MIPS32-NEXT: subu $1, $1, $2 -; MIPS32-NEXT: sll $2, $4, 24 -; MIPS32-NEXT: sll $3, $4, 22 -; MIPS32-NEXT: sll $5, $4, 20 -; MIPS32-NEXT: sll $4, $4, 18 -; MIPS32-NEXT: addu $1, $4, $1 -; MIPS32-NEXT: addu $1, $5, $1 -; MIPS32-NEXT: addu $1, $3, $1 +; MIPS32-NEXT: lui $1, 339 +; MIPS32-NEXT: ori $1, $1, 7374 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $2, $2, $1 +; MIPS32-NEXT: mul $2, $4, $1 ; ; MIPS64-LABEL: mul22224078_32: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: sll $1, $4, 0 -; MIPS64-NEXT: sll $2, $1, 1 -; MIPS64-NEXT: sll $3, $1, 4 -; MIPS64-NEXT: subu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 6 -; MIPS64-NEXT: subu $2, $2, $3 -; MIPS64-NEXT: sll $3, $1, 8 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 10 -; MIPS64-NEXT: subu $2, $2, $3 -; MIPS64-NEXT: sll $3, $1, 13 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 16 -; MIPS64-NEXT: subu $2, $2, $3 -; MIPS64-NEXT: sll $3, $1, 24 -; MIPS64-NEXT: sll $4, $1, 22 -; MIPS64-NEXT: sll $5, $1, 20 -; MIPS64-NEXT: sll $1, $1, 18 -; MIPS64-NEXT: addu $1, $1, $2 -; MIPS64-NEXT: addu $1, $5, $1 -; MIPS64-NEXT: addu $1, $4, $1 +; MIPS64-NEXT: lui $1, 339 +; MIPS64-NEXT: ori $1, $1, 7374 +; MIPS64-NEXT: sll $2, $4, 0 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: addu $2, $3, $1 +; MIPS64-NEXT: mul $2, $2, $1 entry: %b = mul i32 %a, 22224078 ret i32 %b @@ -368,55 +279,18 @@ define i64 @mul22224078_64(i64 %a) { ; MIPS32-NEXT: ori $1, $1, 7374 ; MIPS32-NEXT: multu $4, $1 ; MIPS32-NEXT: mflo $2 -; MIPS32-NEXT: mfhi $1 -; MIPS32-NEXT: sll $3, $5, 1 -; MIPS32-NEXT: sll $4, $5, 4 -; MIPS32-NEXT: subu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 6 -; MIPS32-NEXT: subu $3, $3, $4 -; MIPS32-NEXT: sll $4, $5, 8 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 10 -; MIPS32-NEXT: subu $3, $3, $4 -; MIPS32-NEXT: sll $4, $5, 13 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 16 -; MIPS32-NEXT: subu $3, $3, $4 -; MIPS32-NEXT: sll $4, $5, 24 -; MIPS32-NEXT: sll $6, $5, 22 -; MIPS32-NEXT: sll $7, $5, 20 -; MIPS32-NEXT: sll $5, $5, 18 -; MIPS32-NEXT: addu $3, $5, $3 -; MIPS32-NEXT: addu $3, $7, $3 -; MIPS32-NEXT: addu $3, $6, $3 -; MIPS32-NEXT: addu $3, $4, $3 +; MIPS32-NEXT: mfhi $3 +; MIPS32-NEXT: mul $1, $5, $1 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $3, $1, $3 +; MIPS32-NEXT: addu $3, $3, $1 ; ; MIPS64-LABEL: mul22224078_64: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: dsll $1, $4, 1 -; MIPS64-NEXT: dsll $2, $4, 4 -; MIPS64-NEXT: dsubu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 6 -; MIPS64-NEXT: dsubu $1, $1, $2 -; MIPS64-NEXT: dsll $2, $4, 8 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 10 -; MIPS64-NEXT: dsubu $1, $1, $2 -; MIPS64-NEXT: dsll $2, $4, 13 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 16 -; MIPS64-NEXT: dsubu $1, $1, $2 -; MIPS64-NEXT: dsll $2, $4, 24 -; MIPS64-NEXT: dsll $3, $4, 22 -; MIPS64-NEXT: dsll $5, $4, 20 -; MIPS64-NEXT: dsll $4, $4, 18 -; MIPS64-NEXT: daddu $1, $4, $1 -; MIPS64-NEXT: daddu $1, $5, $1 -; MIPS64-NEXT: daddu $1, $3, $1 +; MIPS64-NEXT: lui $1, 339 +; MIPS64-NEXT: ori $1, $1, 7374 +; MIPS64-NEXT: dmult $4, $1 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: daddu $2, $2, $1 +; MIPS64-NEXT: mflo $2 entry: %b = mul i64 %a, 22224078 ret i64 %b @@ -425,36 +299,18 @@ entry: define i32 @mul22245375_32(i32 %a) { ; MIPS32-LABEL: mul22245375_32: ; MIPS32: # %bb.0: # %entry -; MIPS32-NEXT: sll $1, $4, 12 -; MIPS32-NEXT: addu $1, $1, $4 -; MIPS32-NEXT: sll $2, $4, 15 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 18 -; MIPS32-NEXT: subu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 20 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 22 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 24 +; MIPS32-NEXT: lui $1, 339 +; MIPS32-NEXT: ori $1, $1, 28671 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $2, $2, $1 +; MIPS32-NEXT: mul $2, $4, $1 ; ; MIPS64-LABEL: mul22245375_32: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: sll $1, $4, 0 -; MIPS64-NEXT: sll $2, $1, 12 -; MIPS64-NEXT: addu $2, $2, $1 -; MIPS64-NEXT: sll $3, $1, 15 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 18 -; MIPS64-NEXT: subu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 20 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 22 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $1, $1, 24 +; MIPS64-NEXT: lui $1, 339 +; MIPS64-NEXT: ori $1, $1, 28671 +; MIPS64-NEXT: sll $2, $4, 0 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: addu $2, $1, $2 +; MIPS64-NEXT: mul $2, $2, $1 entry: %b = mul i32 %a, 22245375 ret i32 %b @@ -467,37 +323,18 @@ define i64 @mul22245375_64(i64 %a) { ; MIPS32-NEXT: ori $1, $1, 28671 ; MIPS32-NEXT: multu $4, $1 ; MIPS32-NEXT: mflo $2 -; MIPS32-NEXT: mfhi $1 -; MIPS32-NEXT: sll $3, $5, 12 -; MIPS32-NEXT: addu $3, $3, $5 -; MIPS32-NEXT: sll $4, $5, 15 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 18 -; MIPS32-NEXT: subu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 20 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 22 -; MIPS32-NEXT: addu $3, $4, $3 -; MIPS32-NEXT: sll $4, $5, 24 -; MIPS32-NEXT: addu $3, $4, $3 +; MIPS32-NEXT: mfhi $3 +; MIPS32-NEXT: mul $1, $5, $1 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $3, $1, $3 +; MIPS32-NEXT: addu $3, $3, $1 ; ; MIPS64-LABEL: mul22245375_64: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: dsll $1, $4, 12 -; MIPS64-NEXT: daddu $1, $1, $4 -; MIPS64-NEXT: dsll $2, $4, 15 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 18 -; MIPS64-NEXT: dsubu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 20 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 22 -; MIPS64-NEXT: daddu $1, $2, $1 -; MIPS64-NEXT: dsll $2, $4, 24 +; MIPS64-NEXT: lui $1, 339 +; MIPS64-NEXT: ori $1, $1, 28671 +; MIPS64-NEXT: dmult $4, $1 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: daddu $2, $2, $1 +; MIPS64-NEXT: mflo $2 entry: %b = mul i64 %a, 22245375 ret i64 %b @@ -506,36 +343,18 @@ entry: define i32 @mul25165824_32(i32 %a) { ; MIPS32-LABEL: mul25165824_32: ; MIPS32: # %bb.0: # %entry -; MIPS32-NEXT: sll $1, $4, 12 -; MIPS32-NEXT: addu $1, $1, $4 -; MIPS32-NEXT: sll $2, $4, 15 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 18 -; MIPS32-NEXT: subu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 20 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 22 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 24 +; MIPS32-NEXT: lui $1, 339 +; MIPS32-NEXT: ori $1, $1, 28671 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $2, $2, $1 +; MIPS32-NEXT: mul $2, $4, $1 ; ; MIPS64-LABEL: mul25165824_32: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: sll $1, $4, 0 -; MIPS64-NEXT: sll $2, $1, 12 -; MIPS64-NEXT: addu $2, $2, $1 -; MIPS64-NEXT: sll $3, $1, 15 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 18 -; MIPS64-NEXT: subu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 20 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 22 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $1, $1, 24 +; MIPS64-NEXT: lui $1, 339 +; MIPS64-NEXT: ori $1, $1, 28671 +; MIPS64-NEXT: sll $2, $4, 0 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: addu $2, $1, $2 +; MIPS64-NEXT: mul $2, $2, $1 entry: %b = mul i32 %a, 22245375 ret i32 %b @@ -572,36 +391,18 @@ entry: define i32 @mul33554432_32(i32 %a) { ; MIPS32-LABEL: mul33554432_32: ; MIPS32: # %bb.0: # %entry -; MIPS32-NEXT: sll $1, $4, 12 -; MIPS32-NEXT: addu $1, $1, $4 -; MIPS32-NEXT: sll $2, $4, 15 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 18 -; MIPS32-NEXT: subu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 20 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 22 -; MIPS32-NEXT: addu $1, $2, $1 -; MIPS32-NEXT: sll $2, $4, 24 +; MIPS32-NEXT: lui $1, 339 +; MIPS32-NEXT: ori $1, $1, 28671 ; MIPS32-NEXT: jr $ra -; MIPS32-NEXT: addu $2, $2, $1 +; MIPS32-NEXT: mul $2, $4, $1 ; ; MIPS64-LABEL: mul33554432_32: ; MIPS64: # %bb.0: # %entry -; MIPS64-NEXT: sll $1, $4, 0 -; MIPS64-NEXT: sll $2, $1, 12 -; MIPS64-NEXT: addu $2, $2, $1 -; MIPS64-NEXT: sll $3, $1, 15 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 18 -; MIPS64-NEXT: subu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 20 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $3, $1, 22 -; MIPS64-NEXT: addu $2, $3, $2 -; MIPS64-NEXT: sll $1, $1, 24 +; MIPS64-NEXT: lui $1, 339 +; MIPS64-NEXT: ori $1, $1, 28671 +; MIPS64-NEXT: sll $2, $4, 0 ; MIPS64-NEXT: jr $ra -; MIPS64-NEXT: addu $2, $1, $2 +; MIPS64-NEXT: mul $2, $2, $1 entry: %b = mul i32 %a, 22245375 ret i32 %b From 3d7a057b0d1d978da382c4ae71653b03f09efa54 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 24 May 2019 08:39:43 +0000 Subject: [PATCH 0141/1176] CodeGen: factor out swifterror value tracking. llvm-svn: 361607 --- .../llvm/CodeGen/FunctionLoweringInfo.h | 42 --- llvm/include/llvm/CodeGen/SelectionDAGISel.h | 2 + .../llvm/CodeGen/SwiftErrorValueTracking.h | 109 ++++++ llvm/lib/CodeGen/CMakeLists.txt | 1 + .../SelectionDAG/FunctionLoweringInfo.cpp | 50 --- .../SelectionDAG/SelectionDAGBuilder.cpp | 36 +- .../SelectionDAG/SelectionDAGBuilder.h | 10 +- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 278 +--------------- llvm/lib/CodeGen/SwiftErrorValueTracking.cpp | 312 ++++++++++++++++++ 9 files changed, 457 insertions(+), 383 deletions(-) create mode 100644 llvm/include/llvm/CodeGen/SwiftErrorValueTracking.h create mode 100644 llvm/lib/CodeGen/SwiftErrorValueTracking.cpp diff --git a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index f5f37d1403a3a..b3077fcaabd4f 100644 --- a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -71,48 +71,6 @@ class FunctionLoweringInfo { /// MBBMap - A mapping from LLVM basic blocks to their machine code entry. DenseMap MBBMap; - /// A map from swifterror value in a basic block to the virtual register it is - /// currently represented by. - DenseMap, unsigned> - SwiftErrorVRegDefMap; - - /// A list of upward exposed vreg uses that need to be satisfied by either a - /// copy def or a phi node at the beginning of the basic block representing - /// the predecessor(s) swifterror value. - DenseMap, unsigned> - SwiftErrorVRegUpwardsUse; - - /// A map from instructions that define/use a swifterror value to the virtual - /// register that represents that def/use. - llvm::DenseMap, unsigned> - SwiftErrorVRegDefUses; - - /// The swifterror argument of the current function. - const Value *SwiftErrorArg; - - using SwiftErrorValues = SmallVector; - /// A function can only have a single swifterror argument. And if it does - /// have a swifterror argument, it must be the first entry in - /// SwiftErrorVals. - SwiftErrorValues SwiftErrorVals; - - /// Get or create the swifterror value virtual register in - /// SwiftErrorVRegDefMap for this basic block. - unsigned getOrCreateSwiftErrorVReg(const MachineBasicBlock *, - const Value *); - - /// Set the swifterror virtual register in the SwiftErrorVRegDefMap for this - /// basic block. - void setCurrentSwiftErrorVReg(const MachineBasicBlock *MBB, const Value *, - unsigned); - - /// Get or create the swifterror value virtual register for a def of a - /// swifterror by an instruction. - std::pair getOrCreateSwiftErrorVRegDefAt(const Instruction *); - std::pair - getOrCreateSwiftErrorVRegUseAt(const Instruction *, const MachineBasicBlock *, - const Value *); - /// ValueMap - Since we emit code for the function a basic block at a time, /// we must remember which virtual registers hold the values for /// cross-basic-block values. diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 36bc6c0bd7398..147c325342fcc 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -34,6 +34,7 @@ namespace llvm { class TargetLibraryInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; + class SwiftErrorValueTracking; class GCFunctionInfo; class ScheduleDAGSDNodes; class LoadInst; @@ -45,6 +46,7 @@ class SelectionDAGISel : public MachineFunctionPass { TargetMachine &TM; const TargetLibraryInfo *LibInfo; FunctionLoweringInfo *FuncInfo; + SwiftErrorValueTracking *SwiftError; MachineFunction *MF; MachineRegisterInfo *RegInfo; SelectionDAG *CurDAG; diff --git a/llvm/include/llvm/CodeGen/SwiftErrorValueTracking.h b/llvm/include/llvm/CodeGen/SwiftErrorValueTracking.h new file mode 100644 index 0000000000000..52dccc714d653 --- /dev/null +++ b/llvm/include/llvm/CodeGen/SwiftErrorValueTracking.h @@ -0,0 +1,109 @@ +//===- SwiftErrorValueTracking.h - Track swifterror VReg vals --*- C++ -*--===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This implements a limited mem2reg-like analysis to promote uses of function +// arguments and allocas marked with swiftalloc from memory into virtual +// registers tracked by this class. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFTERRORVALUETRACKING_H +#define SWIFTERRORVALUETRACKING_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/DebugLoc.h" +#include +#include +#include + + +namespace llvm { + class Function; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class TargetInstrInfo; + class TargetLowering; + +class SwiftErrorValueTracking { + // Some useful objects to reduce the number of function arguments needed. + MachineFunction *MF; + const Function *Fn; + const TargetLowering *TLI; + const TargetInstrInfo *TII; + + /// A map from swifterror value in a basic block to the virtual register it is + /// currently represented by. + DenseMap, unsigned> + VRegDefMap; + + /// A list of upward exposed vreg uses that need to be satisfied by either a + /// copy def or a phi node at the beginning of the basic block representing + /// the predecessor(s) swifterror value. + DenseMap, unsigned> + VRegUpwardsUse; + + /// A map from instructions that define/use a swifterror value to the virtual + /// register that represents that def/use. + llvm::DenseMap, unsigned> + VRegDefUses; + + /// The swifterror argument of the current function. + const Value *SwiftErrorArg; + + using SwiftErrorValues = SmallVector; + /// A function can only have a single swifterror argument. And if it does + /// have a swifterror argument, it must be the first entry in + /// SwiftErrorVals. + SwiftErrorValues SwiftErrorVals; + +public: + /// Initialize data structures for specified new function. + void setFunction(MachineFunction &MF); + + /// Get the (unique) function argument that was marked swifterror, or nullptr + /// if this function has no swifterror args. + const Value *getFunctionArg() const { + return SwiftErrorArg; + } + + /// Get or create the swifterror value virtual register in + /// VRegDefMap for this basic block. + unsigned getOrCreateVReg(const MachineBasicBlock *, const Value *); + + /// Set the swifterror virtual register in the VRegDefMap for this + /// basic block. + void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, unsigned); + + /// Get or create the swifterror value virtual register for a def of a + /// swifterror by an instruction. + unsigned getOrCreateVRegDefAt(const Instruction *, const MachineBasicBlock *, + const Value *); + + /// Get or create the swifterror value virtual register for a use of a + /// swifterror by an instruction. + unsigned getOrCreateVRegUseAt(const Instruction *, const MachineBasicBlock *, + const Value *); + + /// Create initial definitions of swifterror values in the entry block of the + /// current function. + bool createEntriesInEntryBlock(DebugLoc DbgLoc); + + /// Propagate assigned swifterror vregs through a function, synthesizing PHI + /// nodes when needed to maintain consistency. + void propagateVRegs(); + + void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End); +}; + +} + +#endif diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index e76f9f8ed4e7c..fedf04270d297 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -143,6 +143,7 @@ add_llvm_library(LLVMCodeGen StackMaps.cpp StackProtector.cpp StackSlotColoring.cpp + SwiftErrorValueTracking.cpp TailDuplication.cpp TailDuplicator.cpp TargetFrameLoweringImpl.cpp diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index ee2ca90e5d9fc..d8ef10f58aa7c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -519,56 +519,6 @@ unsigned FunctionLoweringInfo::getCatchPadExceptionPointerVReg( return VReg; } -unsigned -FunctionLoweringInfo::getOrCreateSwiftErrorVReg(const MachineBasicBlock *MBB, - const Value *Val) { - auto Key = std::make_pair(MBB, Val); - auto It = SwiftErrorVRegDefMap.find(Key); - // If this is the first use of this swifterror value in this basic block, - // create a new virtual register. - // After we processed all basic blocks we will satisfy this "upwards exposed - // use" by inserting a copy or phi at the beginning of this block. - if (It == SwiftErrorVRegDefMap.end()) { - auto &DL = MF->getDataLayout(); - const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); - auto VReg = MF->getRegInfo().createVirtualRegister(RC); - SwiftErrorVRegDefMap[Key] = VReg; - SwiftErrorVRegUpwardsUse[Key] = VReg; - return VReg; - } else return It->second; -} - -void FunctionLoweringInfo::setCurrentSwiftErrorVReg( - const MachineBasicBlock *MBB, const Value *Val, unsigned VReg) { - SwiftErrorVRegDefMap[std::make_pair(MBB, Val)] = VReg; -} - -std::pair -FunctionLoweringInfo::getOrCreateSwiftErrorVRegDefAt(const Instruction *I) { - auto Key = PointerIntPair(I, true); - auto It = SwiftErrorVRegDefUses.find(Key); - if (It == SwiftErrorVRegDefUses.end()) { - auto &DL = MF->getDataLayout(); - const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); - unsigned VReg = MF->getRegInfo().createVirtualRegister(RC); - SwiftErrorVRegDefUses[Key] = VReg; - return std::make_pair(VReg, true); - } - return std::make_pair(It->second, false); -} - -std::pair -FunctionLoweringInfo::getOrCreateSwiftErrorVRegUseAt(const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) { - auto Key = PointerIntPair(I, false); - auto It = SwiftErrorVRegDefUses.find(Key); - if (It == SwiftErrorVRegDefUses.end()) { - unsigned VReg = getOrCreateSwiftErrorVReg(MBB, Val); - SwiftErrorVRegDefUses[Key] = VReg; - return std::make_pair(VReg, true); - } - return std::make_pair(It->second, false); -} - const Value * FunctionLoweringInfo::getValueFromVirtualReg(unsigned Vreg) { if (VirtReg2Value.empty()) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 5ac9d796f7823..76e5847ba111d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -54,6 +54,7 @@ #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/StackMaps.h" +#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" @@ -1895,7 +1896,7 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { const Function *F = I.getParent()->getParent(); if (TLI.supportSwiftError() && F->getAttributes().hasAttrSomewhere(Attribute::SwiftError)) { - assert(FuncInfo.SwiftErrorArg && "Need a swift error argument"); + assert(SwiftError.getFunctionArg() && "Need a swift error argument"); ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); Flags.setSwiftError(); Outs.push_back(ISD::OutputArg(Flags, EVT(TLI.getPointerTy(DL)) /*vt*/, @@ -1904,8 +1905,8 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { 0 /*partOffs*/)); // Create SDNode for the swifterror virtual register. OutVals.push_back( - DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVRegUseAt( - &I, FuncInfo.MBB, FuncInfo.SwiftErrorArg).first, + DAG.getRegister(SwiftError.getOrCreateVRegUseAt( + &I, FuncInfo.MBB, SwiftError.getFunctionArg()), EVT(TLI.getPointerTy(DL)))); } @@ -4146,15 +4147,13 @@ void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) { SDValue Src = getValue(SrcV); // Create a virtual register, then update the virtual register. - unsigned VReg; bool CreatedVReg; - std::tie(VReg, CreatedVReg) = FuncInfo.getOrCreateSwiftErrorVRegDefAt(&I); + unsigned VReg = + SwiftError.getOrCreateVRegDefAt(&I, FuncInfo.MBB, I.getPointerOperand()); // Chain, DL, Reg, N or Chain, DL, Reg, N, Glue // Chain can be getRoot or getControlRoot. SDValue CopyNode = DAG.getCopyToReg(getRoot(), getCurSDLoc(), VReg, SDValue(Src.getNode(), Src.getResNo())); DAG.setRoot(CopyNode); - if (CreatedVReg) - FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, I.getOperand(1), VReg); } void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) { @@ -4187,8 +4186,7 @@ void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) { // Chain, DL, Reg, VT, Glue or Chain, DL, Reg, VT SDValue L = DAG.getCopyFromReg( getRoot(), getCurSDLoc(), - FuncInfo.getOrCreateSwiftErrorVRegUseAt(&I, FuncInfo.MBB, SV).first, - ValueVTs[0]); + SwiftError.getOrCreateVRegUseAt(&I, FuncInfo.MBB, SV), ValueVTs[0]); setValue(&I, L); } @@ -7073,11 +7071,9 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, SwiftErrorVal = V; // We find the virtual register for the actual swifterror argument. // Instead of using the Value, we use the virtual register instead. - Entry.Node = DAG.getRegister(FuncInfo - .getOrCreateSwiftErrorVRegUseAt( - CS.getInstruction(), FuncInfo.MBB, V) - .first, - EVT(TLI.getPointerTy(DL))); + Entry.Node = DAG.getRegister( + SwiftError.getOrCreateVRegUseAt(CS.getInstruction(), FuncInfo.MBB, V), + EVT(TLI.getPointerTy(DL))); } Args.push_back(Entry); @@ -7118,13 +7114,9 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, if (SwiftErrorVal && TLI.supportSwiftError()) { // Get the last element of InVals. SDValue Src = CLI.InVals.back(); - unsigned VReg; bool CreatedVReg; - std::tie(VReg, CreatedVReg) = - FuncInfo.getOrCreateSwiftErrorVRegDefAt(CS.getInstruction()); + unsigned VReg = SwiftError.getOrCreateVRegDefAt( + CS.getInstruction(), FuncInfo.MBB, SwiftErrorVal); SDValue CopyNode = CLI.DAG.getCopyToReg(Result.second, CLI.DL, VReg, Src); - // We update the virtual register for the actual swifterror argument. - if (CreatedVReg) - FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, SwiftErrorVal, VReg); DAG.setRoot(CopyNode); } } @@ -9761,8 +9753,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) { if (Res.getOpcode() == ISD::CopyFromReg && isSwiftErrorArg) { unsigned Reg = cast(Res.getOperand(1))->getReg(); if (TargetRegisterInfo::isVirtualRegister(Reg)) - FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, - FuncInfo->SwiftErrorArg, Reg); + SwiftError->setCurrentVReg(FuncInfo->MBB, SwiftError->getFunctionArg(), + Reg); } // If this argument is live outside of the entry block, insert a copy from diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 176d726985d75..f68fcd1aa9fe9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -77,6 +77,7 @@ class ResumeInst; class ReturnInst; class SDDbgValue; class StoreInst; +class SwiftErrorValueTracking; class SwitchInst; class TargetLibraryInfo; class TargetMachine; @@ -613,6 +614,9 @@ class SelectionDAGBuilder { /// Information about the function as a whole. FunctionLoweringInfo &FuncInfo; + /// Information about the swifterror values used throughout the function. + SwiftErrorValueTracking &SwiftError; + /// Garbage collection metadata for the function. GCFunctionInfo *GFI; @@ -626,9 +630,9 @@ class SelectionDAGBuilder { LLVMContext *Context; SelectionDAGBuilder(SelectionDAG &dag, FunctionLoweringInfo &funcinfo, - CodeGenOpt::Level ol) - : SDNodeOrder(LowestSDNodeOrder), TM(dag.getTarget()), DAG(dag), - FuncInfo(funcinfo) {} + SwiftErrorValueTracking &swifterror, CodeGenOpt::Level ol) + : SDNodeOrder(LowestSDNodeOrder), TM(dag.getTarget()), DAG(dag), + FuncInfo(funcinfo), SwiftError(swifterror) {} void init(GCFunctionInfo *gfi, AliasAnalysis *AA, const TargetLibraryInfo *li); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index e1c6b18a1bd95..6c9a1cd646ef3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -49,6 +49,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/StackProtector.h" +#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetRegisterInfo.h" @@ -307,8 +308,9 @@ SelectionDAGISel::SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL) : MachineFunctionPass(ID), TM(tm), FuncInfo(new FunctionLoweringInfo()), + SwiftError(new SwiftErrorValueTracking()), CurDAG(new SelectionDAG(tm, OL)), - SDB(new SelectionDAGBuilder(*CurDAG, *FuncInfo, OL)), + SDB(new SelectionDAGBuilder(*CurDAG, *FuncInfo, *SwiftError, OL)), AA(), GFI(), OptLevel(OL), DAGSize(0) { @@ -324,6 +326,7 @@ SelectionDAGISel::~SelectionDAGISel() { delete SDB; delete CurDAG; delete FuncInfo; + delete SwiftError; } void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { @@ -446,6 +449,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { CurDAG->init(*MF, *ORE, this, LibInfo, getAnalysisIfAvailable()); FuncInfo->set(Fn, *MF, CurDAG); + SwiftError->setFunction(*MF); // Now get the optional analyzes if we want to. // This is based on the possibly changed OptLevel (after optnone is taken @@ -1254,77 +1258,6 @@ static bool isFoldedOrDeadInstruction(const Instruction *I, !FuncInfo->isExportedInst(I); // Exported instrs must be computed. } -/// Set up SwiftErrorVals by going through the function. If the function has -/// swifterror argument, it will be the first entry. -static void setupSwiftErrorVals(const Function &Fn, const TargetLowering *TLI, - FunctionLoweringInfo *FuncInfo) { - if (!TLI->supportSwiftError()) - return; - - FuncInfo->SwiftErrorVals.clear(); - FuncInfo->SwiftErrorVRegDefMap.clear(); - FuncInfo->SwiftErrorVRegUpwardsUse.clear(); - FuncInfo->SwiftErrorVRegDefUses.clear(); - FuncInfo->SwiftErrorArg = nullptr; - - // Check if function has a swifterror argument. - bool HaveSeenSwiftErrorArg = false; - for (Function::const_arg_iterator AI = Fn.arg_begin(), AE = Fn.arg_end(); - AI != AE; ++AI) - if (AI->hasSwiftErrorAttr()) { - assert(!HaveSeenSwiftErrorArg && - "Must have only one swifterror parameter"); - (void)HaveSeenSwiftErrorArg; // silence warning. - HaveSeenSwiftErrorArg = true; - FuncInfo->SwiftErrorArg = &*AI; - FuncInfo->SwiftErrorVals.push_back(&*AI); - } - - for (const auto &LLVMBB : Fn) - for (const auto &Inst : LLVMBB) { - if (const AllocaInst *Alloca = dyn_cast(&Inst)) - if (Alloca->isSwiftError()) - FuncInfo->SwiftErrorVals.push_back(Alloca); - } -} - -static void createSwiftErrorEntriesInEntryBlock(FunctionLoweringInfo *FuncInfo, - FastISel *FastIS, - const TargetLowering *TLI, - const TargetInstrInfo *TII, - SelectionDAGBuilder *SDB) { - if (!TLI->supportSwiftError()) - return; - - // We only need to do this when we have swifterror parameter or swifterror - // alloc. - if (FuncInfo->SwiftErrorVals.empty()) - return; - - assert(FuncInfo->MBB == &*FuncInfo->MF->begin() && - "expected to insert into entry block"); - auto &DL = FuncInfo->MF->getDataLayout(); - auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); - for (const auto *SwiftErrorVal : FuncInfo->SwiftErrorVals) { - // We will always generate a copy from the argument. It is always used at - // least by the 'return' of the swifterror. - if (FuncInfo->SwiftErrorArg && FuncInfo->SwiftErrorArg == SwiftErrorVal) - continue; - unsigned VReg = FuncInfo->MF->getRegInfo().createVirtualRegister(RC); - // Assign Undef to Vreg. We construct MI directly to make sure it works - // with FastISel. - BuildMI(*FuncInfo->MBB, FuncInfo->MBB->getFirstNonPHI(), - SDB->getCurDebugLoc(), TII->get(TargetOpcode::IMPLICIT_DEF), - VReg); - - // Keep FastIS informed about the value we just inserted. - if (FastIS) - FastIS->setLastLocalValue(&*std::prev(FuncInfo->InsertPt)); - - FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorVal, VReg); - } -} - /// Collect llvm.dbg.declare information. This is done after argument lowering /// in case the declarations refer to arguments. static void processDbgDeclares(FunctionLoweringInfo *FuncInfo) { @@ -1370,195 +1303,6 @@ static void processDbgDeclares(FunctionLoweringInfo *FuncInfo) { } } -/// Propagate swifterror values through the machine function CFG. -static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) { - auto *TLI = FuncInfo->TLI; - if (!TLI->supportSwiftError()) - return; - - // We only need to do this when we have swifterror parameter or swifterror - // alloc. - if (FuncInfo->SwiftErrorVals.empty()) - return; - - // For each machine basic block in reverse post order. - ReversePostOrderTraversal RPOT(FuncInfo->MF); - for (MachineBasicBlock *MBB : RPOT) { - // For each swifterror value in the function. - for(const auto *SwiftErrorVal : FuncInfo->SwiftErrorVals) { - auto Key = std::make_pair(MBB, SwiftErrorVal); - auto UUseIt = FuncInfo->SwiftErrorVRegUpwardsUse.find(Key); - auto VRegDefIt = FuncInfo->SwiftErrorVRegDefMap.find(Key); - bool UpwardsUse = UUseIt != FuncInfo->SwiftErrorVRegUpwardsUse.end(); - unsigned UUseVReg = UpwardsUse ? UUseIt->second : 0; - bool DownwardDef = VRegDefIt != FuncInfo->SwiftErrorVRegDefMap.end(); - assert(!(UpwardsUse && !DownwardDef) && - "We can't have an upwards use but no downwards def"); - - // If there is no upwards exposed use and an entry for the swifterror in - // the def map for this value we don't need to do anything: We already - // have a downward def for this basic block. - if (!UpwardsUse && DownwardDef) - continue; - - // Otherwise we either have an upwards exposed use vreg that we need to - // materialize or need to forward the downward def from predecessors. - - // Check whether we have a single vreg def from all predecessors. - // Otherwise we need a phi. - SmallVector, 4> VRegs; - SmallSet Visited; - for (auto *Pred : MBB->predecessors()) { - if (!Visited.insert(Pred).second) - continue; - VRegs.push_back(std::make_pair( - Pred, FuncInfo->getOrCreateSwiftErrorVReg(Pred, SwiftErrorVal))); - if (Pred != MBB) - continue; - // We have a self-edge. - // If there was no upwards use in this basic block there is now one: the - // phi needs to use it self. - if (!UpwardsUse) { - UpwardsUse = true; - UUseIt = FuncInfo->SwiftErrorVRegUpwardsUse.find(Key); - assert(UUseIt != FuncInfo->SwiftErrorVRegUpwardsUse.end()); - UUseVReg = UUseIt->second; - } - } - - // We need a phi node if we have more than one predecessor with different - // downward defs. - bool needPHI = - VRegs.size() >= 1 && - std::find_if( - VRegs.begin(), VRegs.end(), - [&](const std::pair &V) - -> bool { return V.second != VRegs[0].second; }) != - VRegs.end(); - - // If there is no upwards exposed used and we don't need a phi just - // forward the swifterror vreg from the predecessor(s). - if (!UpwardsUse && !needPHI) { - assert(!VRegs.empty() && - "No predecessors? The entry block should bail out earlier"); - // Just forward the swifterror vreg from the predecessor(s). - FuncInfo->setCurrentSwiftErrorVReg(MBB, SwiftErrorVal, VRegs[0].second); - continue; - } - - auto DLoc = isa(SwiftErrorVal) - ? cast(SwiftErrorVal)->getDebugLoc() - : DebugLoc(); - const auto *TII = FuncInfo->MF->getSubtarget().getInstrInfo(); - - // If we don't need a phi create a copy to the upward exposed vreg. - if (!needPHI) { - assert(UpwardsUse); - assert(!VRegs.empty() && - "No predecessors? Is the Calling Convention correct?"); - unsigned DestReg = UUseVReg; - BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY), - DestReg) - .addReg(VRegs[0].second); - continue; - } - - // We need a phi: if there is an upwards exposed use we already have a - // destination virtual register number otherwise we generate a new one. - auto &DL = FuncInfo->MF->getDataLayout(); - auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); - unsigned PHIVReg = - UpwardsUse ? UUseVReg - : FuncInfo->MF->getRegInfo().createVirtualRegister(RC); - MachineInstrBuilder SwiftErrorPHI = - BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, - TII->get(TargetOpcode::PHI), PHIVReg); - for (auto BBRegPair : VRegs) { - SwiftErrorPHI.addReg(BBRegPair.second).addMBB(BBRegPair.first); - } - - // We did not have a definition in this block before: store the phi's vreg - // as this block downward exposed def. - if (!UpwardsUse) - FuncInfo->setCurrentSwiftErrorVReg(MBB, SwiftErrorVal, PHIVReg); - } - } -} - -static void preassignSwiftErrorRegs(const TargetLowering *TLI, - FunctionLoweringInfo *FuncInfo, - BasicBlock::const_iterator Begin, - BasicBlock::const_iterator End) { - if (!TLI->supportSwiftError() || FuncInfo->SwiftErrorVals.empty()) - return; - - // Iterator over instructions and assign vregs to swifterror defs and uses. - for (auto It = Begin; It != End; ++It) { - ImmutableCallSite CS(&*It); - if (CS) { - // A call-site with a swifterror argument is both use and def. - const Value *SwiftErrorAddr = nullptr; - for (auto &Arg : CS.args()) { - if (!Arg->isSwiftError()) - continue; - // Use of swifterror. - assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments"); - SwiftErrorAddr = &*Arg; - assert(SwiftErrorAddr->isSwiftError() && - "Must have a swifterror value argument"); - unsigned VReg; bool CreatedReg; - std::tie(VReg, CreatedReg) = FuncInfo->getOrCreateSwiftErrorVRegUseAt( - &*It, FuncInfo->MBB, SwiftErrorAddr); - assert(CreatedReg); - } - if (!SwiftErrorAddr) - continue; - - // Def of swifterror. - unsigned VReg; bool CreatedReg; - std::tie(VReg, CreatedReg) = - FuncInfo->getOrCreateSwiftErrorVRegDefAt(&*It); - assert(CreatedReg); - FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorAddr, VReg); - - // A load is a use. - } else if (const LoadInst *LI = dyn_cast(&*It)) { - const Value *V = LI->getOperand(0); - if (!V->isSwiftError()) - continue; - - unsigned VReg; bool CreatedReg; - std::tie(VReg, CreatedReg) = - FuncInfo->getOrCreateSwiftErrorVRegUseAt(LI, FuncInfo->MBB, V); - assert(CreatedReg); - - // A store is a def. - } else if (const StoreInst *SI = dyn_cast(&*It)) { - const Value *SwiftErrorAddr = SI->getOperand(1); - if (!SwiftErrorAddr->isSwiftError()) - continue; - - // Def of swifterror. - unsigned VReg; bool CreatedReg; - std::tie(VReg, CreatedReg) = - FuncInfo->getOrCreateSwiftErrorVRegDefAt(&*It); - assert(CreatedReg); - FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorAddr, VReg); - - // A return in a swiferror returning function is a use. - } else if (const ReturnInst *R = dyn_cast(&*It)) { - const Function *F = R->getParent()->getParent(); - if(!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError)) - continue; - - unsigned VReg; bool CreatedReg; - std::tie(VReg, CreatedReg) = FuncInfo->getOrCreateSwiftErrorVRegUseAt( - R, FuncInfo->MBB, FuncInfo->SwiftErrorArg); - assert(CreatedReg); - } - } -} - void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FastISelFailed = false; // Initialize the Fast-ISel state, if needed. @@ -1568,8 +1312,6 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { FastIS = TLI->createFastISel(*FuncInfo, LibInfo); } - setupSwiftErrorVals(Fn, TLI, FuncInfo); - ReversePostOrderTraversal RPOT(&Fn); // Lower arguments up front. An RPO iteration always visits the entry block @@ -1615,7 +1357,11 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { else FastIS->setLastLocalValue(nullptr); } - createSwiftErrorEntriesInEntryBlock(FuncInfo, FastIS, TLI, TII, SDB); + + bool Inserted = SwiftError->createEntriesInEntryBlock(SDB->getCurDebugLoc()); + + if (FastIS && Inserted) + FastIS->setLastLocalValue(&*std::prev(FuncInfo->InsertPt)); processDbgDeclares(FuncInfo); @@ -1670,7 +1416,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { unsigned NumFastIselRemaining = std::distance(Begin, End); // Pre-assign swifterror vregs. - preassignSwiftErrorRegs(TLI, FuncInfo, Begin, End); + SwiftError->preassignVRegs(FuncInfo->MBB, Begin, End); // Do FastISel on as many instructions as possible. for (; BI != Begin; --BI) { @@ -1826,7 +1572,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { SP.copyToMachineFrameInfo(MF->getFrameInfo()); - propagateSwiftErrorVRegs(FuncInfo); + SwiftError->propagateVRegs(); delete FastIS; SDB->clearDanglingDebugInfo(); diff --git a/llvm/lib/CodeGen/SwiftErrorValueTracking.cpp b/llvm/lib/CodeGen/SwiftErrorValueTracking.cpp new file mode 100644 index 0000000000000..0359053d8ab7a --- /dev/null +++ b/llvm/lib/CodeGen/SwiftErrorValueTracking.cpp @@ -0,0 +1,312 @@ +//===-- SwiftErrorValueTracking.cpp --------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This implements a limited mem2reg-like analysis to promote uses of function +// arguments and allocas marked with swiftalloc from memory into virtual +// registers tracked by this class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/SwiftErrorValueTracking.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/IR/Value.h" + +using namespace llvm; + +unsigned SwiftErrorValueTracking::getOrCreateVReg(const MachineBasicBlock *MBB, + const Value *Val) { + auto Key = std::make_pair(MBB, Val); + auto It = VRegDefMap.find(Key); + // If this is the first use of this swifterror value in this basic block, + // create a new virtual register. + // After we processed all basic blocks we will satisfy this "upwards exposed + // use" by inserting a copy or phi at the beginning of this block. + if (It == VRegDefMap.end()) { + auto &DL = MF->getDataLayout(); + const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); + auto VReg = MF->getRegInfo().createVirtualRegister(RC); + VRegDefMap[Key] = VReg; + VRegUpwardsUse[Key] = VReg; + return VReg; + } else + return It->second; +} + +void SwiftErrorValueTracking::setCurrentVReg(const MachineBasicBlock *MBB, + const Value *Val, unsigned VReg) { + VRegDefMap[std::make_pair(MBB, Val)] = VReg; +} + +unsigned SwiftErrorValueTracking::getOrCreateVRegDefAt( + const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) { + auto Key = PointerIntPair(I, true); + auto It = VRegDefUses.find(Key); + if (It != VRegDefUses.end()) + return It->second; + + auto &DL = MF->getDataLayout(); + const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); + unsigned VReg = MF->getRegInfo().createVirtualRegister(RC); + VRegDefUses[Key] = VReg; + setCurrentVReg(MBB, Val, VReg); + return VReg; +} + +unsigned SwiftErrorValueTracking::getOrCreateVRegUseAt( + const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) { + auto Key = PointerIntPair(I, false); + auto It = VRegDefUses.find(Key); + if (It != VRegDefUses.end()) + return It->second; + + unsigned VReg = getOrCreateVReg(MBB, Val); + VRegDefUses[Key] = VReg; + return VReg; +} + +/// Set up SwiftErrorVals by going through the function. If the function has +/// swifterror argument, it will be the first entry. +void SwiftErrorValueTracking::setFunction(MachineFunction &mf) { + MF = &mf; + Fn = &MF->getFunction(); + TLI = MF->getSubtarget().getTargetLowering(); + TII = MF->getSubtarget().getInstrInfo(); + + if (!TLI->supportSwiftError()) + return; + + SwiftErrorVals.clear(); + VRegDefMap.clear(); + VRegUpwardsUse.clear(); + VRegDefUses.clear(); + SwiftErrorArg = nullptr; + + // Check if function has a swifterror argument. + bool HaveSeenSwiftErrorArg = false; + for (Function::const_arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end(); + AI != AE; ++AI) + if (AI->hasSwiftErrorAttr()) { + assert(!HaveSeenSwiftErrorArg && + "Must have only one swifterror parameter"); + (void)HaveSeenSwiftErrorArg; // silence warning. + HaveSeenSwiftErrorArg = true; + SwiftErrorArg = &*AI; + SwiftErrorVals.push_back(&*AI); + } + + for (const auto &LLVMBB : *Fn) + for (const auto &Inst : LLVMBB) { + if (const AllocaInst *Alloca = dyn_cast(&Inst)) + if (Alloca->isSwiftError()) + SwiftErrorVals.push_back(Alloca); + } +} + +bool SwiftErrorValueTracking::createEntriesInEntryBlock(DebugLoc DbgLoc) { + if (!TLI->supportSwiftError()) + return false; + + // We only need to do this when we have swifterror parameter or swifterror + // alloc. + if (SwiftErrorVals.empty()) + return false; + + MachineBasicBlock *MBB = &*MF->begin(); + auto &DL = MF->getDataLayout(); + auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); + bool Inserted = false; + for (const auto *SwiftErrorVal : SwiftErrorVals) { + // We will always generate a copy from the argument. It is always used at + // least by the 'return' of the swifterror. + if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal) + continue; + unsigned VReg = MF->getRegInfo().createVirtualRegister(RC); + // Assign Undef to Vreg. We construct MI directly to make sure it works + // with FastISel. + BuildMI(*MBB, MBB->getFirstNonPHI(), DbgLoc, + TII->get(TargetOpcode::IMPLICIT_DEF), VReg); + + setCurrentVReg(MBB, SwiftErrorVal, VReg); + Inserted = true; + } + + return Inserted; +} + +/// Propagate swifterror values through the machine function CFG. +void SwiftErrorValueTracking::propagateVRegs() { + if (!TLI->supportSwiftError()) + return; + + // We only need to do this when we have swifterror parameter or swifterror + // alloc. + if (SwiftErrorVals.empty()) + return; + + // For each machine basic block in reverse post order. + ReversePostOrderTraversal RPOT(MF); + for (MachineBasicBlock *MBB : RPOT) { + // For each swifterror value in the function. + for (const auto *SwiftErrorVal : SwiftErrorVals) { + auto Key = std::make_pair(MBB, SwiftErrorVal); + auto UUseIt = VRegUpwardsUse.find(Key); + auto VRegDefIt = VRegDefMap.find(Key); + bool UpwardsUse = UUseIt != VRegUpwardsUse.end(); + unsigned UUseVReg = UpwardsUse ? UUseIt->second : 0; + bool DownwardDef = VRegDefIt != VRegDefMap.end(); + assert(!(UpwardsUse && !DownwardDef) && + "We can't have an upwards use but no downwards def"); + + // If there is no upwards exposed use and an entry for the swifterror in + // the def map for this value we don't need to do anything: We already + // have a downward def for this basic block. + if (!UpwardsUse && DownwardDef) + continue; + + // Otherwise we either have an upwards exposed use vreg that we need to + // materialize or need to forward the downward def from predecessors. + + // Check whether we have a single vreg def from all predecessors. + // Otherwise we need a phi. + SmallVector, 4> VRegs; + SmallSet Visited; + for (auto *Pred : MBB->predecessors()) { + if (!Visited.insert(Pred).second) + continue; + VRegs.push_back(std::make_pair( + Pred, getOrCreateVReg(Pred, SwiftErrorVal))); + if (Pred != MBB) + continue; + // We have a self-edge. + // If there was no upwards use in this basic block there is now one: the + // phi needs to use it self. + if (!UpwardsUse) { + UpwardsUse = true; + UUseIt = VRegUpwardsUse.find(Key); + assert(UUseIt != VRegUpwardsUse.end()); + UUseVReg = UUseIt->second; + } + } + + // We need a phi node if we have more than one predecessor with different + // downward defs. + bool needPHI = + VRegs.size() >= 1 && + std::find_if( + VRegs.begin(), VRegs.end(), + [&](const std::pair &V) + -> bool { return V.second != VRegs[0].second; }) != + VRegs.end(); + + // If there is no upwards exposed used and we don't need a phi just + // forward the swifterror vreg from the predecessor(s). + if (!UpwardsUse && !needPHI) { + assert(!VRegs.empty() && + "No predecessors? The entry block should bail out earlier"); + // Just forward the swifterror vreg from the predecessor(s). + setCurrentVReg(MBB, SwiftErrorVal, VRegs[0].second); + continue; + } + + auto DLoc = isa(SwiftErrorVal) + ? cast(SwiftErrorVal)->getDebugLoc() + : DebugLoc(); + const auto *TII = MF->getSubtarget().getInstrInfo(); + + // If we don't need a phi create a copy to the upward exposed vreg. + if (!needPHI) { + assert(UpwardsUse); + assert(!VRegs.empty() && + "No predecessors? Is the Calling Convention correct?"); + unsigned DestReg = UUseVReg; + BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY), + DestReg) + .addReg(VRegs[0].second); + continue; + } + + // We need a phi: if there is an upwards exposed use we already have a + // destination virtual register number otherwise we generate a new one. + auto &DL = MF->getDataLayout(); + auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL)); + unsigned PHIVReg = + UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC); + MachineInstrBuilder PHI = + BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, + TII->get(TargetOpcode::PHI), PHIVReg); + for (auto BBRegPair : VRegs) { + PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first); + } + + // We did not have a definition in this block before: store the phi's vreg + // as this block downward exposed def. + if (!UpwardsUse) + setCurrentVReg(MBB, SwiftErrorVal, PHIVReg); + } + } +} + +void SwiftErrorValueTracking::preassignVRegs( + MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End) { + if (!TLI->supportSwiftError() || SwiftErrorVals.empty()) + return; + + // Iterator over instructions and assign vregs to swifterror defs and uses. + for (auto It = Begin; It != End; ++It) { + ImmutableCallSite CS(&*It); + if (CS) { + // A call-site with a swifterror argument is both use and def. + const Value *SwiftErrorAddr = nullptr; + for (auto &Arg : CS.args()) { + if (!Arg->isSwiftError()) + continue; + // Use of swifterror. + assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments"); + SwiftErrorAddr = &*Arg; + assert(SwiftErrorAddr->isSwiftError() && + "Must have a swifterror value argument"); + getOrCreateVRegUseAt(&*It, MBB, SwiftErrorAddr); + } + if (!SwiftErrorAddr) + continue; + + // Def of swifterror. + getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr); + + // A load is a use. + } else if (const LoadInst *LI = dyn_cast(&*It)) { + const Value *V = LI->getOperand(0); + if (!V->isSwiftError()) + continue; + + getOrCreateVRegUseAt(LI, MBB, V); + + // A store is a def. + } else if (const StoreInst *SI = dyn_cast(&*It)) { + const Value *SwiftErrorAddr = SI->getOperand(1); + if (!SwiftErrorAddr->isSwiftError()) + continue; + + // Def of swifterror. + getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr); + + // A return in a swiferror returning function is a use. + } else if (const ReturnInst *R = dyn_cast(&*It)) { + const Function *F = R->getParent()->getParent(); + if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError)) + continue; + + getOrCreateVRegUseAt(R, MBB, SwiftErrorArg); + } + } +} From 3b2157aeed845b0cf70f38cf7d3b29da50291cf8 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 24 May 2019 08:40:13 +0000 Subject: [PATCH 0142/1176] GlobalISel: support swifterror attribute on AArch64. swifterror marks an argument as a register pretending to be a pointer, so we need a guaranteed mem2reg-like analysis of its uses. Fortunately most of the infrastructure can be reused from the DAG world. llvm-svn: 361608 --- .../llvm/CodeGen/GlobalISel/CallLowering.h | 56 +- .../llvm/CodeGen/GlobalISel/IRTranslator.h | 3 + llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 14 +- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 89 ++- .../Target/AArch64/AArch64CallLowering.cpp | 16 +- llvm/lib/Target/AArch64/AArch64CallLowering.h | 14 +- .../AArch64/GlobalISel/arm64-fallback.ll | 21 +- .../CodeGen/AArch64/GlobalISel/swifterror.ll | 518 ++++++++++++++++++ 8 files changed, 684 insertions(+), 47 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 426906af34299..33152e9779ad4 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -147,16 +147,39 @@ class CallLowering { CallLowering(const TargetLowering *TLI) : TLI(TLI) {} virtual ~CallLowering() = default; + /// \return true if the target is capable of handling swifterror values that + /// have been promoted to a specified register. The extended versions of + /// lowerReturn and lowerCall should be implemented. + virtual bool supportSwiftError() const { + return false; + } + /// This hook must be implemented to lower outgoing return values, described /// by \p Val, into the specified virtual registers \p VRegs. /// This hook is used by GlobalISel. /// + /// \p SwiftErrorVReg is non-zero if the function has a swifterror parameter + /// that needs to be implicitly returned. + /// /// \return True if the lowering succeeds, false otherwise. + virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, + ArrayRef VRegs, + unsigned SwiftErrorVReg) const { + if (!supportSwiftError()) { + assert(SwiftErrorVReg == 0 && "attempt to use unsupported swifterror"); + return lowerReturn(MIRBuilder, Val, VRegs); + } + return false; + } + + /// This hook behaves as the extended lowerReturn function, but for targets + /// that do not support swifterror value promotion. virtual bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, ArrayRef VRegs) const { return false; } + /// This hook must be implemented to lower the incoming (formal) /// arguments, described by \p Args, for GlobalISel. Each argument /// must end up in the related virtual register described by VRegs. @@ -180,18 +203,29 @@ class CallLowering { /// \p Callee is the destination of the call. It should be either a register, /// globaladdress, or externalsymbol. /// - /// \p ResTy is the type returned by the function + /// \p OrigRet is a descriptor for the return type of the function. /// - /// \p ResReg is the generic virtual register that the returned - /// value should be lowered into. + /// \p OrigArgs is a list of descriptors of the arguments passed to the + /// function. /// - /// \p ArgTys is a list of the types each member of \p ArgRegs has; used by - /// the target to decide which register/stack slot should be allocated. - /// - /// \p ArgRegs is a list of virtual registers containing each argument that - /// needs to be passed. + /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout + /// parameter, and contains the vreg that the swifterror should be copied into + /// after the call. /// /// \return true if the lowering succeeded, false otherwise. + virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef OrigArgs, + unsigned SwiftErrorVReg) const { + if (!supportSwiftError()) { + assert(SwiftErrorVReg == 0 && "trying to use unsupported swifterror"); + return lowerCall(MIRBuilder, CallConv, Callee, OrigRet, OrigArgs); + } + return false; + } + + /// This hook behaves as the extended lowerCall function, but for targets that + /// do not support swifterror value promotion. virtual bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, ArrayRef OrigArgs) const { @@ -209,6 +243,10 @@ class CallLowering { /// \p ArgRegs is a list of virtual registers containing each argument that /// needs to be passed. /// + /// \p SwiftErrorVReg is non-zero if the call has a swifterror inout + /// parameter, and contains the vreg that the swifterror should be copied into + /// after the call. + /// /// \p GetCalleeReg is a callback to materialize a register for the callee if /// the target determines it cannot jump to the destination based purely on \p /// CI. This might be because \p CI is indirect, or because of the limited @@ -217,7 +255,9 @@ class CallLowering { /// \return true if the lowering succeeded, false otherwise. bool lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, unsigned ResReg, ArrayRef ArgRegs, + unsigned SwiftErrorVReg, std::function GetCalleeReg) const; + }; } // end namespace llvm diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index c75d823501acd..7433a4760151b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -22,6 +22,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Types.h" +#include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Allocator.h" @@ -163,6 +164,8 @@ class IRTranslator : public MachineFunctionPass { /// this function. DenseMap FrameIndices; + SwiftErrorValueTracking SwiftError; + /// \name Methods for translating form LLVM IR to MachineInstr. /// \see ::translate for general information on the translate methods. /// @{ diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index b6b1bef26007e..f144b18aa6358 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -26,9 +26,10 @@ using namespace llvm; void CallLowering::anchor() {} -bool CallLowering::lowerCall( - MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, unsigned ResReg, - ArrayRef ArgRegs, std::function GetCalleeReg) const { +bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS, + unsigned ResReg, ArrayRef ArgRegs, + unsigned SwiftErrorVReg, + std::function GetCalleeReg) const { auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout(); // First step is to marshall all the function's parameters into the correct @@ -41,8 +42,8 @@ bool CallLowering::lowerCall( ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}, i < NumFixedArgs}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS); - // We don't currently support swifterror or swiftself args. - if (OrigArg.Flags.isSwiftError() || OrigArg.Flags.isSwiftSelf()) + // We don't currently support swiftself args. + if (OrigArg.Flags.isSwiftSelf()) return false; OrigArgs.push_back(OrigArg); ++i; @@ -58,7 +59,8 @@ bool CallLowering::lowerCall( if (!OrigRet.Ty->isVoidTy()) setArgFlags(OrigRet, AttributeList::ReturnIndex, DL, CS); - return lowerCall(MIRBuilder, CS.getCallingConv(), Callee, OrigRet, OrigArgs); + return lowerCall(MIRBuilder, CS.getCallingConv(), Callee, OrigRet, OrigArgs, + SwiftErrorVReg); } template diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 4ac720181edcf..b1a53c540247a 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -354,11 +354,16 @@ bool IRTranslator::translateRet(const User &U, MachineIRBuilder &MIRBuilder) { if (Ret) VRegs = getOrCreateVRegs(*Ret); + unsigned SwiftErrorVReg = 0; + if (CLI->supportSwiftError() && SwiftError.getFunctionArg()) { + SwiftErrorVReg = SwiftError.getOrCreateVRegUseAt( + &RI, &MIRBuilder.getMBB(), SwiftError.getFunctionArg()); + } + // The target may mess up with the insertion point, but // this is not important as a return is the last instruction // of the block anyway. - - return CLI->lowerReturn(MIRBuilder, Ret, VRegs); + return CLI->lowerReturn(MIRBuilder, Ret, VRegs, SwiftErrorVReg); } bool IRTranslator::translateBr(const User &U, MachineIRBuilder &MIRBuilder) { @@ -447,6 +452,14 @@ bool IRTranslator::translateIndirectBr(const User &U, return true; } +static bool isSwiftError(const Value *V) { + if (auto Arg = dyn_cast(V)) + return Arg->hasSwiftErrorAttr(); + if (auto AI = dyn_cast(V)) + return AI->isSwiftError(); + return false; +} + bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) { const LoadInst &LI = cast(U); @@ -464,6 +477,15 @@ bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) { Type *OffsetIRTy = DL->getIntPtrType(LI.getPointerOperandType()); LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL); + if (CLI->supportSwiftError() && isSwiftError(LI.getPointerOperand())) { + assert(Regs.size() == 1 && "swifterror should be single pointer"); + unsigned VReg = SwiftError.getOrCreateVRegUseAt(&LI, &MIRBuilder.getMBB(), + LI.getPointerOperand()); + MIRBuilder.buildCopy(Regs[0], VReg); + return true; + } + + for (unsigned i = 0; i < Regs.size(); ++i) { unsigned Addr = 0; MIRBuilder.materializeGEP(Addr, Base, OffsetTy, Offsets[i] / 8); @@ -496,6 +518,15 @@ bool IRTranslator::translateStore(const User &U, MachineIRBuilder &MIRBuilder) { Type *OffsetIRTy = DL->getIntPtrType(SI.getPointerOperandType()); LLT OffsetTy = getLLTForType(*OffsetIRTy, *DL); + if (CLI->supportSwiftError() && isSwiftError(SI.getPointerOperand())) { + assert(Vals.size() == 1 && "swifterror should be single pointer"); + + unsigned VReg = SwiftError.getOrCreateVRegDefAt(&SI, &MIRBuilder.getMBB(), + SI.getPointerOperand()); + MIRBuilder.buildCopy(VReg, Vals[0]); + return true; + } + for (unsigned i = 0; i < Vals.size(); ++i) { unsigned Addr = 0; MIRBuilder.materializeGEP(Addr, Base, OffsetTy, Offsets[i] / 8); @@ -1154,16 +1185,29 @@ bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) { : getOrCreateVReg(CI); SmallVector Args; - for (auto &Arg: CI.arg_operands()) + unsigned SwiftErrorVReg = 0; + for (auto &Arg: CI.arg_operands()) { + if (CLI->supportSwiftError() && isSwiftError(Arg)) { + LLT Ty = getLLTForType(*Arg->getType(), *DL); + unsigned InVReg = MRI->createGenericVirtualRegister(Ty); + MIRBuilder.buildCopy(InVReg, SwiftError.getOrCreateVRegUseAt( + &CI, &MIRBuilder.getMBB(), Arg)); + Args.push_back(InVReg); + SwiftErrorVReg = + SwiftError.getOrCreateVRegDefAt(&CI, &MIRBuilder.getMBB(), Arg); + continue; + } Args.push_back(packRegs(*Arg, MIRBuilder)); + } MF->getFrameInfo().setHasCalls(true); - bool Success = CLI->lowerCall(MIRBuilder, &CI, Res, Args, [&]() { - return getOrCreateVReg(*CI.getCalledValue()); - }); + bool Success = + CLI->lowerCall(MIRBuilder, &CI, Res, Args, SwiftErrorVReg, + [&]() { return getOrCreateVReg(*CI.getCalledValue()); }); if (IsSplitType) unpackRegs(CI, Res, MIRBuilder); + return Success; } @@ -1239,10 +1283,23 @@ bool IRTranslator::translateInvoke(const User &U, if (!I.getType()->isVoidTy()) Res = MRI->createGenericVirtualRegister(getLLTForType(*I.getType(), *DL)); SmallVector Args; - for (auto &Arg: I.arg_operands()) + unsigned SwiftErrorVReg = 0; + for (auto &Arg : I.arg_operands()) { + if (CLI->supportSwiftError() && isSwiftError(Arg)) { + LLT Ty = getLLTForType(*Arg->getType(), *DL); + unsigned InVReg = MRI->createGenericVirtualRegister(Ty); + MIRBuilder.buildCopy(InVReg, SwiftError.getOrCreateVRegUseAt( + &I, &MIRBuilder.getMBB(), Arg)); + Args.push_back(InVReg); + SwiftErrorVReg = + SwiftError.getOrCreateVRegDefAt(&I, &MIRBuilder.getMBB(), Arg); + continue; + } + Args.push_back(packRegs(*Arg, MIRBuilder)); + } - if (!CLI->lowerCall(MIRBuilder, &I, Res, Args, + if (!CLI->lowerCall(MIRBuilder, &I, Res, Args, SwiftErrorVReg, [&]() { return getOrCreateVReg(*I.getCalledValue()); })) return false; @@ -1331,7 +1388,7 @@ bool IRTranslator::translateAlloca(const User &U, auto &AI = cast(U); if (AI.isSwiftError()) - return false; + return true; if (AI.isStaticAlloca()) { unsigned Res = getOrCreateVReg(AI); @@ -1776,6 +1833,10 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { MF->push_back(EntryBB); EntryBuilder->setMBB(*EntryBB); + DebugLoc DbgLoc = F.getEntryBlock().getFirstNonPHI()->getDebugLoc(); + SwiftError.setFunction(CurMF); + SwiftError.createEntriesInEntryBlock(DbgLoc); + // Create all blocks, in IR order, to preserve the layout. for (const BasicBlock &BB: F) { auto *&MBB = BBToMBB[&BB]; @@ -1797,14 +1858,18 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { continue; // Don't handle zero sized types. VRegArgs.push_back( MRI->createGenericVirtualRegister(getLLTForType(*Arg.getType(), *DL))); + + if (Arg.hasSwiftErrorAttr()) + SwiftError.setCurrentVReg(EntryBB, SwiftError.getFunctionArg(), + VRegArgs.back()); } // We don't currently support translating swifterror or swiftself functions. for (auto &Arg : F.args()) { - if (Arg.hasSwiftErrorAttr() || Arg.hasSwiftSelfAttr()) { + if (Arg.hasSwiftSelfAttr()) { OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure", F.getSubprogram(), &F.getEntryBlock()); - R << "unable to lower arguments due to swifterror/swiftself: " + R << "unable to lower arguments due to swiftself: " << ore::NV("Prototype", F.getType()); reportTranslationError(*MF, *TPC, *ORE, R); return false; @@ -1880,6 +1945,8 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { finishPendingPhis(); + SwiftError.propagateVRegs(); + // Merge the argument lowering and constants block with its single // successor, the LLVM-IR entry block. We want the basic block to // be maximal. diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp index c568cd9b7c3e3..9d04dd8658347 100644 --- a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp @@ -232,7 +232,8 @@ void AArch64CallLowering::splitToValueTypes( bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef VRegs) const { + ArrayRef VRegs, + unsigned SwiftErrorVReg) const { auto MIB = MIRBuilder.buildInstrNoInsert(AArch64::RET_ReallyLR); assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) && "Return value without a vreg"); @@ -340,6 +341,11 @@ bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, Success = handleAssignments(MIRBuilder, SplitArgs, Handler); } + if (SwiftErrorVReg) { + MIB.addUse(AArch64::X21, RegState::Implicit); + MIRBuilder.buildCopy(AArch64::X21, SwiftErrorVReg); + } + MIRBuilder.insertInstr(MIB); return Success; } @@ -420,7 +426,8 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, - ArrayRef OrigArgs) const { + ArrayRef OrigArgs, + unsigned SwiftErrorVReg) const { MachineFunction &MF = MIRBuilder.getMF(); const Function &F = MF.getFunction(); MachineRegisterInfo &MRI = MF.getRegInfo(); @@ -503,6 +510,11 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, MIRBuilder.buildSequence(OrigRet.Reg, SplitRegs, RegOffsets); } + if (SwiftErrorVReg) { + MIB.addDef(AArch64::X21, RegState::Implicit); + MIRBuilder.buildCopy(SwiftErrorVReg, AArch64::X21); + } + CallSeqStart.addImm(Handler.StackSize).addImm(0); MIRBuilder.buildInstr(AArch64::ADJCALLSTACKUP) .addImm(Handler.StackSize) diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.h b/llvm/lib/Target/AArch64/AArch64CallLowering.h index 76337567c7a50..6aab6bd170317 100644 --- a/llvm/lib/Target/AArch64/AArch64CallLowering.h +++ b/llvm/lib/Target/AArch64/AArch64CallLowering.h @@ -34,14 +34,24 @@ class AArch64CallLowering: public CallLowering { AArch64CallLowering(const AArch64TargetLowering &TLI); bool lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, - ArrayRef VRegs) const override; + ArrayRef VRegs, + unsigned SwiftErrorVReg) const override; bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef VRegs) const override; bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, const MachineOperand &Callee, const ArgInfo &OrigRet, - ArrayRef OrigArgs) const override; + ArrayRef OrigArgs, + unsigned SwiftErrorVReg) const override; + + bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef OrigArgs) const override { + return lowerCall(MIRBuilder, CallConv, Callee, OrigRet, OrigArgs, 0); + } + + bool supportSwiftError() const override { return true; } private: using RegHandler = std::function:0:0: unable to lower arguments due to swifterror/swiftself: void (%swift_error**)* (in function: swifterror_param) -; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for swifterror_param -define void @swifterror_param(%swift_error** swifterror %error_ptr_ref) { +; FALLBACK-WITH-REPORT-ERR: remark: :0:0: unable to lower arguments due to swiftself: void (%swift_error**)* (in function: swiftself_param) +; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for swiftself_param +define void @swiftself_param(%swift_error** swiftself %error_ptr_ref) { ret void } - -; FALLBACK-WITH-REPORT-ERR: remark: :0:0: unable to translate instruction: alloca: ' %error_ptr_ref = alloca swifterror %swift_error*' (in function: swifterror_alloca) -; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for swifterror_alloca -; We can't currently test the call parameters being swifterror because the value -; must come from a swifterror alloca or parameter, at which point we already -; fallback. As long as those cases work however we should be fine. -define void @swifterror_alloca(i8* %error_ref) { -entry: - %error_ptr_ref = alloca swifterror %swift_error* - store %swift_error* null, %swift_error** %error_ptr_ref - call void @swifterror_param(%swift_error** swifterror %error_ptr_ref) - ret void -} - - diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll b/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll new file mode 100644 index 0000000000000..83e48a6a504c7 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll @@ -0,0 +1,518 @@ +; RUN: llc -verify-machineinstrs -frame-pointer=all -global-isel < %s -mtriple=aarch64-apple-ios -disable-post-ra | FileCheck %s + +declare i8* @malloc(i64) +declare void @free(i8*) +%swift_error = type {i64, i8} + +; This tests the basic usage of a swifterror parameter. "foo" is the function +; that takes a swifterror parameter and "caller" is the caller of "foo". +define float @foo(%swift_error** swifterror %error_ptr_ref) { +; CHECK-LABEL: foo: +; CHECK: mov [[ID:w[0-9]+]], #1 +; CHECK: mov x0, #16 +; CHECK: malloc +; CHECK: strb [[ID]], [x0, #8] +; CHECK: mov x21, x0 +; CHECK-NOT: x21 + +entry: + %call = call i8* @malloc(i64 16) + %call.0 = bitcast i8* %call to %swift_error* + store %swift_error* %call.0, %swift_error** %error_ptr_ref + %tmp = getelementptr inbounds i8, i8* %call, i64 8 + store i8 1, i8* %tmp + ret float 1.0 +} + +; "caller" calls "foo" that takes a swifterror parameter. +define float @caller(i8* %error_ref) { +; CHECK-LABEL: caller: +; CHECK: mov [[ID:x[0-9]+]], x0 +; CHECK: mov [[ZERO:x[0-9]+]], #0 +; CHECK: mov x21, #0 +; CHECK: bl {{.*}}foo +; CHECK: mov x0, x21 +; CHECK: cmp x21, [[ZERO]] +; CHECK: b.ne +; Access part of the error object and save it to error_ref +; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] +; CHECK: strb [[CODE]], [{{.*}}[[ID]]] +; CHECK: bl {{.*}}free + +entry: + %error_ptr_ref = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr_ref + %call = call float @foo(%swift_error** swifterror %error_ptr_ref) + %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref + %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null + %tmp = bitcast %swift_error* %error_from_foo to i8* + br i1 %had_error_from_foo, label %handler, label %cont +cont: + %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 + %t = load i8, i8* %v1 + store i8 %t, i8* %error_ref + br label %handler +handler: + call void @free(i8* %tmp) + ret float 1.0 +} + +; "caller2" is the caller of "foo", it calls "foo" inside a loop. +define float @caller2(i8* %error_ref) { +; CHECK-LABEL: caller2: +; CHECK: mov [[ID:x[0-9]+]], x0 +; CHECK: mov [[ZERO:x[0-9]+]], #0 +; CHECK: fmov [[CMP:s[0-9]+]], #1.0 +; CHECK: mov x21, #0 +; CHECK: bl {{.*}}foo +; CHECK: cmp x21, [[ZERO]] +; CHECK: b.ne +; CHECK: fcmp s0, [[CMP]] +; CHECK: b.le +; Access part of the error object and save it to error_ref +; CHECK: ldrb [[CODE:w[0-9]+]], [x21, #8] +; CHECK: strb [[CODE]], [{{.*}}[[ID]]] +; CHECK: mov x0, x21 +; CHECK: bl {{.*}}free + +entry: + %error_ptr_ref = alloca swifterror %swift_error* + br label %bb_loop +bb_loop: + store %swift_error* null, %swift_error** %error_ptr_ref + %call = call float @foo(%swift_error** swifterror %error_ptr_ref) + %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref + %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null + %tmp = bitcast %swift_error* %error_from_foo to i8* + br i1 %had_error_from_foo, label %handler, label %cont +cont: + %cmp = fcmp ogt float %call, 1.000000e+00 + br i1 %cmp, label %bb_end, label %bb_loop +bb_end: + %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 + %t = load i8, i8* %v1 + store i8 %t, i8* %error_ref + br label %handler +handler: + call void @free(i8* %tmp) + ret float 1.0 +} + +; "foo_if" is a function that takes a swifterror parameter, it sets swifterror +; under a certain condition. +define float @foo_if(%swift_error** swifterror %error_ptr_ref, i32 %cc) { +; CHECK-LABEL: foo_if: +; CHECK: cbz w0 +; CHECK: mov [[ID:w[0-9]+]], #1 +; CHECK: mov x0, #16 +; CHECK: malloc +; CHECK: strb [[ID]], [x0, #8] +; CHECK: mov x21, x0 +; CHECK-NOT: x21 +; CHECK: ret + +entry: + %cond = icmp ne i32 %cc, 0 + br i1 %cond, label %gen_error, label %normal + +gen_error: + %call = call i8* @malloc(i64 16) + %call.0 = bitcast i8* %call to %swift_error* + store %swift_error* %call.0, %swift_error** %error_ptr_ref + %tmp = getelementptr inbounds i8, i8* %call, i64 8 + store i8 1, i8* %tmp + ret float 1.0 + +normal: + ret float 0.0 +} + +; "foo_loop" is a function that takes a swifterror parameter, it sets swifterror +; under a certain condition inside a loop. +define float @foo_loop(%swift_error** swifterror %error_ptr_ref, i32 %cc, float %cc2) { +; CHECK-LABEL: foo_loop: +; CHECK: cbz +; CHECK: mov x0, #16 +; CHECK: malloc +; CHECK: mov x21, x0 +; CHECK: strb w{{.*}}, [x0, #8] +; CHECK: fcmp +; CHECK: b.le +; CHECK: ret + +entry: + br label %bb_loop + +bb_loop: + %cond = icmp ne i32 %cc, 0 + br i1 %cond, label %gen_error, label %bb_cont + +gen_error: + %call = call i8* @malloc(i64 16) + %call.0 = bitcast i8* %call to %swift_error* + store %swift_error* %call.0, %swift_error** %error_ptr_ref + %tmp = getelementptr inbounds i8, i8* %call, i64 8 + store i8 1, i8* %tmp + br label %bb_cont + +bb_cont: + %cmp = fcmp ogt float %cc2, 1.000000e+00 + br i1 %cmp, label %bb_end, label %bb_loop +bb_end: + ret float 0.0 +} + +%struct.S = type { i32, i32, i32, i32, i32, i32 } + +; "foo_sret" is a function that takes a swifterror parameter, it also has a sret +; parameter. +define void @foo_sret(%struct.S* sret %agg.result, i32 %val1, %swift_error** swifterror %error_ptr_ref) { +; CHECK-LABEL: foo_sret: +; CHECK: mov [[SRET:x[0-9]+]], x8 +; CHECK: mov [[ID:w[0-9]+]], #1 +; CHECK: mov x0, #16 +; CHECK: malloc +; CHECK: strb [[ID]], [x0, #8] +; CHECK: str w{{.*}}, [{{.*}}[[SRET]], #4] +; CHECK: mov x21, x0 +; CHECK-NOT: x21 + +entry: + %call = call i8* @malloc(i64 16) + %call.0 = bitcast i8* %call to %swift_error* + store %swift_error* %call.0, %swift_error** %error_ptr_ref + %tmp = getelementptr inbounds i8, i8* %call, i64 8 + store i8 1, i8* %tmp + %v2 = getelementptr inbounds %struct.S, %struct.S* %agg.result, i32 0, i32 1 + store i32 %val1, i32* %v2 + ret void +} + +; "caller3" calls "foo_sret" that takes a swifterror parameter. +define float @caller3(i8* %error_ref) { +; CHECK-LABEL: caller3: +; CHECK: mov [[ID:x[0-9]+]], x0 +; CHECK: mov [[ZERO:x[0-9]+]], #0 +; CHECK: mov x21, #0 +; CHECK: bl {{.*}}foo_sret +; CHECK: mov x0, x21 +; CHECK: cmp x21, [[ZERO]] +; CHECK: b.ne +; Access part of the error object and save it to error_ref +; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] +; CHECK: strb [[CODE]], [{{.*}}[[ID]]] +; CHECK: bl {{.*}}free + +entry: + %s = alloca %struct.S, align 8 + %error_ptr_ref = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr_ref + call void @foo_sret(%struct.S* sret %s, i32 1, %swift_error** swifterror %error_ptr_ref) + %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref + %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null + %tmp = bitcast %swift_error* %error_from_foo to i8* + br i1 %had_error_from_foo, label %handler, label %cont +cont: + %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 + %t = load i8, i8* %v1 + store i8 %t, i8* %error_ref + br label %handler +handler: + call void @free(i8* %tmp) + ret float 1.0 +} + +; "foo_vararg" is a function that takes a swifterror parameter, it also has +; variable number of arguments. +declare void @llvm.va_start(i8*) nounwind +define float @foo_vararg(%swift_error** swifterror %error_ptr_ref, ...) { +; CHECK-LABEL: foo_vararg: +; CHECK-DAG: mov [[ID:w[0-9]+]], #1 +; CHECK: mov x0, #16 +; CHECK: malloc +; CHECK-DAG: strb [[ID]], [x0, #8] + +; First vararg +; CHECK: ldr {{w[0-9]+}}, [x[[ARG1:[0-9]+]]] +; Second vararg +; CHECK: mov [[EIGHT:x[0-9]+]], #8 +; CHECK: add x[[ARG2:[0-9]+]], x[[ARG1]], [[EIGHT]] +; CHECK: ldr {{w[0-9]+}}, [x[[ARG2]]] +; Third vararg +; CHECK: add x[[ARG3:[0-9]+]], x[[ARG2]], [[EIGHT]] +; CHECK: ldr {{w[0-9]+}}, [x[[ARG3]]] + +; CHECK: mov x21, x0 +; CHECK-NOT: x21 +entry: + %call = call i8* @malloc(i64 16) + %call.0 = bitcast i8* %call to %swift_error* + store %swift_error* %call.0, %swift_error** %error_ptr_ref + %tmp = getelementptr inbounds i8, i8* %call, i64 8 + store i8 1, i8* %tmp + + %args = alloca i8*, align 8 + %a10 = alloca i32, align 4 + %a11 = alloca i32, align 4 + %a12 = alloca i32, align 4 + %v10 = bitcast i8** %args to i8* + call void @llvm.va_start(i8* %v10) + %v11 = va_arg i8** %args, i32 + store i32 %v11, i32* %a10, align 4 + %v12 = va_arg i8** %args, i32 + store i32 %v12, i32* %a11, align 4 + %v13 = va_arg i8** %args, i32 + store i32 %v13, i32* %a12, align 4 + + ret float 1.0 +} + +; "caller4" calls "foo_vararg" that takes a swifterror parameter. +define float @caller4(i8* %error_ref) { +; CHECK-LABEL: caller4: + +; CHECK: mov [[ID:x[0-9]+]], x0 +; CHECK: mov [[ZERO:x[0-9]+]], #0 +; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp] +; CHECK: mov x21, #0 +; CHECK: str {{x[0-9]+}}, [sp, #16] + +; CHECK: bl {{.*}}foo_vararg +; CHECK: mov x0, x21 +; CHECK: cmp x21, [[ZERO]] +; CHECK: b.ne +; Access part of the error object and save it to error_ref +; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8] +; CHECK: strb [[CODE]], [{{.*}}[[ID]]] +; CHECK: bl {{.*}}free +entry: + %error_ptr_ref = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr_ref + + %a10 = alloca i32, align 4 + %a11 = alloca i32, align 4 + %a12 = alloca i32, align 4 + store i32 10, i32* %a10, align 4 + store i32 11, i32* %a11, align 4 + store i32 12, i32* %a12, align 4 + %v10 = load i32, i32* %a10, align 4 + %v11 = load i32, i32* %a11, align 4 + %v12 = load i32, i32* %a12, align 4 + + %call = call float (%swift_error**, ...) @foo_vararg(%swift_error** swifterror %error_ptr_ref, i32 %v10, i32 %v11, i32 %v12) + %error_from_foo = load %swift_error*, %swift_error** %error_ptr_ref + %had_error_from_foo = icmp ne %swift_error* %error_from_foo, null + %tmp = bitcast %swift_error* %error_from_foo to i8* + br i1 %had_error_from_foo, label %handler, label %cont + +cont: + %v1 = getelementptr inbounds %swift_error, %swift_error* %error_from_foo, i64 0, i32 1 + %t = load i8, i8* %v1 + store i8 %t, i8* %error_ref + br label %handler +handler: + call void @free(i8* %tmp) + ret float 1.0 +} + +; Check that we don't blow up on tail calling swifterror argument functions. +define float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) { +entry: + %0 = tail call float @tailcallswifterror(%swift_error** swifterror %error_ptr_ref) + ret float %0 +} +define swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) { +entry: + %0 = tail call swiftcc float @tailcallswifterror_swiftcc(%swift_error** swifterror %error_ptr_ref) + ret float %0 +} + +; CHECK-LABEL: params_in_reg +; Save callee saved registers and swifterror since it will be clobbered by the first call to params_in_reg2. +; CHECK: stp x28, x0, [sp +; CHECK: stp x27, x26, [sp +; CHECK: stp x25, x24, [sp +; CHECK: stp x23, x22, [sp +; CHECK: stp x20, x19, [sp +; CHECK: stp x29, x30, [sp +; Store argument registers. +; CHECK: mov x20, x1 +; CHECK: mov x22, x2 +; CHECK: mov x23, x3 +; CHECK: mov x24, x4 +; CHECK: mov x25, x5 +; CHECK: mov x26, x6 +; CHECK: mov x27, x7 +; CHECK: mov x28, x21 +; Setup call. +; CHECK: mov x8, #0 +; CHECK: mov x0, #1 +; CHECK: mov x1, #2 +; CHECK: mov x2, #3 +; CHECK: mov x3, #4 +; CHECK: mov x4, #5 +; CHECK: mov x5, #6 +; CHECK: mov x6, #7 +; CHECK: mov x7, #8 +; CHECK: mov x21, #0 +; CHECK: bl _params_in_reg2 +; Restore original arguments for next call. +; CHECK: ldr x0, [sp +; CHECK: mov x1, x20 +; CHECK: mov x2, x22 +; CHECK: mov x3, x23 +; CHECK: mov x4, x24 +; CHECK: mov x5, x25 +; CHECK: mov x6, x26 +; CHECK: mov x7, x27 +; Restore original swiftself argument and swifterror %err. +; CHECK: mov x21, x28 +; CHECK: bl _params_in_reg2 +; Restore calle save registers but don't clober swifterror x21. +; CHECK-NOT: x21 +; CHECK: ldp x29, x30, [sp +; CHECK-NOT: x21 +; CHECK: ldp x20, x19, [sp +; CHECK-NOT: x21 +; CHECK: ldp x23, x22, [sp +; CHECK-NOT: x21 +; CHECK: ldp x25, x24, [sp +; CHECK-NOT: x21 +; CHECK: ldp x27, x26, [sp +; CHECK-NOT: x21 +; CHECK: ldr x28, [sp +; CHECK-NOT: x21 +; CHECK: ret +define swiftcc void @params_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, i8*, %swift_error** nocapture swifterror %err) { + %error_ptr_ref = alloca swifterror %swift_error*, align 8 + store %swift_error* null, %swift_error** %error_ptr_ref + call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i8* null, %swift_error** nocapture swifterror %error_ptr_ref) + call swiftcc void @params_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i8* %8, %swift_error** nocapture swifterror %err) + ret void +} +declare swiftcc void @params_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, i8* , %swift_error** nocapture swifterror %err) + +; CHECK-LABEL: params_and_return_in_reg +; Store callee saved registers. +; CHECK: stp x28, x0, [sp, #16 +; CHECK: stp x27, x26, [sp +; CHECK: stp x25, x24, [sp +; CHECK: stp x23, x22, [sp +; CHECK: stp x20, x19, [sp +; CHECK: stp x29, x30, [sp +; Save original arguments. +; CHECK: mov x20, x1 +; CHECK: mov x22, x2 +; CHECK: mov x23, x3 +; CHECK: mov x24, x4 +; CHECK: mov x25, x5 +; CHECK: mov x26, x6 +; CHECK: mov x27, x7 +; CHECK: mov x28, x21 +; Setup call arguments. +; CHECK: mov x0, #1 +; CHECK: mov x1, #2 +; CHECK: mov x2, #3 +; CHECK: mov x3, #4 +; CHECK: mov x4, #5 +; CHECK: mov x5, #6 +; CHECK: mov x6, #7 +; CHECK: mov x7, #8 +; CHECK: mov x21, #0 +; CHECK: bl _params_in_reg2 +; Store swifterror %error_ptr_ref. +; CHECK: stp {{x[0-9]+}}, x21, [sp] +; Setup call arguments from original arguments. +; CHECK: ldr x0, [sp, #24 +; CHECK: mov x1, x20 +; CHECK: mov x2, x22 +; CHECK: mov x3, x23 +; CHECK: mov x4, x24 +; CHECK: mov x5, x25 +; CHECK: mov x6, x26 +; CHECK: mov x7, x27 +; CHECK: mov x21, x28 +; CHECK: bl _params_and_return_in_reg2 +; Store return values. +; CHECK: mov x20, x0 +; CHECK: mov x22, x1 +; CHECK: mov x23, x2 +; CHECK: mov x24, x3 +; CHECK: mov x25, x4 +; CHECK: mov x26, x5 +; CHECK: mov x27, x6 +; CHECK: mov x28, x7 +; Save swifterror %err. +; CHECK: mov x19, x21 +; Setup call. +; CHECK: mov x0, #1 +; CHECK: mov x1, #2 +; CHECK: mov x2, #3 +; CHECK: mov x3, #4 +; CHECK: mov x4, #5 +; CHECK: mov x5, #6 +; CHECK: mov x6, #7 +; CHECK: mov x7, #8 +; ... setup call with swiferror %error_ptr_ref. +; CHECK: ldr x21, [sp, #8] +; CHECK: bl _params_in_reg2 +; Restore return values for return from this function. +; CHECK: mov x0, x20 +; CHECK: mov x1, x22 +; CHECK: mov x2, x23 +; CHECK: mov x3, x24 +; CHECK: mov x4, x25 +; CHECK: mov x5, x26 +; CHECK: mov x6, x27 +; CHECK: mov x7, x28 +; CHECK: mov x21, x19 +; Restore callee save registers. +; CHECK: ldp x29, x30, [sp +; CHECK: ldp x20, x19, [sp +; CHECK: ldp x23, x22, [sp +; CHECK: ldp x25, x24, [sp +; CHECK: ldp x27, x26, [sp +; CHECK: ldr x28, [sp +; CHECK: ret +define swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg(i64, i64, i64, i64, i64, i64, i64, i64, i8* , %swift_error** nocapture swifterror %err) { + %error_ptr_ref = alloca swifterror %swift_error*, align 8 + store %swift_error* null, %swift_error** %error_ptr_ref + call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i8* null, %swift_error** nocapture swifterror %error_ptr_ref) + %val = call swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64 %0, i64 %1, i64 %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i8* %8, %swift_error** nocapture swifterror %err) + call swiftcc void @params_in_reg2(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i8* null, %swift_error** nocapture swifterror %error_ptr_ref) + ret { i64, i64, i64, i64, i64, i64, i64, i64 } %val +} + +declare swiftcc { i64, i64, i64, i64, i64, i64, i64, i64 } @params_and_return_in_reg2(i64, i64, i64, i64, i64, i64, i64, i64, i8* , %swift_error** nocapture swifterror %err) + +declare void @acallee(i8*) + +; Make sure we don't tail call if the caller returns a swifterror value. We +; would have to move into the swifterror register before the tail call. +; CHECK: tailcall_from_swifterror: +; CHECK-NOT: b _acallee +; CHECK: bl _acallee + +define swiftcc void @tailcall_from_swifterror(%swift_error** swifterror %error_ptr_ref) { +entry: + tail call void @acallee(i8* null) + ret void +} + +declare swiftcc void @foo2(%swift_error** swifterror) +; CHECK-LABEL: testAssign +; CHECK: mov x21, #0 +; CHECK: bl _foo2 +; CHECK: mov x0, x21 + +define swiftcc %swift_error* @testAssign(i8* %error_ref) { +entry: + %error_ptr = alloca swifterror %swift_error* + store %swift_error* null, %swift_error** %error_ptr + call swiftcc void @foo2(%swift_error** swifterror %error_ptr) + br label %a + +a: + %error = load %swift_error*, %swift_error** %error_ptr + ret %swift_error* %error +} From d9bb7b69abe266ab8d3ba54186604af9cc8750ad Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 08:45:37 +0000 Subject: [PATCH 0143/1176] [AArch64][SVE2] Asm: fix overlapping bit Summary: Bit 20 in sve2_int_arith_pred TableGen class was overlapping. The encodings are not affected as bit 20 is defined by the opc bits and this was overwriting the earlier error of setting bit 20 to 0. Raised by Momchil: https://reviews.llvm.org/D62130 Reviewed By: chill Differential Revision: https://reviews.llvm.org/D62292 llvm-svn: 361609 --- llvm/lib/Target/AArch64/SVEInstrFormats.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 79f2dab932f9e..ac4d800197b70 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -2070,7 +2070,7 @@ class sve2_int_arith_pred sz, bits<6> opc, string asm, bits<5> Zdn; let Inst{31-24} = 0b01000100; let Inst{23-22} = sz; - let Inst{21-20} = 0b01; + let Inst{21} = 0b0; let Inst{20-16} = opc{5-1}; let Inst{15-14} = 0b10; let Inst{13} = opc{0}; From 119c31ad9374210b5a950960a401582aac0c5333 Mon Sep 17 00:00:00 2001 From: Neil Henning Date: Fri, 24 May 2019 08:59:17 +0000 Subject: [PATCH 0144/1176] StructurizeCFG: Relax uniformity checks. This change relaxes the checks for hasOnlyUniformBranches such that our region is uniform if: 1. All conditional branches that are direct children are uniform. 2. And either: a. All sub-regions are uniform. b. There is one or less conditional branches among the direct children. Differential Revision: https://reviews.llvm.org/D62198 llvm-svn: 361610 --- llvm/lib/Transforms/Scalar/StructurizeCFG.cpp | 33 +++++- .../StructurizeCFG/AMDGPU/uniform-regions.ll | 108 +++++++++++++++++- 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp index b3ef31cea0a88..42318e47dae4a 100644 --- a/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp +++ b/llvm/lib/Transforms/Scalar/StructurizeCFG.cpp @@ -62,6 +62,11 @@ static cl::opt ForceSkipUniformRegions( cl::desc("Force whether the StructurizeCFG pass skips uniform regions"), cl::init(false)); +static cl::opt + RelaxedUniformRegions("structurizecfg-relaxed-uniform-regions", cl::Hidden, + cl::desc("Allow relaxed uniform region checks"), + cl::init(false)); + // Definition of the complex types used in this pass. using BBValuePair = std::pair; @@ -936,6 +941,11 @@ void StructurizeCFG::rebuildSSA() { static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, const LegacyDivergenceAnalysis &DA) { + // Bool for if all sub-regions are uniform. + bool SubRegionsAreUniform = true; + // Count of how many direct children are conditional. + unsigned ConditionalDirectChildren = 0; + for (auto E : R->elements()) { if (!E->isSubRegion()) { auto Br = dyn_cast(E->getEntry()->getTerminator()); @@ -944,6 +954,10 @@ static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, if (!DA.isUniform(Br)) return false; + + // One of our direct children is conditional. + ConditionalDirectChildren++; + LLVM_DEBUG(dbgs() << "BB: " << Br->getParent()->getName() << " has uniform terminator\n"); } else { @@ -961,12 +975,25 @@ static bool hasOnlyUniformBranches(Region *R, unsigned UniformMDKindID, if (!Br || !Br->isConditional()) continue; - if (!Br->getMetadata(UniformMDKindID)) - return false; + if (!Br->getMetadata(UniformMDKindID)) { + // Early exit if we cannot have relaxed uniform regions. + if (!RelaxedUniformRegions) + return false; + + SubRegionsAreUniform = false; + break; + } } } } - return true; + + // Our region is uniform if: + // 1. All conditional branches that are direct children are uniform (checked + // above). + // 2. And either: + // a. All sub-regions are uniform. + // b. There is one or less conditional branches among the direct children. + return SubRegionsAreUniform || (ConditionalDirectChildren <= 1); } /// Run the transformation for each region found diff --git a/llvm/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll b/llvm/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll index 7c8c09b782b51..e91e73ceb2b60 100644 --- a/llvm/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll +++ b/llvm/test/Transforms/StructurizeCFG/AMDGPU/uniform-regions.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -mtriple=amdgcn-- -S -o - -structurizecfg -structurizecfg-skip-uniform-regions < %s | FileCheck %s +; RUN: opt -mtriple=amdgcn-- -S -o - -structurizecfg -structurizecfg-skip-uniform-regions -structurizecfg-relaxed-uniform-regions < %s | FileCheck %s define amdgpu_cs void @uniform(i32 inreg %v) { ; CHECK-LABEL: @uniform( @@ -79,4 +79,110 @@ end: ret void } +define amdgpu_cs void @uniform_branch_to_nonuniform_subregions(i32 addrspace(4)* %ptr, i32 inreg %data) { +; CHECK-LABEL: @uniform_branch_to_nonuniform_subregions( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[DATA:%.*]], 42 +; CHECK-NEXT: br i1 [[C]], label [[UNIFORM_FOR_BODY:%.*]], label [[FOR_BODY:%.*]], !structurizecfg.uniform !0 +; CHECK: for.body: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[FLOW1:%.*]] ] +; CHECK-NEXT: [[CC:%.*]] = icmp ult i32 [[I]], 4 +; CHECK-NEXT: br i1 [[CC]], label [[MID_LOOP:%.*]], label [[FLOW1]] +; CHECK: mid.loop: +; CHECK-NEXT: [[V:%.*]] = call i32 @llvm.amdgcn.workitem.id.x() +; CHECK-NEXT: [[CC2:%.*]] = icmp eq i32 [[V]], 0 +; CHECK-NEXT: br i1 [[CC2]], label [[END_LOOP:%.*]], label [[FLOW2:%.*]] +; CHECK: Flow1: +; CHECK-NEXT: [[TMP0]] = phi i32 [ [[TMP2:%.*]], [[FLOW2]] ], [ undef, [[FOR_BODY]] ] +; CHECK-NEXT: [[TMP1:%.*]] = phi i1 [ [[TMP3:%.*]], [[FLOW2]] ], [ true, [[FOR_BODY]] ] +; CHECK-NEXT: br i1 [[TMP1]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; CHECK: end.loop: +; CHECK-NEXT: [[I_INC:%.*]] = add i32 [[I]], 1 +; CHECK-NEXT: br label [[FLOW2]] +; CHECK: Flow2: +; CHECK-NEXT: [[TMP2]] = phi i32 [ [[I_INC]], [[END_LOOP]] ], [ undef, [[MID_LOOP]] ] +; CHECK-NEXT: [[TMP3]] = phi i1 [ false, [[END_LOOP]] ], [ true, [[MID_LOOP]] ] +; CHECK-NEXT: br label [[FLOW1]] +; CHECK: for.end: +; CHECK-NEXT: br i1 [[CC]], label [[IF:%.*]], label [[FLOW:%.*]] +; CHECK: if: +; CHECK-NEXT: br label [[FLOW]] +; CHECK: uniform.for.body: +; CHECK-NEXT: [[UNIFORM_I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP4:%.*]], [[FLOW4:%.*]] ] +; CHECK-NEXT: [[UNIFORM_CC:%.*]] = icmp ult i32 [[UNIFORM_I]], 4 +; CHECK-NEXT: br i1 [[UNIFORM_CC]], label [[UNIFORM_MID_LOOP:%.*]], label [[FLOW4]] +; CHECK: uniform.mid.loop: +; CHECK-NEXT: [[UNIFORM_V:%.*]] = call i32 @llvm.amdgcn.workitem.id.x() +; CHECK-NEXT: [[UNIFORM_CC2:%.*]] = icmp eq i32 [[UNIFORM_V]], 0 +; CHECK-NEXT: br i1 [[UNIFORM_CC2]], label [[UNIFORM_END_LOOP:%.*]], label [[FLOW5:%.*]] +; CHECK: Flow4: +; CHECK-NEXT: [[TMP4]] = phi i32 [ [[TMP6:%.*]], [[FLOW5]] ], [ undef, [[UNIFORM_FOR_BODY]] ] +; CHECK-NEXT: [[TMP5:%.*]] = phi i1 [ [[TMP7:%.*]], [[FLOW5]] ], [ true, [[UNIFORM_FOR_BODY]] ] +; CHECK-NEXT: br i1 [[TMP5]], label [[UNIFORM_FOR_END:%.*]], label [[UNIFORM_FOR_BODY]] +; CHECK: uniform.end.loop: +; CHECK-NEXT: [[UNIFORM_I_INC:%.*]] = add i32 [[UNIFORM_I]], 1 +; CHECK-NEXT: br label [[FLOW5]] +; CHECK: Flow5: +; CHECK-NEXT: [[TMP6]] = phi i32 [ [[UNIFORM_I_INC]], [[UNIFORM_END_LOOP]] ], [ undef, [[UNIFORM_MID_LOOP]] ] +; CHECK-NEXT: [[TMP7]] = phi i1 [ false, [[UNIFORM_END_LOOP]] ], [ true, [[UNIFORM_MID_LOOP]] ] +; CHECK-NEXT: br label [[FLOW4]] +; CHECK: uniform.for.end: +; CHECK-NEXT: br i1 [[UNIFORM_CC]], label [[UNIFORM_IF:%.*]], label [[FLOW3:%.*]] +; CHECK: uniform.if: +; CHECK-NEXT: br label [[FLOW3]] +; CHECK: Flow: +; CHECK-NEXT: br label [[END:%.*]] +; CHECK: Flow3: +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; +entry: + %c = icmp eq i32 %data, 42 + br i1 %c, label %uniform.for.body, label %for.body + +for.body: + %i = phi i32 [0, %entry], [%i.inc, %end.loop] + %cc = icmp ult i32 %i, 4 + br i1 %cc, label %mid.loop, label %for.end + +mid.loop: + %v = call i32 @llvm.amdgcn.workitem.id.x() + %cc2 = icmp eq i32 %v, 0 + br i1 %cc2, label %end.loop, label %for.end + +end.loop: + %i.inc = add i32 %i, 1 + br label %for.body + +for.end: + br i1 %cc, label %if, label %end + +if: + br label %end + +uniform.for.body: + %uniform.i = phi i32 [0, %entry], [%uniform.i.inc, %uniform.end.loop] + %uniform.cc = icmp ult i32 %uniform.i, 4 + br i1 %uniform.cc, label %uniform.mid.loop, label %uniform.for.end + +uniform.mid.loop: + %uniform.v = call i32 @llvm.amdgcn.workitem.id.x() + %uniform.cc2 = icmp eq i32 %uniform.v, 0 + br i1 %uniform.cc2, label %uniform.end.loop, label %uniform.for.end + +uniform.end.loop: + %uniform.i.inc = add i32 %uniform.i, 1 + br label %uniform.for.body + +uniform.for.end: + br i1 %uniform.cc, label %uniform.if, label %end + +uniform.if: + br label %end + +end: + ret void +} + declare i32 @llvm.amdgcn.workitem.id.x() From 6bca64fe5e9cf04cd39217e5ae2e148dc96b7dae Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 09:06:37 +0000 Subject: [PATCH 0145/1176] [AArch64][SVE2] Asm: add saturating add/sub instructions Summary: Patch adds support for the following instructions: * SQADD, UQADD, SUQADD, USQADD * SQSUB, UQSUB, SQSUBR, UQSUBR The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: chill Differential Revision: https://reviews.llvm.org/D62130 llvm-svn: 361611 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 10 ++++ llvm/test/MC/AArch64/SVE2/sqadd-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/sqadd.s | 59 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/sqsub-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/sqsub.s | 59 +++++++++++++++++++ .../test/MC/AArch64/SVE2/sqsubr-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/sqsubr.s | 59 +++++++++++++++++++ .../test/MC/AArch64/SVE2/suqadd-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/suqadd.s | 59 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uqadd-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/uqadd.s | 59 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uqsub-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/uqsub.s | 59 +++++++++++++++++++ .../test/MC/AArch64/SVE2/uqsubr-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/uqsubr.s | 59 +++++++++++++++++++ .../test/MC/AArch64/SVE2/usqadd-diagnostics.s | 37 ++++++++++++ llvm/test/MC/AArch64/SVE2/usqadd.s | 59 +++++++++++++++++++ 17 files changed, 778 insertions(+) create mode 100644 llvm/test/MC/AArch64/SVE2/sqadd-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqadd.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqsub-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqsub.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqsubr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqsubr.s create mode 100644 llvm/test/MC/AArch64/SVE2/suqadd-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/suqadd.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqadd-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqadd.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqsub-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqsub.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqsubr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqsubr.s create mode 100644 llvm/test/MC/AArch64/SVE2/usqadd-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/usqadd.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 62dfdf1345aae..7e2b152395a43 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1140,6 +1140,16 @@ let Predicates = [HasSVE2] in { defm SQABS_ZPmZ : sve2_int_un_pred_arit<0b100, "sqabs">; defm SQNEG_ZPmZ : sve2_int_un_pred_arit<0b101, "sqneg">; + // SVE2 saturating add/subtract + defm SQADD_ZPmZ : sve2_int_arith_pred<0b110000, "sqadd">; + defm UQADD_ZPmZ : sve2_int_arith_pred<0b110010, "uqadd">; + defm SQSUB_ZPmZ : sve2_int_arith_pred<0b110100, "sqsub">; + defm UQSUB_ZPmZ : sve2_int_arith_pred<0b110110, "uqsub">; + defm SUQADD_ZPmZ : sve2_int_arith_pred<0b111000, "suqadd">; + defm USQADD_ZPmZ : sve2_int_arith_pred<0b111010, "usqadd">; + defm SQSUBR_ZPmZ : sve2_int_arith_pred<0b111100, "sqsubr">; + defm UQSUBR_ZPmZ : sve2_int_arith_pred<0b111110, "uqsubr">; + // SVE2 integer multiply long defm SQDMULLB_ZZZ : sve2_wide_int_arith_long<0b11000, "sqdmullb">; defm SQDMULLT_ZZZ : sve2_wide_int_arith_long<0b11001, "sqdmullt">; diff --git a/llvm/test/MC/AArch64/SVE2/sqadd-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqadd-diagnostics.s new file mode 100644 index 0000000000000..4ba83c1e42e1a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqadd-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqadd z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqadd z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqadd z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqadd z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqadd z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqadd z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqadd z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqadd z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqadd z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqadd z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqadd.s b/llvm/test/MC/AArch64/SVE2/sqadd.s new file mode 100644 index 0000000000000..77c3ca9f499fe --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqadd.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqadd z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqadd z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x18,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 18 44 + +sqadd z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqadd z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x58,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 58 44 + +sqadd z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqadd z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x98,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 98 44 + +sqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xd8,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f d8 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqadd z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqadd z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xd8,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 d8 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xd8,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f d8 44 diff --git a/llvm/test/MC/AArch64/SVE2/sqsub-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqsub-diagnostics.s new file mode 100644 index 0000000000000..9960dde0201ec --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqsub-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqsub z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqsub z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqsub z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqsub z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqsub z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqsub z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqsub z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqsub z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqsub z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqsub z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqsub.s b/llvm/test/MC/AArch64/SVE2/sqsub.s new file mode 100644 index 0000000000000..9a3e4c73bfcec --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqsub.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqsub z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqsub z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x1a,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 1a 44 + +sqsub z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqsub z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x5a,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 5a 44 + +sqsub z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqsub z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x9a,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 9a 44 + +sqsub z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqsub z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xda,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f da 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqsub z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqsub z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xda,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 da 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqsub z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqsub z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xda,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f da 44 diff --git a/llvm/test/MC/AArch64/SVE2/sqsubr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqsubr-diagnostics.s new file mode 100644 index 0000000000000..af7caaa67ab7d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqsubr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqsubr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqsubr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqsubr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqsubr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqsubr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqsubr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqsubr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqsubr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqsubr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqsubr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqsubr.s b/llvm/test/MC/AArch64/SVE2/sqsubr.s new file mode 100644 index 0000000000000..a19d4fef39ecd --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqsubr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqsubr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqsubr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x1e,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 1e 44 + +sqsubr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqsubr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x5e,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 5e 44 + +sqsubr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqsubr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x9e,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 9e 44 + +sqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xde,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f de 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqsubr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqsubr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xde,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 de 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xde,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f de 44 diff --git a/llvm/test/MC/AArch64/SVE2/suqadd-diagnostics.s b/llvm/test/MC/AArch64/SVE2/suqadd-diagnostics.s new file mode 100644 index 0000000000000..9faa706b69cd5 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/suqadd-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +suqadd z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: suqadd z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +suqadd z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: suqadd z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +suqadd z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: suqadd z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +suqadd z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: suqadd z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +suqadd z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: suqadd z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/suqadd.s b/llvm/test/MC/AArch64/SVE2/suqadd.s new file mode 100644 index 0000000000000..016275da2e0c2 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/suqadd.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +suqadd z0.b, p0/m, z0.b, z1.b +// CHECK-INST: suqadd z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x1c,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 1c 44 + +suqadd z0.h, p0/m, z0.h, z1.h +// CHECK-INST: suqadd z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x5c,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 5c 44 + +suqadd z29.s, p7/m, z29.s, z30.s +// CHECK-INST: suqadd z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x9c,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 9c 44 + +suqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: suqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdc,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f dc 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +suqadd z31.d, p0/m, z31.d, z30.d +// CHECK-INST: suqadd z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xdc,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 dc 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +suqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: suqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdc,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f dc 44 diff --git a/llvm/test/MC/AArch64/SVE2/uqadd-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqadd-diagnostics.s new file mode 100644 index 0000000000000..c08a0cc4b4639 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqadd-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqadd z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqadd z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqadd z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqadd z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqadd z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqadd z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqadd z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqadd z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqadd z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqadd z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqadd.s b/llvm/test/MC/AArch64/SVE2/uqadd.s new file mode 100644 index 0000000000000..54d96163994ed --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqadd.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqadd z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqadd z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x19,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 19 44 + +uqadd z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqadd z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x59,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 59 44 + +uqadd z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqadd z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x99,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 99 44 + +uqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xd9,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f d9 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqadd z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqadd z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xd9,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 d9 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xd9,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f d9 44 diff --git a/llvm/test/MC/AArch64/SVE2/uqsub-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqsub-diagnostics.s new file mode 100644 index 0000000000000..486c458d43e7a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqsub-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqsub z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqsub z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqsub z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqsub z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqsub z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqsub z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqsub z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqsub z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqsub z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqsub z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqsub.s b/llvm/test/MC/AArch64/SVE2/uqsub.s new file mode 100644 index 0000000000000..0df03aa2f30d0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqsub.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqsub z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqsub z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x1b,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 1b 44 + +uqsub z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqsub z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x5b,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 5b 44 + +uqsub z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqsub z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x9b,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 9b 44 + +uqsub z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqsub z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdb,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f db 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqsub z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqsub z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xdb,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 db 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqsub z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqsub z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdb,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f db 44 diff --git a/llvm/test/MC/AArch64/SVE2/uqsubr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqsubr-diagnostics.s new file mode 100644 index 0000000000000..e6300a2e54bbb --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqsubr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqsubr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqsubr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqsubr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqsubr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqsubr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqsubr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqsubr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqsubr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqsubr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqsubr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqsubr.s b/llvm/test/MC/AArch64/SVE2/uqsubr.s new file mode 100644 index 0000000000000..64f95c72d8612 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqsubr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqsubr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqsubr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x1f,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 1f 44 + +uqsubr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqsubr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x5f,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 5f 44 + +uqsubr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqsubr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x9f,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 9f 44 + +uqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdf,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f df 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqsubr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqsubr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xdf,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 df 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqsubr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdf,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f df 44 diff --git a/llvm/test/MC/AArch64/SVE2/usqadd-diagnostics.s b/llvm/test/MC/AArch64/SVE2/usqadd-diagnostics.s new file mode 100644 index 0000000000000..4c7271f983061 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usqadd-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +usqadd z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: usqadd z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +usqadd z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usqadd z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usqadd z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usqadd z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +usqadd z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: usqadd z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usqadd z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: usqadd z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/usqadd.s b/llvm/test/MC/AArch64/SVE2/usqadd.s new file mode 100644 index 0000000000000..9bec555dcbd6b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usqadd.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +usqadd z0.b, p0/m, z0.b, z1.b +// CHECK-INST: usqadd z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x1d,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 1d 44 + +usqadd z0.h, p0/m, z0.h, z1.h +// CHECK-INST: usqadd z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x5d,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 5d 44 + +usqadd z29.s, p7/m, z29.s, z30.s +// CHECK-INST: usqadd z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x9d,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 9d 44 + +usqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: usqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdd,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f dd 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +usqadd z31.d, p0/m, z31.d, z30.d +// CHECK-INST: usqadd z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xdd,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 dd 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +usqadd z31.d, p7/m, z31.d, z30.d +// CHECK-INST: usqadd z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xdd,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f dd 44 From 968cb0e0499436cdbe4dd97e61b1ffb8abd5817c Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 09:17:23 +0000 Subject: [PATCH 0146/1176] [AArch64][SVE2] Asm: add various bitwise shift instructions Summary: This patch adds support for the SVE2 saturating/rounding bitwise shift left (predicated) group of instructions: * SRSHL, URSHL, SRSHLR, URSHLR, SQSHL, UQSHL, SQRSHL, UQRSHL, SQSHLR, UQSHLR, SQRSHLR, UQRSHLR Immediate forms of the SQSHL and UQSHL instructions are also added to the existing SVE bitwise shift by immediate (predicated) group, as well as three new instructions SRSHR/URSHR/SQSHLU. The new instructions in this group are encoded similarly and are implemented using the same TableGen class with a minimal change (1 bit in encoding). The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D62140 llvm-svn: 361612 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 29 +++- llvm/lib/Target/AArch64/SVEInstrFormats.td | 14 +- .../test/MC/AArch64/SVE2/sqrshl-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/sqrshl.s | 59 ++++++++ .../MC/AArch64/SVE2/sqrshlr-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/sqrshlr.s | 59 ++++++++ llvm/test/MC/AArch64/SVE2/sqshl-diagnostics.s | 98 +++++++++++++ llvm/test/MC/AArch64/SVE2/sqshl.s | 131 ++++++++++++++++++ .../test/MC/AArch64/SVE2/sqshlr-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/sqshlr.s | 59 ++++++++ .../test/MC/AArch64/SVE2/sqshlu-diagnostics.s | 78 +++++++++++ llvm/test/MC/AArch64/SVE2/sqshlu.s | 83 +++++++++++ llvm/test/MC/AArch64/SVE2/srshl-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/srshl.s | 59 ++++++++ .../test/MC/AArch64/SVE2/srshlr-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/srshlr.s | 59 ++++++++ llvm/test/MC/AArch64/SVE2/srshr-diagnostics.s | 78 +++++++++++ llvm/test/MC/AArch64/SVE2/srshr.s | 84 +++++++++++ .../test/MC/AArch64/SVE2/uqrshl-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/uqrshl.s | 59 ++++++++ .../MC/AArch64/SVE2/uqrshlr-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/uqrshlr.s | 59 ++++++++ llvm/test/MC/AArch64/SVE2/uqshl-diagnostics.s | 98 +++++++++++++ llvm/test/MC/AArch64/SVE2/uqshl.s | 131 ++++++++++++++++++ .../test/MC/AArch64/SVE2/uqshlr-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/uqshlr.s | 59 ++++++++ llvm/test/MC/AArch64/SVE2/urshl-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/urshl.s | 59 ++++++++ .../test/MC/AArch64/SVE2/urshlr-diagnostics.s | 37 +++++ llvm/test/MC/AArch64/SVE2/urshlr.s | 59 ++++++++ llvm/test/MC/AArch64/SVE2/urshr-diagnostics.s | 78 +++++++++++ llvm/test/MC/AArch64/SVE2/urshr.s | 84 +++++++++++ 32 files changed, 1935 insertions(+), 11 deletions(-) create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshl-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshl.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshlr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshlr.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshl-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshl.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshlr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshlr.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshlu-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshlu.s create mode 100644 llvm/test/MC/AArch64/SVE2/srshl-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/srshl.s create mode 100644 llvm/test/MC/AArch64/SVE2/srshlr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/srshlr.s create mode 100644 llvm/test/MC/AArch64/SVE2/srshr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/srshr.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshl-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshl.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshlr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshlr.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshl-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshl.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshlr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshlr.s create mode 100644 llvm/test/MC/AArch64/SVE2/urshl-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/urshl.s create mode 100644 llvm/test/MC/AArch64/SVE2/urshlr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/urshlr.s create mode 100644 llvm/test/MC/AArch64/SVE2/urshr-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/urshr.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 7e2b152395a43..9d775ec8d5f7f 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -875,10 +875,10 @@ let Predicates = [HasSVE] in { defm LSL_WIDE_ZZZ : sve_int_bin_cons_shift_wide<0b11, "lsl">; // Predicated shifts - defm ASR_ZPmI : sve_int_bin_pred_shift_imm_right<0b000, "asr">; - defm LSR_ZPmI : sve_int_bin_pred_shift_imm_right<0b001, "lsr">; - defm LSL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b011, "lsl">; - defm ASRD_ZPmI : sve_int_bin_pred_shift_imm_right<0b100, "asrd">; + defm ASR_ZPmI : sve_int_bin_pred_shift_imm_right<0b0000, "asr">; + defm LSR_ZPmI : sve_int_bin_pred_shift_imm_right<0b0001, "lsr">; + defm LSL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0011, "lsl">; + defm ASRD_ZPmI : sve_int_bin_pred_shift_imm_right<0b0100, "asrd">; defm ASR_ZPmZ : sve_int_bin_pred_shift<0b000, "asr">; defm LSR_ZPmZ : sve_int_bin_pred_shift<0b001, "lsr">; @@ -1150,6 +1150,20 @@ let Predicates = [HasSVE2] in { defm SQSUBR_ZPmZ : sve2_int_arith_pred<0b111100, "sqsubr">; defm UQSUBR_ZPmZ : sve2_int_arith_pred<0b111110, "uqsubr">; + // SVE2 saturating/rounding bitwise shift left (predicated) + defm SRSHL_ZPmZ : sve2_int_arith_pred<0b000100, "srshl">; + defm URSHL_ZPmZ : sve2_int_arith_pred<0b000110, "urshl">; + defm SRSHLR_ZPmZ : sve2_int_arith_pred<0b001100, "srshlr">; + defm URSHLR_ZPmZ : sve2_int_arith_pred<0b001110, "urshlr">; + defm SQSHL_ZPmZ : sve2_int_arith_pred<0b010000, "sqshl">; + defm UQSHL_ZPmZ : sve2_int_arith_pred<0b010010, "uqshl">; + defm SQRSHL_ZPmZ : sve2_int_arith_pred<0b010100, "sqrshl">; + defm UQRSHL_ZPmZ : sve2_int_arith_pred<0b010110, "uqrshl">; + defm SQSHLR_ZPmZ : sve2_int_arith_pred<0b011000, "sqshlr">; + defm UQSHLR_ZPmZ : sve2_int_arith_pred<0b011010, "uqshlr">; + defm SQRSHLR_ZPmZ : sve2_int_arith_pred<0b011100, "sqrshlr">; + defm UQRSHLR_ZPmZ : sve2_int_arith_pred<0b011110, "uqrshlr">; + // SVE2 integer multiply long defm SQDMULLB_ZZZ : sve2_wide_int_arith_long<0b11000, "sqdmullb">; defm SQDMULLT_ZZZ : sve2_wide_int_arith_long<0b11001, "sqdmullt">; @@ -1157,4 +1171,11 @@ let Predicates = [HasSVE2] in { defm SMULLT_ZZZ : sve2_wide_int_arith_long<0b11101, "smullt">; defm UMULLB_ZZZ : sve2_wide_int_arith_long<0b11110, "umullb">; defm UMULLT_ZZZ : sve2_wide_int_arith_long<0b11111, "umullt">; + + // Predicated shifts + defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; + defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; + defm SRSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1100, "srshr">; + defm URSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1101, "urshr">; + defm SQSHLU_ZPmI : sve_int_bin_pred_shift_imm_left< 0b1111, "sqshlu">; } diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index ac4d800197b70..8b4c00935e524 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -2926,9 +2926,9 @@ multiclass sve_int_index_rr { //===----------------------------------------------------------------------===// // SVE Bitwise Shift - Predicated Group //===----------------------------------------------------------------------===// -class sve_int_bin_pred_shift_imm tsz8_64, bits<3> opc, string asm, - ZPRRegOp zprty, Operand immtype, - ElementSizeEnum size> +class sve_int_bin_pred_shift_imm tsz8_64, bits<4> opc, string asm, + ZPRRegOp zprty, Operand immtype, + ElementSizeEnum size> : I<(outs zprty:$Zdn), (ins PPR3bAny:$Pg, zprty:$_Zdn, immtype:$imm), asm, "\t$Zdn, $Pg/m, $_Zdn, $imm", "", @@ -2938,8 +2938,8 @@ class sve_int_bin_pred_shift_imm tsz8_64, bits<3> opc, string asm, bits<6> imm; let Inst{31-24} = 0b00000100; let Inst{23-22} = tsz8_64{3-2}; - let Inst{21-19} = 0b000; - let Inst{18-16} = opc; + let Inst{21-20} = 0b00; + let Inst{19-16} = opc; let Inst{15-13} = 0b100; let Inst{12-10} = Pg; let Inst{9-8} = tsz8_64{1-0}; @@ -2951,7 +2951,7 @@ class sve_int_bin_pred_shift_imm tsz8_64, bits<3> opc, string asm, let ElementSize = size; } -multiclass sve_int_bin_pred_shift_imm_left opc, string asm> { +multiclass sve_int_bin_pred_shift_imm_left opc, string asm> { def _B : sve_int_bin_pred_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftL8, ElementSizeB>; def _H : sve_int_bin_pred_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftL16, @@ -2969,7 +2969,7 @@ multiclass sve_int_bin_pred_shift_imm_left opc, string asm> { } } -multiclass sve_int_bin_pred_shift_imm_right opc, string asm> { +multiclass sve_int_bin_pred_shift_imm_right opc, string asm> { def _B : sve_int_bin_pred_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8, ElementSizeB>; def _H : sve_int_bin_pred_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16, diff --git a/llvm/test/MC/AArch64/SVE2/sqrshl-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqrshl-diagnostics.s new file mode 100644 index 0000000000000..b56264a3cf070 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshl-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqrshl z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqrshl z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqrshl z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshl z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshl z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshl z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqrshl z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqrshl z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshl z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqrshl z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqrshl.s b/llvm/test/MC/AArch64/SVE2/sqrshl.s new file mode 100644 index 0000000000000..048d952629674 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshl.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqrshl z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqrshl z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x0a,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 0a 44 + +sqrshl z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqrshl z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x4a,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 4a 44 + +sqrshl z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqrshl z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x8a,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 8a 44 + +sqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xca,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f ca 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqrshl z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqrshl z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xca,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 ca 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xca,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f ca 44 diff --git a/llvm/test/MC/AArch64/SVE2/sqrshlr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqrshlr-diagnostics.s new file mode 100644 index 0000000000000..76f7d155f3dc4 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshlr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqrshlr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqrshlr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqrshlr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshlr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshlr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshlr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqrshlr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqrshlr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshlr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqrshlr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqrshlr.s b/llvm/test/MC/AArch64/SVE2/sqrshlr.s new file mode 100644 index 0000000000000..4566611ee14a1 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshlr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqrshlr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqrshlr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x0e,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 0e 44 + +sqrshlr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqrshlr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x4e,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 4e 44 + +sqrshlr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqrshlr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x8e,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 8e 44 + +sqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xce,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f ce 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqrshlr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqrshlr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xce,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 ce 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xce,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f ce 44 diff --git a/llvm/test/MC/AArch64/SVE2/sqshl-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshl-diagnostics.s new file mode 100644 index 0000000000000..565cbf19c7720 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshl-diagnostics.s @@ -0,0 +1,98 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqshl z0.b, p0/m, z0.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: sqshl z0.b, p0/m, z0.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.b, p0/m, z0.b, #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: sqshl z0.b, p0/m, z0.b, #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.h, p0/m, z0.h, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: sqshl z0.h, p0/m, z0.h, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.h, p0/m, z0.h, #16 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: sqshl z0.h, p0/m, z0.h, #16 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.s, p0/m, z0.s, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: sqshl z0.s, p0/m, z0.s, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.s, p0/m, z0.s, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: sqshl z0.s, p0/m, z0.s, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.d, p0/m, z0.d, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: sqshl z0.d, p0/m, z0.d, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.d, p0/m, z0.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: sqshl z0.d, p0/m, z0.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqshl z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqshl z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.b, p0/m, z1.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqshl z0.b, p0/m, z1.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqshl z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshl z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshl z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.b, p0/m, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshl z0.b, p0/m, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.d, p0/m, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshl z0.d, p0/m, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqshl z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqshl z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqshl z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshl z0.b, p8/m, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqshl z0.b, p8/m, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshl.s b/llvm/test/MC/AArch64/SVE2/sqshl.s new file mode 100644 index 0000000000000..c7065a50ccd53 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshl.s @@ -0,0 +1,131 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshl z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqshl z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x08,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 08 44 + +sqshl z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqshl z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x48,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 48 44 + +sqshl z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqshl z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x88,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 88 44 + +sqshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc8,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c8 44 + +sqshl z0.b, p0/m, z0.b, #0 +// CHECK-INST: sqshl z0.b, p0/m, z0.b, #0 +// CHECK-ENCODING: [0x00,0x81,0x06,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 81 06 04 + +sqshl z31.b, p0/m, z31.b, #7 +// CHECK-INST: sqshl z31.b, p0/m, z31.b, #7 +// CHECK-ENCODING: [0xff,0x81,0x06,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 81 06 04 + +sqshl z0.h, p0/m, z0.h, #0 +// CHECK-INST: sqshl z0.h, p0/m, z0.h, #0 +// CHECK-ENCODING: [0x00,0x82,0x06,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 82 06 04 + +sqshl z31.h, p0/m, z31.h, #15 +// CHECK-INST: sqshl z31.h, p0/m, z31.h, #15 +// CHECK-ENCODING: [0xff,0x83,0x06,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 06 04 + +sqshl z0.s, p0/m, z0.s, #0 +// CHECK-INST: sqshl z0.s, p0/m, z0.s, #0 +// CHECK-ENCODING: [0x00,0x80,0x46,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 46 04 + +sqshl z31.s, p0/m, z31.s, #31 +// CHECK-INST: sqshl z31.s, p0/m, z31.s, #31 +// CHECK-ENCODING: [0xff,0x83,0x46,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 46 04 + +sqshl z0.d, p0/m, z0.d, #0 +// CHECK-INST: sqshl z0.d, p0/m, z0.d, #0 +// CHECK-ENCODING: [0x00,0x80,0x86,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 86 04 + +sqshl z31.d, p0/m, z31.d, #63 +// CHECK-INST: sqshl z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xc6,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 c6 04 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqshl z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqshl z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xc8,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 c8 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc8,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c8 44 + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqshl z31.d, p0/m, z31.d, #63 +// CHECK-INST: sqshl z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xc6,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 c6 04 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqshl z31.d, p0/m, z31.d, #63 +// CHECK-INST: sqshl z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xc6,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 c6 04 diff --git a/llvm/test/MC/AArch64/SVE2/sqshlr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshlr-diagnostics.s new file mode 100644 index 0000000000000..a33ea84e548c2 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshlr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqshlr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqshlr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqshlr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshlr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshlr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqshlr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqshlr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqshlr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshlr.s b/llvm/test/MC/AArch64/SVE2/sqshlr.s new file mode 100644 index 0000000000000..36e95d7fd3b7d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshlr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshlr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: sqshlr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x0c,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 0c 44 + +sqshlr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: sqshlr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x4c,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 4c 44 + +sqshlr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: sqshlr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x8c,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 8c 44 + +sqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcc,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cc 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqshlr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: sqshlr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xcc,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 cc 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: sqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcc,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cc 44 diff --git a/llvm/test/MC/AArch64/SVE2/sqshlu-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshlu-diagnostics.s new file mode 100644 index 0000000000000..0c2601a598a8c --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshlu-diagnostics.s @@ -0,0 +1,78 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqshlu z0.b, p0/m, z0.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: sqshlu z0.b, p0/m, z0.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.b, p0/m, z0.b, #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: sqshlu z0.b, p0/m, z0.b, #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.h, p0/m, z0.h, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: sqshlu z0.h, p0/m, z0.h, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.h, p0/m, z0.h, #16 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: sqshlu z0.h, p0/m, z0.h, #16 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.s, p0/m, z0.s, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: sqshlu z0.s, p0/m, z0.s, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.s, p0/m, z0.s, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: sqshlu z0.s, p0/m, z0.s, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.d, p0/m, z0.d, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: sqshlu z0.d, p0/m, z0.d, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.d, p0/m, z0.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: sqshlu z0.d, p0/m, z0.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqshlu z0.b, p0/m, z1.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqshlu z0.b, p0/m, z1.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sqshlu z0.b, p0/m, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshlu z0.b, p0/m, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.d, p0/m, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshlu z0.d, p0/m, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +sqshlu z0.b, p0/z, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: sqshlu z0.b, p0/z, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshlu z0.b, p8/m, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: sqshlu z0.b, p8/m, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshlu.s b/llvm/test/MC/AArch64/SVE2/sqshlu.s new file mode 100644 index 0000000000000..196db03a26dfe --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshlu.s @@ -0,0 +1,83 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshlu z0.b, p0/m, z0.b, #0 +// CHECK-INST: sqshlu z0.b, p0/m, z0.b, #0 +// CHECK-ENCODING: [0x00,0x81,0x0f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 81 0f 04 + +sqshlu z31.b, p0/m, z31.b, #7 +// CHECK-INST: sqshlu z31.b, p0/m, z31.b, #7 +// CHECK-ENCODING: [0xff,0x81,0x0f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 81 0f 04 + +sqshlu z0.h, p0/m, z0.h, #0 +// CHECK-INST: sqshlu z0.h, p0/m, z0.h, #0 +// CHECK-ENCODING: [0x00,0x82,0x0f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 82 0f 04 + +sqshlu z31.h, p0/m, z31.h, #15 +// CHECK-INST: sqshlu z31.h, p0/m, z31.h, #15 +// CHECK-ENCODING: [0xff,0x83,0x0f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 0f 04 + +sqshlu z0.s, p0/m, z0.s, #0 +// CHECK-INST: sqshlu z0.s, p0/m, z0.s, #0 +// CHECK-ENCODING: [0x00,0x80,0x4f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 4f 04 + +sqshlu z31.s, p0/m, z31.s, #31 +// CHECK-INST: sqshlu z31.s, p0/m, z31.s, #31 +// CHECK-ENCODING: [0xff,0x83,0x4f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 4f 04 + +sqshlu z0.d, p0/m, z0.d, #0 +// CHECK-INST: sqshlu z0.d, p0/m, z0.d, #0 +// CHECK-ENCODING: [0x00,0x80,0x8f,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 8f 04 + +sqshlu z31.d, p0/m, z31.d, #63 +// CHECK-INST: sqshlu z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xcf,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 cf 04 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +sqshlu z31.d, p0/m, z31.d, #63 +// CHECK-INST: sqshlu z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xcf,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 cf 04 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +sqshlu z31.d, p0/m, z31.d, #63 +// CHECK-INST: sqshlu z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xcf,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 cf 04 diff --git a/llvm/test/MC/AArch64/SVE2/srshl-diagnostics.s b/llvm/test/MC/AArch64/SVE2/srshl-diagnostics.s new file mode 100644 index 0000000000000..6d599aa08df1a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srshl-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +srshl z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: srshl z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +srshl z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srshl z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshl z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srshl z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +srshl z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: srshl z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshl z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: srshl z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/srshl.s b/llvm/test/MC/AArch64/SVE2/srshl.s new file mode 100644 index 0000000000000..ab0c8f2944522 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srshl.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +srshl z0.b, p0/m, z0.b, z1.b +// CHECK-INST: srshl z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x02,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 02 44 + +srshl z0.h, p0/m, z0.h, z1.h +// CHECK-INST: srshl z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x42,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 42 44 + +srshl z29.s, p7/m, z29.s, z30.s +// CHECK-INST: srshl z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x82,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 82 44 + +srshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: srshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc2,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c2 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +srshl z31.d, p0/m, z31.d, z30.d +// CHECK-INST: srshl z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xc2,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 c2 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +srshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: srshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc2,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c2 44 diff --git a/llvm/test/MC/AArch64/SVE2/srshlr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/srshlr-diagnostics.s new file mode 100644 index 0000000000000..f1f760da9c69d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srshlr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +srshlr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: srshlr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +srshlr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srshlr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshlr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srshlr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +srshlr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: srshlr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshlr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: srshlr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/srshlr.s b/llvm/test/MC/AArch64/SVE2/srshlr.s new file mode 100644 index 0000000000000..822a4b82e2fb8 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srshlr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +srshlr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: srshlr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x06,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 06 44 + +srshlr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: srshlr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x46,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 46 44 + +srshlr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: srshlr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x86,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 86 44 + +srshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: srshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc6,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c6 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +srshlr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: srshlr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xc6,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 c6 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +srshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: srshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc6,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c6 44 diff --git a/llvm/test/MC/AArch64/SVE2/srshr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/srshr-diagnostics.s new file mode 100644 index 0000000000000..0440f08a36446 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srshr-diagnostics.s @@ -0,0 +1,78 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +srshr z18.b, p0/m, z18.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: srshr z18.b, p0/m, z18.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z1.b, p0/m, z1.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: srshr z1.b, p0/m, z1.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z21.h, p0/m, z21.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: srshr z21.h, p0/m, z21.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z14.h, p0/m, z14.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: srshr z14.h, p0/m, z14.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z6.s, p0/m, z6.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: srshr z6.s, p0/m, z6.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z23.s, p0/m, z23.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: srshr z23.s, p0/m, z23.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z3.d, p0/m, z3.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: srshr z3.d, p0/m, z3.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z25.d, p0/m, z25.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: srshr z25.d, p0/m, z25.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +srshr z0.b, p0/m, z1.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: srshr z0.b, p0/m, z1.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +srshr z0.b, p0/m, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srshr z0.b, p0/m, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z0.d, p0/m, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srshr z0.d, p0/m, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +srshr z0.b, p0/z, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: srshr z0.b, p0/z, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srshr z0.b, p8/m, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: srshr z0.b, p8/m, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/srshr.s b/llvm/test/MC/AArch64/SVE2/srshr.s new file mode 100644 index 0000000000000..34955fed55d3e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srshr.s @@ -0,0 +1,84 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +srshr z0.b, p0/m, z0.b, #1 +// CHECK-INST: srshr z0.b, p0/m, z0.b, #1 +// CHECK-ENCODING: [0xe0,0x81,0x0c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 81 0c 04 + +srshr z31.b, p0/m, z31.b, #8 +// CHECK-INST: srshr z31.b, p0/m, z31.b, #8 +// CHECK-ENCODING: [0x1f,0x81,0x0c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 81 0c 04 + +srshr z0.h, p0/m, z0.h, #1 +// CHECK-INST: srshr z0.h, p0/m, z0.h, #1 +// CHECK-ENCODING: [0xe0,0x83,0x0c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 83 0c 04 + +srshr z31.h, p0/m, z31.h, #16 +// CHECK-INST: srshr z31.h, p0/m, z31.h, #16 +// CHECK-ENCODING: [0x1f,0x82,0x0c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 82 0c 04 + +srshr z0.s, p0/m, z0.s, #1 +// CHECK-INST: srshr z0.s, p0/m, z0.s, #1 +// CHECK-ENCODING: [0xe0,0x83,0x4c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 83 4c 04 + +srshr z31.s, p0/m, z31.s, #32 +// CHECK-INST: srshr z31.s, p0/m, z31.s, #32 +// CHECK-ENCODING: [0x1f,0x80,0x4c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 4c 04 + +srshr z0.d, p0/m, z0.d, #1 +// CHECK-INST: srshr z0.d, p0/m, z0.d, #1 +// CHECK-ENCODING: [0xe0,0x83,0xcc,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 83 cc 04 + +srshr z31.d, p0/m, z31.d, #64 +// CHECK-INST: srshr z31.d, p0/m, z31.d, #64 +// CHECK-ENCODING: [0x1f,0x80,0x8c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 8c 04 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +srshr z31.d, p0/m, z31.d, #64 +// CHECK-INST: srshr z31.d, p0/m, z31.d, #64 +// CHECK-ENCODING: [0x1f,0x80,0x8c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 8c 04 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +srshr z31.d, p0/m, z31.d, #64 +// CHECK-INST: srshr z31.d, p0/m, z31.d, #64 +// CHECK-ENCODING: [0x1f,0x80,0x8c,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 8c 04 diff --git a/llvm/test/MC/AArch64/SVE2/uqrshl-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqrshl-diagnostics.s new file mode 100644 index 0000000000000..120ad54deb055 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshl-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqrshl z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqrshl z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqrshl z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshl z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshl z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshl z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqrshl z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqrshl z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshl z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqrshl z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqrshl.s b/llvm/test/MC/AArch64/SVE2/uqrshl.s new file mode 100644 index 0000000000000..8dde5efb5e244 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshl.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqrshl z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqrshl z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x0b,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 0b 44 + +uqrshl z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqrshl z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x4b,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 4b 44 + +uqrshl z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqrshl z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x8b,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 8b 44 + +uqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcb,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cb 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqrshl z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqrshl z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xcb,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 cb 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqrshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcb,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cb 44 diff --git a/llvm/test/MC/AArch64/SVE2/uqrshlr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqrshlr-diagnostics.s new file mode 100644 index 0000000000000..b235ae8aaa55f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshlr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqrshlr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqrshlr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqrshlr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshlr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshlr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshlr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqrshlr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqrshlr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshlr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqrshlr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqrshlr.s b/llvm/test/MC/AArch64/SVE2/uqrshlr.s new file mode 100644 index 0000000000000..eb6aabf6a014b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshlr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqrshlr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqrshlr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x0f,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 0f 44 + +uqrshlr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqrshlr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x4f,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 4f 44 + +uqrshlr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqrshlr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x8f,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 8f 44 + +uqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcf,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cf 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqrshlr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqrshlr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xcf,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 cf 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqrshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcf,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cf 44 diff --git a/llvm/test/MC/AArch64/SVE2/uqshl-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqshl-diagnostics.s new file mode 100644 index 0000000000000..e3a44cb05b945 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshl-diagnostics.s @@ -0,0 +1,98 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +uqshl z0.b, p0/m, z0.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: uqshl z0.b, p0/m, z0.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.b, p0/m, z0.b, #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: uqshl z0.b, p0/m, z0.b, #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.h, p0/m, z0.h, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: uqshl z0.h, p0/m, z0.h, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.h, p0/m, z0.h, #16 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: uqshl z0.h, p0/m, z0.h, #16 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.s, p0/m, z0.s, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: uqshl z0.s, p0/m, z0.s, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.s, p0/m, z0.s, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: uqshl z0.s, p0/m, z0.s, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.d, p0/m, z0.d, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: uqshl z0.d, p0/m, z0.d, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.d, p0/m, z0.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: uqshl z0.d, p0/m, z0.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqshl z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqshl z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.b, p0/m, z1.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqshl z0.b, p0/m, z1.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqshl z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshl z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshl z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.b, p0/m, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshl z0.b, p0/m, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.d, p0/m, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshl z0.d, p0/m, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqshl z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqshl z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqshl z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshl z0.b, p8/m, z0.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqshl z0.b, p8/m, z0.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqshl.s b/llvm/test/MC/AArch64/SVE2/uqshl.s new file mode 100644 index 0000000000000..36e8c6e11757a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshl.s @@ -0,0 +1,131 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqshl z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqshl z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x09,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 09 44 + +uqshl z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqshl z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x49,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 49 44 + +uqshl z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqshl z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x89,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 89 44 + +uqshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc9,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c9 44 + +uqshl z0.b, p0/m, z0.b, #0 +// CHECK-INST: uqshl z0.b, p0/m, z0.b, #0 +// CHECK-ENCODING: [0x00,0x81,0x07,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 81 07 04 + +uqshl z31.b, p0/m, z31.b, #7 +// CHECK-INST: uqshl z31.b, p0/m, z31.b, #7 +// CHECK-ENCODING: [0xff,0x81,0x07,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 81 07 04 + +uqshl z0.h, p0/m, z0.h, #0 +// CHECK-INST: uqshl z0.h, p0/m, z0.h, #0 +// CHECK-ENCODING: [0x00,0x82,0x07,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 82 07 04 + +uqshl z31.h, p0/m, z31.h, #15 +// CHECK-INST: uqshl z31.h, p0/m, z31.h, #15 +// CHECK-ENCODING: [0xff,0x83,0x07,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 07 04 + +uqshl z0.s, p0/m, z0.s, #0 +// CHECK-INST: uqshl z0.s, p0/m, z0.s, #0 +// CHECK-ENCODING: [0x00,0x80,0x47,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 47 04 + +uqshl z31.s, p0/m, z31.s, #31 +// CHECK-INST: uqshl z31.s, p0/m, z31.s, #31 +// CHECK-ENCODING: [0xff,0x83,0x47,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 47 04 + +uqshl z0.d, p0/m, z0.d, #0 +// CHECK-INST: uqshl z0.d, p0/m, z0.d, #0 +// CHECK-ENCODING: [0x00,0x80,0x87,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 87 04 + +uqshl z31.d, p0/m, z31.d, #63 +// CHECK-INST: uqshl z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xc7,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 c7 04 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqshl z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqshl z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xc9,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 c9 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc9,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c9 44 + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqshl z31.d, p0/m, z31.d, #63 +// CHECK-INST: uqshl z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xc7,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 c7 04 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqshl z31.d, p0/m, z31.d, #63 +// CHECK-INST: uqshl z31.d, p0/m, z31.d, #63 +// CHECK-ENCODING: [0xff,0x83,0xc7,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 83 c7 04 diff --git a/llvm/test/MC/AArch64/SVE2/uqshlr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqshlr-diagnostics.s new file mode 100644 index 0000000000000..c8006eab6f1fc --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshlr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +uqshlr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: uqshlr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +uqshlr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshlr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshlr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshlr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +uqshlr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: uqshlr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshlr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: uqshlr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqshlr.s b/llvm/test/MC/AArch64/SVE2/uqshlr.s new file mode 100644 index 0000000000000..eaadc0ba72157 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshlr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqshlr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: uqshlr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x0d,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 0d 44 + +uqshlr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: uqshlr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x4d,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 4d 44 + +uqshlr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: uqshlr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x8d,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 8d 44 + +uqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcd,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cd 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +uqshlr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: uqshlr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xcd,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 cd 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +uqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: uqshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xcd,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f cd 44 diff --git a/llvm/test/MC/AArch64/SVE2/urshl-diagnostics.s b/llvm/test/MC/AArch64/SVE2/urshl-diagnostics.s new file mode 100644 index 0000000000000..d1ec794871d86 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/urshl-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +urshl z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: urshl z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +urshl z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: urshl z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshl z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: urshl z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +urshl z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: urshl z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshl z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: urshl z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/urshl.s b/llvm/test/MC/AArch64/SVE2/urshl.s new file mode 100644 index 0000000000000..9e057fb261156 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/urshl.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +urshl z0.b, p0/m, z0.b, z1.b +// CHECK-INST: urshl z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x03,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 03 44 + +urshl z0.h, p0/m, z0.h, z1.h +// CHECK-INST: urshl z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x43,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 43 44 + +urshl z29.s, p7/m, z29.s, z30.s +// CHECK-INST: urshl z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x83,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 83 44 + +urshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: urshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc3,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c3 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +urshl z31.d, p0/m, z31.d, z30.d +// CHECK-INST: urshl z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xc3,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 c3 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +urshl z31.d, p7/m, z31.d, z30.d +// CHECK-INST: urshl z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc3,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c3 44 diff --git a/llvm/test/MC/AArch64/SVE2/urshlr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/urshlr-diagnostics.s new file mode 100644 index 0000000000000..2241eb3885d02 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/urshlr-diagnostics.s @@ -0,0 +1,37 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +urshlr z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: urshlr z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +urshlr z0.b, p0/m, z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: urshlr z0.b, p0/m, z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshlr z0.b, p0/m, z0.b, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: urshlr z0.b, p0/m, z0.b, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +urshlr z0.b, p0/z, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: urshlr z0.b, p0/z, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshlr z0.b, p8/m, z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: urshlr z0.b, p8/m, z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/urshlr.s b/llvm/test/MC/AArch64/SVE2/urshlr.s new file mode 100644 index 0000000000000..170eb4a7aeb64 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/urshlr.s @@ -0,0 +1,59 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +urshlr z0.b, p0/m, z0.b, z1.b +// CHECK-INST: urshlr z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: [0x20,0x80,0x07,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 07 44 + +urshlr z0.h, p0/m, z0.h, z1.h +// CHECK-INST: urshlr z0.h, p0/m, z0.h, z1.h +// CHECK-ENCODING: [0x20,0x80,0x47,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 80 47 44 + +urshlr z29.s, p7/m, z29.s, z30.s +// CHECK-INST: urshlr z29.s, p7/m, z29.s, z30.s +// CHECK-ENCODING: [0xdd,0x9f,0x87,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 9f 87 44 + +urshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: urshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc7,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c7 44 + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +urshlr z31.d, p0/m, z31.d, z30.d +// CHECK-INST: urshlr z31.d, p0/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x83,0xc7,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 83 c7 44 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +urshlr z31.d, p7/m, z31.d, z30.d +// CHECK-INST: urshlr z31.d, p7/m, z31.d, z30.d +// CHECK-ENCODING: [0xdf,0x9f,0xc7,0x44] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f c7 44 diff --git a/llvm/test/MC/AArch64/SVE2/urshr-diagnostics.s b/llvm/test/MC/AArch64/SVE2/urshr-diagnostics.s new file mode 100644 index 0000000000000..f021bb9de7aba --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/urshr-diagnostics.s @@ -0,0 +1,78 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +urshr z18.b, p0/m, z18.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: urshr z18.b, p0/m, z18.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z1.b, p0/m, z1.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: urshr z1.b, p0/m, z1.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z21.h, p0/m, z21.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: urshr z21.h, p0/m, z21.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z14.h, p0/m, z14.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: urshr z14.h, p0/m, z14.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z6.s, p0/m, z6.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: urshr z6.s, p0/m, z6.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z23.s, p0/m, z23.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: urshr z23.s, p0/m, z23.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z3.d, p0/m, z3.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: urshr z3.d, p0/m, z3.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z25.d, p0/m, z25.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: urshr z25.d, p0/m, z25.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +urshr z0.b, p0/m, z1.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: urshr z0.b, p0/m, z1.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +urshr z0.b, p0/m, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: urshr z0.b, p0/m, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z0.d, p0/m, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: urshr z0.d, p0/m, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate + +urshr z0.b, p0/z, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: urshr z0.b, p0/z, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +urshr z0.b, p8/m, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: urshr z0.b, p8/m, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/urshr.s b/llvm/test/MC/AArch64/SVE2/urshr.s new file mode 100644 index 0000000000000..b06edfeb9b792 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/urshr.s @@ -0,0 +1,84 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +urshr z0.b, p0/m, z0.b, #1 +// CHECK-INST: urshr z0.b, p0/m, z0.b, #1 +// CHECK-ENCODING: [0xe0,0x81,0x0d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 81 0d 04 + +urshr z31.b, p0/m, z31.b, #8 +// CHECK-INST: urshr z31.b, p0/m, z31.b, #8 +// CHECK-ENCODING: [0x1f,0x81,0x0d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 81 0d 04 + +urshr z0.h, p0/m, z0.h, #1 +// CHECK-INST: urshr z0.h, p0/m, z0.h, #1 +// CHECK-ENCODING: [0xe0,0x83,0x0d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 83 0d 04 + +urshr z31.h, p0/m, z31.h, #16 +// CHECK-INST: urshr z31.h, p0/m, z31.h, #16 +// CHECK-ENCODING: [0x1f,0x82,0x0d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 82 0d 04 + +urshr z0.s, p0/m, z0.s, #1 +// CHECK-INST: urshr z0.s, p0/m, z0.s, #1 +// CHECK-ENCODING: [0xe0,0x83,0x4d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 83 4d 04 + +urshr z31.s, p0/m, z31.s, #32 +// CHECK-INST: urshr z31.s, p0/m, z31.s, #32 +// CHECK-ENCODING: [0x1f,0x80,0x4d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 4d 04 + +urshr z0.d, p0/m, z0.d, #1 +// CHECK-INST: urshr z0.d, p0/m, z0.d, #1 +// CHECK-ENCODING: [0xe0,0x83,0xcd,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 83 cd 04 + +urshr z31.d, p0/m, z31.d, #64 +// CHECK-INST: urshr z31.d, p0/m, z31.d, #64 +// CHECK-ENCODING: [0x1f,0x80,0x8d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 8d 04 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z31.d, p0/z, z6.d +// CHECK-INST: movprfx z31.d, p0/z, z6.d +// CHECK-ENCODING: [0xdf,0x20,0xd0,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df 20 d0 04 + +urshr z31.d, p0/m, z31.d, #64 +// CHECK-INST: urshr z31.d, p0/m, z31.d, #64 +// CHECK-ENCODING: [0x1f,0x80,0x8d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 8d 04 + +movprfx z31, z6 +// CHECK-INST: movprfx z31, z6 +// CHECK-ENCODING: [0xdf,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: df bc 20 04 + +urshr z31.d, p0/m, z31.d, #64 +// CHECK-INST: urshr z31.d, p0/m, z31.d, #64 +// CHECK-ENCODING: [0x1f,0x80,0x8d,0x04] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 1f 80 8d 04 From b4771425f53c7c7efa911eac0399b4029073e7d0 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Fri, 24 May 2019 09:20:20 +0000 Subject: [PATCH 0147/1176] Use the DataLayout::typeSizeEqualsStoreSize helper. NFC Just a minor refactoring to use the new helper method DataLayout::typeSizeEqualsStoreSize(). This is done when checking if getTypeSizeInBits is equal/non-equal to getTypeStoreSizeInBits. llvm-svn: 361613 --- llvm/lib/CodeGen/CodeGenPrepare.cpp | 5 ++--- .../Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp | 2 +- llvm/lib/Transforms/Scalar/SROA.cpp | 6 ++---- llvm/lib/Transforms/Scalar/Scalarizer.cpp | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 76f82c27847d0..488cfe6b6c89c 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -6649,14 +6649,13 @@ static bool splitMergedValStore(StoreInst &SI, const DataLayout &DL, const TargetLowering &TLI) { // Handle simple but common cases only. Type *StoreType = SI.getValueOperand()->getType(); - if (DL.getTypeStoreSizeInBits(StoreType) != DL.getTypeSizeInBits(StoreType) || + if (!DL.typeSizeEqualsStoreSize(StoreType) || DL.getTypeSizeInBits(StoreType) == 0) return false; unsigned HalfValBitSize = DL.getTypeSizeInBits(StoreType) / 2; Type *SplitStoreType = Type::getIntNTy(SI.getContext(), HalfValBitSize); - if (DL.getTypeStoreSizeInBits(SplitStoreType) != - DL.getTypeSizeInBits(SplitStoreType)) + if (!DL.typeSizeEqualsStoreSize(SplitStoreType)) return false; // Don't split the store if it is volatile. diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index dd07561d4646f..0df80e07e840a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -630,7 +630,7 @@ static Instruction *combineLoadToOperationType(InstCombiner &IC, LoadInst &LI) { // infinite loop). if (!Ty->isIntegerTy() && Ty->isSized() && DL.isLegalInteger(DL.getTypeStoreSizeInBits(Ty)) && - DL.getTypeStoreSizeInBits(Ty) == DL.getTypeSizeInBits(Ty) && + DL.typeSizeEqualsStoreSize(Ty) && !DL.isNonIntegralPointerType(Ty) && !isMinMaxWithLoads( peekThroughBitcast(LI.getPointerOperand(), /*OneUseOnly=*/true))) { diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index 9786614db0af3..790a16d2aff77 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -2519,8 +2519,7 @@ class llvm::sroa::AllocaSliceRewriter "Only integer type loads and stores are split"); assert(SliceSize < DL.getTypeStoreSize(LI.getType()) && "Split load isn't smaller than original load"); - assert(LI.getType()->getIntegerBitWidth() == - DL.getTypeStoreSizeInBits(LI.getType()) && + assert(DL.typeSizeEqualsStoreSize(LI.getType()) && "Non-byte-multiple bit width"); // Move the insertion point just past the load so that we can refer to it. IRB.SetInsertPoint(&*std::next(BasicBlock::iterator(&LI))); @@ -2615,8 +2614,7 @@ class llvm::sroa::AllocaSliceRewriter assert(!SI.isVolatile()); assert(V->getType()->isIntegerTy() && "Only integer type loads and stores are split"); - assert(V->getType()->getIntegerBitWidth() == - DL.getTypeStoreSizeInBits(V->getType()) && + assert(DL.typeSizeEqualsStoreSize(V->getType()) && "Non-byte-multiple bit width"); IntegerType *NarrowTy = Type::getIntNTy(SI.getContext(), SliceSize * 8); V = extractInteger(DL, IRB, V, NarrowTy, NewBeginOffset - BeginOffset, diff --git a/llvm/lib/Transforms/Scalar/Scalarizer.cpp b/llvm/lib/Transforms/Scalar/Scalarizer.cpp index 3d554f15af2cf..0bd0fff1aa59b 100644 --- a/llvm/lib/Transforms/Scalar/Scalarizer.cpp +++ b/llvm/lib/Transforms/Scalar/Scalarizer.cpp @@ -408,8 +408,7 @@ bool ScalarizerVisitor::getVectorLayout(Type *Ty, unsigned Alignment, // Check that we're dealing with full-byte elements. Layout.ElemTy = Layout.VecTy->getElementType(); - if (DL.getTypeSizeInBits(Layout.ElemTy) != - DL.getTypeStoreSizeInBits(Layout.ElemTy)) + if (!DL.typeSizeEqualsStoreSize(Layout.ElemTy)) return false; if (Alignment) From 7f1ff68a165a8a593dd96b4e77691a61a91612c5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 24 May 2019 09:25:47 +0000 Subject: [PATCH 0148/1176] [ELF] Deleted unused forward declarations. NFC llvm-svn: 361614 --- lld/ELF/LinkerScript.h | 1 - lld/ELF/SymbolTable.h | 8 -------- 2 files changed, 9 deletions(-) diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index e5f464ff1fd5e..fe092b27d6f03 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -31,7 +31,6 @@ namespace elf { class Defined; class InputSection; class InputSectionBase; -class InputSectionBase; class OutputSection; class SectionBase; class Symbol; diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 8c9a8f8f2e760..6e93e0a144d9a 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -17,14 +17,6 @@ namespace lld { namespace elf { -class CommonSymbol; -class Defined; -class LazyArchive; -class LazyObject; -class SectionBase; -class SharedSymbol; -class Undefined; - // SymbolTable is a bucket of all known symbols, including defined, // undefined, or lazy symbols (the last one is symbols in archive // files whose archive members are not yet loaded). From 8bcea9daaa6236b92ccc4453e398ed46d1f32745 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 09:28:27 +0000 Subject: [PATCH 0149/1176] [AArch64][SVE2] Asm: add integer add/sub long/wide instructions Summary: Patch adds support for the following instructions: SVE2 integer add/subtract long: * SADDLB, SADDLT, UADDLB, UADDLT, SSUBLB, SSUBLT, USUBLB, USUBLT, SABDLB, SABDLT, UABDLB, UABDLT SVE2 integer add/subtract wide: * SADDWB, SADDWT, UADDWB, UADDWT, SSUBWB, SSUBWT, USUBWB, USUBWT The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D62142 llvm-svn: 361615 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 24 +++++++++++ llvm/lib/Target/AArch64/SVEInstrFormats.td | 6 +++ .../test/MC/AArch64/SVE2/sabdlb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/sabdlb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/sabdlt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/sabdlt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/saddlb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/saddlb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/saddlt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/saddlt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/saddwb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/saddwb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/saddwt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/saddwt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/ssublb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/ssublb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/ssublt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/ssublt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/ssubwb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/ssubwb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/ssubwt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/ssubwt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/uabdlb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uabdlb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/uabdlt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uabdlt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/uaddlb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uaddlb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/uaddlt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uaddlt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/uaddwb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uaddwb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/uaddwt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/uaddwt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/usublb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/usublb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/usublt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/usublt.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/usubwb-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/usubwb.s | 27 +++++++++++++ .../test/MC/AArch64/SVE2/usubwt-diagnostics.s | 40 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/usubwt.s | 27 +++++++++++++ 42 files changed, 1370 insertions(+) create mode 100644 llvm/test/MC/AArch64/SVE2/sabdlb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabdlb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabdlt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabdlt.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddlb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddlb.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddlt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddlt.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddwb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddwb.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddwt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/saddwt.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssublb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssublb.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssublt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssublt.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssubwb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssubwb.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssubwt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssubwt.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabdlb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabdlb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabdlt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabdlt.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddlb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddlb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddlt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddlt.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddwb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddwb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddwt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaddwt.s create mode 100644 llvm/test/MC/AArch64/SVE2/usublb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/usublb.s create mode 100644 llvm/test/MC/AArch64/SVE2/usublt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/usublt.s create mode 100644 llvm/test/MC/AArch64/SVE2/usubwb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/usubwb.s create mode 100644 llvm/test/MC/AArch64/SVE2/usubwt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/usubwt.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 9d775ec8d5f7f..dd14e4ba815e4 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1164,6 +1164,30 @@ let Predicates = [HasSVE2] in { defm SQRSHLR_ZPmZ : sve2_int_arith_pred<0b011100, "sqrshlr">; defm UQRSHLR_ZPmZ : sve2_int_arith_pred<0b011110, "uqrshlr">; + // SVE2 integer add/subtract long + defm SADDLB_ZZZ : sve2_wide_int_arith_long<0b00000, "saddlb">; + defm SADDLT_ZZZ : sve2_wide_int_arith_long<0b00001, "saddlt">; + defm UADDLB_ZZZ : sve2_wide_int_arith_long<0b00010, "uaddlb">; + defm UADDLT_ZZZ : sve2_wide_int_arith_long<0b00011, "uaddlt">; + defm SSUBLB_ZZZ : sve2_wide_int_arith_long<0b00100, "ssublb">; + defm SSUBLT_ZZZ : sve2_wide_int_arith_long<0b00101, "ssublt">; + defm USUBLB_ZZZ : sve2_wide_int_arith_long<0b00110, "usublb">; + defm USUBLT_ZZZ : sve2_wide_int_arith_long<0b00111, "usublt">; + defm SABDLB_ZZZ : sve2_wide_int_arith_long<0b01100, "sabdlb">; + defm SABDLT_ZZZ : sve2_wide_int_arith_long<0b01101, "sabdlt">; + defm UABDLB_ZZZ : sve2_wide_int_arith_long<0b01110, "uabdlb">; + defm UABDLT_ZZZ : sve2_wide_int_arith_long<0b01111, "uabdlt">; + + // SVE2 integer add/subtract wide + defm SADDWB_ZZZ : sve2_wide_int_arith_wide<0b000, "saddwb">; + defm SADDWT_ZZZ : sve2_wide_int_arith_wide<0b001, "saddwt">; + defm UADDWB_ZZZ : sve2_wide_int_arith_wide<0b010, "uaddwb">; + defm UADDWT_ZZZ : sve2_wide_int_arith_wide<0b011, "uaddwt">; + defm SSUBWB_ZZZ : sve2_wide_int_arith_wide<0b100, "ssubwb">; + defm SSUBWT_ZZZ : sve2_wide_int_arith_wide<0b101, "ssubwt">; + defm USUBWB_ZZZ : sve2_wide_int_arith_wide<0b110, "usubwb">; + defm USUBWT_ZZZ : sve2_wide_int_arith_wide<0b111, "usubwt">; + // SVE2 integer multiply long defm SQDMULLB_ZZZ : sve2_wide_int_arith_long<0b11000, "sqdmullb">; defm SQDMULLT_ZZZ : sve2_wide_int_arith_long<0b11001, "sqdmullt">; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 8b4c00935e524..b741f09886b55 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -2180,6 +2180,12 @@ multiclass sve2_wide_int_arith_long opc, string asm> { def _D : sve2_wide_int_arith<0b11, opc, asm, ZPR64, ZPR32, ZPR32>; } +multiclass sve2_wide_int_arith_wide opc, string asm> { + def _H : sve2_wide_int_arith<0b01, { 0b10, opc }, asm, ZPR16, ZPR16, ZPR8>; + def _S : sve2_wide_int_arith<0b10, { 0b10, opc }, asm, ZPR32, ZPR32, ZPR16>; + def _D : sve2_wide_int_arith<0b11, { 0b10, opc }, asm, ZPR64, ZPR64, ZPR32>; +} + //===----------------------------------------------------------------------===// // SVE Integer Arithmetic - Unary Predicated Group //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SVE2/sabdlb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sabdlb-diagnostics.s new file mode 100644 index 0000000000000..2e7d0f5388bfb --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabdlb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sabdlb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabdlb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabdlb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabdlb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +sabdlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sabdlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +sabdlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sabdlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sabdlb.s b/llvm/test/MC/AArch64/SVE2/sabdlb.s new file mode 100644 index 0000000000000..af2b358cea737 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabdlb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sabdlb z0.h, z1.b, z2.b +// CHECK-INST: sabdlb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x30,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 30 42 45 + +sabdlb z29.s, z30.h, z31.h +// CHECK-INST: sabdlb z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x33,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 33 9f 45 + +sabdlb z31.d, z31.s, z31.s +// CHECK-INST: sabdlb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x33,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 33 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sabdlt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sabdlt-diagnostics.s new file mode 100644 index 0000000000000..b08ff54aec3f7 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabdlt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sabdlt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabdlt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabdlt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabdlt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabdlt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +sabdlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sabdlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +sabdlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sabdlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sabdlt.s b/llvm/test/MC/AArch64/SVE2/sabdlt.s new file mode 100644 index 0000000000000..f8819b5a388ae --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabdlt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sabdlt z0.h, z1.b, z2.b +// CHECK-INST: sabdlt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x34,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 34 42 45 + +sabdlt z29.s, z30.h, z31.h +// CHECK-INST: sabdlt z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x37,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 37 9f 45 + +sabdlt z31.d, z31.s, z31.s +// CHECK-INST: sabdlt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x37,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 37 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/saddlb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/saddlb-diagnostics.s new file mode 100644 index 0000000000000..46d9bc408f18f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddlb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +saddlb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddlb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddlb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddlb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +saddlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +saddlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/saddlb.s b/llvm/test/MC/AArch64/SVE2/saddlb.s new file mode 100644 index 0000000000000..d592ae8ec6a79 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddlb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +saddlb z0.h, z1.b, z2.b +// CHECK-INST: saddlb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x00,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 00 42 45 + +saddlb z29.s, z30.h, z31.h +// CHECK-INST: saddlb z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x03,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 03 9f 45 + +saddlb z31.d, z31.s, z31.s +// CHECK-INST: saddlb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x03,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 03 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/saddlt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/saddlt-diagnostics.s new file mode 100644 index 0000000000000..437a146576452 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddlt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +saddlt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddlt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddlt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddlt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddlt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +saddlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +saddlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/saddlt.s b/llvm/test/MC/AArch64/SVE2/saddlt.s new file mode 100644 index 0000000000000..047bc4fa2ba37 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddlt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +saddlt z0.h, z1.b, z2.b +// CHECK-INST: saddlt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x04,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 04 42 45 + +saddlt z29.s, z30.h, z31.h +// CHECK-INST: saddlt z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x07,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 07 9f 45 + +saddlt z31.d, z31.s, z31.s +// CHECK-INST: saddlt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x07,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 07 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/saddwb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/saddwb-diagnostics.s new file mode 100644 index 0000000000000..b308fdd1042ec --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddwb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +saddwb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddwb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddwb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddwb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +saddwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +saddwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/saddwb.s b/llvm/test/MC/AArch64/SVE2/saddwb.s new file mode 100644 index 0000000000000..2b9213de26070 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddwb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +saddwb z0.h, z1.h, z2.b +// CHECK-INST: saddwb z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x40,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 40 42 45 + +saddwb z29.s, z30.s, z31.h +// CHECK-INST: saddwb z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x43,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 43 9f 45 + +saddwb z31.d, z31.d, z31.s +// CHECK-INST: saddwb z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x43,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 43 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/saddwt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/saddwt-diagnostics.s new file mode 100644 index 0000000000000..133830d39bca4 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddwt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +saddwt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddwt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddwt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +saddwt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saddwt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +saddwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +saddwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: saddwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/saddwt.s b/llvm/test/MC/AArch64/SVE2/saddwt.s new file mode 100644 index 0000000000000..7521eb6f0133e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saddwt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +saddwt z0.h, z1.h, z2.b +// CHECK-INST: saddwt z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x44,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 44 42 45 + +saddwt z29.s, z30.s, z31.h +// CHECK-INST: saddwt z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x47,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 47 9f 45 + +saddwt z31.d, z31.d, z31.s +// CHECK-INST: saddwt z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x47,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 47 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/ssublb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/ssublb-diagnostics.s new file mode 100644 index 0000000000000..d608194a9124a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssublb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +ssublb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssublb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssublb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssublb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +ssublb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssublb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +ssublb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssublb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/ssublb.s b/llvm/test/MC/AArch64/SVE2/ssublb.s new file mode 100644 index 0000000000000..3ccc3abf52dc1 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssublb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +ssublb z0.h, z1.b, z2.b +// CHECK-INST: ssublb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x10,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 10 42 45 + +ssublb z29.s, z30.h, z31.h +// CHECK-INST: ssublb z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x13,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 13 9f 45 + +ssublb z31.d, z31.s, z31.s +// CHECK-INST: ssublb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x13,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 13 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/ssublt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/ssublt-diagnostics.s new file mode 100644 index 0000000000000..5c7d7b952da89 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssublt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +ssublt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssublt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssublt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssublt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssublt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +ssublt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssublt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +ssublt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssublt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/ssublt.s b/llvm/test/MC/AArch64/SVE2/ssublt.s new file mode 100644 index 0000000000000..ffd7d54cab975 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssublt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +ssublt z0.h, z1.b, z2.b +// CHECK-INST: ssublt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x14,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 14 42 45 + +ssublt z29.s, z30.h, z31.h +// CHECK-INST: ssublt z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x17,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 17 9f 45 + +ssublt z31.d, z31.s, z31.s +// CHECK-INST: ssublt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x17,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 17 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/ssubwb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/ssubwb-diagnostics.s new file mode 100644 index 0000000000000..94679b2d6db7f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssubwb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +ssubwb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssubwb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssubwb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssubwb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +ssubwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssubwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +ssubwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssubwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/ssubwb.s b/llvm/test/MC/AArch64/SVE2/ssubwb.s new file mode 100644 index 0000000000000..be3a41e91322e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssubwb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +ssubwb z0.h, z1.h, z2.b +// CHECK-INST: ssubwb z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x50,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 50 42 45 + +ssubwb z29.s, z30.s, z31.h +// CHECK-INST: ssubwb z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x53,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 53 9f 45 + +ssubwb z31.d, z31.d, z31.s +// CHECK-INST: ssubwb z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x53,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 53 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/ssubwt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/ssubwt-diagnostics.s new file mode 100644 index 0000000000000..e1ba02da627c0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssubwt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +ssubwt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssubwt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssubwt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssubwt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssubwt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +ssubwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssubwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +ssubwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: ssubwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/ssubwt.s b/llvm/test/MC/AArch64/SVE2/ssubwt.s new file mode 100644 index 0000000000000..1894548a6d3f9 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssubwt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +ssubwt z0.h, z1.h, z2.b +// CHECK-INST: ssubwt z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x54,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 54 42 45 + +ssubwt z29.s, z30.s, z31.h +// CHECK-INST: ssubwt z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x57,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 57 9f 45 + +ssubwt z31.d, z31.d, z31.s +// CHECK-INST: ssubwt z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x57,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 57 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uabdlb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uabdlb-diagnostics.s new file mode 100644 index 0000000000000..a24e3b7c617d0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabdlb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uabdlb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabdlb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabdlb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabdlb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +uabdlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uabdlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +uabdlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uabdlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uabdlb.s b/llvm/test/MC/AArch64/SVE2/uabdlb.s new file mode 100644 index 0000000000000..7782fdb9fec70 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabdlb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uabdlb z0.h, z1.b, z2.b +// CHECK-INST: uabdlb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x38,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 38 42 45 + +uabdlb z29.s, z30.h, z31.h +// CHECK-INST: uabdlb z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x3b,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 3b 9f 45 + +uabdlb z31.d, z31.s, z31.s +// CHECK-INST: uabdlb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x3b,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3b df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uabdlt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uabdlt-diagnostics.s new file mode 100644 index 0000000000000..ed63851a2e92b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabdlt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uabdlt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabdlt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabdlt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabdlt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabdlt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +uabdlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uabdlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +uabdlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uabdlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uabdlt.s b/llvm/test/MC/AArch64/SVE2/uabdlt.s new file mode 100644 index 0000000000000..118c286c18739 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabdlt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uabdlt z0.h, z1.b, z2.b +// CHECK-INST: uabdlt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x3c,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 3c 42 45 + +uabdlt z29.s, z30.h, z31.h +// CHECK-INST: uabdlt z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x3f,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 3f 9f 45 + +uabdlt z31.d, z31.s, z31.s +// CHECK-INST: uabdlt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x3f,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3f df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uaddlb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uaddlb-diagnostics.s new file mode 100644 index 0000000000000..0272eb29a1de8 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddlb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uaddlb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddlb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddlb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddlb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +uaddlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +uaddlb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddlb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uaddlb.s b/llvm/test/MC/AArch64/SVE2/uaddlb.s new file mode 100644 index 0000000000000..6804540fdf0d7 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddlb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uaddlb z0.h, z1.b, z2.b +// CHECK-INST: uaddlb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x08,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 08 42 45 + +uaddlb z29.s, z30.h, z31.h +// CHECK-INST: uaddlb z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x0b,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 0b 9f 45 + +uaddlb z31.d, z31.s, z31.s +// CHECK-INST: uaddlb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x0b,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0b df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uaddlt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uaddlt-diagnostics.s new file mode 100644 index 0000000000000..84f68dd2c313e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddlt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uaddlt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddlt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddlt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddlt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddlt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +uaddlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +uaddlt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddlt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uaddlt.s b/llvm/test/MC/AArch64/SVE2/uaddlt.s new file mode 100644 index 0000000000000..366f2c42ed4d6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddlt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uaddlt z0.h, z1.b, z2.b +// CHECK-INST: uaddlt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x0c,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 0c 42 45 + +uaddlt z29.s, z30.h, z31.h +// CHECK-INST: uaddlt z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x0f,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 0f 9f 45 + +uaddlt z31.d, z31.s, z31.s +// CHECK-INST: uaddlt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x0f,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0f df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uaddwb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uaddwb-diagnostics.s new file mode 100644 index 0000000000000..f7f3084ce2d31 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddwb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uaddwb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddwb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddwb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddwb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +uaddwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +uaddwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uaddwb.s b/llvm/test/MC/AArch64/SVE2/uaddwb.s new file mode 100644 index 0000000000000..d07d779b1c27c --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddwb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uaddwb z0.h, z1.h, z2.b +// CHECK-INST: uaddwb z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x48,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 48 42 45 + +uaddwb z29.s, z30.s, z31.h +// CHECK-INST: uaddwb z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x4b,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 4b 9f 45 + +uaddwb z31.d, z31.d, z31.s +// CHECK-INST: uaddwb z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x4b,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 4b df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uaddwt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uaddwt-diagnostics.s new file mode 100644 index 0000000000000..b916ec6014f96 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddwt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uaddwt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddwt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddwt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uaddwt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaddwt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +uaddwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +uaddwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uaddwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uaddwt.s b/llvm/test/MC/AArch64/SVE2/uaddwt.s new file mode 100644 index 0000000000000..6520bd449187f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaddwt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uaddwt z0.h, z1.h, z2.b +// CHECK-INST: uaddwt z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x4c,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 4c 42 45 + +uaddwt z29.s, z30.s, z31.h +// CHECK-INST: uaddwt z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x4f,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 4f 9f 45 + +uaddwt z31.d, z31.d, z31.s +// CHECK-INST: uaddwt z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x4f,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 4f df 45 diff --git a/llvm/test/MC/AArch64/SVE2/usublb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/usublb-diagnostics.s new file mode 100644 index 0000000000000..074235809097a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usublb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +usublb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usublb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usublb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usublb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +usublb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usublb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +usublb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usublb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/usublb.s b/llvm/test/MC/AArch64/SVE2/usublb.s new file mode 100644 index 0000000000000..a985e38af659d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usublb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +usublb z0.h, z1.b, z2.b +// CHECK-INST: usublb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x18,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 18 42 45 + +usublb z29.s, z30.h, z31.h +// CHECK-INST: usublb z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x1b,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 1b 9f 45 + +usublb z31.d, z31.s, z31.s +// CHECK-INST: usublb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x1b,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1b df 45 diff --git a/llvm/test/MC/AArch64/SVE2/usublt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/usublt-diagnostics.s new file mode 100644 index 0000000000000..2b7f444c10d9d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usublt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +usublt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usublt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usublt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usublt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usublt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +usublt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usublt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +usublt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usublt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/usublt.s b/llvm/test/MC/AArch64/SVE2/usublt.s new file mode 100644 index 0000000000000..9a7f23d6a5427 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usublt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +usublt z0.h, z1.b, z2.b +// CHECK-INST: usublt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x1c,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 1c 42 45 + +usublt z29.s, z30.h, z31.h +// CHECK-INST: usublt z29.s, z30.h, z31.h +// CHECK-ENCODING: [0xdd,0x1f,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 1f 9f 45 + +usublt z31.d, z31.s, z31.s +// CHECK-INST: usublt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x1f,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1f df 45 diff --git a/llvm/test/MC/AArch64/SVE2/usubwb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/usubwb-diagnostics.s new file mode 100644 index 0000000000000..61047157ca65f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usubwb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +usubwb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usubwb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usubwb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usubwb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +usubwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usubwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +usubwb z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usubwb z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/usubwb.s b/llvm/test/MC/AArch64/SVE2/usubwb.s new file mode 100644 index 0000000000000..d1ebf20c725ce --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usubwb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +usubwb z0.h, z1.h, z2.b +// CHECK-INST: usubwb z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x58,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 58 42 45 + +usubwb z29.s, z30.s, z31.h +// CHECK-INST: usubwb z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x5b,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 5b 9f 45 + +usubwb z31.d, z31.d, z31.s +// CHECK-INST: usubwb z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x5b,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 5b df 45 diff --git a/llvm/test/MC/AArch64/SVE2/usubwt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/usubwt-diagnostics.s new file mode 100644 index 0000000000000..69f4c1865b31f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usubwt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +usubwt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usubwt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usubwt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usubwt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usubwt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +usubwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usubwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +usubwt z0.d, z1.d, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: usubwt z0.d, z1.d, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/usubwt.s b/llvm/test/MC/AArch64/SVE2/usubwt.s new file mode 100644 index 0000000000000..2b3874ac89531 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usubwt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +usubwt z0.h, z1.h, z2.b +// CHECK-INST: usubwt z0.h, z1.h, z2.b +// CHECK-ENCODING: [0x20,0x5c,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 5c 42 45 + +usubwt z29.s, z30.s, z31.h +// CHECK-INST: usubwt z29.s, z30.s, z31.h +// CHECK-ENCODING: [0xdd,0x5f,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: dd 5f 9f 45 + +usubwt z31.d, z31.d, z31.s +// CHECK-INST: usubwt z31.d, z31.d, z31.s +// CHECK-ENCODING: [0xff,0x5f,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 5f df 45 From c472f7b010de533cb33a21fad603a0de9cec65c1 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 24 May 2019 09:31:32 +0000 Subject: [PATCH 0150/1176] Fix sphinx "Malformed option description" warning llvm-svn: 361616 --- .../checks/cppcoreguidelines-pro-type-member-init.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst index 5ac0465e5462f..6df091b733e94 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.rst @@ -35,7 +35,7 @@ Options .. option:: UseAssignment If set to non-zero, the check will provide fix-its with literal initializers - (``int i = 0;``) instead of curly braces (``int i{};``). + \( ``int i = 0;`` \) instead of curly braces \( ``int i{};`` \). This rule is part of the "Type safety" profile of the C++ Core Guidelines, corresponding to rule Type.6. See From 7d4a67852da7ecce3ae43b61baa9f0cd068b05c6 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 24 May 2019 09:53:25 +0000 Subject: [PATCH 0151/1176] [ELF] Fix a doc typo. NFC llvm-svn: 361617 --- lld/ELF/MarkLive.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index d040a214aa6cf..5132bb4b72b9b 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -287,7 +287,7 @@ template void elf::markLive() { // unconditionally make non-SHF_ALLOC sections alive except // SHF_LINK_ORDER and SHT_REL/SHT_RELA sections. // - // Usually, SHF_ALLOC sections are not removed even if they are + // Usually, non-SHF_ALLOC sections are not removed even if they are // unreachable through relocations because reachability is not // a good signal whether they are garbage or not (e.g. there is // usually no section referring to a .comment section, but we From 1a0312ca0b20d16edb859065bbace75f6701c92e Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 24 May 2019 09:54:39 +0000 Subject: [PATCH 0152/1176] [FuncUnwinders] Use "symbol file" unwind plans for unwinding Summary: Previous patch (r360409) introduced the "symbol file unwind plan" concept, but that plan wasn't used for unwinding yet. With this patch, we start to consider the new plan as a possible strategy for both synchronous and asynchronous unwinding. I also add a test that asserts that unwinding via breakpad STACK CFI info works end-to-end. Reviewers: jasonmolenda, clayborg Subscribers: lldb-commits, amccarth, markmentovai Differential Revision: https://reviews.llvm.org/D61853 llvm-svn: 361618 --- lldb/include/lldb/Symbol/FuncUnwinders.h | 2 +- .../Breakpad/Inputs/unwind-via-stack-cfi.syms | 6 +++ .../Breakpad/Inputs/unwind-via-stack-cfi.yaml | 43 +++++++++++++++++++ .../Breakpad/stack-cfi-parsing.test | 4 ++ .../Breakpad/unwind-via-stack-cfi.test | 20 +++++++++ lldb/source/Commands/CommandObjectTarget.cpp | 2 +- .../Process/Utility/RegisterContextLLDB.cpp | 14 +++--- lldb/source/Symbol/FuncUnwinders.cpp | 7 ++- 8 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms create mode 100644 lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.yaml create mode 100644 lldb/lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test diff --git a/lldb/include/lldb/Symbol/FuncUnwinders.h b/lldb/include/lldb/Symbol/FuncUnwinders.h index 1872e77fb82ba..cc767d4e1e82f 100644 --- a/lldb/include/lldb/Symbol/FuncUnwinders.h +++ b/lldb/include/lldb/Symbol/FuncUnwinders.h @@ -35,7 +35,7 @@ class FuncUnwinders { ~FuncUnwinders(); - lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target); + lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread); lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target, lldb_private::Thread &thread); diff --git a/lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms b/lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms new file mode 100644 index 0000000000000..d4c8287e68a29 --- /dev/null +++ b/lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.syms @@ -0,0 +1,6 @@ +MODULE Linux x86_64 603FCF6CA7FF4BCC86AE8FF44DB2576A0 linux-x86_64_not_crashed +INFO CODE_ID 6CCF3F60FFA7CC4B86AE8FF44DB2576A68983611 +PUBLIC 420 0 bar +PUBLIC 450 0 foo +PUBLIC 480 0 _start +STACK CFI INIT 420 29 .cfa: $rbp ^ .ra: .cfa 8 + ^ $rsp: .cfa 16 + $rbp: .cfa ^ diff --git a/lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.yaml b/lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.yaml new file mode 100644 index 0000000000000..0672f9e612360 --- /dev/null +++ b/lldb/lit/SymbolFile/Breakpad/Inputs/unwind-via-stack-cfi.yaml @@ -0,0 +1,43 @@ +--- !minidump +Streams: + - Type: ThreadList + Threads: + - Thread Id: 0x000074F3 + Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B001000000000006CAE000000006B7FC05A0000C81D415A0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A2BF9E5A6B7F0000000000000000000000000000000000008850C14BFD7F00009850C14BFD7F00000100000000000000B04AC14BFD7F0000000000000000000060812D01000000000800000000000000B065E05A6B7F00008004400000000000E050C14BFD7F00000000000000000000000000000000000030044000000000007F03FFFF0000FFFFFFFFFFFF000000000000000000000000801F00006B7F00000400000000000000B84CC14BFD7F0000304D405A6B7F0000C84DC14BFD7F0000C0AA405A6B7F00004F033D0000000000B84DC14BFD7F0000E84DC14BFD7F0000000000000000000000000000000000000070E05A6B7F000078629E5A6B7F0000C81D415A6B7F0000804F9E5A6B7F00000000000001000000E603000001000000E093115A6B7F0000804EC14BFD7F0000584EC14BFD7F000099ADC05A6B7F00000100000000000000AAAAD77D0000000002000000000000000800000000000000B065E05A6B7F0000E6B7C05A6B7F0000010000006B7F0000884DC14BFD7F0000106F7C5A6B7F0000984EC14BFD7F0000488B7C5A6B7F0000C4A71CB90000000001000000000000000800000000000000B065E05A6B7F000048B6C05A6B7F0000702AE25A6B7F0000D84DC14BFD7F000030489E5A6B7F0000E84EC14BFD7F0000E05E9E5A6B7F00000991F0460000000001000000000000000800000000000000B065E05A6B7F000048B6C05A6B7F00000100000000000000284EC14BFD7F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + Stack: + Start of Memory Range: 0x00007FFD4BC15080 + Content: 30044000000000000000000000000000FFFFFFFF03000000B850C14BFD7F0000670440000000000000000000000000000000000001000000D850C14BFD7F0000970440000000000000000000000000000000000000000000000000000000000001000000000000009F67C14BFD7F00000000000000000000BA67C14BFD7F0000 + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000400000 + Size of Image: 0x00001000 + Module Name: '/tmp/unwind-via-stack-cfi' + CodeView Record: 4C4570426CCF3F60FFA7CC4B86AE8FF44DB2576A68983611 + - Type: MemoryList + Memory Ranges: + - Start of Memory Range: 0x00007FFD4BC15080 + Content: 30044000000000000000000000000000FFFFFFFF03000000B850C14BFD7F0000670440000000000000000000000000000000000001000000D850C14BFD7F0000970440000000000000000000000000000000000000000000000000000000000001000000000000009F67C14BFD7F00000000000000000000BA67C14BFD7F0000 + - Type: SystemInfo + Processor Arch: AMD64 + Processor Level: 6 + Processor Revision: 15876 + Number of Processors: 40 + Platform ID: Linux + CSD Version: 'Linux 3.13.0-91-generic' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 + - Type: LinuxProcStatus + Text: | + Name: unwind-via-stack-cfi + State: t (tracing stop) + Tgid: 29939 + Ngid: 0 + Pid: 29939 + PPid: 29370 + TracerPid: 29940 + Uid: 1001 1001 1001 1001 + Gid: 1001 1001 1001 1001 + +... diff --git a/lldb/lit/SymbolFile/Breakpad/stack-cfi-parsing.test b/lldb/lit/SymbolFile/Breakpad/stack-cfi-parsing.test index c8d9694172c75..ffb64602c15e5 100644 --- a/lldb/lit/SymbolFile/Breakpad/stack-cfi-parsing.test +++ b/lldb/lit/SymbolFile/Breakpad/stack-cfi-parsing.test @@ -4,6 +4,8 @@ image show-unwind -n func0 # CHECK-LABEL: image show-unwind -n func0 +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' # CHECK: Symbol file UnwindPlan: # CHECK-NEXT: This UnwindPlan originally sourced from breakpad STACK CFI # CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. @@ -42,6 +44,8 @@ image show-unwind -n func7 # Finally, try an unwind plan with just a single row image show-unwind -n func9 # CHECK-LABEL: image show-unwind -n func9 +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' # CHECK: Symbol file UnwindPlan: # CHECK: Address range of this UnwindPlan: [stack-cfi-parsing.out..module_image + 9-0x000000000000000a) # CHECK: row[0]: 0: CFA=DW_OP_breg6 +0 => rip=DW_OP_breg0 +0 diff --git a/lldb/lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test b/lldb/lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test new file mode 100644 index 0000000000000..9a6c2166c1300 --- /dev/null +++ b/lldb/lit/SymbolFile/Breakpad/unwind-via-stack-cfi.test @@ -0,0 +1,20 @@ +# RUN: yaml2obj %S/Inputs/unwind-via-stack-cfi.yaml > %t +# RUN: %lldb -c %t -o "target symbols add %S/Inputs/unwind-via-stack-cfi.syms" \ +# RUN: -s %s -b | FileCheck %s + +image show-unwind -n bar +# CHECK-LABEL: image show-unwind -n bar +# CHECK: Asynchronous (not restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Synchronous (restricted to call-sites) UnwindPlan is 'breakpad STACK CFI' +# CHECK: Symbol file UnwindPlan: +# CHECK-NEXT: This UnwindPlan originally sourced from breakpad STACK CFI +# CHECK-NEXT: This UnwindPlan is sourced from the compiler: yes. +# CHECK-NEXT: This UnwindPlan is valid at all instruction locations: no. +# CHECK-NEXT: Address range of this UnwindPlan: [unwind-via-stack-cfi..module_image + 1056-0x0000000000000449) +# CHECK-NEXT: row[0]: 0: CFA=DW_OP_breg6 +0, DW_OP_deref => rbp=DW_OP_pick 0x00, DW_OP_deref rsp=DW_OP_pick 0x00, DW_OP_consts +16, DW_OP_plus rip=DW_OP_pick 0x00, DW_OP_consts +8, DW_OP_plus , DW_OP_deref + +thread backtrace +# CHECK-LABEL: thread backtrace +# CHECK: frame #0: 0x0000000000400430 unwind-via-stack-cfi`bar + 16 +# CHECK: frame #1: 0x0000000000400497 unwind-via-stack-cfi`_start + 23 +# CHECK-NOT: frame diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index c1f5ff0d283ca..764461ee92b84 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -3521,7 +3521,7 @@ class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed { non_callsite_unwind_plan->GetSourceName().AsCString()); } UnwindPlanSP callsite_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(*target); + func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread); if (callsite_unwind_plan) { result.GetOutputStream().Printf( "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 4ec8bba098148..76646d8897d19 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -244,8 +244,8 @@ void RegisterContextLLDB::InitializeZerothFrame() { } if (func_unwinders_sp.get() != nullptr) - call_site_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_thread); if (call_site_unwind_plan.get() != nullptr) { m_fallback_unwind_plan_sp = call_site_unwind_plan; @@ -873,7 +873,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // location what helps in the most common cases when the instruction // emulation fails. UnwindPlanSP call_site_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), + m_thread); if (call_site_unwind_plan && call_site_unwind_plan.get() != unwind_plan_sp.get() && call_site_unwind_plan->GetSourceName() != @@ -909,8 +910,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // Typically this is unwind info from an eh_frame section intended for // exception handling; only valid at call sites if (process) { - unwind_plan_sp = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite( + process->GetTarget(), m_thread); } int valid_offset = -1; if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset)) { @@ -940,7 +941,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() { // code it is often written in a way that it valid at all location what // helps in the most common cases when the instruction emulation fails. UnwindPlanSP call_site_unwind_plan = - func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget()); + func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), + m_thread); if (call_site_unwind_plan && call_site_unwind_plan.get() != unwind_plan_sp.get() && call_site_unwind_plan->GetSourceName() != diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp index bbdb5e1bbf79c..33b2e29598985 100644 --- a/lldb/source/Symbol/FuncUnwinders.cpp +++ b/lldb/source/Symbol/FuncUnwinders.cpp @@ -54,9 +54,12 @@ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) FuncUnwinders::~FuncUnwinders() {} -UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target) { +UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, + Thread &thread) { std::lock_guard guard(m_mutex); + if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) + return plan_sp; if (UnwindPlanSP plan_sp = GetEHFrameUnwindPlan(target)) return plan_sp; if (UnwindPlanSP plan_sp = GetDebugFrameUnwindPlan(target)) @@ -357,6 +360,8 @@ UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, return eh_frame_sp; } + if (UnwindPlanSP plan_sp = GetSymbolFileUnwindPlan(thread)) + return plan_sp; if (UnwindPlanSP plan_sp = GetEHFrameAugmentedUnwindPlan(target, thread)) return plan_sp; if (UnwindPlanSP plan_sp = GetDebugFrameAugmentedUnwindPlan(target, thread)) From 980f7605156e76fe2310fccca1581e5860c1512e Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 09:56:23 +0000 Subject: [PATCH 0153/1176] [AArch64][SVE2] Asm: add PMULLB/PMULLT instructions Summary: This patch adds support for the polynomial multiplication instructions PMULLB/PMULLT. The 64-bit source and 128-bit destination element variants are enabled with crypto extensions (+sve2-aes), similar to the NEON PMULL2 instruction. All other variants are enabled with +sve2. The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D62145 llvm-svn: 361619 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 12 +++++ llvm/lib/Target/AArch64/SVEInstrFormats.td | 5 +++ .../MC/AArch64/SVE2/pmullb-128-diagnostics.s | 25 +++++++++++ llvm/test/MC/AArch64/SVE2/pmullb-128.s | 15 +++++++ .../test/MC/AArch64/SVE2/pmullb-diagnostics.s | 45 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/pmullb.s | 21 +++++++++ .../MC/AArch64/SVE2/pmullt-128-diagnostics.s | 25 +++++++++++ llvm/test/MC/AArch64/SVE2/pmullt-128.s | 15 +++++++ .../test/MC/AArch64/SVE2/pmullt-diagnostics.s | 45 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/pmullt.s | 21 +++++++++ 10 files changed, 229 insertions(+) create mode 100644 llvm/test/MC/AArch64/SVE2/pmullb-128-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullb-128.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullb.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullt-128-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullt-128.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/pmullt.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index dd14e4ba815e4..18f874fccb66c 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1195,6 +1195,8 @@ let Predicates = [HasSVE2] in { defm SMULLT_ZZZ : sve2_wide_int_arith_long<0b11101, "smullt">; defm UMULLB_ZZZ : sve2_wide_int_arith_long<0b11110, "umullb">; defm UMULLT_ZZZ : sve2_wide_int_arith_long<0b11111, "umullt">; + defm PMULLB_ZZZ : sve2_pmul_long<0b0, "pmullb">; + defm PMULLT_ZZZ : sve2_pmul_long<0b1, "pmullt">; // Predicated shifts defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; @@ -1203,3 +1205,13 @@ let Predicates = [HasSVE2] in { defm URSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1101, "urshr">; defm SQSHLU_ZPmI : sve_int_bin_pred_shift_imm_left< 0b1111, "sqshlu">; } + +let Predicates = [HasSVE2AES] in { + // PMULLB and PMULLT instructions which operate with 64-bit source and + // 128-bit destination elements are enabled with crypto extensions, similar + // to NEON PMULL2 instruction. + def PMULLB_ZZZ_Q : sve2_wide_int_arith<0b00, 0b11010, "pmullb", + ZPR128, ZPR64, ZPR64>; + def PMULLT_ZZZ_Q : sve2_wide_int_arith<0b00, 0b11011, "pmullt", + ZPR128, ZPR64, ZPR64>; +} diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index b741f09886b55..333fa72500cf4 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -2186,6 +2186,11 @@ multiclass sve2_wide_int_arith_wide opc, string asm> { def _D : sve2_wide_int_arith<0b11, { 0b10, opc }, asm, ZPR64, ZPR64, ZPR32>; } +multiclass sve2_pmul_long opc, string asm> { + def _H : sve2_wide_int_arith<0b01, {0b1101, opc}, asm, ZPR16, ZPR8, ZPR8>; + def _D : sve2_wide_int_arith<0b11, {0b1101, opc}, asm, ZPR64, ZPR32, ZPR32>; +} + //===----------------------------------------------------------------------===// // SVE Integer Arithmetic - Unary Predicated Group //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SVE2/pmullb-128-diagnostics.s b/llvm/test/MC/AArch64/SVE2/pmullb-128-diagnostics.s new file mode 100644 index 0000000000000..001b40c69fc30 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullb-128-diagnostics.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-aes 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +pmullb z0.q, z0.q, z0.q +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullb z0.q, z0.q, z0.q +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +pmullb z0.q, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullb z0.q, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +pmullb z0.q, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullb z0.q, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/pmullb-128.s b/llvm/test/MC/AArch64/SVE2/pmullb-128.s new file mode 100644 index 0000000000000..021874e9e69a0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullb-128.s @@ -0,0 +1,15 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-aes < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-aes < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2-aes - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-aes < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +pmullb z29.q, z30.d, z31.d +// CHECK-INST: pmullb z29.q, z30.d, z31.d +// CHECK-ENCODING: [0xdd,0x6b,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2-aes +// CHECK-UNKNOWN: dd 6b 1f 45 diff --git a/llvm/test/MC/AArch64/SVE2/pmullb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/pmullb-diagnostics.s new file mode 100644 index 0000000000000..e4710e1f96f01 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullb-diagnostics.s @@ -0,0 +1,45 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +pmullb z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullb z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullb z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullb z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullb z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullb z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullb z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullb z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullb z0.q, z0.q, z0.q +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: pmullb z0.q, z0.q, z0.q +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +pmullb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +pmullb z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullb z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/pmullb.s b/llvm/test/MC/AArch64/SVE2/pmullb.s new file mode 100644 index 0000000000000..5a9989ab3837e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullb.s @@ -0,0 +1,21 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +pmullb z0.h, z1.b, z2.b +// CHECK-INST: pmullb z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x68,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 68 42 45 + +pmullb z31.d, z31.s, z31.s +// CHECK-INST: pmullb z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x6b,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 6b df 45 diff --git a/llvm/test/MC/AArch64/SVE2/pmullt-128-diagnostics.s b/llvm/test/MC/AArch64/SVE2/pmullt-128-diagnostics.s new file mode 100644 index 0000000000000..301824e868172 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullt-128-diagnostics.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-aes 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +pmullt z0.q, z0.q, z0.q +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullt z0.q, z0.q, z0.q +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +pmullt z0.q, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullt z0.q, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +pmullt z0.q, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullt z0.q, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/pmullt-128.s b/llvm/test/MC/AArch64/SVE2/pmullt-128.s new file mode 100644 index 0000000000000..5b454b01f33b0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullt-128.s @@ -0,0 +1,15 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-aes < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-aes < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2-aes - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-aes < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +pmullt z29.q, z30.d, z31.d +// CHECK-INST: pmullt z29.q, z30.d, z31.d +// CHECK-ENCODING: [0xdd,0x6f,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2-aes +// CHECK-UNKNOWN: dd 6f 1f 45 diff --git a/llvm/test/MC/AArch64/SVE2/pmullt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/pmullt-diagnostics.s new file mode 100644 index 0000000000000..f068bd3bac1a5 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullt-diagnostics.s @@ -0,0 +1,45 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +pmullt z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullt z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullt z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullt z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullt z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullt z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullt z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: pmullt z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pmullt z0.q, z0.q, z0.q +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: pmullt z0.q, z0.q, z0.q +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31.d, p0/z, z6.d +pmullt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z31, z6 +pmullt z0.d, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: pmullt z0.d, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/pmullt.s b/llvm/test/MC/AArch64/SVE2/pmullt.s new file mode 100644 index 0000000000000..9493e2a1a8248 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/pmullt.s @@ -0,0 +1,21 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +pmullt z0.h, z1.b, z2.b +// CHECK-INST: pmullt z0.h, z1.b, z2.b +// CHECK-ENCODING: [0x20,0x6c,0x42,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 6c 42 45 + +pmullt z31.d, z31.s, z31.s +// CHECK-INST: pmullt z31.d, z31.s, z31.s +// CHECK-ENCODING: [0xff,0x6f,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 6f df 45 From 95b8d9bbf852428fc738bb93c78ef7b00f39341f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Fri, 24 May 2019 10:03:11 +0000 Subject: [PATCH 0154/1176] [SelectionDAG] computeKnownBits - support constant pool values from target This patch adds the overridable TargetLowering::getTargetConstantFromLoad function which allows targets to return any constant value loaded by a LoadSDNode node - only X86 makes use of this so far but everything should be in place for other targets. computeKnownBits then uses this function to improve codegen, notably vector code after legalization. A future commit will do the same for ComputeNumSignBits but computeKnownBits sees the bigger benefit. This required a couple of fixes: * SimplifyDemandedBits must early-out for getTargetConstantFromLoad cases to prevent infinite loops of constant regeneration (similar to what we already do for BUILD_VECTOR). * Fix a DAGCombiner::visitTRUNCATE issue as we had trunc(shl(v8i32),v8i16) <-> shl(trunc(v8i16),v8i32) infinite loops after legalization on AVX512 targets. Differential Revision: https://reviews.llvm.org/D61887 llvm-svn: 361620 --- llvm/include/llvm/CodeGen/TargetLowering.h | 4 + llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2 +- .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 55 +- .../CodeGen/SelectionDAG/TargetLowering.cpp | 12 + llvm/lib/Target/X86/X86ISelLowering.cpp | 16 +- llvm/lib/Target/X86/X86ISelLowering.h | 2 + llvm/test/CodeGen/X86/avx512-vec-cmp.ll | 5 +- llvm/test/CodeGen/X86/bitreverse.ll | 18 +- llvm/test/CodeGen/X86/combine-bitreverse.ll | 18 +- llvm/test/CodeGen/X86/combine-shl.ll | 11 +- llvm/test/CodeGen/X86/movmsk-cmp.ll | 16 - llvm/test/CodeGen/X86/vector-bitreverse.ll | 553 +++----- llvm/test/CodeGen/X86/vector-pcmp.ll | 3 +- .../CodeGen/X86/vector-reduce-mul-widen.ll | 1147 +++++++---------- llvm/test/CodeGen/X86/vector-reduce-mul.ll | 1122 +++++++--------- .../CodeGen/X86/vector-shift-lshr-sub128.ll | 24 +- llvm/test/CodeGen/X86/vector-zext.ll | 2 - 17 files changed, 1193 insertions(+), 1817 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 7f4b2bad803de..b1a64744f0642 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3119,6 +3119,10 @@ class TargetLowering : public TargetLoweringBase { TargetLoweringOpt &TLO, unsigned Depth = 0) const; + /// This method returns the constant pool value that will be loaded by LD. + /// NOTE: You must check for implicit extensions of the constant by LD. + virtual const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const; + /// If \p SNaN is false, \returns true if \p Op is known to never be any /// NaN. If \p sNaN is true, returns if \p Op is known to never be a signaling /// NaN. diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index b5bb86580fb61..117654bc7a3f7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10110,7 +10110,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { // trunc (shl x, K) -> shl (trunc x), K => K < VT.getScalarSizeInBits() if (N0.getOpcode() == ISD::SHL && N0.hasOneUse() && - (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::SHL, VT)) && + (!LegalOperations || TLI.isOperationLegal(ISD::SHL, VT)) && TLI.isTypeDesirableForOp(ISD::SHL, VT)) { SDValue Amt = N0.getOperand(1); KnownBits Known = DAG.computeKnownBits(Amt); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 366b404b30446..553a46f6ec160 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2886,8 +2886,59 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, } case ISD::LOAD: { LoadSDNode *LD = cast(Op); - // If this is a ZEXTLoad and we are looking at the loaded value. - if (ISD::isZEXTLoad(Op.getNode()) && Op.getResNo() == 0) { + const Constant *Cst = TLI->getTargetConstantFromLoad(LD); + if (ISD::isNON_EXTLoad(LD) && Cst) { + // Determine any common known bits from the loaded constant pool value. + Type *CstTy = Cst->getType(); + if ((NumElts * BitWidth) == CstTy->getPrimitiveSizeInBits()) { + // If its a vector splat, then we can (quickly) reuse the scalar path. + // NOTE: We assume all elements match and none are UNDEF. + if (CstTy->isVectorTy()) { + if (const Constant *Splat = Cst->getSplatValue()) { + Cst = Splat; + CstTy = Cst->getType(); + } + } + // TODO - do we need to handle different bitwidths? + if (CstTy->isVectorTy() && BitWidth == CstTy->getScalarSizeInBits()) { + // Iterate across all vector elements finding common known bits. + Known.One.setAllBits(); + Known.Zero.setAllBits(); + for (unsigned i = 0; i != NumElts; ++i) { + if (!DemandedElts[i]) + continue; + if (Constant *Elt = Cst->getAggregateElement(i)) { + if (auto *CInt = dyn_cast(Elt)) { + const APInt &Value = CInt->getValue(); + Known.One &= Value; + Known.Zero &= ~Value; + continue; + } + if (auto *CFP = dyn_cast(Elt)) { + APInt Value = CFP->getValueAPF().bitcastToAPInt(); + Known.One &= Value; + Known.Zero &= ~Value; + continue; + } + } + Known.One.clearAllBits(); + Known.Zero.clearAllBits(); + break; + } + } else if (BitWidth == CstTy->getPrimitiveSizeInBits()) { + if (auto *CInt = dyn_cast(Cst)) { + const APInt &Value = CInt->getValue(); + Known.One = Value; + Known.Zero = ~Value; + } else if (auto *CFP = dyn_cast(Cst)) { + APInt Value = CFP->getValueAPF().bitcastToAPInt(); + Known.One = Value; + Known.Zero = ~Value; + } + } + } + } else if (ISD::isZEXTLoad(Op.getNode()) && Op.getResNo() == 0) { + // If this is a ZEXTLoad and we are looking at the loaded value. EVT VT = LD->getMemoryVT(); unsigned MemBits = VT.getScalarSizeInBits(); Known.Zero.setBitsFrom(MemBits); diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 4d950984b29ce..d636e613363e4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -659,6 +659,14 @@ bool TargetLowering::SimplifyDemandedBits( Known.Zero &= Known2.Zero; } return false; // Don't fall through, will infinitely loop. + case ISD::LOAD: { + LoadSDNode *LD = cast(Op); + if (getTargetConstantFromLoad(LD)) { + Known = TLO.DAG.computeKnownBits(Op, DemandedElts, Depth); + return false; // Don't fall through, will infinitely loop. + } + break; + } case ISD::INSERT_VECTOR_ELT: { SDValue Vec = Op.getOperand(0); SDValue Scl = Op.getOperand(1); @@ -2314,6 +2322,10 @@ bool TargetLowering::SimplifyDemandedBitsForTargetNode( return false; } +const Constant *TargetLowering::getTargetConstantFromLoad(LoadSDNode*) const { + return nullptr; +} + bool TargetLowering::isKnownNeverNaNForTargetNode(SDValue Op, const SelectionDAG &DAG, bool SNaN, diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index b5940b1d780eb..246e494de782c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -5731,10 +5731,7 @@ static SDValue getShuffleVectorZeroOrUndef(SDValue V2, int Idx, return DAG.getVectorShuffle(VT, SDLoc(V2), V1, V2, MaskVec); } -static const Constant *getTargetConstantFromNode(SDValue Op) { - Op = peekThroughBitcasts(Op); - - auto *Load = dyn_cast(Op); +static const Constant *getTargetConstantFromNode(LoadSDNode *Load) { if (!Load) return nullptr; @@ -5750,6 +5747,17 @@ static const Constant *getTargetConstantFromNode(SDValue Op) { return CNode->getConstVal(); } +static const Constant *getTargetConstantFromNode(SDValue Op) { + Op = peekThroughBitcasts(Op); + return getTargetConstantFromNode(dyn_cast(Op)); +} + +const Constant * +X86TargetLowering::getTargetConstantFromLoad(LoadSDNode *LD) const { + assert(LD && "Unexpected null LoadSDNode"); + return getTargetConstantFromNode(LD); +} + // Extract raw constant bits from constant pools. static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits, APInt &UndefElts, diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 70bcbe3c8a5de..be3d29019db7c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -908,6 +908,8 @@ namespace llvm { TargetLoweringOpt &TLO, unsigned Depth) const override; + const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const override; + SDValue unwrapAddress(SDValue N) const override; SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const; diff --git a/llvm/test/CodeGen/X86/avx512-vec-cmp.ll b/llvm/test/CodeGen/X86/avx512-vec-cmp.ll index 2c7d63d5ab959..a823e1b275b39 100644 --- a/llvm/test/CodeGen/X86/avx512-vec-cmp.ll +++ b/llvm/test/CodeGen/X86/avx512-vec-cmp.ll @@ -940,9 +940,8 @@ define <2 x i64> @test46(<2 x float> %x, <2 x float> %y) #0 { ; AVX512-LABEL: test46: ; AVX512: ## %bb.0: ; AVX512-NEXT: vcmpeqps %xmm1, %xmm0, %xmm0 ## encoding: [0xc5,0xf8,0xc2,0xc1,0x00] -; AVX512-NEXT: vxorps %xmm1, %xmm1, %xmm1 ## encoding: [0xc5,0xf0,0x57,0xc9] -; AVX512-NEXT: vunpcklps %xmm1, %xmm0, %xmm0 ## encoding: [0xc5,0xf8,0x14,0xc1] -; AVX512-NEXT: ## xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; AVX512-NEXT: vpermilps $212, %xmm0, %xmm0 ## encoding: [0xc4,0xe3,0x79,0x04,0xc0,0xd4] +; AVX512-NEXT: ## xmm0 = xmm0[0,1,1,3] ; AVX512-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0 ## encoding: [0xc5,0xf8,0x54,0x05,A,A,A,A] ; AVX512-NEXT: ## fixup A - offset: 4, value: LCPI47_0-4, kind: reloc_riprel_4byte ; AVX512-NEXT: retq ## encoding: [0xc3] diff --git a/llvm/test/CodeGen/X86/bitreverse.ll b/llvm/test/CodeGen/X86/bitreverse.ll index 5da95c574eb43..23056f9e802a5 100644 --- a/llvm/test/CodeGen/X86/bitreverse.ll +++ b/llvm/test/CodeGen/X86/bitreverse.ll @@ -61,31 +61,25 @@ define <2 x i16> @test_bitreverse_v2i16(<2 x i16> %a) nounwind { ; X64-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; X64-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] ; X64-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] -; X64-NEXT: pshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,7,6,5,4] -; X64-NEXT: packuswb %xmm2, %xmm1 -; X64-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] -; X64-NEXT: movdqa %xmm1, %xmm2 -; X64-NEXT: pand %xmm0, %xmm2 -; X64-NEXT: psllw $4, %xmm2 +; X64-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] +; X64-NEXT: packuswb %xmm2, %xmm0 +; X64-NEXT: movdqa %xmm0, %xmm1 +; X64-NEXT: psllw $4, %xmm1 ; X64-NEXT: pand {{.*}}(%rip), %xmm1 -; X64-NEXT: psrlw $4, %xmm1 -; X64-NEXT: pand %xmm0, %xmm1 -; X64-NEXT: pandn %xmm2, %xmm0 +; X64-NEXT: psrlw $4, %xmm0 +; X64-NEXT: pand {{.*}}(%rip), %xmm0 ; X64-NEXT: por %xmm1, %xmm0 ; X64-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; X64-NEXT: pand %xmm0, %xmm1 ; X64-NEXT: psllw $2, %xmm1 -; X64-NEXT: pand {{.*}}(%rip), %xmm1 ; X64-NEXT: pand {{.*}}(%rip), %xmm0 ; X64-NEXT: psrlw $2, %xmm0 -; X64-NEXT: pand {{.*}}(%rip), %xmm0 ; X64-NEXT: por %xmm1, %xmm0 ; X64-NEXT: movdqa {{.*#+}} xmm1 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; X64-NEXT: pand %xmm0, %xmm1 ; X64-NEXT: paddb %xmm1, %xmm1 ; X64-NEXT: pand {{.*}}(%rip), %xmm0 ; X64-NEXT: psrlw $1, %xmm0 -; X64-NEXT: pand {{.*}}(%rip), %xmm0 ; X64-NEXT: por %xmm1, %xmm0 ; X64-NEXT: psrlq $48, %xmm0 ; X64-NEXT: retq diff --git a/llvm/test/CodeGen/X86/combine-bitreverse.ll b/llvm/test/CodeGen/X86/combine-bitreverse.ll index 29a0cdadfd41a..8d268ddd75ee3 100644 --- a/llvm/test/CodeGen/X86/combine-bitreverse.ll +++ b/llvm/test/CodeGen/X86/combine-bitreverse.ll @@ -47,31 +47,25 @@ define <4 x i32> @test_demandedbits_bitreverse(<4 x i32> %a0) nounwind { ; X86-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,7,6,5,4] ; X86-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; X86-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] -; X86-NEXT: pshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,7,6,5,4] -; X86-NEXT: packuswb %xmm2, %xmm1 -; X86-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] -; X86-NEXT: movdqa %xmm1, %xmm2 -; X86-NEXT: pand %xmm0, %xmm2 -; X86-NEXT: psllw $4, %xmm2 +; X86-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] +; X86-NEXT: packuswb %xmm2, %xmm0 +; X86-NEXT: movdqa %xmm0, %xmm1 +; X86-NEXT: psllw $4, %xmm1 ; X86-NEXT: pand {{\.LCPI.*}}, %xmm1 -; X86-NEXT: psrlw $4, %xmm1 -; X86-NEXT: pand %xmm0, %xmm1 -; X86-NEXT: pandn %xmm2, %xmm0 +; X86-NEXT: psrlw $4, %xmm0 +; X86-NEXT: pand {{\.LCPI.*}}, %xmm0 ; X86-NEXT: por %xmm1, %xmm0 ; X86-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; X86-NEXT: pand %xmm0, %xmm1 ; X86-NEXT: psllw $2, %xmm1 -; X86-NEXT: pand {{\.LCPI.*}}, %xmm1 ; X86-NEXT: pand {{\.LCPI.*}}, %xmm0 ; X86-NEXT: psrlw $2, %xmm0 -; X86-NEXT: pand {{\.LCPI.*}}, %xmm0 ; X86-NEXT: por %xmm1, %xmm0 ; X86-NEXT: movdqa {{.*#+}} xmm1 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; X86-NEXT: pand %xmm0, %xmm1 ; X86-NEXT: paddb %xmm1, %xmm1 ; X86-NEXT: pand {{\.LCPI.*}}, %xmm0 ; X86-NEXT: psrlw $1, %xmm0 -; X86-NEXT: pand {{\.LCPI.*}}, %xmm0 ; X86-NEXT: por %xmm1, %xmm0 ; X86-NEXT: pand {{\.LCPI.*}}, %xmm0 ; X86-NEXT: retl diff --git a/llvm/test/CodeGen/X86/combine-shl.ll b/llvm/test/CodeGen/X86/combine-shl.ll index f9b1b93022442..3e54d29cef95d 100644 --- a/llvm/test/CodeGen/X86/combine-shl.ll +++ b/llvm/test/CodeGen/X86/combine-shl.ll @@ -268,16 +268,11 @@ define <8 x i32> @combine_vec_shl_ext_shl1(<8 x i16> %x) { ; SSE2-LABEL: combine_vec_shl_ext_shl1: ; SSE2: # %bb.0: ; SSE2-NEXT: pmullw {{.*}}(%rip), %xmm0 -; SSE2-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3] -; SSE2-NEXT: psrad $16, %xmm1 -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: pslld $29, %xmm2 -; SSE2-NEXT: pslld $28, %xmm1 -; SSE2-NEXT: movsd {{.*#+}} xmm1 = xmm2[0],xmm1[1] ; SSE2-NEXT: pslld $30, %xmm0 -; SSE2-NEXT: xorpd %xmm2, %xmm2 -; SSE2-NEXT: movsd {{.*#+}} xmm0 = xmm2[0],xmm0[1] +; SSE2-NEXT: xorpd %xmm1, %xmm1 +; SSE2-NEXT: movsd {{.*#+}} xmm0 = xmm1[0],xmm0[1] +; SSE2-NEXT: movsd {{.*#+}} xmm1 = xmm1[0,1] ; SSE2-NEXT: retq ; ; SSE41-LABEL: combine_vec_shl_ext_shl1: diff --git a/llvm/test/CodeGen/X86/movmsk-cmp.ll b/llvm/test/CodeGen/X86/movmsk-cmp.ll index 6f62787c950ac..6f7ec7d3a207f 100644 --- a/llvm/test/CodeGen/X86/movmsk-cmp.ll +++ b/llvm/test/CodeGen/X86/movmsk-cmp.ll @@ -1309,7 +1309,6 @@ define i1 @allones_v32i8_and1(<32 x i8> %arg) { ; AVX1-NEXT: vpmovmskb %xmm1, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0 -; AVX1-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %ecx ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx @@ -1368,7 +1367,6 @@ define i1 @allzeros_v32i8_and1(<32 x i8> %arg) { ; AVX1-NEXT: vpmovmskb %xmm1, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0 -; AVX1-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %ecx ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx @@ -1432,8 +1430,6 @@ define i1 @allones_v64i8_and1(<64 x i8> %arg) { ; AVX1-LABEL: allones_v64i8_and1: ; AVX1: # %bb.0: ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm2 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm3 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128] -; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX1-NEXT: vpmovmskb %xmm2, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0 @@ -1441,7 +1437,6 @@ define i1 @allones_v64i8_and1(<64 x i8> %arg) { ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx ; AVX1-NEXT: vpsllw $7, %xmm1, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %eax ; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0 @@ -1518,8 +1513,6 @@ define i1 @allzeros_v64i8_and1(<64 x i8> %arg) { ; AVX1-LABEL: allzeros_v64i8_and1: ; AVX1: # %bb.0: ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm2 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm3 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128] -; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX1-NEXT: vpmovmskb %xmm2, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0 @@ -1527,7 +1520,6 @@ define i1 @allzeros_v64i8_and1(<64 x i8> %arg) { ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx ; AVX1-NEXT: vpsllw $7, %xmm1, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %eax ; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 ; AVX1-NEXT: vpsllw $7, %xmm0, %xmm0 @@ -2728,7 +2720,6 @@ define i1 @allones_v32i8_and4(<32 x i8> %arg) { ; AVX1-NEXT: vpmovmskb %xmm1, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm0 -; AVX1-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %ecx ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx @@ -2787,7 +2778,6 @@ define i1 @allzeros_v32i8_and4(<32 x i8> %arg) { ; AVX1-NEXT: vpmovmskb %xmm1, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm0 -; AVX1-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %ecx ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx @@ -2851,8 +2841,6 @@ define i1 @allones_v64i8_and4(<64 x i8> %arg) { ; AVX1-LABEL: allones_v64i8_and4: ; AVX1: # %bb.0: ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm2 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm3 = [224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224] -; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX1-NEXT: vpmovmskb %xmm2, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm0 @@ -2860,7 +2848,6 @@ define i1 @allones_v64i8_and4(<64 x i8> %arg) { ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx ; AVX1-NEXT: vpsllw $5, %xmm1, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %eax ; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm0 @@ -2937,8 +2924,6 @@ define i1 @allzeros_v64i8_and4(<64 x i8> %arg) { ; AVX1-LABEL: allzeros_v64i8_and4: ; AVX1: # %bb.0: ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm2 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm3 = [224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224] -; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX1-NEXT: vpmovmskb %xmm2, %eax ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm0 @@ -2946,7 +2931,6 @@ define i1 @allzeros_v64i8_and4(<64 x i8> %arg) { ; AVX1-NEXT: shll $16, %ecx ; AVX1-NEXT: orl %eax, %ecx ; AVX1-NEXT: vpsllw $5, %xmm1, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX1-NEXT: vpmovmskb %xmm0, %eax ; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 ; AVX1-NEXT: vpsllw $5, %xmm0, %xmm0 diff --git a/llvm/test/CodeGen/X86/vector-bitreverse.ll b/llvm/test/CodeGen/X86/vector-bitreverse.ll index a564bbc1743cc..bfbfda08cd0eb 100644 --- a/llvm/test/CodeGen/X86/vector-bitreverse.ll +++ b/llvm/test/CodeGen/X86/vector-bitreverse.ll @@ -237,29 +237,22 @@ define <16 x i8> @test_bitreverse_v16i8(<16 x i8> %a) nounwind { ; SSE2-LABEL: test_bitreverse_v16i8: ; SSE2: # %bb.0: ; SSE2-NEXT: movdqa %xmm0, %xmm1 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: psllw $4, %xmm2 +; SSE2-NEXT: psllw $4, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 -; SSE2-NEXT: psrlw $4, %xmm1 -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: pandn %xmm2, %xmm0 +; SSE2-NEXT: psrlw $4, %xmm0 +; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: psllw $2, %xmm1 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: paddb %xmm1, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $1, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: retq ; @@ -309,31 +302,25 @@ define <8 x i16> @test_bitreverse_v8i16(<8 x i16> %a) nounwind { ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,4,7,6] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[1,0,3,2,4,5,6,7] -; SSE2-NEXT: pshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,5,4,7,6] -; SSE2-NEXT: packuswb %xmm2, %xmm1 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: psllw $4, %xmm2 +; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,5,4,7,6] +; SSE2-NEXT: packuswb %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psllw $4, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 -; SSE2-NEXT: psrlw $4, %xmm1 -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: pandn %xmm2, %xmm0 +; SSE2-NEXT: psrlw $4, %xmm0 +; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: psllw $2, %xmm1 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: paddb %xmm1, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $1, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: retq ; @@ -385,31 +372,25 @@ define <4 x i32> @test_bitreverse_v4i32(<4 x i32> %a) nounwind { ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,7,6,5,4] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] -; SSE2-NEXT: pshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,7,6,5,4] -; SSE2-NEXT: packuswb %xmm2, %xmm1 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: psllw $4, %xmm2 +; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] +; SSE2-NEXT: packuswb %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psllw $4, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 -; SSE2-NEXT: psrlw $4, %xmm1 -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: pandn %xmm2, %xmm0 +; SSE2-NEXT: psrlw $4, %xmm0 +; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: psllw $2, %xmm1 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: paddb %xmm1, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $1, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: retq ; @@ -463,31 +444,25 @@ define <2 x i64> @test_bitreverse_v2i64(<2 x i64> %a) nounwind { ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] -; SSE2-NEXT: pshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,7,6,5,4] -; SSE2-NEXT: packuswb %xmm2, %xmm1 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: psllw $4, %xmm2 +; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] +; SSE2-NEXT: packuswb %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psllw $4, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 -; SSE2-NEXT: psrlw $4, %xmm1 -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: pandn %xmm2, %xmm0 +; SSE2-NEXT: psrlw $4, %xmm0 +; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: psllw $2, %xmm1 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: pand %xmm0, %xmm1 ; SSE2-NEXT: paddb %xmm1, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: psrlw $1, %xmm0 -; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: retq ; @@ -533,14 +508,11 @@ define <32 x i8> @test_bitreverse_v32i8(<32 x i8> %a) nounwind { ; SSE2-LABEL: test_bitreverse_v32i8: ; SSE2: # %bb.0: ; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $4, %xmm3 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pandn %xmm3, %xmm4 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm1, %xmm0 ; SSE2-NEXT: por %xmm4, %xmm0 @@ -548,44 +520,33 @@ define <32 x i8> @test_bitreverse_v32i8(<32 x i8> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm4 ; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm5, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm4, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm4 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] -; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: pand %xmm4, %xmm5 -; SSE2-NEXT: psrlw $1, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm6 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm6, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] +; SSE2-NEXT: movdqa {{.*#+}} xmm4 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] +; SSE2-NEXT: movdqa %xmm0, %xmm6 +; SSE2-NEXT: pand %xmm4, %xmm6 +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] ; SSE2-NEXT: pand %xmm7, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 -; SSE2-NEXT: por %xmm5, %xmm0 -; SSE2-NEXT: movdqa %xmm2, %xmm5 -; SSE2-NEXT: pand %xmm1, %xmm5 -; SSE2-NEXT: psllw $4, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: por %xmm6, %xmm0 +; SSE2-NEXT: movdqa %xmm2, %xmm6 +; SSE2-NEXT: psllw $4, %xmm6 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm1, %xmm2 -; SSE2-NEXT: pandn %xmm5, %xmm1 +; SSE2-NEXT: pandn %xmm6, %xmm1 ; SSE2-NEXT: por %xmm2, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $2, %xmm3 -; SSE2-NEXT: pand %xmm9, %xmm3 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm5, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm3, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm6, %xmm4 +; SSE2-NEXT: paddb %xmm4, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: retq ; @@ -695,14 +656,11 @@ define <16 x i16> @test_bitreverse_v16i16(<16 x i16> %a) nounwind { ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,5,4,7,6] ; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $4, %xmm3 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm1, %xmm5 ; SSE2-NEXT: pandn %xmm3, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm1, %xmm0 ; SSE2-NEXT: por %xmm5, %xmm0 @@ -710,23 +668,17 @@ define <16 x i16> @test_bitreverse_v16i16(<16 x i16> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm5 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm5, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm5, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] ; SSE2-NEXT: pand %xmm7, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 ; SSE2-NEXT: movdqa %xmm2, %xmm6 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] @@ -737,25 +689,20 @@ define <16 x i16> @test_bitreverse_v16i16(<16 x i16> %a) nounwind { ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,4,7,6] ; SSE2-NEXT: packuswb %xmm6, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm1, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm1, %xmm2 ; SSE2-NEXT: pandn %xmm4, %xmm1 ; SSE2-NEXT: por %xmm2, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $2, %xmm3 -; SSE2-NEXT: pand %xmm9, %xmm3 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm3, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm5 -; SSE2-NEXT: psrlw $1, %xmm5 -; SSE2-NEXT: pand %xmm12, %xmm5 +; SSE2-NEXT: paddb %xmm5, %xmm5 ; SSE2-NEXT: pand %xmm7, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm5, %xmm1 ; SSE2-NEXT: retq ; @@ -873,14 +820,11 @@ define <8 x i32> @test_bitreverse_v8i32(<8 x i32> %a) nounwind { ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $4, %xmm3 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm1, %xmm5 ; SSE2-NEXT: pandn %xmm3, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm1, %xmm0 ; SSE2-NEXT: por %xmm5, %xmm0 @@ -888,23 +832,17 @@ define <8 x i32> @test_bitreverse_v8i32(<8 x i32> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm5 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm5, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm5, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] ; SSE2-NEXT: pand %xmm7, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 ; SSE2-NEXT: movdqa %xmm2, %xmm6 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] @@ -915,25 +853,20 @@ define <8 x i32> @test_bitreverse_v8i32(<8 x i32> %a) nounwind { ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm6, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm1, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm1, %xmm2 ; SSE2-NEXT: pandn %xmm4, %xmm1 ; SSE2-NEXT: por %xmm2, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $2, %xmm3 -; SSE2-NEXT: pand %xmm9, %xmm3 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm3, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm5 -; SSE2-NEXT: psrlw $1, %xmm5 -; SSE2-NEXT: pand %xmm12, %xmm5 +; SSE2-NEXT: paddb %xmm5, %xmm5 ; SSE2-NEXT: pand %xmm7, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm5, %xmm1 ; SSE2-NEXT: retq ; @@ -1053,14 +986,11 @@ define <4 x i64> @test_bitreverse_v4i64(<4 x i64> %a) nounwind { ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $4, %xmm3 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm1, %xmm5 ; SSE2-NEXT: pandn %xmm3, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm1, %xmm0 ; SSE2-NEXT: por %xmm5, %xmm0 @@ -1068,23 +998,17 @@ define <4 x i64> @test_bitreverse_v4i64(<4 x i64> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm5 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm5, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm5, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] ; SSE2-NEXT: pand %xmm7, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 ; SSE2-NEXT: movdqa %xmm2, %xmm6 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] @@ -1097,25 +1021,20 @@ define <4 x i64> @test_bitreverse_v4i64(<4 x i64> %a) nounwind { ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm6, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm1, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm1, %xmm2 ; SSE2-NEXT: pandn %xmm4, %xmm1 ; SSE2-NEXT: por %xmm2, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm3 ; SSE2-NEXT: psllw $2, %xmm3 -; SSE2-NEXT: pand %xmm9, %xmm3 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm3, %xmm1 ; SSE2-NEXT: pand %xmm1, %xmm5 -; SSE2-NEXT: psrlw $1, %xmm5 -; SSE2-NEXT: pand %xmm12, %xmm5 +; SSE2-NEXT: paddb %xmm5, %xmm5 ; SSE2-NEXT: pand %xmm7, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm5, %xmm1 ; SSE2-NEXT: retq ; @@ -1223,15 +1142,12 @@ define <4 x i64> @test_bitreverse_v4i64(<4 x i64> %a) nounwind { define <64 x i8> @test_bitreverse_v64i8(<64 x i8> %a) nounwind { ; SSE2-LABEL: test_bitreverse_v64i8: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm3, %xmm14 -; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; SSE2-NEXT: movdqa %xmm3, %xmm10 ; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $4, %xmm5 +; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm5, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm9, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm3, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 @@ -1239,92 +1155,71 @@ define <64 x i8> @test_bitreverse_v64i8(<64 x i8> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm5, %xmm6 ; SSE2-NEXT: psllw $2, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm8, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm6 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm6 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm7 ; SSE2-NEXT: pand %xmm6, %xmm7 -; SSE2-NEXT: psrlw $1, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm13 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] -; SSE2-NEXT: pand %xmm13, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: paddb %xmm7, %xmm7 +; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: pand %xmm9, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 ; SSE2-NEXT: movdqa %xmm1, %xmm7 -; SSE2-NEXT: pand %xmm3, %xmm7 ; SSE2-NEXT: psllw $4, %xmm7 ; SSE2-NEXT: movdqa %xmm3, %xmm4 ; SSE2-NEXT: pandn %xmm7, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm1 ; SSE2-NEXT: psrlw $4, %xmm1 ; SSE2-NEXT: pand %xmm3, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm6, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 ; SSE2-NEXT: movdqa %xmm3, %xmm7 ; SSE2-NEXT: pandn %xmm4, %xmm7 -; SSE2-NEXT: pand %xmm9, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm3, %xmm2 ; SSE2-NEXT: por %xmm7, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm2 +; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $2, %xmm2 -; SSE2-NEXT: pand %xmm11, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm6, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm2 -; SSE2-NEXT: paddb %xmm2, %xmm2 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 -; SSE2-NEXT: movdqa %xmm14, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 +; SSE2-NEXT: movdqa %xmm10, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm14 -; SSE2-NEXT: psrlw $4, %xmm14 -; SSE2-NEXT: pand %xmm3, %xmm14 +; SSE2-NEXT: psrlw $4, %xmm10 +; SSE2-NEXT: pand %xmm3, %xmm10 ; SSE2-NEXT: pandn %xmm4, %xmm3 -; SSE2-NEXT: por %xmm14, %xmm3 +; SSE2-NEXT: por %xmm10, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 -; SSE2-NEXT: pand %xmm10, %xmm3 +; SSE2-NEXT: pand %xmm8, %xmm3 ; SSE2-NEXT: psrlw $2, %xmm3 -; SSE2-NEXT: pand %xmm11, %xmm3 ; SSE2-NEXT: por %xmm5, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: pand %xmm13, %xmm3 -; SSE2-NEXT: paddb %xmm3, %xmm3 +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: pand %xmm9, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm3 ; SSE2-NEXT: por %xmm6, %xmm3 ; SSE2-NEXT: retq ; @@ -1490,24 +1385,21 @@ define <64 x i8> @test_bitreverse_v64i8(<64 x i8> %a) nounwind { define <32 x i16> @test_bitreverse_v32i16(<32 x i16> %a) nounwind { ; SSE2-LABEL: test_bitreverse_v32i16: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm3, %xmm15 -; SSE2-NEXT: pxor %xmm14, %xmm14 +; SSE2-NEXT: movdqa %xmm3, %xmm11 +; SSE2-NEXT: pxor %xmm10, %xmm10 ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm14[8],xmm3[9],xmm14[9],xmm3[10],xmm14[10],xmm3[11],xmm14[11],xmm3[12],xmm14[12],xmm3[13],xmm14[13],xmm3[14],xmm14[14],xmm3[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm10[8],xmm3[9],xmm10[9],xmm3[10],xmm10[10],xmm3[11],xmm10[11],xmm3[12],xmm10[12],xmm3[13],xmm10[13],xmm3[14],xmm10[14],xmm3[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,5,4,7,6] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm14[0],xmm0[1],xmm14[1],xmm0[2],xmm14[2],xmm0[3],xmm14[3],xmm0[4],xmm14[4],xmm0[5],xmm14[5],xmm0[6],xmm14[6],xmm0[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm10[0],xmm0[1],xmm10[1],xmm0[2],xmm10[2],xmm0[3],xmm10[3],xmm0[4],xmm10[4],xmm0[5],xmm10[5],xmm0[6],xmm10[6],xmm0[7],xmm10[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,5,4,7,6] ; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $4, %xmm5 +; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm3, %xmm7 ; SSE2-NEXT: pandn %xmm5, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm3, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 @@ -1515,116 +1407,95 @@ define <32 x i16> @test_bitreverse_v32i16(<32 x i16> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm7 ; SSE2-NEXT: pand %xmm5, %xmm7 ; SSE2-NEXT: psllw $2, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm7, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm13 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] -; SSE2-NEXT: pand %xmm13, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: pand %xmm9, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 ; SSE2-NEXT: movdqa %xmm1, %xmm6 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm14[8],xmm6[9],xmm14[9],xmm6[10],xmm14[10],xmm6[11],xmm14[11],xmm6[12],xmm14[12],xmm6[13],xmm14[13],xmm6[14],xmm14[14],xmm6[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm10[8],xmm6[9],xmm10[9],xmm6[10],xmm10[10],xmm6[11],xmm10[11],xmm6[12],xmm10[12],xmm6[13],xmm10[13],xmm6[14],xmm10[14],xmm6[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm6[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm6 = xmm6[0,1,2,3,5,4,7,6] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm14[0],xmm1[1],xmm14[1],xmm1[2],xmm14[2],xmm1[3],xmm14[3],xmm1[4],xmm14[4],xmm1[5],xmm14[5],xmm1[6],xmm14[6],xmm1[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm10[0],xmm1[1],xmm10[1],xmm1[2],xmm10[2],xmm1[3],xmm10[3],xmm1[4],xmm10[4],xmm1[5],xmm10[5],xmm1[6],xmm10[6],xmm1[7],xmm10[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,5,4,7,6] ; SSE2-NEXT: packuswb %xmm6, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm6 -; SSE2-NEXT: pand %xmm3, %xmm6 ; SSE2-NEXT: psllw $4, %xmm6 ; SSE2-NEXT: movdqa %xmm3, %xmm4 ; SSE2-NEXT: pandn %xmm6, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $4, %xmm1 ; SSE2-NEXT: pand %xmm3, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm14[8],xmm4[9],xmm14[9],xmm4[10],xmm14[10],xmm4[11],xmm14[11],xmm4[12],xmm14[12],xmm4[13],xmm14[13],xmm4[14],xmm14[14],xmm4[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm4[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,5,4,7,6] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm14[0],xmm2[1],xmm14[1],xmm2[2],xmm14[2],xmm2[3],xmm14[3],xmm2[4],xmm14[4],xmm2[5],xmm14[5],xmm2[6],xmm14[6],xmm2[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm10[0],xmm2[1],xmm10[1],xmm2[2],xmm10[2],xmm2[3],xmm10[3],xmm2[4],xmm10[4],xmm2[5],xmm10[5],xmm2[6],xmm10[6],xmm2[7],xmm10[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm2[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,5,4,7,6] ; SSE2-NEXT: packuswb %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 ; SSE2-NEXT: movdqa %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm4, %xmm6 -; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm3, %xmm2 ; SSE2-NEXT: por %xmm6, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm2 +; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $2, %xmm2 -; SSE2-NEXT: pand %xmm11, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm2 -; SSE2-NEXT: paddb %xmm2, %xmm2 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 -; SSE2-NEXT: movdqa %xmm15, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm14[8],xmm4[9],xmm14[9],xmm4[10],xmm14[10],xmm4[11],xmm14[11],xmm4[12],xmm14[12],xmm4[13],xmm14[13],xmm4[14],xmm14[14],xmm4[15],xmm14[15] +; SSE2-NEXT: movdqa %xmm11, %xmm4 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm4[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,5,4,7,6] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm15 = xmm15[0],xmm14[0],xmm15[1],xmm14[1],xmm15[2],xmm14[2],xmm15[3],xmm14[3],xmm15[4],xmm14[4],xmm15[5],xmm14[5],xmm15[6],xmm14[6],xmm15[7],xmm14[7] -; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm15[1,0,3,2,4,5,6,7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm11 = xmm11[0],xmm10[0],xmm11[1],xmm10[1],xmm11[2],xmm10[2],xmm11[3],xmm10[3],xmm11[4],xmm10[4],xmm11[5],xmm10[5],xmm11[6],xmm10[6],xmm11[7],xmm10[7] +; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm11[1,0,3,2,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm6 = xmm6[0,1,2,3,5,4,7,6] ; SSE2-NEXT: packuswb %xmm4, %xmm6 ; SSE2-NEXT: movdqa %xmm6, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm6 ; SSE2-NEXT: psrlw $4, %xmm6 ; SSE2-NEXT: pand %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm4, %xmm3 ; SSE2-NEXT: por %xmm6, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: pand %xmm9, %xmm5 -; SSE2-NEXT: pand %xmm10, %xmm3 +; SSE2-NEXT: pand %xmm8, %xmm3 ; SSE2-NEXT: psrlw $2, %xmm3 -; SSE2-NEXT: pand %xmm11, %xmm3 ; SSE2-NEXT: por %xmm5, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm7 -; SSE2-NEXT: psrlw $1, %xmm7 -; SSE2-NEXT: pand %xmm12, %xmm7 -; SSE2-NEXT: pand %xmm13, %xmm3 -; SSE2-NEXT: paddb %xmm3, %xmm3 +; SSE2-NEXT: paddb %xmm7, %xmm7 +; SSE2-NEXT: pand %xmm9, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm3 ; SSE2-NEXT: por %xmm7, %xmm3 ; SSE2-NEXT: retq ; @@ -1808,24 +1679,21 @@ define <32 x i16> @test_bitreverse_v32i16(<32 x i16> %a) nounwind { define <16 x i32> @test_bitreverse_v16i32(<16 x i32> %a) nounwind { ; SSE2-LABEL: test_bitreverse_v16i32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm3, %xmm15 -; SSE2-NEXT: pxor %xmm14, %xmm14 +; SSE2-NEXT: movdqa %xmm3, %xmm11 +; SSE2-NEXT: pxor %xmm10, %xmm10 ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm14[8],xmm3[9],xmm14[9],xmm3[10],xmm14[10],xmm3[11],xmm14[11],xmm3[12],xmm14[12],xmm3[13],xmm14[13],xmm3[14],xmm14[14],xmm3[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm10[8],xmm3[9],xmm10[9],xmm3[10],xmm10[10],xmm3[11],xmm10[11],xmm3[12],xmm10[12],xmm3[13],xmm10[13],xmm3[14],xmm10[14],xmm3[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm14[0],xmm0[1],xmm14[1],xmm0[2],xmm14[2],xmm0[3],xmm14[3],xmm0[4],xmm14[4],xmm0[5],xmm14[5],xmm0[6],xmm14[6],xmm0[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm10[0],xmm0[1],xmm10[1],xmm0[2],xmm10[2],xmm0[3],xmm10[3],xmm0[4],xmm10[4],xmm0[5],xmm10[5],xmm0[6],xmm10[6],xmm0[7],xmm10[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $4, %xmm5 +; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm3, %xmm7 ; SSE2-NEXT: pandn %xmm5, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm3, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 @@ -1833,116 +1701,95 @@ define <16 x i32> @test_bitreverse_v16i32(<16 x i32> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm7 ; SSE2-NEXT: pand %xmm5, %xmm7 ; SSE2-NEXT: psllw $2, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm7, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm13 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] -; SSE2-NEXT: pand %xmm13, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: pand %xmm9, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 ; SSE2-NEXT: movdqa %xmm1, %xmm6 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm14[8],xmm6[9],xmm14[9],xmm6[10],xmm14[10],xmm6[11],xmm14[11],xmm6[12],xmm14[12],xmm6[13],xmm14[13],xmm6[14],xmm14[14],xmm6[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm10[8],xmm6[9],xmm10[9],xmm6[10],xmm10[10],xmm6[11],xmm10[11],xmm6[12],xmm10[12],xmm6[13],xmm10[13],xmm6[14],xmm10[14],xmm6[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm6[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm6 = xmm6[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm14[0],xmm1[1],xmm14[1],xmm1[2],xmm14[2],xmm1[3],xmm14[3],xmm1[4],xmm14[4],xmm1[5],xmm14[5],xmm1[6],xmm14[6],xmm1[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm10[0],xmm1[1],xmm10[1],xmm1[2],xmm10[2],xmm1[3],xmm10[3],xmm1[4],xmm10[4],xmm1[5],xmm10[5],xmm1[6],xmm10[6],xmm1[7],xmm10[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm6, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm6 -; SSE2-NEXT: pand %xmm3, %xmm6 ; SSE2-NEXT: psllw $4, %xmm6 ; SSE2-NEXT: movdqa %xmm3, %xmm4 ; SSE2-NEXT: pandn %xmm6, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $4, %xmm1 ; SSE2-NEXT: pand %xmm3, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm14[8],xmm4[9],xmm14[9],xmm4[10],xmm14[10],xmm4[11],xmm14[11],xmm4[12],xmm14[12],xmm4[13],xmm14[13],xmm4[14],xmm14[14],xmm4[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm4[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm14[0],xmm2[1],xmm14[1],xmm2[2],xmm14[2],xmm2[3],xmm14[3],xmm2[4],xmm14[4],xmm2[5],xmm14[5],xmm2[6],xmm14[6],xmm2[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm10[0],xmm2[1],xmm10[1],xmm2[2],xmm10[2],xmm2[3],xmm10[3],xmm2[4],xmm10[4],xmm2[5],xmm10[5],xmm2[6],xmm10[6],xmm2[7],xmm10[7] ; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm2[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 ; SSE2-NEXT: movdqa %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm4, %xmm6 -; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm3, %xmm2 ; SSE2-NEXT: por %xmm6, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm2 +; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $2, %xmm2 -; SSE2-NEXT: pand %xmm11, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm2 -; SSE2-NEXT: paddb %xmm2, %xmm2 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 -; SSE2-NEXT: movdqa %xmm15, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm14[8],xmm4[9],xmm14[9],xmm4[10],xmm14[10],xmm4[11],xmm14[11],xmm4[12],xmm14[12],xmm4[13],xmm14[13],xmm4[14],xmm14[14],xmm4[15],xmm14[15] +; SSE2-NEXT: movdqa %xmm11, %xmm4 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] ; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm4[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm15 = xmm15[0],xmm14[0],xmm15[1],xmm14[1],xmm15[2],xmm14[2],xmm15[3],xmm14[3],xmm15[4],xmm14[4],xmm15[5],xmm14[5],xmm15[6],xmm14[6],xmm15[7],xmm14[7] -; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm15[3,2,1,0,4,5,6,7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm11 = xmm11[0],xmm10[0],xmm11[1],xmm10[1],xmm11[2],xmm10[2],xmm11[3],xmm10[3],xmm11[4],xmm10[4],xmm11[5],xmm10[5],xmm11[6],xmm10[6],xmm11[7],xmm10[7] +; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm11[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm6 = xmm6[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm4, %xmm6 ; SSE2-NEXT: movdqa %xmm6, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm6 ; SSE2-NEXT: psrlw $4, %xmm6 ; SSE2-NEXT: pand %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm4, %xmm3 ; SSE2-NEXT: por %xmm6, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: pand %xmm9, %xmm5 -; SSE2-NEXT: pand %xmm10, %xmm3 +; SSE2-NEXT: pand %xmm8, %xmm3 ; SSE2-NEXT: psrlw $2, %xmm3 -; SSE2-NEXT: pand %xmm11, %xmm3 ; SSE2-NEXT: por %xmm5, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm7 -; SSE2-NEXT: psrlw $1, %xmm7 -; SSE2-NEXT: pand %xmm12, %xmm7 -; SSE2-NEXT: pand %xmm13, %xmm3 -; SSE2-NEXT: paddb %xmm3, %xmm3 +; SSE2-NEXT: paddb %xmm7, %xmm7 +; SSE2-NEXT: pand %xmm9, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm3 ; SSE2-NEXT: por %xmm7, %xmm3 ; SSE2-NEXT: retq ; @@ -2132,26 +1979,23 @@ define <16 x i32> @test_bitreverse_v16i32(<16 x i32> %a) nounwind { define <8 x i64> @test_bitreverse_v8i64(<8 x i64> %a) nounwind { ; SSE2-LABEL: test_bitreverse_v8i64: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm3, %xmm15 -; SSE2-NEXT: pxor %xmm14, %xmm14 +; SSE2-NEXT: movdqa %xmm3, %xmm11 +; SSE2-NEXT: pxor %xmm10, %xmm10 ; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm14[8],xmm3[9],xmm14[9],xmm3[10],xmm14[10],xmm3[11],xmm14[11],xmm3[12],xmm14[12],xmm3[13],xmm14[13],xmm3[14],xmm14[14],xmm3[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm10[8],xmm3[9],xmm10[9],xmm3[10],xmm10[10],xmm3[11],xmm10[11],xmm3[12],xmm10[12],xmm3[13],xmm10[13],xmm3[14],xmm10[14],xmm3[15],xmm10[15] ; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm3[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm3 = xmm3[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm14[0],xmm0[1],xmm14[1],xmm0[2],xmm14[2],xmm0[3],xmm14[3],xmm0[4],xmm14[4],xmm0[5],xmm14[5],xmm0[6],xmm14[6],xmm0[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm10[0],xmm0[1],xmm10[1],xmm0[2],xmm10[2],xmm0[3],xmm10[3],xmm0[4],xmm10[4],xmm0[5],xmm10[5],xmm0[6],xmm10[6],xmm0[7],xmm10[7] ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $4, %xmm5 +; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] ; SSE2-NEXT: movdqa %xmm3, %xmm7 ; SSE2-NEXT: pandn %xmm5, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240] -; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $4, %xmm0 ; SSE2-NEXT: pand %xmm3, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 @@ -2159,122 +2003,101 @@ define <8 x i64> @test_bitreverse_v8i64(<8 x i64> %a) nounwind { ; SSE2-NEXT: movdqa %xmm0, %xmm7 ; SSE2-NEXT: pand %xmm5, %xmm7 ; SSE2-NEXT: psllw $2, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252] -; SSE2-NEXT: pand %xmm9, %xmm7 -; SSE2-NEXT: movdqa {{.*#+}} xmm10 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] -; SSE2-NEXT: pand %xmm10, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204] +; SSE2-NEXT: pand %xmm8, %xmm0 ; SSE2-NEXT: psrlw $2, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm11 = [63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63] -; SSE2-NEXT: pand %xmm11, %xmm0 ; SSE2-NEXT: por %xmm7, %xmm0 -; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] ; SSE2-NEXT: movdqa %xmm0, %xmm6 ; SSE2-NEXT: pand %xmm7, %xmm6 -; SSE2-NEXT: psrlw $1, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm12 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] -; SSE2-NEXT: pand %xmm12, %xmm6 -; SSE2-NEXT: movdqa {{.*#+}} xmm13 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] -; SSE2-NEXT: pand %xmm13, %xmm0 -; SSE2-NEXT: paddb %xmm0, %xmm0 +; SSE2-NEXT: paddb %xmm6, %xmm6 +; SSE2-NEXT: movdqa {{.*#+}} xmm9 = [170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170] +; SSE2-NEXT: pand %xmm9, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 ; SSE2-NEXT: por %xmm6, %xmm0 ; SSE2-NEXT: movdqa %xmm1, %xmm6 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm14[8],xmm6[9],xmm14[9],xmm6[10],xmm14[10],xmm6[11],xmm14[11],xmm6[12],xmm14[12],xmm6[13],xmm14[13],xmm6[14],xmm14[14],xmm6[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm10[8],xmm6[9],xmm10[9],xmm6[10],xmm10[10],xmm6[11],xmm10[11],xmm6[12],xmm10[12],xmm6[13],xmm10[13],xmm6[14],xmm10[14],xmm6[15],xmm10[15] ; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm6[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm6[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm6 = xmm6[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm14[0],xmm1[1],xmm14[1],xmm1[2],xmm14[2],xmm1[3],xmm14[3],xmm1[4],xmm14[4],xmm1[5],xmm14[5],xmm1[6],xmm14[6],xmm1[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm10[0],xmm1[1],xmm10[1],xmm1[2],xmm10[2],xmm1[3],xmm10[3],xmm1[4],xmm10[4],xmm1[5],xmm10[5],xmm1[6],xmm10[6],xmm1[7],xmm10[7] ; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm6, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm6 -; SSE2-NEXT: pand %xmm3, %xmm6 ; SSE2-NEXT: psllw $4, %xmm6 ; SSE2-NEXT: movdqa %xmm3, %xmm4 ; SSE2-NEXT: pandn %xmm6, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $4, %xmm1 ; SSE2-NEXT: pand %xmm3, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm1 ; SSE2-NEXT: psrlw $2, %xmm1 -; SSE2-NEXT: pand %xmm11, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm1 -; SSE2-NEXT: paddb %xmm1, %xmm1 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 ; SSE2-NEXT: por %xmm4, %xmm1 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm14[8],xmm4[9],xmm14[9],xmm4[10],xmm14[10],xmm4[11],xmm14[11],xmm4[12],xmm14[12],xmm4[13],xmm14[13],xmm4[14],xmm14[14],xmm4[15],xmm14[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] ; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm4[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm14[0],xmm2[1],xmm14[1],xmm2[2],xmm14[2],xmm2[3],xmm14[3],xmm2[4],xmm14[4],xmm2[5],xmm14[5],xmm2[6],xmm14[6],xmm2[7],xmm14[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm10[0],xmm2[1],xmm10[1],xmm2[2],xmm10[2],xmm2[3],xmm10[3],xmm2[4],xmm10[4],xmm2[5],xmm10[5],xmm2[6],xmm10[6],xmm2[7],xmm10[7] ; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm2[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm2 = xmm2[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 ; SSE2-NEXT: movdqa %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm4, %xmm6 -; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $4, %xmm2 ; SSE2-NEXT: pand %xmm3, %xmm2 ; SSE2-NEXT: por %xmm6, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm5, %xmm4 ; SSE2-NEXT: psllw $2, %xmm4 -; SSE2-NEXT: pand %xmm9, %xmm4 -; SSE2-NEXT: pand %xmm10, %xmm2 +; SSE2-NEXT: pand %xmm8, %xmm2 ; SSE2-NEXT: psrlw $2, %xmm2 -; SSE2-NEXT: pand %xmm11, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm4 ; SSE2-NEXT: pand %xmm7, %xmm4 -; SSE2-NEXT: psrlw $1, %xmm4 -; SSE2-NEXT: pand %xmm12, %xmm4 -; SSE2-NEXT: pand %xmm13, %xmm2 -; SSE2-NEXT: paddb %xmm2, %xmm2 +; SSE2-NEXT: paddb %xmm4, %xmm4 +; SSE2-NEXT: pand %xmm9, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm2 ; SSE2-NEXT: por %xmm4, %xmm2 -; SSE2-NEXT: movdqa %xmm15, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm14[8],xmm4[9],xmm14[9],xmm4[10],xmm14[10],xmm4[11],xmm14[11],xmm4[12],xmm14[12],xmm4[13],xmm14[13],xmm4[14],xmm14[14],xmm4[15],xmm14[15] +; SSE2-NEXT: movdqa %xmm11, %xmm4 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm10[8],xmm4[9],xmm10[9],xmm4[10],xmm10[10],xmm4[11],xmm10[11],xmm4[12],xmm10[12],xmm4[13],xmm10[13],xmm4[14],xmm10[14],xmm4[15],xmm10[15] ; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm4[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm4 = xmm4[0,1,2,3,7,6,5,4] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm15 = xmm15[0],xmm14[0],xmm15[1],xmm14[1],xmm15[2],xmm14[2],xmm15[3],xmm14[3],xmm15[4],xmm14[4],xmm15[5],xmm14[5],xmm15[6],xmm14[6],xmm15[7],xmm14[7] -; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm15[2,3,0,1] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm11 = xmm11[0],xmm10[0],xmm11[1],xmm10[1],xmm11[2],xmm10[2],xmm11[3],xmm10[3],xmm11[4],xmm10[4],xmm11[5],xmm10[5],xmm11[6],xmm10[6],xmm11[7],xmm10[7] +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm11[2,3,0,1] ; SSE2-NEXT: pshuflw {{.*#+}} xmm6 = xmm6[3,2,1,0,4,5,6,7] ; SSE2-NEXT: pshufhw {{.*#+}} xmm6 = xmm6[0,1,2,3,7,6,5,4] ; SSE2-NEXT: packuswb %xmm4, %xmm6 ; SSE2-NEXT: movdqa %xmm6, %xmm4 -; SSE2-NEXT: pand %xmm3, %xmm4 ; SSE2-NEXT: psllw $4, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm6 ; SSE2-NEXT: psrlw $4, %xmm6 ; SSE2-NEXT: pand %xmm3, %xmm6 ; SSE2-NEXT: pandn %xmm4, %xmm3 ; SSE2-NEXT: por %xmm6, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm5 ; SSE2-NEXT: psllw $2, %xmm5 -; SSE2-NEXT: pand %xmm9, %xmm5 -; SSE2-NEXT: pand %xmm10, %xmm3 +; SSE2-NEXT: pand %xmm8, %xmm3 ; SSE2-NEXT: psrlw $2, %xmm3 -; SSE2-NEXT: pand %xmm11, %xmm3 ; SSE2-NEXT: por %xmm5, %xmm3 ; SSE2-NEXT: pand %xmm3, %xmm7 -; SSE2-NEXT: psrlw $1, %xmm7 -; SSE2-NEXT: pand %xmm12, %xmm7 -; SSE2-NEXT: pand %xmm13, %xmm3 -; SSE2-NEXT: paddb %xmm3, %xmm3 +; SSE2-NEXT: paddb %xmm7, %xmm7 +; SSE2-NEXT: pand %xmm9, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm3 ; SSE2-NEXT: por %xmm7, %xmm3 ; SSE2-NEXT: retq ; diff --git a/llvm/test/CodeGen/X86/vector-pcmp.ll b/llvm/test/CodeGen/X86/vector-pcmp.ll index 6e010f75ad26a..89eaad82fd227 100644 --- a/llvm/test/CodeGen/X86/vector-pcmp.ll +++ b/llvm/test/CodeGen/X86/vector-pcmp.ll @@ -414,10 +414,9 @@ define <2 x i64> @cmpgt_zext_v2i64(<2 x i64> %a, <2 x i64> %b) { ; SSE2-NEXT: pxor %xmm2, %xmm0 ; SSE2-NEXT: movdqa %xmm0, %xmm2 ; SSE2-NEXT: pcmpgtd %xmm1, %xmm2 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[0,0,2,2] ; SSE2-NEXT: pcmpeqd %xmm1, %xmm0 ; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,3,3] -; SSE2-NEXT: pand %xmm3, %xmm1 +; SSE2-NEXT: pand %xmm2, %xmm1 ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[1,1,3,3] ; SSE2-NEXT: por %xmm1, %xmm0 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 diff --git a/llvm/test/CodeGen/X86/vector-reduce-mul-widen.ll b/llvm/test/CodeGen/X86/vector-reduce-mul-widen.ll index b2668ef75c51b..76ace68eb8c03 100644 --- a/llvm/test/CodeGen/X86/vector-reduce-mul-widen.ll +++ b/llvm/test/CodeGen/X86/vector-reduce-mul-widen.ll @@ -1658,20 +1658,14 @@ define i8 @test_v8i8(<8 x i8> %a0) { ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; SSE2-NEXT: pmullw %xmm0, %xmm1 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm1 -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: psrldq {{.*#+}} xmm1 = xmm1[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm2, %xmm1 -; SSE2-NEXT: pand %xmm0, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm1 -; SSE2-NEXT: movdqa %xmm1, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,2,3,0] ; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: movd %xmm0, %eax +; SSE2-NEXT: pand {{.*}}(%rip), %xmm0 +; SSE2-NEXT: packuswb %xmm0, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrlw $8, %xmm1 +; SSE2-NEXT: pmullw %xmm0, %xmm1 +; SSE2-NEXT: movd %xmm1, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; @@ -1744,29 +1738,27 @@ define i8 @test_v16i8(<16 x i8> %a0) { ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; SSE2-NEXT: pmullw %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm0 ; SSE2-NEXT: pand %xmm1, %xmm0 -; SSE2-NEXT: pxor %xmm2, %xmm2 -; SSE2-NEXT: packuswb %xmm2, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 -; SSE2-NEXT: packuswb %xmm2, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 +; SSE2-NEXT: packuswb %xmm3, %xmm0 +; SSE2-NEXT: psrldq {{.*#+}} xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm3 = xmm3[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 -; SSE2-NEXT: packuswb %xmm2, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 -; SSE2-NEXT: packuswb %xmm2, %xmm3 -; SSE2-NEXT: movd %xmm3, %eax +; SSE2-NEXT: pmullw %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; @@ -1831,7 +1823,7 @@ define i8 @test_v16i8(<16 x i8> %a0) { ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX2-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] ; AVX2-NEXT: vpand %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpackuswb %xmm0, %xmm0, %xmm2 ; AVX2-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] @@ -1965,40 +1957,32 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; SSE2-NEXT: movdqa %xmm0, %xmm3 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] ; SSE2-NEXT: pmullw %xmm2, %xmm3 -; SSE2-NEXT: movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm2, %xmm3 ; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: pmullw %xmm3, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm0 +; SSE2-NEXT: pand %xmm1, %xmm0 ; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa %xmm0, %xmm1 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm2, %xmm0 -; SSE2-NEXT: pxor %xmm1, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm2, %xmm3 -; SSE2-NEXT: packuswb %xmm1, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 +; SSE2-NEXT: psrldq {{.*#+}} xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm3 = xmm3[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm2, %xmm3 -; SSE2-NEXT: packuswb %xmm1, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm2, %xmm3 -; SSE2-NEXT: packuswb %xmm1, %xmm3 -; SSE2-NEXT: movd %xmm3, %eax +; SSE2-NEXT: pmullw %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; @@ -2009,32 +1993,29 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; SSE41-NEXT: pmullw %xmm1, %xmm0 -; SSE41-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] -; SSE41-NEXT: pand %xmm1, %xmm0 ; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm0, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: pxor %xmm0, %xmm0 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,0,1] -; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 +; SSE41-NEXT: pshufb {{.*#+}} xmm3 = xmm3[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u] +; SSE41-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,2,3] -; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: movdqa %xmm3, %xmm0 +; SSE41-NEXT: pmullw %xmm0, %xmm2 +; SSE41-NEXT: pand %xmm1, %xmm2 +; SSE41-NEXT: pxor %xmm0, %xmm0 +; SSE41-NEXT: packuswb %xmm0, %xmm2 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,0,1] +; SSE41-NEXT: pmullw %xmm3, %xmm2 +; SSE41-NEXT: pand %xmm1, %xmm2 +; SSE41-NEXT: packuswb %xmm0, %xmm2 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] +; SSE41-NEXT: pmullw %xmm3, %xmm2 +; SSE41-NEXT: pand %xmm1, %xmm2 +; SSE41-NEXT: packuswb %xmm0, %xmm2 +; SSE41-NEXT: movdqa %xmm2, %xmm0 ; SSE41-NEXT: psrlw $8, %xmm0 -; SSE41-NEXT: pmullw %xmm3, %xmm0 +; SSE41-NEXT: pmullw %xmm2, %xmm0 ; SSE41-NEXT: pextrb $0, %xmm0, %eax ; SSE41-NEXT: # kill: def $al killed $al killed $eax ; SSE41-NEXT: retq @@ -2044,37 +2025,31 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1 ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] -; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX1-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u] +; AVX1-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm1 +; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpextrb $0, %xmm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -2086,16 +2061,15 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX2-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2182,16 +2156,15 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQ-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512DQ-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512DQ-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2222,33 +2195,25 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512DQVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQVL-NEXT: vpextrb $0, %xmm0, %eax @@ -2262,102 +2227,74 @@ define i8 @test_v32i8(<32 x i8> %a0) { define i8 @test_v64i8(<64 x i8> %a0) { ; SSE2-LABEL: test_v64i8: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm4, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm4, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm2, %xmm0 -; SSE2-NEXT: pand %xmm4, %xmm0 -; SSE2-NEXT: packuswb %xmm5, %xmm0 -; SSE2-NEXT: movdqa %xmm3, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm3, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] ; SSE2-NEXT: movdqa %xmm1, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm5 -; SSE2-NEXT: pand %xmm4, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm3, %xmm1 -; SSE2-NEXT: pand %xmm4, %xmm1 -; SSE2-NEXT: packuswb %xmm5, %xmm1 -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3],xmm5[4],xmm0[4],xmm5[5],xmm0[5],xmm5[6],xmm0[6],xmm5[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm4, %xmm5 +; SSE2-NEXT: movdqa %xmm2, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; SSE2-NEXT: movdqa %xmm0, %xmm6 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3],xmm6[4],xmm0[4],xmm6[5],xmm0[5],xmm6[6],xmm0[6],xmm6[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm4, %xmm6 +; SSE2-NEXT: pmullw %xmm5, %xmm6 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm3 -; SSE2-NEXT: pand %xmm4, %xmm3 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm4, %xmm0 -; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa %xmm0, %xmm1 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pmullw %xmm3, %xmm1 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: pmullw %xmm2, %xmm0 ; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm4, %xmm0 -; SSE2-NEXT: pxor %xmm1, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pmullw %xmm6, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm4, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm0 +; SSE2-NEXT: pand %xmm1, %xmm0 +; SSE2-NEXT: packuswb %xmm3, %xmm0 +; SSE2-NEXT: psrldq {{.*#+}} xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm2 = xmm2[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm4, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 ; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm4, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 ; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; ; SSE41-LABEL: test_v64i8: ; SSE41: # %bb.0: -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; SSE41-NEXT: pmullw %xmm2, %xmm0 -; SSE41-NEXT: movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] -; SSE41-NEXT: pand %xmm2, %xmm0 -; SSE41-NEXT: pmullw %xmm5, %xmm4 -; SSE41-NEXT: pand %xmm2, %xmm4 -; SSE41-NEXT: packuswb %xmm0, %xmm4 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; SSE41-NEXT: pmullw %xmm3, %xmm1 -; SSE41-NEXT: pand %xmm2, %xmm1 -; SSE41-NEXT: pmullw %xmm0, %xmm5 -; SSE41-NEXT: pand %xmm2, %xmm5 -; SSE41-NEXT: packuswb %xmm1, %xmm5 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE41-NEXT: pmullw %xmm2, %xmm0 +; SSE41-NEXT: pmullw %xmm1, %xmm0 +; SSE41-NEXT: pmullw %xmm3, %xmm6 +; SSE41-NEXT: movdqa {{.*#+}} xmm1 = <0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u> +; SSE41-NEXT: pshufb %xmm1, %xmm6 +; SSE41-NEXT: pmullw %xmm4, %xmm5 +; SSE41-NEXT: pshufb %xmm1, %xmm5 +; SSE41-NEXT: movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmullw %xmm3, %xmm4 +; SSE41-NEXT: pshufb %xmm1, %xmm4 ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm5, %xmm4 -; SSE41-NEXT: pand %xmm2, %xmm4 -; SSE41-NEXT: pmullw %xmm0, %xmm1 -; SSE41-NEXT: pand %xmm2, %xmm1 -; SSE41-NEXT: packuswb %xmm4, %xmm1 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; SSE41-NEXT: pmullw %xmm0, %xmm1 ; SSE41-NEXT: pand %xmm2, %xmm1 ; SSE41-NEXT: pxor %xmm0, %xmm0 @@ -2383,59 +2320,48 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; ; AVX1-LABEL: test_v64i8: ; AVX1: # %bb.0: -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm3 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] -; AVX1-NEXT: vpand %xmm2, %xmm3, %xmm3 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm4 -; AVX1-NEXT: vpand %xmm2, %xmm4, %xmm4 -; AVX1-NEXT: vpackuswb %xmm3, %xmm4, %xmm3 -; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm3, %xmm5, %xmm3 ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm4 -; AVX1-NEXT: vpand %xmm2, %xmm4, %xmm4 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm1, %xmm4, %xmm1 -; AVX1-NEXT: vpand %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm1 = <0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u> +; AVX1-NEXT: vpshufb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX1-NEXT: vpmullw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpshufb %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpshufb %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm5, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 ; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] -; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] -; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm3 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm1 +; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpextrb $0, %xmm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -2457,16 +2383,15 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX2-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2508,16 +2433,15 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BW-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BW-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512BW-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512BW-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512BW-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512BW-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2559,33 +2483,25 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BWVL-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BWVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512BWVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BWVL-NEXT: vpextrb $0, %xmm0, %eax @@ -2609,16 +2525,15 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQ-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512DQ-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512DQ-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2659,33 +2574,25 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512DQVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQVL-NEXT: vpextrb $0, %xmm0, %eax @@ -2699,298 +2606,211 @@ define i8 @test_v64i8(<64 x i8> %a0) { define i8 @test_v128i8(<128 x i8> %a0) { ; SSE2-LABEL: test_v128i8: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm5, %xmm8 +; SSE2-NEXT: movdqa %xmm6, %xmm8 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm1, %xmm9 +; SSE2-NEXT: movdqa %xmm2, %xmm9 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm0[8],xmm9[9],xmm0[9],xmm9[10],xmm0[10],xmm9[11],xmm0[11],xmm9[12],xmm0[12],xmm9[13],xmm0[13],xmm9[14],xmm0[14],xmm9[15],xmm0[15] ; SSE2-NEXT: pmullw %xmm8, %xmm9 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm8, %xmm9 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3],xmm5[4],xmm0[4],xmm5[5],xmm0[5],xmm5[6],xmm0[6],xmm5[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm5, %xmm1 -; SSE2-NEXT: pand %xmm8, %xmm1 -; SSE2-NEXT: packuswb %xmm9, %xmm1 -; SSE2-NEXT: movdqa %xmm7, %xmm9 +; SSE2-NEXT: movdqa %xmm4, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm0, %xmm10 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm0[8],xmm10[9],xmm0[9],xmm10[10],xmm0[10],xmm10[11],xmm0[11],xmm10[12],xmm0[12],xmm10[13],xmm0[13],xmm10[14],xmm0[14],xmm10[15],xmm0[15] +; SSE2-NEXT: pmullw %xmm8, %xmm10 +; SSE2-NEXT: pmullw %xmm9, %xmm10 +; SSE2-NEXT: movdqa %xmm7, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm3, %xmm9 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm0[8],xmm9[9],xmm0[9],xmm9[10],xmm0[10],xmm9[11],xmm0[11],xmm9[12],xmm0[12],xmm9[13],xmm0[13],xmm9[14],xmm0[14],xmm9[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm3, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm9, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm0[0],xmm7[1],xmm0[1],xmm7[2],xmm0[2],xmm7[3],xmm0[3],xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm7, %xmm3 -; SSE2-NEXT: pand %xmm8, %xmm3 -; SSE2-NEXT: packuswb %xmm5, %xmm3 -; SSE2-NEXT: movdqa %xmm4, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm7 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm5, %xmm7 -; SSE2-NEXT: pand %xmm8, %xmm7 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm4, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: packuswb %xmm7, %xmm0 -; SSE2-NEXT: movdqa %xmm6, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm2, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm4, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 +; SSE2-NEXT: pmullw %xmm8, %xmm9 +; SSE2-NEXT: movdqa %xmm5, %xmm11 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm11 = xmm11[8],xmm0[8],xmm11[9],xmm0[9],xmm11[10],xmm0[10],xmm11[11],xmm0[11],xmm11[12],xmm0[12],xmm11[13],xmm0[13],xmm11[14],xmm0[14],xmm11[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm1, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: pmullw %xmm11, %xmm8 +; SSE2-NEXT: pmullw %xmm9, %xmm8 +; SSE2-NEXT: pmullw %xmm10, %xmm8 ; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3],xmm6[4],xmm0[4],xmm6[5],xmm0[5],xmm6[6],xmm0[6],xmm6[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; SSE2-NEXT: pmullw %xmm6, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm5, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm4, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pmullw %xmm4, %xmm0 ; SSE2-NEXT: pmullw %xmm2, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: packuswb %xmm5, %xmm0 -; SSE2-NEXT: movdqa %xmm3, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm1, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm0[0],xmm7[1],xmm0[1],xmm7[2],xmm0[2],xmm7[3],xmm0[3],xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm7, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3],xmm5[4],xmm0[4],xmm5[5],xmm0[5],xmm5[6],xmm0[6],xmm5[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm5, %xmm1 ; SSE2-NEXT: pmullw %xmm3, %xmm1 -; SSE2-NEXT: pand %xmm8, %xmm1 -; SSE2-NEXT: packuswb %xmm4, %xmm1 +; SSE2-NEXT: pmullw %xmm0, %xmm1 +; SSE2-NEXT: pmullw %xmm8, %xmm1 +; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [255,255,255,255,255,255,255,255] ; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm3 -; SSE2-NEXT: pand %xmm8, %xmm3 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa %xmm0, %xmm1 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: pxor %xmm1, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pand %xmm0, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm2 = xmm2[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 +; SSE2-NEXT: pmullw %xmm1, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm1 +; SSE2-NEXT: pand %xmm0, %xmm1 +; SSE2-NEXT: packuswb %xmm3, %xmm1 +; SSE2-NEXT: psrldq {{.*#+}} xmm1 = xmm1[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm2, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: pand %xmm0, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 +; SSE2-NEXT: pmullw %xmm1, %xmm2 +; SSE2-NEXT: pand %xmm0, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 ; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; ; SSE41-LABEL: test_v128i8: ; SSE41: # %bb.0: -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm8 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm5, %xmm1 -; SSE41-NEXT: movdqa {{.*#+}} xmm5 = [255,255,255,255,255,255,255,255] -; SSE41-NEXT: pand %xmm5, %xmm1 -; SSE41-NEXT: pmullw %xmm9, %xmm8 -; SSE41-NEXT: pand %xmm5, %xmm8 -; SSE41-NEXT: packuswb %xmm1, %xmm8 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm7, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 -; SSE41-NEXT: pmullw %xmm9, %xmm1 -; SSE41-NEXT: pand %xmm5, %xmm1 -; SSE41-NEXT: packuswb %xmm3, %xmm1 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm7 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; SSE41-NEXT: pmullw %xmm4, %xmm0 -; SSE41-NEXT: pand %xmm5, %xmm0 -; SSE41-NEXT: pmullw %xmm7, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm8 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] ; SSE41-NEXT: pmullw %xmm6, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: pmullw %xmm0, %xmm4 -; SSE41-NEXT: pand %xmm5, %xmm4 -; SSE41-NEXT: packuswb %xmm2, %xmm4 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm10 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm4, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE41-NEXT: pmullw %xmm4, %xmm0 ; SSE41-NEXT: pmullw %xmm2, %xmm0 -; SSE41-NEXT: pand %xmm5, %xmm0 -; SSE41-NEXT: packuswb %xmm3, %xmm0 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm11 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; SSE41-NEXT: pmullw %xmm7, %xmm3 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm7 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero,xmm8[4],zero,xmm8[5],zero,xmm8[6],zero,xmm8[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm1, %xmm8 -; SSE41-NEXT: pand %xmm5, %xmm8 -; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 -; SSE41-NEXT: packuswb %xmm8, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; SSE41-NEXT: pmullw %xmm5, %xmm1 +; SSE41-NEXT: pmullw %xmm3, %xmm1 +; SSE41-NEXT: pmullw %xmm0, %xmm1 +; SSE41-NEXT: pmullw %xmm7, %xmm2 +; SSE41-NEXT: movdqa {{.*#+}} xmm0 = <0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u> +; SSE41-NEXT: pshufb %xmm0, %xmm2 +; SSE41-NEXT: pmullw %xmm11, %xmm4 +; SSE41-NEXT: pshufb %xmm0, %xmm4 +; SSE41-NEXT: pmullw %xmm10, %xmm6 +; SSE41-NEXT: pshufb %xmm0, %xmm6 +; SSE41-NEXT: pmullw %xmm8, %xmm9 +; SSE41-NEXT: pshufb %xmm0, %xmm9 +; SSE41-NEXT: movdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero,xmm9[4],zero,xmm9[5],zero,xmm9[6],zero,xmm9[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmullw %xmm5, %xmm6 +; SSE41-NEXT: pshufb %xmm0, %xmm6 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: pmullw %xmm4, %xmm2 +; SSE41-NEXT: pshufb %xmm0, %xmm2 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmullw %xmm2, %xmm4 +; SSE41-NEXT: pshufb %xmm0, %xmm4 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE41-NEXT: pmullw %xmm1, %xmm0 +; SSE41-NEXT: pand %xmm3, %xmm0 +; SSE41-NEXT: pxor %xmm1, %xmm1 +; SSE41-NEXT: packuswb %xmm1, %xmm0 ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; SSE41-NEXT: pmullw %xmm3, %xmm0 -; SSE41-NEXT: pand %xmm5, %xmm0 -; SSE41-NEXT: pmullw %xmm1, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm0, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: pxor %xmm0, %xmm0 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,0,1] -; SSE41-NEXT: pmullw %xmm1, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] -; SSE41-NEXT: pmullw %xmm1, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: movdqa %xmm2, %xmm0 -; SSE41-NEXT: psrlw $8, %xmm0 +; SSE41-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] ; SSE41-NEXT: pmullw %xmm2, %xmm0 -; SSE41-NEXT: pextrb $0, %xmm0, %eax +; SSE41-NEXT: pand %xmm3, %xmm0 +; SSE41-NEXT: packuswb %xmm1, %xmm0 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE41-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] +; SSE41-NEXT: pmullw %xmm2, %xmm0 +; SSE41-NEXT: pand %xmm3, %xmm0 +; SSE41-NEXT: packuswb %xmm1, %xmm0 +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrlw $8, %xmm1 +; SSE41-NEXT: pmullw %xmm0, %xmm1 +; SSE41-NEXT: pextrb $0, %xmm1, %eax ; SSE41-NEXT: # kill: def $al killed $al killed $eax ; SSE41-NEXT: retq ; ; AVX1-LABEL: test_v128i8: ; AVX1: # %bb.0: -; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm5 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm6 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm4, %xmm7, %xmm7 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] -; AVX1-NEXT: vpand %xmm4, %xmm7, %xmm7 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero -; AVX1-NEXT: vpmullw %xmm5, %xmm6, %xmm5 -; AVX1-NEXT: vpand %xmm4, %xmm5, %xmm5 -; AVX1-NEXT: vpackuswb %xmm7, %xmm5, %xmm8 -; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm6 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm9, %xmm7, %xmm7 -; AVX1-NEXT: vpand %xmm4, %xmm7, %xmm7 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; AVX1-NEXT: vpmullw %xmm6, %xmm5, %xmm5 -; AVX1-NEXT: vpand %xmm4, %xmm5, %xmm5 -; AVX1-NEXT: vpackuswb %xmm7, %xmm5, %xmm6 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm4 ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm5, %xmm7, %xmm5 -; AVX1-NEXT: vpand %xmm4, %xmm5, %xmm5 +; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm9 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm8 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm11 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm11[8],xmm0[8],xmm11[9],xmm0[9],xmm11[10],xmm0[10],xmm11[11],xmm0[11],xmm11[12],xmm0[12],xmm11[13],xmm0[13],xmm11[14],xmm0[14],xmm11[15],xmm0[15] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm7, %xmm5, %xmm10 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm7 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm10, %xmm5, %xmm10 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm10, %xmm6, %xmm6 +; AVX1-NEXT: vpmullw %xmm6, %xmm9, %xmm9 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm7 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; AVX1-NEXT: vpmullw %xmm7, %xmm5, %xmm5 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm7 = <0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u> +; AVX1-NEXT: vpshufb %xmm7, %xmm5, %xmm5 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm6 = xmm11[0],zero,xmm11[1],zero,xmm11[2],zero,xmm11[3],zero,xmm11[4],zero,xmm11[5],zero,xmm11[6],zero,xmm11[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX1-NEXT: vpmullw %xmm6, %xmm4, %xmm4 +; AVX1-NEXT: vpshufb %xmm7, %xmm4, %xmm4 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm5, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm2, %xmm5, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; AVX1-NEXT: vpshufb %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; AVX1-NEXT: vpmullw %xmm3, %xmm1, %xmm1 -; AVX1-NEXT: vpand %xmm4, %xmm1, %xmm1 -; AVX1-NEXT: vpackuswb %xmm2, %xmm1, %xmm1 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vpmullw %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpshufb %xmm7, %xmm1, %xmm1 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm1, %xmm2, %xmm1 -; AVX1-NEXT: vpand %xmm4, %xmm1, %xmm1 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero,xmm8[4],zero,xmm8[5],zero,xmm8[6],zero,xmm8[7],zero -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX1-NEXT: vpackuswb %xmm1, %xmm2, %xmm1 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vpshufb %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; AVX1-NEXT: vpmullw %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpshufb %xmm7, %xmm1, %xmm1 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX1-NEXT: vpshufb %xmm7, %xmm0, %xmm0 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm9, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm8, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 ; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm1 +; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpextrb $0, %xmm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -2998,48 +2818,37 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; ; AVX2-LABEL: test_v128i8: ; AVX2: # %bb.0: -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] ; AVX2-NEXT: vpmullw %ymm4, %ymm5, %ymm4 -; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %ymm5, %ymm4, %ymm4 -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] -; AVX2-NEXT: vpmullw %ymm2, %ymm0, %ymm0 -; AVX2-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX2-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX2-NEXT: vpmullw %ymm2, %ymm4, %ymm2 -; AVX2-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; AVX2-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX2-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm1 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] ; AVX2-NEXT: vpmullw %ymm3, %ymm1, %ymm1 -; AVX2-NEXT: vpand %ymm5, %ymm1, %ymm1 -; AVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] -; AVX2-NEXT: vpmullw %ymm2, %ymm3, %ymm2 -; AVX2-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; AVX2-NEXT: vpmullw %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] ; AVX2-NEXT: vpmullw %ymm1, %ymm0, %ymm0 -; AVX2-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX2-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX2-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -3070,18 +2879,16 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] ; AVX512BW-NEXT: vpmullw %zmm2, %zmm3, %zmm2 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BW-NEXT: vpandq %zmm3, %zmm2, %zmm2 +; AVX512BW-NEXT: vpandq %zmm3, %zmm2, %zmm4 ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BW-NEXT: vpmullw %zmm1, %zmm0, %zmm0 -; AVX512BW-NEXT: vpandq %zmm3, %zmm0, %zmm0 -; AVX512BW-NEXT: vpackuswb %zmm2, %zmm0, %zmm0 -; AVX512BW-NEXT: vextracti64x4 $1, %zmm0, %ymm1 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm2 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] +; AVX512BW-NEXT: vpandq %zmm3, %zmm0, %zmm1 +; AVX512BW-NEXT: vpackuswb %zmm4, %zmm1, %zmm1 +; AVX512BW-NEXT: vextracti64x4 $1, %zmm1, %ymm1 ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm4 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] ; AVX512BW-NEXT: vpmullw %zmm4, %zmm2, %zmm2 ; AVX512BW-NEXT: vpandq %zmm3, %zmm2, %zmm2 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BW-NEXT: vpmullw %zmm1, %zmm0, %zmm0 ; AVX512BW-NEXT: vpandq %zmm3, %zmm0, %zmm0 @@ -3090,16 +2897,15 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BW-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BW-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512BW-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512BW-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512BW-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512BW-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -3130,18 +2936,16 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] ; AVX512BWVL-NEXT: vpmullw %zmm2, %zmm3, %zmm2 ; AVX512BWVL-NEXT: vmovdqa64 {{.*#+}} zmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BWVL-NEXT: vpandq %zmm3, %zmm2, %zmm2 +; AVX512BWVL-NEXT: vpandq %zmm3, %zmm2, %zmm4 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BWVL-NEXT: vpmullw %zmm1, %zmm0, %zmm0 -; AVX512BWVL-NEXT: vpandq %zmm3, %zmm0, %zmm0 -; AVX512BWVL-NEXT: vpackuswb %zmm2, %zmm0, %zmm0 -; AVX512BWVL-NEXT: vextracti64x4 $1, %zmm0, %ymm1 -; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} zmm2 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] +; AVX512BWVL-NEXT: vpandq %zmm3, %zmm0, %zmm1 +; AVX512BWVL-NEXT: vpackuswb %zmm4, %zmm1, %zmm1 +; AVX512BWVL-NEXT: vextracti64x4 $1, %zmm1, %ymm1 ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} zmm4 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] ; AVX512BWVL-NEXT: vpmullw %zmm4, %zmm2, %zmm2 ; AVX512BWVL-NEXT: vpandq %zmm3, %zmm2, %zmm2 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BWVL-NEXT: vpmullw %zmm1, %zmm0, %zmm0 ; AVX512BWVL-NEXT: vpandq %zmm3, %zmm0, %zmm0 @@ -3150,33 +2954,25 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BWVL-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BWVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512BWVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BWVL-NEXT: vpextrb $0, %xmm0, %eax @@ -3186,48 +2982,37 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; ; AVX512DQ-LABEL: test_v128i8: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] ; AVX512DQ-NEXT: vpmullw %ymm4, %ymm5, %ymm4 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %ymm5, %ymm4, %ymm4 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] -; AVX512DQ-NEXT: vpmullw %ymm2, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQ-NEXT: vpmullw %ymm2, %ymm4, %ymm2 -; AVX512DQ-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; AVX512DQ-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQ-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm1 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] ; AVX512DQ-NEXT: vpmullw %ymm3, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpand %ymm5, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] -; AVX512DQ-NEXT: vpmullw %ymm2, %ymm3, %ymm2 -; AVX512DQ-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; AVX512DQ-NEXT: vpmullw %ymm1, %ymm2, %ymm1 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] ; AVX512DQ-NEXT: vpmullw %ymm1, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %ymm1, %ymm0, %ymm0 +; AVX512DQ-NEXT: vpand %ymm1, %ymm4, %ymm1 +; AVX512DQ-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 ; AVX512DQ-NEXT: vextracti128 $1, %ymm0, %xmm1 ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQ-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512DQ-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512DQ-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -3254,65 +3039,47 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; ; AVX512DQVL-LABEL: test_v128i8: ; AVX512DQVL: # %bb.0: -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] ; AVX512DQVL-NEXT: vpmullw %ymm4, %ymm5, %ymm4 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %ymm5, %ymm4, %ymm4 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] -; AVX512DQVL-NEXT: vpmullw %ymm2, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQVL-NEXT: vpmullw %ymm2, %ymm4, %ymm2 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; AVX512DQVL-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQVL-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm1 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] ; AVX512DQVL-NEXT: vpmullw %ymm3, %ymm1, %ymm1 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm1, %ymm1 -; AVX512DQVL-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] -; AVX512DQVL-NEXT: vpmullw %ymm2, %ymm3, %ymm2 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; AVX512DQVL-NEXT: vpmullw %ymm1, %ymm2, %ymm1 +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] ; AVX512DQVL-NEXT: vpmullw %ymm1, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} ymm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %ymm1, %ymm0, %ymm0 +; AVX512DQVL-NEXT: vpand %ymm1, %ymm4, %ymm1 +; AVX512DQVL-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 ; AVX512DQVL-NEXT: vextracti128 $1, %ymm0, %xmm1 ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512DQVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQVL-NEXT: vpextrb $0, %xmm0, %eax diff --git a/llvm/test/CodeGen/X86/vector-reduce-mul.ll b/llvm/test/CodeGen/X86/vector-reduce-mul.ll index 9bd16753332d7..662415bf1d2c5 100644 --- a/llvm/test/CodeGen/X86/vector-reduce-mul.ll +++ b/llvm/test/CodeGen/X86/vector-reduce-mul.ll @@ -1708,29 +1708,27 @@ define i8 @test_v16i8(<16 x i8> %a0) { ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; SSE2-NEXT: pmullw %xmm1, %xmm0 ; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm0 ; SSE2-NEXT: pand %xmm1, %xmm0 -; SSE2-NEXT: pxor %xmm2, %xmm2 -; SSE2-NEXT: packuswb %xmm2, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 -; SSE2-NEXT: packuswb %xmm2, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 +; SSE2-NEXT: packuswb %xmm3, %xmm0 +; SSE2-NEXT: psrldq {{.*#+}} xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm3 = xmm3[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 -; SSE2-NEXT: packuswb %xmm2, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm1, %xmm3 -; SSE2-NEXT: packuswb %xmm2, %xmm3 -; SSE2-NEXT: movd %xmm3, %eax +; SSE2-NEXT: pmullw %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; @@ -1791,8 +1789,7 @@ define i8 @test_v16i8(<16 x i8> %a0) { ; ; AVX2-LABEL: test_v16i8: ; AVX2: # %bb.0: -; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15] +; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] @@ -1924,40 +1921,32 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; SSE2-NEXT: movdqa %xmm0, %xmm3 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] ; SSE2-NEXT: pmullw %xmm2, %xmm3 -; SSE2-NEXT: movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm2, %xmm3 ; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: pmullw %xmm3, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm0 +; SSE2-NEXT: pand %xmm1, %xmm0 ; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa %xmm0, %xmm1 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; SSE2-NEXT: psrldq {{.*#+}} xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm2, %xmm0 -; SSE2-NEXT: pxor %xmm1, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm2, %xmm3 -; SSE2-NEXT: packuswb %xmm1, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm3 = xmm3[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm2, %xmm3 -; SSE2-NEXT: packuswb %xmm1, %xmm3 -; SSE2-NEXT: movdqa %xmm3, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm3 -; SSE2-NEXT: pand %xmm2, %xmm3 -; SSE2-NEXT: packuswb %xmm1, %xmm3 -; SSE2-NEXT: movd %xmm3, %eax +; SSE2-NEXT: pmullw %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 +; SSE2-NEXT: pmullw %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; @@ -1968,32 +1957,29 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; SSE41-NEXT: pmullw %xmm1, %xmm0 -; SSE41-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] -; SSE41-NEXT: pand %xmm1, %xmm0 ; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm0, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: pxor %xmm0, %xmm0 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,0,1] -; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 +; SSE41-NEXT: pshufb {{.*#+}} xmm3 = xmm3[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u] +; SSE41-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,2,3] -; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm1, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: movdqa %xmm3, %xmm0 +; SSE41-NEXT: pmullw %xmm0, %xmm2 +; SSE41-NEXT: pand %xmm1, %xmm2 +; SSE41-NEXT: pxor %xmm0, %xmm0 +; SSE41-NEXT: packuswb %xmm0, %xmm2 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,0,1] +; SSE41-NEXT: pmullw %xmm3, %xmm2 +; SSE41-NEXT: pand %xmm1, %xmm2 +; SSE41-NEXT: packuswb %xmm0, %xmm2 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] +; SSE41-NEXT: pmullw %xmm3, %xmm2 +; SSE41-NEXT: pand %xmm1, %xmm2 +; SSE41-NEXT: packuswb %xmm0, %xmm2 +; SSE41-NEXT: movdqa %xmm2, %xmm0 ; SSE41-NEXT: psrlw $8, %xmm0 -; SSE41-NEXT: pmullw %xmm3, %xmm0 +; SSE41-NEXT: pmullw %xmm2, %xmm0 ; SSE41-NEXT: pextrb $0, %xmm0, %eax ; SSE41-NEXT: # kill: def $al killed $al killed $eax ; SSE41-NEXT: retq @@ -2004,36 +1990,28 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] -; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX1-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 ; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm1 +; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpextrb $0, %xmm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -2045,16 +2023,15 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX2-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2141,16 +2118,15 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQ-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512DQ-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512DQ-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2181,33 +2157,25 @@ define i8 @test_v32i8(<32 x i8> %a0) { ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512DQVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQVL-NEXT: vpextrb $0, %xmm0, %eax @@ -2221,102 +2189,74 @@ define i8 @test_v32i8(<32 x i8> %a0) { define i8 @test_v64i8(<64 x i8> %a0) { ; SSE2-LABEL: test_v64i8: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm4, %xmm5 -; SSE2-NEXT: movdqa {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm4, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm2, %xmm0 -; SSE2-NEXT: pand %xmm4, %xmm0 -; SSE2-NEXT: packuswb %xmm5, %xmm0 -; SSE2-NEXT: movdqa %xmm3, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm3, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] ; SSE2-NEXT: movdqa %xmm1, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm5 -; SSE2-NEXT: pand %xmm4, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm3, %xmm1 -; SSE2-NEXT: pand %xmm4, %xmm1 -; SSE2-NEXT: packuswb %xmm5, %xmm1 -; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3],xmm5[4],xmm0[4],xmm5[5],xmm0[5],xmm5[6],xmm0[6],xmm5[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm4, %xmm5 +; SSE2-NEXT: movdqa %xmm2, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; SSE2-NEXT: movdqa %xmm0, %xmm6 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3],xmm6[4],xmm0[4],xmm6[5],xmm0[5],xmm6[6],xmm0[6],xmm6[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm4, %xmm6 +; SSE2-NEXT: pmullw %xmm5, %xmm6 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm3 -; SSE2-NEXT: pand %xmm4, %xmm3 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm4, %xmm0 -; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa %xmm0, %xmm1 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pmullw %xmm3, %xmm1 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE2-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: pmullw %xmm2, %xmm0 ; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm4, %xmm0 -; SSE2-NEXT: pxor %xmm1, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pmullw %xmm6, %xmm0 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm4, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 ; SSE2-NEXT: movdqa %xmm2, %xmm0 +; SSE2-NEXT: pand %xmm1, %xmm0 +; SSE2-NEXT: packuswb %xmm3, %xmm0 +; SSE2-NEXT: psrldq {{.*#+}} xmm0 = xmm0[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm2 = xmm2[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm4, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 ; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm4, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 ; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; ; SSE41-LABEL: test_v64i8: ; SSE41: # %bb.0: -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; SSE41-NEXT: pmullw %xmm2, %xmm0 -; SSE41-NEXT: movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] -; SSE41-NEXT: pand %xmm2, %xmm0 -; SSE41-NEXT: pmullw %xmm5, %xmm4 -; SSE41-NEXT: pand %xmm2, %xmm4 -; SSE41-NEXT: packuswb %xmm0, %xmm4 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; SSE41-NEXT: pmullw %xmm3, %xmm1 -; SSE41-NEXT: pand %xmm2, %xmm1 -; SSE41-NEXT: pmullw %xmm0, %xmm5 -; SSE41-NEXT: pand %xmm2, %xmm5 -; SSE41-NEXT: packuswb %xmm1, %xmm5 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE41-NEXT: pmullw %xmm2, %xmm0 +; SSE41-NEXT: pmullw %xmm1, %xmm0 +; SSE41-NEXT: pmullw %xmm3, %xmm6 +; SSE41-NEXT: movdqa {{.*#+}} xmm1 = <0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u> +; SSE41-NEXT: pshufb %xmm1, %xmm6 +; SSE41-NEXT: pmullw %xmm4, %xmm5 +; SSE41-NEXT: pshufb %xmm1, %xmm5 +; SSE41-NEXT: movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmullw %xmm3, %xmm4 +; SSE41-NEXT: pshufb %xmm1, %xmm4 ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm5, %xmm4 -; SSE41-NEXT: pand %xmm2, %xmm4 -; SSE41-NEXT: pmullw %xmm0, %xmm1 -; SSE41-NEXT: pand %xmm2, %xmm1 -; SSE41-NEXT: packuswb %xmm4, %xmm1 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; SSE41-NEXT: pmullw %xmm0, %xmm1 ; SSE41-NEXT: pand %xmm2, %xmm1 ; SSE41-NEXT: pxor %xmm0, %xmm0 @@ -2342,59 +2282,42 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; ; AVX1-LABEL: test_v64i8: ; AVX1: # %bb.0: -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm3 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] -; AVX1-NEXT: vpand %xmm2, %xmm3, %xmm3 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm4 -; AVX1-NEXT: vpand %xmm2, %xmm4, %xmm4 -; AVX1-NEXT: vpackuswb %xmm3, %xmm4, %xmm3 -; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm3, %xmm5, %xmm3 ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm4 -; AVX1-NEXT: vpand %xmm2, %xmm4, %xmm4 +; AVX1-NEXT: vpmullw %xmm3, %xmm5, %xmm3 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX1-NEXT: vpmullw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand {{.*}}(%rip), %xmm2, %xmm2 +; AVX1-NEXT: vpmullw %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpmullw %xmm3, %xmm1, %xmm1 ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm1, %xmm4, %xmm1 -; AVX1-NEXT: vpand %xmm2, %xmm1, %xmm1 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 ; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] -; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] -; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm3 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm3, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm1 +; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpextrb $0, %xmm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -2416,16 +2339,15 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX2-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2467,16 +2389,15 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BW-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BW-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512BW-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512BW-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512BW-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512BW-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2518,33 +2439,25 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BWVL-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BWVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512BWVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BWVL-NEXT: vpextrb $0, %xmm0, %eax @@ -2568,16 +2481,15 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQ-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512DQ-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512DQ-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -2618,33 +2530,25 @@ define i8 @test_v64i8(<64 x i8> %a0) { ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512DQVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQVL-NEXT: vpextrb $0, %xmm0, %eax @@ -2658,298 +2562,201 @@ define i8 @test_v64i8(<64 x i8> %a0) { define i8 @test_v128i8(<128 x i8> %a0) { ; SSE2-LABEL: test_v128i8: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa %xmm5, %xmm8 +; SSE2-NEXT: movdqa %xmm6, %xmm8 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm1, %xmm9 +; SSE2-NEXT: movdqa %xmm2, %xmm9 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm0[8],xmm9[9],xmm0[9],xmm9[10],xmm0[10],xmm9[11],xmm0[11],xmm9[12],xmm0[12],xmm9[13],xmm0[13],xmm9[14],xmm0[14],xmm9[15],xmm0[15] ; SSE2-NEXT: pmullw %xmm8, %xmm9 -; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [255,255,255,255,255,255,255,255] -; SSE2-NEXT: pand %xmm8, %xmm9 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3],xmm5[4],xmm0[4],xmm5[5],xmm0[5],xmm5[6],xmm0[6],xmm5[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm5, %xmm1 -; SSE2-NEXT: pand %xmm8, %xmm1 -; SSE2-NEXT: packuswb %xmm9, %xmm1 -; SSE2-NEXT: movdqa %xmm7, %xmm9 +; SSE2-NEXT: movdqa %xmm4, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm0, %xmm10 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm0[8],xmm10[9],xmm0[9],xmm10[10],xmm0[10],xmm10[11],xmm0[11],xmm10[12],xmm0[12],xmm10[13],xmm0[13],xmm10[14],xmm0[14],xmm10[15],xmm0[15] +; SSE2-NEXT: pmullw %xmm8, %xmm10 +; SSE2-NEXT: pmullw %xmm9, %xmm10 +; SSE2-NEXT: movdqa %xmm7, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm3, %xmm9 ; SSE2-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm0[8],xmm9[9],xmm0[9],xmm9[10],xmm0[10],xmm9[11],xmm0[11],xmm9[12],xmm0[12],xmm9[13],xmm0[13],xmm9[14],xmm0[14],xmm9[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm3, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm9, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm0[0],xmm7[1],xmm0[1],xmm7[2],xmm0[2],xmm7[3],xmm0[3],xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm7, %xmm3 -; SSE2-NEXT: pand %xmm8, %xmm3 -; SSE2-NEXT: packuswb %xmm5, %xmm3 -; SSE2-NEXT: movdqa %xmm4, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm7 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm5, %xmm7 -; SSE2-NEXT: pand %xmm8, %xmm7 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm4, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: packuswb %xmm7, %xmm0 -; SSE2-NEXT: movdqa %xmm6, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm2, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm4, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 +; SSE2-NEXT: pmullw %xmm8, %xmm9 +; SSE2-NEXT: movdqa %xmm5, %xmm11 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm11 = xmm11[8],xmm0[8],xmm11[9],xmm0[9],xmm11[10],xmm0[10],xmm11[11],xmm0[11],xmm11[12],xmm0[12],xmm11[13],xmm0[13],xmm11[14],xmm0[14],xmm11[15],xmm0[15] +; SSE2-NEXT: movdqa %xmm1, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: pmullw %xmm11, %xmm8 +; SSE2-NEXT: pmullw %xmm9, %xmm8 +; SSE2-NEXT: pmullw %xmm10, %xmm8 ; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3],xmm6[4],xmm0[4],xmm6[5],xmm0[5],xmm6[6],xmm0[6],xmm6[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; SSE2-NEXT: pmullw %xmm6, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm5, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm5 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm4, %xmm5 -; SSE2-NEXT: pand %xmm8, %xmm5 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1],xmm4[2],xmm0[2],xmm4[3],xmm0[3],xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pmullw %xmm4, %xmm0 ; SSE2-NEXT: pmullw %xmm2, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: packuswb %xmm5, %xmm0 -; SSE2-NEXT: movdqa %xmm3, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm1, %xmm4 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm4 -; SSE2-NEXT: pand %xmm8, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm0[0],xmm7[1],xmm0[1],xmm7[2],xmm0[2],xmm7[3],xmm0[3],xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm7, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3],xmm5[4],xmm0[4],xmm5[5],xmm0[5],xmm5[6],xmm0[6],xmm5[7],xmm0[7] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm5, %xmm1 ; SSE2-NEXT: pmullw %xmm3, %xmm1 -; SSE2-NEXT: pand %xmm8, %xmm1 -; SSE2-NEXT: packuswb %xmm4, %xmm1 +; SSE2-NEXT: pmullw %xmm0, %xmm1 +; SSE2-NEXT: pmullw %xmm8, %xmm1 +; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [255,255,255,255,255,255,255,255] ; SSE2-NEXT: movdqa %xmm1, %xmm2 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE2-NEXT: movdqa %xmm0, %xmm3 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE2-NEXT: pmullw %xmm2, %xmm3 -; SSE2-NEXT: pand %xmm8, %xmm3 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: packuswb %xmm3, %xmm0 -; SSE2-NEXT: movdqa %xmm0, %xmm1 -; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: pmullw %xmm1, %xmm0 -; SSE2-NEXT: pand %xmm8, %xmm0 -; SSE2-NEXT: pxor %xmm1, %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,2,3,3] -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE2-NEXT: pand %xmm0, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,2,3,3] ; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE2-NEXT: psrldq {{.*#+}} xmm2 = xmm2[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 -; SSE2-NEXT: movdqa %xmm2, %xmm0 -; SSE2-NEXT: psrlw $8, %xmm0 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] -; SSE2-NEXT: pmullw %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm8, %xmm2 -; SSE2-NEXT: packuswb %xmm1, %xmm2 +; SSE2-NEXT: pmullw %xmm1, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm1 +; SSE2-NEXT: pand %xmm0, %xmm1 +; SSE2-NEXT: packuswb %xmm3, %xmm1 +; SSE2-NEXT: psrldq {{.*#+}} xmm1 = xmm1[2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero,zero +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; SSE2-NEXT: pmullw %xmm2, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: pand %xmm0, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 +; SSE2-NEXT: psrlw $8, %xmm2 +; SSE2-NEXT: pmullw %xmm1, %xmm2 +; SSE2-NEXT: pand %xmm0, %xmm2 +; SSE2-NEXT: packuswb %xmm3, %xmm2 ; SSE2-NEXT: movd %xmm2, %eax ; SSE2-NEXT: # kill: def $al killed $al killed $eax ; SSE2-NEXT: retq ; ; SSE41-LABEL: test_v128i8: ; SSE41: # %bb.0: -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm8 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm5, %xmm1 -; SSE41-NEXT: movdqa {{.*#+}} xmm5 = [255,255,255,255,255,255,255,255] -; SSE41-NEXT: pand %xmm5, %xmm1 -; SSE41-NEXT: pmullw %xmm9, %xmm8 -; SSE41-NEXT: pand %xmm5, %xmm8 -; SSE41-NEXT: packuswb %xmm1, %xmm8 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm7, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 -; SSE41-NEXT: pmullw %xmm9, %xmm1 -; SSE41-NEXT: pand %xmm5, %xmm1 -; SSE41-NEXT: packuswb %xmm3, %xmm1 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm7 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; SSE41-NEXT: pmullw %xmm4, %xmm0 -; SSE41-NEXT: pand %xmm5, %xmm0 -; SSE41-NEXT: pmullw %xmm7, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 -; SSE41-NEXT: packuswb %xmm0, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm8 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm9 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] ; SSE41-NEXT: pmullw %xmm6, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: pmullw %xmm0, %xmm4 -; SSE41-NEXT: pand %xmm5, %xmm4 -; SSE41-NEXT: packuswb %xmm2, %xmm4 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm10 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm4, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE41-NEXT: pmullw %xmm4, %xmm0 ; SSE41-NEXT: pmullw %xmm2, %xmm0 -; SSE41-NEXT: pand %xmm5, %xmm0 -; SSE41-NEXT: packuswb %xmm3, %xmm0 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm11 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; SSE41-NEXT: pmullw %xmm7, %xmm3 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm7 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; SSE41-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; SSE41-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero,xmm8[4],zero,xmm8[5],zero,xmm8[6],zero,xmm8[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm1, %xmm8 -; SSE41-NEXT: pand %xmm5, %xmm8 -; SSE41-NEXT: pmullw %xmm2, %xmm3 -; SSE41-NEXT: pand %xmm5, %xmm3 -; SSE41-NEXT: packuswb %xmm8, %xmm3 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; SSE41-NEXT: pmullw %xmm5, %xmm1 +; SSE41-NEXT: pmullw %xmm3, %xmm1 +; SSE41-NEXT: pmullw %xmm0, %xmm1 +; SSE41-NEXT: pmullw %xmm7, %xmm2 +; SSE41-NEXT: movdqa {{.*#+}} xmm0 = <0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u> +; SSE41-NEXT: pshufb %xmm0, %xmm2 +; SSE41-NEXT: pmullw %xmm11, %xmm4 +; SSE41-NEXT: pshufb %xmm0, %xmm4 +; SSE41-NEXT: pmullw %xmm10, %xmm6 +; SSE41-NEXT: pshufb %xmm0, %xmm6 +; SSE41-NEXT: pmullw %xmm8, %xmm9 +; SSE41-NEXT: pshufb %xmm0, %xmm9 +; SSE41-NEXT: movdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm5 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero,xmm9[4],zero,xmm9[5],zero,xmm9[6],zero,xmm9[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmullw %xmm5, %xmm6 +; SSE41-NEXT: pshufb %xmm0, %xmm6 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: pmullw %xmm4, %xmm2 +; SSE41-NEXT: pshufb %xmm0, %xmm2 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE41-NEXT: pmullw %xmm2, %xmm4 +; SSE41-NEXT: pshufb %xmm0, %xmm4 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE41-NEXT: pmullw %xmm1, %xmm0 +; SSE41-NEXT: pand %xmm3, %xmm0 +; SSE41-NEXT: pxor %xmm1, %xmm1 +; SSE41-NEXT: packuswb %xmm1, %xmm0 ; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; SSE41-NEXT: pmullw %xmm3, %xmm0 -; SSE41-NEXT: pand %xmm5, %xmm0 -; SSE41-NEXT: pmullw %xmm1, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; SSE41-NEXT: pmullw %xmm0, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: pxor %xmm0, %xmm0 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,0,1] -; SSE41-NEXT: pmullw %xmm1, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero -; SSE41-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] -; SSE41-NEXT: pmullw %xmm1, %xmm2 -; SSE41-NEXT: pand %xmm5, %xmm2 -; SSE41-NEXT: packuswb %xmm0, %xmm2 -; SSE41-NEXT: movdqa %xmm2, %xmm0 -; SSE41-NEXT: psrlw $8, %xmm0 +; SSE41-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] ; SSE41-NEXT: pmullw %xmm2, %xmm0 -; SSE41-NEXT: pextrb $0, %xmm0, %eax +; SSE41-NEXT: pand %xmm3, %xmm0 +; SSE41-NEXT: packuswb %xmm1, %xmm0 +; SSE41-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE41-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] +; SSE41-NEXT: pmullw %xmm2, %xmm0 +; SSE41-NEXT: pand %xmm3, %xmm0 +; SSE41-NEXT: packuswb %xmm1, %xmm0 +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: psrlw $8, %xmm1 +; SSE41-NEXT: pmullw %xmm0, %xmm1 +; SSE41-NEXT: pextrb $0, %xmm1, %eax ; SSE41-NEXT: # kill: def $al killed $al killed $eax ; SSE41-NEXT: retq ; ; AVX1-LABEL: test_v128i8: ; AVX1: # %bb.0: -; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm5 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm6 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm4, %xmm7, %xmm7 -; AVX1-NEXT: vmovdqa {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] -; AVX1-NEXT: vpand %xmm4, %xmm7, %xmm7 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero -; AVX1-NEXT: vpmullw %xmm5, %xmm6, %xmm5 -; AVX1-NEXT: vpand %xmm4, %xmm5, %xmm5 -; AVX1-NEXT: vpackuswb %xmm7, %xmm5, %xmm8 -; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm6 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm9, %xmm7, %xmm7 -; AVX1-NEXT: vpand %xmm4, %xmm7, %xmm7 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero -; AVX1-NEXT: vpmullw %xmm6, %xmm5, %xmm5 -; AVX1-NEXT: vpand %xmm4, %xmm5, %xmm5 -; AVX1-NEXT: vpackuswb %xmm7, %xmm5, %xmm6 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm4 ; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm5, %xmm7, %xmm5 -; AVX1-NEXT: vpand %xmm4, %xmm5, %xmm5 +; AVX1-NEXT: vpmullw %xmm4, %xmm5, %xmm8 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm11 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm11[8],xmm0[8],xmm11[9],xmm0[9],xmm11[10],xmm0[10],xmm11[11],xmm0[11],xmm11[12],xmm0[12],xmm11[13],xmm0[13],xmm11[14],xmm0[14],xmm11[15],xmm0[15] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm7, %xmm5, %xmm10 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm7 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm10, %xmm5, %xmm10 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; AVX1-NEXT: vpmullw %xmm10, %xmm6, %xmm6 +; AVX1-NEXT: vpmullw %xmm6, %xmm8, %xmm6 +; AVX1-NEXT: vpmullw %xmm6, %xmm9, %xmm6 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm7 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; AVX1-NEXT: vpmullw %xmm7, %xmm5, %xmm5 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm7 = xmm11[0],zero,xmm11[1],zero,xmm11[2],zero,xmm11[3],zero,xmm11[4],zero,xmm11[5],zero,xmm11[6],zero,xmm11[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX1-NEXT: vpmullw %xmm7, %xmm4, %xmm4 ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm5, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm2, %xmm5, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero ; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX1-NEXT: vpmullw %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vmovdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm4, %xmm3 +; AVX1-NEXT: vpand %xmm2, %xmm5, %xmm4 +; AVX1-NEXT: vpmullw %xmm3, %xmm4, %xmm3 +; AVX1-NEXT: vpand %xmm2, %xmm3, %xmm3 ; AVX1-NEXT: vpmullw %xmm3, %xmm1, %xmm1 -; AVX1-NEXT: vpand %xmm4, %xmm1, %xmm1 -; AVX1-NEXT: vpackuswb %xmm2, %xmm1, %xmm1 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm6[8],xmm0[8],xmm6[9],xmm0[9],xmm6[10],xmm0[10],xmm6[11],xmm0[11],xmm6[12],xmm0[12],xmm6[13],xmm0[13],xmm6[14],xmm0[14],xmm6[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] -; AVX1-NEXT: vpmullw %xmm1, %xmm2, %xmm1 -; AVX1-NEXT: vpand %xmm4, %xmm1, %xmm1 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero,xmm8[4],zero,xmm8[5],zero,xmm8[6],zero,xmm8[7],zero -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX1-NEXT: vpackuswb %xmm1, %xmm2, %xmm1 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmullw %xmm6, %xmm1, %xmm1 ; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 ; AVX1-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,0,1] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX1-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,2,3] -; AVX1-NEXT: vpmullw %xmm0, %xmm2, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 -; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm2 -; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX1-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpmullw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 ; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm1 +; AVX1-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vpextrb $0, %xmm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -2957,48 +2764,37 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; ; AVX2-LABEL: test_v128i8: ; AVX2: # %bb.0: -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] ; AVX2-NEXT: vpmullw %ymm4, %ymm5, %ymm4 -; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %ymm5, %ymm4, %ymm4 -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] -; AVX2-NEXT: vpmullw %ymm2, %ymm0, %ymm0 -; AVX2-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX2-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX2-NEXT: vpmullw %ymm2, %ymm4, %ymm2 -; AVX2-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; AVX2-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX2-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm1 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] ; AVX2-NEXT: vpmullw %ymm3, %ymm1, %ymm1 -; AVX2-NEXT: vpand %ymm5, %ymm1, %ymm1 -; AVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] -; AVX2-NEXT: vpmullw %ymm2, %ymm3, %ymm2 -; AVX2-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX2-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; AVX2-NEXT: vpmullw %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] ; AVX2-NEXT: vpmullw %ymm1, %ymm0, %ymm0 -; AVX2-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX2-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX2-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX2-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX2-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX2-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX2-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX2-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX2-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX2-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX2-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -3029,18 +2825,16 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] ; AVX512BW-NEXT: vpmullw %zmm2, %zmm3, %zmm2 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BW-NEXT: vpandq %zmm3, %zmm2, %zmm2 +; AVX512BW-NEXT: vpandq %zmm3, %zmm2, %zmm4 ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BW-NEXT: vpmullw %zmm1, %zmm0, %zmm0 -; AVX512BW-NEXT: vpandq %zmm3, %zmm0, %zmm0 -; AVX512BW-NEXT: vpackuswb %zmm2, %zmm0, %zmm0 -; AVX512BW-NEXT: vextracti64x4 $1, %zmm0, %ymm1 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm2 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] +; AVX512BW-NEXT: vpandq %zmm3, %zmm0, %zmm1 +; AVX512BW-NEXT: vpackuswb %zmm4, %zmm1, %zmm1 +; AVX512BW-NEXT: vextracti64x4 $1, %zmm1, %ymm1 ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} zmm4 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] ; AVX512BW-NEXT: vpmullw %zmm4, %zmm2, %zmm2 ; AVX512BW-NEXT: vpandq %zmm3, %zmm2, %zmm2 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BW-NEXT: vpmullw %zmm1, %zmm0, %zmm0 ; AVX512BW-NEXT: vpandq %zmm3, %zmm0, %zmm0 @@ -3049,16 +2843,15 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BW-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512BW-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BW-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512BW-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512BW-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512BW-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512BW-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512BW-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512BW-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512BW-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -3089,18 +2882,16 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} zmm3 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] ; AVX512BWVL-NEXT: vpmullw %zmm2, %zmm3, %zmm2 ; AVX512BWVL-NEXT: vmovdqa64 {{.*#+}} zmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BWVL-NEXT: vpandq %zmm3, %zmm2, %zmm2 +; AVX512BWVL-NEXT: vpandq %zmm3, %zmm2, %zmm4 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BWVL-NEXT: vpmullw %zmm1, %zmm0, %zmm0 -; AVX512BWVL-NEXT: vpandq %zmm3, %zmm0, %zmm0 -; AVX512BWVL-NEXT: vpackuswb %zmm2, %zmm0, %zmm0 -; AVX512BWVL-NEXT: vextracti64x4 $1, %zmm0, %ymm1 -; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} zmm2 = zmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63,63] +; AVX512BWVL-NEXT: vpandq %zmm3, %zmm0, %zmm1 +; AVX512BWVL-NEXT: vpackuswb %zmm4, %zmm1, %zmm1 +; AVX512BWVL-NEXT: vextracti64x4 $1, %zmm1, %ymm1 ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} zmm4 = zmm1[8],zmm0[8],zmm1[9],zmm0[9],zmm1[10],zmm0[10],zmm1[11],zmm0[11],zmm1[12],zmm0[12],zmm1[13],zmm0[13],zmm1[14],zmm0[14],zmm1[15],zmm0[15],zmm1[24],zmm0[24],zmm1[25],zmm0[25],zmm1[26],zmm0[26],zmm1[27],zmm0[27],zmm1[28],zmm0[28],zmm1[29],zmm0[29],zmm1[30],zmm0[30],zmm1[31],zmm0[31],zmm1[40],zmm0[40],zmm1[41],zmm0[41],zmm1[42],zmm0[42],zmm1[43],zmm0[43],zmm1[44],zmm0[44],zmm1[45],zmm0[45],zmm1[46],zmm0[46],zmm1[47],zmm0[47],zmm1[56],zmm0[56],zmm1[57],zmm0[57],zmm1[58],zmm0[58],zmm1[59],zmm0[59],zmm1[60],zmm0[60],zmm1[61],zmm0[61],zmm1[62],zmm0[62],zmm1[63],zmm0[63] ; AVX512BWVL-NEXT: vpmullw %zmm4, %zmm2, %zmm2 ; AVX512BWVL-NEXT: vpandq %zmm3, %zmm2, %zmm2 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm0 = zmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55,55] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} zmm1 = zmm1[0],zmm0[0],zmm1[1],zmm0[1],zmm1[2],zmm0[2],zmm1[3],zmm0[3],zmm1[4],zmm0[4],zmm1[5],zmm0[5],zmm1[6],zmm0[6],zmm1[7],zmm0[7],zmm1[16],zmm0[16],zmm1[17],zmm0[17],zmm1[18],zmm0[18],zmm1[19],zmm0[19],zmm1[20],zmm0[20],zmm1[21],zmm0[21],zmm1[22],zmm0[22],zmm1[23],zmm0[23],zmm1[32],zmm0[32],zmm1[33],zmm0[33],zmm1[34],zmm0[34],zmm1[35],zmm0[35],zmm1[36],zmm0[36],zmm1[37],zmm0[37],zmm1[38],zmm0[38],zmm1[39],zmm0[39],zmm1[48],zmm0[48],zmm1[49],zmm0[49],zmm1[50],zmm0[50],zmm1[51],zmm0[51],zmm1[52],zmm0[52],zmm1[53],zmm0[53],zmm1[54],zmm0[54],zmm1[55],zmm0[55] ; AVX512BWVL-NEXT: vpmullw %zmm1, %zmm0, %zmm0 ; AVX512BWVL-NEXT: vpandq %zmm3, %zmm0, %zmm0 @@ -3109,33 +2900,25 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512BWVL-NEXT: vpmullw %xmm3, %xmm2, %xmm2 -; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512BWVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512BWVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512BWVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512BWVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512BWVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512BWVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512BWVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512BWVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512BWVL-NEXT: vpextrb $0, %xmm0, %eax @@ -3145,48 +2928,37 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; ; AVX512DQ-LABEL: test_v128i8: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] ; AVX512DQ-NEXT: vpmullw %ymm4, %ymm5, %ymm4 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %ymm5, %ymm4, %ymm4 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] -; AVX512DQ-NEXT: vpmullw %ymm2, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQ-NEXT: vpmullw %ymm2, %ymm4, %ymm2 -; AVX512DQ-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; AVX512DQ-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQ-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm1 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] ; AVX512DQ-NEXT: vpmullw %ymm3, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpand %ymm5, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] -; AVX512DQ-NEXT: vpmullw %ymm2, %ymm3, %ymm2 -; AVX512DQ-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; AVX512DQ-NEXT: vpmullw %ymm1, %ymm2, %ymm1 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] ; AVX512DQ-NEXT: vpmullw %ymm1, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQ-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %ymm1, %ymm0, %ymm0 +; AVX512DQ-NEXT: vpand %ymm1, %ymm4, %ymm1 +; AVX512DQ-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 ; AVX512DQ-NEXT: vextracti128 $1, %ymm0, %xmm1 ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQ-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255] +; AVX512DQ-NEXT: vpand %xmm3, %xmm2, %xmm4 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero ; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; AVX512DQ-NEXT: vpackuswb %xmm4, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero -; AVX512DQ-NEXT: vpmullw %xmm1, %xmm0, %xmm0 +; AVX512DQ-NEXT: vpmullw %xmm2, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpand %xmm3, %xmm0, %xmm0 ; AVX512DQ-NEXT: vpxor %xmm1, %xmm1, %xmm1 ; AVX512DQ-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 @@ -3213,65 +2985,47 @@ define i8 @test_v128i8(<128 x i8> %a0) { ; ; AVX512DQVL-LABEL: test_v128i8: ; AVX512DQVL: # %bb.0: -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm5 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] ; AVX512DQVL-NEXT: vpmullw %ymm4, %ymm5, %ymm4 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %ymm5, %ymm4, %ymm4 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] -; AVX512DQVL-NEXT: vpmullw %ymm2, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpackuswb %ymm4, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm4 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQVL-NEXT: vpmullw %ymm2, %ymm4, %ymm2 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm0[0],ymm3[1],ymm0[1],ymm3[2],ymm0[2],ymm3[3],ymm0[3],ymm3[4],ymm0[4],ymm3[5],ymm0[5],ymm3[6],ymm0[6],ymm3[7],ymm0[7],ymm3[16],ymm0[16],ymm3[17],ymm0[17],ymm3[18],ymm0[18],ymm3[19],ymm0[19],ymm3[20],ymm0[20],ymm3[21],ymm0[21],ymm3[22],ymm0[22],ymm3[23],ymm0[23] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm2[0],ymm0[0],ymm2[1],ymm0[1],ymm2[2],ymm0[2],ymm2[3],ymm0[3],ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[16],ymm0[16],ymm2[17],ymm0[17],ymm2[18],ymm0[18],ymm2[19],ymm0[19],ymm2[20],ymm0[20],ymm2[21],ymm0[21],ymm2[22],ymm0[22],ymm2[23],ymm0[23] +; AVX512DQVL-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQVL-NEXT: vpmullw %ymm4, %ymm5, %ymm4 +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm3[8],ymm0[8],ymm3[9],ymm0[9],ymm3[10],ymm0[10],ymm3[11],ymm0[11],ymm3[12],ymm0[12],ymm3[13],ymm0[13],ymm3[14],ymm0[14],ymm3[15],ymm0[15],ymm3[24],ymm0[24],ymm3[25],ymm0[25],ymm3[26],ymm0[26],ymm3[27],ymm0[27],ymm3[28],ymm0[28],ymm3[29],ymm0[29],ymm3[30],ymm0[30],ymm3[31],ymm0[31] +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm1 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] ; AVX512DQVL-NEXT: vpmullw %ymm3, %ymm1, %ymm1 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm1, %ymm1 -; AVX512DQVL-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm1[8],ymm0[8],ymm1[9],ymm0[9],ymm1[10],ymm0[10],ymm1[11],ymm0[11],ymm1[12],ymm0[12],ymm1[13],ymm0[13],ymm1[14],ymm0[14],ymm1[15],ymm0[15],ymm1[24],ymm0[24],ymm1[25],ymm0[25],ymm1[26],ymm0[26],ymm1[27],ymm0[27],ymm1[28],ymm0[28],ymm1[29],ymm0[29],ymm1[30],ymm0[30],ymm1[31],ymm0[31] -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm3 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] -; AVX512DQVL-NEXT: vpmullw %ymm2, %ymm3, %ymm2 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm2, %ymm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm1 = ymm1[0],ymm0[0],ymm1[1],ymm0[1],ymm1[2],ymm0[2],ymm1[3],ymm0[3],ymm1[4],ymm0[4],ymm1[5],ymm0[5],ymm1[6],ymm0[6],ymm1[7],ymm0[7],ymm1[16],ymm0[16],ymm1[17],ymm0[17],ymm1[18],ymm0[18],ymm1[19],ymm0[19],ymm1[20],ymm0[20],ymm1[21],ymm0[21],ymm1[22],ymm0[22],ymm1[23],ymm0[23] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23] +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm2 = ymm2[8],ymm0[8],ymm2[9],ymm0[9],ymm2[10],ymm0[10],ymm2[11],ymm0[11],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15],ymm2[24],ymm0[24],ymm2[25],ymm0[25],ymm2[26],ymm0[26],ymm2[27],ymm0[27],ymm2[28],ymm0[28],ymm2[29],ymm0[29],ymm2[30],ymm0[30],ymm2[31],ymm0[31] +; AVX512DQVL-NEXT: vpmullw %ymm1, %ymm2, %ymm1 +; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31] ; AVX512DQVL-NEXT: vpmullw %ymm1, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpand %ymm5, %ymm0, %ymm0 -; AVX512DQVL-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} ymm1 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %ymm1, %ymm0, %ymm0 +; AVX512DQVL-NEXT: vpand %ymm1, %ymm4, %ymm1 +; AVX512DQVL-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 ; AVX512DQVL-NEXT: vextracti128 $1, %ymm0, %xmm1 ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] ; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm3, %xmm2 -; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm3 = [255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] -; AVX512DQVL-NEXT: vpand %xmm3, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] +; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm0[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] -; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[1,1,2,3] -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[1,1,2,3] ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrld $16, %xmm0, %xmm2 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpsrld $16, %xmm2, %xmm2 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm2, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpand %xmm3, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 -; AVX512DQVL-NEXT: vpsrlw $8, %xmm0, %xmm1 -; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7] +; AVX512DQVL-NEXT: vpand %xmm1, %xmm0, %xmm1 +; AVX512DQVL-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX512DQVL-NEXT: vpsrlw $8, %xmm1, %xmm1 ; AVX512DQVL-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3],xmm1[4],xmm0[4],xmm1[5],xmm0[5],xmm1[6],xmm0[6],xmm1[7],xmm0[7] ; AVX512DQVL-NEXT: vpmullw %xmm1, %xmm0, %xmm0 ; AVX512DQVL-NEXT: vpextrb $0, %xmm0, %eax diff --git a/llvm/test/CodeGen/X86/vector-shift-lshr-sub128.ll b/llvm/test/CodeGen/X86/vector-shift-lshr-sub128.ll index fc3bb0350afa7..546f723e68be6 100644 --- a/llvm/test/CodeGen/X86/vector-shift-lshr-sub128.ll +++ b/llvm/test/CodeGen/X86/vector-shift-lshr-sub128.ll @@ -339,9 +339,7 @@ define <8 x i8> @var_shift_v8i8(<8 x i8> %a, <8 x i8> %b) nounwind { ; SSE2-LABEL: var_shift_v8i8: ; SSE2: # %bb.0: ; SSE2-NEXT: movdqa %xmm0, %xmm2 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: pand %xmm0, %xmm1 +; SSE2-NEXT: pand {{.*}}(%rip), %xmm2 ; SSE2-NEXT: psllw $12, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm0 ; SSE2-NEXT: psraw $15, %xmm0 @@ -505,9 +503,7 @@ define <8 x i8> @var_shift_v8i8(<8 x i8> %a, <8 x i8> %b) nounwind { ; X32-SSE-LABEL: var_shift_v8i8: ; X32-SSE: # %bb.0: ; X32-SSE-NEXT: movdqa %xmm0, %xmm2 -; X32-SSE-NEXT: movdqa {{.*#+}} xmm0 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] -; X32-SSE-NEXT: pand %xmm0, %xmm2 -; X32-SSE-NEXT: pand %xmm0, %xmm1 +; X32-SSE-NEXT: pand {{\.LCPI.*}}, %xmm2 ; X32-SSE-NEXT: psllw $12, %xmm1 ; X32-SSE-NEXT: movdqa %xmm1, %xmm0 ; X32-SSE-NEXT: psraw $15, %xmm0 @@ -1122,11 +1118,9 @@ define <8 x i8> @splatvar_shift_v8i8(<8 x i8> %a, <8 x i8> %b) nounwind { ; SSE2-LABEL: splatvar_shift_v8i8: ; SSE2: # %bb.0: ; SSE2-NEXT: movdqa %xmm0, %xmm2 -; SSE2-NEXT: movdqa {{.*#+}} xmm0 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] -; SSE2-NEXT: pand %xmm0, %xmm2 -; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,0,2,3,4,5,6,7] -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,0,0,0] -; SSE2-NEXT: pand %xmm0, %xmm1 +; SSE2-NEXT: pand {{.*}}(%rip), %xmm2 +; SSE2-NEXT: pshuflw {{.*#+}} xmm0 = xmm1[0,0,2,3,4,5,6,7] +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[0,0,0,0] ; SSE2-NEXT: psllw $12, %xmm1 ; SSE2-NEXT: movdqa %xmm1, %xmm0 ; SSE2-NEXT: psraw $15, %xmm0 @@ -1287,11 +1281,9 @@ define <8 x i8> @splatvar_shift_v8i8(<8 x i8> %a, <8 x i8> %b) nounwind { ; X32-SSE-LABEL: splatvar_shift_v8i8: ; X32-SSE: # %bb.0: ; X32-SSE-NEXT: movdqa %xmm0, %xmm2 -; X32-SSE-NEXT: movdqa {{.*#+}} xmm0 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] -; X32-SSE-NEXT: pand %xmm0, %xmm2 -; X32-SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,0,2,3,4,5,6,7] -; X32-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,0,0,0] -; X32-SSE-NEXT: pand %xmm0, %xmm1 +; X32-SSE-NEXT: pand {{\.LCPI.*}}, %xmm2 +; X32-SSE-NEXT: pshuflw {{.*#+}} xmm0 = xmm1[0,0,2,3,4,5,6,7] +; X32-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm0[0,0,0,0] ; X32-SSE-NEXT: psllw $12, %xmm1 ; X32-SSE-NEXT: movdqa %xmm1, %xmm0 ; X32-SSE-NEXT: psraw $15, %xmm0 diff --git a/llvm/test/CodeGen/X86/vector-zext.ll b/llvm/test/CodeGen/X86/vector-zext.ll index da6923c2b83a8..7403eb5b81e42 100644 --- a/llvm/test/CodeGen/X86/vector-zext.ll +++ b/llvm/test/CodeGen/X86/vector-zext.ll @@ -1660,9 +1660,7 @@ define <8 x i32> @shuf_zext_8i8_to_8i32(<8 x i8> %A) { ; SSE2: # %bb.0: # %entry ; SSE2-NEXT: movdqa %xmm0, %xmm1 ; SSE2-NEXT: pand {{.*}}(%rip), %xmm1 -; SSE2-NEXT: packuswb %xmm1, %xmm1 ; SSE2-NEXT: pxor %xmm2, %xmm2 -; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7] ; SSE2-NEXT: movdqa %xmm1, %xmm0 ; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3] ; SSE2-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7] From 8654b8c55b56fd2a14dbe504da865adfcce22d54 Mon Sep 17 00:00:00 2001 From: James Henderson Date: Fri, 24 May 2019 10:07:24 +0000 Subject: [PATCH 0155/1176] [llvm-objdump][test] Fix for spurious matches against file paths r361479 added tests that did --implicit-check-not=main, but a user found that they failed on his machine, due to it having 'main' in a file path printed earlier in the output. This test fixes this issue by making the check pattern more explicit. llvm-svn: 361621 --- .../X86/source-interleave-missing-source.test | 2 +- .../X86/source-interleave-no-debug-info.test | 2 +- .../X86/source-interleave-relative-paths.test | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test index 166caeb41b50d..d987728472167 100644 --- a/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-missing-source.test @@ -7,7 +7,7 @@ # RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %t.ll # RUN: llc -o %t2.o -filetype=obj -mtriple=x86_64-pc-linux %t2.ll -# RUN: llvm-objdump --source %t.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source %t.o | FileCheck %s --implicit-check-not='main()' # RUN: llvm-objdump --source %t2.o | FileCheck %s --check-prefixes=CHECK,SOURCE # CHECK: 0000000000000010 main: diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test index 4a0a34a9eae0e..15f7b7ecb222d 100644 --- a/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-no-debug-info.test @@ -6,7 +6,7 @@ # RUN: llvm-objcopy --strip-debug %t.o %t2.o # RUN: llvm-objdump --source %t.o | FileCheck %s --check-prefixes=CHECK,SOURCE -# RUN: llvm-objdump --source %t2.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source %t2.o | FileCheck %s --implicit-check-not='main()' # CHECK: 0000000000000010 main: # SOURCE-NEXT: ; int main() { diff --git a/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test b/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test index f9c69dfc0c06a..baf4ec919c000 100644 --- a/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test +++ b/llvm/test/tools/llvm-objdump/X86/source-interleave-relative-paths.test @@ -17,18 +17,18 @@ # RUN: cd %t # RUN: llvm-objdump --source a/a.o | FileCheck %s --check-prefixes=CHECK,SOURCE -# RUN: llvm-objdump --source a/b.o | FileCheck %s --implicit-check-not=main -# RUN: llvm-objdump --source a/c.o | FileCheck %s --implicit-check-not=main -# RUN: llvm-objdump --source a/d.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source a/b.o | FileCheck %s --implicit-check-not='main()' +# RUN: llvm-objdump --source a/c.o | FileCheck %s --implicit-check-not='main()' +# RUN: llvm-objdump --source a/d.o | FileCheck %s --implicit-check-not='main()' # RUN: cd a -# RUN: llvm-objdump --source a.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source a.o | FileCheck %s --implicit-check-not='main()' # RUN: llvm-objdump --source b.o | FileCheck %s --check-prefixes=CHECK,SOURCE # RUN: llvm-objdump --source c.o | FileCheck %s --check-prefixes=CHECK,SOURCE -# RUN: llvm-objdump --source d.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source d.o | FileCheck %s --implicit-check-not='main()' # RUN: cd b -# RUN: llvm-objdump --source ../a.o | FileCheck %s --implicit-check-not=main -# RUN: llvm-objdump --source ../b.o | FileCheck %s --implicit-check-not=main -# RUN: llvm-objdump --source ../c.o | FileCheck %s --implicit-check-not=main +# RUN: llvm-objdump --source ../a.o | FileCheck %s --implicit-check-not='main()' +# RUN: llvm-objdump --source ../b.o | FileCheck %s --implicit-check-not='main()' +# RUN: llvm-objdump --source ../c.o | FileCheck %s --implicit-check-not='main()' # RUN: llvm-objdump --source ../d.o | FileCheck %s --check-prefixes=CHECK,SOURCE # CHECK: 0000000000000010 main: From 5f04f0028209bb582076405b8e984d4f91335945 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 10:10:34 +0000 Subject: [PATCH 0156/1176] [AArch64][SVE2] Asm: support SVE2 Accumulate Group Summary: Patch adds support for the following instructions: SVE2 bitwise shift and insert: * SRI, SLI SVE2 bitwise shift right and accumulate: * SSRA, USRA, SRSRA, URSRA SVE2 complex integer add: * CADD, SQCADD SVE2 integer absolute difference and accumulate: * SABA, UABA SVE2 integer absolute difference and accumulate long: * SABALB, SABALT, UABALB, UABALT SVE2 integer add/subtract long with carry: * ADCLB, ADCLT, SBCLB, SBCLT The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D62204 llvm-svn: 361622 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 30 ++++ llvm/lib/Target/AArch64/SVEInstrFormats.td | 156 ++++++++++++++++++ llvm/test/MC/AArch64/SVE2/adclb-diagnostics.s | 25 +++ llvm/test/MC/AArch64/SVE2/adclb.s | 36 ++++ llvm/test/MC/AArch64/SVE2/adclt-diagnostics.s | 25 +++ llvm/test/MC/AArch64/SVE2/adclt.s | 36 ++++ llvm/test/MC/AArch64/SVE2/cadd-diagnostics.s | 38 +++++ llvm/test/MC/AArch64/SVE2/cadd.s | 72 ++++++++ llvm/test/MC/AArch64/SVE2/saba-diagnostics.s | 20 +++ llvm/test/MC/AArch64/SVE2/saba.s | 48 ++++++ .../test/MC/AArch64/SVE2/sabalb-diagnostics.s | 34 ++++ llvm/test/MC/AArch64/SVE2/sabalb.s | 43 +++++ .../test/MC/AArch64/SVE2/sabalt-diagnostics.s | 34 ++++ llvm/test/MC/AArch64/SVE2/sabalt.s | 43 +++++ llvm/test/MC/AArch64/SVE2/sbclb-diagnostics.s | 25 +++ llvm/test/MC/AArch64/SVE2/sbclb.s | 36 ++++ llvm/test/MC/AArch64/SVE2/sbclt-diagnostics.s | 25 +++ llvm/test/MC/AArch64/SVE2/sbclt.s | 36 ++++ llvm/test/MC/AArch64/SVE2/sli-diagnostics.s | 59 +++++++ llvm/test/MC/AArch64/SVE2/sli.s | 56 +++++++ .../test/MC/AArch64/SVE2/sqcadd-diagnostics.s | 38 +++++ llvm/test/MC/AArch64/SVE2/sqcadd.s | 72 ++++++++ llvm/test/MC/AArch64/SVE2/sri-diagnostics.s | 60 +++++++ llvm/test/MC/AArch64/SVE2/sri.s | 56 +++++++ llvm/test/MC/AArch64/SVE2/srsra-diagnostics.s | 60 +++++++ llvm/test/MC/AArch64/SVE2/srsra.s | 72 ++++++++ llvm/test/MC/AArch64/SVE2/ssra-diagnostics.s | 60 +++++++ llvm/test/MC/AArch64/SVE2/ssra.s | 72 ++++++++ llvm/test/MC/AArch64/SVE2/uaba-diagnostics.s | 20 +++ llvm/test/MC/AArch64/SVE2/uaba.s | 48 ++++++ .../test/MC/AArch64/SVE2/uabalb-diagnostics.s | 34 ++++ llvm/test/MC/AArch64/SVE2/uabalb.s | 43 +++++ .../test/MC/AArch64/SVE2/uabalt-diagnostics.s | 34 ++++ llvm/test/MC/AArch64/SVE2/uabalt.s | 43 +++++ llvm/test/MC/AArch64/SVE2/ursra-diagnostics.s | 60 +++++++ llvm/test/MC/AArch64/SVE2/ursra.s | 72 ++++++++ llvm/test/MC/AArch64/SVE2/usra-diagnostics.s | 60 +++++++ llvm/test/MC/AArch64/SVE2/usra.s | 72 ++++++++ 38 files changed, 1853 insertions(+) create mode 100644 llvm/test/MC/AArch64/SVE2/adclb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/adclb.s create mode 100644 llvm/test/MC/AArch64/SVE2/adclt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/adclt.s create mode 100644 llvm/test/MC/AArch64/SVE2/cadd-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/cadd.s create mode 100644 llvm/test/MC/AArch64/SVE2/saba-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/saba.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabalb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabalb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabalt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sabalt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sbclb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sbclb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sbclt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sbclt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sli-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sli.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqcadd-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqcadd.s create mode 100644 llvm/test/MC/AArch64/SVE2/sri-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sri.s create mode 100644 llvm/test/MC/AArch64/SVE2/srsra-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/srsra.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssra-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/ssra.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaba-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uaba.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabalb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabalb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabalt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uabalt.s create mode 100644 llvm/test/MC/AArch64/SVE2/ursra-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/ursra.s create mode 100644 llvm/test/MC/AArch64/SVE2/usra-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/usra.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 18f874fccb66c..3f48490bcc178 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1198,6 +1198,36 @@ let Predicates = [HasSVE2] in { defm PMULLB_ZZZ : sve2_pmul_long<0b0, "pmullb">; defm PMULLT_ZZZ : sve2_pmul_long<0b1, "pmullt">; + // SVE2 bitwise shift and insert + defm SRI_ZZI : sve2_int_bin_cons_shift_imm_right<0b0, "sri">; + defm SLI_ZZI : sve2_int_bin_cons_shift_imm_left< 0b1, "sli">; + + // SVE2 bitwise shift right and accumulate + defm SSRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b00, "ssra">; + defm USRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b01, "usra">; + defm SRSRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b10, "srsra">; + defm URSRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b11, "ursra">; + + // SVE2 complex integer add + defm CADD_ZZI : sve2_int_cadd<0b0, "cadd">; + defm SQCADD_ZZI : sve2_int_cadd<0b1, "sqcadd">; + + // SVE2 integer absolute difference and accumulate + defm SABA_ZZZ : sve2_int_absdiff_accum<0b0, "saba">; + defm UABA_ZZZ : sve2_int_absdiff_accum<0b1, "uaba">; + + // SVE2 integer absolute difference and accumulate long + defm SABALB_ZZZ : sve2_int_absdiff_accum_long<0b00, "sabalb">; + defm SABALT_ZZZ : sve2_int_absdiff_accum_long<0b01, "sabalt">; + defm UABALB_ZZZ : sve2_int_absdiff_accum_long<0b10, "uabalb">; + defm UABALT_ZZZ : sve2_int_absdiff_accum_long<0b11, "uabalt">; + + // SVE2 integer add/subtract long with carry + defm ADCLB_ZZZ : sve2_int_addsub_long_carry<0b00, "adclb">; + defm ADCLT_ZZZ : sve2_int_addsub_long_carry<0b01, "adclt">; + defm SBCLB_ZZZ : sve2_int_addsub_long_carry<0b10, "sbclb">; + defm SBCLT_ZZZ : sve2_int_addsub_long_carry<0b11, "sbclt">; + // Predicated shifts defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 333fa72500cf4..90c8076d2907f 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -2191,6 +2191,162 @@ multiclass sve2_pmul_long opc, string asm> { def _D : sve2_wide_int_arith<0b11, {0b1101, opc}, asm, ZPR64, ZPR32, ZPR32>; } +//===----------------------------------------------------------------------===// +// SVE2 Accumulate Group +//===----------------------------------------------------------------------===// + +class sve2_int_bin_cons_shift_imm tsz8_64, bit opc, string asm, + ZPRRegOp zprty, Operand immtype> +: I<(outs zprty:$Zd), (ins zprty:$Zn, immtype:$imm), + asm, "\t$Zd, $Zn, $imm", + "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + bits<6> imm; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = tsz8_64{3-2}; + let Inst{21} = 0b0; + let Inst{20-19} = tsz8_64{1-0}; + let Inst{18-16} = imm{2-0}; // imm3 + let Inst{15-11} = 0b11110; + let Inst{10} = opc; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2_int_bin_cons_shift_imm_left { + def _B : sve2_int_bin_cons_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftL8>; + def _H : sve2_int_bin_cons_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftL16> { + let Inst{19} = imm{3}; + } + def _S : sve2_int_bin_cons_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftL32> { + let Inst{20-19} = imm{4-3}; + } + def _D : sve2_int_bin_cons_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftL64> { + let Inst{22} = imm{5}; + let Inst{20-19} = imm{4-3}; + } +} + +multiclass sve2_int_bin_cons_shift_imm_right { + def _B : sve2_int_bin_cons_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8>; + def _H : sve2_int_bin_cons_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16> { + let Inst{19} = imm{3}; + } + def _S : sve2_int_bin_cons_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftR32> { + let Inst{20-19} = imm{4-3}; + } + def _D : sve2_int_bin_cons_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftR64> { + let Inst{22} = imm{5}; + let Inst{20-19} = imm{4-3}; + } +} + +class sve2_int_bin_accum_cons_shift_imm tsz8_64, bits<2> opc, string asm, + ZPRRegOp zprty, Operand immtype> +: I<(outs zprty:$Zda), (ins zprty:$_Zda, zprty:$Zn, immtype:$imm), + asm, "\t$Zda, $Zn, $imm", + "", []>, Sched<[]> { + bits<5> Zda; + bits<5> Zn; + bits<6> imm; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = tsz8_64{3-2}; + let Inst{21} = 0b0; + let Inst{20-19} = tsz8_64{1-0}; + let Inst{18-16} = imm{2-0}; // imm3 + let Inst{15-12} = 0b1110; + let Inst{11-10} = opc; + let Inst{9-5} = Zn; + let Inst{4-0} = Zda; + + let Constraints = "$Zda = $_Zda"; + let DestructiveInstType = Destructive; + let ElementSize = ElementSizeNone; +} + +multiclass sve2_int_bin_accum_cons_shift_imm_right opc, string asm> { + def _B : sve2_int_bin_accum_cons_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8>; + def _H : sve2_int_bin_accum_cons_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16> { + let Inst{19} = imm{3}; + } + def _S : sve2_int_bin_accum_cons_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftR32> { + let Inst{20-19} = imm{4-3}; + } + def _D : sve2_int_bin_accum_cons_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftR64> { + let Inst{22} = imm{5}; + let Inst{20-19} = imm{4-3}; + } +} + +class sve2_int_cadd sz, bit opc, string asm, ZPRRegOp zprty> +: I<(outs zprty:$Zdn), (ins zprty:$_Zdn, zprty:$Zm, complexrotateopodd:$rot), + asm, "\t$Zdn, $_Zdn, $Zm, $rot", "", []>, Sched<[]> { + bits<5> Zdn; + bits<5> Zm; + bit rot; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = sz; + let Inst{21-17} = 0b00000; + let Inst{16} = opc; + let Inst{15-11} = 0b11011; + let Inst{10} = rot; + let Inst{9-5} = Zm; + let Inst{4-0} = Zdn; + + let Constraints = "$Zdn = $_Zdn"; + let DestructiveInstType = Destructive; + let ElementSize = ElementSizeNone; +} + +multiclass sve2_int_cadd { + def _B : sve2_int_cadd<0b00, opc, asm, ZPR8>; + def _H : sve2_int_cadd<0b01, opc, asm, ZPR16>; + def _S : sve2_int_cadd<0b10, opc, asm, ZPR32>; + def _D : sve2_int_cadd<0b11, opc, asm, ZPR64>; +} + +class sve2_int_absdiff_accum sz, bits<4> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> +: I<(outs zprty1:$Zda), (ins zprty1:$_Zda, zprty2:$Zn, zprty2:$Zm), + asm, "\t$Zda, $Zn, $Zm", "", []>, Sched<[]> { + bits<5> Zda; + bits<5> Zn; + bits<5> Zm; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = sz; + let Inst{21} = 0b0; + let Inst{20-16} = Zm; + let Inst{15-14} = 0b11; + let Inst{13-10} = opc; + let Inst{9-5} = Zn; + let Inst{4-0} = Zda; + + let Constraints = "$Zda = $_Zda"; + let DestructiveInstType = Destructive; + let ElementSize = ElementSizeNone; +} + +multiclass sve2_int_absdiff_accum { + def _B : sve2_int_absdiff_accum<0b00, { 0b111, opc }, asm, ZPR8, ZPR8>; + def _H : sve2_int_absdiff_accum<0b01, { 0b111, opc }, asm, ZPR16, ZPR16>; + def _S : sve2_int_absdiff_accum<0b10, { 0b111, opc }, asm, ZPR32, ZPR32>; + def _D : sve2_int_absdiff_accum<0b11, { 0b111, opc }, asm, ZPR64, ZPR64>; +} + +multiclass sve2_int_absdiff_accum_long opc, string asm> { + def _H : sve2_int_absdiff_accum<0b01, { 0b00, opc }, asm, ZPR16, ZPR8>; + def _S : sve2_int_absdiff_accum<0b10, { 0b00, opc }, asm, ZPR32, ZPR16>; + def _D : sve2_int_absdiff_accum<0b11, { 0b00, opc }, asm, ZPR64, ZPR32>; +} + +multiclass sve2_int_addsub_long_carry opc, string asm> { + def _S : sve2_int_absdiff_accum<{ opc{1}, 0b0 }, { 0b010, opc{0} }, asm, + ZPR32, ZPR32>; + def _D : sve2_int_absdiff_accum<{ opc{1}, 0b1 }, { 0b010, opc{0} }, asm, + ZPR64, ZPR64>; +} + //===----------------------------------------------------------------------===// // SVE Integer Arithmetic - Unary Predicated Group //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SVE2/adclb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/adclb-diagnostics.s new file mode 100644 index 0000000000000..e2077dea9d591 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/adclb-diagnostics.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +adclb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: adclb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +adclb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: adclb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +adclb z0.d, z1.d, z7.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: adclb z0.d, z1.d, z7.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/adclb.s b/llvm/test/MC/AArch64/SVE2/adclb.s new file mode 100644 index 0000000000000..bcc0297173d03 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/adclb.s @@ -0,0 +1,36 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +adclb z0.s, z1.s, z31.s +// CHECK-INST: adclb z0.s, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xd0,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d0 1f 45 + +adclb z0.d, z1.d, z31.d +// CHECK-INST: adclb z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd0,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d0 5f 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +adclb z0.d, z1.d, z31.d +// CHECK-INST: adclb z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd0,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d0 5f 45 diff --git a/llvm/test/MC/AArch64/SVE2/adclt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/adclt-diagnostics.s new file mode 100644 index 0000000000000..d5a226d9eef44 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/adclt-diagnostics.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +adclt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: adclt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +adclt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: adclt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +adclt z0.d, z1.d, z7.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: adclt z0.d, z1.d, z7.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/adclt.s b/llvm/test/MC/AArch64/SVE2/adclt.s new file mode 100644 index 0000000000000..46de92fd5a542 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/adclt.s @@ -0,0 +1,36 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +adclt z0.s, z1.s, z31.s +// CHECK-INST: adclt z0.s, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xd4,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d4 1f 45 + +adclt z0.d, z1.d, z31.d +// CHECK-INST: adclt z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd4,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d4 5f 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +adclt z0.d, z1.d, z31.d +// CHECK-INST: adclt z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd4,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d4 5f 45 diff --git a/llvm/test/MC/AArch64/SVE2/cadd-diagnostics.s b/llvm/test/MC/AArch64/SVE2/cadd-diagnostics.s new file mode 100644 index 0000000000000..3537f7b788046 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/cadd-diagnostics.s @@ -0,0 +1,38 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +cadd z0.d, z1.d, z2.d, #90 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: cadd z0.d, z1.d, z2.d, #90 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid rotation + +cadd z0.d, z0.d, z1.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: complex rotation must be 90 or 270. +// CHECK-NEXT: cadd z0.d, z0.d, z1.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +cadd z0.d, z0.d, z1.d, #180 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: complex rotation must be 90 or 270. +// CHECK-NEXT: cadd z0.d, z0.d, z1.d, #180 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +cadd z0.d, z0.d, z1.d, #450 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: complex rotation must be 90 or 270. +// CHECK-NEXT: cadd z0.d, z0.d, z1.d, #450 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +cadd z0.d, z0.d, z31.d, #90 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: cadd z0.d, z0.d, z31.d, #90 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/cadd.s b/llvm/test/MC/AArch64/SVE2/cadd.s new file mode 100644 index 0000000000000..75d1deb29f0fc --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/cadd.s @@ -0,0 +1,72 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +cadd z0.b, z0.b, z0.b, #90 +// CHECK-INST: cadd z0.b, z0.b, z0.b, #90 +// CHECK-ENCODING: [0x00,0xd8,0x00,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 00 45 + +cadd z0.h, z0.h, z0.h, #90 +// CHECK-INST: cadd z0.h, z0.h, z0.h, #90 +// CHECK-ENCODING: [0x00,0xd8,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 40 45 + +cadd z0.s, z0.s, z0.s, #90 +// CHECK-INST: cadd z0.s, z0.s, z0.s, #90 +// CHECK-ENCODING: [0x00,0xd8,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 80 45 + +cadd z0.d, z0.d, z0.d, #90 +// CHECK-INST: cadd z0.d, z0.d, z0.d, #90 +// CHECK-ENCODING: [0x00,0xd8,0xc0,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 c0 45 + +cadd z31.b, z31.b, z31.b, #270 +// CHECK-INST: cadd z31.b, z31.b, z31.b, #270 +// CHECK-ENCODING: [0xff,0xdf,0x00,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df 00 45 + +cadd z31.h, z31.h, z31.h, #270 +// CHECK-INST: cadd z31.h, z31.h, z31.h, #270 +// CHECK-ENCODING: [0xff,0xdf,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df 40 45 + +cadd z31.s, z31.s, z31.s, #270 +// CHECK-INST: cadd z31.s, z31.s, z31.s, #270 +// CHECK-ENCODING: [0xff,0xdf,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df 80 45 + +cadd z31.d, z31.d, z31.d, #270 +// CHECK-INST: cadd z31.d, z31.d, z31.d, #270 +// CHECK-ENCODING: [0xff,0xdf,0xc0,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df c0 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z4, z6 +// CHECK-INST: movprfx z4, z6 +// CHECK-ENCODING: [0xc4,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: c4 bc 20 04 + +cadd z4.d, z4.d, z31.d, #270 +// CHECK-INST: cadd z4.d, z4.d, z31.d, #270 +// CHECK-ENCODING: [0xe4,0xdf,0xc0,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e4 df c0 45 diff --git a/llvm/test/MC/AArch64/SVE2/saba-diagnostics.s b/llvm/test/MC/AArch64/SVE2/saba-diagnostics.s new file mode 100644 index 0000000000000..3d6a8347be168 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saba-diagnostics.s @@ -0,0 +1,20 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +saba z0.b, z1.h, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: saba z0.b, z1.h, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +saba z0.d, z1.d, z7.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: saba z0.d, z1.d, z7.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/saba.s b/llvm/test/MC/AArch64/SVE2/saba.s new file mode 100644 index 0000000000000..7d02e9816fbcb --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/saba.s @@ -0,0 +1,48 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +saba z0.b, z1.b, z31.b +// CHECK-INST: saba z0.b, z1.b, z31.b +// CHECK-ENCODING: [0x20,0xf8,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 f8 1f 45 + +saba z0.h, z1.h, z31.h +// CHECK-INST: saba z0.h, z1.h, z31.h +// CHECK-ENCODING: [0x20,0xf8,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 f8 5f 45 + +saba z0.s, z1.s, z31.s +// CHECK-INST: saba z0.s, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xf8,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 f8 9f 45 + +saba z0.d, z1.d, z31.d +// CHECK-INST: saba z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xf8,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 f8 df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +saba z0.d, z1.d, z31.d +// CHECK-INST: saba z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xf8,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 f8 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sabalb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sabalb-diagnostics.s new file mode 100644 index 0000000000000..1f928af82df91 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabalb-diagnostics.s @@ -0,0 +1,34 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sabalb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabalb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabalb z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalb z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabalb z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalb z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +sabalb z0.d, z1.s, z31.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: sabalb z0.d, z1.s, z31.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sabalb.s b/llvm/test/MC/AArch64/SVE2/sabalb.s new file mode 100644 index 0000000000000..450c005fb55ef --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabalb.s @@ -0,0 +1,43 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sabalb z0.h, z1.b, z31.b +// CHECK-INST: sabalb z0.h, z1.b, z31.b +// CHECK-ENCODING: [0x20,0xc0,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c0 5f 45 + +sabalb z0.s, z1.h, z31.h +// CHECK-INST: sabalb z0.s, z1.h, z31.h +// CHECK-ENCODING: [0x20,0xc0,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c0 9f 45 + +sabalb z0.d, z1.s, z31.s +// CHECK-INST: sabalb z0.d, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xc0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c0 df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z21, z28 +// CHECK-INST: movprfx z21, z28 +// CHECK-ENCODING: [0x95,0xbf,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 95 bf 20 04 + +sabalb z21.d, z1.s, z31.s +// CHECK-INST: sabalb z21.d, z1.s, z31.s +// CHECK-ENCODING: [0x35,0xc0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 35 c0 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sabalt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sabalt-diagnostics.s new file mode 100644 index 0000000000000..a6a96abf34c4b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabalt-diagnostics.s @@ -0,0 +1,34 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sabalt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabalt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabalt z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalt z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabalt z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabalt z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +sabalt z0.d, z1.s, z31.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: sabalt z0.d, z1.s, z31.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sabalt.s b/llvm/test/MC/AArch64/SVE2/sabalt.s new file mode 100644 index 0000000000000..2653848efb172 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sabalt.s @@ -0,0 +1,43 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sabalt z0.h, z1.b, z31.b +// CHECK-INST: sabalt z0.h, z1.b, z31.b +// CHECK-ENCODING: [0x20,0xc4,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c4 5f 45 + +sabalt z0.s, z1.h, z31.h +// CHECK-INST: sabalt z0.s, z1.h, z31.h +// CHECK-ENCODING: [0x20,0xc4,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c4 9f 45 + +sabalt z0.d, z1.s, z31.s +// CHECK-INST: sabalt z0.d, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xc4,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c4 df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z21, z28 +// CHECK-INST: movprfx z21, z28 +// CHECK-ENCODING: [0x95,0xbf,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 95 bf 20 04 + +sabalt z21.d, z1.s, z31.s +// CHECK-INST: sabalt z21.d, z1.s, z31.s +// CHECK-ENCODING: [0x35,0xc4,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 35 c4 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sbclb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sbclb-diagnostics.s new file mode 100644 index 0000000000000..f05f0fd9c4cf5 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sbclb-diagnostics.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sbclb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sbclb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sbclb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sbclb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +sbclb z0.d, z1.d, z7.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: sbclb z0.d, z1.d, z7.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sbclb.s b/llvm/test/MC/AArch64/SVE2/sbclb.s new file mode 100644 index 0000000000000..bec58658aa431 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sbclb.s @@ -0,0 +1,36 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sbclb z0.s, z1.s, z31.s +// CHECK-INST: sbclb z0.s, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xd0,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d0 9f 45 + +sbclb z0.d, z1.d, z31.d +// CHECK-INST: sbclb z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d0 df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +sbclb z0.d, z1.d, z31.d +// CHECK-INST: sbclb z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d0 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sbclt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sbclt-diagnostics.s new file mode 100644 index 0000000000000..ead1aae029dc6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sbclt-diagnostics.s @@ -0,0 +1,25 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sbclt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sbclt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sbclt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sbclt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +sbclt z0.d, z1.d, z7.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: sbclt z0.d, z1.d, z7.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sbclt.s b/llvm/test/MC/AArch64/SVE2/sbclt.s new file mode 100644 index 0000000000000..e35499f72a31b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sbclt.s @@ -0,0 +1,36 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sbclt z0.s, z1.s, z31.s +// CHECK-INST: sbclt z0.s, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xd4,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d4 9f 45 + +sbclt z0.d, z1.d, z31.d +// CHECK-INST: sbclt z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd4,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d4 df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +sbclt z0.d, z1.d, z31.d +// CHECK-INST: sbclt z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xd4,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 d4 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sli-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sli-diagnostics.s new file mode 100644 index 0000000000000..150bf95a693a2 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sli-diagnostics.s @@ -0,0 +1,59 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sli z18.b, z28.b, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: sli z18.b, z28.b, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z1.b, z9.b, #8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 7] +// CHECK-NEXT: sli z1.b, z9.b, #8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z21.h, z2.h, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: sli z21.h, z2.h, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z14.h, z30.h, #16 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 15] +// CHECK-NEXT: sli z14.h, z30.h, #16 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z6.s, z12.s, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: sli z6.s, z12.s, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z23.s, z19.s, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 31] +// CHECK-NEXT: sli z23.s, z19.s, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z3.d, z24.d, #-1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: sli z3.d, z24.d, #-1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sli z25.d, z16.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [0, 63] +// CHECK-NEXT: sli z25.d, z16.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sli z0.b, z0.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sli z0.b, z0.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sli z31.d, z31.d, #63 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sli z31.d, z31.d, #63 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sli.s b/llvm/test/MC/AArch64/SVE2/sli.s new file mode 100644 index 0000000000000..e5100fd057874 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sli.s @@ -0,0 +1,56 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sli z0.b, z0.b, #0 +// CHECK-INST: sli z0.b, z0.b, #0 +// CHECK-ENCODING: [0x00,0xf4,0x08,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f4 08 45 + +sli z31.b, z31.b, #7 +// CHECK-INST: sli z31.b, z31.b, #7 +// CHECK-ENCODING: [0xff,0xf7,0x0f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f7 0f 45 + +sli z0.h, z0.h, #0 +// CHECK-INST: sli z0.h, z0.h, #0 +// CHECK-ENCODING: [0x00,0xf4,0x10,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f4 10 45 + +sli z31.h, z31.h, #15 +// CHECK-INST: sli z31.h, z31.h, #15 +// CHECK-ENCODING: [0xff,0xf7,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f7 1f 45 + +sli z0.s, z0.s, #0 +// CHECK-INST: sli z0.s, z0.s, #0 +// CHECK-ENCODING: [0x00,0xf4,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f4 40 45 + +sli z31.s, z31.s, #31 +// CHECK-INST: sli z31.s, z31.s, #31 +// CHECK-ENCODING: [0xff,0xf7,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f7 5f 45 + +sli z0.d, z0.d, #0 +// CHECK-INST: sli z0.d, z0.d, #0 +// CHECK-ENCODING: [0x00,0xf4,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f4 80 45 + +sli z31.d, z31.d, #63 +// CHECK-INST: sli z31.d, z31.d, #63 +// CHECK-ENCODING: [0xff,0xf7,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f7 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqcadd-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqcadd-diagnostics.s new file mode 100644 index 0000000000000..e399f9e87cfe9 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqcadd-diagnostics.s @@ -0,0 +1,38 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Source and Destination Registers must match + +sqcadd z0.d, z1.d, z2.d, #90 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: sqcadd z0.d, z1.d, z2.d, #90 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid rotation + +sqcadd z0.d, z0.d, z1.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: complex rotation must be 90 or 270. +// CHECK-NEXT: sqcadd z0.d, z0.d, z1.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqcadd z0.d, z0.d, z1.d, #180 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: complex rotation must be 90 or 270. +// CHECK-NEXT: sqcadd z0.d, z0.d, z1.d, #180 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqcadd z0.d, z0.d, z1.d, #450 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: complex rotation must be 90 or 270. +// CHECK-NEXT: sqcadd z0.d, z0.d, z1.d, #450 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +sqcadd z0.d, z0.d, z31.d, #90 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: sqcadd z0.d, z0.d, z31.d, #90 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqcadd.s b/llvm/test/MC/AArch64/SVE2/sqcadd.s new file mode 100644 index 0000000000000..2784d1d15bd0b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqcadd.s @@ -0,0 +1,72 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqcadd z0.b, z0.b, z0.b, #90 +// CHECK-INST: sqcadd z0.b, z0.b, z0.b, #90 +// CHECK-ENCODING: [0x00,0xd8,0x01,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 01 45 + +sqcadd z0.h, z0.h, z0.h, #90 +// CHECK-INST: sqcadd z0.h, z0.h, z0.h, #90 +// CHECK-ENCODING: [0x00,0xd8,0x41,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 41 45 + +sqcadd z0.s, z0.s, z0.s, #90 +// CHECK-INST: sqcadd z0.s, z0.s, z0.s, #90 +// CHECK-ENCODING: [0x00,0xd8,0x81,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 81 45 + +sqcadd z0.d, z0.d, z0.d, #90 +// CHECK-INST: sqcadd z0.d, z0.d, z0.d, #90 +// CHECK-ENCODING: [0x00,0xd8,0xc1,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 d8 c1 45 + +sqcadd z31.b, z31.b, z31.b, #270 +// CHECK-INST: sqcadd z31.b, z31.b, z31.b, #270 +// CHECK-ENCODING: [0xff,0xdf,0x01,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df 01 45 + +sqcadd z31.h, z31.h, z31.h, #270 +// CHECK-INST: sqcadd z31.h, z31.h, z31.h, #270 +// CHECK-ENCODING: [0xff,0xdf,0x41,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df 41 45 + +sqcadd z31.s, z31.s, z31.s, #270 +// CHECK-INST: sqcadd z31.s, z31.s, z31.s, #270 +// CHECK-ENCODING: [0xff,0xdf,0x81,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df 81 45 + +sqcadd z31.d, z31.d, z31.d, #270 +// CHECK-INST: sqcadd z31.d, z31.d, z31.d, #270 +// CHECK-ENCODING: [0xff,0xdf,0xc1,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff df c1 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z4, z6 +// CHECK-INST: movprfx z4, z6 +// CHECK-ENCODING: [0xc4,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: c4 bc 20 04 + +sqcadd z4.d, z4.d, z31.d, #270 +// CHECK-INST: sqcadd z4.d, z4.d, z31.d, #270 +// CHECK-ENCODING: [0xe4,0xdf,0xc1,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e4 df c1 45 diff --git a/llvm/test/MC/AArch64/SVE2/sri-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sri-diagnostics.s new file mode 100644 index 0000000000000..da88d51642650 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sri-diagnostics.s @@ -0,0 +1,60 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sri z30.b, z10.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sri z30.b, z10.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z18.b, z27.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sri z18.b, z27.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z26.h, z4.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sri z26.h, z4.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z25.h, z10.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sri z25.h, z10.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z17.s, z0.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sri z17.s, z0.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z0.s, z15.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sri z0.s, z15.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z4.d, z13.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: sri z4.d, z13.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sri z26.d, z26.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: sri z26.d, z26.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +sri z0.b, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sri z0.b, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sri z31.d, z31.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sri z31.d, z31.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sri.s b/llvm/test/MC/AArch64/SVE2/sri.s new file mode 100644 index 0000000000000..c06fa6bc4527e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sri.s @@ -0,0 +1,56 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sri z0.b, z0.b, #1 +// CHECK-INST: sri z0.b, z0.b, #1 +// CHECK-ENCODING: [0x00,0xf0,0x0f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f0 0f 45 + +sri z31.b, z31.b, #8 +// CHECK-INST: sri z31.b, z31.b, #8 +// CHECK-ENCODING: [0xff,0xf3,0x08,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f3 08 45 + +sri z0.h, z0.h, #1 +// CHECK-INST: sri z0.h, z0.h, #1 +// CHECK-ENCODING: [0x00,0xf0,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f0 1f 45 + +sri z31.h, z31.h, #16 +// CHECK-INST: sri z31.h, z31.h, #16 +// CHECK-ENCODING: [0xff,0xf3,0x10,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f3 10 45 + +sri z0.s, z0.s, #1 +// CHECK-INST: sri z0.s, z0.s, #1 +// CHECK-ENCODING: [0x00,0xf0,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f0 5f 45 + +sri z31.s, z31.s, #32 +// CHECK-INST: sri z31.s, z31.s, #32 +// CHECK-ENCODING: [0xff,0xf3,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f3 40 45 + +sri z0.d, z0.d, #1 +// CHECK-INST: sri z0.d, z0.d, #1 +// CHECK-ENCODING: [0x00,0xf0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 f0 df 45 + +sri z31.d, z31.d, #64 +// CHECK-INST: sri z31.d, z31.d, #64 +// CHECK-ENCODING: [0xff,0xf3,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff f3 80 45 diff --git a/llvm/test/MC/AArch64/SVE2/srsra-diagnostics.s b/llvm/test/MC/AArch64/SVE2/srsra-diagnostics.s new file mode 100644 index 0000000000000..ed21d5d01d149 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srsra-diagnostics.s @@ -0,0 +1,60 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +srsra z30.b, z10.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: srsra z30.b, z10.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z18.b, z27.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: srsra z18.b, z27.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z26.h, z4.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: srsra z26.h, z4.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z25.h, z10.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: srsra z25.h, z10.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z17.s, z0.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: srsra z17.s, z0.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z0.s, z15.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: srsra z0.s, z15.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z4.d, z13.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: srsra z4.d, z13.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +srsra z26.d, z26.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: srsra z26.d, z26.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +srsra z0.b, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: srsra z0.b, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +srsra z0.d, z1.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: srsra z0.d, z1.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/srsra.s b/llvm/test/MC/AArch64/SVE2/srsra.s new file mode 100644 index 0000000000000..2ac7fa78736a3 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/srsra.s @@ -0,0 +1,72 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +srsra z0.b, z0.b, #1 +// CHECK-INST: srsra z0.b, z0.b, #1 +// CHECK-ENCODING: [0x00,0xe8,0x0f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e8 0f 45 + +srsra z31.b, z31.b, #8 +// CHECK-INST: srsra z31.b, z31.b, #8 +// CHECK-ENCODING: [0xff,0xeb,0x08,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff eb 08 45 + +srsra z0.h, z0.h, #1 +// CHECK-INST: srsra z0.h, z0.h, #1 +// CHECK-ENCODING: [0x00,0xe8,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e8 1f 45 + +srsra z31.h, z31.h, #16 +// CHECK-INST: srsra z31.h, z31.h, #16 +// CHECK-ENCODING: [0xff,0xeb,0x10,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff eb 10 45 + +srsra z0.s, z0.s, #1 +// CHECK-INST: srsra z0.s, z0.s, #1 +// CHECK-ENCODING: [0x00,0xe8,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e8 5f 45 + +srsra z31.s, z31.s, #32 +// CHECK-INST: srsra z31.s, z31.s, #32 +// CHECK-ENCODING: [0xff,0xeb,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff eb 40 45 + +srsra z0.d, z0.d, #1 +// CHECK-INST: srsra z0.d, z0.d, #1 +// CHECK-ENCODING: [0x00,0xe8,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e8 df 45 + +srsra z31.d, z31.d, #64 +// CHECK-INST: srsra z31.d, z31.d, #64 +// CHECK-ENCODING: [0xff,0xeb,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff eb 80 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +srsra z0.d, z1.d, #1 +// CHECK-INST: srsra z0.d, z1.d, #1 +// CHECK-ENCODING: [0x20,0xe8,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 e8 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/ssra-diagnostics.s b/llvm/test/MC/AArch64/SVE2/ssra-diagnostics.s new file mode 100644 index 0000000000000..17d8fdf0ced3d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssra-diagnostics.s @@ -0,0 +1,60 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +ssra z30.b, z10.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: ssra z30.b, z10.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z18.b, z27.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: ssra z18.b, z27.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z26.h, z4.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: ssra z26.h, z4.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z25.h, z10.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: ssra z25.h, z10.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z17.s, z0.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: ssra z17.s, z0.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z0.s, z15.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: ssra z0.s, z15.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z4.d, z13.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: ssra z4.d, z13.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ssra z26.d, z26.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: ssra z26.d, z26.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +ssra z0.b, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ssra z0.b, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +ssra z0.d, z1.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: ssra z0.d, z1.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/ssra.s b/llvm/test/MC/AArch64/SVE2/ssra.s new file mode 100644 index 0000000000000..5daeb9a667e3a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ssra.s @@ -0,0 +1,72 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ssra z0.b, z0.b, #1 +// CHECK-INST: ssra z0.b, z0.b, #1 +// CHECK-ENCODING: [0x00,0xe0,0x0f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e0 0f 45 + +ssra z31.b, z31.b, #8 +// CHECK-INST: ssra z31.b, z31.b, #8 +// CHECK-ENCODING: [0xff,0xe3,0x08,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e3 08 45 + +ssra z0.h, z0.h, #1 +// CHECK-INST: ssra z0.h, z0.h, #1 +// CHECK-ENCODING: [0x00,0xe0,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e0 1f 45 + +ssra z31.h, z31.h, #16 +// CHECK-INST: ssra z31.h, z31.h, #16 +// CHECK-ENCODING: [0xff,0xe3,0x10,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e3 10 45 + +ssra z0.s, z0.s, #1 +// CHECK-INST: ssra z0.s, z0.s, #1 +// CHECK-ENCODING: [0x00,0xe0,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e0 5f 45 + +ssra z31.s, z31.s, #32 +// CHECK-INST: ssra z31.s, z31.s, #32 +// CHECK-ENCODING: [0xff,0xe3,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e3 40 45 + +ssra z0.d, z0.d, #1 +// CHECK-INST: ssra z0.d, z0.d, #1 +// CHECK-ENCODING: [0x00,0xe0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e0 df 45 + +ssra z31.d, z31.d, #64 +// CHECK-INST: ssra z31.d, z31.d, #64 +// CHECK-ENCODING: [0xff,0xe3,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e3 80 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +ssra z0.d, z1.d, #1 +// CHECK-INST: ssra z0.d, z1.d, #1 +// CHECK-ENCODING: [0x20,0xe0,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 e0 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uaba-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uaba-diagnostics.s new file mode 100644 index 0000000000000..4a03e83e57624 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaba-diagnostics.s @@ -0,0 +1,20 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uaba z0.b, z1.h, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uaba z0.b, z1.h, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +uaba z0.d, z1.d, z7.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: uaba z0.d, z1.d, z7.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uaba.s b/llvm/test/MC/AArch64/SVE2/uaba.s new file mode 100644 index 0000000000000..f714902fabe5f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uaba.s @@ -0,0 +1,48 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uaba z0.b, z1.b, z31.b +// CHECK-INST: uaba z0.b, z1.b, z31.b +// CHECK-ENCODING: [0x20,0xfc,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 fc 1f 45 + +uaba z0.h, z1.h, z31.h +// CHECK-INST: uaba z0.h, z1.h, z31.h +// CHECK-ENCODING: [0x20,0xfc,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 fc 5f 45 + +uaba z0.s, z1.s, z31.s +// CHECK-INST: uaba z0.s, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xfc,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 fc 9f 45 + +uaba z0.d, z1.d, z31.d +// CHECK-INST: uaba z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xfc,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 fc df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +uaba z0.d, z1.d, z31.d +// CHECK-INST: uaba z0.d, z1.d, z31.d +// CHECK-ENCODING: [0x20,0xfc,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 fc df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uabalb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uabalb-diagnostics.s new file mode 100644 index 0000000000000..c35bccc9a0156 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabalb-diagnostics.s @@ -0,0 +1,34 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uabalb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabalb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabalb z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalb z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabalb z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalb z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +uabalb z0.d, z1.s, z31.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: uabalb z0.d, z1.s, z31.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uabalb.s b/llvm/test/MC/AArch64/SVE2/uabalb.s new file mode 100644 index 0000000000000..b2cda012973f6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabalb.s @@ -0,0 +1,43 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uabalb z0.h, z1.b, z31.b +// CHECK-INST: uabalb z0.h, z1.b, z31.b +// CHECK-ENCODING: [0x20,0xc8,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c8 5f 45 + +uabalb z0.s, z1.h, z31.h +// CHECK-INST: uabalb z0.s, z1.h, z31.h +// CHECK-ENCODING: [0x20,0xc8,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c8 9f 45 + +uabalb z0.d, z1.s, z31.s +// CHECK-INST: uabalb z0.d, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xc8,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 c8 df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z21, z28 +// CHECK-INST: movprfx z21, z28 +// CHECK-ENCODING: [0x95,0xbf,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 95 bf 20 04 + +uabalb z21.d, z1.s, z31.s +// CHECK-INST: uabalb z21.d, z1.s, z31.s +// CHECK-ENCODING: [0x35,0xc8,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 35 c8 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/uabalt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uabalt-diagnostics.s new file mode 100644 index 0000000000000..16fe160620fd3 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabalt-diagnostics.s @@ -0,0 +1,34 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uabalt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabalt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabalt z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalt z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabalt z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabalt z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +uabalt z0.d, z1.s, z31.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: uabalt z0.d, z1.s, z31.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uabalt.s b/llvm/test/MC/AArch64/SVE2/uabalt.s new file mode 100644 index 0000000000000..f49dede472ae9 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uabalt.s @@ -0,0 +1,43 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uabalt z0.h, z1.b, z31.b +// CHECK-INST: uabalt z0.h, z1.b, z31.b +// CHECK-ENCODING: [0x20,0xcc,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 cc 5f 45 + +uabalt z0.s, z1.h, z31.h +// CHECK-INST: uabalt z0.s, z1.h, z31.h +// CHECK-ENCODING: [0x20,0xcc,0x9f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 cc 9f 45 + +uabalt z0.d, z1.s, z31.s +// CHECK-INST: uabalt z0.d, z1.s, z31.s +// CHECK-ENCODING: [0x20,0xcc,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 cc df 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z21, z28 +// CHECK-INST: movprfx z21, z28 +// CHECK-ENCODING: [0x95,0xbf,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 95 bf 20 04 + +uabalt z21.d, z1.s, z31.s +// CHECK-INST: uabalt z21.d, z1.s, z31.s +// CHECK-ENCODING: [0x35,0xcc,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 35 cc df 45 diff --git a/llvm/test/MC/AArch64/SVE2/ursra-diagnostics.s b/llvm/test/MC/AArch64/SVE2/ursra-diagnostics.s new file mode 100644 index 0000000000000..323901b00f97e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ursra-diagnostics.s @@ -0,0 +1,60 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +ursra z30.b, z10.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: ursra z30.b, z10.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z18.b, z27.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: ursra z18.b, z27.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z26.h, z4.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: ursra z26.h, z4.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z25.h, z10.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: ursra z25.h, z10.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z17.s, z0.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: ursra z17.s, z0.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z0.s, z15.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: ursra z0.s, z15.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z4.d, z13.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: ursra z4.d, z13.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +ursra z26.d, z26.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: ursra z26.d, z26.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +ursra z0.b, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: ursra z0.b, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +ursra z0.d, z1.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: ursra z0.d, z1.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/ursra.s b/llvm/test/MC/AArch64/SVE2/ursra.s new file mode 100644 index 0000000000000..dfa1e8454962b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/ursra.s @@ -0,0 +1,72 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +ursra z0.b, z0.b, #1 +// CHECK-INST: ursra z0.b, z0.b, #1 +// CHECK-ENCODING: [0x00,0xec,0x0f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 ec 0f 45 + +ursra z31.b, z31.b, #8 +// CHECK-INST: ursra z31.b, z31.b, #8 +// CHECK-ENCODING: [0xff,0xef,0x08,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff ef 08 45 + +ursra z0.h, z0.h, #1 +// CHECK-INST: ursra z0.h, z0.h, #1 +// CHECK-ENCODING: [0x00,0xec,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 ec 1f 45 + +ursra z31.h, z31.h, #16 +// CHECK-INST: ursra z31.h, z31.h, #16 +// CHECK-ENCODING: [0xff,0xef,0x10,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff ef 10 45 + +ursra z0.s, z0.s, #1 +// CHECK-INST: ursra z0.s, z0.s, #1 +// CHECK-ENCODING: [0x00,0xec,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 ec 5f 45 + +ursra z31.s, z31.s, #32 +// CHECK-INST: ursra z31.s, z31.s, #32 +// CHECK-ENCODING: [0xff,0xef,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff ef 40 45 + +ursra z0.d, z0.d, #1 +// CHECK-INST: ursra z0.d, z0.d, #1 +// CHECK-ENCODING: [0x00,0xec,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 ec df 45 + +ursra z31.d, z31.d, #64 +// CHECK-INST: ursra z31.d, z31.d, #64 +// CHECK-ENCODING: [0xff,0xef,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff ef 80 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +ursra z0.d, z1.d, #1 +// CHECK-INST: ursra z0.d, z1.d, #1 +// CHECK-ENCODING: [0x20,0xec,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 ec df 45 diff --git a/llvm/test/MC/AArch64/SVE2/usra-diagnostics.s b/llvm/test/MC/AArch64/SVE2/usra-diagnostics.s new file mode 100644 index 0000000000000..bca811ec87740 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usra-diagnostics.s @@ -0,0 +1,60 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +usra z30.b, z10.b, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: usra z30.b, z10.b, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z18.b, z27.b, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: usra z18.b, z27.b, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z26.h, z4.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: usra z26.h, z4.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z25.h, z10.h, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: usra z25.h, z10.h, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z17.s, z0.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: usra z17.s, z0.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z0.s, z15.s, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: usra z0.s, z15.s, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z4.d, z13.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: usra z4.d, z13.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +usra z26.d, z26.d, #65 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 64] +// CHECK-NEXT: usra z26.d, z26.d, #65 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Element sizes must match + +usra z0.b, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: usra z0.b, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.d, p0/z, z7.d +usra z0.d, z1.d, #64 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a predicated movprfx, suggest using unpredicated movprfx +// CHECK-NEXT: usra z0.d, z1.d, #64 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/usra.s b/llvm/test/MC/AArch64/SVE2/usra.s new file mode 100644 index 0000000000000..6e7c35ad415f7 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/usra.s @@ -0,0 +1,72 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +usra z0.b, z0.b, #1 +// CHECK-INST: usra z0.b, z0.b, #1 +// CHECK-ENCODING: [0x00,0xe4,0x0f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e4 0f 45 + +usra z31.b, z31.b, #8 +// CHECK-INST: usra z31.b, z31.b, #8 +// CHECK-ENCODING: [0xff,0xe7,0x08,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e7 08 45 + +usra z0.h, z0.h, #1 +// CHECK-INST: usra z0.h, z0.h, #1 +// CHECK-ENCODING: [0x00,0xe4,0x1f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e4 1f 45 + +usra z31.h, z31.h, #16 +// CHECK-INST: usra z31.h, z31.h, #16 +// CHECK-ENCODING: [0xff,0xe7,0x10,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e7 10 45 + +usra z0.s, z0.s, #1 +// CHECK-INST: usra z0.s, z0.s, #1 +// CHECK-ENCODING: [0x00,0xe4,0x5f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e4 5f 45 + +usra z31.s, z31.s, #32 +// CHECK-INST: usra z31.s, z31.s, #32 +// CHECK-ENCODING: [0xff,0xe7,0x40,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e7 40 45 + +usra z0.d, z0.d, #1 +// CHECK-INST: usra z0.d, z0.d, #1 +// CHECK-ENCODING: [0x00,0xe4,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 e4 df 45 + +usra z31.d, z31.d, #64 +// CHECK-INST: usra z31.d, z31.d, #64 +// CHECK-ENCODING: [0xff,0xe7,0x80,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff e7 80 45 + + +// --------------------------------------------------------------------------// +// Test compatibility with MOVPRFX instruction. + +movprfx z0, z7 +// CHECK-INST: movprfx z0, z7 +// CHECK-ENCODING: [0xe0,0xbc,0x20,0x04] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: e0 bc 20 04 + +usra z0.d, z1.d, #1 +// CHECK-INST: usra z0.d, z1.d, #1 +// CHECK-ENCODING: [0x20,0xe4,0xdf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 e4 df 45 From cabab29af2d86ec03459cc3b57dd727b0a9c96d2 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Fri, 24 May 2019 10:18:39 +0000 Subject: [PATCH 0157/1176] [CodeComplete] Filter override completions by function name Summary: We put only part of the signature starting with a function name into "typed text" chunks now, previously the whole signature was "typed text". This leads to meaningful fuzzy match scores, giving better signals to compare with other completion items. Ideally, we would not display the result type to the user, but that requires adding a new kind of completion chunk. Reviewers: kadircet Reviewed By: kadircet Subscribers: jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62298 llvm-svn: 361623 --- .../clangd/unittests/CodeCompleteTests.cpp | 14 ++++-- clang/lib/Sema/SemaCodeComplete.cpp | 47 ++++++++++++------- clang/test/CodeCompletion/overrides.cpp | 12 ++--- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index e584597e7a90c..8f8376e25bc4c 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -49,6 +49,9 @@ class IgnoreDiagnostics : public DiagnosticsConsumer { // GMock helpers for matching completion items. MATCHER_P(Named, Name, "") { return arg.Name == Name; } +MATCHER_P(NameStartsWith, Prefix, "") { + return llvm::StringRef(arg.Name).startswith(Prefix); +} MATCHER_P(Scope, S, "") { return arg.Scope == S; } MATCHER_P(Qualifier, Q, "") { return arg.RequiredQualifier == Q; } MATCHER_P(Labeled, Label, "") { @@ -1946,10 +1949,13 @@ TEST(CompletionTest, SuggestOverrides) { }; )cpp"); const auto Results = completions(Text); - EXPECT_THAT(Results.Completions, - AllOf(Contains(Labeled("void vfunc(bool param, int p) override")), - Contains(Labeled("void ttt(bool param) const override")), - Not(Contains(Labeled("void vfunc(bool param) override"))))); + EXPECT_THAT( + Results.Completions, + AllOf(Contains(AllOf(Labeled("void vfunc(bool param, int p) override"), + NameStartsWith("vfunc"))), + Contains(AllOf(Labeled("void ttt(bool param) const override"), + NameStartsWith("ttt"))), + Not(Contains(Labeled("void vfunc(bool param) override"))))); } TEST(CompletionTest, OverridesNonIdentName) { diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index e6c0b68b8d5fd..27e684252f51d 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -37,6 +37,7 @@ #include "llvm/Support/Path.h" #include #include +#include #include using namespace clang; @@ -1828,19 +1829,6 @@ static void AddStaticAssertResult(CodeCompletionBuilder &Builder, Results.AddResult(CodeCompletionResult(Builder.TakeString())); } -static void printOverrideString(llvm::raw_ostream &OS, - CodeCompletionString *CCS) { - for (const auto &C : *CCS) { - if (C.Kind == CodeCompletionString::CK_Optional) - printOverrideString(OS, C.Optional); - else - OS << C.Text; - // Add a space after return type. - if (C.Kind == CodeCompletionString::CK_ResultType) - OS << ' '; - } -} - static void AddOverrideResults(ResultBuilder &Results, const CodeCompletionContext &CCContext, CodeCompletionBuilder &Builder) { @@ -3162,19 +3150,42 @@ CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( PP, Ctx, Result, IncludeBriefComments, CCContext, Policy); } +static void printOverrideString(const CodeCompletionString &CCS, + std::string &BeforeName, + std::string &NameAndSignature) { + bool SeenTypedChunk = false; + for (auto &Chunk : CCS) { + if (Chunk.Kind == CodeCompletionString::CK_Optional) { + assert(SeenTypedChunk && "optional parameter before name"); + // Note that we put all chunks inside into NameAndSignature. + printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature); + continue; + } + SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText; + if (SeenTypedChunk) + NameAndSignature += Chunk.Text; + else + BeforeName += Chunk.Text; + } +} + CodeCompletionString * CodeCompletionResult::createCodeCompletionStringForOverride( Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, bool IncludeBriefComments, const CodeCompletionContext &CCContext, PrintingPolicy &Policy) { - std::string OverrideSignature; - llvm::raw_string_ostream OS(OverrideSignature); auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result, /*IncludeBriefComments=*/false, CCContext, Policy); - printOverrideString(OS, CCS); - OS << " override"; - Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str())); + std::string BeforeName; + std::string NameAndSignature; + // For overrides all chunks go into the result, none are informative. + printOverrideString(*CCS, BeforeName, NameAndSignature); + NameAndSignature += " override"; + + Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName)); + Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature)); return Result.TakeString(); } diff --git a/clang/test/CodeCompletion/overrides.cpp b/clang/test/CodeCompletion/overrides.cpp index 06cff6af4d12f..6645569d82a77 100644 --- a/clang/test/CodeCompletion/overrides.cpp +++ b/clang/test/CodeCompletion/overrides.cpp @@ -11,23 +11,23 @@ void vfunc(bool param, int p) override; class C : public B { public: void vfunc(bool param) override; - void + vf }; -// Runs completion at ^void. +// Runs completion at ^vf // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:3 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}} // CHECK-CC1: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}} // CHECK-CC1-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}} // -// Runs completion at vo^id. +// Runs completion at vf^ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:5 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s -// CHECK-CC2: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}} // CHECK-CC2-NOT: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}} +// CHECK-CC2: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}} // CHECK-CC2-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}} // -// Runs completion at void ^. -// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s +// Runs completion at void ^ on line 13. +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:13:8 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3-NOT: COMPLETION: Pattern : int ttt(bool param, int x = 3) const override{{$}} // CHECK-CC3-NOT: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}} // CHECK-CC3-NOT: COMPLETION: Pattern : void vfunc(bool param) override{{$}} From adb1d74bf9e02952567c1a6e2149fb504cff2275 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 10:22:30 +0000 Subject: [PATCH 0158/1176] [AArch64][SVE2] Asm: support SVE2 Narrowing Group Summary: Patch adds support for the following instructions: SVE2 bitwise shift right narrow: * SQSHRUNB, SQSHRUNT, SQRSHRUNB, SQRSHRUNT, SHRNB, SHRNT, RSHRNB, RSHRNT, SQSHRNB, SQSHRNT, SQRSHRNB, SQRSHRNT, UQSHRNB, UQSHRNT, UQRSHRNB, UQRSHRNT SVE2 integer add/subtract narrow high part: * ADDHNB, ADDHNT, RADDHNB, RADDHNT, SUBHNB, SUBHNT, RSUBHNB, RSUBHNT SVE2 saturating extract narrow: * SQXTNB, SQXTNT, UQXTNB, UQXTNT, SQXTUNB, SQXTUNT The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D62205 llvm-svn: 361624 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 36 ++++++++ llvm/lib/Target/AArch64/SVEInstrFormats.td | 82 +++++++++++++++++++ .../test/MC/AArch64/SVE2/addhnb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/addhnb.s | 27 ++++++ .../test/MC/AArch64/SVE2/addhnt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/addhnt.s | 27 ++++++ .../MC/AArch64/SVE2/raddhnb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/raddhnb.s | 27 ++++++ .../MC/AArch64/SVE2/raddhnt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/raddhnt.s | 27 ++++++ .../test/MC/AArch64/SVE2/rshrnb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/rshrnb.s | 44 ++++++++++ .../test/MC/AArch64/SVE2/rshrnt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/rshrnt.s | 44 ++++++++++ .../MC/AArch64/SVE2/rsubhnb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/rsubhnb.s | 27 ++++++ .../MC/AArch64/SVE2/rsubhnt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/rsubhnt.s | 27 ++++++ llvm/test/MC/AArch64/SVE2/shrnb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/shrnb.s | 44 ++++++++++ llvm/test/MC/AArch64/SVE2/shrnt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/shrnt.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqrshrnb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqrshrnb.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqrshrnt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqrshrnt.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqrshrunb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqrshrunb.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqrshrunt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqrshrunt.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqshrnb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqshrnb.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqshrnt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqshrnt.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqshrunb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqshrunb.s | 44 ++++++++++ .../MC/AArch64/SVE2/sqshrunt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/sqshrunt.s | 44 ++++++++++ .../test/MC/AArch64/SVE2/sqxtnb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/sqxtnb.s | 27 ++++++ .../test/MC/AArch64/SVE2/sqxtnt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/sqxtnt.s | 27 ++++++ .../MC/AArch64/SVE2/sqxtunb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/sqxtunb.s | 27 ++++++ .../MC/AArch64/SVE2/sqxtunt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/sqxtunt.s | 27 ++++++ .../test/MC/AArch64/SVE2/subhnb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/subhnb.s | 27 ++++++ .../test/MC/AArch64/SVE2/subhnt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/subhnt.s | 27 ++++++ .../MC/AArch64/SVE2/uqrshrnb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/uqrshrnb.s | 44 ++++++++++ .../MC/AArch64/SVE2/uqrshrnt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/uqrshrnt.s | 44 ++++++++++ .../MC/AArch64/SVE2/uqshrnb-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/uqshrnb.s | 44 ++++++++++ .../MC/AArch64/SVE2/uqshrnt-diagnostics.s | 65 +++++++++++++++ llvm/test/MC/AArch64/SVE2/uqshrnt.s | 44 ++++++++++ .../test/MC/AArch64/SVE2/uqxtnb-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/uqxtnb.s | 27 ++++++ .../test/MC/AArch64/SVE2/uqxtnt-diagnostics.s | 40 +++++++++ llvm/test/MC/AArch64/SVE2/uqxtnt.s | 27 ++++++ 62 files changed, 2800 insertions(+) create mode 100644 llvm/test/MC/AArch64/SVE2/addhnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/addhnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/addhnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/addhnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/raddhnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/raddhnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/raddhnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/raddhnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/rshrnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/rshrnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/rshrnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/rshrnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/rsubhnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/rsubhnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/rsubhnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/rsubhnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/shrnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/shrnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/shrnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/shrnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrunb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrunb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrunt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqrshrunt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrunb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrunb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrunt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqshrunt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtunb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtunb.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtunt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/sqxtunt.s create mode 100644 llvm/test/MC/AArch64/SVE2/subhnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/subhnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/subhnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/subhnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshrnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshrnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshrnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqrshrnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshrnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshrnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshrnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqshrnt.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqxtnb-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqxtnb.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqxtnt-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/uqxtnt.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 3f48490bcc178..3e17e687bdc0b 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1228,6 +1228,42 @@ let Predicates = [HasSVE2] in { defm SBCLB_ZZZ : sve2_int_addsub_long_carry<0b10, "sbclb">; defm SBCLT_ZZZ : sve2_int_addsub_long_carry<0b11, "sbclt">; + // SVE2 bitwise shift right narrow + defm SQSHRUNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0000, "sqshrunb">; + defm SQSHRUNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0001, "sqshrunt">; + defm SQRSHRUNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0010, "sqrshrunb">; + defm SQRSHRUNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0011, "sqrshrunt">; + defm SHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0100, "shrnb">; + defm SHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0101, "shrnt">; + defm RSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0110, "rshrnb">; + defm RSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0111, "rshrnt">; + defm SQSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1000, "sqshrnb">; + defm SQSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1001, "sqshrnt">; + defm SQRSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1010, "sqrshrnb">; + defm SQRSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1011, "sqrshrnt">; + defm UQSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1100, "uqshrnb">; + defm UQSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1101, "uqshrnt">; + defm UQRSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1110, "uqrshrnb">; + defm UQRSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1111, "uqrshrnt">; + + // SVE2 integer add/subtract narrow high part + defm ADDHNB_ZZZ : sve2_int_addsub_narrow_high<0b000, "addhnb">; + defm ADDHNT_ZZZ : sve2_int_addsub_narrow_high<0b001, "addhnt">; + defm RADDHNB_ZZZ : sve2_int_addsub_narrow_high<0b010, "raddhnb">; + defm RADDHNT_ZZZ : sve2_int_addsub_narrow_high<0b011, "raddhnt">; + defm SUBHNB_ZZZ : sve2_int_addsub_narrow_high<0b100, "subhnb">; + defm SUBHNT_ZZZ : sve2_int_addsub_narrow_high<0b101, "subhnt">; + defm RSUBHNB_ZZZ : sve2_int_addsub_narrow_high<0b110, "rsubhnb">; + defm RSUBHNT_ZZZ : sve2_int_addsub_narrow_high<0b111, "rsubhnt">; + + // SVE2 saturating extract narrow + defm SQXTNB_ZZ : sve2_int_sat_extract_narrow<0b000, "sqxtnb">; + defm SQXTNT_ZZ : sve2_int_sat_extract_narrow<0b001, "sqxtnt">; + defm UQXTNB_ZZ : sve2_int_sat_extract_narrow<0b010, "uqxtnb">; + defm UQXTNT_ZZ : sve2_int_sat_extract_narrow<0b011, "uqxtnt">; + defm SQXTUNB_ZZ : sve2_int_sat_extract_narrow<0b100, "sqxtunb">; + defm SQXTUNT_ZZ : sve2_int_sat_extract_narrow<0b101, "sqxtunt">; + // Predicated shifts defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 90c8076d2907f..c4c890a63ecd0 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -2347,6 +2347,88 @@ multiclass sve2_int_addsub_long_carry opc, string asm> { ZPR64, ZPR64>; } +//===----------------------------------------------------------------------===// +// SVE2 Narrowing Group +//===----------------------------------------------------------------------===// + +class sve2_int_bin_cons_shift_imm_narrow tsz8_64, bits<4> opc, + string asm, ZPRRegOp zprty1, + ZPRRegOp zprty2, Operand immtype> +: I<(outs zprty1:$Zd), (ins zprty2:$Zn, immtype:$imm), + asm, "\t$Zd, $Zn, $imm", + "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + bits<5> imm; + let Inst{31-23} = 0b010001010; + let Inst{22} = tsz8_64{2}; + let Inst{21} = 0b1; + let Inst{20-19} = tsz8_64{1-0}; + let Inst{18-16} = imm{2-0}; // imm3 + let Inst{15-14} = 0b00; + let Inst{13-10} = opc; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2_int_bin_cons_shift_imm_right_narrow opc, string asm> { + def _B : sve2_int_bin_cons_shift_imm_narrow<{0,0,1}, opc, asm, ZPR8, ZPR16, + vecshiftR8>; + def _H : sve2_int_bin_cons_shift_imm_narrow<{0,1,?}, opc, asm, ZPR16, ZPR32, + vecshiftR16> { + let Inst{19} = imm{3}; + } + def _S : sve2_int_bin_cons_shift_imm_narrow<{1,?,?}, opc, asm, ZPR32, ZPR64, + vecshiftR32> { + let Inst{20-19} = imm{4-3}; + } +} + +class sve2_int_addsub_narrow_high sz, bits<3> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> +: I<(outs zprty1:$Zd), (ins zprty2:$Zn, zprty2:$Zm), + asm, "\t$Zd, $Zn, $Zm", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + bits<5> Zm; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = sz; + let Inst{21} = 0b1; + let Inst{20-16} = Zm; + let Inst{15-13} = 0b011; + let Inst{12-10} = opc; // S, R, T + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2_int_addsub_narrow_high opc, string asm> { + def _B : sve2_int_addsub_narrow_high<0b01, opc, asm, ZPR8, ZPR16>; + def _H : sve2_int_addsub_narrow_high<0b10, opc, asm, ZPR16, ZPR32>; + def _S : sve2_int_addsub_narrow_high<0b11, opc, asm, ZPR32, ZPR64>; +} + +class sve2_int_sat_extract_narrow tsz8_64, bits<3> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> +: I<(outs zprty1:$Zd), (ins zprty2:$Zn), + asm, "\t$Zd, $Zn", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + let Inst{31-23} = 0b010001010; + let Inst{22} = tsz8_64{2}; + let Inst{21} = 0b1; + let Inst{20-19} = tsz8_64{1-0}; + let Inst{18-13} = 0b000010; + let Inst{12-10} = opc; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2_int_sat_extract_narrow opc, string asm> { + def _B : sve2_int_sat_extract_narrow<0b001, opc, asm, ZPR8, ZPR16>; + def _H : sve2_int_sat_extract_narrow<0b010, opc, asm, ZPR16, ZPR32>; + def _S : sve2_int_sat_extract_narrow<0b100, opc, asm, ZPR32, ZPR64>; +} + //===----------------------------------------------------------------------===// // SVE Integer Arithmetic - Unary Predicated Group //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SVE2/addhnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/addhnb-diagnostics.s new file mode 100644 index 0000000000000..c85456ab8e319 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/addhnb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +addhnb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addhnb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addhnb z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnb z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addhnb z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnb z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +addhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: addhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +addhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: addhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/addhnb.s b/llvm/test/MC/AArch64/SVE2/addhnb.s new file mode 100644 index 0000000000000..fa9e855634bac --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/addhnb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +addhnb z0.b, z1.h, z31.h +// CHECK-INST: addhnb z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x60,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 60 7f 45 + +addhnb z0.h, z1.s, z31.s +// CHECK-INST: addhnb z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x60,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 60 bf 45 + +addhnb z0.s, z1.d, z31.d +// CHECK-INST: addhnb z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x60,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 60 ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/addhnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/addhnt-diagnostics.s new file mode 100644 index 0000000000000..0bebf9236bf43 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/addhnt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +addhnt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addhnt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addhnt z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnt z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addhnt z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addhnt z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +addhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: addhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +addhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: addhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/addhnt.s b/llvm/test/MC/AArch64/SVE2/addhnt.s new file mode 100644 index 0000000000000..fe77e5abe713e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/addhnt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +addhnt z0.b, z1.h, z31.h +// CHECK-INST: addhnt z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x64,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 64 7f 45 + +addhnt z0.h, z1.s, z31.s +// CHECK-INST: addhnt z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x64,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 64 bf 45 + +addhnt z0.s, z1.d, z31.d +// CHECK-INST: addhnt z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x64,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 64 ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/raddhnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/raddhnb-diagnostics.s new file mode 100644 index 0000000000000..94a3cbb81dc4c --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/raddhnb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +raddhnb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +raddhnb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +raddhnb z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnb z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +raddhnb z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnb z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +raddhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: raddhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +raddhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: raddhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/raddhnb.s b/llvm/test/MC/AArch64/SVE2/raddhnb.s new file mode 100644 index 0000000000000..ff04d6b512c0f --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/raddhnb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +raddhnb z0.b, z1.h, z31.h +// CHECK-INST: raddhnb z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x68,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 68 7f 45 + +raddhnb z0.h, z1.s, z31.s +// CHECK-INST: raddhnb z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x68,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 68 bf 45 + +raddhnb z0.s, z1.d, z31.d +// CHECK-INST: raddhnb z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x68,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 68 ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/raddhnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/raddhnt-diagnostics.s new file mode 100644 index 0000000000000..87ddd59464451 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/raddhnt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +raddhnt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +raddhnt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +raddhnt z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnt z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +raddhnt z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: raddhnt z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +raddhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: raddhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +raddhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: raddhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/raddhnt.s b/llvm/test/MC/AArch64/SVE2/raddhnt.s new file mode 100644 index 0000000000000..f6e79af85e5e7 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/raddhnt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +raddhnt z0.b, z1.h, z31.h +// CHECK-INST: raddhnt z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x6c,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 6c 7f 45 + +raddhnt z0.h, z1.s, z31.s +// CHECK-INST: raddhnt z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x6c,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 6c bf 45 + +raddhnt z0.s, z1.d, z31.d +// CHECK-INST: raddhnt z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x6c,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 6c ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/rshrnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/rshrnb-diagnostics.s new file mode 100644 index 0000000000000..f8a1758c81923 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rshrnb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +rshrnb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: rshrnb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: rshrnb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: rshrnb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: rshrnb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: rshrnb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: rshrnb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +rshrnb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +rshrnb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: rshrnb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/rshrnb.s b/llvm/test/MC/AArch64/SVE2/rshrnb.s new file mode 100644 index 0000000000000..1d503099b1452 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rshrnb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +rshrnb z0.b, z0.h, #1 +// CHECK-INST: rshrnb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x18,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 18 2f 45 + +rshrnb z31.b, z31.h, #8 +// CHECK-INST: rshrnb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x1b,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1b 28 45 + +rshrnb z0.h, z0.s, #1 +// CHECK-INST: rshrnb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x18,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 18 3f 45 + +rshrnb z31.h, z31.s, #16 +// CHECK-INST: rshrnb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x1b,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1b 30 45 + +rshrnb z0.s, z0.d, #1 +// CHECK-INST: rshrnb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x18,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 18 7f 45 + +rshrnb z31.s, z31.d, #32 +// CHECK-INST: rshrnb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x1b,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1b 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/rshrnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/rshrnt-diagnostics.s new file mode 100644 index 0000000000000..820ff0f2f7f70 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rshrnt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +rshrnt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: rshrnt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: rshrnt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: rshrnt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: rshrnt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: rshrnt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: rshrnt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +rshrnt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rshrnt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rshrnt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +rshrnt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: rshrnt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/rshrnt.s b/llvm/test/MC/AArch64/SVE2/rshrnt.s new file mode 100644 index 0000000000000..4e997d841e7ec --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rshrnt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +rshrnt z0.b, z0.h, #1 +// CHECK-INST: rshrnt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x1c,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 1c 2f 45 + +rshrnt z31.b, z31.h, #8 +// CHECK-INST: rshrnt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x1f,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1f 28 45 + +rshrnt z0.h, z0.s, #1 +// CHECK-INST: rshrnt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x1c,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 1c 3f 45 + +rshrnt z31.h, z31.s, #16 +// CHECK-INST: rshrnt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x1f,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1f 30 45 + +rshrnt z0.s, z0.d, #1 +// CHECK-INST: rshrnt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x1c,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 1c 7f 45 + +rshrnt z31.s, z31.d, #32 +// CHECK-INST: rshrnt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x1f,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 1f 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/rsubhnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/rsubhnb-diagnostics.s new file mode 100644 index 0000000000000..2b3dbd7592cf5 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rsubhnb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +rsubhnb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rsubhnb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rsubhnb z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnb z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rsubhnb z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnb z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +rsubhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: rsubhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +rsubhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: rsubhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/rsubhnb.s b/llvm/test/MC/AArch64/SVE2/rsubhnb.s new file mode 100644 index 0000000000000..55a93177d78e6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rsubhnb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +rsubhnb z0.b, z1.h, z31.h +// CHECK-INST: rsubhnb z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x78,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 78 7f 45 + +rsubhnb z0.h, z1.s, z31.s +// CHECK-INST: rsubhnb z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x78,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 78 bf 45 + +rsubhnb z0.s, z1.d, z31.d +// CHECK-INST: rsubhnb z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x78,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 78 ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/rsubhnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/rsubhnt-diagnostics.s new file mode 100644 index 0000000000000..305dc061852c6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rsubhnt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +rsubhnt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rsubhnt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rsubhnt z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnt z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +rsubhnt z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: rsubhnt z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +rsubhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: rsubhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +rsubhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: rsubhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/rsubhnt.s b/llvm/test/MC/AArch64/SVE2/rsubhnt.s new file mode 100644 index 0000000000000..16505e5e31787 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/rsubhnt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +rsubhnt z0.b, z1.h, z31.h +// CHECK-INST: rsubhnt z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x7c,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 7c 7f 45 + +rsubhnt z0.h, z1.s, z31.s +// CHECK-INST: rsubhnt z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x7c,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 7c bf 45 + +rsubhnt z0.s, z1.d, z31.d +// CHECK-INST: rsubhnt z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x7c,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 7c ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/shrnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/shrnb-diagnostics.s new file mode 100644 index 0000000000000..b54b45a9e0eb6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/shrnb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +shrnb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: shrnb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: shrnb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: shrnb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: shrnb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: shrnb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: shrnb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +shrnb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +shrnb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: shrnb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/shrnb.s b/llvm/test/MC/AArch64/SVE2/shrnb.s new file mode 100644 index 0000000000000..e59f35a275cd5 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/shrnb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +shrnb z0.b, z0.h, #1 +// CHECK-INST: shrnb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x10,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 10 2f 45 + +shrnb z31.b, z31.h, #8 +// CHECK-INST: shrnb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x13,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 13 28 45 + +shrnb z0.h, z0.s, #1 +// CHECK-INST: shrnb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x10,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 10 3f 45 + +shrnb z31.h, z31.s, #16 +// CHECK-INST: shrnb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x13,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 13 30 45 + +shrnb z0.s, z0.d, #1 +// CHECK-INST: shrnb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x10,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 10 7f 45 + +shrnb z31.s, z31.d, #32 +// CHECK-INST: shrnb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x13,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 13 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/shrnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/shrnt-diagnostics.s new file mode 100644 index 0000000000000..bf1717bd7bf9b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/shrnt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +shrnt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: shrnt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: shrnt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: shrnt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: shrnt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: shrnt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: shrnt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +shrnt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +shrnt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: shrnt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +shrnt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: shrnt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/shrnt.s b/llvm/test/MC/AArch64/SVE2/shrnt.s new file mode 100644 index 0000000000000..539f415a2de74 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/shrnt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +shrnt z0.b, z0.h, #1 +// CHECK-INST: shrnt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x14,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 14 2f 45 + +shrnt z31.b, z31.h, #8 +// CHECK-INST: shrnt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x17,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 17 28 45 + +shrnt z0.h, z0.s, #1 +// CHECK-INST: shrnt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x14,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 14 3f 45 + +shrnt z31.h, z31.s, #16 +// CHECK-INST: shrnt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x17,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 17 30 45 + +shrnt z0.s, z0.d, #1 +// CHECK-INST: shrnt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x14,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 14 7f 45 + +shrnt z31.s, z31.d, #32 +// CHECK-INST: shrnt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x17,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 17 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqrshrnb-diagnostics.s new file mode 100644 index 0000000000000..1748e77ae2cd6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrnb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqrshrnb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrnb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrnb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrnb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrnb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrnb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrnb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqrshrnb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqrshrnb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqrshrnb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrnb.s b/llvm/test/MC/AArch64/SVE2/sqrshrnb.s new file mode 100644 index 0000000000000..d5c6e8cd85138 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrnb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqrshrnb z0.b, z0.h, #1 +// CHECK-INST: sqrshrnb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x28,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 28 2f 45 + +sqrshrnb z31.b, z31.h, #8 +// CHECK-INST: sqrshrnb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x2b,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 2b 28 45 + +sqrshrnb z0.h, z0.s, #1 +// CHECK-INST: sqrshrnb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x28,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 28 3f 45 + +sqrshrnb z31.h, z31.s, #16 +// CHECK-INST: sqrshrnb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x2b,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 2b 30 45 + +sqrshrnb z0.s, z0.d, #1 +// CHECK-INST: sqrshrnb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x28,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 28 7f 45 + +sqrshrnb z31.s, z31.d, #32 +// CHECK-INST: sqrshrnb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x2b,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 2b 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqrshrnt-diagnostics.s new file mode 100644 index 0000000000000..7fef281c81d73 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrnt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqrshrnt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrnt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrnt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrnt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrnt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrnt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrnt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqrshrnt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrnt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrnt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqrshrnt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqrshrnt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrnt.s b/llvm/test/MC/AArch64/SVE2/sqrshrnt.s new file mode 100644 index 0000000000000..f299e9db34804 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrnt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqrshrnt z0.b, z0.h, #1 +// CHECK-INST: sqrshrnt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x2c,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 2c 2f 45 + +sqrshrnt z31.b, z31.h, #8 +// CHECK-INST: sqrshrnt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x2f,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 2f 28 45 + +sqrshrnt z0.h, z0.s, #1 +// CHECK-INST: sqrshrnt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x2c,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 2c 3f 45 + +sqrshrnt z31.h, z31.s, #16 +// CHECK-INST: sqrshrnt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x2f,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 2f 30 45 + +sqrshrnt z0.s, z0.d, #1 +// CHECK-INST: sqrshrnt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x2c,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 2c 7f 45 + +sqrshrnt z31.s, z31.d, #32 +// CHECK-INST: sqrshrnt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x2f,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 2f 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrunb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqrshrunb-diagnostics.s new file mode 100644 index 0000000000000..b4dc68109a61d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrunb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqrshrunb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrunb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrunb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrunb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrunb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrunb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrunb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqrshrunb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqrshrunb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqrshrunb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrunb.s b/llvm/test/MC/AArch64/SVE2/sqrshrunb.s new file mode 100644 index 0000000000000..2380347f8c34b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrunb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqrshrunb z0.b, z0.h, #1 +// CHECK-INST: sqrshrunb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x08,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 08 2f 45 + +sqrshrunb z31.b, z31.h, #8 +// CHECK-INST: sqrshrunb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x0b,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0b 28 45 + +sqrshrunb z0.h, z0.s, #1 +// CHECK-INST: sqrshrunb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x08,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 08 3f 45 + +sqrshrunb z31.h, z31.s, #16 +// CHECK-INST: sqrshrunb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x0b,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0b 30 45 + +sqrshrunb z0.s, z0.d, #1 +// CHECK-INST: sqrshrunb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x08,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 08 7f 45 + +sqrshrunb z31.s, z31.d, #32 +// CHECK-INST: sqrshrunb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x0b,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0b 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrunt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqrshrunt-diagnostics.s new file mode 100644 index 0000000000000..4ff61510759a0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrunt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqrshrunt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrunt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqrshrunt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrunt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqrshrunt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrunt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqrshrunt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqrshrunt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqrshrunt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqrshrunt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqrshrunt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqrshrunt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqrshrunt.s b/llvm/test/MC/AArch64/SVE2/sqrshrunt.s new file mode 100644 index 0000000000000..95f060db6231c --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqrshrunt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqrshrunt z0.b, z0.h, #1 +// CHECK-INST: sqrshrunt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x0c,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 0c 2f 45 + +sqrshrunt z31.b, z31.h, #8 +// CHECK-INST: sqrshrunt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x0f,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0f 28 45 + +sqrshrunt z0.h, z0.s, #1 +// CHECK-INST: sqrshrunt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x0c,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 0c 3f 45 + +sqrshrunt z31.h, z31.s, #16 +// CHECK-INST: sqrshrunt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x0f,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0f 30 45 + +sqrshrunt z0.s, z0.d, #1 +// CHECK-INST: sqrshrunt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x0c,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 0c 7f 45 + +sqrshrunt z31.s, z31.d, #32 +// CHECK-INST: sqrshrunt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x0f,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 0f 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqshrnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshrnb-diagnostics.s new file mode 100644 index 0000000000000..09a98bcfe21a8 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrnb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqshrnb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrnb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrnb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrnb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrnb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrnb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrnb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqshrnb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqshrnb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqshrnb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshrnb.s b/llvm/test/MC/AArch64/SVE2/sqshrnb.s new file mode 100644 index 0000000000000..e829f4995f0c6 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrnb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshrnb z0.b, z0.h, #1 +// CHECK-INST: sqshrnb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x20,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 20 2f 45 + +sqshrnb z31.b, z31.h, #8 +// CHECK-INST: sqshrnb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x23,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 23 28 45 + +sqshrnb z0.h, z0.s, #1 +// CHECK-INST: sqshrnb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x20,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 20 3f 45 + +sqshrnb z31.h, z31.s, #16 +// CHECK-INST: sqshrnb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x23,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 23 30 45 + +sqshrnb z0.s, z0.d, #1 +// CHECK-INST: sqshrnb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x20,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 20 7f 45 + +sqshrnb z31.s, z31.d, #32 +// CHECK-INST: sqshrnb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x23,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 23 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqshrnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshrnt-diagnostics.s new file mode 100644 index 0000000000000..199741bef6f4a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrnt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqshrnt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrnt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrnt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrnt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrnt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrnt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrnt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqshrnt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrnt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrnt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqshrnt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqshrnt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshrnt.s b/llvm/test/MC/AArch64/SVE2/sqshrnt.s new file mode 100644 index 0000000000000..f57b2c00369a8 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrnt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshrnt z0.b, z0.h, #1 +// CHECK-INST: sqshrnt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x24,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 24 2f 45 + +sqshrnt z31.b, z31.h, #8 +// CHECK-INST: sqshrnt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x27,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 27 28 45 + +sqshrnt z0.h, z0.s, #1 +// CHECK-INST: sqshrnt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x24,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 24 3f 45 + +sqshrnt z31.h, z31.s, #16 +// CHECK-INST: sqshrnt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x27,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 27 30 45 + +sqshrnt z0.s, z0.d, #1 +// CHECK-INST: sqshrnt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x24,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 24 7f 45 + +sqshrnt z31.s, z31.d, #32 +// CHECK-INST: sqshrnt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x27,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 27 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqshrunb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshrunb-diagnostics.s new file mode 100644 index 0000000000000..d157918dbaa9e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrunb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqshrunb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrunb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrunb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrunb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrunb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrunb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrunb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqshrunb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqshrunb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqshrunb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshrunb.s b/llvm/test/MC/AArch64/SVE2/sqshrunb.s new file mode 100644 index 0000000000000..8275da0f16ff3 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrunb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshrunb z0.b, z0.h, #1 +// CHECK-INST: sqshrunb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x00,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 00 2f 45 + +sqshrunb z31.b, z31.h, #8 +// CHECK-INST: sqshrunb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x03,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 03 28 45 + +sqshrunb z0.h, z0.s, #1 +// CHECK-INST: sqshrunb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x00,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 00 3f 45 + +sqshrunb z31.h, z31.s, #16 +// CHECK-INST: sqshrunb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x03,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 03 30 45 + +sqshrunb z0.s, z0.d, #1 +// CHECK-INST: sqshrunb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x00,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 00 7f 45 + +sqshrunb z31.s, z31.d, #32 +// CHECK-INST: sqshrunb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x03,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 03 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqshrunt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqshrunt-diagnostics.s new file mode 100644 index 0000000000000..072870648467c --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrunt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +sqshrunt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrunt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: sqshrunt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrunt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: sqshrunt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrunt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: sqshrunt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +sqshrunt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqshrunt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqshrunt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +sqshrunt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqshrunt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqshrunt.s b/llvm/test/MC/AArch64/SVE2/sqshrunt.s new file mode 100644 index 0000000000000..86d62285a6134 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqshrunt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +sqshrunt z0.b, z0.h, #1 +// CHECK-INST: sqshrunt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x04,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 04 2f 45 + +sqshrunt z31.b, z31.h, #8 +// CHECK-INST: sqshrunt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x07,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 07 28 45 + +sqshrunt z0.h, z0.s, #1 +// CHECK-INST: sqshrunt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x04,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 04 3f 45 + +sqshrunt z31.h, z31.s, #16 +// CHECK-INST: sqshrunt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x07,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 07 30 45 + +sqshrunt z0.s, z0.d, #1 +// CHECK-INST: sqshrunt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x04,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 04 7f 45 + +sqshrunt z31.s, z31.d, #32 +// CHECK-INST: sqshrunt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x07,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 07 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqxtnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqxtnb-diagnostics.s new file mode 100644 index 0000000000000..bfce6761aaafa --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtnb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sqxtnb z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnb z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtnb z0.h, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnb z0.h, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtnb z0.s, z1.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnb z0.s, z1.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtnb z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnb z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqxtnb z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtnb z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +sqxtnb z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtnb z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqxtnb.s b/llvm/test/MC/AArch64/SVE2/sqxtnb.s new file mode 100644 index 0000000000000..7f0dcea20a3e8 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtnb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sqxtnb z0.b, z31.h +// CHECK-INST: sqxtnb z0.b, z31.h +// CHECK-ENCODING: [0xe0,0x43,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 43 28 45 + +sqxtnb z0.h, z31.s +// CHECK-INST: sqxtnb z0.h, z31.s +// CHECK-ENCODING: [0xe0,0x43,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 43 30 45 + +sqxtnb z0.s, z31.d +// CHECK-INST: sqxtnb z0.s, z31.d +// CHECK-ENCODING: [0xe0,0x43,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 43 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqxtnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqxtnt-diagnostics.s new file mode 100644 index 0000000000000..2a137d09eb81e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtnt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sqxtnt z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnt z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtnt z0.h, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnt z0.h, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtnt z0.s, z1.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnt z0.s, z1.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtnt z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtnt z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqxtnt z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtnt z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +sqxtnt z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtnt z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqxtnt.s b/llvm/test/MC/AArch64/SVE2/sqxtnt.s new file mode 100644 index 0000000000000..9715b97b14f25 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtnt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sqxtnt z0.b, z31.h +// CHECK-INST: sqxtnt z0.b, z31.h +// CHECK-ENCODING: [0xe0,0x47,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 47 28 45 + +sqxtnt z0.h, z31.s +// CHECK-INST: sqxtnt z0.h, z31.s +// CHECK-ENCODING: [0xe0,0x47,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 47 30 45 + +sqxtnt z0.s, z31.d +// CHECK-INST: sqxtnt z0.s, z31.d +// CHECK-ENCODING: [0xe0,0x47,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 47 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqxtunb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqxtunb-diagnostics.s new file mode 100644 index 0000000000000..0f1be1a05243d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtunb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sqxtunb z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunb z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtunb z0.h, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunb z0.h, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtunb z0.s, z1.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunb z0.s, z1.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtunb z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunb z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqxtunb z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtunb z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +sqxtunb z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtunb z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqxtunb.s b/llvm/test/MC/AArch64/SVE2/sqxtunb.s new file mode 100644 index 0000000000000..6db3885001226 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtunb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sqxtunb z0.b, z31.h +// CHECK-INST: sqxtunb z0.b, z31.h +// CHECK-ENCODING: [0xe0,0x53,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 53 28 45 + +sqxtunb z0.h, z31.s +// CHECK-INST: sqxtunb z0.h, z31.s +// CHECK-ENCODING: [0xe0,0x53,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 53 30 45 + +sqxtunb z0.s, z31.d +// CHECK-INST: sqxtunb z0.s, z31.d +// CHECK-ENCODING: [0xe0,0x53,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 53 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/sqxtunt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/sqxtunt-diagnostics.s new file mode 100644 index 0000000000000..42a7cca3f831e --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtunt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +sqxtunt z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunt z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtunt z0.h, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunt z0.h, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtunt z0.s, z1.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunt z0.s, z1.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sqxtunt z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sqxtunt z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +sqxtunt z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtunt z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +sqxtunt z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: sqxtunt z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/sqxtunt.s b/llvm/test/MC/AArch64/SVE2/sqxtunt.s new file mode 100644 index 0000000000000..bd09163c08bcc --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/sqxtunt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +sqxtunt z0.b, z31.h +// CHECK-INST: sqxtunt z0.b, z31.h +// CHECK-ENCODING: [0xe0,0x57,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 57 28 45 + +sqxtunt z0.h, z31.s +// CHECK-INST: sqxtunt z0.h, z31.s +// CHECK-ENCODING: [0xe0,0x57,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 57 30 45 + +sqxtunt z0.s, z31.d +// CHECK-INST: sqxtunt z0.s, z31.d +// CHECK-ENCODING: [0xe0,0x57,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 57 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/subhnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/subhnb-diagnostics.s new file mode 100644 index 0000000000000..3d8dd545fecb0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/subhnb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +subhnb z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnb z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subhnb z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnb z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subhnb z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnb z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subhnb z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnb z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +subhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: subhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +subhnb z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: subhnb z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/subhnb.s b/llvm/test/MC/AArch64/SVE2/subhnb.s new file mode 100644 index 0000000000000..4b90166a5b048 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/subhnb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +subhnb z0.b, z1.h, z31.h +// CHECK-INST: subhnb z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x70,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 70 7f 45 + +subhnb z0.h, z1.s, z31.s +// CHECK-INST: subhnb z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x70,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 70 bf 45 + +subhnb z0.s, z1.d, z31.d +// CHECK-INST: subhnb z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x70,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 70 ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/subhnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/subhnt-diagnostics.s new file mode 100644 index 0000000000000..2c0b2fd107384 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/subhnt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +subhnt z0.b, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnt z0.b, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subhnt z0.h, z1.h, z2.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnt z0.h, z1.h, z2.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subhnt z0.s, z1.s, z2.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnt z0.s, z1.s, z2.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subhnt z0.d, z1.d, z2.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subhnt z0.d, z1.d, z2.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +subhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: subhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +subhnt z0.s, z1.d, z31.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: subhnt z0.s, z1.d, z31.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/subhnt.s b/llvm/test/MC/AArch64/SVE2/subhnt.s new file mode 100644 index 0000000000000..624147e66b829 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/subhnt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +subhnt z0.b, z1.h, z31.h +// CHECK-INST: subhnt z0.b, z1.h, z31.h +// CHECK-ENCODING: [0x20,0x74,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 74 7f 45 + +subhnt z0.h, z1.s, z31.s +// CHECK-INST: subhnt z0.h, z1.s, z31.s +// CHECK-ENCODING: [0x20,0x74,0xbf,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 74 bf 45 + +subhnt z0.s, z1.d, z31.d +// CHECK-INST: subhnt z0.s, z1.d, z31.d +// CHECK-ENCODING: [0x20,0x74,0xff,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 20 74 ff 45 diff --git a/llvm/test/MC/AArch64/SVE2/uqrshrnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqrshrnb-diagnostics.s new file mode 100644 index 0000000000000..8e87ad29b2368 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshrnb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +uqrshrnb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqrshrnb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqrshrnb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqrshrnb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqrshrnb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqrshrnb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqrshrnb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +uqrshrnb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +uqrshrnb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqrshrnb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqrshrnb.s b/llvm/test/MC/AArch64/SVE2/uqrshrnb.s new file mode 100644 index 0000000000000..a10b02f097b35 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshrnb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqrshrnb z0.b, z0.h, #1 +// CHECK-INST: uqrshrnb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x38,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 38 2f 45 + +uqrshrnb z31.b, z31.h, #8 +// CHECK-INST: uqrshrnb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x3b,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3b 28 45 + +uqrshrnb z0.h, z0.s, #1 +// CHECK-INST: uqrshrnb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x38,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 38 3f 45 + +uqrshrnb z31.h, z31.s, #16 +// CHECK-INST: uqrshrnb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x3b,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3b 30 45 + +uqrshrnb z0.s, z0.d, #1 +// CHECK-INST: uqrshrnb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x38,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 38 7f 45 + +uqrshrnb z31.s, z31.d, #32 +// CHECK-INST: uqrshrnb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x3b,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3b 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/uqrshrnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqrshrnt-diagnostics.s new file mode 100644 index 0000000000000..34f9829873dce --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshrnt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +uqrshrnt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqrshrnt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqrshrnt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqrshrnt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqrshrnt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqrshrnt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqrshrnt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +uqrshrnt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqrshrnt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqrshrnt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +uqrshrnt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqrshrnt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqrshrnt.s b/llvm/test/MC/AArch64/SVE2/uqrshrnt.s new file mode 100644 index 0000000000000..6eaf48440f78a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqrshrnt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqrshrnt z0.b, z0.h, #1 +// CHECK-INST: uqrshrnt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x3c,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 3c 2f 45 + +uqrshrnt z31.b, z31.h, #8 +// CHECK-INST: uqrshrnt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x3f,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3f 28 45 + +uqrshrnt z0.h, z0.s, #1 +// CHECK-INST: uqrshrnt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x3c,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 3c 3f 45 + +uqrshrnt z31.h, z31.s, #16 +// CHECK-INST: uqrshrnt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x3f,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3f 30 45 + +uqrshrnt z0.s, z0.d, #1 +// CHECK-INST: uqrshrnt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x3c,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 3c 7f 45 + +uqrshrnt z31.s, z31.d, #32 +// CHECK-INST: uqrshrnt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x3f,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 3f 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/uqshrnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqshrnb-diagnostics.s new file mode 100644 index 0000000000000..a5c6b10150860 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshrnb-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +uqshrnb z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqshrnb z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqshrnb z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqshrnb z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqshrnb z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqshrnb z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqshrnb z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +uqshrnb z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnb z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnb z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnb z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnb z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnb z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +uqshrnb z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqshrnb z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqshrnb.s b/llvm/test/MC/AArch64/SVE2/uqshrnb.s new file mode 100644 index 0000000000000..9f04d2346da08 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshrnb.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqshrnb z0.b, z0.h, #1 +// CHECK-INST: uqshrnb z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x30,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 30 2f 45 + +uqshrnb z31.b, z31.h, #8 +// CHECK-INST: uqshrnb z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x33,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 33 28 45 + +uqshrnb z0.h, z0.s, #1 +// CHECK-INST: uqshrnb z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x30,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 30 3f 45 + +uqshrnb z31.h, z31.s, #16 +// CHECK-INST: uqshrnb z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x33,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 33 30 45 + +uqshrnb z0.s, z0.d, #1 +// CHECK-INST: uqshrnb z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x30,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 30 7f 45 + +uqshrnb z31.s, z31.d, #32 +// CHECK-INST: uqshrnb z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x33,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 33 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/uqshrnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqshrnt-diagnostics.s new file mode 100644 index 0000000000000..562b8695f7665 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshrnt-diagnostics.s @@ -0,0 +1,65 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +uqshrnt z30.b, z10.h, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqshrnt z30.b, z10.h, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z18.b, z27.h, #9 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 8] +// CHECK-NEXT: uqshrnt z18.b, z27.h, #9 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z26.h, z4.s, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqshrnt z26.h, z4.s, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z25.h, z10.s, #17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 16] +// CHECK-NEXT: uqshrnt z25.h, z10.s, #17 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z17.s, z0.d, #0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqshrnt z17.s, z0.d, #0 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z0.s, z15.d, #33 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [1, 32] +// CHECK-NEXT: uqshrnt z0.s, z15.d, #33 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid element width + +uqshrnt z0.b, z0.b, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnt z0.b, z0.b, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z0.h, z0.h, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnt z0.h, z0.h, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z0.s, z0.s, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnt z0.s, z0.s, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqshrnt z0.d, z0.d, #1 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqshrnt z0.d, z0.d, #1 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z31, z6 +uqshrnt z31.s, z31.d, #32 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqshrnt z31.s, z31.d, #32 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqshrnt.s b/llvm/test/MC/AArch64/SVE2/uqshrnt.s new file mode 100644 index 0000000000000..dc151a2c786c7 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqshrnt.s @@ -0,0 +1,44 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +uqshrnt z0.b, z0.h, #1 +// CHECK-INST: uqshrnt z0.b, z0.h, #1 +// CHECK-ENCODING: [0x00,0x34,0x2f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 34 2f 45 + +uqshrnt z31.b, z31.h, #8 +// CHECK-INST: uqshrnt z31.b, z31.h, #8 +// CHECK-ENCODING: [0xff,0x37,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 37 28 45 + +uqshrnt z0.h, z0.s, #1 +// CHECK-INST: uqshrnt z0.h, z0.s, #1 +// CHECK-ENCODING: [0x00,0x34,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 34 3f 45 + +uqshrnt z31.h, z31.s, #16 +// CHECK-INST: uqshrnt z31.h, z31.s, #16 +// CHECK-ENCODING: [0xff,0x37,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 37 30 45 + +uqshrnt z0.s, z0.d, #1 +// CHECK-INST: uqshrnt z0.s, z0.d, #1 +// CHECK-ENCODING: [0x00,0x34,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 34 7f 45 + +uqshrnt z31.s, z31.d, #32 +// CHECK-INST: uqshrnt z31.s, z31.d, #32 +// CHECK-ENCODING: [0xff,0x37,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: ff 37 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/uqxtnb-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqxtnb-diagnostics.s new file mode 100644 index 0000000000000..5868197b94490 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqxtnb-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uqxtnb z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnb z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqxtnb z0.h, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnb z0.h, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqxtnb z0.s, z1.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnb z0.s, z1.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqxtnb z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnb z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +uqxtnb z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqxtnb z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +uqxtnb z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqxtnb z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqxtnb.s b/llvm/test/MC/AArch64/SVE2/uqxtnb.s new file mode 100644 index 0000000000000..e0361addc8eec --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqxtnb.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uqxtnb z0.b, z31.h +// CHECK-INST: uqxtnb z0.b, z31.h +// CHECK-ENCODING: [0xe0,0x4b,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 4b 28 45 + +uqxtnb z0.h, z31.s +// CHECK-INST: uqxtnb z0.h, z31.s +// CHECK-ENCODING: [0xe0,0x4b,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 4b 30 45 + +uqxtnb z0.s, z31.d +// CHECK-INST: uqxtnb z0.s, z31.d +// CHECK-ENCODING: [0xe0,0x4b,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 4b 60 45 diff --git a/llvm/test/MC/AArch64/SVE2/uqxtnt-diagnostics.s b/llvm/test/MC/AArch64/SVE2/uqxtnt-diagnostics.s new file mode 100644 index 0000000000000..d61fc764a374b --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqxtnt-diagnostics.s @@ -0,0 +1,40 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + + +// ------------------------------------------------------------------------- // +// Invalid element width + +uqxtnt z0.b, z1.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnt z0.b, z1.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqxtnt z0.h, z1.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnt z0.h, z1.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqxtnt z0.s, z1.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnt z0.s, z1.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uqxtnt z0.d, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uqxtnt z0.d, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +uqxtnt z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqxtnt z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0.s, p0/z, z7.s +uqxtnt z0.s, z1.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: uqxtnt z0.s, z1.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/uqxtnt.s b/llvm/test/MC/AArch64/SVE2/uqxtnt.s new file mode 100644 index 0000000000000..73dfc27a0fda0 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/uqxtnt.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + + +uqxtnt z0.b, z31.h +// CHECK-INST: uqxtnt z0.b, z31.h +// CHECK-ENCODING: [0xe0,0x4f,0x28,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 4f 28 45 + +uqxtnt z0.h, z31.s +// CHECK-INST: uqxtnt z0.h, z31.s +// CHECK-ENCODING: [0xe0,0x4f,0x30,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 4f 30 45 + +uqxtnt z0.s, z31.d +// CHECK-INST: uqxtnt z0.s, z31.d +// CHECK-ENCODING: [0xe0,0x4f,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: e0 4f 60 45 From 0f748e6e9b974a427d0b699d4d2534aa865ba9b6 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Fri, 24 May 2019 10:26:23 +0000 Subject: [PATCH 0159/1176] [clangd] Limit the size of synthesized fix message Summary: A temporary workaround until we figure out a better way to present fixes. Reviewers: kadircet Reviewed By: kadircet Subscribers: MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D62372 llvm-svn: 361625 --- clang-tools-extra/clangd/Diagnostics.cpp | 38 ++++++++++++++++--- .../clangd/unittests/DiagnosticsTests.cpp | 32 +++++++++++++++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index 5f42841db7717..a7bc1f1dcdb86 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -25,7 +25,9 @@ #include "llvm/Support/Path.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" #include +#include namespace clang { namespace clangd { @@ -437,6 +439,21 @@ void StoreDiags::EndSourceFile() { LangOpts = None; } +/// Sanitizes a piece for presenting it in a synthesized fix message. Ensures +/// the result is not too large and does not contain newlines. +static void writeCodeToFixMessage(llvm::raw_ostream &OS, llvm::StringRef Code) { + constexpr unsigned MaxLen = 50; + + // Only show the first line if there are many. + llvm::StringRef R = Code.split('\n').first; + // Shorten the message if it's too long. + R = R.take_front(MaxLen); + + OS << R; + if (R.size() != Code.size()) + OS << "…"; +} + void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) { DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info); @@ -494,12 +511,21 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, llvm::StringRef Insert = FixIt.CodeToInsert; if (!Invalid) { llvm::raw_svector_ostream M(Message); - if (!Remove.empty() && !Insert.empty()) - M << "change '" << Remove << "' to '" << Insert << "'"; - else if (!Remove.empty()) - M << "remove '" << Remove << "'"; - else if (!Insert.empty()) - M << "insert '" << Insert << "'"; + if (!Remove.empty() && !Insert.empty()) { + M << "change '"; + writeCodeToFixMessage(M, Remove); + M << "' to '"; + writeCodeToFixMessage(M, Insert); + M << "'"; + } else if (!Remove.empty()) { + M << "remove '"; + writeCodeToFixMessage(M, Remove); + M << "'"; + } else if (!Insert.empty()) { + M << "insert '"; + writeCodeToFixMessage(M, Insert); + M << "'"; + } // Don't allow source code to inject newlines into diagnostics. std::replace(Message.begin(), Message.end(), '\n', ' '); } diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 9d0492aa84d20..02126833df65c 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -120,7 +120,7 @@ o]](); "use of undeclared identifier 'goo'; did you mean 'foo'?"), DiagSource(Diag::Clang), DiagName("undeclared_var_use_suggest"), WithFix( - Fix(Test.range("typo"), "foo", "change 'go\\ o' to 'foo'")), + Fix(Test.range("typo"), "foo", "change 'go\\…' to 'foo'")), // This is a pretty normal range. WithNote(Diag(Test.range("decl"), "'foo' declared here"))), // This range is zero-width and insertion. Therefore make sure we are @@ -247,6 +247,36 @@ TEST(DiagnosticTest, ClangTidyWarningAsError) { DiagSeverity(DiagnosticsEngine::Error)))); } +TEST(DiagnosticTest, LongFixMessages) { + // We limit the size of printed code. + Annotations Source(R"cpp( + int main() { + int somereallyreallyreallyreallyreallyreallyreallyreallylongidentifier; + [[omereallyreallyreallyreallyreallyreallyreallyreallylongidentifier]]= 10; + } + )cpp"); + TestTU TU = TestTU::withCode(Source.code()); + EXPECT_THAT( + TU.build().getDiagnostics(), + ElementsAre(WithFix(Fix( + Source.range(), + "somereallyreallyreallyreallyreallyreallyreallyreallylongidentifier", + "change 'omereallyreallyreallyreallyreallyreallyreallyreall…' to " + "'somereallyreallyreallyreallyreallyreallyreallyreal…'")))); + // Only show changes up to a first newline. + Source = Annotations(R"cpp( + int main() { + int ident; + [[ide\ +n]] = 10; + } + )cpp"); + TU = TestTU::withCode(Source.code()); + EXPECT_THAT(TU.build().getDiagnostics(), + ElementsAre(WithFix( + Fix(Source.range(), "ident", "change 'ide\\…' to 'ident'")))); +} + TEST(DiagnosticTest, ClangTidyWarningAsErrorTrumpsSuppressionComment) { Annotations Main(R"cpp( int main() { From e4f01ec50c467ebf743191ca6895ef4595762462 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 24 May 2019 10:26:48 +0000 Subject: [PATCH 0160/1176] [llvm-readobj][mips] Align GOT columns headers properly in 64-bit case llvm-svn: 361626 --- llvm/test/tools/llvm-readobj/mips-got.test | 10 +++++----- llvm/tools/llvm-readobj/ELFDumper.cpp | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/mips-got.test b/llvm/test/tools/llvm-readobj/mips-got.test index 021dcfb116d3c..b3424dbc6f1f4 100644 --- a/llvm/test/tools/llvm-readobj/mips-got.test +++ b/llvm/test/tools/llvm-readobj/mips-got.test @@ -14,15 +14,15 @@ RUN: FileCheck %s -check-prefix GOT-STATIC RUN: not llvm-readelf --mips-plt-got %p/Inputs/relocs.obj.elf-mips 2>&1 | \ RUN: FileCheck %s -check-prefix GNU-GOT-OBJ RUN: llvm-readelf --mips-plt-got %p/Inputs/dynamic-table-exe.mips | \ -RUN: FileCheck %s -check-prefix GNU-GOT-EXE +RUN: FileCheck %s --strict-whitespace -check-prefix GNU-GOT-EXE RUN: llvm-readelf --mips-plt-got %p/Inputs/dynamic-table-so.mips | \ -RUN: FileCheck %s -check-prefix GNU-GOT-SO +RUN: FileCheck %s --strict-whitespace -check-prefix GNU-GOT-SO RUN: llvm-readelf --mips-plt-got %p/Inputs/got-tls.so.elf-mips64el | \ -RUN: FileCheck %s -check-prefix GNU-GOT-TLS +RUN: FileCheck %s --strict-whitespace -check-prefix GNU-GOT-TLS RUN: llvm-readelf --mips-plt-got %p/Inputs/got-empty.exe.mipsel | \ -RUN: FileCheck %s -check-prefix GNU-GOT-EMPTY +RUN: FileCheck %s --strict-whitespace -check-prefix GNU-GOT-EMPTY RUN: llvm-readelf --mips-plt-got %p/Inputs/got-static.exe.mips | \ -RUN: FileCheck %s -check-prefix GNU-GOT-STATIC +RUN: FileCheck %s --strict-whitespace -check-prefix GNU-GOT-STATIC GOT-OBJ: error: Cannot find .got section diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 65abdbd6109f0..159e300de3058 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -4061,7 +4061,10 @@ void GNUStyle::printMipsGOT(const MipsGOTParser &Parser) { << format_hex_no_prefix(Parser.getGp(), 8 + Bias) << "\n\n"; OS << " Reserved entries:\n"; - OS << " Address Access Initial Purpose\n"; + if (ELFT::Is64Bits) + OS << " Address Access Initial Purpose\n"; + else + OS << " Address Access Initial Purpose\n"; PrintEntry(Parser.getGotLazyResolver(), "Lazy resolver"); if (Parser.getGotModulePointer()) PrintEntry(Parser.getGotModulePointer(), "Module pointer (GNU extension)"); @@ -4069,7 +4072,10 @@ void GNUStyle::printMipsGOT(const MipsGOTParser &Parser) { if (!Parser.getLocalEntries().empty()) { OS << "\n"; OS << " Local entries:\n"; - OS << " Address Access Initial\n"; + if (ELFT::Is64Bits) + OS << " Address Access Initial\n"; + else + OS << " Address Access Initial\n"; for (auto &E : Parser.getLocalEntries()) PrintEntry(&E, ""); } @@ -4080,7 +4086,11 @@ void GNUStyle::printMipsGOT(const MipsGOTParser &Parser) { if (!Parser.getGlobalEntries().empty()) { OS << "\n"; OS << " Global entries:\n"; - OS << " Address Access Initial Sym.Val. Type Ndx Name\n"; + if (ELFT::Is64Bits) + OS << " Address Access Initial Sym.Val." + << " Type Ndx Name\n"; + else + OS << " Address Access Initial Sym.Val. Type Ndx Name\n"; for (auto &E : Parser.getGlobalEntries()) { const Elf_Sym *Sym = Parser.getGotSym(&E); std::string SymName = this->dumper()->getFullSymbolName( From b3e58df80c592b3ce3de77455b9b8cdfd66bb7c4 Mon Sep 17 00:00:00 2001 From: Cullen Rhodes Date: Fri, 24 May 2019 10:32:01 +0000 Subject: [PATCH 0161/1176] [AArch64][SVE2] Asm: support SVE2 String Processing Group Summary: Patch adds support for the SVE2 character match instructions MATCH and NMATCH. The specification can be found here: https://developer.arm.com/docs/ddi0602/latest Reviewed By: SjoerdMeijer Differential Revision: https://reviews.llvm.org/D62206 llvm-svn: 361627 --- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 4 ++ llvm/lib/Target/AArch64/SVEInstrFormats.td | 31 ++++++++++ llvm/test/MC/AArch64/SVE2/match-diagnostics.s | 61 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/match.s | 32 ++++++++++ .../test/MC/AArch64/SVE2/nmatch-diagnostics.s | 61 +++++++++++++++++++ llvm/test/MC/AArch64/SVE2/nmatch.s | 32 ++++++++++ 6 files changed, 221 insertions(+) create mode 100644 llvm/test/MC/AArch64/SVE2/match-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/match.s create mode 100644 llvm/test/MC/AArch64/SVE2/nmatch-diagnostics.s create mode 100644 llvm/test/MC/AArch64/SVE2/nmatch.s diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 3e17e687bdc0b..da26b409a4570 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1264,6 +1264,10 @@ let Predicates = [HasSVE2] in { defm SQXTUNB_ZZ : sve2_int_sat_extract_narrow<0b100, "sqxtunb">; defm SQXTUNT_ZZ : sve2_int_sat_extract_narrow<0b101, "sqxtunt">; + // SVE2 character match + defm MATCH_PPzZZ : sve2_char_match<0b0, "match">; + defm NMATCH_PPzZZ : sve2_char_match<0b1, "nmatch">; + // Predicated shifts defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index c4c890a63ecd0..a05533b18dae1 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -5132,3 +5132,34 @@ multiclass sve_int_break_z opc, string asm> { def NAME : sve_int_break; } +//===----------------------------------------------------------------------===// +// SVE2 String Processing Group +//===----------------------------------------------------------------------===// + +class sve2_char_match +: I<(outs pprty:$Pd), (ins PPR3bAny:$Pg, zprty:$Zn, zprty:$Zm), + asm, "\t$Pd, $Pg/z, $Zn, $Zm", + "", + []>, Sched<[]> { + bits<4> Pd; + bits<3> Pg; + bits<5> Zm; + bits<5> Zn; + let Inst{31-23} = 0b010001010; + let Inst{22} = sz; + let Inst{21} = 0b1; + let Inst{20-16} = Zm; + let Inst{15-13} = 0b100; + let Inst{12-10} = Pg; + let Inst{9-5} = Zn; + let Inst{4} = opc; + let Inst{3-0} = Pd; + + let Defs = [NZCV]; +} + +multiclass sve2_char_match { + def _B : sve2_char_match<0b0, opc, asm, PPR8, ZPR8>; + def _H : sve2_char_match<0b1, opc, asm, PPR16, ZPR16>; +} diff --git a/llvm/test/MC/AArch64/SVE2/match-diagnostics.s b/llvm/test/MC/AArch64/SVE2/match-diagnostics.s new file mode 100644 index 0000000000000..349747fdeb45a --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/match-diagnostics.s @@ -0,0 +1,61 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Restricted predicate out of range. + +match p0.b, p8/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: match p0.b, p8/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate operation + +match p0.b, p0/m, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: match p0.b, p0/m, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid destination predicate register + +match p0.s, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register. +// CHECK-NEXT: match p0.s, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +match p0.d, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register. +// CHECK-NEXT: match p0.d, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +match p0.b, p0/z, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: match p0.b, p0/z, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +match p0.b, p0/z, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: match p0.b, p0/z, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.b, p0/z, z7.b +match p0.b, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: match p0.b, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0, z7 +match p0.b, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: match p0.b, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/match.s b/llvm/test/MC/AArch64/SVE2/match.s new file mode 100644 index 0000000000000..07008f0d506d1 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/match.s @@ -0,0 +1,32 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +match p0.b, p0/z, z0.b, z0.b +// CHECK-INST: match p0.b, p0/z, z0.b, z0.b +// CHECK-ENCODING: [0x00,0x80,0x20,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 20 45 + +match p0.h, p0/z, z0.h, z0.h +// CHECK-INST: match p0.h, p0/z, z0.h, z0.h +// CHECK-ENCODING: [0x00,0x80,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 00 80 60 45 + +match p15.b, p7/z, z30.b, z31.b +// CHECK-INST: match p15.b, p7/z, z30.b, z31.b +// CHECK-ENCODING: [0xcf,0x9f,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: cf 9f 3f 45 + +match p15.h, p7/z, z30.h, z31.h +// CHECK-INST: match p15.h, p7/z, z30.h, z31.h +// CHECK-ENCODING: [0xcf,0x9f,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: cf 9f 7f 45 diff --git a/llvm/test/MC/AArch64/SVE2/nmatch-diagnostics.s b/llvm/test/MC/AArch64/SVE2/nmatch-diagnostics.s new file mode 100644 index 0000000000000..e53b9e6299879 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/nmatch-diagnostics.s @@ -0,0 +1,61 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Restricted predicate out of range. + +nmatch p0.b, p8/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: restricted predicate has range [0, 7]. +// CHECK-NEXT: nmatch p0.b, p8/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid predicate operation + +nmatch p0.b, p0/m, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: nmatch p0.b, p0/m, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Invalid destination predicate register + +nmatch p0.s, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register. +// CHECK-NEXT: nmatch p0.s, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +nmatch p0.d, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid predicate register. +// CHECK-NEXT: nmatch p0.d, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +nmatch p0.b, p0/z, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: nmatch p0.b, p0/z, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +nmatch p0.b, p0/z, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: nmatch p0.b, p0/z, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0.b, p0/z, z7.b +nmatch p0.b, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: nmatch p0.b, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0, z7 +nmatch p0.b, p0/z, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: nmatch p0.b, p0/z, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2/nmatch.s b/llvm/test/MC/AArch64/SVE2/nmatch.s new file mode 100644 index 0000000000000..6121f5530c446 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2/nmatch.s @@ -0,0 +1,32 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +nmatch p0.b, p0/z, z0.b, z0.b +// CHECK-INST: nmatch p0.b, p0/z, z0.b, z0.b +// CHECK-ENCODING: [0x10,0x80,0x20,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 10 80 20 45 + +nmatch p0.h, p0/z, z0.h, z0.h +// CHECK-INST: nmatch p0.h, p0/z, z0.h, z0.h +// CHECK-ENCODING: [0x10,0x80,0x60,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: 10 80 60 45 + +nmatch p15.b, p7/z, z30.b, z31.b +// CHECK-INST: nmatch p15.b, p7/z, z30.b, z31.b +// CHECK-ENCODING: [0xdf,0x9f,0x3f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f 3f 45 + +nmatch p15.h, p7/z, z30.h, z31.h +// CHECK-INST: nmatch p15.h, p7/z, z30.h, z31.h +// CHECK-ENCODING: [0xdf,0x9f,0x7f,0x45] +// CHECK-ERROR: instruction requires: sve2 +// CHECK-UNKNOWN: df 9f 7f 45 From f2d5b7a4fa01b076553db7a5fb0f3b773fe26693 Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Fri, 24 May 2019 10:39:00 +0000 Subject: [PATCH 0162/1176] Made cppcoreguidelines-pro-type-member-init-use-assignment run in all language modes llvm-svn: 361628 --- .../cppcoreguidelines-pro-type-member-init-use-assignment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp index dd1f9ac4aa9a5..6cf12b6e2db2b 100644 --- a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -config="{CheckOptions: [{key: "cppcoreguidelines-pro-type-member-init.UseAssignment", value: 1}]}" -- -std=c++11 +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -config="{CheckOptions: [{key: "cppcoreguidelines-pro-type-member-init.UseAssignment", value: 1}]}" struct T { int i; From b7f2a2b4c0ec40e17371c5b15d4e92b39b196c5c Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Fri, 24 May 2019 10:50:15 +0000 Subject: [PATCH 0163/1176] Make cppcoreguidelines-pro-type-member-init-use-assignment.cpp pass on platforms where char is unsigned The other options are to completely specify the triple (reduces test coverage), or to specify a regex that allows either '0' or '0U' for char initializers, however, that relaxes the test. llvm-svn: 361629 --- .../cppcoreguidelines-pro-type-member-init-use-assignment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp index 6cf12b6e2db2b..d6570502c92d9 100644 --- a/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp +++ b/clang-tools-extra/test/clang-tidy/cppcoreguidelines-pro-type-member-init-use-assignment.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -config="{CheckOptions: [{key: "cppcoreguidelines-pro-type-member-init.UseAssignment", value: 1}]}" +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -config="{CheckOptions: [{key: "cppcoreguidelines-pro-type-member-init.UseAssignment", value: 1}]}" -- -fsigned-char struct T { int i; From f835fcf412c92eac20bf2110e13c49fc86d0c55c Mon Sep 17 00:00:00 2001 From: George Rimar Date: Fri, 24 May 2019 11:12:50 +0000 Subject: [PATCH 0164/1176] [llvm-readelf] - Allow dumping of the .dynamic section even if there is no PT_DYNAMIC header. It is now possible after D61937 was landed and was discussed in it's review comments. It is not consistent with GNU, which does not output .dynamic section content in this case for no visible reason. Differential revision: https://reviews.llvm.org/D62179 llvm-svn: 361630 --- .../elf-dynamic-no-pt-dynamic.test | 15 +++++++++++---- llvm/tools/llvm-readobj/ELFDumper.cpp | 18 +++++++++--------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test b/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test index 3ef293714a897..5a03d04ab4d54 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test @@ -1,16 +1,23 @@ -# Show that no dumping occurs if there is no PT_DYNAMIC header. +## Show that dumping occurs even if there is no PT_DYNAMIC header. +## This is inconsistent with the GNU behavior, but seems to be more reasonable. # RUN: yaml2obj %s -o %t.no-phdr # RUN: llvm-readobj --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=LLVM -# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU --allow-empty +# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU # LLVM: File: {{.*}}.no-phdr # LLVM-NEXT: Format: ELF64-x86-64 # LLVM-NEXT: Arch: x86_64 # LLVM-NEXT: AddressSize: 64bit # LLVM-NEXT: LoadName:{{ *}} -# LLVM-NOT: {{.}} +# LLVM-NEXT: DynamicSection [ (1 entries) +# LLVM-NEXT: Tag Type Name/Value +# LLVM-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-NEXT: ] -# GNU-NOT: {{.}} +# GNU: DynamicSection [ (1 entries) +# GNU-NEXT: Tag Type Name/Value +# GNU-NEXT: 0x0000000000000000 NULL 0x0 +# GNU-NEXT: ] --- !ELF FileHeader: diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 159e300de3058..b86a6c192cab3 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1331,6 +1331,7 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { template void ELFDumper::loadDynamicTable(const ELFFile *Obj) { + // Try to locate the PT_DYNAMIC header. const Elf_Phdr *DynamicPhdr = nullptr; for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { if (Phdr.p_type != ELF::PT_DYNAMIC) @@ -1339,11 +1340,6 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { break; } - // We do not want to dump dynamic section if we have no PT_DYNAMIC header. - // This matches GNU's behavior. - if (!DynamicPhdr) - return; - // Try to locate the .dynamic section in the sections header table. const Elf_Shdr *DynamicSec = nullptr; for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { @@ -1358,9 +1354,16 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { // Ignore sh_entsize and use the expected value for entry size explicitly. // This allows us to dump the dynamic sections with a broken sh_entsize // field. - if (DynamicSec) + if (DynamicSec) { DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn)}); + parseDynamicTable(); + } + + // If we have a PT_DYNAMIC header, we will either check the found dynamic + // section or take the dynamic table data directly from the header. + if (!DynamicPhdr) + return; if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz > ObjF->getMemoryBufferRef().getBufferSize()) @@ -1374,7 +1377,6 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { } StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec)); - if (DynamicSec->sh_addr + DynamicSec->sh_size > DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || DynamicSec->sh_addr < DynamicPhdr->p_vaddr) @@ -1386,8 +1388,6 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { reportWarning("The SHT_DYNAMIC section '" + Name + "' is not at the start of " "PT_DYNAMIC segment"); - - parseDynamicTable(); } template From 33bee053c39b46c6aa46abca6cc758979da44b14 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Fri, 24 May 2019 11:24:42 +0000 Subject: [PATCH 0165/1176] Revert r361630 "[llvm-readelf] - Allow dumping of the .dynamic section even if there is no PT_DYNAMIC header." It broke BB: http://lab.llvm.org:8011/builders/ppc64le-lld-multistage-test/builds/3748 llvm-svn: 361631 --- .../elf-dynamic-no-pt-dynamic.test | 15 ++++----------- llvm/tools/llvm-readobj/ELFDumper.cpp | 18 +++++++++--------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test b/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test index 5a03d04ab4d54..3ef293714a897 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-no-pt-dynamic.test @@ -1,23 +1,16 @@ -## Show that dumping occurs even if there is no PT_DYNAMIC header. -## This is inconsistent with the GNU behavior, but seems to be more reasonable. +# Show that no dumping occurs if there is no PT_DYNAMIC header. # RUN: yaml2obj %s -o %t.no-phdr # RUN: llvm-readobj --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=LLVM -# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU +# RUN: llvm-readelf --dynamic-table %t.no-phdr | FileCheck %s --check-prefix=GNU --allow-empty # LLVM: File: {{.*}}.no-phdr # LLVM-NEXT: Format: ELF64-x86-64 # LLVM-NEXT: Arch: x86_64 # LLVM-NEXT: AddressSize: 64bit # LLVM-NEXT: LoadName:{{ *}} -# LLVM-NEXT: DynamicSection [ (1 entries) -# LLVM-NEXT: Tag Type Name/Value -# LLVM-NEXT: 0x0000000000000000 NULL 0x0 -# LLVM-NEXT: ] +# LLVM-NOT: {{.}} -# GNU: DynamicSection [ (1 entries) -# GNU-NEXT: Tag Type Name/Value -# GNU-NEXT: 0x0000000000000000 NULL 0x0 -# GNU-NEXT: ] +# GNU-NOT: {{.}} --- !ELF FileHeader: diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index b86a6c192cab3..159e300de3058 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1331,7 +1331,6 @@ static const char *getElfMipsOptionsOdkType(unsigned Odk) { template void ELFDumper::loadDynamicTable(const ELFFile *Obj) { - // Try to locate the PT_DYNAMIC header. const Elf_Phdr *DynamicPhdr = nullptr; for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { if (Phdr.p_type != ELF::PT_DYNAMIC) @@ -1340,6 +1339,11 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { break; } + // We do not want to dump dynamic section if we have no PT_DYNAMIC header. + // This matches GNU's behavior. + if (!DynamicPhdr) + return; + // Try to locate the .dynamic section in the sections header table. const Elf_Shdr *DynamicSec = nullptr; for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { @@ -1354,16 +1358,9 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { // Ignore sh_entsize and use the expected value for entry size explicitly. // This allows us to dump the dynamic sections with a broken sh_entsize // field. - if (DynamicSec) { + if (DynamicSec) DynamicTable = checkDRI({ObjF->getELFFile()->base() + DynamicSec->sh_offset, DynamicSec->sh_size, sizeof(Elf_Dyn)}); - parseDynamicTable(); - } - - // If we have a PT_DYNAMIC header, we will either check the found dynamic - // section or take the dynamic table data directly from the header. - if (!DynamicPhdr) - return; if (DynamicPhdr->p_offset + DynamicPhdr->p_filesz > ObjF->getMemoryBufferRef().getBufferSize()) @@ -1377,6 +1374,7 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { } StringRef Name = unwrapOrError(Obj->getSectionName(DynamicSec)); + if (DynamicSec->sh_addr + DynamicSec->sh_size > DynamicPhdr->p_vaddr + DynamicPhdr->p_memsz || DynamicSec->sh_addr < DynamicPhdr->p_vaddr) @@ -1388,6 +1386,8 @@ void ELFDumper::loadDynamicTable(const ELFFile *Obj) { reportWarning("The SHT_DYNAMIC section '" + Name + "' is not at the start of " "PT_DYNAMIC segment"); + + parseDynamicTable(); } template From 522307fa40da4b4d892e273c058418e112d844a4 Mon Sep 17 00:00:00 2001 From: Stefan Pintilie Date: Fri, 24 May 2019 12:05:37 +0000 Subject: [PATCH 0166/1176] [PowerPC] Remove CRBits Copy Of Unset/set CBit For the situation, where we generate the following code: crxor 8, 8, 8 < Some instructions> .LBB0_1: < Some instructions> cror 1, 8, 8 cror (COPY of CRbit) depends on the result of the crxor instruction. CR8 is known to be zero as crxor is equivalent to CRUNSET. We can simply use crxor 1, 1, 1 instead to zero out CR1, which does not have any dependency on any previous instruction. This patch will optimize it to: < Some instructions> .LBB0_1: < Some instructions> cror 1, 1, 1 Patch By: Victor Huang (NeHuang) Differential Revision: https://reviews.llvm.org/D62044 llvm-svn: 361632 --- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 2 + llvm/lib/Target/PowerPC/PPCInstrInfo.td | 2 + llvm/test/CodeGen/PowerPC/knowCRBitSpill.ll | 14 +- .../PowerPC/remove-copy-crunsetcrbit.mir | 178 ++++++++++++++++++ 4 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index a03742d74025c..25f4c9aa8ebd1 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -341,6 +341,8 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable(const MachineInstr &MI, case PPC::V_SETALLONESB: case PPC::V_SETALLONESH: case PPC::V_SETALLONES: + case PPC::CRSET: + case PPC::CRUNSET: return true; } return false; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 64511a0c79e1c..14fe0cd87fa52 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -2546,6 +2546,7 @@ def CRORC : XLForm_1<19, 417, (outs crbitrc:$CRD), [(set i1:$CRD, (or i1:$CRA, (not i1:$CRB)))]>; let isCodeGenOnly = 1 in { +let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def CRSET : XLForm_1_ext<19, 289, (outs crbitrc:$dst), (ins), "creqv $dst, $dst, $dst", IIC_BrCR, [(set i1:$dst, 1)]>; @@ -2553,6 +2554,7 @@ def CRSET : XLForm_1_ext<19, 289, (outs crbitrc:$dst), (ins), def CRUNSET: XLForm_1_ext<19, 193, (outs crbitrc:$dst), (ins), "crxor $dst, $dst, $dst", IIC_BrCR, [(set i1:$dst, 0)]>; +} let Defs = [CR1EQ], CRD = 6 in { def CR6SET : XLForm_1_ext<19, 289, (outs), (ins), diff --git a/llvm/test/CodeGen/PowerPC/knowCRBitSpill.ll b/llvm/test/CodeGen/PowerPC/knowCRBitSpill.ll index be05c57b83f21..f49a70325b5d4 100644 --- a/llvm/test/CodeGen/PowerPC/knowCRBitSpill.ll +++ b/llvm/test/CodeGen/PowerPC/knowCRBitSpill.ll @@ -1,6 +1,6 @@ ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ ; RUN: -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | FileCheck %s -; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 \ ; RUN: -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | FileCheck %s @@ -16,13 +16,19 @@ ; Function Attrs: nounwind define dso_local signext i32 @spillCRSET(i32 signext %p1, i32 signext %p2) { ; CHECK-LABEL: spillCRSET: -; CHECK: # %bb.0: # %entry -; CHECK: lis [[REG1:.*]], -32768 +; CHECK: # %bb.2: +; CHECK-DAG: crnor [[CREG:.*]]*cr5+lt, eq, eq +; CHECK-DAG: mfocrf [[REG2:.*]], [[CREG]] +; CHECK-DAG: rlwinm [[REG2]], [[REG2]] +; CHECK: .LBB0_3: ; CHECK-DAG: creqv [[CREG:.*]]*cr5+lt, [[CREG]]*cr5+lt, [[CREG]]*cr5+lt +; CHECK: lis [[REG1:.*]], -32768 +; CHECK: .LBB0_4: ; CHECK-NOT: mfocrf [[REG2:.*]], [[CREG]] ; CHECK-NOT: rlwinm [[REG2]], [[REG2]] ; CHECK: stw [[REG1]] -; CHECK: .LBB0_1: # %redo_first_pass +; CHECK: # %bb.5: + entry: %tobool = icmp eq i32 %p2, 0 %tobool2 = icmp eq i32 %p1, 0 diff --git a/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir b/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir new file mode 100644 index 0000000000000..7ede66c32e4d1 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir @@ -0,0 +1,178 @@ +# RUN: llc -run-pass simple-register-coalescing %s -o - | FileCheck %s +--- | + target datalayout = "e-m:e-i64:64-n32:64" + target triple = "powerpc64le-unknown-linux-gnu" + + @b = common dso_local local_unnamed_addr global i32 0, align 4 + @d = common dso_local local_unnamed_addr global i32 0, align 4 + @e = common dso_local local_unnamed_addr global i32* null, align 8 + @c = common dso_local local_unnamed_addr global i32 0, align 4 + @a = common dso_local local_unnamed_addr global [1 x i32] zeroinitializer, align 4 + + ; Function Attrs: norecurse nounwind + define dso_local signext i32 @copycrunset() local_unnamed_addr #0 { + entry: + %0 = load i32, i32* @b, align 4 + %tobool3 = icmp eq i32 %0, 0 + br i1 %tobool3, label %while.end, label %while.body.preheader + + while.body.preheader: ; preds = %entry + %.pre = load i32, i32* @d, align 4 + %tobool1 = icmp eq i32 %.pre, 0 + br label %while.body + + while.body: ; preds = %land.end, %while.body.preheader + br i1 %tobool1, label %land.end, label %land.rhs + + land.rhs: ; preds = %while.body + %1 = load i32*, i32** @e, align 8 + %2 = load i32, i32* %1, align 4 + %idxprom = sext i32 %2 to i64 + %arrayidx = getelementptr inbounds [1 x i32], [1 x i32]* @a, i64 0, i64 %idxprom + %3 = load i32, i32* %arrayidx, align 4 + %tobool2 = icmp ne i32 %3, 0 + br label %land.end + + land.end: ; preds = %land.rhs, %while.body + %4 = phi i1 [ false, %while.body ], [ %tobool2, %land.rhs ] + %land.ext = zext i1 %4 to i32 + store i32 %land.ext, i32* @c, align 4 + br label %while.body + + while.end: ; preds = %entry + ret i32 undef + } + +... +--- +name: copycrunset +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: + - { id: 0, class: crbitrc, preferred-register: '' } + - { id: 1, class: crbitrc, preferred-register: '' } + - { id: 2, class: crbitrc, preferred-register: '' } + - { id: 3, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 4, class: gprc, preferred-register: '' } + - { id: 5, class: crrc, preferred-register: '' } + - { id: 6, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 7, class: gprc, preferred-register: '' } + - { id: 8, class: crrc, preferred-register: '' } + - { id: 9, class: crbitrc, preferred-register: '' } + - { id: 10, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 11, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 12, class: g8rc, preferred-register: '' } + - { id: 13, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 14, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 15, class: g8rc, preferred-register: '' } + - { id: 16, class: gprc, preferred-register: '' } + - { id: 17, class: crrc, preferred-register: '' } + - { id: 18, class: crbitrc, preferred-register: '' } + - { id: 19, class: gprc_and_gprc_nor0, preferred-register: '' } + - { id: 20, class: gprc_and_gprc_nor0, preferred-register: '' } + - { id: 21, class: gprc, preferred-register: '' } + - { id: 22, class: g8rc_and_g8rc_nox0, preferred-register: '' } + - { id: 23, class: g8rc, preferred-register: '' } + - { id: 24, class: crbitrc, preferred-register: '' } +liveins: + - { reg: '$x2', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + successors: %bb.5(0x30000000), %bb.1(0x50000000) + liveins: $x2 + + %3:g8rc_and_g8rc_nox0 = ADDIStocHA $x2, @b + %4:gprc = LWZ target-flags(ppc-toc-lo) @b, killed %3, implicit $x2 :: (dereferenceable load 4 from @b) + %5:crrc = CMPLWI killed %4, 0 + BCC 76, killed %5, %bb.5 + B %bb.1 + + bb.1.while.body.preheader: + successors: %bb.2(0x80000000) + liveins: $x2 + + %6:g8rc_and_g8rc_nox0 = ADDIStocHA $x2, @d + %7:gprc = LWZ target-flags(ppc-toc-lo) @d, killed %6, implicit $x2 :: (dereferenceable load 4 from @d) + %8:crrc = CMPWI killed %7, 0 + %0:crbitrc = COPY killed %8.sub_eq + %9:crbitrc = CRUNSET + %19:gprc_and_gprc_nor0 = LI 0 + %20:gprc_and_gprc_nor0 = LI 1 + %22:g8rc_and_g8rc_nox0 = ADDIStocHA $x2, @c + %10:g8rc_and_g8rc_nox0 = ADDIStocHA $x2, @e + %13:g8rc_and_g8rc_nox0 = ADDIStocHA $x2, @a + %14:g8rc_and_g8rc_nox0 = ADDItocL killed %13, @a, implicit $x2 + + bb.2.while.body: + successors: %bb.4(0x30000000), %bb.3(0x50000000) + liveins: $x2 + + %24:crbitrc = COPY %9 + BC %0, %bb.4 + B %bb.3 + + bb.3.land.rhs: + successors: %bb.4(0x80000000) + liveins: $x2 + + %11:g8rc_and_g8rc_nox0 = LD target-flags(ppc-toc-lo) @e, %10, implicit $x2 :: (dereferenceable load 8 from @e) + %12:g8rc = LWA 0, killed %11 :: (load 4 from %ir.1) + %15:g8rc = RLDICR killed %12, 2, 61 + %16:gprc = LWZX %14, killed %15 :: (load 4 from %ir.arrayidx) + %17:crrc = CMPWI killed %16, 0 + %18:crbitrc = COPY killed %17.sub_eq + %1:crbitrc = CRNOR killed %18, %18 + %24:crbitrc = COPY killed %1 + + bb.4.land.end: + successors: %bb.2(0x80000000) + liveins: $x2 + + %2:crbitrc = COPY killed %24 + %21:gprc = ISEL %20, %19, killed %2 + STW killed %21, target-flags(ppc-toc-lo) @c, %22, implicit $x2 :: (store 4 into @c) + B %bb.2 + + bb.5.while.end: + %23:g8rc = LI8 0 + $x3 = COPY killed %23 + BLR8 implicit $lr8, implicit $rm, implicit killed $x3 + +... +#Copy of CRUNSET should be removed in simple register coalescing pass +#CHECK-LABEL: copycrunset +#CHECK: bb.1.while.body.preheader: +#CHECK-NOT: %9:crbitrc = CRUNSET +#CHECK: bb.2.while.body: +#CHECK-NOT: %24:crbitrc = COPY %9 +#CHECK: %24:crbitrc = CRUNSET +#CHECK: B %bb.3 From 8362cbe13b3226c7048b8c523e2cc8363ace47c5 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 24 May 2019 12:22:53 +0000 Subject: [PATCH 0167/1176] [llvm-readobj] Implement GNU-style output for dynamic table GNU readelf tool prints slightly different dynamic table "header" and surrounds dynamic tag names by brackets. This patch implements the same formatting for GNU-style output of the `llvm-readobj`. LLVM ``` DynamicSection [ (13 entries) Tag Type Name/Value 0x00000006 SYMTAB 0x168 ... ] ``` GNU ``` Dynamic section at offset 0x1d0 contains 13 entries: Tag Type Name/Value 0x00000006 (SYMTAB) 0x168 ... ``` Differential Revision: https://reviews.llvm.org/D62256 llvm-svn: 361633 --- lld/test/ELF/ppc64-dynamic-relocations.s | 2 +- llvm/test/tools/llvm-readobj/dynamic.test | 59 ++++++++ .../llvm-readobj/elf-dynamic-malformed.test | 19 ++- .../elf-dynamic-not-in-pt-dynamic.test | 24 ++-- .../llvm-readobj/elf-dynamic-table-dtnull.s | 35 +++-- .../elf-dynamic-tags-machine-specific.test | 127 +++++++++--------- .../tools/llvm-readobj/elf-dynamic-tags.test | 125 +++++++++-------- .../elf-non-dynamic-in-pt-dynamic.test | 22 ++- .../tools/llvm-readobj/elf-versioninfo.test | 6 +- llvm/tools/llvm-readobj/ELFDumper.cpp | 115 ++++++++++------ 10 files changed, 327 insertions(+), 207 deletions(-) diff --git a/lld/test/ELF/ppc64-dynamic-relocations.s b/lld/test/ELF/ppc64-dynamic-relocations.s index a3ede240ee225..71a26137a7793 100644 --- a/lld/test/ELF/ppc64-dynamic-relocations.s +++ b/lld/test/ELF/ppc64-dynamic-relocations.s @@ -29,7 +29,7 @@ // DIS: .plt 00000018 0000000010030000 BSS // DT_PLTGOT should point to the start of the .plt section. -// DT: 0x0000000000000003 PLTGOT 0x10030000 +// DT: 0x0000000000000003 (PLTGOT) 0x10030000 .text .abiversion 2 diff --git a/llvm/test/tools/llvm-readobj/dynamic.test b/llvm/test/tools/llvm-readobj/dynamic.test index 02ae622038ca2..5f3cdabad62ef 100644 --- a/llvm/test/tools/llvm-readobj/dynamic.test +++ b/llvm/test/tools/llvm-readobj/dynamic.test @@ -1,6 +1,8 @@ // Check dynamic section tags in case of shared library file. RUN: llvm-readobj --dynamic-table %p/Inputs/dynamic-table-so.mips \ RUN: | FileCheck %s -check-prefix ELF-MIPS +RUN: llvm-readelf --dynamic-table %p/Inputs/dynamic-table-so.mips \ +RUN: | FileCheck %s --strict-whitespace -check-prefix ELF-MIPS-GNU ELF-MIPS: Format: ELF32-mips ELF-MIPS: Arch: mipsel @@ -33,6 +35,32 @@ ELF-MIPS: 0x6FFFFFF0 VERSYM 0x4C0 ELF-MIPS: 0x00000000 NULL 0x0 ELF-MIPS: ] +ELF-MIPS-GNU: Dynamic section at offset 0x{{.*}} contains 23 entries: +ELF-MIPS-GNU-NEXT: Tag Type Name/Value +ELF-MIPS-GNU-NEXT: 0x00000001 (NEEDED) Shared library: [libc.so.6] +ELF-MIPS-GNU-NEXT: 0x0000000c (INIT) 0x528 +ELF-MIPS-GNU-NEXT: 0x0000000d (FINI) 0x860 +ELF-MIPS-GNU-NEXT: 0x00000004 (HASH) 0x210 +ELF-MIPS-GNU-NEXT: 0x00000005 (STRTAB) 0x3d8 +ELF-MIPS-GNU-NEXT: 0x00000006 (SYMTAB) 0x2a8 +ELF-MIPS-GNU-NEXT: 0x0000000a (STRSZ) 231 (bytes) +ELF-MIPS-GNU-NEXT: 0x0000000b (SYMENT) 16 (bytes) +ELF-MIPS-GNU-NEXT: 0x00000003 (PLTGOT) 0x108e0 +ELF-MIPS-GNU-NEXT: 0x00000011 (REL) 0x518 +ELF-MIPS-GNU-NEXT: 0x00000012 (RELSZ) 16 (bytes) +ELF-MIPS-GNU-NEXT: 0x00000013 (RELENT) 8 (bytes) +ELF-MIPS-GNU-NEXT: 0x70000001 (MIPS_RLD_VERSION) 1 +ELF-MIPS-GNU-NEXT: 0x70000005 (MIPS_FLAGS) NOTPOT +ELF-MIPS-GNU-NEXT: 0x70000006 (MIPS_BASE_ADDRESS) 0x0 +ELF-MIPS-GNU-NEXT: 0x7000000a (MIPS_LOCAL_GOTNO) 10 +ELF-MIPS-GNU-NEXT: 0x70000011 (MIPS_SYMTABNO) 19 +ELF-MIPS-GNU-NEXT: 0x70000012 (MIPS_UNREFEXTNO) 26 +ELF-MIPS-GNU-NEXT: 0x70000013 (MIPS_GOTSYM) 0xd +ELF-MIPS-GNU-NEXT: 0x6ffffffe (VERNEED) 0x4e8 +ELF-MIPS-GNU-NEXT: 0x6fffffff (VERNEEDNUM) 1 +ELF-MIPS-GNU-NEXT: 0x6ffffff0 (VERSYM) 0x4c0 +ELF-MIPS-GNU-NEXT: 0x00000000 (NULL) 0x0 + // Check dynamic section tags in case of non-pic executable file. RUN: llvm-readobj --dynamic-table %p/Inputs/dynamic-table-exe.mips \ RUN: | FileCheck %s -check-prefix ELF-MIPS-EXE @@ -151,6 +179,8 @@ ELF-X86-SO: 0x0000000000000000 NULL 0x0 RUN: llvm-readobj --dynamic-table %p/Inputs/dynamic-table-so.aarch64 \ RUN: | FileCheck %s -check-prefix ELF-AARCH64-SO +RUN: llvm-readelf --dynamic-table %p/Inputs/dynamic-table-so.aarch64 \ +RUN: | FileCheck %s --strict-whitespace -check-prefix ELF-AARCH64-SO-GNU ELF-AARCH64-SO: Format: ELF64-aarch64-little ELF-AARCH64-SO: Arch: aarch64 @@ -185,3 +215,32 @@ ELF-AARCH64-SO: 0x000000006FFFFFF0 VERSYM 0x4F2 ELF-AARCH64-SO: 0x000000006FFFFFF9 RELACOUNT 3 ELF-AARCH64-SO: 0x0000000000000000 NULL 0x0 ELF-AARCH64-SO: ] + +ELF-AARCH64-SO-GNU: Dynamic section at offset 0x{{.*}} contains 26 entries: +ELF-AARCH64-SO-GNU-NEXT: Tag Type Name/Value +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000000c (INIT) 0x660 +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000000d (FINI) 0x83c +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000019 (INIT_ARRAY) 0x10db8 +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000001a (FINI_ARRAY) 0x10dc0 +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x000000006ffffef5 (GNU_HASH) 0x1f0 +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000005 (STRTAB) 0x420 +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000006 (SYMTAB) 0x240 +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000000a (STRSZ) 210 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x000000000000000b (SYMENT) 24 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000003 (PLTGOT) 0x10fe8 +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000002 (PLTRELSZ) 96 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000014 (PLTREL) RELA +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000017 (JMPREL) 0x600 +ELF-AARCH64-SO-GNU-NEXT: 0x000000006ffffef6 (TLSDESC_PLT) 0x6d0 +ELF-AARCH64-SO-GNU-NEXT: 0x000000006ffffef7 (TLSDESC_GOT) 0x10fe0 +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000007 (RELA) 0x540 +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000008 (RELASZ) 192 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000009 (RELAENT) 24 (bytes) +ELF-AARCH64-SO-GNU-NEXT: 0x000000006ffffffe (VERNEED) 0x520 +ELF-AARCH64-SO-GNU-NEXT: 0x000000006fffffff (VERNEEDNUM) 1 +ELF-AARCH64-SO-GNU-NEXT: 0x000000006ffffff0 (VERSYM) 0x4f2 +ELF-AARCH64-SO-GNU-NEXT: 0x000000006ffffff9 (RELACOUNT) 3 +ELF-AARCH64-SO-GNU-NEXT: 0x0000000000000000 (NULL) 0x0 diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-malformed.test b/llvm/test/tools/llvm-readobj/elf-dynamic-malformed.test index 4e04423d7b18c..aaee340e1cca6 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-malformed.test +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-malformed.test @@ -28,14 +28,19 @@ ProgramHeaders: # Test handling of a .dynamic section with an invalid entsize (i.e. not 2 * sizeof(Elf_Dyn)). # RUN: yaml2obj %s --docnum=2 -o %t.bad-entsize -# RUN: llvm-readobj --dynamic-table %t.bad-entsize | FileCheck %s --check-prefix BAD-ENTSIZE -# RUN: llvm-readelf --dynamic-table %t.bad-entsize | FileCheck %s --check-prefix BAD-ENTSIZE +# RUN: llvm-readobj --dynamic-table %t.bad-entsize | FileCheck %s --check-prefix BAD-ENTSIZE-LLVM +# RUN: llvm-readelf --dynamic-table %t.bad-entsize | FileCheck %s --check-prefix BAD-ENTSIZE-GNU -# BAD-ENTSIZE: DynamicSection [ (2 entries) -# BAD-ENTSIZE-NEXT: Tag Type Name/Value -# BAD-ENTSIZE-NEXT: 0x0000000000000015 DEBUG 0x0 -# BAD-ENTSIZE-NEXT: 0x0000000000000000 NULL 0x0 -# BAD-ENTSIZE-NEXT: ] +# BAD-ENTSIZE-LLVM: DynamicSection [ (2 entries) +# BAD-ENTSIZE-LLVM-NEXT: Tag Type Name/Value +# BAD-ENTSIZE-LLVM-NEXT: 0x0000000000000015 DEBUG 0x0 +# BAD-ENTSIZE-LLVM-NEXT: 0x0000000000000000 NULL 0x0 +# BAD-ENTSIZE-LLVM-NEXT: ] + +# BAD-ENTSIZE-GNU: Dynamic section at offset 0x{{.*}} contains 2 entries: +# BAD-ENTSIZE-GNU-NEXT: Tag Type Name/Value +# BAD-ENTSIZE-GNU-NEXT: 0x0000000000000015 (DEBUG) 0x0 +# BAD-ENTSIZE-GNU-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-not-in-pt-dynamic.test b/llvm/test/tools/llvm-readobj/elf-dynamic-not-in-pt-dynamic.test index d52ec7696fdfd..482d683f5c108 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-not-in-pt-dynamic.test +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-not-in-pt-dynamic.test @@ -2,15 +2,23 @@ ## section when it is not in a PT_DYNAMIC segment. # RUN: yaml2obj %s -o %t.o -# RUN: llvm-readobj --dynamic-table %t.o 2>&1 | FileCheck %s -# RUN: llvm-readelf --dynamic-table %t.o 2>&1 | FileCheck %s +# RUN: llvm-readobj --dynamic-table %t.o 2>&1 \ +# RUN: | FileCheck --check-prefixes=WARNING,LLVM %s +# RUN: llvm-readelf --dynamic-table %t.o 2>&1 \ +# RUN: | FileCheck --check-prefixes=WARNING,GNU %s -# CHECK: warning: The SHT_DYNAMIC section '.dynamic' is not contained within the PT_DYNAMIC segment -# CHECK: DynamicSection [ (2 entries) -# CHECK-NEXT: Tag Type Name/Value -# CHECK-NEXT: 0x0000000000000018 BIND_NOW 0x1 -# CHECK-NEXT: 0x0000000000000000 NULL 0x0 -# CHECK-NEXT: ] +# WARNING: warning: The SHT_DYNAMIC section '.dynamic' is not contained within the PT_DYNAMIC segment + +# LLVM: DynamicSection [ (2 entries) +# LLVM-NEXT: Tag Type Name/Value +# LLVM-NEXT: 0x0000000000000018 BIND_NOW 0x1 +# LLVM-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-NEXT: ] + +# GNU: Dynamic section at offset 0x{{.*}} contains 2 entries: +# GNU-NEXT: Tag Type Name/Value +# GNU-NEXT: 0x0000000000000018 (BIND_NOW) 0x1 +# GNU-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-table-dtnull.s b/llvm/test/tools/llvm-readobj/elf-dynamic-table-dtnull.s index 8bb8d055bfba9..b613e4137d125 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-table-dtnull.s +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-table-dtnull.s @@ -1,13 +1,17 @@ # Check we are able to dump the dynamic section without a DT_NULL entry correctly. # RUN: yaml2obj -docnum=1 %s -o %t.o -# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s --check-prefix=NONULL -# RUN: llvm-readelf --dynamic-table %t.o | FileCheck %s --check-prefix=NONULL +# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s --check-prefix=NONULL-LLVM +# RUN: llvm-readelf --dynamic-table %t.o | FileCheck %s --check-prefix=NONULL-GNU -# NONULL: DynamicSection [ (1 entries) -# NONULL-NEXT: Tag Type Name/Value -# NONULL-NEXT: 0x0000000000000015 DEBUG 0x0 -# NONULL-NEXT: ] +# NONULL-LLVM: DynamicSection [ (1 entries) +# NONULL-LLVM-NEXT: Tag Type Name/Value +# NONULL-LLVM-NEXT: 0x0000000000000015 DEBUG 0x0 +# NONULL-LLVM-NEXT: ] + +# NONULL-GNU: Dynamic section at offset {{.*}} contains 1 entries: +# NONULL-GNU-NEXT: Tag Type Name/Value +# NONULL-GNU-NEXT: 0x0000000000000015 (DEBUG) 0x0 --- !ELF FileHeader: @@ -39,14 +43,19 @@ ProgramHeaders: # past the DT_NULL entry, which works as a terminator. # RUN: yaml2obj -docnum=2 %s -o %t.o -# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s --check-prefix=LONG -# RUN: llvm-readelf --dynamic-table %t.o | FileCheck %s --check-prefix=LONG +# RUN: llvm-readobj --dynamic-table %t.o | FileCheck %s --check-prefix=LONG-LLVM +# RUN: llvm-readelf --dynamic-table %t.o | FileCheck %s --check-prefix=LONG-GNU + +# LONG-LLVM: DynamicSection [ (2 entries) +# LONG-LLVM-NEXT: Tag Type Name/Value +# LONG-LLVM-NEXT: 0x0000000000000015 DEBUG 0x0 +# LONG-LLVM-NEXT: 0x0000000000000000 NULL 0x0 +# LONG-LLVM-NEXT: ] -# LONG: DynamicSection [ (2 entries) -# LONG-NEXT: Tag Type Name/Value -# LONG-NEXT: 0x0000000000000015 DEBUG 0x0 -# LONG-NEXT: 0x0000000000000000 NULL 0x0 -# LONG-NEXT: ] +# LONG-GNU: Dynamic section at offset {{.*}} contains 2 entries: +# LONG-GNU-NEXT: Tag Type Name/Value +# LONG-GNU-NEXT: 0x0000000000000015 (DEBUG) 0x0 +# LONG-GNU-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-tags-machine-specific.test b/llvm/test/tools/llvm-readobj/elf-dynamic-tags-machine-specific.test index 95c008dd37437..06c8b6d3fbe70 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-tags-machine-specific.test +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-tags-machine-specific.test @@ -13,15 +13,14 @@ # LLVM-HEXAGON-NEXT: 0x0000000000000000 NULL 0x0 # LLVM-HEXAGON-NEXT: ] -# GNU-HEXAGON: DynamicSection [ (6 entries) +# GNU-HEXAGON: Dynamic section at offset {{.*}} contains 6 entries: # GNU-HEXAGON-NEXT: Tag Type Name/Value -# GNU-HEXAGON-NEXT: 0x0000000000000004 HASH 0x1000 -# GNU-HEXAGON-NEXT: 0x0000000070000000 HEXAGON_SYMSZ 0x10 -# GNU-HEXAGON-NEXT: 0x0000000070000001 HEXAGON_VER 4096 -# GNU-HEXAGON-NEXT: 0x0000000070000002 HEXAGON_PLT 0x1000 -# GNU-HEXAGON-NEXT: 0x000000001234abcd unknown 0x1 -# GNU-HEXAGON-NEXT: 0x0000000000000000 NULL 0x0 -# GNU-HEXAGON-NEXT: ] +# GNU-HEXAGON-NEXT: 0x0000000000000004 (HASH) 0x1000 +# GNU-HEXAGON-NEXT: 0x0000000070000000 (HEXAGON_SYMSZ) 0x10 +# GNU-HEXAGON-NEXT: 0x0000000070000001 (HEXAGON_VER) 4096 +# GNU-HEXAGON-NEXT: 0x0000000070000002 (HEXAGON_PLT) 0x1000 +# GNU-HEXAGON-NEXT: 0x000000001234abcd (unknown) 0x1 +# GNU-HEXAGON-NEXT: 0x0000000000000000 (NULL) 0x0 # Test that MIPS machine-specific tags can be dumped. @@ -81,57 +80,56 @@ # LLVM-MIPS-NEXT: 0x0000000000000000 NULL 0x0 # LLVM-MIPS-NEXT: ] -# GNU-MIPS: DynamicSection [ (48 entries) -# GNU-MIPS-NEXT: Tag Type Name/Value -# GNU-MIPS-NEXT: 0x0000000000000004 HASH 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000001 MIPS_RLD_VERSION 305419896 -# GNU-MIPS-NEXT: 0x0000000070000002 MIPS_TIME_STAMP 0x11223344 -# GNU-MIPS-NEXT: 0x0000000070000003 MIPS_ICHECKSUM 0x11112222 -# GNU-MIPS-NEXT: 0x0000000070000004 MIPS_IVERSION 0x1 -# GNU-MIPS-NEXT: 0x0000000070000005 MIPS_FLAGS QUICKSTART SGI_ONLY PIXIE CORD -# GNU-MIPS-NEXT: 0x0000000070000006 MIPS_BASE_ADDRESS 0x87654321 -# GNU-MIPS-NEXT: 0x0000000070000007 MIPS_MSYM 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000008 MIPS_CONFLICT 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000009 MIPS_LIBLIST 0x1000 -# GNU-MIPS-NEXT: 0x000000007000000a MIPS_LOCAL_GOTNO 1 -# GNU-MIPS-NEXT: 0x000000007000000b MIPS_CONFLICTNO 0x1 -# GNU-MIPS-NEXT: 0x0000000070000010 MIPS_LIBLISTNO 0x1 -# GNU-MIPS-NEXT: 0x0000000070000011 MIPS_SYMTABNO 1 -# GNU-MIPS-NEXT: 0x0000000070000012 MIPS_UNREFEXTNO 0 -# GNU-MIPS-NEXT: 0x0000000070000013 MIPS_GOTSYM 0x0 -# GNU-MIPS-NEXT: 0x0000000070000014 MIPS_HIPAGENO 0x88776655 -# GNU-MIPS-NEXT: 0x0000000070000016 MIPS_RLD_MAP 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000017 MIPS_DELTA_CLASS 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000018 MIPS_DELTA_CLASS_NO 0x1 -# GNU-MIPS-NEXT: 0x0000000070000019 MIPS_DELTA_INSTANCE 0x1000 -# GNU-MIPS-NEXT: 0x000000007000001a MIPS_DELTA_INSTANCE_NO0x1 -# GNU-MIPS-NEXT: 0x000000007000001b MIPS_DELTA_RELOC 0x1000 -# GNU-MIPS-NEXT: 0x000000007000001c MIPS_DELTA_RELOC_NO 0x1 -# GNU-MIPS-NEXT: 0x000000007000001d MIPS_DELTA_SYM 0x1000 -# GNU-MIPS-NEXT: 0x000000007000001e MIPS_DELTA_SYM_NO 0x1 -# GNU-MIPS-NEXT: 0x0000000070000020 MIPS_DELTA_CLASSSYM 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000021 MIPS_DELTA_CLASSSYM_NO0x1 -# GNU-MIPS-NEXT: 0x0000000070000022 MIPS_CXX_FLAGS 0x88887777 -# GNU-MIPS-NEXT: 0x0000000070000023 MIPS_PIXIE_INIT 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000025 MIPS_LOCALPAGE_GOTIDX0x1 -# GNU-MIPS-NEXT: 0x0000000070000026 MIPS_LOCAL_GOTIDX 0x1 -# GNU-MIPS-NEXT: 0x0000000070000027 MIPS_HIDDEN_GOTIDX 0x1 -# GNU-MIPS-NEXT: 0x0000000070000028 MIPS_PROTECTED_GOTIDX0x1 -# GNU-MIPS-NEXT: 0x0000000070000029 MIPS_OPTIONS 0x1000 -# GNU-MIPS-NEXT: 0x000000007000002a MIPS_INTERFACE 0x1000 -# GNU-MIPS-NEXT: 0x000000007000002b MIPS_DYNSTR_ALIGN 0x88888888 -# GNU-MIPS-NEXT: 0x000000007000002c MIPS_INTERFACE_SIZE 0x10 -# GNU-MIPS-NEXT: 0x000000007000002d MIPS_RLD_TEXT_RESOLVE_ADDR0x8 -# GNU-MIPS-NEXT: 0x000000007000002e MIPS_PERF_SUFFIX 0x0 -# GNU-MIPS-NEXT: 0x000000007000002f MIPS_COMPACT_SIZE 0x10 -# GNU-MIPS-NEXT: 0x0000000070000030 MIPS_GP_VALUE 0x1 -# GNU-MIPS-NEXT: 0x0000000070000031 MIPS_AUX_DYNAMIC 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000032 MIPS_PLTGOT 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000034 MIPS_RWPLT 0x1000 -# GNU-MIPS-NEXT: 0x0000000070000035 MIPS_RLD_MAP_REL 0x1000 -# GNU-MIPS-NEXT: 0x000000001234abcd unknown 0x1 -# GNU-MIPS-NEXT: 0x0000000000000000 NULL 0x0 -# GNU-MIPS-NEXT: ] +# GNU-MIPS: Dynamic section at offset {{.*}} contains 48 entries: +# GNU-MIPS-NEXT: Tag Type Name/Value +# GNU-MIPS-NEXT: 0x0000000000000004 (HASH) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000001 (MIPS_RLD_VERSION) 305419896 +# GNU-MIPS-NEXT: 0x0000000070000002 (MIPS_TIME_STAMP) 0x11223344 +# GNU-MIPS-NEXT: 0x0000000070000003 (MIPS_ICHECKSUM) 0x11112222 +# GNU-MIPS-NEXT: 0x0000000070000004 (MIPS_IVERSION) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000005 (MIPS_FLAGS) QUICKSTART SGI_ONLY PIXIE CORD +# GNU-MIPS-NEXT: 0x0000000070000006 (MIPS_BASE_ADDRESS) 0x87654321 +# GNU-MIPS-NEXT: 0x0000000070000007 (MIPS_MSYM) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000008 (MIPS_CONFLICT) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000009 (MIPS_LIBLIST) 0x1000 +# GNU-MIPS-NEXT: 0x000000007000000a (MIPS_LOCAL_GOTNO) 1 +# GNU-MIPS-NEXT: 0x000000007000000b (MIPS_CONFLICTNO) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000010 (MIPS_LIBLISTNO) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000011 (MIPS_SYMTABNO) 1 +# GNU-MIPS-NEXT: 0x0000000070000012 (MIPS_UNREFEXTNO) 0 +# GNU-MIPS-NEXT: 0x0000000070000013 (MIPS_GOTSYM) 0x0 +# GNU-MIPS-NEXT: 0x0000000070000014 (MIPS_HIPAGENO) 0x88776655 +# GNU-MIPS-NEXT: 0x0000000070000016 (MIPS_RLD_MAP) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000017 (MIPS_DELTA_CLASS) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000018 (MIPS_DELTA_CLASS_NO) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000019 (MIPS_DELTA_INSTANCE) 0x1000 +# GNU-MIPS-NEXT: 0x000000007000001a (MIPS_DELTA_INSTANCE_NO) 0x1 +# GNU-MIPS-NEXT: 0x000000007000001b (MIPS_DELTA_RELOC) 0x1000 +# GNU-MIPS-NEXT: 0x000000007000001c (MIPS_DELTA_RELOC_NO) 0x1 +# GNU-MIPS-NEXT: 0x000000007000001d (MIPS_DELTA_SYM) 0x1000 +# GNU-MIPS-NEXT: 0x000000007000001e (MIPS_DELTA_SYM_NO) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000020 (MIPS_DELTA_CLASSSYM) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000021 (MIPS_DELTA_CLASSSYM_NO) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000022 (MIPS_CXX_FLAGS) 0x88887777 +# GNU-MIPS-NEXT: 0x0000000070000023 (MIPS_PIXIE_INIT) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000025 (MIPS_LOCALPAGE_GOTIDX) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000026 (MIPS_LOCAL_GOTIDX) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000027 (MIPS_HIDDEN_GOTIDX) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000028 (MIPS_PROTECTED_GOTIDX) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000029 (MIPS_OPTIONS) 0x1000 +# GNU-MIPS-NEXT: 0x000000007000002a (MIPS_INTERFACE) 0x1000 +# GNU-MIPS-NEXT: 0x000000007000002b (MIPS_DYNSTR_ALIGN) 0x88888888 +# GNU-MIPS-NEXT: 0x000000007000002c (MIPS_INTERFACE_SIZE) 0x10 +# GNU-MIPS-NEXT: 0x000000007000002d (MIPS_RLD_TEXT_RESOLVE_ADDR) 0x8 +# GNU-MIPS-NEXT: 0x000000007000002e (MIPS_PERF_SUFFIX) 0x0 +# GNU-MIPS-NEXT: 0x000000007000002f (MIPS_COMPACT_SIZE) 0x10 +# GNU-MIPS-NEXT: 0x0000000070000030 (MIPS_GP_VALUE) 0x1 +# GNU-MIPS-NEXT: 0x0000000070000031 (MIPS_AUX_DYNAMIC) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000032 (MIPS_PLTGOT) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000034 (MIPS_RWPLT) 0x1000 +# GNU-MIPS-NEXT: 0x0000000070000035 (MIPS_RLD_MAP_REL) 0x1000 +# GNU-MIPS-NEXT: 0x000000001234abcd (unknown) 0x1 +# GNU-MIPS-NEXT: 0x0000000000000000 (NULL) 0x0 # Test that PPC64 machine-specific tags can be dumped. @@ -147,10 +145,9 @@ # LLVM-PPC-NEXT: 0x0000000000000000 NULL 0x0 # LLVM-PPC-NEXT: ] -# GNU-PPC: DynamicSection [ (4 entries) +# GNU-PPC: Dynamic section at offset {{.*}} contains 4 entries: # GNU-PPC-NEXT: Tag Type Name/Value -# GNU-PPC-NEXT: 0x0000000000000004 HASH 0x1000 -# GNU-PPC-NEXT: 0x0000000070000000 PPC64_GLINK 0x1000 -# GNU-PPC-NEXT: 0x000000001234abcd unknown 0x1 -# GNU-PPC-NEXT: 0x0000000000000000 NULL 0x0 -# GNU-PPC-NEXT: ] +# GNU-PPC-NEXT: 0x0000000000000004 (HASH) 0x1000 +# GNU-PPC-NEXT: 0x0000000070000000 (PPC64_GLINK) 0x1000 +# GNU-PPC-NEXT: 0x000000001234abcd (unknown) 0x1 +# GNU-PPC-NEXT: 0x0000000000000000 (NULL) 0x0 diff --git a/llvm/test/tools/llvm-readobj/elf-dynamic-tags.test b/llvm/test/tools/llvm-readobj/elf-dynamic-tags.test index 15b8d678d189f..2e4f390920fda 100644 --- a/llvm/test/tools/llvm-readobj/elf-dynamic-tags.test +++ b/llvm/test/tools/llvm-readobj/elf-dynamic-tags.test @@ -68,70 +68,69 @@ # LLVM-NEXT: 0x0000000000000000 NULL 0x0 # LLVM-NEXT: ] -# GNU: DynamicSection [ (61 entries) +# GNU: Dynamic section at offset {{.*}} contains 61 entries: # GNU-NEXT: Tag Type Name/Value -# GNU-NEXT: 0x0000000000000001 NEEDED Shared library: [D] -# GNU-NEXT: 0x0000000000000002 PLTRELSZ 16 (bytes) -# GNU-NEXT: 0x0000000000000003 PLTGOT 0x1000 -# GNU-NEXT: 0x0000000000000004 HASH 0x1000 -# GNU-NEXT: 0x0000000000000005 STRTAB 0x1000 -# GNU-NEXT: 0x0000000000000006 SYMTAB 0x1000 -# GNU-NEXT: 0x0000000000000007 RELA 0x1000 -# GNU-NEXT: 0x0000000000000008 RELASZ 16 (bytes) -# GNU-NEXT: 0x0000000000000009 RELAENT 1929 (bytes) -# GNU-NEXT: 0x000000000000000a STRSZ 16 (bytes) -# GNU-NEXT: 0x000000000000000b SYMENT 2439 (bytes) -# GNU-NEXT: 0x000000000000000c INIT 0x1000 -# GNU-NEXT: 0x000000000000000d FINI 0x1000 -# GNU-NEXT: 0x000000000000000e SONAME Library soname: [U] -# GNU-NEXT: 0x000000000000000f RPATH f -# GNU-NEXT: 0x0000000000000010 SYMBOLIC 0x1234567890abcdef -# GNU-NEXT: 0x0000000000000011 REL 0x1000 -# GNU-NEXT: 0x0000000000000012 RELSZ 16 (bytes) -# GNU-NEXT: 0x0000000000000013 RELENT 291 (bytes) -# GNU-NEXT: 0x0000000000000014 PLTREL RELA -# GNU-NEXT: 0x0000000000000015 DEBUG 0xfedcba0987654321 -# GNU-NEXT: 0x0000000000000016 TEXTREL 0x1122334455667788 -# GNU-NEXT: 0x0000000000000017 JMPREL 0x1000 -# GNU-NEXT: 0x0000000000000018 BIND_NOW 0x8877665544332211 -# GNU-NEXT: 0x0000000000000019 INIT_ARRAY 0x1000 -# GNU-NEXT: 0x000000000000001a FINI_ARRAY 0x1000 -# GNU-NEXT: 0x000000000000001b INIT_ARRAYSZ 16 (bytes) -# GNU-NEXT: 0x000000000000001c FINI_ARRAYSZ 16 (bytes) -# GNU-NEXT: 0x000000000000001d RUNPATH w -# GNU-NEXT: 0x000000000000001e FLAGS ORIGIN SYMBOLIC TEXTREL BIND_NOW STATIC_TLS {{$}} -# GNU-NEXT: 0x0000000000000020 PREINIT_ARRAY 0x1000 -# GNU-NEXT: 0x0000000000000021 PREINIT_ARRAYSZ 16 (bytes) -# GNU-NEXT: 0x0000000000000022 SYMTAB_SHNDX 0x1000 -# GNU-NEXT: 0x0000000000000023 RELRSZ 0x10 -# GNU-NEXT: 0x0000000000000024 RELR 0x1000 -# GNU-NEXT: 0x0000000000000025 RELRENT 0x4321 -# GNU-NEXT: 0x000000006000000f ANDROID_REL 0x1000 -# GNU-NEXT: 0x0000000060000010 ANDROID_RELSZ 16 (bytes) -# GNU-NEXT: 0x0000000060000011 ANDROID_RELA 0x1000 -# GNU-NEXT: 0x0000000060000012 ANDROID_RELASZ 16 (bytes) -# GNU-NEXT: 0x000000006fffe000 ANDROID_RELR 0x1000 -# GNU-NEXT: 0x000000006fffe001 ANDROID_RELRSZ 0x10 -# GNU-NEXT: 0x000000006fffe003 ANDROID_RELRENT 0x1234 -# GNU-NEXT: 0x000000006ffffef5 GNU_HASH 0x1000 -# GNU-NEXT: 0x000000006ffffef6 TLSDESC_PLT 0x1000 -# GNU-NEXT: 0x000000006ffffef7 TLSDESC_GOT 0x1000 -# GNU-NEXT: 0x000000006ffffff9 RELACOUNT 0 -# GNU-NEXT: 0x000000006ffffffa RELCOUNT 0 -# GNU-NEXT: 0x000000006ffffffb FLAGS_1 NOW GLOBAL GROUP NODELETE LOADFLTR INITFIRST NOOPEN ORIGIN DIRECT TRANS INTERPOSE NODEFLIB NODUMP CONFALT ENDFILTEE DISPRELDNE DISPRELPND NODIRECT IGNMULDEF NOKSYMS NOHDR EDITED NORELOC SYMINTPOSE GLOBAUDIT SINGLETON {{$}} -# GNU-NEXT: 0x000000006ffffff0 VERSYM 0x1000 -# GNU-NEXT: 0x000000006ffffffc VERDEF 0x1000 -# GNU-NEXT: 0x000000006ffffffd VERDEFNUM 0 -# GNU-NEXT: 0x000000006ffffffe VERNEED 0x1000 -# GNU-NEXT: 0x000000006fffffff VERNEEDNUM 0 -# GNU-NEXT: 0x000000007ffffffd AUXILIARY Auxiliary library: [D] -# GNU-NEXT: 0x000000007ffffffe USED Not needed object: [U] -# GNU-NEXT: 0x000000007fffffff FILTER Filter library: [U] -# GNU-NEXT: 0x0000000012345678 unknown 0x8765432187654321 -# GNU-NEXT: 0x000000006abcdef0 unknown 0x9988776655443322 -# GNU-NEXT: 0x0000000076543210 unknown 0x5555666677778888 -# GNU-NEXT: 0x0000000000000000 NULL 0x0 -# GNU-NEXT: ] +# GNU-NEXT: 0x0000000000000001 (NEEDED) Shared library: [D] +# GNU-NEXT: 0x0000000000000002 (PLTRELSZ) 16 (bytes) +# GNU-NEXT: 0x0000000000000003 (PLTGOT) 0x1000 +# GNU-NEXT: 0x0000000000000004 (HASH) 0x1000 +# GNU-NEXT: 0x0000000000000005 (STRTAB) 0x1000 +# GNU-NEXT: 0x0000000000000006 (SYMTAB) 0x1000 +# GNU-NEXT: 0x0000000000000007 (RELA) 0x1000 +# GNU-NEXT: 0x0000000000000008 (RELASZ) 16 (bytes) +# GNU-NEXT: 0x0000000000000009 (RELAENT) 1929 (bytes) +# GNU-NEXT: 0x000000000000000a (STRSZ) 16 (bytes) +# GNU-NEXT: 0x000000000000000b (SYMENT) 2439 (bytes) +# GNU-NEXT: 0x000000000000000c (INIT) 0x1000 +# GNU-NEXT: 0x000000000000000d (FINI) 0x1000 +# GNU-NEXT: 0x000000000000000e (SONAME) Library soname: [U] +# GNU-NEXT: 0x000000000000000f (RPATH) f +# GNU-NEXT: 0x0000000000000010 (SYMBOLIC) 0x1234567890abcdef +# GNU-NEXT: 0x0000000000000011 (REL) 0x1000 +# GNU-NEXT: 0x0000000000000012 (RELSZ) 16 (bytes) +# GNU-NEXT: 0x0000000000000013 (RELENT) 291 (bytes) +# GNU-NEXT: 0x0000000000000014 (PLTREL) RELA +# GNU-NEXT: 0x0000000000000015 (DEBUG) 0xfedcba0987654321 +# GNU-NEXT: 0x0000000000000016 (TEXTREL) 0x1122334455667788 +# GNU-NEXT: 0x0000000000000017 (JMPREL) 0x1000 +# GNU-NEXT: 0x0000000000000018 (BIND_NOW) 0x8877665544332211 +# GNU-NEXT: 0x0000000000000019 (INIT_ARRAY) 0x1000 +# GNU-NEXT: 0x000000000000001a (FINI_ARRAY) 0x1000 +# GNU-NEXT: 0x000000000000001b (INIT_ARRAYSZ) 16 (bytes) +# GNU-NEXT: 0x000000000000001c (FINI_ARRAYSZ) 16 (bytes) +# GNU-NEXT: 0x000000000000001d (RUNPATH) w +# GNU-NEXT: 0x000000000000001e (FLAGS) ORIGIN SYMBOLIC TEXTREL BIND_NOW STATIC_TLS {{$}} +# GNU-NEXT: 0x0000000000000020 (PREINIT_ARRAY) 0x1000 +# GNU-NEXT: 0x0000000000000021 (PREINIT_ARRAYSZ) 16 (bytes) +# GNU-NEXT: 0x0000000000000022 (SYMTAB_SHNDX) 0x1000 +# GNU-NEXT: 0x0000000000000023 (RELRSZ) 0x10 +# GNU-NEXT: 0x0000000000000024 (RELR) 0x1000 +# GNU-NEXT: 0x0000000000000025 (RELRENT) 0x4321 +# GNU-NEXT: 0x000000006000000f (ANDROID_REL) 0x1000 +# GNU-NEXT: 0x0000000060000010 (ANDROID_RELSZ) 16 (bytes) +# GNU-NEXT: 0x0000000060000011 (ANDROID_RELA) 0x1000 +# GNU-NEXT: 0x0000000060000012 (ANDROID_RELASZ) 16 (bytes) +# GNU-NEXT: 0x000000006fffe000 (ANDROID_RELR) 0x1000 +# GNU-NEXT: 0x000000006fffe001 (ANDROID_RELRSZ) 0x10 +# GNU-NEXT: 0x000000006fffe003 (ANDROID_RELRENT) 0x1234 +# GNU-NEXT: 0x000000006ffffef5 (GNU_HASH) 0x1000 +# GNU-NEXT: 0x000000006ffffef6 (TLSDESC_PLT) 0x1000 +# GNU-NEXT: 0x000000006ffffef7 (TLSDESC_GOT) 0x1000 +# GNU-NEXT: 0x000000006ffffff9 (RELACOUNT) 0 +# GNU-NEXT: 0x000000006ffffffa (RELCOUNT) 0 +# GNU-NEXT: 0x000000006ffffffb (FLAGS_1) NOW GLOBAL GROUP NODELETE LOADFLTR INITFIRST NOOPEN ORIGIN DIRECT TRANS INTERPOSE NODEFLIB NODUMP CONFALT ENDFILTEE DISPRELDNE DISPRELPND NODIRECT IGNMULDEF NOKSYMS NOHDR EDITED NORELOC SYMINTPOSE GLOBAUDIT SINGLETON {{$}} +# GNU-NEXT: 0x000000006ffffff0 (VERSYM) 0x1000 +# GNU-NEXT: 0x000000006ffffffc (VERDEF) 0x1000 +# GNU-NEXT: 0x000000006ffffffd (VERDEFNUM) 0 +# GNU-NEXT: 0x000000006ffffffe (VERNEED) 0x1000 +# GNU-NEXT: 0x000000006fffffff (VERNEEDNUM) 0 +# GNU-NEXT: 0x000000007ffffffd (AUXILIARY) Auxiliary library: [D] +# GNU-NEXT: 0x000000007ffffffe (USED) Not needed object: [U] +# GNU-NEXT: 0x000000007fffffff (FILTER) Filter library: [U] +# GNU-NEXT: 0x0000000012345678 (unknown) 0x8765432187654321 +# GNU-NEXT: 0x000000006abcdef0 (unknown) 0x9988776655443322 +# GNU-NEXT: 0x0000000076543210 (unknown) 0x5555666677778888 +# GNU-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/elf-non-dynamic-in-pt-dynamic.test b/llvm/test/tools/llvm-readobj/elf-non-dynamic-in-pt-dynamic.test index 610148f26ffc3..37c4ad538a426 100644 --- a/llvm/test/tools/llvm-readobj/elf-non-dynamic-in-pt-dynamic.test +++ b/llvm/test/tools/llvm-readobj/elf-non-dynamic-in-pt-dynamic.test @@ -5,15 +5,23 @@ ## We check that we warn about this case. # RUN: yaml2obj --docnum=1 %s -o %t.o -# RUN: llvm-readobj --dynamic-table %t.o 2>&1 | FileCheck %s --check-prefixes=WARNING,CHECK -# RUN: llvm-readelf --dynamic-table %t.o 2>&1 | FileCheck %s --check-prefixes=WARNING,CHECK +# RUN: llvm-readobj --dynamic-table %t.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=WARNING,LLVM +# RUN: llvm-readelf --dynamic-table %t.o 2>&1 \ +# RUN: | FileCheck %s --check-prefixes=WARNING,GNU # WARNING: warning: The SHT_DYNAMIC section '.dynamic' is not at the start of PT_DYNAMIC segment -# CHECK: DynamicSection [ (2 entries) -# CHECK-NEXT: Tag Type Name/Value -# CHECK-NEXT: 0x0000000000000018 BIND_NOW 0x1 -# CHECK-NEXT: 0x0000000000000000 NULL 0x0 -# CHECK-NEXT: ] + +# LLVM: DynamicSection [ (2 entries) +# LLVM-NEXT: Tag Type Name/Value +# LLVM-NEXT: 0x0000000000000018 BIND_NOW 0x1 +# LLVM-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-NEXT: ] + +# GNU: Dynamic section at offset 0x{{.*}} contains 2 entries: +# GNU-NEXT: Tag Type Name/Value +# GNU-NEXT: 0x0000000000000018 (BIND_NOW) 0x1 +# GNU-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: diff --git a/llvm/test/tools/llvm-readobj/elf-versioninfo.test b/llvm/test/tools/llvm-readobj/elf-versioninfo.test index 8138f09715fa3..28653b7608b76 100644 --- a/llvm/test/tools/llvm-readobj/elf-versioninfo.test +++ b/llvm/test/tools/llvm-readobj/elf-versioninfo.test @@ -73,9 +73,9 @@ LLVM-VERDEF-NEXT: Predecessor: VERSION1 LLVM-VERDEF-NEXT: } LLVM-VERDEF-NEXT: } -GNU-VERDEF: 0x000000006ffffff0 VERSYM 0x24c -GNU-VERDEF: 0x000000006ffffffc VERDEF 0x25c -GNU-VERDEF: 0x000000006ffffffd VERDEFNUM 3 +GNU-VERDEF: 0x000000006ffffff0 (VERSYM) 0x24c +GNU-VERDEF: 0x000000006ffffffc (VERDEF) 0x25c +GNU-VERDEF: 0x000000006ffffffd (VERDEFNUM) 3 GNU-VERDEF: Version symbols section '.gnu.version' contains 8 entries: GNU-VERDEF-NEXT: Addr: 000000000000024c Offset: 0x00024c Link: 1 (.dynsym) diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 159e300de3058..48dd47d10824a 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -206,8 +206,6 @@ template class ELFDumper : public ObjDumper { void loadDynamicTable(const ELFFile *Obj); void parseDynamicTable(); - void printValue(uint64_t Type, uint64_t Value); - StringRef getDynamicString(uint64_t Offset) const; StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, bool &IsDefault) const; @@ -262,7 +260,18 @@ template class ELFDumper : public ObjDumper { public: Elf_Dyn_Range dynamic_table() const { - return DynamicTable.getAsArrayRef(); + // A valid .dynamic section contains an array of entries terminated + // with a DT_NULL entry. However, sometimes the section content may + // continue past the DT_NULL entry, so to dump the section correctly, + // we first find the end of the entries by iterating over them. + Elf_Dyn_Range Table = DynamicTable.getAsArrayRef(); + + size_t Size = 0; + while (Size < Table.size()) + if (Table[Size++].getTag() == DT_NULL) + break; + + return Table.slice(0, Size); } Elf_Sym_Range dynamic_symbols() const { @@ -283,6 +292,8 @@ template class ELFDumper : public ObjDumper { bool &IsDefault) const; void printSymbolsHelper(bool IsDynamic) const; + void printDynamicEntry(raw_ostream &OS, uint64_t Type, uint64_t Value) const; + const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; } const Elf_Shdr *getDotAddrsigSec() const { return DotAddrsigSec; } @@ -292,6 +303,7 @@ template class ELFDumper : public ObjDumper { const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; } const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; } const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; } + const DynRegionInfo &getDynamicTableRegion() const { return DynamicTable; } const Elf_Hash *getHashTable() const { return HashTable; } const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } }; @@ -340,6 +352,7 @@ template class DumpStyle { virtual void printSymbols(const ELFFile *Obj, bool PrintSymbols, bool PrintDynamicSymbols) = 0; virtual void printHashSymbols(const ELFFile *Obj) {} + virtual void printDynamic(const ELFFile *Obj) {} virtual void printDynamicRelocations(const ELFFile *Obj) = 0; virtual void printSymtabMessage(const ELFFile *Obj, StringRef Name, size_t Offset) {} @@ -384,6 +397,7 @@ template class GNUStyle : public DumpStyle { void printSymbols(const ELFO *Obj, bool PrintSymbols, bool PrintDynamicSymbols) override; void printHashSymbols(const ELFO *Obj) override; + void printDynamic(const ELFFile *Obj) override; void printDynamicRelocations(const ELFO *Obj) override; void printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Offset) override; @@ -488,6 +502,7 @@ template class LLVMStyle : public DumpStyle { void printSectionHeaders(const ELFO *Obj) override; void printSymbols(const ELFO *Obj, bool PrintSymbols, bool PrintDynamicSymbols) override; + void printDynamic(const ELFFile *Obj) override; void printDynamicRelocations(const ELFO *Obj) override; void printProgramHeaders(const ELFO *Obj, bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) override; @@ -1764,8 +1779,8 @@ static void printLibrary(raw_ostream &OS, const Twine &Tag, const Twine &Name) { } template -void ELFDumper::printValue(uint64_t Type, uint64_t Value) { - raw_ostream &OS = W.getOStream(); +void ELFDumper::printDynamicEntry(raw_ostream &OS, uint64_t Type, + uint64_t Value) const { const char *ConvChar = (opts::Output == opts::GNU) ? "0x%" PRIx64 : "0x%" PRIX64; switch (Type) { @@ -1883,41 +1898,7 @@ template <> void ELFDumper::printUnwindInfo() { } // end anonymous namespace template void ELFDumper::printDynamicTable() { - // A valid .dynamic section contains an array of entries terminated with - // a DT_NULL entry. However, sometimes the section content may continue - // past the DT_NULL entry, so to dump the section correctly, we first find - // the end of the entries by iterating over them. - size_t Size = 0; - Elf_Dyn_Range DynTableEntries = dynamic_table(); - for (; Size < DynTableEntries.size();) - if (DynTableEntries[Size++].getTag() == DT_NULL) - break; - - if (!Size) - return; - - raw_ostream &OS = W.getOStream(); - W.startLine() << "DynamicSection [ (" << Size << " entries)\n"; - - bool Is64 = ELFT::Is64Bits; - W.startLine() << " Tag" << (Is64 ? " " : " ") << "Type" - << " " - << "Name/Value\n"; - for (size_t I = 0; I < Size; ++I) { - const Elf_Dyn &Entry = DynTableEntries[I]; - uintX_t Tag = Entry.getTag(); - W.startLine() << " " - << format_hex(Tag, Is64 ? 18 : 10, opts::Output != opts::GNU) - << " " - << format( - "%-21s", - getTypeString( - ObjF->getELFFile()->getHeader()->e_machine, Tag)); - printValue(Tag, Entry.getVal()); - OS << "\n"; - } - - W.startLine() << "]\n"; + ELFDumperStyle->printDynamic(ObjF->getELFFile()); } template void ELFDumper::printNeededLibraries() { @@ -3344,6 +3325,35 @@ void GNUStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, printRelocation(Obj, Sym, SymbolName, R, IsRela); } +template void GNUStyle::printDynamic(const ELFO *Obj) { + Elf_Dyn_Range Table = this->dumper()->dynamic_table(); + if (Table.empty()) + return; + + const DynRegionInfo &DynamicTableRegion = + this->dumper()->getDynamicTableRegion(); + + OS << "Dynamic section at offset " + << format_hex(reinterpret_cast(DynamicTableRegion.Addr) - + Obj->base(), + 1) + << " contains " << Table.size() << " entries:\n"; + + bool Is64 = ELFT::Is64Bits; + if (Is64) + OS << " Tag Type Name/Value\n"; + else + OS << " Tag Type Name/Value\n"; + for (auto Entry : Table) { + uintX_t Tag = Entry.getTag(); + std::string TypeString = getTypeString(Obj->getHeader()->e_machine, Tag); + OS << format(" 0x%0*x %-20s ", Is64 ? 16 : 8, Tag, + ("(" + TypeString + ")").c_str()); + this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal()); + OS << "\n"; + } +} + template void GNUStyle::printDynamicRelocations(const ELFO *Obj) { const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); @@ -4502,6 +4512,31 @@ void LLVMStyle::printDynamicSymbols(const ELFO *Obj) { this->dumper()->printSymbolsHelper(true); } +template void LLVMStyle::printDynamic(const ELFFile *Obj) { + Elf_Dyn_Range Table = this->dumper()->dynamic_table(); + if (Table.empty()) + return; + + raw_ostream &OS = W.getOStream(); + W.startLine() << "DynamicSection [ (" << Table.size() << " entries)\n"; + + bool Is64 = ELFT::Is64Bits; + if (Is64) + W.startLine() << " Tag Type Name/Value\n"; + else + W.startLine() << " Tag Type Name/Value\n"; + for (auto Entry : Table) { + uintX_t Tag = Entry.getTag(); + W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, true) << " " + << format("%-21s", + getTypeString(Obj->getHeader()->e_machine, Tag)); + this->dumper()->printDynamicEntry(OS, Tag, Entry.getVal()); + OS << "\n"; + } + + W.startLine() << "]\n"; +} + template void LLVMStyle::printDynamicRelocations(const ELFO *Obj) { const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); From 74de6203efd12c5f57561a44b248051652a3de2c Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Fri, 24 May 2019 12:42:36 +0000 Subject: [PATCH 0168/1176] [LLD][COFF] Implement /filealign parameter Patch by Stefan Schmidt. This adds the /filealign parameter to lld, which allows to specify the section alignment in the output file (as it does on Microsoft's link.exe). This is required to be able to load dynamically linked libraries on the original Xbox, where the debugger monitor expects the section alignment in the file to be the same as in memory. llvm-svn: 361634 --- lld/COFF/Config.h | 1 + lld/COFF/Driver.cpp | 7 +++++ lld/COFF/Options.td | 1 + lld/COFF/Writer.cpp | 11 ++++---- lld/test/COFF/filealign.test | 51 ++++++++++++++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 lld/test/COFF/filealign.test diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 3b2fe2769c6a9..ba2bbcdebaf5d 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -180,6 +180,7 @@ struct Configuration { std::string MapFile; uint64_t ImageBase = -1; + uint64_t FileAlign = 512; uint64_t StackReserve = 1024 * 1024; uint64_t StackCommit = 4096; uint64_t HeapReserve = 1024 * 1024; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 006984309e184..df374f518d94d 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1197,6 +1197,13 @@ void LinkerDriver::link(ArrayRef ArgsArr) { if (auto *Arg = Args.getLastArg(OPT_base)) parseNumbers(Arg->getValue(), &Config->ImageBase); + // Handle /filealign + if (auto *Arg = Args.getLastArg(OPT_filealign)) { + parseNumbers(Arg->getValue(), &Config->FileAlign); + if (!isPowerOf2_64(Config->FileAlign)) + error("/filealign: not a power of two: " + Twine(Config->FileAlign)); + } + // Handle /stack if (auto *Arg = Args.getLastArg(OPT_stack)) parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit); diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index d87183c7e8096..f92349f27bd90 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -32,6 +32,7 @@ def errorlimit : P<"errorlimit", def export : P<"export", "Export a function">; // No help text because /failifmismatch is not intended to be used by the user. def failifmismatch : P<"failifmismatch", "">; +def filealign : P<"filealign", "Section alignment in the output file">; def functionpadmin : F<"functionpadmin">; def functionpadmin_opt : P<"functionpadmin", "Prepares an image for hotpatching">; def guard : P<"guard", "Control flow guard">; diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index d673fc8de8527..19614058a2b69 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -73,7 +73,6 @@ static unsigned char DOSProgram[] = { static_assert(sizeof(DOSProgram) % 8 == 0, "DOSProgram size must be multiple of 8"); -static const int SectorSize = 512; static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram); static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8"); @@ -1100,7 +1099,7 @@ void Writer::createSymbolAndStringTable() { PointerToSymbolTable = FileOff; FileOff += OutputSymtab.size() * sizeof(coff_symbol16); FileOff += 4 + Strtab.size(); - FileSize = alignTo(FileOff, SectorSize); + FileSize = alignTo(FileOff, Config->FileAlign); } void Writer::mergeSections() { @@ -1142,7 +1141,7 @@ void Writer::assignAddresses() { sizeof(coff_section) * OutputSections.size(); SizeOfHeaders += Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); - SizeOfHeaders = alignTo(SizeOfHeaders, SectorSize); + SizeOfHeaders = alignTo(SizeOfHeaders, Config->FileAlign); uint64_t RVA = PageSize; // The first page is kept unmapped. FileSize = SizeOfHeaders; @@ -1167,7 +1166,7 @@ void Writer::assignAddresses() { C->setRVA(RVA + VirtualSize); VirtualSize += C->getSize(); if (C->hasData()) - RawSize = alignTo(VirtualSize, SectorSize); + RawSize = alignTo(VirtualSize, Config->FileAlign); } if (VirtualSize > UINT32_MAX) error("section larger than 4 GiB: " + Sec->Name); @@ -1176,7 +1175,7 @@ void Writer::assignAddresses() { if (RawSize != 0) Sec->Header.PointerToRawData = FileSize; RVA += alignTo(VirtualSize, PageSize); - FileSize += alignTo(RawSize, SectorSize); + FileSize += alignTo(RawSize, Config->FileAlign); } SizeOfImage = alignTo(RVA, PageSize); @@ -1248,7 +1247,7 @@ template void Writer::writeHeader() { PE->ImageBase = Config->ImageBase; PE->SectionAlignment = PageSize; - PE->FileAlignment = SectorSize; + PE->FileAlignment = Config->FileAlign; PE->MajorImageVersion = Config->MajorImageVersion; PE->MinorImageVersion = Config->MinorImageVersion; PE->MajorOperatingSystemVersion = Config->MajorOSVersion; diff --git a/lld/test/COFF/filealign.test b/lld/test/COFF/filealign.test new file mode 100644 index 0000000000000..d6535101c4a21 --- /dev/null +++ b/lld/test/COFF/filealign.test @@ -0,0 +1,51 @@ +# RUN: yaml2obj < %s > %t.obj + +# RUN: lld-link /out:%t.exe /entry:main %t.obj +# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT-HEADER %s + +# DEFAULT-HEADER: FileAlignment: 512 + +# RUN: lld-link /out:%t.exe /entry:main %t.obj /filealign:4096 +# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=FILEALIGN-HEADER %s + +# FILEALIGN-HEADER: FileAlignment: 4096 + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4096 + SectionData: 0000000000000000 + Relocations: + - VirtualAddress: 0 + SymbolName: __ImageBase + Type: IMAGE_REL_AMD64_ADDR64 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __ImageBase + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... From 35be7ff80c1be14d9f7077c0d5a63b4bee6dd6c1 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 24 May 2019 13:28:27 +0000 Subject: [PATCH 0169/1176] [WebAssembly] Add support for -emit-relocs This can be useful for post-link tools and for testing. Sometimes it can be useful to produces a regular executable but with relocations preserved. Differential Revision: https://reviews.llvm.org/D62378 llvm-svn: 361635 --- lld/test/wasm/emit-relocs.ll | 39 ++++++++++++++++++++++++++++++++++++ lld/wasm/Config.h | 1 + lld/wasm/Driver.cpp | 1 + lld/wasm/Options.td | 2 ++ lld/wasm/SyntheticSections.h | 4 +++- lld/wasm/Writer.cpp | 10 ++++----- 6 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 lld/test/wasm/emit-relocs.ll diff --git a/lld/test/wasm/emit-relocs.ll b/lld/test/wasm/emit-relocs.ll new file mode 100644 index 0000000000000..cdf492ab8fbde --- /dev/null +++ b/lld/test/wasm/emit-relocs.ll @@ -0,0 +1,39 @@ +; RUN: llc -filetype=obj %s -o %t.o +; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o +; RUN: wasm-ld --emit-relocs -o %t.wasm %t.o %t.ret32.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare i32 @ret32(float) + +define void @unused_function() { + ret void +} + +define hidden void @_start() local_unnamed_addr #0 { +entry: + call i32 @ret32(float 0.0) + ret void +} + +; CHECK: - Type: CODE +; CHECK-NEXT: Relocations: +; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB +; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Offset: 0x00000009 + +; CHECK: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: Version: 2 +; CHECK-NEXT: SymbolTable: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: _start +; CHECK-NEXT: Flags: [ ] +; CHECK-NEXT: Function: 0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Name: ret32 +; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; CHECK-NEXT: Function: 1 diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h index 7881d01502d8d..6650e9e89df5a 100644 --- a/lld/wasm/Config.h +++ b/lld/wasm/Config.h @@ -27,6 +27,7 @@ struct Configuration { bool CompressRelocations; bool Demangle; bool DisableVerify; + bool EmitRelocs; bool ExportAll; bool ExportDynamic; bool ExportTable; diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 0bea11faf7dc7..06868f34f8e14 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -302,6 +302,7 @@ static void readConfigs(opt::InputArgList &Args) { Config->CompressRelocations = Args.hasArg(OPT_compress_relocations); Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); Config->DisableVerify = Args.hasArg(OPT_disable_verify); + Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); Config->Entry = getEntry(Args); Config->ExportAll = Args.hasArg(OPT_export_all); Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td index a7760e853afdd..b95d9ded5f64f 100644 --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -31,6 +31,8 @@ defm demangle: B<"demangle", "Demangle symbol names", "Do not demangle symbol names">; +def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">; + defm export_dynamic: B<"export-dynamic", "Put symbols in the dynamic symbol table", "Do not put symbols in the dynamic symbol table (default)">; diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h index ccd66326a2461..9f5266188331a 100644 --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -246,7 +246,9 @@ class LinkingSection : public SyntheticSection { const std::vector &DataSegments) : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"), InitFunctions(InitFunctions), DataSegments(DataSegments) {} - bool isNeeded() const override { return Config->Relocatable; } + bool isNeeded() const override { + return Config->Relocatable || Config->EmitRelocs; + } void writeBody() override; void addToSymtab(Symbol *Sym); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index f43191c70273d..5df364fb7706d 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -129,7 +129,7 @@ void Writer::createCustomSections() { LLVM_DEBUG(dbgs() << "createCustomSection: " << Name << "\n"); OutputSection *Sec = make(Name, Pair.second); - if (Config->Relocatable) { + if (Config->Relocatable || Config->EmitRelocs) { auto *Sym = make(Sec); Out.LinkingSec->addToSymtab(Sym); Sec->SectionSym = Sym; @@ -330,7 +330,7 @@ void Writer::addSections() { createCustomSections(); addSection(Out.LinkingSec); - if (Config->Relocatable) { + if (Config->EmitRelocs || Config->Relocatable) { createRelocSections(); } @@ -493,17 +493,17 @@ void Writer::calculateExports() { } void Writer::populateSymtab() { - if (!Config->Relocatable) + if (!Config->Relocatable && !Config->EmitRelocs) return; for (Symbol *Sym : Symtab->getSymbols()) - if (Sym->IsUsedInRegularObj) + if (Sym->IsUsedInRegularObj && Sym->isLive()) Out.LinkingSec->addToSymtab(Sym); for (ObjFile *File : Symtab->ObjectFiles) { LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n"); for (Symbol *Sym : File->getSymbols()) - if (Sym->isLocal() && !isa(Sym)) + if (Sym->isLocal() && !isa(Sym) && Sym->isLive()) Out.LinkingSec->addToSymtab(Sym); } } From 7991b6828484ec6deb466809a36f7ab7b0af90ce Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 24 May 2019 13:29:17 +0000 Subject: [PATCH 0170/1176] [lld] Trace all references with lld --trace-symbol Previously undefined symbol references were only traced if they were seen before that definition. Fixes https://bugs.llvm.org/show_bug.cgi?id=41878 Differential Revision: https://reviews.llvm.org/D61929 llvm-svn: 361636 --- lld/ELF/Symbols.cpp | 5 ++++- lld/ELF/Symbols.h | 2 +- lld/test/ELF/trace-symbols.s | 7 ++++++- lld/test/wasm/trace-symbol.ll | 19 ++++++++++++------- lld/wasm/SymbolTable.cpp | 6 ++++++ lld/wasm/Symbols.cpp | 13 ++++++++++--- lld/wasm/Symbols.h | 1 + 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index d44b24dd1b37a..45c545d532962 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -291,7 +291,7 @@ bool Symbol::includeInDynsym() const { } // Print out a log message for --trace-symbol. -void elf::printTraceSymbol(Symbol *Sym) { +void elf::printTraceSymbol(const Symbol *Sym) { std::string S; if (Sym->isUndefined()) S = ": reference to "; @@ -413,6 +413,9 @@ void Symbol::resolveUndefined(const Undefined &Other) { return; } + if (Traced) + printTraceSymbol(&Other); + if (isShared() || isLazy() || (isUndefined() && Other.Binding != STB_WEAK)) Binding = Other.Binding; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 04c23b588f02f..64fa30db25205 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -464,7 +464,7 @@ static inline void assertSymbols() { AssertSymbol(); } -void printTraceSymbol(Symbol *Sym); +void printTraceSymbol(const Symbol *Sym); size_t Symbol::getSymbolSize() const { switch (kind()) { diff --git a/lld/test/ELF/trace-symbols.s b/lld/test/ELF/trace-symbols.s index dfcce16e6b169..b6f8bea79d120 100644 --- a/lld/test/ELF/trace-symbols.s +++ b/lld/test/ELF/trace-symbols.s @@ -28,10 +28,15 @@ # OBJECTD1FOO: trace-symbols.s.tmp1: definition of foo # OBJECTD1FOO: trace-symbols.s.tmp2: definition of foo +# RUN: ld.lld -y foo %t1 %t2 %t -o %t3 | FileCheck -check-prefix=REFLAST %s +# REFLAST: trace-symbols.s.tmp1: definition of foo +# REFLAST: trace-symbols.s.tmp2: definition of foo +# REFLAST: trace-symbols.s.tmp: reference to foo + # RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \ # RUN: %t %t1 %t2 -o %t3 | FileCheck -check-prefix=OBJECTD2FOO %s # RUN: ld.lld -y foo -y common --trace-symbol=hsymbol \ -# RUN: %t %t2 %t1 -o /dev/null | FileCheck -check-prefix=OBJECTD2FOO %s +# RUN: %t %t2 %t1 -o %t3 | FileCheck -check-prefix=OBJECTD2FOO %s # RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 | \ # RUN: FileCheck -check-prefix=OBJECTD2FOO %s # OBJECTD2FOO: trace-symbols.s.tmp2: definition of foo diff --git a/lld/test/wasm/trace-symbol.ll b/lld/test/wasm/trace-symbol.ll index 4d167014752b4..e589de0f6d43e 100644 --- a/lld/test/wasm/trace-symbol.ll +++ b/lld/test/wasm/trace-symbol.ll @@ -1,9 +1,10 @@ ; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o -; RUN: llc -filetype=obj -o %t.o %s -; RUN: wasm-ld -o %t.wasm %t.o %t.ret32.o -y ret32 -y _start | FileCheck %s -check-prefix=BOTH +; RUN: llc -filetype=obj -o %t.start.o %s +; RUN: wasm-ld -o %t.wasm %t.start.o %t.ret32.o -y ret32 -y _start | FileCheck %s -check-prefix=BOTH +; RUN: wasm-ld -o %t.wasm %t.ret32.o %t.start.o -y ret32 -y _start | FileCheck %s -check-prefix=REVERSED ; check alias -; RUN: wasm-ld -o %t.wasm %t.o %t.ret32.o -trace-symbol=_start | FileCheck %s -check-prefixes=JUST-START +; RUN: wasm-ld -o %t.wasm %t.start.o %t.ret32.o -trace-symbol=_start | FileCheck %s -check-prefixes=JUST-START target triple = "wasm32-unknown-unknown" @@ -15,9 +16,13 @@ entry: ret void } -; BOTH: .o: definition of _start -; BOTH: .o: reference to ret32 -; BOTH: .ret32.o: definition of ret32 +; BOTH: start.o: definition of _start +; BOTH-NEXT: start.o: reference to ret32 +; BOTH-NEXT: ret32.o: definition of ret32 -; JUST-START: .o: definition of _start +; REVERSED: ret32.o: definition of ret32 +; REVERSED-NEXT: start.o: definition of _start +; REVERSED-NEXT: start.o: reference to ret32 + +; JUST-START: start.o: definition of _start ; JUST-START-NOT: ret32 diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index ce1aa5132ba90..244e24eb996d6 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -389,6 +389,8 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, File); + if (S->Traced) + printTraceSymbolUndefined(Name, File); auto Replace = [&]() { replaceSymbol(S, Name, ImportName, ImportModule, Flags, @@ -420,6 +422,8 @@ Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, File); + if (S->Traced) + printTraceSymbolUndefined(Name, File); if (WasInserted) replaceSymbol(S, Name, Flags, File); @@ -439,6 +443,8 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, File); + if (S->Traced) + printTraceSymbolUndefined(Name, File); if (WasInserted) replaceSymbol(S, Name, ImportName, ImportModule, Flags, diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index ba5bb5d43cdd4..07b895a2e67d2 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -307,12 +307,19 @@ std::string lld::toString(wasm::Symbol::Kind Kind) { llvm_unreachable("invalid symbol kind"); } + +void lld::wasm::printTraceSymbolUndefined(StringRef Name, const InputFile* File) { + message(toString(File) + ": reference to " + Name); +} + // Print out a log message for --trace-symbol. void lld::wasm::printTraceSymbol(Symbol *Sym) { - std::string S; + // Undefined symbols are traced via printTraceSymbolUndefined if (Sym->isUndefined()) - S = ": reference to "; - else if (Sym->isLazy()) + return; + + std::string S; + if (Sym->isLazy()) S = ": lazy definition of "; else S = ": definition of "; diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index 8b8b8eb834e4b..0bac81ced05f6 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -457,6 +457,7 @@ union SymbolUnion { }; void printTraceSymbol(Symbol *Sym); +void printTraceSymbolUndefined(StringRef Name, const InputFile* File); template T *replaceSymbol(Symbol *S, ArgT &&... Arg) { From 21977d8e29f84f6dca6ee64205d229bf49d40973 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Fri, 24 May 2019 13:56:01 +0000 Subject: [PATCH 0171/1176] [MCA] Zero-initialize field CRD in InstructionBase. Also run clang-format on a couple of files. NFC llvm-svn: 361637 --- llvm/include/llvm/MCA/Instruction.h | 7 ++++--- llvm/tools/llvm-mca/llvm-mca.cpp | 13 +++++++------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h index c4d0f6aace35a..9ac1fffb4430c 100644 --- a/llvm/include/llvm/MCA/Instruction.h +++ b/llvm/include/llvm/MCA/Instruction.h @@ -256,8 +256,8 @@ class ReadState { public: ReadState(const ReadDescriptor &Desc, unsigned RegID) : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), - CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), - IsReady(true), IsZero(false), IndependentFromDef(false) {} + CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true), + IsZero(false), IndependentFromDef(false) {} const ReadDescriptor &getDescriptor() const { return *RD; } unsigned getSchedClass() const { return RD->SchedClassID; } @@ -409,7 +409,8 @@ class InstructionBase { CriticalRegDep CRD; public: - InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {} + InstructionBase(const InstrDesc &D) + : Desc(D), IsOptimizableMove(false), CRD() {} SmallVectorImpl &getDefs() { return Defs; } const ArrayRef getDefs() const { return Defs; } diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index e70c8f627eff4..8ce1d03c785e0 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -68,8 +68,9 @@ static cl::opt OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); static cl::opt - ArchName("march", cl::desc("Target architecture. " - "See -version for available targets"), + ArchName("march", + cl::desc("Target architecture. " + "See -version for available targets"), cl::cat(ToolOptions)); static cl::opt @@ -441,8 +442,8 @@ int main(int argc, char **argv) { WithColor::error() << IE.Message << '\n'; IP->printInst(&IE.Inst, SS, "", *STI); SS.flush(); - WithColor::note() << "instruction: " << InstructionStr - << '\n'; + WithColor::note() + << "instruction: " << InstructionStr << '\n'; })) { // Default case. WithColor::error() << toString(std::move(NewE)); @@ -482,8 +483,8 @@ int main(int argc, char **argv) { mca::PipelinePrinter Printer(*P); if (PrintSummaryView) - Printer.addView(llvm::make_unique( - SM, Insts, DispatchWidth)); + Printer.addView( + llvm::make_unique(SM, Insts, DispatchWidth)); if (EnableBottleneckAnalysis) Printer.addView(llvm::make_unique(SM)); From e1947b84c12afe4207cab5e9365361822cc4a011 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 24 May 2019 14:06:47 +0000 Subject: [PATCH 0172/1176] Revert "[OPENMP][NVPTX]Fix barriers and parallel level counters, NFC." This reverts commit r361421 to split the patch into 3 parts. llvm-svn: 361638 --- openmp/libomptarget/deviceRTLs/nvptx/src/omp_data.cu | 3 +-- openmp/libomptarget/deviceRTLs/nvptx/src/omptarget-nvptx.h | 2 +- openmp/libomptarget/deviceRTLs/nvptx/src/sync.cu | 4 +--- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/openmp/libomptarget/deviceRTLs/nvptx/src/omp_data.cu b/openmp/libomptarget/deviceRTLs/nvptx/src/omp_data.cu index 0cd9b57fd7cf5..d369da1cb7e73 100644 --- a/openmp/libomptarget/deviceRTLs/nvptx/src/omp_data.cu +++ b/openmp/libomptarget/deviceRTLs/nvptx/src/omp_data.cu @@ -31,8 +31,7 @@ __device__ omptarget_nvptx_SimpleMemoryManager __device__ __shared__ uint32_t usedMemIdx; __device__ __shared__ uint32_t usedSlotIdx; -__device__ __shared__ volatile uint8_t - parallelLevel[MAX_THREADS_PER_TEAM / WARPSIZE]; +__device__ __shared__ uint8_t parallelLevel[MAX_THREADS_PER_TEAM / WARPSIZE]; __device__ __shared__ uint16_t threadLimit; __device__ __shared__ uint16_t threadsInTeam; __device__ __shared__ uint16_t nThreads; diff --git a/openmp/libomptarget/deviceRTLs/nvptx/src/omptarget-nvptx.h b/openmp/libomptarget/deviceRTLs/nvptx/src/omptarget-nvptx.h index b85d0a750f2a9..cd51538ad795c 100644 --- a/openmp/libomptarget/deviceRTLs/nvptx/src/omptarget-nvptx.h +++ b/openmp/libomptarget/deviceRTLs/nvptx/src/omptarget-nvptx.h @@ -398,7 +398,7 @@ extern __device__ omptarget_nvptx_SimpleMemoryManager omptarget_nvptx_simpleMemoryManager; extern __device__ __shared__ uint32_t usedMemIdx; extern __device__ __shared__ uint32_t usedSlotIdx; -extern __device__ __shared__ volatile uint8_t +extern __device__ __shared__ uint8_t parallelLevel[MAX_THREADS_PER_TEAM / WARPSIZE]; extern __device__ __shared__ uint16_t threadLimit; extern __device__ __shared__ uint16_t threadsInTeam; diff --git a/openmp/libomptarget/deviceRTLs/nvptx/src/sync.cu b/openmp/libomptarget/deviceRTLs/nvptx/src/sync.cu index 191b046c9f46f..d81aa8f0f3acc 100644 --- a/openmp/libomptarget/deviceRTLs/nvptx/src/sync.cu +++ b/openmp/libomptarget/deviceRTLs/nvptx/src/sync.cu @@ -62,8 +62,6 @@ EXTERN void __kmpc_barrier(kmp_Ident *loc_ref, int32_t tid) { // Barrier #1 is for synchronization among active threads. named_sync(L1_BARRIER, threads); } - } else { - __kmpc_flush(loc_ref); } // numberOfActiveOMPThreads > 1 PRINT0(LD_SYNC, "completed kmpc_barrier\n"); } @@ -132,7 +130,7 @@ EXTERN void __kmpc_end_single(kmp_Ident *loc, int32_t global_tid) { EXTERN void __kmpc_flush(kmp_Ident *loc) { PRINT0(LD_IO, "call kmpc_flush\n"); - __threadfence(); + __threadfence_system(); } //////////////////////////////////////////////////////////////////////////////// From a5ca34e6b3c2508ee1504ff6e18776f8cef25af9 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 24 May 2019 14:14:25 +0000 Subject: [PATCH 0173/1176] [WebAssebmly] Add support for --wrap The code for implementing this features is taken almost verbatim from the ELF backend. Fixes: https://bugs.llvm.org/show_bug.cgi?id=41681 Differential Revision: https://reviews.llvm.org/D62380 llvm-svn: 361639 --- lld/ELF/Driver.cpp | 2 +- lld/ELF/InputFiles.h | 2 +- lld/include/lld/Common/LLVM.h | 2 + lld/test/wasm/wrap.ll | 40 +++++++++++++++++ lld/wasm/Driver.cpp | 85 +++++++++++++++++++++++++++++++++++ lld/wasm/InputFiles.h | 2 + lld/wasm/LTO.cpp | 5 +++ lld/wasm/Options.td | 3 ++ lld/wasm/SymbolTable.cpp | 17 ++++++- lld/wasm/SymbolTable.h | 15 ++++--- lld/wasm/Symbols.h | 10 ++++- 11 files changed, 172 insertions(+), 11 deletions(-) create mode 100644 lld/test/wasm/wrap.ll diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 9a72876631665..416fbb12b65d5 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1522,7 +1522,7 @@ static void wrapSymbols(ArrayRef Wrapped) { // Update pointers in input files. parallelForEach(ObjectFiles, [&](InputFile *File) { - std::vector &Syms = File->getMutableSymbols(); + MutableArrayRef Syms = File->getMutableSymbols(); for (size_t I = 0, E = Syms.size(); I != E; ++I) if (Symbol *S = Map.lookup(Syms[I])) Syms[I] = S; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 648f5b51452dc..81ee0302da020 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -90,7 +90,7 @@ class InputFile { // function on files of other types. ArrayRef getSymbols() { return getMutableSymbols(); } - std::vector &getMutableSymbols() { + MutableArrayRef getMutableSymbols() { assert(FileKind == BinaryKind || FileKind == ObjKind || FileKind == BitcodeKind); return Symbols; diff --git a/lld/include/lld/Common/LLVM.h b/lld/include/lld/Common/LLVM.h index 944bb412a2e62..f7ed1d793ca7b 100644 --- a/lld/include/lld/Common/LLVM.h +++ b/lld/include/lld/Common/LLVM.h @@ -29,6 +29,7 @@ class Twine; class MemoryBuffer; class MemoryBufferRef; template class ArrayRef; +template class MutableArrayRef; template class SmallString; template class SmallVector; template class ErrorOr; @@ -62,6 +63,7 @@ using llvm::isa; // ADT's. using llvm::ArrayRef; +using llvm::MutableArrayRef; using llvm::Error; using llvm::ErrorOr; using llvm::Expected; diff --git a/lld/test/wasm/wrap.ll b/lld/test/wasm/wrap.ll new file mode 100644 index 0000000000000..ff850accfd596 --- /dev/null +++ b/lld/test/wasm/wrap.ll @@ -0,0 +1,40 @@ +; RUN: llc -filetype=obj %s -o %t.o +; RUN: wasm-ld -wrap nosuchsym -wrap foo -o %t.wasm %t.o +; RUN: wasm-ld -emit-relocs -wrap foo -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define i32 @foo() { + ret i32 1 +} + +define void @_start() { +entry: + call i32 @foo() + ret void +} + +declare i32 @__real_foo() + +define i32 @__wrap_foo() { + %rtn = call i32 @__real_foo() + ret i32 %rtn +} + +; CHECK: - Type: CODE +; CHECK-NEXT: Relocations: +; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB +; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Offset: 0x00000009 +; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Offset: 0x00000013 + +; CHECK: FunctionNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: foo +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: _start +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: __wrap_foo diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 06868f34f8e14..4ac5aff2494f4 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -535,6 +535,84 @@ static std::string createResponseFile(const opt::InputArgList &Args) { return Data.str(); } +// The --wrap option is a feature to rename symbols so that you can write +// wrappers for existing functions. If you pass `-wrap=foo`, all +// occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are +// expected to write `wrap_foo` function as a wrapper). The original +// symbol becomes accessible as `real_foo`, so you can call that from your +// wrapper. +// +// This data structure is instantiated for each -wrap option. +struct WrappedSymbol { + Symbol *Sym; + Symbol *Real; + Symbol *Wrap; +}; + +static Symbol *addUndefined(StringRef Name) { + return Symtab->addUndefinedFunction(Name, "", "", 0, nullptr, nullptr); +} + +// Handles -wrap option. +// +// This function instantiates wrapper symbols. At this point, they seem +// like they are not being used at all, so we explicitly set some flags so +// that LTO won't eliminate them. +static std::vector addWrappedSymbols(opt::InputArgList &Args) { + std::vector V; + DenseSet Seen; + + for (auto *Arg : Args.filtered(OPT_wrap)) { + StringRef Name = Arg->getValue(); + if (!Seen.insert(Name).second) + continue; + + Symbol *Sym = Symtab->find(Name); + if (!Sym) + continue; + + Symbol *Real = addUndefined(Saver.save("__real_" + Name)); + Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); + V.push_back({Sym, Real, Wrap}); + + // We want to tell LTO not to inline symbols to be overwritten + // because LTO doesn't know the final symbol contents after renaming. + Real->CanInline = false; + Sym->CanInline = false; + + // Tell LTO not to eliminate these symbols. + Sym->IsUsedInRegularObj = true; + Wrap->IsUsedInRegularObj = true; + Real->IsUsedInRegularObj = false; + } + return V; +} + +// Do renaming for -wrap by updating pointers to symbols. +// +// When this function is executed, only InputFiles and symbol table +// contain pointers to symbol objects. We visit them to replace pointers, +// so that wrapped symbols are swapped as instructed by the command line. +static void wrapSymbols(ArrayRef Wrapped) { + DenseMap Map; + for (const WrappedSymbol &W : Wrapped) { + Map[W.Sym] = W.Wrap; + Map[W.Real] = W.Sym; + } + + // Update pointers in input files. + parallelForEach(Symtab->ObjectFiles, [&](InputFile *File) { + MutableArrayRef Syms = File->getMutableSymbols(); + for (size_t I = 0, E = Syms.size(); I != E; ++I) + if (Symbol *S = Map.lookup(Syms[I])) + Syms[I] = S; + }); + + // Update pointers in the symbol table. + for (const WrappedSymbol &W : Wrapped) + Symtab->wrap(W.Sym, W.Real, W.Wrap); +} + void LinkerDriver::link(ArrayRef ArgsArr) { WasmOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); @@ -628,6 +706,9 @@ void LinkerDriver::link(ArrayRef ArgsArr) { for (auto *Arg : Args.filtered(OPT_export)) handleUndefined(Arg->getValue()); + // Create wrapped symbols for -wrap option. + std::vector Wrapped = addWrappedSymbols(Args); + // Do link-time optimization if given files are LLVM bitcode files. // This compiles bitcode files into real object files. Symtab->addCombinedLTOObject(); @@ -640,6 +721,10 @@ void LinkerDriver::link(ArrayRef ArgsArr) { if (errorCount()) return; + // Apply symbol renames for -wrap. + if (!Wrapped.empty()) + wrapSymbols(Wrapped); + for (auto *Arg : Args.filtered(OPT_export)) { Symbol *Sym = Symtab->find(Arg->getValue()); if (Sym && Sym->isDefined()) diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h index aedcb15ca3e24..7c8601e29f2a8 100644 --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -61,6 +61,8 @@ class InputFile { ArrayRef getSymbols() const { return Symbols; } + MutableArrayRef getMutableSymbols() { return Symbols; } + protected: InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} MemoryBufferRef MB; diff --git a/lld/wasm/LTO.cpp b/lld/wasm/LTO.cpp index 2b49bac5cf2f7..0c42e0e212333 100644 --- a/lld/wasm/LTO.cpp +++ b/lld/wasm/LTO.cpp @@ -108,6 +108,11 @@ void BitcodeCompiler::add(BitcodeFile &F) { (R.Prevailing && Sym->isExported()); if (R.Prevailing) undefine(Sym); + + // We tell LTO to not apply interprocedural optimization for wrapped + // (with --wrap) symbols because otherwise LTO would inline them while + // their values are still not final. + R.LinkerRedefined = !Sym->CanInline; } checkError(LTOObj->add(std::move(F.Obj), Resols)); } diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td index b95d9ded5f64f..b6fe25d5d25ca 100644 --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -112,6 +112,9 @@ def version: F<"version">, HelpText<"Display the version number and exit">; def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"