Browse Source

chore: cherry-pick 5 changes from 2-M126 (#42693)

* chore: [30-x-y] cherry-pick 5 changes from 2-M126

* 5d4df51d1d7d from angle
* 771e74ab497d from DirectXShaderCompiler
* 8f07d39227f6 from DirectXShaderCompiler
* b3c64851765c from DirectXShaderCompiler
* d5217a718925 from v8

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Pedro Pontes 9 months ago
parent
commit
ccd682e837

+ 3 - 0
patches/DirectXShaderCompiler/.patches

@@ -1,3 +1,6 @@
 cherry-pick-93c3cf1c787f.patch
 cherry-pick-33051b084850.patch
 cherry-pick-b845fed99111.patch
+cherry-pick-771e74ab497d.patch
+cherry-pick-8f07d39227f6.patch
+cherry-pick-b3c64851765c.patch

+ 116 - 0
patches/DirectXShaderCompiler/cherry-pick-771e74ab497d.patch

@@ -0,0 +1,116 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Antonio Maiorano <[email protected]>
+Date: Thu, 20 Jun 2024 14:02:42 -0400
+Subject: indvars: don't replace a phi when that breaks LCSSA (#6695)
+
+Induction variable simplification (indvars) tries to rewrite exit
+values; these appear as phi nodes in loop exit blocks. If the
+replacement for the phi is still in the loop, then that would break the
+LCSSA property. Don't do that.
+
+Add a test for this.
+
+Bug: chromium:345993680
+Change-Id: Ib2330afa3c6f47373cb4336cfd00e851044fea3a
+Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5645925
+Reviewed-by: dan sinclair <[email protected]>
+Reviewed-by: James Price <[email protected]>
+
+diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp
+index f5b1455d5932b63dfef699991c5eeab38e447a7d..e6ff7b3ab4d81bbb782f0bd0a7b5185a30fd1285 100644
+--- a/lib/Transforms/Scalar/IndVarSimplify.cpp
++++ b/lib/Transforms/Scalar/IndVarSimplify.cpp
+@@ -24,7 +24,6 @@
+ //
+ //===----------------------------------------------------------------------===//
+ 
+-#include "llvm/Transforms/Scalar.h"
+ #include "llvm/ADT/DenseMap.h"
+ #include "llvm/ADT/SmallVector.h"
+ #include "llvm/ADT/Statistic.h"
+@@ -41,11 +40,13 @@
+ #include "llvm/IR/Instructions.h"
+ #include "llvm/IR/IntrinsicInst.h"
+ #include "llvm/IR/LLVMContext.h"
++#include "llvm/IR/Module.h"
+ #include "llvm/IR/PatternMatch.h"
+ #include "llvm/IR/Type.h"
+ #include "llvm/Support/CommandLine.h"
+ #include "llvm/Support/Debug.h"
+ #include "llvm/Support/raw_ostream.h"
++#include "llvm/Transforms/Scalar.h"
+ #include "llvm/Transforms/Utils/BasicBlockUtils.h"
+ #include "llvm/Transforms/Utils/Local.h"
+ #include "llvm/Transforms/Utils/SimplifyIndVar.h"
+@@ -698,6 +699,16 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
+           continue;
+         }
+ 
++        // HLSL Change Begin
++        // Avoid breaking LCSSA: Don't replace the PHI if its replacement
++        // is defined inside the loop.
++        if (auto *ExitValInst = dyn_cast<Instruction>(ExitVal)) {
++          if (L->contains(ExitValInst)) {
++            continue;
++          }
++        }
++        // HLSL Change End
++
+         // Collect all the candidate PHINodes to be rewritten.
+         RewritePhiSet.push_back(
+             RewritePhi(PN, i, ExitVal, HighCost, LCSSASafePhiForRAUW));
+diff --git a/test/HLSL/passes/indvars/preserve-phi-when-replacement-is-in-loop.ll b/test/HLSL/passes/indvars/preserve-phi-when-replacement-is-in-loop.ll
+new file mode 100644
+index 0000000000000000000000000000000000000000..b550ce993837814229f8223a47b2af328cc7c87c
+--- /dev/null
++++ b/test/HLSL/passes/indvars/preserve-phi-when-replacement-is-in-loop.ll
+@@ -0,0 +1,49 @@
++; RUN: opt < %s -indvars -S | FileCheck %s
++
++; The inner loop (%header1) has a fixed trip count.
++; The indvars pass is tempted to delete the phi instruction %hexit,
++; and replace its uses with %add3.
++; But %hexit is used in %latch0, which is outside the inner loop and
++; its exit block. Deleting the phi %hexit would break LCSSA form.
++
++; CHECK: @main
++; CHECK: exit1:
++; CHECK-NEXT: %hexit = phi i32 [ %hnext, %header1 ]
++; CHECK-NEXT: br label %latch0
++
++; CHECK: latch0:
++
++target triple = "dxil-ms-dx"
++
++define void @main(i32 %arg) {
++entry:
++  br label %header0
++
++header0:
++  %isgt0 = icmp sgt i32 %arg, 0
++  %smax = select i1 %isgt0, i32 %arg, i32 0
++  %h0 = add i32 %smax, 1
++  %j0 = add i32 %smax, 2
++  %doinner = icmp slt i32 %j0, 1
++  br i1 %doinner, label %header1.pre, label %latch0
++
++header1.pre:
++  br label %header1
++
++header1:
++  %hi = phi i32 [ %hnext, %header1 ], [ %h0, %header1.pre ]
++  %ji = phi i32 [ %jnext, %header1 ], [ %j0, %header1.pre ]
++  %add3 = add i32 %smax, 3
++  %hnext = add i32 %hi, 1
++  %jnext = add nsw i32 %ji, 1 ; the nsw here is essential
++  %do1again = icmp slt i32 %ji, %add3
++  br i1 %do1again, label %header1, label %exit1
++
++exit1:
++  %hexit = phi i32 [ %hnext, %header1 ]
++  br label %latch0
++
++latch0:
++  %useh = phi i32 [ %h0, %header0 ], [ %hexit, %exit1 ]
++  br label %header0
++}

+ 151 - 0
patches/DirectXShaderCompiler/cherry-pick-8f07d39227f6.patch

@@ -0,0 +1,151 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Antonio Maiorano <[email protected]>
+Date: Thu, 20 Jun 2024 14:49:58 -0400
+Subject: Fix crash in scalarrepl-param-hlsl when dynamically indexing a GEP of
+ a constant indexed GEP (#6670)
+
+When processing global values to determine when to flatten vectors, this
+pass was only checking the immdiate users of the value for non-dynamic
+indexing of the vector. But this would fail in the case of a dynamic
+indexed GEP of a constant indexed GEP (e.g. h[0][a]) because the first
+level GEP was constant indexed, but not the second. We fix this by
+checking the full User tree of the value in `hasDynamicVectorIndexing`.
+
+Bug: chromium:342428008
+Change-Id: Ibf2ae3a6528cfc9b50634058385c5a45aa1d3b75
+Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5645927
+Reviewed-by: James Price <[email protected]>
+Reviewed-by: dan sinclair <[email protected]>
+
+diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
+index 9b843ef0e49e554001b827e30eb6256853d90f5b..b1b38c0ee038dedb2064f5726663992a5bec736b 100644
+--- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
++++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
+@@ -1645,6 +1645,10 @@ bool hasDynamicVectorIndexing(Value *V) {
+         }
+       }
+     }
++    // Also recursively check the uses of this User to find a possible
++    // dynamically indexed GEP of this GEP.
++    if (hasDynamicVectorIndexing(U))
++      return true;
+   }
+   return false;
+ }
+diff --git a/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-dyn-idx-gep-of-const-idx-gep.ll b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-dyn-idx-gep-of-const-idx-gep.ll
+new file mode 100644
+index 0000000000000000000000000000000000000000..04fdea1500e75266a59705a1c2da98a4aef7391c
+--- /dev/null
++++ b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-dyn-idx-gep-of-const-idx-gep.ll
+@@ -0,0 +1,111 @@
++; RUN: %dxopt %s -hlsl-passes-resume -scalarrepl-param-hlsl -S | FileCheck %s
++
++; Produced from the following HLSL:
++;   static int4 g[4] = (int4[4])0;
++;   static int4 h[4] = (int4[4])0;
++;
++;   [numthreads(1, 1, 1)]
++;   void main() {
++;     int a = 0;
++;     int b = h[0][a];
++;     h = g;
++;   }
++;
++; This was crashing in scalarrepl-param-hlsl because it was attempting to flatten
++; global variable 'h' even though it is dynamically indexed. This was not detected
++; because the resulting IR was a dynamically indexed GEP of a constant-indexed GEP,
++; and the code was only checking the immediate users of 'h':
++;
++;  %1 = getelementptr <4 x i32>, <4 x i32>* getelementptr inbounds ([4 x <4 x i32>], [4 x <4 x i32>]* @h, i32 0, i32 0), i32 0, i32 %0, !dbg !26 ; line:7 col:11
++;
++; Verify that it does not get flattened
++; CHECK: %1 = getelementptr <4 x i32>, <4 x i32>* getelementptr inbounds ([4 x <4 x i32>], [4 x <4 x i32>]* @g, i32 0, i32 0), i32 0, i32 %0
++
++;
++; Buffer Definitions:
++;
++; cbuffer $Globals
++; {
++;
++;   [0 x i8] (type annotation not present)
++;
++; }
++;
++;
++; Resource Bindings:
++;
++; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
++; ------------------------------ ---------- ------- ----------- ------- -------------- ------
++; $Globals                          cbuffer      NA          NA     CB0   cb4294967295     1
++;
++target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
++target triple = "dxil-ms-dx"
++
++%ConstantBuffer = type opaque
++
++@h = internal global [4 x <4 x i32>] zeroinitializer, align 4
++@g = internal global [4 x <4 x i32>] zeroinitializer, align 4
++@"$Globals" = external constant %ConstantBuffer
++
++; Function Attrs: nounwind
++define void @main() #0 {
++entry:
++  %a = alloca i32, align 4
++  %b = alloca i32, align 4
++  store i32 0, i32* %a, align 4, !dbg !17, !tbaa !21 ; line:6 col:7
++  %0 = load i32, i32* %a, align 4, !dbg !25, !tbaa !21 ; line:7 col:16
++  %1 = getelementptr <4 x i32>, <4 x i32>* getelementptr inbounds ([4 x <4 x i32>], [4 x <4 x i32>]* @h, i32 0, i32 0), i32 0, i32 %0, !dbg !26 ; line:7 col:11
++  %2 = load i32, i32* %1, !dbg !26, !tbaa !21 ; line:7 col:11
++  store i32 %2, i32* %b, align 4, !dbg !27, !tbaa !21 ; line:7 col:7
++  %3 = bitcast [4 x <4 x i32>]* @h to i8*, !dbg !28 ; line:8 col:7
++  %4 = bitcast [4 x <4 x i32>]* @g to i8*, !dbg !28 ; line:8 col:7
++  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %4, i64 64, i32 1, i1 false), !dbg !28 ; line:8 col:7
++  ret void, !dbg !29 ; line:9 col:1
++}
++
++; Function Attrs: nounwind
++declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
++
++attributes #0 = { nounwind }
++
++!llvm.module.flags = !{!0}
++!pauseresume = !{!1}
++!llvm.ident = !{!2}
++!dx.version = !{!3}
++!dx.valver = !{!4}
++!dx.shaderModel = !{!5}
++!dx.typeAnnotations = !{!6}
++!dx.entryPoints = !{!10}
++!dx.fnprops = !{!14}
++!dx.options = !{!15, !16}
++
++!0 = !{i32 2, !"Debug Info Version", i32 3}
++!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"}
++!2 = !{!"dxc(private) 1.8.0.4514 (d9bd2a706-dirty)"}
++!3 = !{i32 1, i32 0}
++!4 = !{i32 1, i32 8}
++!5 = !{!"cs", i32 6, i32 0}
++!6 = !{i32 1, void ()* @main, !7}
++!7 = !{!8}
++!8 = !{i32 1, !9, !9}
++!9 = !{}
++!10 = !{void ()* @main, !"main", null, !11, null}
++!11 = !{null, null, !12, null}
++!12 = !{!13}
++!13 = !{i32 0, %ConstantBuffer* @"$Globals", !"$Globals", i32 0, i32 -1, i32 1, i32 0, null}
++!14 = !{void ()* @main, i32 5, i32 1, i32 1, i32 1}
++!15 = !{i32 64}
++!16 = !{i32 -1}
++!17 = !DILocation(line: 6, column: 7, scope: !18)
++!18 = !DISubprogram(name: "main", scope: !19, file: !19, line: 5, type: !20, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, function: void ()* @main)
++!19 = !DIFile(filename: "/mnt/c/Users/amaiorano/Downloads/342428008/standalone_reduced.hlsl", directory: "")
++!20 = !DISubroutineType(types: !9)
++!21 = !{!22, !22, i64 0}
++!22 = !{!"int", !23, i64 0}
++!23 = !{!"omnipotent char", !24, i64 0}
++!24 = !{!"Simple C/C++ TBAA"}
++!25 = !DILocation(line: 7, column: 16, scope: !18)
++!26 = !DILocation(line: 7, column: 11, scope: !18)
++!27 = !DILocation(line: 7, column: 7, scope: !18)
++!28 = !DILocation(line: 8, column: 7, scope: !18)
++!29 = !DILocation(line: 9, column: 1, scope: !18)

+ 231 - 0
patches/DirectXShaderCompiler/cherry-pick-b3c64851765c.patch

@@ -0,0 +1,231 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Antonio Maiorano <[email protected]>
+Date: Thu, 20 Jun 2024 15:39:00 -0400
+Subject: Fix instcombine overflow check inserting inst at wrong place (#6679)
+
+When optimizing an overflow check of an add followed by a compare, the
+new instruction was being inserted at the compare, and the add removed.
+This produced invalid IR in cases where there were other uses of the
+former add between it and the compare. This fix makes sure to insert the
+new instruction at the old add location, rather than at the compare.
+
+Note that this was also fixed in LLVM:
+
+https://github.com/llvm/llvm-project/commit/6f5dca70ed1c030957a45ad91bd295921f17b18d
+
+Bug: chromium:342545100
+Change-Id: Iecf758e4465b32371266bbe9879790328f363322
+Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5644335
+Reviewed-by: dan sinclair <[email protected]>
+Reviewed-by: Ryan Harrison <[email protected]>
+
+diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp
+index 7274304b3de7b110a4fa3a5123ea7215d99935ef..82e7e49003e65846c84e3df2801453fb463aa23e 100644
+--- a/lib/Transforms/InstCombine/InstCombineCompares.cpp
++++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp
+@@ -2145,6 +2145,12 @@ bool InstCombiner::OptimizeOverflowCheck(OverflowCheckFlavor OCF, Value *LHS,
+     return true;
+   };
+ 
++  // If the overflow check was an add followed by a compare, the insertion point
++  // may be pointing to the compare.  We want to insert the new instructions
++  // before the add in case there are uses of the add between the add and the
++  // compare.
++  Builder->SetInsertPoint(&OrigI);
++
+   switch (OCF) {
+   case OCF_INVALID:
+     llvm_unreachable("bad overflow check kind!");
+diff --git a/tools/clang/test/DXC/Passes/InstructionCombining/instcombine-opt-overflow-check-inserts-at-add.ll b/tools/clang/test/DXC/Passes/InstructionCombining/instcombine-opt-overflow-check-inserts-at-add.ll
+new file mode 100644
+index 0000000000000000000000000000000000000000..70efa00c91c6523867980de0fb9f69c7fcfb318c
+--- /dev/null
++++ b/tools/clang/test/DXC/Passes/InstructionCombining/instcombine-opt-overflow-check-inserts-at-add.ll
+@@ -0,0 +1,187 @@
++; RUN: %dxopt %s -hlsl-passes-resume -instcombine,NoSink=0 -S | FileCheck %s
++
++; Generated from the following HLSL:
++;   cbuffer cbuffer_g : register(b0) {
++;     uint4 g[1];
++;   };
++;
++;   [numthreads(1, 1, 1)]
++;   void main() {
++;     uint a = 2147483648u;
++;     uint b = (g[0].x | 2651317025u);
++;     uint c = (b + 2651317025u);
++;     while (true) {
++;       bool d = (a > c);
++;       if (d) {
++;         break;
++;       } else {
++;         while (true) {
++;           if (!d) {
++;             return;
++;           }
++;           a = b;
++;           bool e = (d ? d : d);
++;           if (e) {
++;             break;
++;           }
++;         }
++;       }
++;     }
++;   }
++;
++; Compiling this was resulting in invalid IR being produced from instcombine.
++; Specifically, when optimizing an overflow check of an add followed by a compare,
++; the new instruction was being inserted at the compare, and the add removed. This
++; broke in cases like this one, where there were other uses of the former add between
++; it and the compare. The fix was to make sure to insert the new instruction
++; (another add in this case) at the old add rather than at the compare.
++
++; Make sure the new %add is still in the entry block before its uses.
++; CHECK-LABEL: entry
++; CHECK:         %add = add i32 %or, -1643650271
++; CHECK-NEXT:    %cmp.2 = icmp sgt i32 %add, -1,
++;
++; Make sure the new %add is NOT in the loopexit where %cmp was optimized.
++; CHECK-LABEL: while.body.loopexit
++; CHECK-NEXT:    br i1 false, label %if.end.preheader, label %while.end.14
++
++;
++; Buffer Definitions:
++;
++; cbuffer cbuffer_g
++; {
++;
++;   struct cbuffer_g
++;   {
++;
++;       uint4 g[1];                                   ; Offset:    0
++;
++;   } cbuffer_g;                                      ; Offset:    0 Size:    16
++;
++; }
++;
++;
++; Resource Bindings:
++;
++; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
++; ------------------------------ ---------- ------- ----------- ------- -------------- ------
++; cbuffer_g                         cbuffer      NA          NA     CB0            cb0     1
++;
++target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
++target triple = "dxil-ms-dx"
++
++%cbuffer_g = type { [1 x <4 x i32>] }
++%dx.types.Handle = type { i8* }
++%dx.types.ResourceProperties = type { i32, i32 }
++%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 }
++
++@cbuffer_g = external constant %cbuffer_g
[email protected] = appending global [1 x i8*] [i8* bitcast (%cbuffer_g* @cbuffer_g to i8*)], section "llvm.metadata"
++
++; Function Attrs: nounwind
++define void @main() #0 {
++entry:
++  %0 = load %cbuffer_g, %cbuffer_g* @cbuffer_g
++  %cbuffer_g = call %dx.types.Handle @dx.op.createHandleForLib.cbuffer_g(i32 160, %cbuffer_g %0)  ; CreateHandleForLib(Resource)
++  %1 = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %cbuffer_g, %dx.types.ResourceProperties { i32 13, i32 16 })  ; AnnotateHandle(res,props)  resource: CBuffer
++  %2 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %1, i32 0), !dbg !19 ; line:8 col:13  ; CBufferLoadLegacy(handle,regIndex)
++  %3 = extractvalue %dx.types.CBufRet.i32 %2, 0, !dbg !19 ; line:8 col:13
++  %or = or i32 %3, -1643650271, !dbg !23 ; line:8 col:20
++  %add = add i32 %or, -1643650271, !dbg !24 ; line:9 col:15
++  %cmp.2 = icmp ugt i32 -2147483648, %add, !dbg !25 ; line:11 col:17
++  %frombool.3 = zext i1 %cmp.2 to i32, !dbg !26 ; line:11 col:10
++  %tobool1.4 = icmp eq i32 %frombool.3, 0, !dbg !27 ; line:12 col:9
++  %or.cond.6 = and i1 %tobool1.4, %cmp.2, !dbg !27 ; line:12 col:9
++  br i1 %or.cond.6, label %if.end.preheader, label %while.end.14, !dbg !27 ; line:12 col:9
++
++while.body.loopexit:                              ; preds = %if.end
++  %cmp = icmp ugt i32 %or, %add, !dbg !25 ; line:11 col:17
++  %frombool = zext i1 %cmp to i32, !dbg !26 ; line:11 col:10
++  %tobool1 = icmp eq i32 %frombool, 0, !dbg !27 ; line:12 col:9
++  %or.cond = and i1 %tobool1, %cmp, !dbg !27 ; line:12 col:9
++  br i1 %or.cond, label %if.end.preheader, label %while.end.14, !dbg !27 ; line:12 col:9
++
++if.end.preheader:                                 ; preds = %entry, %while.body.loopexit
++  %d.0 = phi i32 [ %frombool, %while.body.loopexit ], [ %frombool.3, %entry ]
++  br label %if.end, !dbg !28 ; line:19 col:13
++
++while.body.3:                                     ; preds = %if.end
++  %tobool4.old = icmp ne i32 %d.0, 0, !dbg !29 ; line:16 col:14
++  br i1 %tobool4.old, label %if.end, label %while.end.14, !dbg !30 ; line:16 col:13
++
++if.end:                                           ; preds = %if.end.preheader, %while.body.3
++  %tobool6 = icmp ne i32 %d.0, 0, !dbg !31 ; line:20 col:19
++  %tobool7 = icmp ne i32 %d.0, 0, !dbg !32 ; line:20 col:23
++  %tobool8 = icmp ne i32 %d.0, 0, !dbg !33 ; line:20 col:27
++  %4 = select i1 %tobool6, i1 %tobool7, i1 %tobool8, !dbg !31 ; line:20 col:19
++  br i1 %4, label %while.body.loopexit, label %while.body.3, !dbg !34 ; line:21 col:13
++
++while.end.14:                                     ; preds = %while.body.loopexit, %while.body.3, %entry
++  ret void, !dbg !35 ; line:27 col:1
++}
++
++; Function Attrs: nounwind readnone
++declare %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %cbuffer_g*, i32)"(i32, %cbuffer_g*, i32) #1
++
++; Function Attrs: nounwind readnone
++declare %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %cbuffer_g)"(i32, %dx.types.Handle, %dx.types.ResourceProperties, %cbuffer_g) #1
++
++; Function Attrs: nounwind readonly
++declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2
++
++; Function Attrs: nounwind readonly
++declare %dx.types.Handle @dx.op.createHandleForLib.cbuffer_g(i32, %cbuffer_g) #2
++
++; Function Attrs: nounwind readnone
++declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #1
++
++attributes #0 = { nounwind }
++attributes #1 = { nounwind readnone }
++attributes #2 = { nounwind readonly }
++
++!llvm.module.flags = !{!0}
++!pauseresume = !{!1}
++!llvm.ident = !{!2}
++!dx.version = !{!3}
++!dx.valver = !{!4}
++!dx.shaderModel = !{!5}
++!dx.resources = !{!6}
++!dx.typeAnnotations = !{!9, !12}
++!dx.entryPoints = !{!16}
++
++!0 = !{i32 2, !"Debug Info Version", i32 3}
++!1 = !{!"hlsl-dxilemit", !"hlsl-dxilload"}
++!2 = !{!"dxc(private) 1.8.0.4514 (d9bd2a706-dirty)"}
++!3 = !{i32 1, i32 0}
++!4 = !{i32 1, i32 8}
++!5 = !{!"cs", i32 6, i32 0}
++!6 = !{null, null, !7, null}
++!7 = !{!8}
++!8 = !{i32 0, %cbuffer_g* @cbuffer_g, !"cbuffer_g", i32 0, i32 0, i32 1, i32 16, null}
++!9 = !{i32 0, %cbuffer_g undef, !10}
++!10 = !{i32 16, !11}
++!11 = !{i32 6, !"g", i32 3, i32 0, i32 7, i32 5}
++!12 = !{i32 1, void ()* @main, !13}
++!13 = !{!14}
++!14 = !{i32 1, !15, !15}
++!15 = !{}
++!16 = !{void ()* @main, !"main", null, !6, !17}
++!17 = !{i32 4, !18}
++!18 = !{i32 1, i32 1, i32 1}
++!19 = !DILocation(line: 8, column: 13, scope: !20)
++!20 = !DISubprogram(name: "main", scope: !21, file: !21, line: 6, type: !22, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false, function: void ()* @main)
++!21 = !DIFile(filename: "/mnt/c/Users/amaiorano/Downloads/342545100/standalone_reduced.hlsl", directory: "")
++!22 = !DISubroutineType(types: !15)
++!23 = !DILocation(line: 8, column: 20, scope: !20)
++!24 = !DILocation(line: 9, column: 15, scope: !20)
++!25 = !DILocation(line: 11, column: 17, scope: !20)
++!26 = !DILocation(line: 11, column: 10, scope: !20)
++!27 = !DILocation(line: 12, column: 9, scope: !20)
++!28 = !DILocation(line: 19, column: 13, scope: !20)
++!29 = !DILocation(line: 16, column: 14, scope: !20)
++!30 = !DILocation(line: 16, column: 13, scope: !20)
++!31 = !DILocation(line: 20, column: 19, scope: !20)
++!32 = !DILocation(line: 20, column: 23, scope: !20)
++!33 = !DILocation(line: 20, column: 27, scope: !20)
++!34 = !DILocation(line: 21, column: 13, scope: !20)
++!35 = !DILocation(line: 27, column: 1, scope: !20)

+ 1 - 0
patches/angle/.patches

@@ -0,0 +1 @@
+cherry-pick-5d4df51d1d7d.patch

+ 28 - 0
patches/angle/cherry-pick-5d4df51d1d7d.patch

@@ -0,0 +1,28 @@
+From 5d4df51d1d7d6a290d54111527a4798f10c7ca3c Mon Sep 17 00:00:00 2001
+From: Shahbaz Youssefi <[email protected]>
+Date: Thu, 13 Jun 2024 16:54:03 -0400
+Subject: [PATCH] M126: Vulkan: Disable VK_EXT_shader_stencil_export on SwiftShader
+
+Bug: chromium:40942995
+Change-Id: I5035d9b11997a1c7c839d7d62544fecca9fd1f73
+Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5634418
+Reviewed-by: Yuly Novikov <[email protected]>
+---
+
+diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.cpp b/src/libANGLE/renderer/vulkan/vk_renderer.cpp
+index 581c84b..f818130 100644
+--- a/src/libANGLE/renderer/vulkan/vk_renderer.cpp
++++ b/src/libANGLE/renderer/vulkan/vk_renderer.cpp
+@@ -4287,9 +4287,11 @@
+     }
+ #endif  // defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_PLATFORM_LINUX)
+ 
++    // Disabled on SwiftShader due to http://crbug.com/40942995
+     ANGLE_FEATURE_CONDITION(
+         &mFeatures, supportsShaderStencilExport,
+-        ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
++        ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames) &&
++            !isSwiftShader);
+ 
+     ANGLE_FEATURE_CONDITION(
+         &mFeatures, supportsRenderPassLoadStoreOpNone,

+ 1 - 0
patches/v8/.patches

@@ -2,3 +2,4 @@ chore_allow_customizing_microtask_policy_per_context.patch
 deps_add_v8_object_setinternalfieldfornodecore.patch
 cherry-pick-8b400f9b7d66.patch
 cherry-pick-ba6cab40612d.patch
+merged_wasm_add_missing_type_canonicalization_for_exceptions_js.patch

+ 152 - 0
patches/v8/merged_wasm_add_missing_type_canonicalization_for_exceptions_js.patch

@@ -0,0 +1,152 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Thibaud Michaud <[email protected]>
+Date: Tue, 18 Jun 2024 11:34:17 +0200
+Subject: Merged: [wasm] Add missing type canonicalization for exceptions JS
+ API
+
+When we encode a JS value in a wasm exception, canonicalize the type
+stored in the tag's signature first. Canonicalize it using the tag's
+original module by storing the instance on the tag object.
+
[email protected]
+
+Bug: 346197738
+(cherry picked from commit 89dc6eab605cde2ffaa92dd9acf461caa63478de)
+
+Change-Id: I9a0b42702b1e5f7ef25091ed99c9bb00849bbc10
+Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5633661
+Reviewed-by: Jakob Kummerow <[email protected]>
+Commit-Queue: Thibaud Michaud <[email protected]>
+Cr-Commit-Position: refs/branch-heads/12.6@{#36}
+Cr-Branched-From: 3c9fa12db3183a6f4ea53d2675adb66ea1194529-refs/heads/12.6.228@{#2}
+Cr-Branched-From: 981bb15ba4dbf9e2381dfc94ec2c4af0b9c6a0b6-refs/heads/main@{#93835}
+
+diff --git a/src/wasm/module-instantiate.cc b/src/wasm/module-instantiate.cc
+index c74dc117ee21b999125a59549fa1f56a69313560..51b9d1e7492444a9bf96e7ea78b61f64fdc01ac9 100644
+--- a/src/wasm/module-instantiate.cc
++++ b/src/wasm/module-instantiate.cc
+@@ -2655,8 +2655,10 @@ void InstanceBuilder::ProcessExports(
+               isolate_);
+           uint32_t canonical_sig_index =
+               module_->isorecursive_canonical_type_ids[tag.sig_index];
++          Handle<WasmInstanceObject> instance =
++              handle(trusted_instance_data->instance_object(), isolate_);
+           wrapper = WasmTagObject::New(isolate_, tag.sig, canonical_sig_index,
+-                                       tag_object);
++                                       tag_object, instance);
+           tags_wrappers_[exp.index] = wrapper;
+         }
+         value = wrapper;
+diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc
+index c6d20d790c850437330b8718f32c916ae9412ff6..dc5cf36c26326c5787fe99b17651bc2af5d157ea 100644
+--- a/src/wasm/wasm-js.cc
++++ b/src/wasm/wasm-js.cc
+@@ -1852,7 +1852,8 @@ void WebAssemblyTagImpl(const v8::FunctionCallbackInfo<v8::Value>& info) {
+       i::wasm::GetWasmEngine()->type_canonicalizer()->AddRecursiveGroup(&sig);
+ 
+   i::Handle<i::JSObject> tag_object =
+-      i::WasmTagObject::New(i_isolate, &sig, canonical_type_index, tag);
++      i::WasmTagObject::New(i_isolate, &sig, canonical_type_index, tag,
++                            i_isolate->factory()->undefined_value());
+   info.GetReturnValue().Set(Utils::ToLocal(tag_object));
+ }
+ 
+@@ -1898,6 +1899,7 @@ uint32_t GetEncodedSize(i::Handle<i::WasmTagObject> tag_object) {
+ 
+ void EncodeExceptionValues(v8::Isolate* isolate,
+                            i::Handle<i::PodArray<i::wasm::ValueType>> signature,
++                           i::Handle<i::WasmTagObject> tag_object,
+                            const Local<Value>& arg, ErrorThrower* thrower,
+                            i::Handle<i::FixedArray> values_out) {
+   Local<Context> context = isolate->GetCurrentContext();
+@@ -1955,6 +1957,19 @@ void EncodeExceptionValues(v8::Isolate* isolate,
+       case i::wasm::kRefNull: {
+         const char* error_message;
+         i::Handle<i::Object> value_handle = Utils::OpenHandle(*value);
++
++        if (type.has_index()) {
++          // Canonicalize the type using the tag's original module.
++          i::Tagged<i::HeapObject> maybe_instance = tag_object->instance();
++          CHECK(!i::IsUndefined(maybe_instance));
++          auto instance = i::WasmInstanceObject::cast(maybe_instance);
++          const i::wasm::WasmModule* module = instance->module();
++          uint32_t canonical_index =
++              module->isorecursive_canonical_type_ids[type.ref_index()];
++          type = i::wasm::ValueType::RefMaybeNull(canonical_index,
++                                                  type.nullability());
++        }
++
+         if (!internal::wasm::JSToWasmObject(i_isolate, value_handle, type,
+                                             &error_message)
+                  .ToHandle(&value_handle)) {
+@@ -2010,7 +2025,8 @@ void WebAssemblyExceptionImpl(const v8::FunctionCallbackInfo<v8::Value>& info) {
+                                                   runtime_exception));
+   i::Handle<i::PodArray<i::wasm::ValueType>> signature(
+       tag_object->serialized_signature(), i_isolate);
+-  EncodeExceptionValues(isolate, signature, info[1], &thrower, values);
++  EncodeExceptionValues(isolate, signature, tag_object, info[1], &thrower,
++                        values);
+   if (thrower.error()) return;
+ 
+   // Third argument: optional ExceptionOption ({traceStack: <bool>}).
+@@ -3224,9 +3240,9 @@ void WasmJs::PrepareForSnapshot(Isolate* isolate) {
+     // Note the canonical_type_index is reset in WasmJs::Install s.t.
+     // type_canonicalizer bookkeeping remains valid.
+     static constexpr uint32_t kInitialCanonicalTypeIndex = 0;
+-    Handle<JSObject> js_tag_object =
+-        WasmTagObject::New(isolate, &kWasmExceptionTagSignature,
+-                           kInitialCanonicalTypeIndex, js_tag);
++    Handle<JSObject> js_tag_object = WasmTagObject::New(
++        isolate, &kWasmExceptionTagSignature, kInitialCanonicalTypeIndex,
++        js_tag, isolate->factory()->undefined_value());
+     native_context->set_wasm_js_tag(*js_tag_object);
+     JSObject::AddProperty(isolate, webassembly, "JSTag", js_tag_object,
+                           ro_attributes);
+diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc
+index ab1e4841a9f156601a544161ab4c6626f8e9d06e..c0c340d253370d8c443323577e9695975c899d28 100644
+--- a/src/wasm/wasm-objects.cc
++++ b/src/wasm/wasm-objects.cc
+@@ -1785,7 +1785,8 @@ void WasmArray::SetTaggedElement(uint32_t index, Handle<Object> value,
+ Handle<WasmTagObject> WasmTagObject::New(Isolate* isolate,
+                                          const wasm::FunctionSig* sig,
+                                          uint32_t canonical_type_index,
+-                                         Handle<HeapObject> tag) {
++                                         Handle<HeapObject> tag,
++                                         Handle<HeapObject> instance) {
+   Handle<JSFunction> tag_cons(isolate->native_context()->wasm_tag_constructor(),
+                               isolate);
+ 
+@@ -1806,6 +1807,7 @@ Handle<WasmTagObject> WasmTagObject::New(Isolate* isolate,
+   tag_wrapper->set_serialized_signature(*serialized_sig);
+   tag_wrapper->set_canonical_type_index(canonical_type_index);
+   tag_wrapper->set_tag(*tag);
++  tag_wrapper->set_instance(*instance);
+ 
+   return tag_wrapper;
+ }
+diff --git a/src/wasm/wasm-objects.h b/src/wasm/wasm-objects.h
+index 341e97040b69f9998e0441094a12434aede4f99d..a7495d3cbb394e143dc69c121361f1b17b26abc7 100644
+--- a/src/wasm/wasm-objects.h
++++ b/src/wasm/wasm-objects.h
+@@ -605,7 +605,8 @@ class WasmTagObject
+   static Handle<WasmTagObject> New(Isolate* isolate,
+                                    const wasm::FunctionSig* sig,
+                                    uint32_t canonical_type_index,
+-                                   Handle<HeapObject> tag);
++                                   Handle<HeapObject> tag,
++                                   Handle<HeapObject> instance);
+ 
+   TQ_OBJECT_CONSTRUCTORS(WasmTagObject)
+ };
+diff --git a/src/wasm/wasm-objects.tq b/src/wasm/wasm-objects.tq
+index dadb0342d08a948aaddf880a7b3d98df488ab627..7d937ec308f734b0ed168ddd455286d4d261d79f 100644
+--- a/src/wasm/wasm-objects.tq
++++ b/src/wasm/wasm-objects.tq
+@@ -211,6 +211,7 @@ extern class WasmGlobalObject extends JSObject {
+ extern class WasmTagObject extends JSObject {
+   serialized_signature: PodArrayOfWasmValueType;
+   tag: HeapObject;
++  instance: WasmInstanceObject|Undefined;
+   canonical_type_index: Smi;
+ }
+