Kaynağa Gözat

Fix arg flatten issue caused by load before init. (#447)

* Fix arg flatten issue caused by load before init.
* Refine ShaderCompatSuite.
* Remove HLFunctions has body early.
Xiang Li 8 yıl önce
ebeveyn
işleme
9db715523f

+ 4 - 6
lib/HLSL/DxilGenerationPass.cpp

@@ -1031,12 +1031,10 @@ void DxilGenerationPass::GenerateDxilOperations(
   // Remove unused HL Operation functions.
   std::vector<Function *> deadList;
   for (iplist<Function>::iterator F : M.getFunctionList()) {
-    if (F->isDeclaration()) {
-      hlsl::HLOpcodeGroup group = hlsl::GetHLOpcodeGroupByName(F);
-      if (group != HLOpcodeGroup::NotHL || F->isIntrinsic())
-        if (F->user_empty())
-          deadList.emplace_back(F);
-    }
+    hlsl::HLOpcodeGroup group = hlsl::GetHLOpcodeGroupByName(F);
+    if (group != HLOpcodeGroup::NotHL || F->isIntrinsic())
+      if (F->user_empty())
+        deadList.emplace_back(F);
   }
 
   for (Function *F : deadList)

+ 23 - 5
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -4829,7 +4829,17 @@ Value *SROA_Parameter_HLSL::castArgumentIfRequired(
     // Create load here to make correct type.
     // The Ptr will be store with correct value in replaceCastParameter and
     // replaceCastArgument.
-    V = Builder.CreateLoad(Ptr);
+    if (Ptr->hasOneUse()) {
+      // Load after existing user for call arg replace.
+      // If not, call arg will load undef.
+      // This will not hurt parameter, new load is only after first load.
+      // It still before all the load users.
+      Instruction *User = cast<Instruction>(*(Ptr->user_begin()));
+      IRBuilder<> CallBuilder(User->getNextNode());
+      V = CallBuilder.CreateLoad(Ptr);
+    } else {
+      V = Builder.CreateLoad(Ptr);
+    }
     castParamMap[V] = std::make_pair(Ptr, inputQual);
   }
 
@@ -4877,11 +4887,16 @@ Value *SROA_Parameter_HLSL::castArgumentIfRequired(
           vectorEltsMap[V].emplace_back(Elt);
         }
       } else {
+        IRBuilder<> TmpBuilder(Builder.GetInsertPoint());
+        // Make sure extract element after OldV.
+        if (Instruction *OldI = dyn_cast<Instruction>(OldV)) {
+          TmpBuilder.SetInsertPoint(OldI->getNextNode());
+        }
         // Split into scalar.
-        V = Builder.CreateExtractElement(OldV, (uint64_t)0);
+        V = TmpBuilder.CreateExtractElement(OldV, (uint64_t)0);
         vectorEltsMap[V].emplace_back(V);
         for (unsigned i = 1; i < vecSize; i++) {
-          Value *Elt = Builder.CreateExtractElement(OldV, i);
+          Value *Elt = TmpBuilder.CreateExtractElement(OldV, i);
           vectorEltsMap[V].emplace_back(Elt);
         }
       }
@@ -5673,6 +5688,9 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
   std::unique_ptr<BasicBlock> TmpBlockForFuncDecl;
   if (F->isDeclaration()) {
     TmpBlockForFuncDecl.reset(BasicBlock::Create(Ctx));
+    // Create return as terminator.
+    IRBuilder<> RetBuilder(TmpBlockForFuncDecl.get());
+    RetBuilder.CreateRetVoid();
   }
 
   std::vector<Value *> FlatParamList;
@@ -5690,7 +5708,7 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
     if (!F->isDeclaration()) {
       Builder.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
     } else {
-      Builder.SetInsertPoint(TmpBlockForFuncDecl.get());
+      Builder.SetInsertPoint(TmpBlockForFuncDecl->getFirstInsertionPt());
     }
 
     unsigned prevFlatParamCount = FlatParamList.size();
@@ -5716,7 +5734,7 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
     if (!F->isDeclaration()) {
       Builder.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
     } else {
-      Builder.SetInsertPoint(TmpBlockForFuncDecl.get());
+      Builder.SetInsertPoint(TmpBlockForFuncDecl->getFirstInsertionPt());
     }
     Value *retValAddr = Builder.CreateAlloca(retType);
     DxilParameterAnnotation &retAnnotation =

+ 0 - 0
tools/clang/test/CodeGenHLSL/lib_arg_flatten.hlsl → tools/clang/test/CodeGenHLSL/shader-compat-suite/lib_arg_flatten/lib_arg_flatten.hlsl


+ 24 - 0
tools/clang/test/CodeGenHLSL/shader-compat-suite/lib_arg_flatten/lib_arg_flatten2.hlsl

@@ -0,0 +1,24 @@
+// RUN: %dxc -T lib_6_1 %s | FileCheck %s
+
+// Make sure no undef in test3.
+// CHECK: define void
+// CHECK-NOT: undef
+// CHECK: ret void
+
+struct T {
+  float2 v;
+};
+
+cbuffer M {
+  float2 m;
+}
+
+float test(T t);
+
+float4 test3(){
+  float2 x = m + 2;
+  T t = { x };
+  float a = test(t);
+  t.v.x += 2;
+  return a + test(t);
+}

+ 80 - 8
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -39,6 +39,11 @@
 #include "dia2.h"
 
 #include <fstream>
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MSFileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
 
 using namespace std;
 using namespace hlsl_test;
@@ -525,7 +530,6 @@ public:
   TEST_METHOD(CodeGenIntrinsic5)
   TEST_METHOD(CodeGenInvalidInputOutputTypes)
   TEST_METHOD(CodeGenLegacyStruct)
-  TEST_METHOD(CodeGenLibArgFlatten)
   TEST_METHOD(CodeGenLibCsEntry)
   TEST_METHOD(CodeGenLibCsEntry2)
   TEST_METHOD(CodeGenLibCsEntry3)
@@ -1008,6 +1012,10 @@ public:
   TEST_METHOD(ConstantFolding)
   TEST_METHOD(HoistConstantArray)
   TEST_METHOD(ViewID)
+  TEST_METHOD(ShaderCompatSuite)
+  BEGIN_TEST_METHOD(SingleFileCheckTest)
+    TEST_METHOD_PROPERTY(L"Ignore", L"true")
+  END_TEST_METHOD()
 
   dxc::DxcDllSupport m_dllSupport;
   VersionSupportInfo m_ver;
@@ -1308,9 +1316,8 @@ public:
     VERIFY_ARE_NOT_EQUAL(0, disassembleString.size());
   }
 
-  void CodeGenTestCheck(LPCWSTR name) {
-    std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(name);
-    FileRunTestResult t = FileRunTestResult::RunFromFileCommands(fullPath.c_str());
+  void CodeGenTestCheckFullPath(LPCWSTR fullPath) {
+    FileRunTestResult t = FileRunTestResult::RunFromFileCommands(fullPath);
     if (t.RunResult != 0) {
       CA2W commentWide(t.ErrorMessage.c_str(), CP_UTF8);
       WEX::Logging::Log::Comment(commentWide);
@@ -1318,6 +1325,19 @@ public:
     }
   }
 
+  void CodeGenTestCheck(LPCWSTR name) {
+    std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(name);
+    CodeGenTestCheckFullPath(fullPath.c_str());
+  }
+
+  void CodeGenTestCheckBatch(LPCWSTR name, unsigned option) {
+    WEX::Logging::Log::StartGroup(name);
+
+    CodeGenTestCheckFullPath(name);
+
+    WEX::Logging::Log::EndGroup(name);
+  }
+
   std::string VerifyCompileFailed(LPCSTR pText, LPWSTR pTargetProfile, LPCSTR pErrorMsg) {
     return VerifyCompileFailed(pText, pTargetProfile, pErrorMsg, L"main");
   }
@@ -3186,10 +3206,6 @@ TEST_F(CompilerTest, CodeGenLegacyStruct) {
   CodeGenTestCheck(L"..\\CodeGenHLSL\\legacy_struct.hlsl");
 }
 
-TEST_F(CompilerTest, CodeGenLibArgFlatten) {
-  CodeGenTestCheck(L"..\\CodeGenHLSL\\lib_arg_flatten.hlsl");
-}
-
 TEST_F(CompilerTest, CodeGenLibCsEntry) {
   CodeGenTestCheck(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl");
 }
@@ -5258,3 +5274,59 @@ TEST_F(CompilerTest, ViewID) {
   CodeGenTestCheck(L"..\\CodeGenHLSL\\viewid\\viewid17.hlsl");
   CodeGenTestCheck(L"..\\CodeGenHLSL\\viewid\\viewid18.hlsl");
 }
+
+TEST_F(CompilerTest, ShaderCompatSuite) {
+  using namespace llvm;
+  using namespace WEX::TestExecution;
+
+  ::llvm::sys::fs::MSFileSystem *msfPtr;
+  VERIFY_SUCCEEDED(CreateMSFileSystemForDisk(&msfPtr));
+  std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
+  ::llvm::sys::fs::AutoPerThreadSystem pts(msf.get());
+  IFTLLVM(pts.error_code());
+
+  std::wstring suitePath = L"..\\CodeGenHLSL\\shader-compat-suite";
+
+  WEX::Common::String value;
+  if (!DXC_FAILED(RuntimeParameters::TryGetValue(L"SuitePath", value)))
+  {
+    suitePath = value;
+  }
+
+  CW2A pUtf8Filename(suitePath.c_str());
+  if (!llvm::sys::path::is_absolute(pUtf8Filename.m_psz)) {
+    suitePath = hlsl_test::GetPathToHlslDataFile(suitePath.c_str());
+  }
+
+  CW2A utf8SuitePath(suitePath.c_str());
+
+  std::error_code EC;
+  llvm::SmallString<128> DirNative;
+  llvm::sys::path::native(utf8SuitePath.m_psz, DirNative);
+  for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative, EC), DirEnd;
+       Dir != DirEnd && !EC; Dir.increment(EC)) {
+    // Check whether this entry has an extension typically associated with
+    // headers.
+    if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
+             .Cases(".hlsl", ".hlsl", true)
+             .Default(false))
+      continue;
+    StringRef filename = Dir->path();
+    CA2W wRelPath(filename.data());
+    CodeGenTestCheckBatch(wRelPath.m_psz, 0);
+  }
+}
+
+TEST_F(CompilerTest, SingleFileCheckTest) {
+  using namespace llvm;
+  using namespace WEX::TestExecution;
+  WEX::Common::String value;
+  VERIFY_SUCCEEDED(RuntimeParameters::TryGetValue(L"InputFile", value));
+  std::wstring filename = value;
+  CW2A pUtf8Filename(filename.c_str());
+  if (!llvm::sys::path::is_absolute(pUtf8Filename.m_psz)) {
+    filename = hlsl_test::GetPathToHlslDataFile(filename.c_str());
+  }
+
+  CodeGenTestCheckBatch(filename.c_str(), 0);
+}

+ 34 - 6
utils/hct/hcttest.cmd

@@ -17,6 +17,10 @@ set TEST_EXEC_REQUIRED=0
 set TEST_CLANG_FILTER= /select: "@Priority<1"
 set TEST_EXEC_FILTER=ExecutionTest::*
 set LOG_FILTER=/logOutput:LowWithConsoleBuffering
+set TEST_COMPAT_SUITE=0
+set COMPAT_SUIT_PATH=
+set TEST_SINGLE_FILE_CHECK=0
+set SINGLE_FILE_CHECK_NAME=0
 
 rem Begin SPIRV change
 set TEST_SPIRV=0
@@ -73,6 +77,16 @@ if "%1"=="-clean" (
   set TEST_CLANG=1
   set TEST_CLANG_FILTER= /name:%2
   shift /1
+) else if "%1"=="compat-suite" (
+  set TEST_ALL=0
+  set TEST_COMPAT_SUITE=1
+  set COMPAT_SUIT_PATH= /p:"SuitePath=%~2"
+  shift /1
+) else if "%1"=="file-check" (
+  set TEST_ALL=0
+  set TEST_SINGLE_FILE_CHECK=1
+  set COMPAT_SUIT_PATH= /p:"InputFile=%~2"
+  shift /1
 ) else if "%1"=="v" (
   set TEST_ALL=0
   set TEST_CLANG=1
@@ -250,6 +264,16 @@ if exist "%HCT_EXTRAS%\hcttest-after.cmd" (
   set RES_HCTTEST_AFTER=!ERRORLEVEL!
 )
 
+if "%TEST_SINGLE_FILE_CHECK%"=="1" (
+  call :runte clang-hlsl-tests.dll /p:"HlslDataDir=%HLSL_SRC_DIR%\tools\clang\test\HLSL" /name:CompilerTest::SingleFileCheckTest /runIgnoredTests %COMPAT_SUIT_PATH%
+  set RES_EXEC=!ERRORLEVEL!
+)
+
+if "%TEST_COMPAT_SUITE%"=="1" (
+  call :runte clang-hlsl-tests.dll /p:"HlslDataDir=%HLSL_SRC_DIR%\tools\clang\test\HLSL" /name:CompilerTest::ShaderCompatSuite %COMPAT_SUIT_PATH%
+  set RES_EXEC=!ERRORLEVEL!
+)
+
 echo.
 echo ==================================
 echo Unit test results:
@@ -299,12 +323,16 @@ echo   -x64 targets an x64 build (aka. Win64)
 echo   -arm targets an ARM build
 echo.
 echo target(s):
-echo  clang   - run clang tests.
-echo  cmd     - run command line tool tests.
-echo  v       - run the subset of clang tests that are verified-based.
-echo  exec    - run execution tests.
-echo  extras  - run hcttest-extras tests.
-echo  noexec  - all except exec and extras tests.
+echo  clang         - run clang tests.
+echo  file-check    - run file-check test on single file.
+echo                - hcttest file-check "..\CodeGenHLSL\shader-compat-suite\lib_arg_flatten\lib_arg_flatten.hlsl"
+echo  compat-suite  - run compat-suite test.
+echo                - hcttest compat-suite "..\CodeGenHLSL\shader-compat-suite\lib_arg_flatten"
+echo  cmd           - run command line tool tests.
+echo  v             - run the subset of clang tests that are verified-based.
+echo  exec          - run execution tests.
+echo  extras        - run hcttest-extras tests.
+echo  noexec        - all except exec and extras tests.
 echo.
 echo Select clang or exec targets with filter by test name:
 echo  clang-filter Name