diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/README.md b/clang-tools-extra/clangd/clients/clangd-vscode/README.md index 9babfce5f95e5d..929dd4c27fcc55 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/README.md +++ b/clang-tools-extra/clangd/clients/clangd-vscode/README.md @@ -9,7 +9,7 @@ Protocol](https://github.com/Microsoft/language-server-protocol), such as code completion, code formatting and goto definition. **Note**: `clangd` is under heavy development, not all LSP features are -implemented. See [Current Status](https://clang.llvm.org/extra/clangd.html#current-status) +implemented. See [Current Status](https://clang.llvm.org/extra/clangd/Features.html#complete-list-of-features) for details. To use `vscode-clangd` extension in VS Code, you need to install `vscode-clangd` @@ -25,7 +25,7 @@ Alternatively, the `clangd` executable can be specified in your VS Code } ``` -To obtain `clangd` binary, please see the [installing Clangd](https://clang.llvm.org/extra/clangd.html#installing-clangd). +To obtain `clangd` binary, please see the [installing Clangd](https://clang.llvm.org/extra/clangd/Installation.html#installing-clangd). ## Development @@ -68,7 +68,7 @@ to the marketplace. The extension is published under `llvm-vs-code-extensions` account, which is currently maintained by clangd developers. If you want to make a new release, -please contact cfe-dev@lists.llvm.org. +please contact clangd-dev@lists.llvm.org. ### Steps diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp index 4b284163ef7e2d..d21db54b31a46d 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp @@ -459,6 +459,7 @@ CapturedZoneInfo captureZoneInfo(const ExtractionZone &ExtZone) { // Adds parameters to ExtractedFunc. // Returns true if able to find the parameters successfully and no hoisting // needed. +// FIXME: Check if the declaration has a local/anonymous type bool createParameters(NewFunction &ExtractedFunc, const CapturedZoneInfo &CapturedInfo) { for (const auto &KeyVal : CapturedInfo.DeclInfoMap) { diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 4157cf3b083a4d..44015b4e418f54 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -238,10 +238,6 @@ class DWARFExpression { lldb::addr_t loclist_base_load_addr, lldb::addr_t address, ABI *abi); - static size_t LocationListSize(const DWARFUnit *dwarf_cu, - const DataExtractor &debug_loc_data, - lldb::offset_t offset); - static bool PrintDWARFExpression(Stream &s, const DataExtractor &data, int address_size, int dwarf_ref_size, bool location_expression); diff --git a/lldb/lit/SymbolFile/DWARF/debug_loc.s b/lldb/lit/SymbolFile/DWARF/debug_loc.s index ce7177d7d56b31..1fc862f8a1fc5b 100644 --- a/lldb/lit/SymbolFile/DWARF/debug_loc.s +++ b/lldb/lit/SymbolFile/DWARF/debug_loc.s @@ -1,14 +1,22 @@ +# Test debug_loc parsing, including the cases of invalid input. The exact +# behavior in the invalid cases is not particularly important, but it should be +# "reasonable". + # REQUIRES: x86 # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s > %t -# RUN: lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" -o exit \ +# RUN: %lldb %t -o "image lookup -v -a 0" -o "image lookup -v -a 2" -o exit \ # RUN: | FileCheck %s # CHECK-LABEL: image lookup -v -a 0 -# CHECK: Variable: {{.*}}, name = "x", type = "int", location = rdi, +# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = rdi, +# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = , +# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = , # CHECK-LABEL: image lookup -v -a 2 -# CHECK: Variable: {{.*}}, name = "x", type = "int", location = rax, +# CHECK: Variable: {{.*}}, name = "x0", type = "int", location = rax, +# CHECK: Variable: {{.*}}, name = "x1", type = "int", location = , +# CHECK: Variable: {{.*}}, name = "x2", type = "int", location = , .type f,@function f: # @f @@ -27,8 +35,12 @@ f: # @f .asciz "f" .Linfo_string4: .asciz "int" -.Linfo_string5: - .asciz "x" +.Lx0: + .asciz "x0" +.Lx1: + .asciz "x1" +.Lx2: + .asciz "x2" .section .debug_loc,"",@progbits .Ldebug_loc0: @@ -42,6 +54,10 @@ f: # @f .byte 80 # super-register DW_OP_reg0 .quad 0 .quad 0 +.Ldebug_loc2: + .quad .Lfunc_begin0-.Lfunc_begin0 + .quad .Lfunc_end0-.Lfunc_begin0 + .short 0xdead # Loc expr size .section .debug_abbrev,"",@progbits .byte 1 # Abbreviation Code @@ -104,10 +120,18 @@ f: # @f .quad .Lfunc_begin0 # DW_AT_low_pc .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc .long .Linfo_string3 # DW_AT_name - .long 83 # DW_AT_type - .byte 3 # Abbrev [3] 0x43:0xf DW_TAG_formal_parameter + .long .Lint # DW_AT_type + .byte 3 # Abbrev [3] DW_TAG_formal_parameter .long .Ldebug_loc0 # DW_AT_location - .long .Linfo_string5 # DW_AT_name + .long .Lx0 # DW_AT_name + .long .Lint-.Lcu_begin0 # DW_AT_type + .byte 3 # Abbrev [3] DW_TAG_formal_parameter + .long 0xdeadbeef # DW_AT_location + .long .Lx1 # DW_AT_name + .long .Lint-.Lcu_begin0 # DW_AT_type + .byte 3 # Abbrev [3] DW_TAG_formal_parameter + .long .Ldebug_loc2 # DW_AT_location + .long .Lx2 # DW_AT_name .long .Lint-.Lcu_begin0 # DW_AT_type .byte 0 # End Of Children Mark .Lint: diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 507e4fa4c79494..44aacfde43c06b 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -2708,29 +2708,6 @@ bool DWARFExpression::Evaluate( return true; // Return true on success } -size_t DWARFExpression::LocationListSize(const DWARFUnit *dwarf_cu, - const DataExtractor &debug_loc_data, - lldb::offset_t offset) { - const lldb::offset_t debug_loc_offset = offset; - while (debug_loc_data.ValidOffset(offset)) { - lldb::addr_t start_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t end_addr = LLDB_INVALID_ADDRESS; - if (!AddressRangeForLocationListEntry(dwarf_cu, debug_loc_data, &offset, - start_addr, end_addr)) - break; - - if (start_addr == 0 && end_addr == 0) - break; - - uint16_t loc_length = debug_loc_data.GetU16(&offset); - offset += loc_length; - } - - if (offset > debug_loc_offset) - return offset - debug_loc_offset; - return 0; -} - bool DWARFExpression::AddressRangeForLocationListEntry( const DWARFUnit *dwarf_cu, const DataExtractor &debug_loc_data, lldb::offset_t *offset_ptr, lldb::addr_t &low_pc, lldb::addr_t &high_pc) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 056cc70545e141..3c799f920a272d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2186,9 +2186,10 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, std::vector DWARFASTParserClang::GetDIEForDeclContext( lldb_private::CompilerDeclContext decl_context) { std::vector result; - for (auto it = m_decl_ctx_to_die.find( - (clang::DeclContext *)decl_context.GetOpaqueDeclContext()); - it != m_decl_ctx_to_die.end(); it++) + auto opaque_decl_ctx = + (clang::DeclContext *)decl_context.GetOpaqueDeclContext(); + for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx); + it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx; it++) result.push_back(it->second); return result; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index a7349d197004a7..e5b301d24c0c57 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -343,17 +343,11 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges( *frame_base = DWARFExpression( module, DataExtractor(data, block_offset, block_length), cu); } else { - const DWARFDataExtractor &debug_loc_data = dwarf.DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - cu, debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - *frame_base = DWARFExpression(module, - DataExtractor(debug_loc_data, - debug_loc_offset, - loc_list_length), - cu); + DataExtractor data = dwarf.DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + *frame_base = DWARFExpression(module, data, cu); if (lo_pc != LLDB_INVALID_ADDRESS) { assert(lo_pc >= cu->GetBaseAddress()); frame_base->SetLocationListSlide(lo_pc - diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index f625e2bdedc123..f91c1237f13a5f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3302,17 +3302,11 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, module, DataExtractor(data, block_offset, block_length), die.GetCU()); } else { - const DWARFDataExtractor &debug_loc_data = DebugLocData(); - const dw_offset_t debug_loc_offset = form_value.Unsigned(); - - size_t loc_list_length = DWARFExpression::LocationListSize( - die.GetCU(), debug_loc_data, debug_loc_offset); - if (loc_list_length > 0) { - location = DWARFExpression(module, - DataExtractor(debug_loc_data, - debug_loc_offset, - loc_list_length), - die.GetCU()); + DataExtractor data = DebugLocData(); + const dw_offset_t offset = form_value.Unsigned(); + if (data.ValidOffset(offset)) { + data = DataExtractor(data, offset, data.GetByteSize() - offset); + location = DWARFExpression(module, data, die.GetCU()); assert(func_low_pc != LLDB_INVALID_ADDRESS); location.SetLocationListSlide( func_low_pc - diff --git a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt index b2ece4eeaed736..57ee46316e03f2 100644 --- a/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/unittests/SymbolFile/DWARF/CMakeLists.txt @@ -1,4 +1,5 @@ add_lldb_unittest(SymbolFileDWARFTests + DWARFASTParserClangTests.cpp SymbolFileDWARFTests.cpp LINK_LIBS diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp new file mode 100644 index 00000000000000..8ffd330985226e --- /dev/null +++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp @@ -0,0 +1,47 @@ +//===-- DWARFASTParserClangTests.cpp ----------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" + +#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" +#include "Plugins/SymbolFile/DWARF/DWARFDIE.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { +class DWARFASTParserClangStub : public DWARFASTParserClang { +public: + using DWARFASTParserClang::DWARFASTParserClang; + using DWARFASTParserClang::LinkDeclContextToDIE; +}; +} // namespace + +// If your implementation needs to dereference the dummy pointers we are +// defining here, causing this test to fail, feel free to delete it. +TEST(DWARFASTParserClangTests, + TestGetDIEForDeclContextReturnsOnlyMatchingEntries) { + ClangASTContext ast_ctx; + DWARFASTParserClangStub ast_parser(ast_ctx); + + DWARFUnit *unit = nullptr; + DWARFDIE die1(unit, (DWARFDebugInfoEntry *)1LL); + DWARFDIE die2(unit, (DWARFDebugInfoEntry *)2LL); + DWARFDIE die3(unit, (DWARFDebugInfoEntry *)3LL); + DWARFDIE die4(unit, (DWARFDebugInfoEntry *)4LL); + ast_parser.LinkDeclContextToDIE((clang::DeclContext *)1LL, die1); + ast_parser.LinkDeclContextToDIE((clang::DeclContext *)2LL, die2); + ast_parser.LinkDeclContextToDIE((clang::DeclContext *)2LL, die3); + ast_parser.LinkDeclContextToDIE((clang::DeclContext *)3LL, die4); + + auto die_list = ast_parser.GetDIEForDeclContext( + CompilerDeclContext(nullptr, (clang::DeclContext *)2LL)); + ASSERT_EQ(2u, die_list.size()); + ASSERT_EQ(die2, die_list[0]); + ASSERT_EQ(die3, die_list[1]); +} diff --git a/llvm/test/CodeGen/PowerPC/fp-int-conversions-direct-moves.ll b/llvm/test/CodeGen/PowerPC/fp-int-conversions-direct-moves.ll index 955b1f27ca2670..3954dd7aa85f62 100644 --- a/llvm/test/CodeGen/PowerPC/fp-int-conversions-direct-moves.ll +++ b/llvm/test/CodeGen/PowerPC/fp-int-conversions-direct-moves.ll @@ -1,418 +1,529 @@ -; RUN: llc -verify-machineinstrs -mcpu=pwr8 -mtriple=powerpc64-unknown-unknown < %s | FileCheck %s -; RUN: llc -verify-machineinstrs -mcpu=pwr8 -mtriple=powerpc64le-unknown-unknown < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mcpu=pwr8 -ppc-asm-full-reg-names \ +; RUN: -ppc-vsr-nums-as-vr -mtriple=powerpc64-unknown-unknown < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mcpu=pwr8 -ppc-asm-full-reg-names \ +; RUN: -ppc-vsr-nums-as-vr -mtriple=powerpc64le-unknown-unknown < %s | FileCheck %s ; Function Attrs: nounwind define zeroext i8 @_Z6testcff(float %arg) { +; CHECK-LABEL: _Z6testcff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptoui float %0 to i8 ret i8 %conv -; CHECK-LABEL: @_Z6testcff -; CHECK: xscvdpsxws [[CONVREG01:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG01]] } ; Function Attrs: nounwind define float @_Z6testfcc(i8 zeroext %arg) { +; CHECK-LABEL: _Z6testfcc: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: stb r3, -1(r1) +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i8, align 1 store i8 %arg, i8* %arg.addr, align 1 %0 = load i8, i8* %arg.addr, align 1 %conv = uitofp i8 %0 to float ret float %conv -; CHECK-LABEL: @_Z6testfcc -; CHECK: mtvsrwz [[MOVEREG01:[0-9]+]], 3 -; CHECK: xscvuxdsp 1, [[MOVEREG01]] } ; Function Attrs: nounwind define zeroext i8 @_Z6testcdd(double %arg) { +; CHECK-LABEL: _Z6testcdd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptoui double %0 to i8 ret i8 %conv -; CHECK-LABEL: @_Z6testcdd -; CHECK: xscvdpsxws [[CONVREG02:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG02]] } ; Function Attrs: nounwind define double @_Z6testdcc(i8 zeroext %arg) { +; CHECK-LABEL: _Z6testdcc: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: stb r3, -1(r1) +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i8, align 1 store i8 %arg, i8* %arg.addr, align 1 %0 = load i8, i8* %arg.addr, align 1 %conv = uitofp i8 %0 to double ret double %conv -; CHECK-LABEL: @_Z6testdcc -; CHECK: mtvsrwz [[MOVEREG02:[0-9]+]], 3 -; CHECK: xscvuxddp 1, [[MOVEREG02]] } ; Function Attrs: nounwind define zeroext i8 @_Z7testucff(float %arg) { +; CHECK-LABEL: _Z7testucff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptoui float %0 to i8 ret i8 %conv -; CHECK-LABEL: @_Z7testucff -; CHECK: xscvdpsxws [[CONVREG03:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG03]] } ; Function Attrs: nounwind define float @_Z7testfuch(i8 zeroext %arg) { +; CHECK-LABEL: _Z7testfuch: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: stb r3, -1(r1) +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i8, align 1 store i8 %arg, i8* %arg.addr, align 1 %0 = load i8, i8* %arg.addr, align 1 %conv = uitofp i8 %0 to float ret float %conv -; CHECK-LABEL: @_Z7testfuch -; CHECK: mtvsrwz [[MOVEREG03:[0-9]+]], 3 -; CHECK: xscvuxdsp 1, [[MOVEREG03]] } ; Function Attrs: nounwind define zeroext i8 @_Z7testucdd(double %arg) { +; CHECK-LABEL: _Z7testucdd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptoui double %0 to i8 ret i8 %conv -; CHECK-LABEL: @_Z7testucdd -; CHECK: xscvdpsxws [[CONVREG04:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG04]] } ; Function Attrs: nounwind define double @_Z7testduch(i8 zeroext %arg) { +; CHECK-LABEL: _Z7testduch: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: stb r3, -1(r1) +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i8, align 1 store i8 %arg, i8* %arg.addr, align 1 %0 = load i8, i8* %arg.addr, align 1 %conv = uitofp i8 %0 to double ret double %conv -; CHECK-LABEL: @_Z7testduch -; CHECK: mtvsrwz [[MOVEREG04:[0-9]+]], 3 -; CHECK: xscvuxddp 1, [[MOVEREG04]] } ; Function Attrs: nounwind define signext i16 @_Z6testsff(float %arg) { +; CHECK-LABEL: _Z6testsff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptosi float %0 to i16 ret i16 %conv -; CHECK-LABEL: @_Z6testsff -; CHECK: xscvdpsxws [[CONVREG05:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG05]] } ; Function Attrs: nounwind define float @_Z6testfss(i16 signext %arg) { +; CHECK-LABEL: _Z6testfss: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwa f0, r3 +; CHECK-NEXT: sth r3, -2(r1) +; CHECK-NEXT: xscvsxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i16, align 2 store i16 %arg, i16* %arg.addr, align 2 %0 = load i16, i16* %arg.addr, align 2 %conv = sitofp i16 %0 to float ret float %conv -; CHECK-LABEL: @_Z6testfss -; CHECK: mtvsrwa [[MOVEREG05:[0-9]+]], 3 -; CHECK: xscvsxdsp 1, [[MOVEREG05]] } ; Function Attrs: nounwind define signext i16 @_Z6testsdd(double %arg) { +; CHECK-LABEL: _Z6testsdd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptosi double %0 to i16 ret i16 %conv -; CHECK-LABEL: @_Z6testsdd -; CHECK: xscvdpsxws [[CONVREG06:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG06]] } ; Function Attrs: nounwind define double @_Z6testdss(i16 signext %arg) { +; CHECK-LABEL: _Z6testdss: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwa f0, r3 +; CHECK-NEXT: sth r3, -2(r1) +; CHECK-NEXT: xscvsxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i16, align 2 store i16 %arg, i16* %arg.addr, align 2 %0 = load i16, i16* %arg.addr, align 2 %conv = sitofp i16 %0 to double ret double %conv -; CHECK-LABEL: @_Z6testdss -; CHECK: mtvsrwa [[MOVEREG06:[0-9]+]], 3 -; CHECK: xscvsxddp 1, [[MOVEREG06]] } ; Function Attrs: nounwind define zeroext i16 @_Z7testusff(float %arg) { +; CHECK-LABEL: _Z7testusff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptoui float %0 to i16 ret i16 %conv -; CHECK-LABEL: @_Z7testusff -; CHECK: xscvdpsxws [[CONVREG07:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG07]] } ; Function Attrs: nounwind define float @_Z7testfust(i16 zeroext %arg) { +; CHECK-LABEL: _Z7testfust: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: sth r3, -2(r1) +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i16, align 2 store i16 %arg, i16* %arg.addr, align 2 %0 = load i16, i16* %arg.addr, align 2 %conv = uitofp i16 %0 to float ret float %conv -; CHECK-LABEL: @_Z7testfust -; CHECK: mtvsrwz [[MOVEREG07:[0-9]+]], 3 -; CHECK: xscvuxdsp 1, [[MOVEREG07]] } ; Function Attrs: nounwind define zeroext i16 @_Z7testusdd(double %arg) { +; CHECK-LABEL: _Z7testusdd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptoui double %0 to i16 ret i16 %conv -; CHECK-LABEL: @_Z7testusdd -; CHECK: xscvdpsxws [[CONVREG08:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG08]] } ; Function Attrs: nounwind define double @_Z7testdust(i16 zeroext %arg) { +; CHECK-LABEL: _Z7testdust: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: sth r3, -2(r1) +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i16, align 2 store i16 %arg, i16* %arg.addr, align 2 %0 = load i16, i16* %arg.addr, align 2 %conv = uitofp i16 %0 to double ret double %conv -; CHECK-LABEL: @_Z7testdust -; CHECK: mtvsrwz [[MOVEREG08:[0-9]+]], 3 -; CHECK: xscvuxddp 1, [[MOVEREG08]] } ; Function Attrs: nounwind define signext i32 @_Z6testiff(float %arg) { +; CHECK-LABEL: _Z6testiff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptosi float %0 to i32 ret i32 %conv -; CHECK-LABEL: @_Z6testiff -; CHECK: xscvdpsxws [[CONVREG09:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG09]] } ; Function Attrs: nounwind define float @_Z6testfii(i32 signext %arg) { +; CHECK-LABEL: _Z6testfii: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwa f0, r3 +; CHECK-NEXT: stw r3, -4(r1) +; CHECK-NEXT: xscvsxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i32, align 4 store i32 %arg, i32* %arg.addr, align 4 %0 = load i32, i32* %arg.addr, align 4 %conv = sitofp i32 %0 to float ret float %conv -; CHECK-LABEL: @_Z6testfii -; CHECK: mtvsrwa [[MOVEREG09:[0-9]+]], 3 -; CHECK: xscvsxdsp 1, [[MOVEREG09]] } ; Function Attrs: nounwind define signext i32 @_Z6testidd(double %arg) { +; CHECK-LABEL: _Z6testidd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxws f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: extsw r3, r3 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptosi double %0 to i32 ret i32 %conv -; CHECK-LABEL: @_Z6testidd -; CHECK: xscvdpsxws [[CONVREG10:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG10]] } ; Function Attrs: nounwind define double @_Z6testdii(i32 signext %arg) { +; CHECK-LABEL: _Z6testdii: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwa f0, r3 +; CHECK-NEXT: stw r3, -4(r1) +; CHECK-NEXT: xscvsxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i32, align 4 store i32 %arg, i32* %arg.addr, align 4 %0 = load i32, i32* %arg.addr, align 4 %conv = sitofp i32 %0 to double ret double %conv -; CHECK-LABEL: @_Z6testdii -; CHECK: mtvsrwa [[MOVEREG10:[0-9]+]], 3 -; CHECK: xscvsxddp 1, [[MOVEREG10]] } ; Function Attrs: nounwind define zeroext i32 @_Z7testuiff(float %arg) { +; CHECK-LABEL: _Z7testuiff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpuxws f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptoui float %0 to i32 ret i32 %conv -; CHECK-LABEL: @_Z7testuiff -; CHECK: xscvdpuxws [[CONVREG11:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG11]] } ; Function Attrs: nounwind define float @_Z7testfuij(i32 zeroext %arg) { +; CHECK-LABEL: _Z7testfuij: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: stw r3, -4(r1) +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i32, align 4 store i32 %arg, i32* %arg.addr, align 4 %0 = load i32, i32* %arg.addr, align 4 %conv = uitofp i32 %0 to float ret float %conv -; CHECK-LABEL: @_Z7testfuij -; CHECK: mtvsrwz [[MOVEREG11:[0-9]+]], 3 -; CHECK: xscvuxdsp 1, [[MOVEREG11]] } ; Function Attrs: nounwind define zeroext i32 @_Z7testuidd(double %arg) { +; CHECK-LABEL: _Z7testuidd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpuxws f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mfvsrwz r3, f0 +; CHECK-NEXT: clrldi r3, r3, 32 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptoui double %0 to i32 ret i32 %conv -; CHECK-LABEL: @_Z7testuidd -; CHECK: xscvdpuxws [[CONVREG12:[0-9]+]], 1 -; CHECK: mfvsrwz 3, [[CONVREG12]] } ; Function Attrs: nounwind define double @_Z7testduij(i32 zeroext %arg) { +; CHECK-LABEL: _Z7testduij: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrwz f0, r3 +; CHECK-NEXT: stw r3, -4(r1) +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i32, align 4 store i32 %arg, i32* %arg.addr, align 4 %0 = load i32, i32* %arg.addr, align 4 %conv = uitofp i32 %0 to double ret double %conv -; CHECK-LABEL: @_Z7testduij -; CHECK: mtvsrwz [[MOVEREG12:[0-9]+]], 3 -; CHECK: xscvuxddp 1, [[MOVEREG12]] } ; Function Attrs: nounwind define i64 @_Z7testllff(float %arg) { +; CHECK-LABEL: _Z7testllff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxds f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mffprd r3, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptosi float %0 to i64 ret i64 %conv -; CHECK-LABEL: @_Z7testllff -; CHECK: xscvdpsxds [[CONVREG13:[0-9]+]], 1 -; CHECK: mffprd 3, [[CONVREG13]] } ; Function Attrs: nounwind define float @_Z7testfllx(i64 %arg) { +; CHECK-LABEL: _Z7testfllx: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrd f0, r3 +; CHECK-NEXT: std r3, -8(r1) +; CHECK-NEXT: xscvsxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i64, align 8 store i64 %arg, i64* %arg.addr, align 8 %0 = load i64, i64* %arg.addr, align 8 %conv = sitofp i64 %0 to float ret float %conv -; CHECK-LABEL:@_Z7testfllx -; CHECK: mtvsrd [[MOVEREG13:[0-9]+]], 3 -; CHECK: xscvsxdsp 1, [[MOVEREG13]] } ; Function Attrs: nounwind define i64 @_Z7testlldd(double %arg) { +; CHECK-LABEL: _Z7testlldd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpsxds f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mffprd r3, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptosi double %0 to i64 ret i64 %conv -; CHECK-LABEL: @_Z7testlldd -; CHECK: xscvdpsxds [[CONVREG14:[0-9]+]], 1 -; CHECK: mffprd 3, [[CONVREG14]] } ; Function Attrs: nounwind define double @_Z7testdllx(i64 %arg) { +; CHECK-LABEL: _Z7testdllx: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrd f0, r3 +; CHECK-NEXT: std r3, -8(r1) +; CHECK-NEXT: xscvsxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i64, align 8 store i64 %arg, i64* %arg.addr, align 8 %0 = load i64, i64* %arg.addr, align 8 %conv = sitofp i64 %0 to double ret double %conv -; CHECK-LABEL: @_Z7testdllx -; CHECK: mtvsrd [[MOVEREG14:[0-9]+]], 3 -; CHECK: xscvsxddp 1, [[MOVEREG14]] } ; Function Attrs: nounwind define i64 @_Z8testullff(float %arg) { +; CHECK-LABEL: _Z8testullff: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpuxds f0, f1 +; CHECK-NEXT: stfs f1, -4(r1) +; CHECK-NEXT: mffprd r3, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca float, align 4 store float %arg, float* %arg.addr, align 4 %0 = load float, float* %arg.addr, align 4 %conv = fptoui float %0 to i64 ret i64 %conv -; CHECK-LABEL: @_Z8testullff -; CHECK: xscvdpuxds [[CONVREG15:[0-9]+]], 1 -; CHECK: mffprd 3, [[CONVREG15]] } ; Function Attrs: nounwind define float @_Z8testfully(i64 %arg) { +; CHECK-LABEL: _Z8testfully: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrd f0, r3 +; CHECK-NEXT: std r3, -8(r1) +; CHECK-NEXT: xscvuxdsp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i64, align 8 store i64 %arg, i64* %arg.addr, align 8 %0 = load i64, i64* %arg.addr, align 8 %conv = uitofp i64 %0 to float ret float %conv -; CHECK-LABEL: @_Z8testfully -; CHECK: mtvsrd [[MOVEREG15:[0-9]+]], 3 -; CHECK: xscvuxdsp 1, [[MOVEREG15]] } ; Function Attrs: nounwind define i64 @_Z8testulldd(double %arg) { +; CHECK-LABEL: _Z8testulldd: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xscvdpuxds f0, f1 +; CHECK-NEXT: stfd f1, -8(r1) +; CHECK-NEXT: mffprd r3, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca double, align 8 store double %arg, double* %arg.addr, align 8 %0 = load double, double* %arg.addr, align 8 %conv = fptoui double %0 to i64 ret i64 %conv -; CHECK-LABEL: @_Z8testulldd -; CHECK: xscvdpuxds [[CONVREG16:[0-9]+]], 1 -; CHECK: mffprd 3, [[CONVREG16]] } ; Function Attrs: nounwind define double @_Z8testdully(i64 %arg) { +; CHECK-LABEL: _Z8testdully: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mtvsrd f0, r3 +; CHECK-NEXT: std r3, -8(r1) +; CHECK-NEXT: xscvuxddp f1, f0 +; CHECK-NEXT: blr entry: %arg.addr = alloca i64, align 8 store i64 %arg, i64* %arg.addr, align 8 %0 = load i64, i64* %arg.addr, align 8 %conv = uitofp i64 %0 to double ret double %conv -; CHECK-LABEL: @_Z8testdully -; CHECK: mtvsrd [[MOVEREG16:[0-9]+]], 3 -; CHECK: xscvuxddp 1, [[MOVEREG16]] } diff --git a/llvm/test/Transforms/SimplifyCFG/safe-low-bit-extract.ll b/llvm/test/Transforms/SimplifyCFG/safe-low-bit-extract.ll new file mode 100644 index 00000000000000..354cfff7ba72a8 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/safe-low-bit-extract.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -simplifycfg -S | FileCheck %s + +; This is the naive implementation of x86 BZHI/BEXTR instruction: +; it takes input and bit count, and extracts low nbits up to bit width. +; I.e. unlike shift it does not have any UB when nbits >= bitwidth. +; Which means we don't need a while PHI here, simple select will do. +define i32 @extract_low_bits(i32 %input, i32 %nbits) { +; CHECK-LABEL: @extract_low_bits( +; CHECK-NEXT: begin: +; CHECK-NEXT: [[SHOULD_MASK:%.*]] = icmp ult i32 [[NBITS:%.*]], 32 +; CHECK-NEXT: br i1 [[SHOULD_MASK]], label [[PERFORM_MASKING:%.*]], label [[END:%.*]] +; CHECK: perform_masking: +; CHECK-NEXT: [[MASK_NOT:%.*]] = shl nsw i32 -1, [[NBITS]] +; CHECK-NEXT: [[MASK:%.*]] = xor i32 [[MASK_NOT]], -1 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[MASK]], [[INPUT:%.*]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RES:%.*]] = phi i32 [ [[MASKED]], [[PERFORM_MASKING]] ], [ [[INPUT]], [[BEGIN:%.*]] ] +; CHECK-NEXT: ret i32 [[RES]] +; +begin: + %should_mask = icmp ult i32 %nbits, 32 + br i1 %should_mask, label %perform_masking, label %end + +perform_masking: ; preds = %begin + %mask.not = shl nsw i32 -1, %nbits + %mask = xor i32 %mask.not, -1 + %masked = and i32 %mask, %input + br label %end + +end: ; preds = %perform_masking, %begin + %res = phi i32 [ %masked, %perform_masking ], [ %input, %begin ] + ret i32 %res +}