Skip to content

[WebAssembly][TTI] Avoid crash when costing scalable vector shifts - #212759

Merged
anutosh491 merged 2 commits into
llvm:mainfrom
anutosh491:wasm_shift
Jul 30, 2026
Merged

[WebAssembly][TTI] Avoid crash when costing scalable vector shifts#212759
anutosh491 merged 2 commits into
llvm:mainfrom
anutosh491:wasm_shift

Conversation

@anutosh491

Copy link
Copy Markdown
Member

I see the following

 anutosh491@Anutoshs-MacBook-Air llvm-project % cat /private/tmp/wasm-scalable-shift-cost.ll
define <vscale x 4 x i32> @shift(<vscale x 4 x i32> %x,
                                 <vscale x 4 x i32> %amount) {
  %result = shl <vscale x 4 x i32> %x, %amount
  ret <vscale x 4 x i32> %result
}


 anutosh491@Anutoshs-MacBook-Air llvm-project % build-assert/bin/opt \
  -mtriple=wasm32-unknown-unknown \
  -mattr=+simd128 \
  -passes='print<cost-model>' \
  -disable-output \
  /private/tmp/wasm-scalable-shift-cost.ll
Printing analysis 'Cost Model Analysis' for function 'shift':
Cost Model: Assertion failed: (isa<To>(Val) && "cast<Ty>() argument of incompatible type!"), function cast, file Casting.h, line 572.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.      Program arguments: build-assert/bin/opt -mtriple=wasm32-unknown-unknown -mattr=+simd128 -passes=print<cost-model> -disable-output /private/tmp/wasm-scalable-shift-cost.ll
1.      Running pass "function(print<cost-model>)" on module "/private/tmp/wasm-scalable-shift-cost.ll"
2.      Running pass "print<cost-model>" on function "shift"
 #0 0x0000000105b7a56c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102f6256c)
 #1 0x0000000105b78248 llvm::sys::RunSignalHandlers() (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102f60248)
 #2 0x0000000105b7b170 SignalHandler(int, __siginfo*, void*) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102f63170)
 #3 0x000000018b5f7744 (/usr/lib/system/libsystem_platform.dylib+0x1804fb744)
 #4 0x000000018b5ed8d8 (/usr/lib/system/libsystem_pthread.dylib+0x1804f18d8)
 #5 0x000000018b4f4644 (/usr/lib/system/libsystem_c.dylib+0x1803f8644)
 #6 0x000000018b4f38a0 (/usr/lib/system/libsystem_c.dylib+0x1803f78a0)
 #7 0x0000000104036ddc llvm::BasicTTIImplBase<llvm::WebAssemblyTTIImpl>::getArithmeticInstrCost(unsigned int, llvm::Type*, llvm::TargetTransformInfo::TargetCostKind, llvm::TargetTransformInfo::OperandValueInfo, llvm::TargetTransformInfo::OperandValueInfo, llvm::ArrayRef<llvm::Value const*>, llvm::Instruction const*) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10141eddc)
 #8 0x000000010403b0ac llvm::TargetTransformInfoImplCRTPBase<llvm::WebAssemblyTTIImpl>::getInstructionCost(llvm::User const*, llvm::ArrayRef<llvm::Value const*>, llvm::TargetTransformInfo::TargetCostKind) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x1014230ac)
 #9 0x00000001049162c8 llvm::TargetTransformInfo::getInstructionCost(llvm::User const*, llvm::ArrayRef<llvm::Value const*>, llvm::TargetTransformInfo::TargetCostKind) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x101cfe2c8)
#10 0x00000001058d90b4 llvm::TargetTransformInfo::getInstructionCost(llvm::User const*, llvm::TargetTransformInfo::TargetCostKind) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102cc10b4)
#11 0x000000010468a368 getCost(llvm::Instruction&, llvm::TargetTransformInfo::TargetCostKind, llvm::TargetTransformInfo&) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x101a72368)
#12 0x0000000104689dd4 llvm::CostModelPrinterPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x101a71dd4)
#13 0x0000000105186554 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10256e554)
#14 0x000000010518a680 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102572680)
#15 0x0000000105185418 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10256d418)
#16 0x0000000106127cb0 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::__1::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10350fcb0)
#17 0x0000000106131eac optMain (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x103519eac)
#18 0x000000018b22fe00
zsh: abort      build-assert/bin/opt -mtriple=wasm32-unknown-unknown -mattr=+simd128 

@llvmorg-github-actions llvmorg-github-actions Bot added backend:WebAssembly llvm:analysis Includes value tracking, cost tables and constant folding labels Jul 29, 2026
@anutosh491

Copy link
Copy Markdown
Member Author

Basically WebAssemblyTTIImpl::getArithmeticInstrCost accepted any VectorType when handling vector shifts, but unconditionally cast it to FixedVectorType for non-uniform shift amounts. This caused an assertion failure when
costing a scalable-vector shift.

We should restrict the WebAssembly-specific shift cost calculation to FixedVectorType.

@llvmorg-github-actions

llvmorg-github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

@llvm/pr-subscribers-backend-webassembly

@llvm/pr-subscribers-llvm-analysis

Author: Anutosh Bhat (anutosh491)

Changes

I see the following

 anutosh491@<!-- -->Anutoshs-MacBook-Air llvm-project % cat /private/tmp/wasm-scalable-shift-cost.ll
define &lt;vscale x 4 x i32&gt; @<!-- -->shift(&lt;vscale x 4 x i32&gt; %x,
                                 &lt;vscale x 4 x i32&gt; %amount) {
  %result = shl &lt;vscale x 4 x i32&gt; %x, %amount
  ret &lt;vscale x 4 x i32&gt; %result
}


 anutosh491@<!-- -->Anutoshs-MacBook-Air llvm-project % build-assert/bin/opt \
  -mtriple=wasm32-unknown-unknown \
  -mattr=+simd128 \
  -passes='print&lt;cost-model&gt;' \
  -disable-output \
  /private/tmp/wasm-scalable-shift-cost.ll
Printing analysis 'Cost Model Analysis' for function 'shift':
Cost Model: Assertion failed: (isa&lt;To&gt;(Val) &amp;&amp; "cast&lt;Ty&gt;() argument of incompatible type!"), function cast, file Casting.h, line 572.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.      Program arguments: build-assert/bin/opt -mtriple=wasm32-unknown-unknown -mattr=+simd128 -passes=print&lt;cost-model&gt; -disable-output /private/tmp/wasm-scalable-shift-cost.ll
1.      Running pass "function(print&lt;cost-model&gt;)" on module "/private/tmp/wasm-scalable-shift-cost.ll"
2.      Running pass "print&lt;cost-model&gt;" on function "shift"
 #<!-- -->0 0x0000000105b7a56c llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102f6256c)
 #<!-- -->1 0x0000000105b78248 llvm::sys::RunSignalHandlers() (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102f60248)
 #<!-- -->2 0x0000000105b7b170 SignalHandler(int, __siginfo*, void*) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102f63170)
 #<!-- -->3 0x000000018b5f7744 (/usr/lib/system/libsystem_platform.dylib+0x1804fb744)
 #<!-- -->4 0x000000018b5ed8d8 (/usr/lib/system/libsystem_pthread.dylib+0x1804f18d8)
 #<!-- -->5 0x000000018b4f4644 (/usr/lib/system/libsystem_c.dylib+0x1803f8644)
 #<!-- -->6 0x000000018b4f38a0 (/usr/lib/system/libsystem_c.dylib+0x1803f78a0)
 #<!-- -->7 0x0000000104036ddc llvm::BasicTTIImplBase&lt;llvm::WebAssemblyTTIImpl&gt;::getArithmeticInstrCost(unsigned int, llvm::Type*, llvm::TargetTransformInfo::TargetCostKind, llvm::TargetTransformInfo::OperandValueInfo, llvm::TargetTransformInfo::OperandValueInfo, llvm::ArrayRef&lt;llvm::Value const*&gt;, llvm::Instruction const*) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10141eddc)
 #<!-- -->8 0x000000010403b0ac llvm::TargetTransformInfoImplCRTPBase&lt;llvm::WebAssemblyTTIImpl&gt;::getInstructionCost(llvm::User const*, llvm::ArrayRef&lt;llvm::Value const*&gt;, llvm::TargetTransformInfo::TargetCostKind) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x1014230ac)
 #<!-- -->9 0x00000001049162c8 llvm::TargetTransformInfo::getInstructionCost(llvm::User const*, llvm::ArrayRef&lt;llvm::Value const*&gt;, llvm::TargetTransformInfo::TargetCostKind) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x101cfe2c8)
#<!-- -->10 0x00000001058d90b4 llvm::TargetTransformInfo::getInstructionCost(llvm::User const*, llvm::TargetTransformInfo::TargetCostKind) const (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102cc10b4)
#<!-- -->11 0x000000010468a368 getCost(llvm::Instruction&amp;, llvm::TargetTransformInfo::TargetCostKind, llvm::TargetTransformInfo&amp;) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x101a72368)
#<!-- -->12 0x0000000104689dd4 llvm::CostModelPrinterPass::run(llvm::Function&amp;, llvm::AnalysisManager&lt;llvm::Function&gt;&amp;) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x101a71dd4)
#<!-- -->13 0x0000000105186554 llvm::PassManager&lt;llvm::Function, llvm::AnalysisManager&lt;llvm::Function&gt;&gt;::run(llvm::Function&amp;, llvm::AnalysisManager&lt;llvm::Function&gt;&amp;) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10256e554)
#<!-- -->14 0x000000010518a680 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&amp;, llvm::AnalysisManager&lt;llvm::Module&gt;&amp;) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x102572680)
#<!-- -->15 0x0000000105185418 llvm::PassManager&lt;llvm::Module, llvm::AnalysisManager&lt;llvm::Module&gt;&gt;::run(llvm::Module&amp;, llvm::AnalysisManager&lt;llvm::Module&gt;&amp;) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10256d418)
#<!-- -->16 0x0000000106127cb0 llvm::runPassPipeline(llvm::StringRef, llvm::Module&amp;, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef&lt;llvm::PassPlugin&gt;, llvm::ArrayRef&lt;std::__1::function&lt;void (llvm::PassBuilder&amp;)&gt;&gt;, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x10350fcb0)
#<!-- -->17 0x0000000106131eac optMain (/Users/anutosh491/work/llvm-project/build-assert/bin/opt+0x103519eac)
#<!-- -->18 0x000000018b22fe00
zsh: abort      build-assert/bin/opt -mtriple=wasm32-unknown-unknown -mattr=+simd128 

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

2 Files Affected:

  • (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp (+2-2)
  • (added) llvm/test/Analysis/CostModel/WebAssembly/vector-shift.ll (+42)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
index 7d1136bb9beba..75c631055ae2d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
@@ -82,7 +82,7 @@ InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
       BasicTTIImplBase<WebAssemblyTTIImpl>::getArithmeticInstrCost(
           Opcode, Ty, CostKind, Op1Info, Op2Info);
 
-  if (auto *VTy = dyn_cast<VectorType>(Ty)) {
+  if (auto *VTy = dyn_cast<FixedVectorType>(Ty)) {
     switch (Opcode) {
     case Instruction::LShr:
     case Instruction::AShr:
@@ -92,7 +92,7 @@ InstructionCost WebAssemblyTTIImpl::getArithmeticInstrCost(
       // approximation.
       if (!Op2Info.isUniform())
         Cost =
-            cast<FixedVectorType>(VTy)->getNumElements() *
+            VTy->getNumElements() *
             (TargetTransformInfo::TCC_Basic +
              getArithmeticInstrCost(Opcode, VTy->getElementType(), CostKind) +
              TargetTransformInfo::TCC_Basic);
diff --git a/llvm/test/Analysis/CostModel/WebAssembly/vector-shift.ll b/llvm/test/Analysis/CostModel/WebAssembly/vector-shift.ll
new file mode 100644
index 0000000000000..97f2a94b7b460
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/WebAssembly/vector-shift.ll
@@ -0,0 +1,42 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -mtriple=wasm32-unknown-unknown -mattr=+simd128 \
+; RUN:   -passes='print<cost-model>' -disable-output < %s 2>&1 | FileCheck %s
+
+define void @fixed_non_uniform(<4 x i32> %x, <4 x i32> %amount) {
+; CHECK-LABEL: 'fixed_non_uniform'
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 12 for instruction: %shl = shl <4 x i32> %x, %amount
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 12 for instruction: %lshr = lshr <4 x i32> %x, %amount
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 12 for instruction: %ashr = ashr <4 x i32> %x, %amount
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 1 for instruction: ret void
+;
+  %shl = shl <4 x i32> %x, %amount
+  %lshr = lshr <4 x i32> %x, %amount
+  %ashr = ashr <4 x i32> %x, %amount
+  ret void
+}
+
+define void @scalable_uniform(<vscale x 4 x i32> %x) {
+; CHECK-LABEL: 'scalable_uniform'
+; CHECK-NEXT:  Cost Model: Invalid cost for instruction: %shl = shl <vscale x 4 x i32> %x, splat (i32 1)
+; CHECK-NEXT:  Cost Model: Invalid cost for instruction: %lshr = lshr <vscale x 4 x i32> %x, splat (i32 1)
+; CHECK-NEXT:  Cost Model: Invalid cost for instruction: %ashr = ashr <vscale x 4 x i32> %x, splat (i32 1)
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 1 for instruction: ret void
+;
+  %shl = shl <vscale x 4 x i32> %x, splat (i32 1)
+  %lshr = lshr <vscale x 4 x i32> %x, splat (i32 1)
+  %ashr = ashr <vscale x 4 x i32> %x, splat (i32 1)
+  ret void
+}
+
+define void @scalable_non_uniform(<vscale x 4 x i32> %x, <vscale x 4 x i32> %amount) {
+; CHECK-LABEL: 'scalable_non_uniform'
+; CHECK-NEXT:  Cost Model: Invalid cost for instruction: %shl = shl <vscale x 4 x i32> %x, %amount
+; CHECK-NEXT:  Cost Model: Invalid cost for instruction: %lshr = lshr <vscale x 4 x i32> %x, %amount
+; CHECK-NEXT:  Cost Model: Invalid cost for instruction: %ashr = ashr <vscale x 4 x i32> %x, %amount
+; CHECK-NEXT:  Cost Model: Found an estimated cost of 1 for instruction: ret void
+;
+  %shl = shl <vscale x 4 x i32> %x, %amount
+  %lshr = lshr <vscale x 4 x i32> %x, %amount
+  %ashr = ashr <vscale x 4 x i32> %x, %amount
+  ret void
+}

@aheejin aheejin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not crashing here sounds fine, but we don't support compile scalable vectors anyway, no?

@anutosh491

anutosh491 commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

but we don't support compile scalable vectors anyway, no?

Yess ! Just a corner case I came across. Would help exit the scalable case gracefully.

@anutosh491

Copy link
Copy Markdown
Member Author

Thanks for the approval. Enabling auto merge.

@anutosh491
anutosh491 enabled auto-merge (squash) July 30, 2026 04:01
@anutosh491
anutosh491 disabled auto-merge July 30, 2026 07:45
@anutosh491
anutosh491 merged commit ddb662d into llvm:main Jul 30, 2026
12 checks passed
@anutosh491
anutosh491 deleted the wasm_shift branch July 30, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:WebAssembly llvm:analysis Includes value tracking, cost tables and constant folding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants