Skip to content

Commit

Permalink
[Hexagon] Emit lookup tables in text section based on a flag
Browse files Browse the repository at this point in the history
The flag "-hexagon-emit-lut-text" (defaulted to false) is added to decide
on where to keep the switch generated lookup table.
Differential Revision: https://reviews.llvm.org/D34818

llvm-svn: 308316
  • Loading branch information
Sumanth Gundapaneni committed Jul 18, 2017
1 parent 9a61a79 commit d5aa0f3
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 0 deletions.
47 changes: 47 additions & 0 deletions llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp
Expand Up @@ -53,6 +53,10 @@ static cl::opt<bool>
EmitJtInText("hexagon-emit-jt-text", cl::Hidden, cl::init(false),
cl::desc("Emit hexagon jump tables in function section"));

static cl::opt<bool>
EmitLutInText("hexagon-emit-lut-text", cl::Hidden, cl::init(false),
cl::desc("Emit hexagon lookup tables in function section"));

// TraceGVPlacement controls messages for all builds. For builds with assertions
// (debug or release), messages are also controlled by the usual debug flags
// (e.g. -debug and -debug-only=globallayout)
Expand Down Expand Up @@ -136,6 +140,13 @@ MCSection *HexagonTargetObjectFile::SelectSectionForGlobal(
<< (Kind.isBSS() ? "kind_bss " : "" )
<< (Kind.isBSSLocal() ? "kind_bss_local " : "" ));

// If the lookup table is used by more than one function, do not place
// it in text section.
if (EmitLutInText && GO->getName().startswith("switch.table")) {
if (const Function *Fn = getLutUsedFunction(GO))
return selectSectionForLookupTable(GO, TM, Fn);
}

if (isGlobalInSmallSection(GO, TM))
return selectSmallSectionForGlobal(GO, Kind, TM);

Expand Down Expand Up @@ -402,3 +413,39 @@ MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
// Otherwise, we work the same as ELF.
return TargetLoweringObjectFileELF::SelectSectionForGlobal(GO, Kind, TM);
}

// Return the function that uses the lookup table. If there are more
// than one live function that uses this look table, bail out and place
// the lookup table in default section.
const Function *
HexagonTargetObjectFile::getLutUsedFunction(const GlobalObject *GO) const {
const Function *ReturnFn = nullptr;
for (auto U : GO->users()) {
// validate each instance of user to be a live function.
auto *I = dyn_cast<Instruction>(U);
if (!I)
continue;
auto *Bb = I->getParent();
if (!Bb)
continue;
auto *UserFn = Bb->getParent();
if (!ReturnFn)
ReturnFn = UserFn;
else if (ReturnFn != UserFn)
return nullptr;
}
return ReturnFn;
}

MCSection *HexagonTargetObjectFile::selectSectionForLookupTable(
const GlobalObject *GO, const TargetMachine &TM, const Function *Fn) const {

SectionKind Kind = SectionKind::getText();
// If the function has explicit section, place the lookup table in this
// explicit section.
if (Fn->hasSection())
return getExplicitSectionGlobal(Fn, Kind, TM);

const auto *FuncObj = dyn_cast<GlobalObject>(Fn);
return SelectSectionForGlobal(FuncObj, Kind, TM);
}
6 changes: 6 additions & 0 deletions llvm/lib/Target/Hexagon/HexagonTargetObjectFile.h
Expand Up @@ -36,6 +36,8 @@ namespace llvm {
bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
const Function &F) const override;

const Function *getLutUsedFunction(const GlobalObject *GO) const;

private:
MCSectionELF *SmallDataSection;
MCSectionELF *SmallBSSSection;
Expand All @@ -46,6 +48,10 @@ namespace llvm {
MCSection *selectSmallSectionForGlobal(const GlobalObject *GO,
SectionKind Kind,
const TargetMachine &TM) const;

MCSection *selectSectionForLookupTable(const GlobalObject *GO,
const TargetMachine &TM,
const Function *Fn) const;
};

} // namespace llvm
Expand Down
32 changes: 32 additions & 0 deletions llvm/test/CodeGen/Hexagon/switch-lut-explicit-section.ll
@@ -0,0 +1,32 @@
;RUN: llc -O2 -hexagon-emit-lut-text=true < %s | FileCheck --check-prefix=FUNCTEXT %s
;RUN: llc -O2 -hexagon-emit-lut-text=true -function-sections < %s | FileCheck --check-prefix=FUNCTEXT %s

;This test checks the placement of lookup table in explicit section from the attribute set.
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon-unknown--elf"

;FUNCTEXT: .text
;FUNCTEXT: .section{{.*}}tcm.hexagon,
;FUNCTEXT-NOT: .section{{.*}}.rodata
;FUNCTEXT-NOT: .text
;FUNCTEXT: .Lswitch.table:
;FUNCTEXT-NEXT: .word

@switch.table = private unnamed_addr constant [9 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5, i32 98, i32 8, i32 11] #0

; Function Attrs: norecurse nounwind readnone
define i32 @foo(i32 %x) local_unnamed_addr #0 section "tcm.hexagon" {
entry:
%0 = icmp ult i32 %x, 9
br i1 %0, label %switch.lookup, label %return

switch.lookup: ; preds = %entry
%switch.gep = getelementptr inbounds [9 x i32], [9 x i32]* @switch.table, i32 0, i32 %x
%switch.load = load i32, i32* %switch.gep, align 4
ret i32 %switch.load

return: ; preds = %entry
ret i32 19
}

attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "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-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv60" "target-features"="-hvx-double,-long-calls" "unsafe-fp-math"="false" "use-soft-float"="false" }
30 changes: 30 additions & 0 deletions llvm/test/CodeGen/Hexagon/switch-lut-function-section.ll
@@ -0,0 +1,30 @@
;RUN: llc -O2 -hexagon-emit-lut-text=true -function-sections < %s | FileCheck --check-prefix=FUNCTEXT %s

;This test checks the placement of lookup table in function's text section.
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon-unknown--elf"

;FUNCTEXT: .text
;FUNCTEXT: .section{{.*}}text.foo,
;FUNCTEXT-NOT: .section{{.*}}.rodata
;FUNCTEXT: .Lswitch.table:
;FUNCTEXT-NEXT: .word

@switch.table = private unnamed_addr constant [9 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5, i32 98, i32 8, i32 11] #0

; Function Attrs: norecurse nounwind readnone
define i32 @foo(i32 %x) local_unnamed_addr #0 {
entry:
%0 = icmp ult i32 %x, 9
br i1 %0, label %switch.lookup, label %return

switch.lookup: ; preds = %entry
%switch.gep = getelementptr inbounds [9 x i32], [9 x i32]* @switch.table, i32 0, i32 %x
%switch.load = load i32, i32* %switch.gep, align 4
ret i32 %switch.load

return: ; preds = %entry
ret i32 19
}

attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "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-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv60" "target-features"="-hvx-double,-long-calls" "unsafe-fp-math"="false" "use-soft-float"="false" }
42 changes: 42 additions & 0 deletions llvm/test/CodeGen/Hexagon/switch-lut-multiple-functions.ll
@@ -0,0 +1,42 @@
;RUN: llc -O2 -hexagon-emit-lut-text=true < %s | FileCheck --check-prefix=TEXT %s
;If the look up table is used by more than one function, we should ignore the
;flag and place it the rodata.
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon-unknown--elf"

;TEXT: .text
;TEXT: .section{{.*}}.rodata
;TEXT: .Lswitch.table:
;TEXT-NEXT: .word
@switch.table = private unnamed_addr constant [9 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5, i32 98, i32 8, i32 11]

; Function Attrs: norecurse nounwind readnone
define i32 @foo(i32 %x) local_unnamed_addr #0 {
entry:
%0 = icmp ult i32 %x, 9
br i1 %0, label %switch.lookup, label %return

switch.lookup: ; preds = %entry
%switch.gep = getelementptr inbounds [9 x i32], [9 x i32]* @switch.table, i32 0, i32 %x
%switch.load = load i32, i32* %switch.gep, align 4
ret i32 %switch.load

return: ; preds = %entry
ret i32 19
}

define i32 @goo(i32 %x) local_unnamed_addr #0 {
entry:
%0 = icmp ult i32 %x, 9
br i1 %0, label %switch.lookup, label %return

switch.lookup: ; preds = %entry
%switch.gep = getelementptr inbounds [9 x i32], [9 x i32]* @switch.table, i32 0, i32 %x
%switch.load = load i32, i32* %switch.gep, align 4
ret i32 %switch.load

return: ; preds = %entry
ret i32 19
}

attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "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-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv60" "target-features"="-hvx-double,-long-calls" "unsafe-fp-math"="false" "use-soft-float"="false" }
27 changes: 27 additions & 0 deletions llvm/test/CodeGen/Hexagon/switch-lut-text-section.ll
@@ -0,0 +1,27 @@
;RUN: llc -O2 -hexagon-emit-lut-text=true < %s | FileCheck --check-prefix=TEXT %s
;This test checks the placement of lookup table in text section.
target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
target triple = "hexagon-unknown--elf"

;TEXT: .text
;TEXT-NOT: .section{{.*}}.rodata
;TEXT: .Lswitch.table:
;TEXT-NEXT: .word
@switch.table = private unnamed_addr constant [9 x i32] [i32 9, i32 20, i32 14, i32 22, i32 12, i32 5, i32 98, i32 8, i32 11]

; Function Attrs: norecurse nounwind readnone
define i32 @foo(i32 %x) local_unnamed_addr #0 {
entry:
%0 = icmp ult i32 %x, 9
br i1 %0, label %switch.lookup, label %return

switch.lookup: ; preds = %entry
%switch.gep = getelementptr inbounds [9 x i32], [9 x i32]* @switch.table, i32 0, i32 %x
%switch.load = load i32, i32* %switch.gep, align 4
ret i32 %switch.load

return: ; preds = %entry
ret i32 19
}

attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "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-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv60" "target-features"="-hvx-double,-long-calls" "unsafe-fp-math"="false" "use-soft-float"="false" }

0 comments on commit d5aa0f3

Please sign in to comment.