llvm.org GIT mirror llvm / decaafe
[ARM] Prefer indirect calls in minsize mode ... When we emit several calls to the same function in the same basic block. An indirect call uses a "BLX r0" instruction which has a 16-bit encoding. If many calls are made to the same target, this can enable significant code size reductions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275537 91177308-0d34-0410-b5e6-96231b3b80d8 James Molloy 4 years ago
2 changed file(s) with 70 addition(s) and 28 deletion(s). Raw diff Collapse all Expand all
18481848 false, false, 0);
18491849 }
18501850 } else if (isa(Callee)) {
1851 isDirect = true;
1852 bool isDef = GV->isStrongDefinitionForLinker();
1853
1854 // ARM call to a local ARM function is predicable.
1855 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !ARMInterworking);
1856 // tBX takes a register source operand.
1857 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
1858 assert(Subtarget->isTargetMachO() && "WrapperPIC use on non-MachO?");
1859 Callee = DAG.getNode(
1860 ARMISD::WrapperPIC, dl, PtrVt,
1861 DAG.getTargetGlobalAddress(GV, dl, PtrVt, 0, ARMII::MO_NONLAZY));
1862 Callee = DAG.getLoad(PtrVt, dl, DAG.getEntryNode(), Callee,
1863 MachinePointerInfo::getGOT(DAG.getMachineFunction()),
1864 false, false, true, 0);
1865 } else if (Subtarget->isTargetCOFF()) {
1866 assert(Subtarget->isTargetWindows() &&
1867 "Windows is the only supported COFF target");
1868 unsigned TargetFlags = GV->hasDLLImportStorageClass()
1869 ? ARMII::MO_DLLIMPORT
1870 : ARMII::MO_NO_FLAG;
1871 Callee =
1872 DAG.getTargetGlobalAddress(GV, dl, PtrVt, /*Offset=*/0, TargetFlags);
1873 if (GV->hasDLLImportStorageClass())
1851 // If we're optimizing for minimum size and the function is called many
1852 // times in this block, we can improve codesize by calling indirectly
1853 // as BLXr has a 16-bit encoding.
1854 auto *GV = cast(Callee)->getGlobal();
1855 auto *BB = CLI.CS->getParent();
1856 bool PreferIndirect =
1857 Subtarget->isThumb() && MF.getFunction()->optForMinSize() &&
1858 std::count_if(GV->user_begin(), GV->user_end(), [&BB](const User *U) {
1859 return isa(U) && cast(U)->getParent() == BB;
1860 }) > 2;
1861
1862 if (!PreferIndirect) {
1863 isDirect = true;
1864 bool isDef = GV->isStrongDefinitionForLinker();
1865
1866 // ARM call to a local ARM function is predicable.
1867 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !ARMInterworking);
1868 // tBX takes a register source operand.
1869 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
1870 assert(Subtarget->isTargetMachO() && "WrapperPIC use on non-MachO?");
1871 Callee = DAG.getNode(
1872 ARMISD::WrapperPIC, dl, PtrVt,
1873 DAG.getTargetGlobalAddress(GV, dl, PtrVt, 0, ARMII::MO_NONLAZY));
18741874 Callee =
1875 DAG.getLoad(PtrVt, dl, DAG.getEntryNode(),
1876 DAG.getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
1875 DAG.getLoad(PtrVt, dl, DAG.getEntryNode(), Callee,
18771876 MachinePointerInfo::getGOT(DAG.getMachineFunction()),
1878 false, false, false, 0);
1879 } else {
1880 Callee = DAG.getTargetGlobalAddress(GV, dl, PtrVt, 0, 0);
1877 false, false, true, 0);
1878 } else if (Subtarget->isTargetCOFF()) {
1879 assert(Subtarget->isTargetWindows() &&
1880 "Windows is the only supported COFF target");
1881 unsigned TargetFlags = GV->hasDLLImportStorageClass()
1882 ? ARMII::MO_DLLIMPORT
1883 : ARMII::MO_NO_FLAG;
1884 Callee = DAG.getTargetGlobalAddress(GV, dl, PtrVt, /*Offset=*/0,
1885 TargetFlags);
1886 if (GV->hasDLLImportStorageClass())
1887 Callee =
1888 DAG.getLoad(PtrVt, dl, DAG.getEntryNode(),
1889 DAG.getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
1890 MachinePointerInfo::getGOT(DAG.getMachineFunction()),
1891 false, false, false, 0);
1892 } else {
1893 Callee = DAG.getTargetGlobalAddress(GV, dl, PtrVt, 0, 0);
1894 }
18811895 }
18821896 } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) {
18831897 isDirect = true;
0 ; RUN: llc < %s | FileCheck %s
1
2 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
3 target triple = "thumbv7m-arm-none-eabi"
4
5 ; CHECK-LABEL: f:
6 ; CHECK: blx r
7 ; CHECK: blx r
8 ; CHECK: blx r
9 define void @f() minsize optsize {
10 entry:
11 call void @g(i32 45, i32 66)
12 call void @g(i32 88, i32 32)
13 call void @g(i32 55, i32 33)
14 ret void
15 }
16
17 ; CHECK-LABEL: h:
18 ; CHECK: bl g
19 ; CHECK: bl g
20 define void @h() minsize optsize {
21 entry:
22 call void @g(i32 45, i32 66)
23 call void @g(i32 88, i32 32)
24 ret void
25 }
26
27 declare void @g(i32,i32)