Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HLSL] set alwaysinline on HLSL functions #106588

Merged
merged 12 commits into from
Sep 17, 2024
Merged

Conversation

pow2clk
Copy link
Contributor

@pow2clk pow2clk commented Aug 29, 2024

HLSL inlines all its functions by default. This uses the alwaysinline attribute to force that in the corresponding pass for user functions by default and overrides the default noinline of some implicit functions. This makes an instance of explicit inlining for buffer subscripts unnecessary.

Adds tests for function and constructor inlining and augments some existing tests to verify correct inlining of implicitly created functions as well.

incidentally restore RUN line that I believe was mistakenly removed as part of #88918

fixes #89282

HLSL inlines all its functions by default. This uses the alwaysinline
attribute to force that in the corresponding pass for user functions
by default and overrides the default noinline of some implicit functions.
This makes an instance of explicit inlining for buffer subscripts unnecessary.

Adds tests for function and constructor inlining and augments some existing
tests to verify correct inlining of implicitly created functions as well.

incidentally restore RUN line that I believe was mistakenly removed as part of llvm#88918

fixes llvm#89282
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen HLSL HLSL Language Support labels Aug 29, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Aug 29, 2024

@llvm/pr-subscribers-clang

Author: Greg Roth (pow2clk)

Changes

HLSL inlines all its functions by default. This uses the alwaysinline attribute to force that in the corresponding pass for user functions by default and overrides the default noinline of some implicit functions. This makes an instance of explicit inlining for buffer subscripts unnecessary.

Adds tests for function and constructor inlining and augments some existing tests to verify correct inlining of implicitly created functions as well.

incidentally restore RUN line that I believe was mistakenly removed as part of #88918

fixes #89282


Full diff: https://github.com/llvm/llvm-project/pull/106588.diff

10 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+14-3)
  • (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+2-2)
  • (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (-2)
  • (modified) clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl (+21-10)
  • (modified) clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl (+19-4)
  • (modified) clang/test/CodeGenHLSL/GlobalDestructors.hlsl (+31-20)
  • (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl (+1)
  • (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl (+3-2)
  • (added) clang/test/CodeGenHLSL/inline-constructors.hlsl (+74)
  • (added) clang/test/CodeGenHLSL/inline-functions.hlsl (+114)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 4bd7b6ba58de0d..24d126ced0d9f7 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -414,9 +414,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
 
 void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
                                               llvm::Function *Fn) {
-  if (FD->isInExportDeclContext()) {
-    const StringRef ExportAttrKindStr = "hlsl.export";
-    Fn->addFnAttr(ExportAttrKindStr);
+  if (FD) { // "explicit" functions with declarations
+    if (FD->isInExportDeclContext()) {
+      const StringRef ExportAttrKindStr = "hlsl.export";
+      Fn->addFnAttr(ExportAttrKindStr);
+    }
+    // Respect noinline if the explicit functions use it
+    // otherwise default to alwaysinline
+    if (!Fn->hasFnAttribute(Attribute::NoInline))
+      Fn->addFnAttr(llvm::Attribute::AlwaysInline);
+  } else { // "implicit" autogenerated functions with no declaration
+    // Implicit functions might get marked as noinline by default
+    // but we override that for HLSL
+    Fn->removeFnAttr(Attribute::NoInline);
+    Fn->addFnAttr(Attribute::AlwaysInline);
   }
 }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a5747283e98058..aceeed0e66d130 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1239,9 +1239,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   if (getLangOpts().OpenMP && CurCodeDecl)
     CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
 
-  if (FD && getLangOpts().HLSL) {
+  if (getLangOpts().HLSL) {
     // Handle emitting HLSL entry functions.
-    if (FD->hasAttr<HLSLShaderAttr>()) {
+    if (FD && FD->hasAttr<HLSLShaderAttr>()) {
       CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
     }
     CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 9aacbe4ad9548e..0a534d94192560 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -290,8 +290,6 @@ struct BuiltinTypeDeclBuilder {
                                              SourceLocation()));
     MethodDecl->setLexicalDeclContext(Record);
     MethodDecl->setAccess(AccessSpecifier::AS_public);
-    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
-        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
     Record->addDecl(MethodDecl);
 
     return *this;
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
index f954c9d2f029f2..b39311ad67cd62 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
 
 int i;
 
@@ -7,7 +8,7 @@ __attribute__((constructor)) void call_me_first(void) {
 }
 
 __attribute__((constructor)) void then_call_me(void) {
-  i = 12;
+  i = 13;
 }
 
 __attribute__((destructor)) void call_me_last(void) {
@@ -21,11 +22,21 @@ void main(unsigned GI : SV_GroupIndex) {}
 // CHECK-NOT:@llvm.global_ctors
 // CHECK-NOT:@llvm.global_dtors
 
-//CHECK: define void @main()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @"?call_me_first@@YAXXZ"()
-//CHECK-NEXT:   call void @"?then_call_me@@YAXXZ"()
-//CHECK-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-//CHECK-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
-//CHECK-NEXT:   call void @"?call_me_last@@YAXXZ"(
-//CHECK-NEXT:   ret void
+// CHECK: define void @main()
+// CHECK-NEXT: entry:
+// Verify function constructors are emitted
+// NOINLINE-NEXT:   call void @"?call_me_first@@YAXXZ"()
+// NOINLINE-NEXT:   call void @"?then_call_me@@YAXXZ"()
+// NOINLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
+// NOINLINE-NEXT:   call void @"?call_me_last@@YAXXZ"(
+// NOINLINE-NEXT:   ret void
+
+// Verify constructor calls are inlined when AlwaysInline is run
+// INLINE-NEXT:   alloca
+// INLINE-NEXT:   store i32 12
+// INLINE-NEXT:   store i32 13
+// INLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// INLINE-NEXT:   store i32 %
+// INLINE-NEXT:   store i32 0
+// INLINE:   ret void
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index 2c5c4e19c3296d..78f6475462bc47 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
 
 // Make sure global variable for ctors exist for lib profile.
 // CHECK:@llvm.global_ctors
@@ -11,7 +12,11 @@ void FirstEntry() {}
 
 // CHECK: define void @FirstEntry()
 // CHECK-NEXT: entry:
-// CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @"?FirstEntry@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
 
 [shader("compute")]
 [numthreads(1,1,1)]
@@ -19,5 +24,15 @@ void SecondEntry() {}
 
 // CHECK: define void @SecondEntry()
 // CHECK-NEXT: entry:
-// CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
-// CHECK-NEXT:   call void @"?SecondEntry@@YAXXZ"()
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @"?SecondEntry@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+
+// Verify the constructor is alwaysinline
+// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
+// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[IntAttr:\#[0-9]+]]
+
+// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
diff --git a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
index 24c3c039fc6192..ea28354222f885 100644
--- a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
@@ -1,10 +1,18 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,CHECK
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
 
-// Make sure global variable for dtors exist for lib profile.
+// Tests that constructors and destructors are appropriately generated for globals
+// and that their calls are inlined when AlwaysInline is run
+// but global variables are retained for the library profiles
+
+// Make sure global variable for ctors/dtors exist for lib profile.
+// LIB:@llvm.global_ctors
 // LIB:@llvm.global_dtors
-// Make sure global variable for dtors removed for compute profile.
-// CS-NOT:llvm.global_dtors
+// Make sure global variable for ctors/dtors removed for compute profile.
+// CS-NOT:@llvm.global_ctors
+// CS-NOT:@llvm.global_dtors
 
 struct Tail {
   Tail() {
@@ -46,22 +54,25 @@ void main(unsigned GI : SV_GroupIndex) {
   Wag();
 }
 
-// Make sure global variable for ctors/dtors removed.
-// CHECK-NOT:@llvm.global_ctors
-// CHECK-NOT:@llvm.global_dtors
-//CHECK:      define void @main()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
-//CHECK-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-//CHECK-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
-//CHECK-NEXT:   call void @_GLOBAL__D_a()
-//CHECK-NEXT:   ret void
+// CHECK:      define void @main()
+// CHECK-NEXT: entry:
+// Verify destructor is emitted
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
+// NOINLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
+// NOINLINE-NEXT:   call void @_GLOBAL__D_a()
+// NOINLINE-NEXT:   ret void
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// INLINE:   ret void
 
 // This is really just a sanity check I needed for myself to verify that
 // function scope static variables also get destroyed properly.
 
-//CHECK: define internal void @_GLOBAL__D_a()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
-//CHECK-NEXT:   call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
-//CHECK-NEXT:   ret void
+// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
+// NOINLINE-NEXT: entry:
+// NOINLINE-NEXT:   call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
+// NOINLINE-NEXT:   call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
+// NOINLINE-NEXT:   ret void
+
+// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index baddfcf2cf1d52..174f4c3eaaad26 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
 
 RWBuffer<float> Buf;
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
index da8a1e538ec5e7..2a350c1619bd6e 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
@@ -11,6 +11,7 @@ void main(unsigned GI : SV_GroupIndex) {
 // Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
 // and confusing to follow so the match here is pretty weak.
 
-// CHECK: define internal void @"?main@@YAXI@Z"
-// CHECK-NOT: call
+// CHECK: define void @main()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// CHECK-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
 // CHECK: ret void
diff --git a/clang/test/CodeGenHLSL/inline-constructors.hlsl b/clang/test/CodeGenHLSL/inline-constructors.hlsl
new file mode 100644
index 00000000000000..40c7a42bdc262e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/inline-constructors.hlsl
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
+
+// Tests that implicit contstructor calls for user classes will always be inlined.
+
+struct Weed {
+  Weed() {Count += 1;}
+  [[maybe_unused]] void pull() {Count--;}
+  static int weedCount() { return Count; }
+private:
+  static int Count;
+
+} YardWeeds;
+
+int Weed::Count = 1; // It begins. . .
+
+struct Kitty {
+  unsigned burrsInFur;
+
+  Kitty() {
+    burrsInFur = 0;
+  }
+
+  void wanderInYard(int hours) {
+    burrsInFur = hours*Weed::weedCount()/8;
+  }
+
+  void lick() {
+    if(burrsInFur) {
+      burrsInFur--;
+      Weed w;
+    }
+  }
+
+} Nion;
+
+void NionsDay(int hours) {
+  static Kitty Nion;
+  Nion.wanderInYard(hours);
+  while(Nion.burrsInFur) Nion.lick();
+}
+
+// CHECK:      define void @main()
+// CHECK-NEXT: entry:
+// Verify constructor is emitted
+// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
+// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:    call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK:         ret void
+[shader("compute")]
+[numthreads(1,1,1)]
+void main(unsigned GI : SV_GroupIndex) {
+  NionsDay(10);
+}
+
+
+// CHECK:      define void @rainyMain()
+// CHECK-NEXT: entry:
+// Verify constructor is emitted
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_inline_constructors.hlsl()
+// NOINLINE-NEXT:   call void @"?rainyMain@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:      call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK:           ret void
+[shader("compute")]
+[numthreads(1,1,1)]
+void rainyMain() {
+  NionsDay(1);
+}
+
diff --git a/clang/test/CodeGenHLSL/inline-functions.hlsl b/clang/test/CodeGenHLSL/inline-functions.hlsl
new file mode 100644
index 00000000000000..9c00e096a9eef2
--- /dev/null
+++ b/clang/test/CodeGenHLSL/inline-functions.hlsl
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.0-compute %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.0-compute %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+
+// Tests that user functions will always be inlined.
+// This includes exported functions and mangled entry point implementation functions.
+// The unmangled entry functions must not be alwaysinlined.
+
+#define MAX 100
+
+float nums[MAX];
+
+// Verify that all functions have the alwaysinline attribute
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define void @"?swap@@YAXY0GE@III@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %ix1, i32 noundef %ix2) [[IntAttr:\#[0-9]+]]
+// CHECK: ret void
+// Swap the values of Buf at indices ix1 and ix2
+void swap(unsigned Buf[MAX], unsigned ix1, unsigned ix2) {
+  float tmp = Buf[ix1];
+  Buf[ix1] = Buf[ix2];
+  Buf[ix2] = tmp;
+}
+
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define void @"?BubbleSort@@YAXY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[IntAttr]]
+// CHECK: ret void
+// Inefficiently sort Buf in place
+void BubbleSort(unsigned Buf[MAX], unsigned size) {
+  bool swapped = true;
+  while (swapped) {
+    swapped = false;
+    for (unsigned i = 1; i < size; i++) {
+      if (Buf[i] < Buf[i-1]) {
+	swap(Buf, i, i-1);
+	swapped = true;
+      }
+    }
+  }
+}
+
+// Note ExtAttr is the inlined export set of attribs
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define noundef i32 @"?RemoveDupes@@YAIY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[ExtAttr:\#[0-9]+]]
+// CHECK: ret i32
+// Sort Buf and remove any duplicate values
+// returns the number of values left
+export
+unsigned RemoveDupes(unsigned Buf[MAX], unsigned size) {
+  BubbleSort(Buf, size);
+  unsigned insertPt = 0;
+  for (unsigned i = 1; i < size; i++) {
+    if (Buf[i] == Buf[i-1])
+      insertPt++;
+    else
+      Buf[insertPt] = Buf[i];
+  }
+  return insertPt;
+}
+
+
+RWBuffer<unsigned> Indices;
+
+// The mangled version of main only remains without inlining
+// because it has internal linkage from the start
+// Note main functions get the norecurse attrib, which IntAttr reflects
+// NOINLINE: Function Attrs: alwaysinline
+// NOINLINE: define internal void @"?main@@YAXI@Z"(i32 noundef %GI) [[IntAttr]]
+// NOINLINE: ret void
+
+// The unmangled version is not inlined, EntryAttr reflects that
+// CHECK: Function Attrs: convergent norecurse
+// CHECK: define void @main() [[EntryAttr:\#[0-9]+]]
+// Make sure function calls are inlined when AlwaysInline is run
+// This only leaves calls to llvm. intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+[numthreads(1,1,1)]
+[shader("compute")]
+void main(unsigned int GI : SV_GroupIndex) {
+  unsigned tmpIndices[MAX];
+  if (GI > MAX) return;
+  for (unsigned i = 1; i < GI; i++)
+    tmpIndices[i] = Indices[i];
+  RemoveDupes(tmpIndices, GI);
+  for (unsigned i = 1; i < GI; i++)
+    tmpIndices[i] = Indices[i];
+}
+
+// The mangled version of main only remains without inlining
+// because it has internal linkage from the start
+// Note main functions get the norecurse attrib, which IntAttr reflects
+// NOINLINE: Function Attrs: alwaysinline
+// NOINLINE: define internal void @"?main10@@YAXXZ"() [[IntAttr]]
+// NOINLINE: ret void
+
+// The unmangled version is not inlined, EntryAttr reflects that
+// CHECK: Function Attrs: convergent norecurse
+// CHECK: define void @main10() [[EntryAttr]]
+// Make sure function calls are inlined when AlwaysInline is run
+// This only leaves calls to llvm. intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+[numthreads(1,1,1)]
+[shader("compute")]
+void main10() {
+  main(10);
+}
+
+// CHECK: attributes [[IntAttr]] = {{.*}} alwaysinline
+// CHECK: attributes [[ExtAttr]] = {{.*}} alwaysinline
+// CHECK-NOT: attributes [[EntryAttr]] = {{.*}} alwaysinline

@llvmbot
Copy link
Collaborator

llvmbot commented Aug 29, 2024

@llvm/pr-subscribers-hlsl

Author: Greg Roth (pow2clk)

Changes

HLSL inlines all its functions by default. This uses the alwaysinline attribute to force that in the corresponding pass for user functions by default and overrides the default noinline of some implicit functions. This makes an instance of explicit inlining for buffer subscripts unnecessary.

Adds tests for function and constructor inlining and augments some existing tests to verify correct inlining of implicitly created functions as well.

incidentally restore RUN line that I believe was mistakenly removed as part of #88918

fixes #89282


Full diff: https://github.com/llvm/llvm-project/pull/106588.diff

10 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+14-3)
  • (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+2-2)
  • (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (-2)
  • (modified) clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl (+21-10)
  • (modified) clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl (+19-4)
  • (modified) clang/test/CodeGenHLSL/GlobalDestructors.hlsl (+31-20)
  • (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl (+1)
  • (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl (+3-2)
  • (added) clang/test/CodeGenHLSL/inline-constructors.hlsl (+74)
  • (added) clang/test/CodeGenHLSL/inline-functions.hlsl (+114)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 4bd7b6ba58de0d..24d126ced0d9f7 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -414,9 +414,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
 
 void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
                                               llvm::Function *Fn) {
-  if (FD->isInExportDeclContext()) {
-    const StringRef ExportAttrKindStr = "hlsl.export";
-    Fn->addFnAttr(ExportAttrKindStr);
+  if (FD) { // "explicit" functions with declarations
+    if (FD->isInExportDeclContext()) {
+      const StringRef ExportAttrKindStr = "hlsl.export";
+      Fn->addFnAttr(ExportAttrKindStr);
+    }
+    // Respect noinline if the explicit functions use it
+    // otherwise default to alwaysinline
+    if (!Fn->hasFnAttribute(Attribute::NoInline))
+      Fn->addFnAttr(llvm::Attribute::AlwaysInline);
+  } else { // "implicit" autogenerated functions with no declaration
+    // Implicit functions might get marked as noinline by default
+    // but we override that for HLSL
+    Fn->removeFnAttr(Attribute::NoInline);
+    Fn->addFnAttr(Attribute::AlwaysInline);
   }
 }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a5747283e98058..aceeed0e66d130 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1239,9 +1239,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   if (getLangOpts().OpenMP && CurCodeDecl)
     CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
 
-  if (FD && getLangOpts().HLSL) {
+  if (getLangOpts().HLSL) {
     // Handle emitting HLSL entry functions.
-    if (FD->hasAttr<HLSLShaderAttr>()) {
+    if (FD && FD->hasAttr<HLSLShaderAttr>()) {
       CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
     }
     CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 9aacbe4ad9548e..0a534d94192560 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -290,8 +290,6 @@ struct BuiltinTypeDeclBuilder {
                                              SourceLocation()));
     MethodDecl->setLexicalDeclContext(Record);
     MethodDecl->setAccess(AccessSpecifier::AS_public);
-    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
-        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
     Record->addDecl(MethodDecl);
 
     return *this;
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
index f954c9d2f029f2..b39311ad67cd62 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
 
 int i;
 
@@ -7,7 +8,7 @@ __attribute__((constructor)) void call_me_first(void) {
 }
 
 __attribute__((constructor)) void then_call_me(void) {
-  i = 12;
+  i = 13;
 }
 
 __attribute__((destructor)) void call_me_last(void) {
@@ -21,11 +22,21 @@ void main(unsigned GI : SV_GroupIndex) {}
 // CHECK-NOT:@llvm.global_ctors
 // CHECK-NOT:@llvm.global_dtors
 
-//CHECK: define void @main()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @"?call_me_first@@YAXXZ"()
-//CHECK-NEXT:   call void @"?then_call_me@@YAXXZ"()
-//CHECK-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-//CHECK-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
-//CHECK-NEXT:   call void @"?call_me_last@@YAXXZ"(
-//CHECK-NEXT:   ret void
+// CHECK: define void @main()
+// CHECK-NEXT: entry:
+// Verify function constructors are emitted
+// NOINLINE-NEXT:   call void @"?call_me_first@@YAXXZ"()
+// NOINLINE-NEXT:   call void @"?then_call_me@@YAXXZ"()
+// NOINLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
+// NOINLINE-NEXT:   call void @"?call_me_last@@YAXXZ"(
+// NOINLINE-NEXT:   ret void
+
+// Verify constructor calls are inlined when AlwaysInline is run
+// INLINE-NEXT:   alloca
+// INLINE-NEXT:   store i32 12
+// INLINE-NEXT:   store i32 13
+// INLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// INLINE-NEXT:   store i32 %
+// INLINE-NEXT:   store i32 0
+// INLINE:   ret void
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index 2c5c4e19c3296d..78f6475462bc47 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
 
 // Make sure global variable for ctors exist for lib profile.
 // CHECK:@llvm.global_ctors
@@ -11,7 +12,11 @@ void FirstEntry() {}
 
 // CHECK: define void @FirstEntry()
 // CHECK-NEXT: entry:
-// CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @"?FirstEntry@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
 
 [shader("compute")]
 [numthreads(1,1,1)]
@@ -19,5 +24,15 @@ void SecondEntry() {}
 
 // CHECK: define void @SecondEntry()
 // CHECK-NEXT: entry:
-// CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
-// CHECK-NEXT:   call void @"?SecondEntry@@YAXXZ"()
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @"?SecondEntry@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+
+// Verify the constructor is alwaysinline
+// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
+// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[IntAttr:\#[0-9]+]]
+
+// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
diff --git a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
index 24c3c039fc6192..ea28354222f885 100644
--- a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
@@ -1,10 +1,18 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,CHECK
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
 
-// Make sure global variable for dtors exist for lib profile.
+// Tests that constructors and destructors are appropriately generated for globals
+// and that their calls are inlined when AlwaysInline is run
+// but global variables are retained for the library profiles
+
+// Make sure global variable for ctors/dtors exist for lib profile.
+// LIB:@llvm.global_ctors
 // LIB:@llvm.global_dtors
-// Make sure global variable for dtors removed for compute profile.
-// CS-NOT:llvm.global_dtors
+// Make sure global variable for ctors/dtors removed for compute profile.
+// CS-NOT:@llvm.global_ctors
+// CS-NOT:@llvm.global_dtors
 
 struct Tail {
   Tail() {
@@ -46,22 +54,25 @@ void main(unsigned GI : SV_GroupIndex) {
   Wag();
 }
 
-// Make sure global variable for ctors/dtors removed.
-// CHECK-NOT:@llvm.global_ctors
-// CHECK-NOT:@llvm.global_dtors
-//CHECK:      define void @main()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
-//CHECK-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-//CHECK-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
-//CHECK-NEXT:   call void @_GLOBAL__D_a()
-//CHECK-NEXT:   ret void
+// CHECK:      define void @main()
+// CHECK-NEXT: entry:
+// Verify destructor is emitted
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
+// NOINLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
+// NOINLINE-NEXT:   call void @_GLOBAL__D_a()
+// NOINLINE-NEXT:   ret void
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// INLINE:   ret void
 
 // This is really just a sanity check I needed for myself to verify that
 // function scope static variables also get destroyed properly.
 
-//CHECK: define internal void @_GLOBAL__D_a()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
-//CHECK-NEXT:   call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
-//CHECK-NEXT:   ret void
+// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
+// NOINLINE-NEXT: entry:
+// NOINLINE-NEXT:   call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
+// NOINLINE-NEXT:   call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
+// NOINLINE-NEXT:   ret void
+
+// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index baddfcf2cf1d52..174f4c3eaaad26 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
 
 RWBuffer<float> Buf;
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
index da8a1e538ec5e7..2a350c1619bd6e 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
@@ -11,6 +11,7 @@ void main(unsigned GI : SV_GroupIndex) {
 // Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
 // and confusing to follow so the match here is pretty weak.
 
-// CHECK: define internal void @"?main@@YAXI@Z"
-// CHECK-NOT: call
+// CHECK: define void @main()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// CHECK-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
 // CHECK: ret void
diff --git a/clang/test/CodeGenHLSL/inline-constructors.hlsl b/clang/test/CodeGenHLSL/inline-constructors.hlsl
new file mode 100644
index 00000000000000..40c7a42bdc262e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/inline-constructors.hlsl
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
+
+// Tests that implicit contstructor calls for user classes will always be inlined.
+
+struct Weed {
+  Weed() {Count += 1;}
+  [[maybe_unused]] void pull() {Count--;}
+  static int weedCount() { return Count; }
+private:
+  static int Count;
+
+} YardWeeds;
+
+int Weed::Count = 1; // It begins. . .
+
+struct Kitty {
+  unsigned burrsInFur;
+
+  Kitty() {
+    burrsInFur = 0;
+  }
+
+  void wanderInYard(int hours) {
+    burrsInFur = hours*Weed::weedCount()/8;
+  }
+
+  void lick() {
+    if(burrsInFur) {
+      burrsInFur--;
+      Weed w;
+    }
+  }
+
+} Nion;
+
+void NionsDay(int hours) {
+  static Kitty Nion;
+  Nion.wanderInYard(hours);
+  while(Nion.burrsInFur) Nion.lick();
+}
+
+// CHECK:      define void @main()
+// CHECK-NEXT: entry:
+// Verify constructor is emitted
+// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
+// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:    call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK:         ret void
+[shader("compute")]
+[numthreads(1,1,1)]
+void main(unsigned GI : SV_GroupIndex) {
+  NionsDay(10);
+}
+
+
+// CHECK:      define void @rainyMain()
+// CHECK-NEXT: entry:
+// Verify constructor is emitted
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_inline_constructors.hlsl()
+// NOINLINE-NEXT:   call void @"?rainyMain@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:      call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK:           ret void
+[shader("compute")]
+[numthreads(1,1,1)]
+void rainyMain() {
+  NionsDay(1);
+}
+
diff --git a/clang/test/CodeGenHLSL/inline-functions.hlsl b/clang/test/CodeGenHLSL/inline-functions.hlsl
new file mode 100644
index 00000000000000..9c00e096a9eef2
--- /dev/null
+++ b/clang/test/CodeGenHLSL/inline-functions.hlsl
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.0-compute %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.0-compute %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+
+// Tests that user functions will always be inlined.
+// This includes exported functions and mangled entry point implementation functions.
+// The unmangled entry functions must not be alwaysinlined.
+
+#define MAX 100
+
+float nums[MAX];
+
+// Verify that all functions have the alwaysinline attribute
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define void @"?swap@@YAXY0GE@III@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %ix1, i32 noundef %ix2) [[IntAttr:\#[0-9]+]]
+// CHECK: ret void
+// Swap the values of Buf at indices ix1 and ix2
+void swap(unsigned Buf[MAX], unsigned ix1, unsigned ix2) {
+  float tmp = Buf[ix1];
+  Buf[ix1] = Buf[ix2];
+  Buf[ix2] = tmp;
+}
+
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define void @"?BubbleSort@@YAXY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[IntAttr]]
+// CHECK: ret void
+// Inefficiently sort Buf in place
+void BubbleSort(unsigned Buf[MAX], unsigned size) {
+  bool swapped = true;
+  while (swapped) {
+    swapped = false;
+    for (unsigned i = 1; i < size; i++) {
+      if (Buf[i] < Buf[i-1]) {
+	swap(Buf, i, i-1);
+	swapped = true;
+      }
+    }
+  }
+}
+
+// Note ExtAttr is the inlined export set of attribs
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define noundef i32 @"?RemoveDupes@@YAIY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[ExtAttr:\#[0-9]+]]
+// CHECK: ret i32
+// Sort Buf and remove any duplicate values
+// returns the number of values left
+export
+unsigned RemoveDupes(unsigned Buf[MAX], unsigned size) {
+  BubbleSort(Buf, size);
+  unsigned insertPt = 0;
+  for (unsigned i = 1; i < size; i++) {
+    if (Buf[i] == Buf[i-1])
+      insertPt++;
+    else
+      Buf[insertPt] = Buf[i];
+  }
+  return insertPt;
+}
+
+
+RWBuffer<unsigned> Indices;
+
+// The mangled version of main only remains without inlining
+// because it has internal linkage from the start
+// Note main functions get the norecurse attrib, which IntAttr reflects
+// NOINLINE: Function Attrs: alwaysinline
+// NOINLINE: define internal void @"?main@@YAXI@Z"(i32 noundef %GI) [[IntAttr]]
+// NOINLINE: ret void
+
+// The unmangled version is not inlined, EntryAttr reflects that
+// CHECK: Function Attrs: convergent norecurse
+// CHECK: define void @main() [[EntryAttr:\#[0-9]+]]
+// Make sure function calls are inlined when AlwaysInline is run
+// This only leaves calls to llvm. intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+[numthreads(1,1,1)]
+[shader("compute")]
+void main(unsigned int GI : SV_GroupIndex) {
+  unsigned tmpIndices[MAX];
+  if (GI > MAX) return;
+  for (unsigned i = 1; i < GI; i++)
+    tmpIndices[i] = Indices[i];
+  RemoveDupes(tmpIndices, GI);
+  for (unsigned i = 1; i < GI; i++)
+    tmpIndices[i] = Indices[i];
+}
+
+// The mangled version of main only remains without inlining
+// because it has internal linkage from the start
+// Note main functions get the norecurse attrib, which IntAttr reflects
+// NOINLINE: Function Attrs: alwaysinline
+// NOINLINE: define internal void @"?main10@@YAXXZ"() [[IntAttr]]
+// NOINLINE: ret void
+
+// The unmangled version is not inlined, EntryAttr reflects that
+// CHECK: Function Attrs: convergent norecurse
+// CHECK: define void @main10() [[EntryAttr]]
+// Make sure function calls are inlined when AlwaysInline is run
+// This only leaves calls to llvm. intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+[numthreads(1,1,1)]
+[shader("compute")]
+void main10() {
+  main(10);
+}
+
+// CHECK: attributes [[IntAttr]] = {{.*}} alwaysinline
+// CHECK: attributes [[ExtAttr]] = {{.*}} alwaysinline
+// CHECK-NOT: attributes [[EntryAttr]] = {{.*}} alwaysinline

@llvmbot
Copy link
Collaborator

llvmbot commented Aug 29, 2024

@llvm/pr-subscribers-clang-codegen

Author: Greg Roth (pow2clk)

Changes

HLSL inlines all its functions by default. This uses the alwaysinline attribute to force that in the corresponding pass for user functions by default and overrides the default noinline of some implicit functions. This makes an instance of explicit inlining for buffer subscripts unnecessary.

Adds tests for function and constructor inlining and augments some existing tests to verify correct inlining of implicitly created functions as well.

incidentally restore RUN line that I believe was mistakenly removed as part of #88918

fixes #89282


Full diff: https://github.com/llvm/llvm-project/pull/106588.diff

10 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+14-3)
  • (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+2-2)
  • (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (-2)
  • (modified) clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl (+21-10)
  • (modified) clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl (+19-4)
  • (modified) clang/test/CodeGenHLSL/GlobalDestructors.hlsl (+31-20)
  • (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl (+1)
  • (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl (+3-2)
  • (added) clang/test/CodeGenHLSL/inline-constructors.hlsl (+74)
  • (added) clang/test/CodeGenHLSL/inline-functions.hlsl (+114)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 4bd7b6ba58de0d..24d126ced0d9f7 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -414,9 +414,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
 
 void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
                                               llvm::Function *Fn) {
-  if (FD->isInExportDeclContext()) {
-    const StringRef ExportAttrKindStr = "hlsl.export";
-    Fn->addFnAttr(ExportAttrKindStr);
+  if (FD) { // "explicit" functions with declarations
+    if (FD->isInExportDeclContext()) {
+      const StringRef ExportAttrKindStr = "hlsl.export";
+      Fn->addFnAttr(ExportAttrKindStr);
+    }
+    // Respect noinline if the explicit functions use it
+    // otherwise default to alwaysinline
+    if (!Fn->hasFnAttribute(Attribute::NoInline))
+      Fn->addFnAttr(llvm::Attribute::AlwaysInline);
+  } else { // "implicit" autogenerated functions with no declaration
+    // Implicit functions might get marked as noinline by default
+    // but we override that for HLSL
+    Fn->removeFnAttr(Attribute::NoInline);
+    Fn->addFnAttr(Attribute::AlwaysInline);
   }
 }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a5747283e98058..aceeed0e66d130 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1239,9 +1239,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
   if (getLangOpts().OpenMP && CurCodeDecl)
     CGM.getOpenMPRuntime().emitFunctionProlog(*this, CurCodeDecl);
 
-  if (FD && getLangOpts().HLSL) {
+  if (getLangOpts().HLSL) {
     // Handle emitting HLSL entry functions.
-    if (FD->hasAttr<HLSLShaderAttr>()) {
+    if (FD && FD->hasAttr<HLSLShaderAttr>()) {
       CGM.getHLSLRuntime().emitEntryFunction(FD, Fn);
     }
     CGM.getHLSLRuntime().setHLSLFunctionAttributes(FD, Fn);
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index 9aacbe4ad9548e..0a534d94192560 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -290,8 +290,6 @@ struct BuiltinTypeDeclBuilder {
                                              SourceLocation()));
     MethodDecl->setLexicalDeclContext(Record);
     MethodDecl->setAccess(AccessSpecifier::AS_public);
-    MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
-        AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
     Record->addDecl(MethodDecl);
 
     return *this;
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
index f954c9d2f029f2..b39311ad67cd62 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorFunction.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
 
 int i;
 
@@ -7,7 +8,7 @@ __attribute__((constructor)) void call_me_first(void) {
 }
 
 __attribute__((constructor)) void then_call_me(void) {
-  i = 12;
+  i = 13;
 }
 
 __attribute__((destructor)) void call_me_last(void) {
@@ -21,11 +22,21 @@ void main(unsigned GI : SV_GroupIndex) {}
 // CHECK-NOT:@llvm.global_ctors
 // CHECK-NOT:@llvm.global_dtors
 
-//CHECK: define void @main()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @"?call_me_first@@YAXXZ"()
-//CHECK-NEXT:   call void @"?then_call_me@@YAXXZ"()
-//CHECK-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-//CHECK-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
-//CHECK-NEXT:   call void @"?call_me_last@@YAXXZ"(
-//CHECK-NEXT:   ret void
+// CHECK: define void @main()
+// CHECK-NEXT: entry:
+// Verify function constructors are emitted
+// NOINLINE-NEXT:   call void @"?call_me_first@@YAXXZ"()
+// NOINLINE-NEXT:   call void @"?then_call_me@@YAXXZ"()
+// NOINLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
+// NOINLINE-NEXT:   call void @"?call_me_last@@YAXXZ"(
+// NOINLINE-NEXT:   ret void
+
+// Verify constructor calls are inlined when AlwaysInline is run
+// INLINE-NEXT:   alloca
+// INLINE-NEXT:   store i32 12
+// INLINE-NEXT:   store i32 13
+// INLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// INLINE-NEXT:   store i32 %
+// INLINE-NEXT:   store i32 0
+// INLINE:   ret void
diff --git a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
index 2c5c4e19c3296d..78f6475462bc47 100644
--- a/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,INLINE
 
 // Make sure global variable for ctors exist for lib profile.
 // CHECK:@llvm.global_ctors
@@ -11,7 +12,11 @@ void FirstEntry() {}
 
 // CHECK: define void @FirstEntry()
 // CHECK-NEXT: entry:
-// CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @"?FirstEntry@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
 
 [shader("compute")]
 [numthreads(1,1,1)]
@@ -19,5 +24,15 @@ void SecondEntry() {}
 
 // CHECK: define void @SecondEntry()
 // CHECK-NEXT: entry:
-// CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
-// CHECK-NEXT:   call void @"?SecondEntry@@YAXXZ"()
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl()
+// NOINLINE-NEXT:   call void @"?SecondEntry@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+
+// Verify the constructor is alwaysinline
+// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
+// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[IntAttr:\#[0-9]+]]
+
+// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
diff --git a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
index 24c3c039fc6192..ea28354222f885 100644
--- a/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
+++ b/clang/test/CodeGenHLSL/GlobalDestructors.hlsl
@@ -1,10 +1,18 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,CHECK
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=CS,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s --check-prefixes=LIB,NOINLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -O0 %s -o - | FileCheck %s --check-prefixes=INLINE,CHECK
 
-// Make sure global variable for dtors exist for lib profile.
+// Tests that constructors and destructors are appropriately generated for globals
+// and that their calls are inlined when AlwaysInline is run
+// but global variables are retained for the library profiles
+
+// Make sure global variable for ctors/dtors exist for lib profile.
+// LIB:@llvm.global_ctors
 // LIB:@llvm.global_dtors
-// Make sure global variable for dtors removed for compute profile.
-// CS-NOT:llvm.global_dtors
+// Make sure global variable for ctors/dtors removed for compute profile.
+// CS-NOT:@llvm.global_ctors
+// CS-NOT:@llvm.global_dtors
 
 struct Tail {
   Tail() {
@@ -46,22 +54,25 @@ void main(unsigned GI : SV_GroupIndex) {
   Wag();
 }
 
-// Make sure global variable for ctors/dtors removed.
-// CHECK-NOT:@llvm.global_ctors
-// CHECK-NOT:@llvm.global_dtors
-//CHECK:      define void @main()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
-//CHECK-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
-//CHECK-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
-//CHECK-NEXT:   call void @_GLOBAL__D_a()
-//CHECK-NEXT:   ret void
+// CHECK:      define void @main()
+// CHECK-NEXT: entry:
+// Verify destructor is emitted
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_GlobalDestructors.hlsl()
+// NOINLINE-NEXT:   %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT:   call void @"?main@@YAXI@Z"(i32 %0)
+// NOINLINE-NEXT:   call void @_GLOBAL__D_a()
+// NOINLINE-NEXT:   ret void
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// INLINE:   ret void
 
 // This is really just a sanity check I needed for myself to verify that
 // function scope static variables also get destroyed properly.
 
-//CHECK: define internal void @_GLOBAL__D_a()
-//CHECK-NEXT: entry:
-//CHECK-NEXT:   call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
-//CHECK-NEXT:   call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
-//CHECK-NEXT:   ret void
+// NOINLINE: define internal void @_GLOBAL__D_a() [[IntAttr:\#[0-9]+]]
+// NOINLINE-NEXT: entry:
+// NOINLINE-NEXT:   call void @"??1Tail@@QAA@XZ"(ptr @"?T@?1??Wag@@YAXXZ@4UTail@@A")
+// NOINLINE-NEXT:   call void @"??1Pupper@@QAA@XZ"(ptr @"?GlobalPup@@3UPupper@@A")
+// NOINLINE-NEXT:   ret void
+
+// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index baddfcf2cf1d52..174f4c3eaaad26 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -1,3 +1,4 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK-SPIRV
 
 RWBuffer<float> Buf;
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
index da8a1e538ec5e7..2a350c1619bd6e 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
@@ -11,6 +11,7 @@ void main(unsigned GI : SV_GroupIndex) {
 // Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
 // and confusing to follow so the match here is pretty weak.
 
-// CHECK: define internal void @"?main@@YAXI@Z"
-// CHECK-NOT: call
+// CHECK: define void @main()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// CHECK-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
 // CHECK: ret void
diff --git a/clang/test/CodeGenHLSL/inline-constructors.hlsl b/clang/test/CodeGenHLSL/inline-constructors.hlsl
new file mode 100644
index 00000000000000..40c7a42bdc262e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/inline-constructors.hlsl
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -std=hlsl202x -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=CHECK,INLINE
+
+// Tests that implicit contstructor calls for user classes will always be inlined.
+
+struct Weed {
+  Weed() {Count += 1;}
+  [[maybe_unused]] void pull() {Count--;}
+  static int weedCount() { return Count; }
+private:
+  static int Count;
+
+} YardWeeds;
+
+int Weed::Count = 1; // It begins. . .
+
+struct Kitty {
+  unsigned burrsInFur;
+
+  Kitty() {
+    burrsInFur = 0;
+  }
+
+  void wanderInYard(int hours) {
+    burrsInFur = hours*Weed::weedCount()/8;
+  }
+
+  void lick() {
+    if(burrsInFur) {
+      burrsInFur--;
+      Weed w;
+    }
+  }
+
+} Nion;
+
+void NionsDay(int hours) {
+  static Kitty Nion;
+  Nion.wanderInYard(hours);
+  while(Nion.burrsInFur) Nion.lick();
+}
+
+// CHECK:      define void @main()
+// CHECK-NEXT: entry:
+// Verify constructor is emitted
+// NOINLINE-NEXT: call void @_GLOBAL__sub_I_inline_constructors.hlsl()
+// NOINLINE-NEXT: %0 = call i32 @llvm.dx.flattened.thread.id.in.group()
+// NOINLINE-NEXT: call void @"?main@@YAXI@Z"(i32 %0)
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:    call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK:         ret void
+[shader("compute")]
+[numthreads(1,1,1)]
+void main(unsigned GI : SV_GroupIndex) {
+  NionsDay(10);
+}
+
+
+// CHECK:      define void @rainyMain()
+// CHECK-NEXT: entry:
+// Verify constructor is emitted
+// NOINLINE-NEXT:   call void @_GLOBAL__sub_I_inline_constructors.hlsl()
+// NOINLINE-NEXT:   call void @"?rainyMain@@YAXXZ"()
+// Verify inlining leaves only calls to "llvm." intrinsics
+// INLINE-NOT:      call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK:           ret void
+[shader("compute")]
+[numthreads(1,1,1)]
+void rainyMain() {
+  NionsDay(1);
+}
+
diff --git a/clang/test/CodeGenHLSL/inline-functions.hlsl b/clang/test/CodeGenHLSL/inline-functions.hlsl
new file mode 100644
index 00000000000000..9c00e096a9eef2
--- /dev/null
+++ b/clang/test/CodeGenHLSL/inline-functions.hlsl
@@ -0,0 +1,114 @@
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.3-library %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.0-compute %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE
+// RUN: %clang_cc1 -x hlsl -triple  dxil-pc-shadermodel6.0-compute %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE
+
+// Tests that user functions will always be inlined.
+// This includes exported functions and mangled entry point implementation functions.
+// The unmangled entry functions must not be alwaysinlined.
+
+#define MAX 100
+
+float nums[MAX];
+
+// Verify that all functions have the alwaysinline attribute
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define void @"?swap@@YAXY0GE@III@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %ix1, i32 noundef %ix2) [[IntAttr:\#[0-9]+]]
+// CHECK: ret void
+// Swap the values of Buf at indices ix1 and ix2
+void swap(unsigned Buf[MAX], unsigned ix1, unsigned ix2) {
+  float tmp = Buf[ix1];
+  Buf[ix1] = Buf[ix2];
+  Buf[ix2] = tmp;
+}
+
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define void @"?BubbleSort@@YAXY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[IntAttr]]
+// CHECK: ret void
+// Inefficiently sort Buf in place
+void BubbleSort(unsigned Buf[MAX], unsigned size) {
+  bool swapped = true;
+  while (swapped) {
+    swapped = false;
+    for (unsigned i = 1; i < size; i++) {
+      if (Buf[i] < Buf[i-1]) {
+	swap(Buf, i, i-1);
+	swapped = true;
+      }
+    }
+  }
+}
+
+// Note ExtAttr is the inlined export set of attribs
+// CHECK: Function Attrs: alwaysinline
+// CHECK: define noundef i32 @"?RemoveDupes@@YAIY0GE@II@Z"(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[ExtAttr:\#[0-9]+]]
+// CHECK: ret i32
+// Sort Buf and remove any duplicate values
+// returns the number of values left
+export
+unsigned RemoveDupes(unsigned Buf[MAX], unsigned size) {
+  BubbleSort(Buf, size);
+  unsigned insertPt = 0;
+  for (unsigned i = 1; i < size; i++) {
+    if (Buf[i] == Buf[i-1])
+      insertPt++;
+    else
+      Buf[insertPt] = Buf[i];
+  }
+  return insertPt;
+}
+
+
+RWBuffer<unsigned> Indices;
+
+// The mangled version of main only remains without inlining
+// because it has internal linkage from the start
+// Note main functions get the norecurse attrib, which IntAttr reflects
+// NOINLINE: Function Attrs: alwaysinline
+// NOINLINE: define internal void @"?main@@YAXI@Z"(i32 noundef %GI) [[IntAttr]]
+// NOINLINE: ret void
+
+// The unmangled version is not inlined, EntryAttr reflects that
+// CHECK: Function Attrs: convergent norecurse
+// CHECK: define void @main() [[EntryAttr:\#[0-9]+]]
+// Make sure function calls are inlined when AlwaysInline is run
+// This only leaves calls to llvm. intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+[numthreads(1,1,1)]
+[shader("compute")]
+void main(unsigned int GI : SV_GroupIndex) {
+  unsigned tmpIndices[MAX];
+  if (GI > MAX) return;
+  for (unsigned i = 1; i < GI; i++)
+    tmpIndices[i] = Indices[i];
+  RemoveDupes(tmpIndices, GI);
+  for (unsigned i = 1; i < GI; i++)
+    tmpIndices[i] = Indices[i];
+}
+
+// The mangled version of main only remains without inlining
+// because it has internal linkage from the start
+// Note main functions get the norecurse attrib, which IntAttr reflects
+// NOINLINE: Function Attrs: alwaysinline
+// NOINLINE: define internal void @"?main10@@YAXXZ"() [[IntAttr]]
+// NOINLINE: ret void
+
+// The unmangled version is not inlined, EntryAttr reflects that
+// CHECK: Function Attrs: convergent norecurse
+// CHECK: define void @main10() [[EntryAttr]]
+// Make sure function calls are inlined when AlwaysInline is run
+// This only leaves calls to llvm. intrinsics
+// INLINE-NOT:   call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
+// CHECK: ret void
+
+[numthreads(1,1,1)]
+[shader("compute")]
+void main10() {
+  main(10);
+}
+
+// CHECK: attributes [[IntAttr]] = {{.*}} alwaysinline
+// CHECK: attributes [[ExtAttr]] = {{.*}} alwaysinline
+// CHECK-NOT: attributes [[EntryAttr]] = {{.*}} alwaysinline

Previously, the alwaysinline attribute was set for the RWBuffer
subscript operator as soon as it was created. Since they are all
in a common place now, that setting was redundant, but it does mean
that it won't show up in the AST
} else { // "implicit" autogenerated functions with no declaration
// Implicit functions might get marked as noinline by default
// but we override that for HLSL
Fn->removeFnAttr(Attribute::NoInline);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which auto-generated functions are getting noinline attached to them? Do you know where that is happening?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is applied here:

if (!F->hasFnAttribute(llvm::Attribute::AlwaysInline) &&
CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)
B.addAttribute(llvm::Attribute::NoInline);

on functions not explicitly created by the user, but generated to construct or destruct global/static local variables as well as the global functions that call each of these at the top and bottom of the entry function.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me like it might make more sense to change that condition to not do that for HLSL rather than to modify the IR after we generate it incorrectly.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying not to litter too many if(getLangOpts().HLSL) conditionals throughout the code. Something similar to this is done in a few places for OpenMP. I don't feel strongly about it though. It's trivial to drop an if HLSL conditional there.

@@ -290,8 +290,6 @@ struct BuiltinTypeDeclBuilder {
SourceLocation()));
MethodDecl->setLexicalDeclContext(Record);
MethodDecl->setAccess(AccessSpecifier::AS_public);
MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was it necessary to remove this? I think we want this because we'll want these calls inlined even in separate compilation cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't necessary so much as redundant for the compilations I tested and actually gets applied to the LLVM function representation after that set by setHLSLFunctionAttributes.

How would I test a relevant separate compilation case?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't really have a workflow in Clang implemented yet for separate compilation. The analog in DXC would be something like -T lib_6_x -default-linkage=external. In that case we would still want these functions to be inlined, and we can accomplish that with this attribute.

Copy link

@pow3clk pow3clk Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that involve generating just AST then? The DXC analog would still be generating LLVM IR, which this setting would catch and does for the inline-constructors.hlsl test among others.

Restore additional alwaysinline setting for RWBuffer subscripts

Add HLSL check to prevent marking autogenerated functions as noinline
Copy link

@pow3clk pow3clk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my laptop account. I assure you it's who you think it is.

} else { // "implicit" autogenerated functions with no declaration
// Implicit functions might get marked as noinline by default
// but we override that for HLSL
Fn->removeFnAttr(Attribute::NoInline);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying not to litter too many if(getLangOpts().HLSL) conditionals throughout the code. Something similar to this is done in a few places for OpenMP. I don't feel strongly about it though. It's trivial to drop an if HLSL conditional there.

@@ -290,8 +290,6 @@ struct BuiltinTypeDeclBuilder {
SourceLocation()));
MethodDecl->setLexicalDeclContext(Record);
MethodDecl->setAccess(AccessSpecifier::AS_public);
MethodDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
Copy link

@pow3clk pow3clk Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that involve generating just AST then? The DXC analog would still be generating LLVM IR, which this setting would catch and does for the inline-constructors.hlsl test among others.

For whatever reason a function might have noinline, if we try to set
alwaysinline, we get an incompatible attribute error. This avoids
that in any case.
Copy link

github-actions bot commented Sep 4, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

clang/test/CodeGenHLSL/inline-constructors.hlsl Outdated Show resolved Hide resolved
clang/test/CodeGenHLSL/inline-functions.hlsl Outdated Show resolved Hide resolved
clang/lib/CodeGen/CodeGenFunction.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Outdated Show resolved Hide resolved
Move all logic into SetLLVMFunctionAttributesForDefinition where
most inlining attribute calculations are done. The way autogenerated
init functions and user functions were created meant that this was hit
at different times for each relative to setHLSLFunctionAttributes.
Instead of trying to resolve that fundamental issue or work around it,
better to keep all the setting in the same place so it doesn't matter
where it is called relative to function body creation.

This required making exceptions for entry functions as they will get
attributes from this code as well and we want it to not be always
inlined and receive the relevant optimization attributes that allows.
Copy link
Contributor Author

@pow2clk pow2clk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Damyan!

clang/lib/CodeGen/CodeGenFunction.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Outdated Show resolved Hide resolved
clang/test/CodeGenHLSL/inline-functions.hlsl Outdated Show resolved Hide resolved
@damyanp damyanp self-requested a review September 9, 2024 22:14
@pow2clk pow2clk requested a review from pow3clk September 9, 2024 22:14
@@ -2471,11 +2471,14 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
B.addAttribute(llvm::Attribute::StackProtectReq);

if (!D) {
// HLSL functions must always be inlined
if (getLangOpts().HLSL && !F->hasFnAttribute("hlsl.shader"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we put noinline on the entry function? Does that simplify this logic? Since we'll also at some point need to support the noinline keyword we'll need to be checking that attribute somewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In earlier discussion, we resolved to make this the default and not worry about noinline as of yet seeing as there are a lot of issues to resolve before that can work properly. In a previous version, I was forced to check for noinline as it was a sign that a function had passed through this function, but my preference is to not respect it until we've worked out the issues that prevent it from working right.

It wouldn't simplify the logic since the entry function doesn't get marked inline until it is passed into this function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an update. As a result of the waning minutes of a design discussion, we resolved to produce a warning when users apply noinline and explicitly set noinline for the outermost entry function which would allow checking for that in place of hlsl.shader here, which might allow graceful resolution of any other functions that happen to get it applied here which we could have an assert for.

Copy link
Contributor

@damyanp damyanp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but would be good to get a review from someone more knowledgeable in the area than I am.

Set noinline explicitly on the outermost entry function and use that
attribute to decide to apply alwaysinline.
Generate a warning and ignore user-specified noinline

Incidentally tidy up some RUN lines
if (D->hasAttr<NoInlineAttr>())
getDiags().Report(D->getLocation(),
diag::warn_unsupported_attribute_ignored)
<< "noinline" << "HLSL";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we warning on this? Does the Clang implementation not work?

If we're going to warn on this, it needs to be in Sema not CodeGen!

@@ -0,0 +1,13 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm-only %s -verify
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not need to emit IR to test a warning. This should work with -fsyntax-only or without the -emit-llvm-only flag.

@pow2clk pow2clk merged commit a729e70 into llvm:main Sep 17, 2024
8 checks passed
@pow2clk pow2clk deleted the hlsl_alwaysinline branch September 17, 2024 17:09
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 17, 2024

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-sie-ubuntu-fast running on sie-linux-worker while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/7235

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -cc1 -internal-isystem /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -cc1 -internal-isystem /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
�[1m/home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: �[0m�[0;1;31merror: �[0m�[1mCHECK: expected string not found in input
�[0m// CHECK: define internal void @"?main@@YAXI@Z"
�[0;1;32m          ^
�[0m�[1m<stdin>:1:1: �[0m�[0;1;30mnote: �[0m�[1mscanning from here
�[0m; ModuleID = '/home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
�[0;1;32m^
�[0m�[1m<stdin>:12:1: �[0m�[0;1;30mnote: �[0m�[1mpossible intended match here
�[0mdefine void @main() #0 {
�[0;1;32m^
�[0m
Input file: <stdin>
Check file: /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
�[1m�[0m�[0;1;30m            1: �[0m�[1m�[0;1;46m; ModuleID = '/home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' �[0m
�[0;1;31mcheck:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
�[0m�[0;1;30m            2: �[0m�[1m�[0;1;46msource_filename = "/home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            3: �[0m�[1m�[0;1;46mtarget datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            4: �[0m�[1m�[0;1;46mtarget triple = "dxilv1.0-pc-shadermodel6.0-compute" �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            5: �[0m�[1m�[0;1;46m �[0m
�[0;1;31mcheck:14'0     ~
�[0m�[0;1;30m            6: �[0m�[1m�[0;1;46m%"class.hlsl::StructuredBuffer" = type { ptr } �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            7: �[0m�[1m�[0;1;46m �[0m
�[0;1;31mcheck:14'0     ~
�[0m�[0;1;30m            8: �[0m�[1m�[0;1;46m@"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            9: �[0m�[1m�[0;1;46m@"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m           10: �[0m�[1m�[0;1;46m �[0m
�[0;1;31mcheck:14'0     ~
�[0m�[0;1;30m           11: �[0m�[1m�[0;1;46m; Function Attrs: convergent noinline norecurse �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m           12: �[0m�[1m�[0;1;46mdefine void @main() #0 { �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;35mcheck:14'1     ?                         possible intended match
...

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 17, 2024

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/5917

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang -cc1 -internal-isystem /Users/buildbot/buildbot-root/aarch64-darwin/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang -cc1 -internal-isystem /Users/buildbot/buildbot-root/aarch64-darwin/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
�[1m/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: �[0m�[0;1;31merror: �[0m�[1mCHECK: expected string not found in input
�[0m// CHECK: define internal void @"?main@@YAXI@Z"
�[0;1;32m          ^
�[0m�[1m<stdin>:1:1: �[0m�[0;1;30mnote: �[0m�[1mscanning from here
�[0m; ModuleID = '/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
�[0;1;32m^
�[0m�[1m<stdin>:12:1: �[0m�[0;1;30mnote: �[0m�[1mpossible intended match here
�[0mdefine void @main() #0 {
�[0;1;32m^
�[0m
Input file: <stdin>
Check file: /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
�[1m�[0m�[0;1;30m            1: �[0m�[1m�[0;1;46m; ModuleID = '/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' �[0m
�[0;1;31mcheck:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
�[0m�[0;1;30m            2: �[0m�[1m�[0;1;46msource_filename = "/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            3: �[0m�[1m�[0;1;46mtarget datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            4: �[0m�[1m�[0;1;46mtarget triple = "dxilv1.0-pc-shadermodel6.0-compute" �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            5: �[0m�[1m�[0;1;46m �[0m
�[0;1;31mcheck:14'0     ~
�[0m�[0;1;30m            6: �[0m�[1m�[0;1;46m%"class.hlsl::StructuredBuffer" = type { ptr } �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            7: �[0m�[1m�[0;1;46m �[0m
�[0;1;31mcheck:14'0     ~
�[0m�[0;1;30m            8: �[0m�[1m�[0;1;46m@"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m            9: �[0m�[1m�[0;1;46m@"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m           10: �[0m�[1m�[0;1;46m �[0m
�[0;1;31mcheck:14'0     ~
�[0m�[0;1;30m           11: �[0m�[1m�[0;1;46m; Function Attrs: convergent noinline norecurse �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;30m           12: �[0m�[1m�[0;1;46mdefine void @main() #0 { �[0m
�[0;1;31mcheck:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
�[0m�[0;1;35mcheck:14'1     ?                         possible intended match
...

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 17, 2024

LLVM Buildbot has detected a new failure on builder ppc64le-lld-multistage-test running on ppc64le-lld-multistage-test while building clang at step 7 "test-build-stage1-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/168/builds/3425

Here is the relevant piece of the build log for the reference
Step 7 (test-build-stage1-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/bin/clang -cc1 -internal-isystem /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/bin/FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/bin/clang -cc1 -internal-isystem /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage1/bin/FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: error: CHECK: expected string not found in input
// CHECK: define internal void @"?main@@YAXI@Z"
          ^
<stdin>:1:1: note: scanning from here
; ModuleID = '/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
^
<stdin>:12:1: note: possible intended match here
define void @main() #0 {
^

Input file: <stdin>
Check file: /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: ; ModuleID = '/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' 
check:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
            2: source_filename = "/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            3: target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            4: target triple = "dxilv1.0-pc-shadermodel6.0-compute" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            5:  
check:14'0     ~
            6: %"class.hlsl::StructuredBuffer" = type { ptr } 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            7:  
check:14'0     ~
            8: @"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            9: @"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           10:  
check:14'0     ~
           11: ; Function Attrs: convergent noinline norecurse 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           12: define void @main() #0 { 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
check:14'1     ?                         possible intended match
...
Step 13 (test-build-stage2-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage2/bin/clang -cc1 -internal-isystem /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage2/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage2/bin/FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage2/bin/clang -cc1 -internal-isystem /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage2/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/build/stage2/bin/FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: error: CHECK: expected string not found in input
// CHECK: define internal void @"?main@@YAXI@Z"
          ^
<stdin>:1:1: note: scanning from here
; ModuleID = '/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
^
<stdin>:12:1: note: possible intended match here
define void @main() #0 {
^

Input file: <stdin>
Check file: /home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: ; ModuleID = '/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' 
check:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
            2: source_filename = "/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            3: target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            4: target triple = "dxilv1.0-pc-shadermodel6.0-compute" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            5:  
check:14'0     ~
            6: %"class.hlsl::StructuredBuffer" = type { ptr } 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            7:  
check:14'0     ~
            8: @"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            9: @"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           10:  
check:14'0     ~
           11: ; Function Attrs: convergent noinline norecurse 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           12: define void @main() #0 { 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
check:14'1     ?                         possible intended match
...

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 17, 2024

LLVM Buildbot has detected a new failure on builder premerge-monolithic-linux running on premerge-linux-1 while building clang at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/153/builds/9181

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /build/buildbot/premerge-monolithic-linux/build/bin/clang -cc1 -internal-isystem /build/buildbot/premerge-monolithic-linux/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /build/buildbot/premerge-monolithic-linux/build/bin/FileCheck /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /build/buildbot/premerge-monolithic-linux/build/bin/clang -cc1 -internal-isystem /build/buildbot/premerge-monolithic-linux/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /build/buildbot/premerge-monolithic-linux/build/bin/FileCheck /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
/build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: error: CHECK: expected string not found in input
// CHECK: define internal void @"?main@@YAXI@Z"
          ^
<stdin>:1:1: note: scanning from here
; ModuleID = '/build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
^
<stdin>:12:1: note: possible intended match here
define void @main() #0 {
^

Input file: <stdin>
Check file: /build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: ; ModuleID = '/build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' 
check:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
            2: source_filename = "/build/buildbot/premerge-monolithic-linux/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            3: target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            4: target triple = "dxilv1.0-pc-shadermodel6.0-compute" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            5:  
check:14'0     ~
            6: %"class.hlsl::StructuredBuffer" = type { ptr } 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            7:  
check:14'0     ~
            8: @"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            9: @"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           10:  
check:14'0     ~
           11: ; Function Attrs: convergent noinline norecurse 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           12: define void @main() #0 { 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
check:14'1     ?                         possible intended match
...

thurstond added a commit that referenced this pull request Sep 17, 2024
This reverts commit a729e70.

Reason:bBuildbot failure (https://lab.llvm.org/buildbot/#/builders/25/builds/2541):
    'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' failed
@nico
Copy link
Contributor

nico commented Sep 17, 2024

Looks like the revert broke check-clang: http://45.33.8.238/linux/148045/step_6.txt

Please take a look, and uh, mark that test as UNSUPPORTED if it takes a while to fix, I suppose.

@nico
Copy link
Contributor

nico commented Sep 17, 2024

@thurstond ^

@thurstond
Copy link
Contributor

@nico Sorry, my bad. I didn't notice the test was also updated as a companion to this change (#109023). I'll revert the test as well.

thurstond added a commit that referenced this pull request Sep 17, 2024
#109023)"

This reverts commit f4fe26d.

Reason: 4a63f4d reverted "[HLSL] set alwaysinline on HLSL functions (#106588)" due to a buildbot failure; this test (which builds upon the reverted patch) also needs to be reverted.
@thurstond
Copy link
Contributor

Oh, actually, I just realized the test update was the fix-forward. So the correct fix would be to reland both the change and the test update. Sorry!

thurstond added a commit that referenced this pull request Sep 17, 2024
This reverts commit 4a63f4d.

It was reverted because of a buildbot breakage, but the fix-forward has
landed (#109023).
@thurstond
Copy link
Contributor

I've reverted both of my reverts

@pow2clk
Copy link
Contributor Author

pow2clk commented Sep 17, 2024

Sorry I didn't mention here that the fix was in. It looks like everything is clean now?

@thurstond
Copy link
Contributor

Sorry I didn't mention here that the fix was in. It looks like everything is clean now?

Yes, both your changes are back in and I anticipate the buildbots will be green again. Sorry for the noise!

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 17, 2024

LLVM Buildbot has detected a new failure on builder clang-x86_64-debian-fast running on gribozavr4 while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/56/builds/7605

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /b/1/clang-x86_64-debian-fast/llvm.obj/bin/clang -cc1 -internal-isystem /b/1/clang-x86_64-debian-fast/llvm.obj/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /b/1/clang-x86_64-debian-fast/llvm.obj/bin/FileCheck /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /b/1/clang-x86_64-debian-fast/llvm.obj/bin/clang -cc1 -internal-isystem /b/1/clang-x86_64-debian-fast/llvm.obj/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /b/1/clang-x86_64-debian-fast/llvm.obj/bin/FileCheck /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
/b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: error: CHECK: expected string not found in input
// CHECK: define internal void @"?main@@YAXI@Z"
          ^
<stdin>:1:1: note: scanning from here
; ModuleID = '/b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
^
<stdin>:12:1: note: possible intended match here
define void @main() #0 {
^

Input file: <stdin>
Check file: /b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: ; ModuleID = '/b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' 
check:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
            2: source_filename = "/b/1/clang-x86_64-debian-fast/llvm.src/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            3: target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            4: target triple = "dxilv1.0-pc-shadermodel6.0-compute" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            5:  
check:14'0     ~
            6: %"class.hlsl::StructuredBuffer" = type { ptr } 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            7:  
check:14'0     ~
            8: @"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            9: @"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           10:  
check:14'0     ~
           11: ; Function Attrs: convergent noinline norecurse 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           12: define void @main() #0 { 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
check:14'1     ?                         possible intended match
...

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 17, 2024

LLVM Buildbot has detected a new failure on builder llvm-x86_64-debian-dylib running on gribozavr4 while building clang at step 6 "test-build-unified-tree-check-clang".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/60/builds/7827

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-clang) failure: test (failure)
******************** TEST 'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: /b/1/llvm-x86_64-debian-dylib/build/bin/clang -cc1 -internal-isystem /b/1/llvm-x86_64-debian-dylib/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl | /b/1/llvm-x86_64-debian-dylib/build/bin/FileCheck /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /b/1/llvm-x86_64-debian-dylib/build/bin/clang -cc1 -internal-isystem /b/1/llvm-x86_64-debian-dylib/build/lib/clang/20/include -nostdsysteminc -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
+ /b/1/llvm-x86_64-debian-dylib/build/bin/FileCheck /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl
/b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl:14:11: error: CHECK: expected string not found in input
// CHECK: define internal void @"?main@@YAXI@Z"
          ^
<stdin>:1:1: note: scanning from here
; ModuleID = '/b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl'
^
<stdin>:12:1: note: possible intended match here
define void @main() #0 {
^

Input file: <stdin>
Check file: /b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl

-dump-input=help explains the following input dump.

Input was:
<<<<<<
            1: ; ModuleID = '/b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' 
check:14'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
            2: source_filename = "/b/1/llvm-x86_64-debian-dylib/llvm-project/clang/test/CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            3: target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            4: target triple = "dxilv1.0-pc-shadermodel6.0-compute" 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            5:  
check:14'0     ~
            6: %"class.hlsl::StructuredBuffer" = type { ptr } 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            7:  
check:14'0     ~
            8: @"?In@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            9: @"?Out@@3V?$StructuredBuffer@H@hlsl@@A" = global %"class.hlsl::StructuredBuffer" zeroinitializer, align 4 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           10:  
check:14'0     ~
           11: ; Function Attrs: convergent noinline norecurse 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           12: define void @main() #0 { 
check:14'0     ~~~~~~~~~~~~~~~~~~~~~~~~~
check:14'1     ?                         possible intended match
...

hamphet pushed a commit to hamphet/llvm-project that referenced this pull request Sep 18, 2024
HLSL inlines all its functions by default. This uses the alwaysinline
attribute to make the alwaysinliner pass inline any function not
explicitly marked noinline by the user or autogeneration. The
alwayslinline marking takes place in `SetLLVMFunctionAttributesForDefinitions`
where all other inlining interactions are determined.

The outermost entry function is marked noinline because there's no
reason to inline it. Any user calls to an entry function will instead call
the internal mangled version of the entry function.

Adds tests for function and constructor inlining and augments some
existing tests to verify correct inlining of implicitly created
functions as well.

Incidentally restore RUN line that I believe was mistakenly removed as
part of llvm#88918

Fixes llvm#89282
hamphet pushed a commit to hamphet/llvm-project that referenced this pull request Sep 18, 2024
This reverts commit a729e70.

Reason:bBuildbot failure (https://lab.llvm.org/buildbot/#/builders/25/builds/2541):
    'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' failed
hamphet pushed a commit to hamphet/llvm-project that referenced this pull request Sep 18, 2024
llvm#109023)"

This reverts commit f4fe26d.

Reason: 4a63f4d reverted "[HLSL] set alwaysinline on HLSL functions (llvm#106588)" due to a buildbot failure; this test (which builds upon the reverted patch) also needs to be reverted.
hamphet pushed a commit to hamphet/llvm-project that referenced this pull request Sep 18, 2024
This reverts commit 4a63f4d.

It was reverted because of a buildbot breakage, but the fix-forward has
landed (llvm#109023).
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
HLSL inlines all its functions by default. This uses the alwaysinline
attribute to make the alwaysinliner pass inline any function not
explicitly marked noinline by the user or autogeneration. The
alwayslinline marking takes place in `SetLLVMFunctionAttributesForDefinitions`
where all other inlining interactions are determined.

The outermost entry function is marked noinline because there's no
reason to inline it. Any user calls to an entry function will instead call
the internal mangled version of the entry function.

Adds tests for function and constructor inlining and augments some
existing tests to verify correct inlining of implicitly created
functions as well.

Incidentally restore RUN line that I believe was mistakenly removed as
part of llvm#88918

Fixes llvm#89282
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
This reverts commit a729e70.

Reason:bBuildbot failure (https://lab.llvm.org/buildbot/#/builders/25/builds/2541):
    'Clang :: CodeGenHLSL/builtins/StructuredBuffer-subscript.hlsl' failed
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
llvm#109023)"

This reverts commit f4fe26d.

Reason: 4a63f4d reverted "[HLSL] set alwaysinline on HLSL functions (llvm#106588)" due to a buildbot failure; this test (which builds upon the reverted patch) also needs to be reverted.
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
This reverts commit 4a63f4d.

It was reverted because of a buildbot breakage, but the fix-forward has
landed (llvm#109023).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

[DXIL] Always inline HLSL functions by default
9 participants