Skip to content

Commit 908e4db

Browse files
committed
Implement @optStrat UDA.
Resolves #1549.
1 parent d7d94c5 commit 908e4db

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

gen/uda.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace {
1717
namespace attr {
1818
const std::string llvmAttr = "llvmAttr";
1919
const std::string llvmFastMathFlag = "llvmFastMathFlag";
20+
const std::string optStrat = "optStrat";
2021
const std::string section = "section";
2122
const std::string target = "target";
2223
const std::string weak = "_weak";
@@ -147,6 +148,30 @@ void applyAttrLLVMFastMathFlag(StructLiteralExp *sle, IrFunction *irFunc) {
147148
}
148149
}
149150

151+
void applyAttrOptStrat(StructLiteralExp *sle, IrFunction *irFunc) {
152+
checkStructElems(sle, {Type::tstring});
153+
llvm::StringRef value = getStringElem(sle, 0);
154+
155+
if (value == "none") {
156+
if (irFunc->decl->inlining == PINLINEalways) {
157+
sle->error("cannot combine '@ldc.attributes.%s(\"none\")' with "
158+
"'pragma(inline, true)'",
159+
sle->sd->ident->string);
160+
return;
161+
}
162+
irFunc->decl->inlining = PINLINEnever;
163+
irFunc->func->addFnAttr(llvm::Attribute::OptimizeNone);
164+
} else if (value == "optsize") {
165+
irFunc->func->addFnAttr(llvm::Attribute::OptimizeForSize);
166+
} else if (value == "minsize") {
167+
irFunc->func->addFnAttr(llvm::Attribute::MinSize);
168+
} else {
169+
sle->warning(
170+
"ignoring unrecognized parameter '%s' for '@ldc.attributes.%s'",
171+
value.data(), sle->sd->ident->string);
172+
}
173+
}
174+
150175
void applyAttrSection(StructLiteralExp *sle, llvm::GlobalObject *globj) {
151176
checkStructElems(sle, {Type::tstring});
152177
globj->setSection(getFirstElemString(sle));
@@ -233,6 +258,10 @@ void applyVarDeclUDAs(VarDeclaration *decl, llvm::GlobalVariable *gvar) {
233258
auto name = sle->sd->ident->string;
234259
if (name == attr::section) {
235260
applyAttrSection(sle, gvar);
261+
} else if (name == attr::optStrat) {
262+
sle->error(
263+
"Special attribute 'ldc.attributes.optStrat' is only valid for "
264+
"functions");
236265
} else if (name == attr::target) {
237266
sle->error("Special attribute 'ldc.attributes.target' is only valid for "
238267
"functions");
@@ -265,6 +294,8 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
265294
applyAttrLLVMAttr(sle, func);
266295
} else if (name == attr::llvmFastMathFlag) {
267296
applyAttrLLVMFastMathFlag(sle, irFunc);
297+
} else if (name == attr::optStrat) {
298+
applyAttrOptStrat(sle, irFunc);
268299
} else if (name == attr::section) {
269300
applyAttrSection(sle, func);
270301
} else if (name == attr::target) {

runtime/druntime

Submodule druntime updated 1 file

tests/codegen/attr_optstrat.d

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %ldc -I%S -c -output-ll -O3 -of=%t.ll %s && FileCheck %s < %t.ll
2+
3+
// REQUIRES: atleast_llvm307
4+
5+
import ldc.attributes;
6+
import inputs.inlinables;
7+
8+
extern (C): // For easier name mangling
9+
10+
// CHECK-LABEL: define{{.*}} @call_easily_inlinable(
11+
// CHECK-SAME: #[[OPTNONE:[0-9]+]]
12+
@optStrat("none")
13+
int call_easily_inlinable(int i)
14+
{
15+
// CHECK: call {{.*}} @easily_inlinable(
16+
return easily_inlinable(i);
17+
// CHECK-NOT: ret i32 2
18+
}
19+
20+
// CHECK-LABEL: define{{.*}} @call_always_inline(
21+
@optStrat("none")
22+
int call_always_inline()
23+
{
24+
// CHECK-NOT: call {{.*}} @always_inline()
25+
return always_inline();
26+
}
27+
28+
// CHECK-LABEL: define{{.*}} @call_optnone(
29+
int call_optnone()
30+
{
31+
// CHECK: call {{.*}} @optnone_function()
32+
return optnone_function();
33+
}
34+
35+
// CHECK-LABEL: define{{.*}} @foo(
36+
// CHECK-SAME: #[[OPTSIZE:[0-9]+]]
37+
@optStrat("optsize")
38+
void foo()
39+
{
40+
}
41+
42+
// CHECK-LABEL: define{{.*}} @foo2(
43+
// CHECK-SAME: #[[MINSIZE:[0-9]+]]
44+
@optStrat("minsize")
45+
void foo2()
46+
{
47+
}
48+
49+
// CHECK-DAG: attributes #[[OPTNONE]] = {{.*}} optnone
50+
// CHECK-DAG: attributes #[[OPTSIZE]] = {{.*}} optsize
51+
// CHECK-DAG: attributes #[[MINSIZE]] = {{.*}} minsize

tests/codegen/inputs/inlinables.d

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ class A
7676
return 654;
7777
}
7878

79+
// optnone functions should not be inlined.
80+
@optStrat("none") int optnone_function()
81+
{
82+
return 654;
83+
}
84+
7985
int module_variable = 666;
8086
pragma(inline, true) void write_module_variable(int i)
8187
{

0 commit comments

Comments
 (0)