llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: ivarusic-amd

<details>
<summary>Changes</summary>

  When compiling HIP for multiple offload archs with clang-cl's /Fo (e.g. 
--offload-arch=gfx900 --offload-arch=gfx90a:xnack+
  /Fo:out.obj), every arch's intermediate device compile job wrote to the same 
literal /Fo path, so each arch silently overwrote theprevious one's object 
before packaging so only one arch's code ended up in the final binary.

  Root cause: in GetNamedOutputPath(), the "output to a temp file" gate falls 
through to the literal user-specified path for -o only when AtTopLevel is true; 
intermediate (non-top-level) -o actions get a genuinely unique temp path. /Fo 
was unconditionally excluded from this gate regardless of AtTopLevel, so 
intermediate offloading-device sub-actions used the literal /Fo path directly 
instead.

  Fix: narrow the /Fo exclusion so it only bypasses the temp-file route for 
non-offloading (host) actions - offloading device
  sub-actions under /Fo now fall through to CreateTempOutputPath, matching how 
-o already behaves. Final top-level output still honors the literal /Fo path.

  Added clang/test/Driver/hip-windows-multiarch-fo.hip, verified to fail before 
the fix 

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


2 Files Affected:

- (modified) clang/lib/Driver/Driver.cpp (+8-1) 
- (added) clang/test/Driver/hip-windows-multiarch-fo.hip (+20) 


``````````diff
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index d4719f37e5b4d..158d9fb1beae6 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6692,8 +6692,15 @@ const char *Driver::GetNamedOutputPath(Compilation &C, 
const JobAction &JA,
   }
 
   // Output to a temporary file?
+  // /Fo is normally exempted from this so that its literal path is honored,
+  // but offloading device sub-actions (e.g. each arch of a multi-arch HIP
+  // compile) are not the final output and must still get a unique path here,
+  // the same way they would under -o; otherwise every arch collides on the
+  // single /Fo path.
   if ((!AtTopLevel && !isSaveTempsEnabled() &&
-       !C.getArgs().hasArg(options::OPT__SLASH_Fo)) ||
+       !(C.getArgs().hasArg(options::OPT__SLASH_Fo) &&
+         (JA.getOffloadingDeviceKind() == Action::OFK_None ||
+          JA.getOffloadingDeviceKind() == Action::OFK_Host))) ||
       CCGenDiagnostics) {
     StringRef Name = llvm::sys::path::filename(BaseInput);
     return CreateTempOutputPath(Name.split('.').first);
diff --git a/clang/test/Driver/hip-windows-multiarch-fo.hip 
b/clang/test/Driver/hip-windows-multiarch-fo.hip
new file mode 100644
index 0000000000000..b997f233427fc
--- /dev/null
+++ b/clang/test/Driver/hip-windows-multiarch-fo.hip
@@ -0,0 +1,20 @@
+// REQUIRES: system-windows
+// REQUIRES: x86-registered-target
+// REQUIRES: amdgpu-registered-target
+
+// Each offload-arch device compile job must get its own unique output path
+// under /Fo, the same way -o already does via GetNamedOutputPath's temp-file
+// gate. Otherwise every arch's device object collides on the single literal
+// /Fo path and silently overwrites the others before packaging.
+
+// RUN: %clang_cl -### --target=x86_64-pc-windows-msvc -x hip \
+// RUN:   --offload-arch=gfx900 --offload-arch=gfx90a:xnack+ \
+// RUN:   -nogpuinc -nogpulib -Foout.obj -- %s 2>&1 | FileCheck %s
+
+// CHECK: "-target-cpu" "gfx900"{{.*}}"-o" "{{.*}}gfx900-{{[^"]*}}"
+// CHECK-NOT: "-o" "out.obj"
+// CHECK: "-target-cpu" "gfx90a" "-mxnack"{{.*}}"-o" 
"{{.*}}gfx90a@xnack+-{{[^"]*}}"
+// CHECK-NOT: "-o" "out.obj"
+// CHECK: "-o" "out.obj"
+
+void main() {}

``````````

</details>


https://github.com/llvm/llvm-project/pull/215663
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to