forked from OSchip/llvm-project
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:
parent
42666eeea2
commit
2aab7f4358
|
@ -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">;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
Loading…
Reference in New Issue