Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -818,7 +818,8 @@ CallGraphUpdater &CGUpdater, DenseSet *Allowed = nullptr) : Allocator(InfoCache.Allocator), Functions(Functions), - InfoCache(InfoCache), CGUpdater(CGUpdater), Allowed(Allowed) {} + InfoCache(InfoCache), CGUpdater(CGUpdater), Allowed(Allowed), + SeedingPeriod(true) {} ~Attributor(); @@ -891,6 +892,13 @@ // No matching attribute found, create one. // Use the static create method. auto &AA = AAType::createForPosition(IRP, *this); + + // If we are currenty seeding attributes, enforce seeding rules. + if (SeedingPeriod && !shouldSeedAttribute(AA)) { + AA.getState().indicatePessimisticFixpoint(); + return AA; + } + registerAA(AA); // For now we ignore naked and optnone functions. @@ -918,8 +926,15 @@ return AA; } + // Allow seeded attributes to declare dependencies. + // Remember the seeding state. + bool OldSeedingPeriod = SeedingPeriod; + SeedingPeriod = false; + updateAA(AA); + SeedingPeriod = OldSeedingPeriod; + if (TrackDependence && AA.getState().isValidState()) recordDependence(AA, const_cast(*QueryingAA), DepClass); @@ -1345,6 +1360,10 @@ ChangeStatus rewriteFunctionSignatures(SmallPtrSetImpl &ModifiedFns); + /// Check if the Attribute \p AA should be seeded. + /// See getOrCreateAAFor. + bool shouldSeedAttribute(AbstractAttribute &AA); + /// The set of all abstract attributes. ///{ using AAVector = SmallVector; @@ -1410,6 +1429,9 @@ /// Invoke instructions with at least a single dead successor block. SmallVector InvokeWithDeadSuccessor; + /// Before the run function gets called. + bool SeedingPeriod; + /// Functions, blocks, and instructions we delete after manifest is done. /// ///{ Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -27,6 +27,7 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" +#include #include using namespace llvm; @@ -78,6 +79,12 @@ "wrappers for non-exact definitions."), cl::init(false)); +static cl::list + SeedAllowList("attributor-seed-allow-list", cl::Hidden, + cl::desc("Comma seperated list of attrbute names that are " + "allowed to be seeded."), + cl::ZeroOrMore, cl::CommaSeparated); + /// Logic operators for the change status enum class. /// ///{ @@ -1250,6 +1257,7 @@ } ChangeStatus Attributor::run() { + SeedingPeriod = false; runTillFixpoint(); ChangeStatus ManifestChange = manifestAttributes(); ChangeStatus CleanupChange = cleanupIR(); @@ -1446,6 +1454,12 @@ return true; } +bool Attributor::shouldSeedAttribute(AbstractAttribute &AA) { + if (SeedAllowList.size() == 0) + return true; + return std::count(SeedAllowList.begin(), SeedAllowList.end(), AA.getName()); +} + ChangeStatus Attributor::rewriteFunctionSignatures( SmallPtrSetImpl &ModifiedFns) { ChangeStatus Changed = ChangeStatus::UNCHANGED; Index: llvm/test/Transforms/Attributor/allow_list.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Attributor/allow_list.ll @@ -0,0 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -S -passes=attributor --attributor-seed-allow-list asd < %s | FileCheck %s --check-prefixes=CHECK_DISABLED +; RUN: opt -S -passes=attributor --attributor-seed-allow-list AAValueSimplify < %s | FileCheck %s --check-prefixes=CHECK_ENABLED + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; Function Attrs: nounwind uwtable +define internal i32 @range_test(i32 %a) #0 { +; CHECK_DISABLED-LABEL: define {{[^@]+}}@range_test +; CHECK_DISABLED-SAME: (i32 [[A:%.*]]) +; CHECK_DISABLED-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], 100 +; CHECK_DISABLED-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i32 +; CHECK_DISABLED-NEXT: ret i32 [[TMP2]] +; + %1 = icmp sgt i32 %a, 100 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +; Function Attrs: nounwind uwtable +define i32 @range_use() #0 { +; CHECK_DISABLED-LABEL: define {{[^@]+}}@range_use() +; CHECK_DISABLED-NEXT: [[TMP1:%.*]] = call i32 @range_test(i32 123) +; CHECK_DISABLED-NEXT: ret i32 [[TMP1]] +; +; CHECK_ENABLED-LABEL: define {{[^@]+}}@range_use() +; CHECK_ENABLED-NEXT: ret i32 1 +; + %1 = call i32 @range_test(i32 123) + ret i32 %1 +} + +attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.ident = !{!0} + +!0 = !{!"clang version 3.8.1-24 (tags/RELEASE_381/final)"}