Add support for no-jump-tables

Add function soft attribute to the generation of Jump Tables in CodeGen
as initial step towards clang support of gcc's no-jump-table support

Reviewers: hans, echristo

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D18321

llvm-svn: 264756
This commit is contained in:
Nirav Dave 2016-03-29 17:46:23 +00:00
parent 42666eeea2
commit 2aab7f4358
4 changed files with 95 additions and 2 deletions

View File

@ -168,6 +168,7 @@ def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">;
def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">;
def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">;
def NoJumpTables : StrBoolAttr<"no-jump-tables">;
class CompatRule<string F> {
// The name of the function called to check the attribute of the caller and
@ -197,4 +198,5 @@ def : MergeRule<"setAND<NoInfsFPMathAttr>">;
def : MergeRule<"setAND<NoNansFPMathAttr>">;
def : MergeRule<"setAND<UnsafeFPMathAttr>">;
def : MergeRule<"setOR<NoImplicitFloatAttr>">;
def : MergeRule<"setOR<NoJumpTablesAttr>">;
def : MergeRule<"adjustCallerSSPLevel">;

View File

@ -7961,7 +7961,12 @@ bool SelectionDAGBuilder::isDense(const CaseClusterVector &Clusters,
return NumCases * 100 >= Range * Density;
}
static inline bool areJTsAllowed(const TargetLowering &TLI) {
static inline bool areJTsAllowed(const TargetLowering &TLI,
const SwitchInst *SI) {
const Function *Fn = SI->getParent()->getParent();
if (Fn->getFnAttribute("no-jump-tables").getValueAsString() == "true")
return false;
return TLI.isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) ||
TLI.isOperationLegalOrCustom(ISD::BRIND, MVT::Other);
}
@ -8055,7 +8060,7 @@ void SelectionDAGBuilder::findJumpTables(CaseClusterVector &Clusters,
#endif
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
if (!areJTsAllowed(TLI))
if (!areJTsAllowed(TLI, SI))
return;
const int64_t N = Clusters.size();

View File

@ -30,6 +30,47 @@ return: ret void
; NOOPT: jmpq
}
; Should never be lowered as a jump table because of the attribute
define void @basic_nojumptable(i32 %x) "no-jump-tables"="true" {
entry:
switch i32 %x, label %return [
i32 3, label %bb0
i32 1, label %bb1
i32 4, label %bb1
i32 5, label %bb2
]
bb0: tail call void @g(i32 0) br label %return
bb1: tail call void @g(i32 1) br label %return
bb2: tail call void @g(i32 1) br label %return
return: ret void
; Lowered as a jump table, both with and without optimization.
; CHECK-LABEL: basic_nojumptable
; CHECK-NOT: jmpq *.LJTI
}
; Should be lowered as a jump table because of the attribute
define void @basic_nojumptable_false(i32 %x) "no-jump-tables"="false" {
entry:
switch i32 %x, label %return [
i32 3, label %bb0
i32 1, label %bb1
i32 4, label %bb1
i32 5, label %bb2
]
bb0: tail call void @g(i32 0) br label %return
bb1: tail call void @g(i32 1) br label %return
bb2: tail call void @g(i32 1) br label %return
return: ret void
; Lowered as a jump table, both with and without optimization.
; CHECK-LABEL: basic_nojumptable_false
; CHECK: decl
; CHECK: cmpl $4
; CHECK: ja
; CHECK: jmpq *.LJTI
}
define void @simple_ranges(i32 %x) {
entry:
@ -47,6 +88,8 @@ bb0: tail call void @g(i32 0) br label %return
bb1: tail call void @g(i32 1) br label %return
return: ret void
; Should be lowered to two range checks.
; CHECK-LABEL: simple_ranges
; CHECK: leal -100

View File

@ -241,6 +241,49 @@ define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {
; CHECK-NEXT: ret i32
}
; Check that no-jump-tables flag propagates from inlined callee to caller
define i32 @no-use-jump-tables_callee0(i32 %i) {
ret i32 %i
; CHECK: @no-use-jump-tables_callee0(i32 %i) {
; CHECK-NEXT: ret i32
}
define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" {
ret i32 %i
; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] {
; CHECK-NEXT: ret i32
}
define i32 @test_no-use-jump-tables0(i32 %i) {
%1 = call i32 @no-use-jump-tables_callee0(i32 %i)
ret i32 %1
; CHECK: @test_no-use-jump-tables0(i32 %i) {
; CHECK-NEXT: ret i32
}
define i32 @test_no-use-jump-tables1(i32 %i) {
%1 = call i32 @no-use-jump-tables_callee1(i32 %i)
ret i32 %1
; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] {
; CHECK-NEXT: ret i32
}
define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" {
%1 = call i32 @no-use-jump-tables_callee0(i32 %i)
ret i32 %1
; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] {
; CHECK-NEXT: ret i32
}
define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" {
%1 = call i32 @no-use-jump-tables_callee1(i32 %i)
ret i32 %1
; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] {
; CHECK-NEXT: ret i32
}
; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }
; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }
; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }
; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }