From e71c7b593a2d1b7d60dc8aaa4b8ede03de7bbd00 Mon Sep 17 00:00:00 2001 From: SharmaRithik Date: Fri, 10 Jul 2020 11:16:06 +0530 Subject: [PATCH 01/10] [CodeMoverUtils] Move OrderedInstructions to CodeMoverUtils Summary: This patch moves OrderedInstructions to CodeMoverUtils as It was the only place where OrderedInstructions is required. Authored By: RithikSharma Reviewer: Whitney, bmahjour, etiotto, fhahn, nikic Reviewed By: Whitney, nikic Subscribers: mgorny, hiraditya, llvm-commits Tag: LLVM Differential Revision: https://reviews.llvm.org/D80643 --- .../llvm/Analysis/OrderedInstructions.h | 57 ----------------- llvm/lib/Analysis/CMakeLists.txt | 1 - llvm/lib/Analysis/OrderedInstructions.cpp | 59 ----------------- llvm/lib/Transforms/Utils/CodeMoverUtils.cpp | 16 ++++- llvm/unittests/Analysis/CMakeLists.txt | 3 +- .../Analysis/OrderedInstructionsTest.cpp | 64 ------------------- .../gn/secondary/llvm/lib/Analysis/BUILD.gn | 1 - .../llvm/unittests/Analysis/BUILD.gn | 1 - 8 files changed, 14 insertions(+), 188 deletions(-) delete mode 100644 llvm/include/llvm/Analysis/OrderedInstructions.h delete mode 100644 llvm/lib/Analysis/OrderedInstructions.cpp delete mode 100644 llvm/unittests/Analysis/OrderedInstructionsTest.cpp diff --git a/llvm/include/llvm/Analysis/OrderedInstructions.h b/llvm/include/llvm/Analysis/OrderedInstructions.h deleted file mode 100644 index b2bf857502280c..00000000000000 --- a/llvm/include/llvm/Analysis/OrderedInstructions.h +++ /dev/null @@ -1,57 +0,0 @@ -//===- llvm/Transforms/Utils/OrderedInstructions.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 -// -//===----------------------------------------------------------------------===// -// -// This file defines an efficient way to check for dominance relation between 2 -// instructions. -// -// FIXME: This is really just a convenience wrapper to check dominance between -// two arbitrary instructions in different basic blocks. We should fold it into -// DominatorTree, which is the more widely used interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H -#define LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H - -namespace llvm { - -class DominatorTree; -class Instruction; - -class OrderedInstructions { - /// The dominator tree of the parent function. - DominatorTree *DT; - - /// Return true if the first instruction comes before the second in the - /// same basic block. It will create an ordered basic block, if it does - /// not yet exist in OBBMap. - bool localDominates(const Instruction *, const Instruction *) const; - -public: - /// Constructor. - OrderedInstructions(DominatorTree *DT) : DT(DT) {} - - /// Return true if first instruction dominates the second. - bool dominates(const Instruction *, const Instruction *) const; - - /// Return true if the first instruction comes before the second in the - /// dominator tree DFS traversal if they are in different basic blocks, - /// or if the first instruction comes before the second in the same basic - /// block. - bool dfsBefore(const Instruction *, const Instruction *) const; - - // Return true if the first instruction comes before the second in the - // dominator tree BFS traversal based on the level number of nodes in - // dominator tree if they are in different basic blocks else if the first - // instruction comes before the second in the same basic block. - bool domTreeLevelBefore(const Instruction *, const Instruction *) const; -}; - -} // end namespace llvm - -#endif // LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 9cc2576ae1ee06..a317579ecc836d 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -90,7 +90,6 @@ add_llvm_component_library(LLVMAnalysis ObjCARCAnalysisUtils.cpp ObjCARCInstKind.cpp OptimizationRemarkEmitter.cpp - OrderedInstructions.cpp PHITransAddr.cpp PhiValues.cpp PostDominators.cpp diff --git a/llvm/lib/Analysis/OrderedInstructions.cpp b/llvm/lib/Analysis/OrderedInstructions.cpp deleted file mode 100644 index 58d9a618184abd..00000000000000 --- a/llvm/lib/Analysis/OrderedInstructions.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===-- OrderedInstructions.cpp - Instruction dominance function ---------===// -// -// 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 file defines utility to check dominance relation of 2 instructions. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/OrderedInstructions.h" -#include "llvm/IR/Dominators.h" - -using namespace llvm; - -bool OrderedInstructions::localDominates(const Instruction *InstA, - const Instruction *InstB) const { - assert(InstA->getParent() == InstB->getParent() && - "Instructions must be in the same basic block"); - - return InstA->comesBefore(InstB); -} - -/// Given 2 instructions, check for dominance relation if the instructions are -/// in the same basic block. Otherwise, use dominator tree. -bool OrderedInstructions::dominates(const Instruction *InstA, - const Instruction *InstB) const { - // Use ordered basic block to do dominance check in case the 2 instructions - // are in the same basic block. - if (InstA->getParent() == InstB->getParent()) - return localDominates(InstA, InstB); - return DT->dominates(InstA->getParent(), InstB->getParent()); -} - -bool OrderedInstructions::dfsBefore(const Instruction *InstA, - const Instruction *InstB) const { - // Use ordered basic block in case the 2 instructions are in the same basic - // block. - if (InstA->getParent() == InstB->getParent()) - return localDominates(InstA, InstB); - - DomTreeNode *DA = DT->getNode(InstA->getParent()); - DomTreeNode *DB = DT->getNode(InstB->getParent()); - return DA->getDFSNumIn() < DB->getDFSNumIn(); -} - -bool OrderedInstructions::domTreeLevelBefore(const Instruction *InstA, - const Instruction *InstB) const { - // Use ordered basic block in case the 2 instructions are in the same basic - // block. - if (InstA->getParent() == InstB->getParent()) - return localDominates(InstA, InstB); - - DomTreeNode *DA = DT->getNode(InstA->getParent()); - DomTreeNode *DB = DT->getNode(InstB->getParent()); - return DA->getLevel() < DB->getLevel(); -} diff --git a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp index 11a740f8285bc9..08047dc0f96ee8 100644 --- a/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp +++ b/llvm/lib/Transforms/Utils/CodeMoverUtils.cpp @@ -15,7 +15,6 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/DependenceAnalysis.h" -#include "llvm/Analysis/OrderedInstructions.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Dominators.h" @@ -94,6 +93,18 @@ class ControlConditions { }; } // namespace +static bool domTreeLevelBefore(DominatorTree *DT, const Instruction *InstA, + const Instruction *InstB) { + // Use ordered basic block in case the 2 instructions are in the same + // block. + if (InstA->getParent() == InstB->getParent()) + return InstA->comesBefore(InstB); + + DomTreeNode *DA = DT->getNode(InstA->getParent()); + DomTreeNode *DB = DT->getNode(InstB->getParent()); + return DA->getLevel() < DB->getLevel(); +} + const Optional ControlConditions::collectControlConditions( const BasicBlock &BB, const BasicBlock &Dominator, const DominatorTree &DT, const PostDominatorTree &PDT, unsigned MaxLookup) { @@ -332,9 +343,8 @@ bool llvm::isSafeToMoveBefore(Instruction &I, Instruction &InsertPoint, if (&InsertPoint == OpInst || !DT.dominates(OpInst, &InsertPoint)) return false; - OrderedInstructions OI(&DT); DT.updateDFSNumbers(); - const bool MoveForward = OI.domTreeLevelBefore(&I, &InsertPoint); + const bool MoveForward = domTreeLevelBefore(&DT, &I, &InsertPoint); Instruction &StartInst = (MoveForward ? I : InsertPoint); Instruction &EndInst = (MoveForward ? InsertPoint : I); SmallPtrSet InstsToCheck; diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt index 9f28bc701b5857..42f7dd3c061013 100644 --- a/llvm/unittests/Analysis/CMakeLists.txt +++ b/llvm/unittests/Analysis/CMakeLists.txt @@ -29,7 +29,6 @@ add_llvm_unittest(AnalysisTests LoopNestTest.cpp MemoryBuiltinsTest.cpp MemorySSATest.cpp - OrderedInstructionsTest.cpp PhiValuesTest.cpp ProfileSummaryInfoTest.cpp ScalarEvolutionTest.cpp @@ -41,4 +40,4 @@ add_llvm_unittest(AnalysisTests ValueLatticeTest.cpp ValueTrackingTest.cpp VectorUtilsTest.cpp - ) \ No newline at end of file + ) diff --git a/llvm/unittests/Analysis/OrderedInstructionsTest.cpp b/llvm/unittests/Analysis/OrderedInstructionsTest.cpp deleted file mode 100644 index 473fe7f50fc8ba..00000000000000 --- a/llvm/unittests/Analysis/OrderedInstructionsTest.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//===- OrderedInstructions.cpp - Unit tests for OrderedInstructions ------===// -// -// 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 "llvm/Analysis/OrderedInstructions.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "gtest/gtest.h" - -using namespace llvm; - -/// Check intra-basicblock and inter-basicblock dominance using -/// OrderedInstruction. -TEST(OrderedInstructionsTest, DominanceTest) { - LLVMContext Ctx; - Module M("test", Ctx); - IRBuilder<> B(Ctx); - FunctionType *FTy = - FunctionType::get(Type::getVoidTy(Ctx), {B.getInt8PtrTy()}, false); - Function *F = Function::Create(FTy, Function::ExternalLinkage, "f", M); - - // Create the function as follow and check for dominance relation. - // - // test(): - // bbx: - // loadx; - // loady; - // bby: - // loadz; - // return; - // - // More specifically, check for loadx -> (dominates) loady, - // loady -> loadx and loady -> loadz. - // - // Create BBX with 2 loads. - BasicBlock *BBX = BasicBlock::Create(Ctx, "bbx", F); - B.SetInsertPoint(BBX); - Argument *PointerArg = &*F->arg_begin(); - LoadInst *LoadInstX = B.CreateLoad(B.getInt8Ty(), PointerArg); - LoadInst *LoadInstY = B.CreateLoad(B.getInt8Ty(), PointerArg); - - // Create BBY with 1 load. - BasicBlock *BBY = BasicBlock::Create(Ctx, "bby", F); - B.SetInsertPoint(BBY); - LoadInst *LoadInstZ = B.CreateLoad(B.getInt8Ty(), PointerArg); - B.CreateRet(LoadInstZ); - std::unique_ptr DT(new DominatorTree(*F)); - OrderedInstructions OI(&*DT); - - // Intra-BB dominance test. - EXPECT_TRUE(OI.dominates(LoadInstX, LoadInstY)); - EXPECT_FALSE(OI.dominates(LoadInstY, LoadInstX)); - - // Inter-BB dominance test. - EXPECT_TRUE(OI.dominates(LoadInstY, LoadInstZ)); -} diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn index e7b89b79171407..11498ed6029843 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn @@ -88,7 +88,6 @@ static_library("Analysis") { "ObjCARCAnalysisUtils.cpp", "ObjCARCInstKind.cpp", "OptimizationRemarkEmitter.cpp", - "OrderedInstructions.cpp", "PHITransAddr.cpp", "PhiValues.cpp", "PostDominators.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn index 191d8483780420..b0dcd497d844e6 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn @@ -31,7 +31,6 @@ unittest("AnalysisTests") { "LoopNestTest.cpp", "MemoryBuiltinsTest.cpp", "MemorySSATest.cpp", - "OrderedInstructionsTest.cpp", "PhiValuesTest.cpp", "ProfileSummaryInfoTest.cpp", "ScalarEvolutionTest.cpp", From 98d763ad051f5eab89fa46167516fc8a84f471d0 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Wed, 8 Jul 2020 02:43:38 -0400 Subject: [PATCH 02/10] [clangd] Factor out some helper functions related to heuristic resolution in TargetFinder Summary: Two helpers are introduced: * Some of the logic previously in TargetFinder::Visit*() methods is factored out into resolveDependentExprToDecls(). * Some of the logic in getMembersReferencedViaDependentName() is factored out into resolveTypeToRecordDecl(). D82739 will build on this and use these functions in new ways. Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D83371 --- clang-tools-extra/clangd/FindTarget.cpp | 81 ++++++++++++++++--------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 1d09e8408c8376..627f40c854368e 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -58,6 +58,24 @@ nodeToString(const ast_type_traits::DynTypedNode &N) { return S; } +// Helper function for getMembersReferencedViaDependentName() +// which takes a dependent type `T` and heuristically +// resolves it to a CXXRecordDecl in which we can try name lookup. +CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) { + assert(T); + if (const auto *ICNT = T->getAs()) { + T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + } + const auto *TST = T->getAs(); + if (!TST) + return nullptr; + const ClassTemplateDecl *TD = dyn_cast_or_null( + TST->getTemplateName().getAsTemplateDecl()); + if (!TD) + return nullptr; + return TD->getTemplatedDecl(); +} + // Given a dependent type and a member name, heuristically resolve the // name to one or more declarations. // The current heuristic is simply to look up the name in the primary @@ -82,25 +100,17 @@ std::vector getMembersReferencedViaDependentName( ET->getDecl()->lookup(NameFactory(ET->getDecl()->getASTContext())); return {Result.begin(), Result.end()}; } - if (auto *ICNT = T->getAs()) { - T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); + if (auto *RD = resolveTypeToRecordDecl(T)) { + if (!RD->hasDefinition()) + return {}; + RD = RD->getDefinition(); + DeclarationName Name = NameFactory(RD->getASTContext()); + return RD->lookupDependentName(Name, [=](const NamedDecl *D) { + return IsNonstaticMember ? D->isCXXInstanceMember() + : !D->isCXXInstanceMember(); + }); } - auto *TST = T->getAs(); - if (!TST) - return {}; - const ClassTemplateDecl *TD = dyn_cast_or_null( - TST->getTemplateName().getAsTemplateDecl()); - if (!TD) - return {}; - CXXRecordDecl *RD = TD->getTemplatedDecl(); - if (!RD->hasDefinition()) - return {}; - RD = RD->getDefinition(); - DeclarationName Name = NameFactory(RD->getASTContext()); - return RD->lookupDependentName(Name, [=](const NamedDecl *D) { - return IsNonstaticMember ? D->isCXXInstanceMember() - : !D->isCXXInstanceMember(); - }); + return {}; } // Given the type T of a dependent expression that appears of the LHS of a "->", @@ -144,6 +154,28 @@ const Type *getPointeeType(const Type *T) { return FirstArg.getAsType().getTypePtrOrNull(); } +// Try to heuristically resolve a dependent expression `E` to one +// or more declarations that it likely references. +std::vector resolveDependentExprToDecls(const Expr *E) { + assert(E->isTypeDependent()); + if (const auto *ME = dyn_cast(E)) { + const Type *BaseType = ME->getBaseType().getTypePtrOrNull(); + if (ME->isArrow()) { + BaseType = getPointeeType(BaseType); + } + return getMembersReferencedViaDependentName( + BaseType, [ME](ASTContext &) { return ME->getMember(); }, + /*IsNonstaticMember=*/true); + } + if (const auto *RE = dyn_cast(E)) { + return getMembersReferencedViaDependentName( + RE->getQualifier()->getAsType(), + [RE](ASTContext &) { return RE->getDeclName(); }, + /*IsNonstaticMember=*/false); + } + return {}; +} + const NamedDecl *getTemplatePattern(const NamedDecl *D) { if (const CXXRecordDecl *CRD = dyn_cast(D)) { if (const auto *Result = CRD->getTemplateInstantiationPattern()) @@ -341,21 +373,12 @@ struct TargetFinder { } void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { - const Type *BaseType = E->getBaseType().getTypePtrOrNull(); - if (E->isArrow()) { - BaseType = getPointeeType(BaseType); - } - for (const NamedDecl *D : getMembersReferencedViaDependentName( - BaseType, [E](ASTContext &) { return E->getMember(); }, - /*IsNonstaticMember=*/true)) { + for (const NamedDecl *D : resolveDependentExprToDecls(E)) { Outer.add(D, Flags); } } void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { - for (const NamedDecl *D : getMembersReferencedViaDependentName( - E->getQualifier()->getAsType(), - [E](ASTContext &) { return E->getDeclName(); }, - /*IsNonstaticMember=*/false)) { + for (const NamedDecl *D : resolveDependentExprToDecls(E)) { Outer.add(D, Flags); } } From 04b9a46c842f793a2baedcad64de35fcbd3e93b7 Mon Sep 17 00:00:00 2001 From: Zakk Chen Date: Thu, 30 Apr 2020 03:24:19 -0700 Subject: [PATCH 03/10] [RISCV] Refactor FeatureRVCHints to make ProcessorModel more intuitive Reviewers: luismarques, asb, evandro Reviewed By: asb, evandro Tags: #llvm Differential Revision: https://reviews.llvm.org/D77030 --- llvm/lib/Target/RISCV/RISCV.td | 20 +++++++++----------- llvm/lib/Target/RISCV/RISCVSubtarget.h | 2 +- llvm/test/MC/RISCV/rv32c-invalid.s | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index ec00b256eeabf3..f0583f6919361f 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -140,12 +140,12 @@ def HasStdExtB : Predicate<"Subtarget->hasStdExtB()">, AssemblerPredicate<(all_of FeatureStdExtB), "'B' (Bit Manipulation Instructions)">; -def FeatureRVCHints - : SubtargetFeature<"rvc-hints", "EnableRVCHintInstrs", "true", - "Enable RVC Hint Instructions.">; +def FeatureNoRVCHints + : SubtargetFeature<"no-rvc-hints", "EnableRVCHintInstrs", "false", + "Disable RVC Hint Instructions.">; def HasRVCHints : Predicate<"Subtarget->enableRVCHintInstrs()">, - AssemblerPredicate<(all_of FeatureRVCHints), - "RVC Hint Instructions">; + AssemblerPredicate<(all_of(not FeatureNoRVCHints)), + "RVC Hint Instructions">; def FeatureStdExtV : SubtargetFeature<"experimental-v", "HasStdExtV", "true", @@ -207,15 +207,13 @@ include "RISCVSchedRocket64.td" // RISC-V processors supported. //===----------------------------------------------------------------------===// -def : ProcessorModel<"generic-rv32", NoSchedModel, [FeatureRVCHints]>; +def : ProcessorModel<"generic-rv32", NoSchedModel, []>; -def : ProcessorModel<"generic-rv64", NoSchedModel, [Feature64Bit, - FeatureRVCHints]>; +def : ProcessorModel<"generic-rv64", NoSchedModel, [Feature64Bit]>; -def : ProcessorModel<"rocket-rv32", Rocket32Model, [FeatureRVCHints]>; +def : ProcessorModel<"rocket-rv32", Rocket32Model, []>; -def : ProcessorModel<"rocket-rv64", Rocket64Model, [Feature64Bit, - FeatureRVCHints]>; +def : ProcessorModel<"rocket-rv64", Rocket64Model, [Feature64Bit]>; //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 133542de2301eb..fe1285f23b1597 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -54,7 +54,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { bool HasRV64 = false; bool IsRV32E = false; bool EnableLinkerRelax = false; - bool EnableRVCHintInstrs = false; + bool EnableRVCHintInstrs = true; bool EnableSaveRestore = false; unsigned XLen = 32; MVT XLenVT = MVT::i32; diff --git a/llvm/test/MC/RISCV/rv32c-invalid.s b/llvm/test/MC/RISCV/rv32c-invalid.s index 29cf0ac239fa4a..53b62c289e75eb 100644 --- a/llvm/test/MC/RISCV/rv32c-invalid.s +++ b/llvm/test/MC/RISCV/rv32c-invalid.s @@ -1,4 +1,4 @@ -# RUN: not llvm-mc -triple=riscv32 -mattr=+c -mattr=-rvc-hints < %s 2>&1 \ +# RUN: not llvm-mc -triple=riscv32 -mattr=+c -mattr=+no-rvc-hints < %s 2>&1 \ # RUN: | FileCheck %s ## GPRC From 50f24331fd91e70de6bf6c3efe45272ddfc711fd Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 30 Jun 2020 14:25:23 +0100 Subject: [PATCH 04/10] Add diagnostic option backing field for -fansi-escape-codes Summary: Keep track of -fansi-escape-codes in DiagnosticOptions and move the option to the new option parsing system. Depends on D82860 Reviewers: Bigcheese Subscribers: dexonsmith, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D82874 --- clang/include/clang/Basic/DiagnosticOptions.def | 1 + clang/include/clang/Driver/Options.td | 3 ++- clang/lib/Frontend/CompilerInvocation.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticOptions.def b/clang/include/clang/Basic/DiagnosticOptions.def index 6d1a1af92821b7..a946b5c6be8ef6 100644 --- a/clang/include/clang/Basic/DiagnosticOptions.def +++ b/clang/include/clang/Basic/DiagnosticOptions.def @@ -65,6 +65,7 @@ VALUE_DIAGOPT(ShowCategories, 2, 0) /// Show categories: 0 -> none, 1 -> Number, ENUM_DIAGOPT(Format, TextDiagnosticFormat, 2, Clang) /// Format for diagnostics: DIAGOPT(ShowColors, 1, 0) /// Show diagnostics with ANSI color sequences. +DIAGOPT(UseANSIEscapeCodes, 1, 0) ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1, Ovl_All) /// Overload candidates to show. DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 113696aeec7f08..c6acd745bfd05d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -849,7 +849,8 @@ def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group, Flags<[CoreOption, DriverOption]>; def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group; def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group, - Flags<[CoreOption, CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">; + Flags<[CoreOption, CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">, + MarshallingInfoFlag<"DiagnosticOpts->UseANSIEscapeCodes", "false">; def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group, Flags<[CC1Option]>, HelpText<"Treat each comma separated argument in as a documentation comment block command">, MetaVarName<"">; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 6f6af917e3a31a..64dcfa83182466 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1580,8 +1580,6 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths); Opts.ShowOptionNames = !Args.hasArg(OPT_fno_diagnostics_show_option); - llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); - // Default behavior is to not to show note include stacks. Opts.ShowNoteIncludeStack = false; if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack, @@ -3724,6 +3722,10 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, } Success &= Res.parseSimpleArgs(Args, Diags); + + llvm::sys::Process::UseANSIEscapeCodes( + Res.DiagnosticOpts->UseANSIEscapeCodes); + Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags); Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args); ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args); From a65da5f5924fbb7bad28bbb397e3e9a94959df4c Mon Sep 17 00:00:00 2001 From: Muhammad Omair Javaid Date: Wed, 8 Jul 2020 01:22:35 +0500 Subject: [PATCH 05/10] [LLDB] Update AArch64 Dwarf and EH frame register numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch updates ARM64_ehframe_Registers.h and ARM64_DWARF_Registers.h with latest register numbers in line with AArch64 SVE support. For refernce take a look at "DWARF for the ARM® 64-bit Architecture (AArch64) with SVE support" manual from Arm. Version used: abi_sve_aadwarf_100985_0000_00_en.pdf --- lldb/source/Utility/ARM64_DWARF_Registers.h | 62 ++++++++++++++++- lldb/source/Utility/ARM64_ehframe_Registers.h | 66 +++++++++++++++++-- 2 files changed, 121 insertions(+), 7 deletions(-) diff --git a/lldb/source/Utility/ARM64_DWARF_Registers.h b/lldb/source/Utility/ARM64_DWARF_Registers.h index 1bb2ba071f956b..ed8ff722088dca 100644 --- a/lldb/source/Utility/ARM64_DWARF_Registers.h +++ b/lldb/source/Utility/ARM64_DWARF_Registers.h @@ -51,7 +51,31 @@ enum { sp = x31, pc = 32, cpsr = 33, - // 34-63 reserved + // 34-45 reserved + + // 64-bit SVE Vector granule pseudo register + vg = 46, + + // VG ́8-bit SVE first fault register + ffr = 47, + + // VG x ́8-bit SVE predicate registers + p0 = 48, + p1, + p2, + p3, + p4, + p5, + p6, + p7, + p8, + p9, + p10, + p11, + p12, + p13, + p14, + p15, // V0-V31 (128 bit vector registers) v0 = 64, @@ -85,9 +109,41 @@ enum { v28, v29, v30, - v31 + v31, - // 96-127 reserved + // VG ́64-bit SVE vector registers + z0 = 96, + z1, + z2, + z3, + z4, + z5, + z6, + z7, + z8, + z9, + z10, + z11, + z12, + z13, + z14, + z15, + z16, + z17, + z18, + z19, + z20, + z21, + z22, + z23, + z24, + z25, + z26, + z27, + z28, + z29, + z30, + z31 }; } // namespace arm64_dwarf diff --git a/lldb/source/Utility/ARM64_ehframe_Registers.h b/lldb/source/Utility/ARM64_ehframe_Registers.h index 3e7baf98e14807..c235891ec015e8 100644 --- a/lldb/source/Utility/ARM64_ehframe_Registers.h +++ b/lldb/source/Utility/ARM64_ehframe_Registers.h @@ -49,10 +49,34 @@ enum { lr, // aka x30 sp, // aka x31 aka wzr pc, // value is 32 - cpsr -}; + cpsr, + // 34-45 reserved -enum { + // 64-bit SVE Vector granule pseudo register + vg = 46, + + // VG ́8-bit SVE first fault register + ffr = 47, + + // VG x ́8-bit SVE predicate registers + p0 = 48, + p1, + p2, + p3, + p4, + p5, + p6, + p7, + p8, + p9, + p10, + p11, + p12, + p13, + p14, + p15, + + // V0-V31 (128 bit vector registers) v0 = 64, v1, v2, @@ -84,7 +108,41 @@ enum { v28, v29, v30, - v31 // 95 + v31, + + // VG ́64-bit SVE vector registers + z0 = 96, + z1, + z2, + z3, + z4, + z5, + z6, + z7, + z8, + z9, + z10, + z11, + z12, + z13, + z14, + z15, + z16, + z17, + z18, + z19, + z20, + z21, + z22, + z23, + z24, + z25, + z26, + z27, + z28, + z29, + z30, + z31 }; } From 229dfb4728f45cf9607aaa564155c267f3a0f59c Mon Sep 17 00:00:00 2001 From: David Sherwood Date: Mon, 6 Jul 2020 10:17:16 +0100 Subject: [PATCH 06/10] [CodeGen] Replace calls to getVectorNumElements() in SelectionDAG::SplitVector This patch replaces some invalid calls to getVectorNumElements() with calls to getVectorMinNumElements() instead, since the code paths changed in this patch work for both fixed and scalable vector types. Fixes warnings in this test: sve-sext-zext.ll Differential Revision: https://reviews.llvm.org/D83203 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 0b80173cb41990..80650912086947 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -9639,14 +9639,22 @@ SelectionDAG::GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT, std::pair SelectionDAG::SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT) { - assert(LoVT.getVectorNumElements() + HiVT.getVectorNumElements() <= - N.getValueType().getVectorNumElements() && + assert(LoVT.isScalableVector() == HiVT.isScalableVector() && + LoVT.isScalableVector() == N.getValueType().isScalableVector() && + "Splitting vector with an invalid mixture of fixed and scalable " + "vector types"); + assert(LoVT.getVectorMinNumElements() + HiVT.getVectorMinNumElements() <= + N.getValueType().getVectorMinNumElements() && "More vector elements requested than available!"); SDValue Lo, Hi; Lo = getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, N, getVectorIdxConstant(0, DL)); + // For scalable vectors it is safe to use LoVT.getVectorMinNumElements() + // (rather than having to use ElementCount), because EXTRACT_SUBVECTOR scales + // IDX with the runtime scaling factor of the result vector type. For + // fixed-width result vectors, that runtime scaling factor is 1. Hi = getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, N, - getVectorIdxConstant(LoVT.getVectorNumElements(), DL)); + getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL)); return std::make_pair(Lo, Hi); } From eb6b7c5d4fd4aeaf92d0ad560e0c078a95d66902 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Fri, 10 Jul 2020 00:53:15 +0300 Subject: [PATCH 07/10] [MLIR][SPIRVToLLVM] Conversion of SPIR-V struct type without offset This patch introduces type conversion for SPIR-V structs. Since handling offset case requires thorough testing, it was left out for now. Hence, only structs with no offset are currently supported. Also, structs containing member decorations cannot be translated. Reviewed By: antiagainst Differential Revision: https://reviews.llvm.org/D83403 --- .../SPIRVToLLVM/ConvertSPIRVToLLVM.cpp | 25 +++++++++++++++++++ .../spirv-types-to-llvm.invalid.mlir | 21 ++++++++++++++++ .../SPIRVToLLVM/spirv-types-to-llvm.mlir | 10 ++++++++ 3 files changed, 56 insertions(+) diff --git a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp index 7755656ea3b861..5820d9022ae1fc 100644 --- a/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp +++ b/mlir/lib/Conversion/SPIRVToLLVM/ConvertSPIRVToLLVM.cpp @@ -165,6 +165,17 @@ static Value processCountOrOffset(Location loc, Value value, Type srcType, return optionallyTruncateOrExtend(loc, broadcasted, dstType, rewriter); } +/// Converts SPIR-V struct with no offset to packed LLVM struct. +static Type convertStructTypePacked(spirv::StructType type, + LLVMTypeConverter &converter) { + auto elementsVector = llvm::to_vector<8>( + llvm::map_range(type.getElementTypes(), [&](Type elementType) { + return converter.convertType(elementType).cast(); + })); + return LLVM::LLVMType::getStructTy(converter.getDialect(), elementsVector, + /*isPacked=*/true); +} + //===----------------------------------------------------------------------===// // Type conversion //===----------------------------------------------------------------------===// @@ -202,6 +213,17 @@ static Optional convertRuntimeArrayType(spirv::RuntimeArrayType type, return LLVM::LLVMType::getArrayTy(elementType, 0); } +/// Converts SPIR-V struct to LLVM struct. There is no support of structs with +/// member decorations or with offset. +static Optional convertStructType(spirv::StructType type, + LLVMTypeConverter &converter) { + SmallVector memberDecorations; + type.getMemberDecorations(memberDecorations); + if (type.hasOffset() || !memberDecorations.empty()) + return llvm::None; + return convertStructTypePacked(type, converter); +} + //===----------------------------------------------------------------------===// // Operation conversion //===----------------------------------------------------------------------===// @@ -711,6 +733,9 @@ void mlir::populateSPIRVToLLVMTypeConversion(LLVMTypeConverter &typeConverter) { typeConverter.addConversion([&](spirv::RuntimeArrayType type) { return convertRuntimeArrayType(type, typeConverter); }); + typeConverter.addConversion([&](spirv::StructType type) { + return convertStructType(type, typeConverter); + }); } void mlir::populateSPIRVToLLVMConversionPatterns( diff --git a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir index 8115b973507bd7..96fb9f44af5783 100644 --- a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir +++ b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.invalid.mlir @@ -4,3 +4,24 @@ spv.func @array_with_stride(%arg: !spv.array<4 x f32, stride=4>) -> () "None" { spv.Return } + +// ----- + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @struct_with_offset1(%arg: !spv.struct) -> () "None" { + spv.Return +} + +// ----- + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @struct_with_offset2(%arg: !spv.struct) -> () "None" { + spv.Return +} + +// ----- + +// expected-error@+1 {{failed to legalize operation 'spv.func' that was explicitly marked illegal}} +spv.func @struct_with_decorations(%arg: !spv.struct) -> () "None" { + spv.Return +} diff --git a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir index d2bfdcd4c33dc9..466f8ad4a9eacc 100644 --- a/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir +++ b/mlir/test/Conversion/SPIRVToLLVM/spirv-types-to-llvm.mlir @@ -26,3 +26,13 @@ func @runtime_array_vector(!spv.rtarray< vector<4xf32> >) -> () // CHECK-LABEL: @runtime_array_scalar(!llvm<"[0 x float]">) func @runtime_array_scalar(!spv.rtarray) -> () + +//===----------------------------------------------------------------------===// +// Struct type +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @struct(!llvm<"<{ double }>">) +func @struct(!spv.struct) -> () + +// CHECK-LABEL: @struct_nested(!llvm<"<{ i32, <{ i64, i32 }> }>">) +func @struct_nested(!spv.struct>) From 043eaa9a4a0808fe4e82b2ef1823ccafa491c065 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 10 Jul 2020 00:18:59 -0700 Subject: [PATCH 08/10] [WebAssembly][NFC] Simplify vector shift lowering and add tests This patch builds on 0d7286a652 by simplifying the code for detecting splat values and adding new tests demonstrating the lowering of splatted absolute value shift amounts, which are common in code generated by Halide. The lowering is very bad right now, but subsequent patches will improve it considerably. The tests will be useful for evaluating the improvements in those patches. Reviewed By: aheejin Differential Revision: https://reviews.llvm.org/D83493 --- .../WebAssembly/WebAssemblyISelLowering.cpp | 13 ++-- .../WebAssembly/simd-shift-complex-splats.ll | 76 +++++++++++++++++++ 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 3f4ebd5015953c..a9b9eceb41304b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -1677,12 +1677,12 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op, // Only manually lower vector shifts assert(Op.getSimpleValueType().isVector()); - auto ShiftVal = Op.getOperand(1); - if (!DAG.isSplatValue(ShiftVal, /*AllowUndefs=*/true)) + auto ShiftVal = DAG.getSplatValue(Op.getOperand(1)); + if (!ShiftVal) return unrollVectorShift(Op, DAG); - auto SplatVal = DAG.getSplatValue(ShiftVal); - assert(SplatVal != SDValue()); + // Use anyext because none of the high bits can affect the shift + ShiftVal = DAG.getAnyExtOrTrunc(ShiftVal, DL, MVT::i32); unsigned Opcode; switch (Op.getOpcode()) { @@ -1699,10 +1699,7 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op, llvm_unreachable("unexpected opcode"); } - // Use anyext because none of the high bits can affect the shift - auto ScalarShift = DAG.getAnyExtOrTrunc(SplatVal, DL, MVT::i32); - return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), - ScalarShift); + return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal); } //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/WebAssembly/simd-shift-complex-splats.ll b/llvm/test/CodeGen/WebAssembly/simd-shift-complex-splats.ll index ded430f8954582..2473f0b27b7e8c 100644 --- a/llvm/test/CodeGen/WebAssembly/simd-shift-complex-splats.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-shift-complex-splats.ll @@ -25,3 +25,79 @@ define <16 x i8> @shl_add(<16 x i8> %v, i8 %a, i8 %b) { %r = shl <16 x i8> %v, %shift ret <16 x i8> %r } + +; CHECK-LABEL: shl_abs: +; CHECK-NEXT: .functype shl_abs (v128, i32) -> (v128) +; CHECK-NEXT: i8x16.extract_lane_u $push8=, $0, 0 +; CHECK-NEXT: i8x16.splat $push0=, $1 +; CHECK-NEXT: i8x16.abs $push98=, $pop0 +; CHECK-NEXT: local.tee $push97=, $2=, $pop98 +; CHECK-NEXT: i8x16.extract_lane_u $push6=, $pop97, 0 +; CHECK-NEXT: i32.const $push2=, 7 +; CHECK-NEXT: i32.and $push7=, $pop6, $pop2 +; CHECK-NEXT: i32.shl $push9=, $pop8, $pop7 +; CHECK-NEXT: i8x16.splat $push10=, $pop9 +; CHECK-NEXT: i8x16.extract_lane_u $push4=, $0, 1 +; CHECK-NEXT: i8x16.extract_lane_u $push1=, $2, 1 +; CHECK-NEXT: i32.const $push96=, 7 +; CHECK-NEXT: i32.and $push3=, $pop1, $pop96 +; CHECK-NEXT: i32.shl $push5=, $pop4, $pop3 +; CHECK-NEXT: i8x16.replace_lane $push11=, $pop10, 1, $pop5 +; ... +; CHECK: i8x16.extract_lane_u $push79=, $0, 15 +; CHECK-NEXT: i8x16.extract_lane_u $push77=, $2, 15 +; CHECK-NEXT: i32.const $push82=, 7 +; CHECK-NEXT: i32.and $push78=, $pop77, $pop82 +; CHECK-NEXT: i32.shl $push80=, $pop79, $pop78 +; CHECK-NEXT: i8x16.replace_lane $push81=, $pop76, 15, $pop80 +; CHECK-NEXT: return $pop81 +define <16 x i8> @shl_abs(<16 x i8> %v, i8 %a) { + %t1 = insertelement <16 x i8> undef, i8 %a, i32 0 + %va = shufflevector <16 x i8> %t1, <16 x i8> undef, <16 x i32> zeroinitializer + %nva = sub <16 x i8> zeroinitializer, %va + %c = icmp sgt <16 x i8> %va, zeroinitializer + %shift = select <16 x i1> %c, <16 x i8> %va, <16 x i8> %nva + %r = shl <16 x i8> %v, %shift + ret <16 x i8> %r +} + +; CHECK-LABEL: shl_abs_add: +; CHECK-NEXT: .functype shl_abs_add (v128, i32, i32) -> (v128) +; CHECK-NEXT: i8x16.extract_lane_u $push11=, $0, 0 +; CHECK-NEXT: i8x16.splat $push1=, $1 +; CHECK-NEXT: i8x16.splat $push0=, $2 +; CHECK-NEXT: i8x16.add $push2=, $pop1, $pop0 +; CHECK-NEXT: v8x16.shuffle $push3=, $pop2, $0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +; CHECK-NEXT: i8x16.abs $push101=, $pop3 +; CHECK-NEXT: local.tee $push100=, $3=, $pop101 +; CHECK-NEXT: i8x16.extract_lane_u $push9=, $pop100, 0 +; CHECK-NEXT: i32.const $push5=, 7 +; CHECK-NEXT: i32.and $push10=, $pop9, $pop5 +; CHECK-NEXT: i32.shl $push12=, $pop11, $pop10 +; CHECK-NEXT: i8x16.splat $push13=, $pop12 +; CHECK-NEXT: i8x16.extract_lane_u $push7=, $0, 1 +; CHECK-NEXT: i8x16.extract_lane_u $push4=, $3, 1 +; CHECK-NEXT: i32.const $push99=, 7 +; CHECK-NEXT: i32.and $push6=, $pop4, $pop99 +; CHECK-NEXT: i32.shl $push8=, $pop7, $pop6 +; CHECK-NEXT: i8x16.replace_lane $push14=, $pop13, 1, $pop8 +; ... +; CHECK: i8x16.extract_lane_u $push82=, $0, 15 +; CHECK-NEXT: i8x16.extract_lane_u $push80=, $3, 15 +; CHECK-NEXT: i32.const $push85=, 7 +; CHECK-NEXT: i32.and $push81=, $pop80, $pop85 +; CHECK-NEXT: i32.shl $push83=, $pop82, $pop81 +; CHECK-NEXT: i8x16.replace_lane $push84=, $pop79, 15, $pop83 +; CHECK-NEXT: return $pop84 +define <16 x i8> @shl_abs_add(<16 x i8> %v, i8 %a, i8 %b) { + %t1 = insertelement <16 x i8> undef, i8 %a, i32 0 + %va = shufflevector <16 x i8> %t1, <16 x i8> undef, <16 x i32> zeroinitializer + %t2 = insertelement <16 x i8> undef, i8 %b, i32 0 + %vb = shufflevector <16 x i8> %t2, <16 x i8> undef, <16 x i32> zeroinitializer + %vadd = add <16 x i8> %va, %vb + %nvadd = sub <16 x i8> zeroinitializer, %vadd + %c = icmp sgt <16 x i8> %vadd, zeroinitializer + %shift = select <16 x i1> %c, <16 x i8> %vadd, <16 x i8> %nvadd + %r = shl <16 x i8> %v, %shift + ret <16 x i8> %r +} From da731894a2fe45fd5bec9698f3206c1fdee2829a Mon Sep 17 00:00:00 2001 From: David Sherwood Date: Fri, 3 Jul 2020 13:27:21 +0100 Subject: [PATCH 09/10] [CodeGen] Replace calls to getVectorNumElements() in DAGTypeLegalizer::SetSplitVector In DAGTypeLegalizer::SetSplitVector I have changed calls in the assert from getVectorNumElements() to getVectorElementCount(), since this code path works for both fixed and scalable vectors. This fixes up one warning in the test: sve-sext-zext.ll Differential Revision: https://reviews.llvm.org/D83196 --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 2e1377c2c1735b..ae087d3bbd8cb7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -835,9 +835,9 @@ void DAGTypeLegalizer::GetSplitVector(SDValue Op, SDValue &Lo, void DAGTypeLegalizer::SetSplitVector(SDValue Op, SDValue Lo, SDValue Hi) { assert(Lo.getValueType().getVectorElementType() == - Op.getValueType().getVectorElementType() && - 2*Lo.getValueType().getVectorNumElements() == - Op.getValueType().getVectorNumElements() && + Op.getValueType().getVectorElementType() && + Lo.getValueType().getVectorElementCount() * 2 == + Op.getValueType().getVectorElementCount() && Hi.getValueType() == Lo.getValueType() && "Invalid type for split vector"); // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. From 7bf168390fd05460b1c0df3fa570758c6be718fd Mon Sep 17 00:00:00 2001 From: Diogo Sampaio Date: Fri, 10 Jul 2020 08:01:04 +0100 Subject: [PATCH 10/10] [BDCE] SExt -> ZExt when no sign bits is used and instruction has multiple uses Summary: This allows to convert any SExt to a ZExt when we know none of the extended bits are used, specially in cases where there are multiple uses of the value. Reviewers: dmgreen, eli.friedman, spatel, lebedev.ri, nikic Reviewed By: lebedev.ri, nikic Subscribers: hiraditya, dmgreen, craig.topper, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60413 --- llvm/lib/Transforms/Scalar/BDCE.cpp | 24 +++++++++++++++++++- llvm/test/Transforms/BDCE/sext_multi_uses.ll | 18 +++++++-------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp index c22ea0b8271e3e..767c7656dcfac7 100644 --- a/llvm/lib/Transforms/Scalar/BDCE.cpp +++ b/llvm/lib/Transforms/Scalar/BDCE.cpp @@ -9,7 +9,8 @@ // This file implements the Bit-Tracking Dead Code Elimination pass. Some // instructions (shifts, some ands, ors, etc.) kill some of their input bits. // We track these dead bits and remove instructions that compute only these -// dead bits. +// dead bits. We also simplify sext that generates unused extension bits, +// converting it to a zext. // //===----------------------------------------------------------------------===// @@ -19,6 +20,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/DemandedBits.h" #include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/InitializePasses.h" @@ -33,6 +35,8 @@ using namespace llvm; STATISTIC(NumRemoved, "Number of instructions removed (unused)"); STATISTIC(NumSimplified, "Number of instructions trivialized (dead bits)"); +STATISTIC(NumSExt2ZExt, + "Number of sign extension instructions converted to zero extension"); /// If an instruction is trivialized (dead), then the chain of users of that /// instruction may need to be cleared of assumptions that can no longer be @@ -109,6 +113,24 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) { continue; } + // Convert SExt into ZExt if none of the extension bits is required + if (SExtInst *SE = dyn_cast(&I)) { + APInt Demanded = DB.getDemandedBits(SE); + const uint32_t SrcBitSize = SE->getSrcTy()->getScalarSizeInBits(); + auto *const DstTy = SE->getDestTy(); + const uint32_t DestBitSize = DstTy->getScalarSizeInBits(); + if (Demanded.countLeadingZeros() >= (DestBitSize - SrcBitSize)) { + clearAssumptionsOfUsers(SE, DB); + IRBuilder<> Builder(SE); + I.replaceAllUsesWith( + Builder.CreateZExt(SE->getOperand(0), DstTy, SE->getName())); + Worklist.push_back(SE); + Changed = true; + NumSExt2ZExt++; + continue; + } + } + for (Use &U : I.operands()) { // DemandedBits only detects dead integer uses. if (!U->getType()->isIntOrIntVectorTy()) diff --git a/llvm/test/Transforms/BDCE/sext_multi_uses.ll b/llvm/test/Transforms/BDCE/sext_multi_uses.ll index 97709357919e9e..fa8549e0dec3b3 100644 --- a/llvm/test/Transforms/BDCE/sext_multi_uses.ll +++ b/llvm/test/Transforms/BDCE/sext_multi_uses.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -o - -bdce -S %s | FileCheck %s +; RUN: opt -S -bdce < %s | FileCheck %s define i32 @ZEXT_0(i16 %a) { ; CHECK-LABEL: @ZEXT_0( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], 65280 -; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8 +; CHECK-NEXT: [[EXT1:%.*]] = zext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT1]], 65280 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT1]], 8 ; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] ; CHECK-NEXT: ret i32 [[OR]] @@ -22,10 +22,10 @@ entry: define i32 @ZEXT_1(i16 %a) { ; CHECK-LABEL: @ZEXT_1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[EXT:%.*]] = sext i16 [[A:%.*]] to i32 -; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT]], 8 +; CHECK-NEXT: [[EXT1:%.*]] = zext i16 [[A:%.*]] to i32 +; CHECK-NEXT: [[LSR:%.*]] = lshr i32 [[EXT1]], 8 ; CHECK-NEXT: [[AND2:%.*]] = and i32 [[LSR]], 255 -; CHECK-NEXT: [[AND:%.*]] = or i32 [[EXT]], -65536 +; CHECK-NEXT: [[AND:%.*]] = or i32 [[EXT1]], -65536 ; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[AND2]] ; CHECK-NEXT: ret i32 [[OR]] ; @@ -99,8 +99,8 @@ entry: define i16 @clear_assumptions(i8 %x, i16 %y) { ; CHECK-LABEL: @clear_assumptions( -; CHECK-NEXT: [[EXT:%.*]] = sext i8 [[X:%.*]] to i16 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[EXT]], [[Y:%.*]] +; CHECK-NEXT: [[EXT1:%.*]] = zext i8 [[X:%.*]] to i16 +; CHECK-NEXT: [[ADD:%.*]] = add i16 [[EXT1]], [[Y:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i16 [[ADD]], 255 ; CHECK-NEXT: ret i16 [[AND]] ;