[PATCH] D150396: [InlineCost] Check for conflicting target attributes early

Kazu Hirata via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 31 10:17:34 PDT 2023


kazu updated this revision to Diff 527106.
kazu added a comment.

Add a FIXME comment.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D150396/new/

https://reviews.llvm.org/D150396

Files:
  llvm/lib/Analysis/InlineCost.cpp
  llvm/test/Transforms/Inline/target-features-vs-alwaysinline.ll


Index: llvm/test/Transforms/Inline/target-features-vs-alwaysinline.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/Inline/target-features-vs-alwaysinline.ll
@@ -0,0 +1,36 @@
+; RUN: opt < %s -passes=inline -pass-remarks-missed=inline -S 2>&1 | FileCheck %s
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Make sure that we do not inline callee into caller.  If we inline
+; callee into caller, caller would end pu with AVX512 intrinsics even
+; though it is not allowed to use AVX512 instructions.
+; CHECK: remark: [[MSG:.*]] because it should never be inlined (cost=never): conflicting target attributes
+
+define void @caller(ptr %0) {
+; CHECK-LABEL: define void @caller
+; CHECK-SAME: (ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    call void @callee(ptr [[TMP0]], i64 0, i32 0) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    ret void
+;
+  call void @callee(ptr %0, i64 0, i32 0) #1
+  ret void
+}
+
+define available_externally void @callee(ptr %0, i64 %1, i32 %2) #0 {
+; CHECK-LABEL: define available_externally void @callee
+; CHECK-SAME: (ptr [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[TMP4:%.*]] = call <16 x float> @llvm.x86.avx512.min.ps.512(<16 x float> zeroinitializer, <16 x float> zeroinitializer, i32 0)
+; CHECK-NEXT:    store <16 x float> [[TMP4]], ptr [[TMP0]], align 1
+; CHECK-NEXT:    ret void
+;
+  %4 = call <16 x float> @llvm.x86.avx512.min.ps.512(<16 x float> zeroinitializer, <16 x float> zeroinitializer, i32 0)
+  store <16 x float> %4, ptr %0, align 1
+  ret void
+}
+
+declare <16 x float> @llvm.x86.avx512.min.ps.512(<16 x float>, <16 x float>, i32 immarg)
+
+attributes #0 = { "target-features"="+aes,+avx,+avx2,+avx512bw,+avx512dq,+avx512f,+avx512vl,+bmi,+bmi2,+crc32,+cx16,+cx8,+f16c,+fma,+fsgsbase,+fxsr,+invpcid,+lzcnt,+mmx,+movbe,+pclmul,+popcnt,+rdrnd,+sahf,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt" }
+attributes #1 = { alwaysinline }
Index: llvm/lib/Analysis/InlineCost.cpp
===================================================================
--- llvm/lib/Analysis/InlineCost.cpp
+++ llvm/lib/Analysis/InlineCost.cpp
@@ -2801,16 +2801,14 @@
 /// Test that there are no attribute conflicts between Caller and Callee
 ///        that prevent inlining.
 static bool functionsHaveCompatibleAttributes(
-    Function *Caller, Function *Callee, TargetTransformInfo &TTI,
+    Function *Caller, Function *Callee,
     function_ref<const TargetLibraryInfo &(Function &)> &GetTLI) {
   // Note that CalleeTLI must be a copy not a reference. The legacy pass manager
   // caches the most recently created TLI in the TargetLibraryInfoWrapperPass
   // object, and always returns the same object (which is overwritten on each
   // GetTLI call). Therefore we copy the first result.
   auto CalleeTLI = GetTLI(*Callee);
-  return (IgnoreTTIInlineCompatible ||
-          TTI.areInlineCompatible(Caller, Callee)) &&
-         GetTLI(*Caller).areInlineCompatible(CalleeTLI,
+  return GetTLI(*Caller).areInlineCompatible(CalleeTLI,
                                              InlineCallerSupersetNoBuiltin) &&
          AttributeFuncs::areInlineCompatible(*Caller, *Callee);
 }
@@ -2926,6 +2924,12 @@
                                      " address space");
     }
 
+  // Never inline functions with conflicting target attributes.
+  Function *Caller = Call.getCaller();
+  if (!IgnoreTTIInlineCompatible &&
+      !CalleeTTI.areInlineCompatible(Caller, Callee))
+    return InlineResult::failure("conflicting target attributes");
+
   // Calls to functions with always-inline attributes should be inlined
   // whenever possible.
   if (Call.hasFnAttr(Attribute::AlwaysInline)) {
@@ -2940,8 +2944,12 @@
 
   // Never inline functions with conflicting attributes (unless callee has
   // always-inline attribute).
-  Function *Caller = Call.getCaller();
-  if (!functionsHaveCompatibleAttributes(Caller, Callee, CalleeTTI, GetTLI))
+  // FIXME: functionsHaveCompatibleAttributes below checks for compatibilities
+  // of different kinds of function attributes -- sanitizer-related ones,
+  // checkDenormMode, no-builtin-memcpy, etc.  It's unclear if we really want
+  // the always-inline attribute to take precedence over these different types
+  // of function attributes.
+  if (!functionsHaveCompatibleAttributes(Caller, Callee, GetTLI))
     return InlineResult::failure("conflicting attributes");
 
   // Don't inline this call if the caller has the optnone attribute.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D150396.527106.patch
Type: text/x-patch
Size: 4613 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230531/001f1fb0/attachment.bin>


More information about the llvm-commits mailing list