[llvm] r366335 - [Attributor] Deduce "willreturn" function attribute
Hideto Ueno via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 17 08:15:43 PDT 2019
Author: uenoku
Date: Wed Jul 17 08:15:43 2019
New Revision: 366335
URL: http://llvm.org/viewvc/llvm-project?rev=366335&view=rev
Log:
[Attributor] Deduce "willreturn" function attribute
Summary:
Deduce the "willreturn" attribute for functions.
For now, intrinsics are not willreturn. More annotation will be done in another patch.
Reviewers: jdoerfert
Subscribers: jvesely, nhaehnle, nicholas, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D63046
Modified:
llvm/trunk/include/llvm/IR/Intrinsics.td
llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
llvm/trunk/lib/Transforms/IPO/Attributor.cpp
llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll
llvm/trunk/test/Transforms/FunctionAttrs/willreturn.ll
llvm/trunk/utils/TableGen/CodeGenIntrinsics.h
llvm/trunk/utils/TableGen/CodeGenTarget.cpp
llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
+++ llvm/trunk/include/llvm/IR/Intrinsics.td Wed Jul 17 08:15:43 2019
@@ -94,6 +94,8 @@ class ReadNone<int argNo> : IntrinsicPro
def IntrNoReturn : IntrinsicProperty;
+def IntrWillReturn : IntrinsicProperty;
+
// IntrCold - Calls to this intrinsic are cold.
// Parallels the cold attribute on LLVM IR functions.
def IntrCold : IntrinsicProperty;
Modified: llvm/trunk/include/llvm/Transforms/IPO/Attributor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/Attributor.h?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/IPO/Attributor.h (original)
+++ llvm/trunk/include/llvm/Transforms/IPO/Attributor.h Wed Jul 17 08:15:43 2019
@@ -740,6 +740,50 @@ struct AANonNull : public AbstractAttrib
/// The identifier used by the Attributor for this class of attributes.
static constexpr Attribute::AttrKind ID = Attribute::NonNull;
};
+
+/// An abstract attribute for norecurse.
+struct AANoRecurse : public AbstractAttribute {
+
+ /// See AbstractAttribute::AbstractAttribute(...).
+ AANoRecurse(Value &V, InformationCache &InfoCache)
+ : AbstractAttribute(V, InfoCache) {}
+
+ /// See AbstractAttribute::getAttrKind()
+ virtual Attribute::AttrKind getAttrKind() const override {
+ return Attribute::NoRecurse;
+ }
+
+ /// Return true if "norecurse" is known.
+ virtual bool isKnownNoRecurse() const = 0;
+
+ /// Return true if "norecurse" is assumed.
+ virtual bool isAssumedNoRecurse() const = 0;
+
+ /// The identifier used by the Attributor for this class of attributes.
+ static constexpr Attribute::AttrKind ID = Attribute::NoRecurse;
+};
+
+/// An abstract attribute for willreturn.
+struct AAWillReturn : public AbstractAttribute {
+
+ /// See AbstractAttribute::AbstractAttribute(...).
+ AAWillReturn(Value &V, InformationCache &InfoCache)
+ : AbstractAttribute(V, InfoCache) {}
+
+ /// See AbstractAttribute::getAttrKind()
+ virtual Attribute::AttrKind getAttrKind() const override {
+ return Attribute::WillReturn;
+ }
+
+ /// Return true if "willreturn" is known.
+ virtual bool isKnownWillReturn() const = 0;
+
+ /// Return true if "willreturn" is assumed.
+ virtual bool isAssumedWillReturn() const = 0;
+
+ /// The identifier used by the Attributor for this class of attributes.
+ static constexpr Attribute::AttrKind ID = Attribute::WillReturn;
+};
} // end namespace llvm
#endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
Modified: llvm/trunk/lib/Transforms/IPO/Attributor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Attributor.cpp?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Attributor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp Wed Jul 17 08:15:43 2019
@@ -15,6 +15,7 @@
#include "llvm/Transforms/IPO/Attributor.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -23,6 +24,7 @@
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/CommandLine.h"
@@ -56,6 +58,7 @@ STATISTIC(NumFnReturnedNonNull,
"Number of function return values marked nonnull");
STATISTIC(NumFnArgumentNonNull, "Number of function arguments marked nonnull");
STATISTIC(NumCSArgumentNonNull, "Number of call site arguments marked nonnull");
+STATISTIC(NumFnWillReturn, "Number of functions marked willreturn");
// TODO: Determine a good default value.
//
@@ -128,6 +131,9 @@ static void bookkeeping(AbstractAttribut
break;
}
break;
+ case Attribute::WillReturn:
+ NumFnWillReturn++;
+ break;
default:
return;
}
@@ -1194,6 +1200,117 @@ ChangeStatus AANonNullCallSiteArgument::
return ChangeStatus::UNCHANGED;
}
+/// ------------------------ Will-Return Attributes ----------------------------
+
+struct AAWillReturnImpl : public AAWillReturn, BooleanState {
+
+ /// See AbstractAttribute::AbstractAttribute(...).
+ AAWillReturnImpl(Function &F, InformationCache &InfoCache)
+ : AAWillReturn(F, InfoCache) {}
+
+ /// See AAWillReturn::isKnownWillReturn().
+ bool isKnownWillReturn() const override { return getKnown(); }
+
+ /// See AAWillReturn::isAssumedWillReturn().
+ bool isAssumedWillReturn() const override { return getAssumed(); }
+
+ /// See AbstractAttribute::getState(...).
+ AbstractState &getState() override { return *this; }
+
+ /// See AbstractAttribute::getState(...).
+ const AbstractState &getState() const override { return *this; }
+
+ /// See AbstractAttribute::getAsStr()
+ const std::string getAsStr() const override {
+ return getAssumed() ? "willreturn" : "may-noreturn";
+ }
+};
+
+struct AAWillReturnFunction final : AAWillReturnImpl {
+
+ /// See AbstractAttribute::AbstractAttribute(...).
+ AAWillReturnFunction(Function &F, InformationCache &InfoCache)
+ : AAWillReturnImpl(F, InfoCache) {}
+
+ /// See AbstractAttribute::getManifestPosition().
+ ManifestPosition getManifestPosition() const override {
+ return MP_FUNCTION;
+ }
+
+ /// See AbstractAttribute::initialize(...).
+ void initialize(Attributor &A) override;
+
+ /// See AbstractAttribute::updateImpl(...).
+ ChangeStatus updateImpl(Attributor &A) override;
+};
+
+// Helper function that checks whether a function has any cycle.
+// TODO: Replace with more efficent code
+bool containsCycle(Function &F) {
+ SmallPtrSet<BasicBlock *, 32> Visited;
+
+ // Traverse BB by dfs and check whether successor is already visited.
+ for (BasicBlock *BB : depth_first(&F)) {
+ Visited.insert(BB);
+ for (auto *SuccBB : successors(BB)) {
+ if (Visited.count(SuccBB))
+ return true;
+ }
+ }
+ return false;
+}
+
+// Helper function that checks the function have a loop which might become an
+// endless loop
+// FIXME: Any cycle is regarded as endless loop for now.
+// We have to allow some patterns.
+bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
+
+void AAWillReturnFunction::initialize(Attributor &A) {
+ Function &F = getAnchorScope();
+
+ if (containsPossiblyEndlessLoop(F))
+ indicatePessimisticFixpoint();
+}
+
+ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A) {
+ Function &F = getAnchorScope();
+
+ // The map from instruction opcodes to those instructions in the function.
+ auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
+
+ for (unsigned Opcode :
+ {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
+ (unsigned)Instruction::Call}) {
+ for (Instruction *I : OpcodeInstMap[Opcode]) {
+ auto ICS = ImmutableCallSite(I);
+
+ if (ICS.hasFnAttr(Attribute::WillReturn))
+ continue;
+
+ auto *WillReturnAA = A.getAAFor<AAWillReturn>(*this, *I);
+ if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn()) {
+ indicatePessimisticFixpoint();
+ return ChangeStatus::CHANGED;
+ }
+
+ auto *NoRecurseAA = A.getAAFor<AANoRecurse>(*this, *I);
+
+ // FIXME: (i) Prohibit any recursion for now.
+ // (ii) AANoRecurse isn't implemented yet so currently any call is
+ // regarded as having recursion.
+ // Code below should be
+ // if ((!NoRecurseAA || !NoRecurseAA->isAssumedNoRecurse()) &&
+ if (!NoRecurseAA && !ICS.hasFnAttr(Attribute::NoRecurse)) {
+ indicatePessimisticFixpoint();
+ return ChangeStatus::CHANGED;
+ }
+ }
+ }
+
+ return ChangeStatus::UNCHANGED;
+}
+
/// ----------------------------------------------------------------------------
/// Attributor
/// ----------------------------------------------------------------------------
@@ -1403,6 +1520,9 @@ void Attributor::identifyDefaultAbstract
registerAA(*new AANonNullArgument(Arg, InfoCache));
}
+ // Every function might be "will-return".
+ registerAA(*new AAWillReturnFunction(F, InfoCache));
+
// Walk all instructions to find more attribute opportunities and also
// interesting instructions that might be queried by abstract attributes
// during their initialization or update.
Modified: llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/arg_returned.ll Wed Jul 17 08:15:43 2019
@@ -744,7 +744,7 @@ unreachableblock2:
attributes #0 = { noinline nounwind uwtable }
; BOTH-NOT: attributes #
-; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable }
+; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn }
; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readnone uwtable }
; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readonly uwtable }
; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind uwtable }
Modified: llvm/trunk/test/Transforms/FunctionAttrs/willreturn.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/FunctionAttrs/willreturn.ll?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/FunctionAttrs/willreturn.ll (original)
+++ llvm/trunk/test/Transforms/FunctionAttrs/willreturn.ll Wed Jul 17 08:15:43 2019
@@ -1,4 +1,6 @@
; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
+; RUN: opt -attributor --attributor-disable=false -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -7,9 +9,10 @@ target datalayout = "e-m:e-i64:64-f80:12
; TEST 1 (positive case)
-; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
; FNATTR-NEXT: define void @only_return()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable willreturn
+; ATTRIBUTOR-NEXT: define void @only_return()
define void @only_return() #0 {
ret void
}
@@ -22,9 +25,11 @@ define void @only_return() #0 {
; return n<=1? n : fib(n-1) + fib(n-2);
; }
-; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline nounwind readnone uwtable
; FNATTR-NEXT: define i32 @fib(i32)
+; FIXME: missing willreturn
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define i32 @fib(i32) local_unnamed_addr
define i32 @fib(i32) local_unnamed_addr #0 {
%2 = icmp slt i32 %0, 2
br i1 %2, label %9, label %3
@@ -54,6 +59,9 @@ define i32 @fib(i32) local_unnamed_addr
; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define i32 @fact_maybe_not_halt(i32) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define i32 @fact_maybe_not_halt(i32) local_unnamed_addr
define i32 @fact_maybe_not_halt(i32) local_unnamed_addr #0 {
%2 = icmp eq i32 %0, 0
br i1 %2, label %11, label %3
@@ -87,6 +95,8 @@ define i32 @fact_maybe_not_halt(i32) loc
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
; FNATTR-NEXT: define i32 @fact_loop(i32)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define i32 @fact_loop(i32) local_unnamed_addr
define i32 @fact_loop(i32) local_unnamed_addr #0 {
%2 = icmp slt i32 %0, 1
br i1 %2, label %3, label %5
@@ -116,6 +126,9 @@ define i32 @fact_loop(i32) local_unnamed
; FNATTR: Function Attrs: noinline nounwind readnone uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @mutual_recursion1()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @mutual_recursion1()
define void @mutual_recursion1() #0 {
call void @mutual_recursion2()
ret void
@@ -125,6 +138,9 @@ define void @mutual_recursion1() #0 {
; FNATTR: Function Attrs: noinline nounwind readnone uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @mutual_recursion2()
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
define void @mutual_recursion2() #0 {
call void @mutual_recursion1()
ret void
@@ -135,11 +151,16 @@ define void @mutual_recursion2() #0 {
; call exit/abort (has noreturn attribute)
; FNATTR: Function Attrs: noreturn
; FNATTR-NEXT: declare void @exit(i32) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noreturn
+; ATTRIBUTOR-NEXT: declare void @exit(i32) local_unnamed_add
declare void @exit(i32) local_unnamed_addr noreturn
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @only_exit()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @only_exit() local_unnamed_addr
define void @only_exit() local_unnamed_addr #0 {
tail call void @exit(i32 0)
unreachable
@@ -158,6 +179,9 @@ define void @only_exit() local_unnamed_a
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @conditional_exit(i32, i32* nocapture readonly) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @conditional_exit(i32, i32* nocapture readonly) local_unnamed_addr
define void @conditional_exit(i32, i32* nocapture readonly) local_unnamed_addr #0 {
%3 = icmp eq i32 %0, 0
br i1 %3, label %5, label %4
@@ -181,13 +205,18 @@ define void @conditional_exit(i32, i32*
; TEST 6 (positive case)
; Call intrinsic function
+; FIXME: missing willreturn
; FNATTRS: Function Attrs: noinline readnone speculatable
; FNATTRS-NEXT: declare float @llvm.floor.f32(float)
+; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
+; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
declare float @llvm.floor.f32(float)
-; FIXME: missing willreturn
; FNATTRS: Function Attrs: noinline nounwind uwtable
; FNATTRS-NEXT: define void @call_floor(float %a)
+; FIXME: missing willreturn
+; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
define void @call_floor(float %a) #0 {
tail call float @llvm.floor.f32(float %a)
ret void
@@ -200,11 +229,17 @@ define void @call_floor(float %a) #0 {
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: declare void @maybe_noreturn()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: declare void @maybe_noreturn()
declare void @maybe_noreturn() #0
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @call_maybe_noreturn()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @call_maybe_noreturn()
define void @call_maybe_noreturn() #0 {
tail call void @maybe_noreturn()
ret void
@@ -216,11 +251,15 @@ define void @call_maybe_noreturn() #0 {
; FNATTR: Function Attrs: willreturn
; FNATTR-NEXT: declare void @will_return()
+; ATTRIBUTOR: Function Attrs: willreturn
+; ATTRIBUTOR-NEXT: declare void @will_return()
declare void @will_return() willreturn
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NEXT: define void @f1()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @f1()
define void @f1() #0 {
tail call void @will_return()
ret void
@@ -229,6 +268,9 @@ define void @f1() #0 {
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NEXT: define void @f2()
+; FIXME: missing willreturn
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @f2()
define void @f2() #0 {
tail call void @f1()
ret void
@@ -241,6 +283,9 @@ define void @f2() #0 {
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @call_will_return_but_has_loop()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @call_will_return_but_has_loop()
define void @call_will_return_but_has_loop() #0 {
br label %label1
label1:
@@ -256,14 +301,17 @@ label2:
; FNATTR: Function Attrs: noinline uwtable willreturn
; FNATTR-NEXT: declare i1 @maybe_raise_exception()
+; ATTRIBUTOR: Function Attrs: noinline uwtable willreturn
+; ATTRIBUTOR-NEXT: declare i1 @maybe_raise_exception()
declare i1 @maybe_raise_exception() #1 willreturn
-; FIXME: missing willreturn
; FNATTR: Function Attrs: nounwind
; FNATTR-NEXT: define void @invoke_test()
+; ATTRIBUTOR: Function Attrs: nounwind willreturn
+; ATTRIBUTOR-NEXT: define void @invoke_test()
define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
invoke i1 @maybe_raise_exception()
- to label %N unwind label %F
+ to label %N unwind label %F
N:
ret void
F:
@@ -288,6 +336,8 @@ declare i32 @__gxx_personality_v0(...)
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
; FNATTR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly)
define i32 @loop_constant_trip_count(i32* nocapture readonly) #0 {
br label %3
@@ -319,6 +369,9 @@ define i32 @loop_constant_trip_count(i32
; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define i32 @loop_trip_count_unbound(i32, i32, i32* nocapture readonly, i32) local_unnamed_addr
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define i32 @loop_trip_count_unbound(i32, i32, i32* nocapture readonly, i32) local_unnamed_addr
define i32 @loop_trip_count_unbound(i32, i32, i32* nocapture readonly, i32) local_unnamed_addr #0 {
%5 = icmp eq i32 %0, %1
br i1 %5, label %6, label %8
@@ -354,6 +407,8 @@ define i32 @loop_trip_count_unbound(i32,
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
; FNATTR-NEXT: define i32 @loop_trip_dec(i32, i32* nocapture readonly)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
+; ATTRIBUTOR-NEXT: define i32 @loop_trip_dec(i32, i32* nocapture readonly) local_unnamed_addr
define i32 @loop_trip_dec(i32, i32* nocapture readonly) local_unnamed_addr #0 {
%3 = icmp sgt i32 %0, -1
@@ -381,9 +436,10 @@ define i32 @loop_trip_dec(i32, i32* noca
; TEST 14 (positive case)
; multiple return
-; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
; FNATTR-NEXT: define i32 @multiple_return(i32 %a)
+; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable willreturn
+; ATTRIBUTOR-NEXT: define i32 @multiple_return(i32 %a)
define i32 @multiple_return(i32 %a) #0 {
%b = icmp eq i32 %a, 0
br i1 %b, label %t, label %f
@@ -401,6 +457,8 @@ f:
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NEXT: define void @unreachable_exit_positive1()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: define void @unreachable_exit_positive1()
define void @unreachable_exit_positive1() #0 {
tail call void @will_return()
ret void
@@ -413,6 +471,8 @@ unreachable_label:
; FIXME: missing willreturn
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NEXT: define i32 @unreachable_exit_positive2(i32)
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NEXT: define i32 @unreachable_exit_positive2(i32)
define i32 @unreachable_exit_positive2(i32) local_unnamed_addr #0 {
%2 = icmp slt i32 %0, 1
br i1 %2, label %3, label %5
@@ -440,6 +500,9 @@ unreachable_label:
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @unreachable_exit_negative1()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative1()
define void @unreachable_exit_negative1() #0 {
tail call void @exit(i32 0)
ret void
@@ -452,6 +515,9 @@ unreachable_label:
; FNATTR: Function Attrs: noinline nounwind uwtable
; FNATTR-NOT: willreturn
; FNATTR-NEXT: define void @unreachable_exit_negative2()
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative2()
define void @unreachable_exit_negative2() #0 {
br label %L1
@@ -465,6 +531,23 @@ unreachable_label:
unreachable
}
+; FNATTR: Function Attrs: noreturn nounwind
+; FNATTR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
+; ATTRIBUTOR: Function Attrs: noreturn nounwind
+; ATTRIBUTOR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
+declare void @llvm.eh.sjlj.longjmp(i8*)
+
+; FNATTR: Function Attrs: noinline nounwind uwtable
+; FNATTR-NOT: willreturn
+; FNATTR-NEXT: define void @call_longjmp(i8* nocapture readnone) local_unnamed_addr #3 {
+; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
+; ATTRIBUTOR-NOT: willreturn
+; ATTRIBUTOR-NEXT: define void @call_longjmp(i8* nocapture readnone) local_unnamed_addr
+define void @call_longjmp(i8* nocapture readnone) local_unnamed_addr #0 {
+ tail call void @llvm.eh.sjlj.longjmp(i8* %0)
+ ret void
+}
+
attributes #0 = { nounwind uwtable noinline }
attributes #1 = { uwtable noinline }
Modified: llvm/trunk/utils/TableGen/CodeGenIntrinsics.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenIntrinsics.h?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenIntrinsics.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenIntrinsics.h Wed Jul 17 08:15:43 2019
@@ -123,6 +123,9 @@ struct CodeGenIntrinsic {
/// True if the intrinsic is no-return.
bool isNoReturn;
+ /// True if the intrinsic is will-return.
+ bool isWillReturn;
+
/// True if the intrinsic is cold.
bool isCold;
Modified: llvm/trunk/utils/TableGen/CodeGenTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenTarget.cpp?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenTarget.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenTarget.cpp Wed Jul 17 08:15:43 2019
@@ -557,6 +557,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Recor
isCommutative = false;
canThrow = false;
isNoReturn = false;
+ isWillReturn = false;
isCold = false;
isNoDuplicate = false;
isConvergent = false;
@@ -721,6 +722,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Recor
isConvergent = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
+ else if (Property->getName() == "IntrWillReturn")
+ isWillReturn = true;
else if (Property->getName() == "IntrCold")
isCold = true;
else if (Property->getName() == "IntrSpeculatable")
Modified: llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp?rev=366335&r1=366334&r2=366335&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp Wed Jul 17 08:15:43 2019
@@ -545,6 +545,9 @@ struct AttributeComparator {
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
+ if (L->isWillReturn != R->isWillReturn)
+ return R->isWillReturn;
+
if (L->isCold != R->isCold)
return R->isCold;
@@ -686,8 +689,9 @@ void IntrinsicEmitter::EmitAttributes(co
if (!intrinsic.canThrow ||
(intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) ||
- intrinsic.isNoReturn || intrinsic.isCold || intrinsic.isNoDuplicate ||
- intrinsic.isConvergent || intrinsic.isSpeculatable) {
+ intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold ||
+ intrinsic.isNoDuplicate || intrinsic.isConvergent ||
+ intrinsic.isSpeculatable) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@@ -700,6 +704,12 @@ void IntrinsicEmitter::EmitAttributes(co
OS << "Attribute::NoReturn";
addComma = true;
}
+ if (intrinsic.isWillReturn) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WillReturn";
+ addComma = true;
+ }
if (intrinsic.isCold) {
if (addComma)
OS << ",";
More information about the llvm-commits
mailing list