[PATCH] D33774: [CodeGen] Make __attribute__(const) calls speculatable

Tobias Grosser via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 1 05:25:20 PDT 2017


grosser created this revision.
Herald added subscribers: javed.absar, wdng.

Today 'const' functions are only marked 'readnone' and 'nounwind', but lack the
'speculatable' attribute for historic reasons. As 'const' functions are known to
not have any side effects and are intended to enable loop optimizations, they
are indeed 'speculatable' and consequently should be marked as such.

Some history: Back before r44273 (long time ago) readnone was indeed called
const and LLVM was assuming that readnone functions do not contain infinite
loops and can be hoisted. This worked at the beginning, but LLVM learned over
time to infer the readnone attribute from function definitions. As a result,
infinite functions that do not touch memory were marked as readnone, incorrectly
also stating that they are free of infinite loops, because different LLVM passes
still assumed a one-to-one correspondence between '__attribute(const)' and
LLVM's readnone attribute. Over time, we learned that 'readnone' must not imply
absence of infinite loops and other side effects to allow us to derive this
attribute automatically. Hence, the definition of readnone was changed to not
give information about the termination of functions. To still provide
information about side effects outside of memory effects LLVM recently learned
about speculatable function attributes: (https://reviews.llvm.org/D20116)

With 'speculatable' now available, we can pass information about the absence
of non-memory side effects to LLVM-IR.

This idea was taken from earlier discussions where for example Chris suggested
this solution:

"This really only matters when the compiler is able to infer readnone/readonly,
which typically doesn't include cases with indirect calls.  Per #2, I think it
could be handled by making the GCC-style pure/const attributes imply both
readonly/readnone *and* halting. :


https://reviews.llvm.org/D33774

Files:
  lib/CodeGen/CGCall.cpp
  test/CodeGen/function-attributes.c
  test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp


Index: test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp
===================================================================
--- test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp
+++ test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp
@@ -5,18 +5,18 @@
 
 // CHECK: define i32 @_Z1fv() [[TF:#[0-9]+]] {
 int f(void) {
-  // CHECK: call i32 @_Z1cv() [[NUW_RN_CALL:#[0-9]+]]
+  // CHECK: call i32 @_Z1cv() [[NUW_RN_SP_CALL:#[0-9]+]]
   // CHECK: call i32 @_Z1pv() [[NUW_RO_CALL:#[0-9]+]]
   return c() + p() + t();
 }
 
-// CHECK: declare i32 @_Z1cv() [[NUW_RN:#[0-9]+]]
+// CHECK: declare i32 @_Z1cv() [[NUW_RN_SP:#[0-9]+]]
 // CHECK: declare i32 @_Z1pv() [[NUW_RO:#[0-9]+]]
 // CHECK: declare i32 @_Z1tv() [[TF2:#[0-9]+]]
 
 // CHECK: attributes [[TF]] = { {{.*}} }
-// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} }
+// CHECK: attributes [[NUW_RN_SP]] = { nounwind readnone speculatable{{.*}} }
 // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} }
 // CHECK: attributes [[TF2]] = { {{.*}} }
-// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone }
+// CHECK: attributes [[NUW_RN_SP_CALL]] = { nounwind readnone speculatable }
 // CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly }
Index: test/CodeGen/function-attributes.c
===================================================================
--- test/CodeGen/function-attributes.c
+++ test/CodeGen/function-attributes.c
@@ -44,7 +44,7 @@
 
 // FIXME: We should be setting nounwind on calls.
 // CHECK: call i32 @f10_t()
-// CHECK: [[NUW_RN:#[0-9]+]]
+// CHECK: [[NUW_RN_SP:#[0-9]+]]
 // CHECK: {
 int __attribute__((const)) f10_t(void);
 int f10(void) { return f10_t(); }
@@ -114,5 +114,5 @@
 // CHECK: attributes [[ALIGN]] = { nounwind optsize alignstack=16{{.*}} }
 // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} }
 // CHECK: attributes [[NR]] = { noreturn optsize }
-// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone }
+// CHECK: attributes [[NUW_RN_SP]] = { nounwind optsize readnone speculatable }
 // CHECK: attributes [[RT_CALL]] = { optsize returns_twice }
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1804,6 +1804,7 @@
     if (TargetDecl->hasAttr<ConstAttr>()) {
       FuncAttrs.addAttribute(llvm::Attribute::ReadNone);
       FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+      FuncAttrs.addAttribute(llvm::Attribute::Speculatable);
     } else if (TargetDecl->hasAttr<PureAttr>()) {
       FuncAttrs.addAttribute(llvm::Attribute::ReadOnly);
       FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33774.101015.patch
Type: text/x-patch
Size: 2642 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170601/cc0d8000/attachment.bin>


More information about the cfe-commits mailing list