Skip to content

Commit 51a9382

Browse files
committed
[WASM] Fix legalizer for LowerBUILD_VECTOR.
Constants in BUILD_VECTOR may be down cast into a smaller value that fits LaneBits, i.e., the bit width of elements in the vector. This cast didn't consider 2^N where it would be cast into -2^N, which still doesn't fit into LaneBits after casting. This will cause an assertion in later legalization. 2^N should be cast into 0, and this patch reflects such behavior. This patch also includes a test to reflect the fix. This patch fixes [issue 61780](#61780) Related patch: https://reviews.llvm.org/D108669 Reviewed By: tlively Differential Revision: https://reviews.llvm.org/D147208
1 parent 962484a commit 51a9382

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,8 @@ SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
21512151
assert((LaneBits == 64 || Val >= -(1ll << (LaneBits - 1))) &&
21522152
"Unexpected out of bounds negative value");
21532153
if (Const && LaneBits != 64 && Val > (1ll << (LaneBits - 1)) - 1) {
2154-
auto NewVal = ((uint64_t)Val % (1ll << LaneBits)) - (1ll << LaneBits);
2154+
uint64_t Mask = (1ll << LaneBits) - 1;
2155+
auto NewVal = (((uint64_t)Val & Mask) - (1ll << LaneBits)) & Mask;
21552156
ConstLanes.push_back(DAG.getConstant(NewVal, SDLoc(Lane), LaneT));
21562157
} else {
21572158
ConstLanes.push_back(Lane);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -mtriple=wasm32 -mattr=+simd128 -opaque-pointers | FileCheck %s
3+
4+
define void @f(ptr %0, ptr %pr) {
5+
; CHECK-LABEL: f:
6+
; CHECK: .functype f (i32, i32) -> ()
7+
; CHECK-NEXT: .local v128
8+
; CHECK-NEXT: # %bb.0: # %BB
9+
; CHECK-NEXT: local.get 1
10+
; CHECK-NEXT: local.get 2
11+
; CHECK-NEXT: i32.const 16
12+
; CHECK-NEXT: local.get 0
13+
; CHECK-NEXT: v128.load64_zero 0
14+
; CHECK-NEXT: v128.const 0, 1, 0, 0
15+
; CHECK-NEXT: i32x4.gt_u
16+
; CHECK-NEXT: local.tee 2
17+
; CHECK-NEXT: i32x4.extract_lane 0
18+
; CHECK-NEXT: i32.const 1
19+
; CHECK-NEXT: i32.and
20+
; CHECK-NEXT: i32.shr_u
21+
; CHECK-NEXT: local.tee 0
22+
; CHECK-NEXT: local.get 0
23+
; CHECK-NEXT: i32.mul
24+
; CHECK-NEXT: i8x16.replace_lane 0
25+
; CHECK-NEXT: i32.const 16
26+
; CHECK-NEXT: local.get 2
27+
; CHECK-NEXT: i32x4.extract_lane 1
28+
; CHECK-NEXT: i32.const 1
29+
; CHECK-NEXT: i32.and
30+
; CHECK-NEXT: i32.shr_u
31+
; CHECK-NEXT: local.tee 0
32+
; CHECK-NEXT: local.get 0
33+
; CHECK-NEXT: i32.mul
34+
; CHECK-NEXT: i8x16.replace_lane 1
35+
; CHECK-NEXT: v128.store16_lane 0, 0
36+
; CHECK-NEXT: # fallthrough-return
37+
BB:
38+
%v0 = load <2 x i32>, ptr %0
39+
%v1 = icmp ugt <2 x i32> %v0, <i32 0, i32 1>
40+
%v2 = zext <2 x i1> %v1 to <2 x i8>
41+
%v3 = ashr <2 x i8> <i8 16, i8 16>, %v2
42+
%v4 = mul <2 x i8> %v3, %v3
43+
store <2 x i8> %v4, ptr %pr
44+
ret void
45+
}
46+

0 commit comments

Comments
 (0)