const Optional<unsigned> &NumElemsArg);
static Attribute getWithByValType(LLVMContext &Context, Type *Ty);
- static Attribute::AttrKind getAttrKindFromName(StringRef AttrName);
-
- static StringRef getNameFromAttrKind(Attribute::AttrKind AttrKind);
-
//===--------------------------------------------------------------------===//
// Attribute Accessors
//===--------------------------------------------------------------------===//
+++ /dev/null
-//===- KnowledgeRetention.h - utilities to preserve informations *- 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 contain tools to preserve informations. They should be used before
-// performing a transformation that may move and delete instructions as those
-// transformation may destroy or worsen information that can be derived from the
-// IR.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TRANSFORMS_UTILS_ASSUMEBUILDER_H
-#define LLVM_TRANSFORMS_UTILS_ASSUMEBUILDER_H
-
-#include "llvm/IR/Instruction.h"
-#include "llvm/IR/PassManager.h"
-
-namespace llvm {
-
-/// Build a call to llvm.assume to preserve informations that can be derived
-/// from the given instruction.
-/// If no information derived from \p I, this call returns null.
-/// The returned instruction is not inserted anywhere.
-CallInst *BuildAssumeFromInst(const Instruction *I, Module *M);
-inline CallInst *BuildAssumeFromInst(Instruction *I) {
- return BuildAssumeFromInst(I, I->getModule());
-}
-
-/// This pass will try to build an llvm.assume for every instruction in the
-/// function. Its main purpose is testing.
-struct AssumeBuilderPass : public PassInfoMixin<AssumeBuilderPass> {
- PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
-};
-
-} // namespace llvm
-
-#endif
return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg));
}
-Attribute::AttrKind Attribute::getAttrKindFromName(StringRef AttrName) {
- return StringSwitch<Attribute::AttrKind>(AttrName)
-#define GET_ATTR_NAMES
-#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
- .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
-#include "llvm/IR/Attributes.inc"
- .Default(Attribute::None);
-}
-
-StringRef Attribute::getNameFromAttrKind(Attribute::AttrKind AttrKind) {
- switch (AttrKind) {
-#define GET_ATTR_NAMES
-#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
- case AttrKind::ENUM_NAME: \
- return #DISPLAY_NAME;
-#include "llvm/IR/Attributes.inc"
- case AttrKind::None:
- return "none";
- default:
- llvm_unreachable("invalid Kind");
- }
-}
-
//===----------------------------------------------------------------------===//
// Attribute Accessor Methods
//===----------------------------------------------------------------------===//
return LLVMGetMDKindIDInContext(LLVMGetGlobalContext(), Name, SLen);
}
+static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {
+ return StringSwitch<Attribute::AttrKind>(AttrName)
+#define GET_ATTR_NAMES
+#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \
+ .Case(#DISPLAY_NAME, Attribute::ENUM_NAME)
+#include "llvm/IR/Attributes.inc"
+ .Default(Attribute::None);
+}
+
unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen) {
- return Attribute::getAttrKindFromName(StringRef(Name, SLen));
+ return getAttrKindFromName(StringRef(Name, SLen));
}
unsigned LLVMGetLastEnumAttributeKind(void) {
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/InjectTLIMappings.h"
-#include "llvm/Transforms/Utils/KnowledgeRetention.h"
#include "llvm/Transforms/Utils/LCSSA.h"
#include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
#include "llvm/Transforms/Utils/LoopSimplify.h"
FUNCTION_PASS("adce", ADCEPass())
FUNCTION_PASS("add-discriminators", AddDiscriminatorsPass())
FUNCTION_PASS("aggressive-instcombine", AggressiveInstCombinePass())
-FUNCTION_PASS("assume-builder", AssumeBuilderPass())
FUNCTION_PASS("alignment-from-assumptions", AlignmentFromAssumptionsPass())
FUNCTION_PASS("bdce", BDCEPass())
FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
InjectTLIMappings.cpp
InstructionNamer.cpp
IntegerDivision.cpp
- KnowledgeRetention.cpp
LCSSA.cpp
LibCallsShrinkWrap.cpp
Local.cpp
+++ /dev/null
-//===- KnowledgeRetention.h - utilities to preserve informations *- 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 "llvm/Transforms/Utils/KnowledgeRetention.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/IR/InstIterator.h"
-#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Support/CommandLine.h"
-
-using namespace llvm;
-
-namespace {
-
-cl::opt<bool> ShouldPreserveAllAttributes(
- "assume-preserve-all", cl::init(false), cl::Hidden,
- cl::desc("enable preservation of all attrbitues. even those that are "
- "unlikely to be usefull"));
-
-struct AssumedKnowledge {
- const char *Name;
- Value *Argument;
- enum {
- None,
- Empty,
- Tombstone,
- };
- /// Contain the argument and a flag if needed.
- llvm::PointerIntPair<Value *, 2> WasOn;
-};
-
-} // namespace
-
-namespace llvm {
-
-template <> struct DenseMapInfo<AssumedKnowledge> {
- static AssumedKnowledge getEmptyKey() {
- return {nullptr, nullptr, {nullptr, AssumedKnowledge::Empty}};
- }
- static AssumedKnowledge getTombstoneKey() {
- return {nullptr, nullptr, {nullptr, AssumedKnowledge::Tombstone}};
- }
- static unsigned getHashValue(const AssumedKnowledge &AK) {
- return hash_combine(AK.Name, AK.Argument, AK.WasOn.getPointer());
- }
- static bool isEqual(const AssumedKnowledge &LHS,
- const AssumedKnowledge &RHS) {
- return LHS.WasOn == RHS.WasOn && LHS.Name == RHS.Name &&
- LHS.Argument == RHS.Argument;
- }
-};
-
-} // namespace llvm
-
-namespace {
-
-/// Deterministically compare OperandBundleDef.
-/// The ordering is:
-/// - by the name of the attribute, (doesn't change)
-/// - then by the Value of the argument, (doesn't change)
-/// - lastly by the Name of the current Value it WasOn. (may change)
-/// This order is deterministic and allows looking for the right kind of
-/// attribute with binary search. However finding the right WasOn needs to be
-/// done via linear search because values can get remplaced.
-bool isLowerOpBundle(const OperandBundleDef &LHS, const OperandBundleDef &RHS) {
- auto getTuple = [](const OperandBundleDef &Op) {
- return std::make_tuple(
- Op.getTag(),
- Op.input_size() < 2
- ? 0
- : cast<ConstantInt>(*std::next(Op.input_begin()))->getZExtValue(),
- Op.input_size() < 1 ? StringRef("") : (*Op.input_begin())->getName());
- };
- return getTuple(LHS) < getTuple(RHS);
-}
-
-/// This class contain all knowledge that have been gather while building an
-/// llvm.assume and the function to manipulate it.
-struct AssumeBuilderState {
- Module *M;
-
- SmallDenseSet<AssumedKnowledge, 8> AssumedKnowledgeSet;
-
- AssumeBuilderState(Module *M) : M(M) {}
-
- void addAttribute(Attribute Attr, Value *WasOn) {
- StringRef Name;
- Value *AttrArg = nullptr;
- if (Attr.isStringAttribute())
- if (ShouldPreserveAllAttributes)
- Name = Attr.getKindAsString();
- else
- return;
- else
- Name = Attribute::getNameFromAttrKind(Attr.getKindAsEnum());
- if (Attr.isIntAttribute())
- AttrArg = ConstantInt::get(Type::getInt64Ty(M->getContext()),
- Attr.getValueAsInt());
- AssumedKnowledgeSet.insert(
- {Name.data(), AttrArg, {WasOn, AssumedKnowledge::None}});
- }
-
- void addCall(const CallBase *Call) {
- auto addAttrList = [&](AttributeList AttrList) {
- for (unsigned Idx = AttributeList::FirstArgIndex;
- Idx < AttrList.getNumAttrSets(); Idx++)
- for (Attribute Attr : AttrList.getAttributes(Idx))
- addAttribute(Attr, Call->getArgOperand(Idx - 1));
- if (ShouldPreserveAllAttributes)
- for (Attribute Attr : AttrList.getFnAttributes())
- addAttribute(Attr, nullptr);
- };
- addAttrList(Call->getAttributes());
- if (Function *Fn = Call->getCalledFunction())
- addAttrList(Fn->getAttributes());
- }
-
- CallInst *build() {
- if (AssumedKnowledgeSet.empty())
- return nullptr;
- Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume);
- LLVMContext &C = M->getContext();
- SmallVector<OperandBundleDef, 8> OpBundle;
- for (const AssumedKnowledge &Elem : AssumedKnowledgeSet) {
- SmallVector<Value *, 2> Args;
- if (Elem.WasOn.getPointer())
- Args.push_back(Elem.WasOn.getPointer());
- if (Elem.Argument)
- Args.push_back(Elem.Argument);
- OpBundle.push_back(OperandBundleDefT<Value *>(Elem.Name, Args));
- }
- llvm::sort(OpBundle, isLowerOpBundle);
- return CallInst::Create(
- FnAssume, ArrayRef<Value *>({ConstantInt::getTrue(C)}), OpBundle);
- }
-
- void addInstruction(const Instruction *I) {
- if (auto *Call = dyn_cast<CallBase>(I))
- addCall(Call);
- // TODO: Add support for the other Instructions.
- // TODO: Maybe we should look around and merge with other llvm.assume.
- }
-};
-
-} // namespace
-
-CallInst *llvm::BuildAssumeFromInst(const Instruction *I, Module *M) {
- AssumeBuilderState Builder(M);
- Builder.addInstruction(I);
- return Builder.build();
-}
-
-PreservedAnalyses AssumeBuilderPass::run(Function &F,
- FunctionAnalysisManager &AM) {
- for (Instruction &I : instructions(F))
- if (Instruction *Assume = BuildAssumeFromInst(&I))
- Assume->insertBefore(&I);
- return PreservedAnalyses::all();
-}
+++ /dev/null
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes='assume-builder' -S %s | FileCheck %s --check-prefixes=BASIC
-; RUN: opt -passes='assume-builder' --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL
-
-declare void @func(i32*, i32*)
-declare void @func_cold(i32*) cold
-declare void @func_strbool(i32*) "no-jump-tables"
-declare void @func_many(i32*) "no-jump-tables" nounwind "less-precise-fpmad" willreturn norecurse
-declare void @func_argattr(i32* align 8, i32* nonnull) nounwind
-
-define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
-; BASIC-LABEL: @test(
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P:%.*]], i64 16), "nonnull"(i32* [[P]]) ]
-; BASIC-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1:%.*]], i64 12), "nonnull"(i32* [[P]]) ]
-; BASIC-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ]
-; BASIC-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) #0
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12) ]
-; BASIC-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]])
-; BASIC-NEXT: call void @func(i32* [[P1]], i32* [[P]])
-; BASIC-NEXT: call void @func_strbool(i32* [[P1]])
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 8), "dereferenceable"(i32* [[P]], i64 16) ]
-; BASIC-NEXT: call void @func(i32* dereferenceable(16) [[P]], i32* dereferenceable(8) [[P]])
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
-; BASIC-NEXT: call void @func_many(i32* align 8 [[P1]])
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P2:%.*]], i64 8), "nonnull"(i32* [[P3:%.*]]) ]
-; BASIC-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "nonnull"(i32* [[P1]]) ]
-; BASIC-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
-; BASIC-NEXT: ret void
-;
-; ALL-LABEL: @test(
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P:%.*]], i64 16), "nonnull"(i32* [[P]]) ]
-; ALL-NEXT: call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1:%.*]], i64 12), "nonnull"(i32* [[P]]) ]
-; ALL-NEXT: call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(i32* [[P1]], i64 12) ]
-; ALL-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]]) #0
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(i32* [[P1]], i64 12) ]
-; ALL-NEXT: call void @func_cold(i32* dereferenceable(12) [[P1]])
-; ALL-NEXT: call void @func(i32* [[P1]], i32* [[P]])
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "no-jump-tables"() ]
-; ALL-NEXT: call void @func_strbool(i32* [[P1]])
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 8), "dereferenceable"(i32* [[P]], i64 16) ]
-; ALL-NEXT: call void @func(i32* dereferenceable(16) [[P]], i32* dereferenceable(8) [[P]])
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8), "less-precise-fpmad"(), "no-jump-tables"(), "norecurse"(), "nounwind"(), "willreturn"() ]
-; ALL-NEXT: call void @func_many(i32* align 8 [[P1]])
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[P2:%.*]], i64 8), "nonnull"(i32* [[P3:%.*]]), "nounwind"() ]
-; ALL-NEXT: call void @func_argattr(i32* [[P2]], i32* [[P3]])
-; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "nonnull"(i32* [[P1]]) ]
-; ALL-NEXT: call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
-; ALL-NEXT: ret void
-;
- call void @func(i32* nonnull dereferenceable(16) %P, i32* null)
- call void @func(i32* dereferenceable(12) %P1, i32* nonnull %P)
- call void @func_cold(i32* dereferenceable(12) %P1) cold
- call void @func_cold(i32* dereferenceable(12) %P1)
- call void @func(i32* %P1, i32* %P)
- call void @func_strbool(i32* %P1)
- call void @func(i32* dereferenceable(16) %P, i32* dereferenceable(8) %P)
- call void @func_many(i32* align 8 %P1)
- call void @func_argattr(i32* %P2, i32* %P3)
- call void @func(i32* nonnull %P1, i32* nonnull %P)
- ret void
-}