Skip to content

Commit b00d0c5

Browse files
committed
[WASM] Fold bitselect with argument <0>
Fixes #73454 Fold bitselect with the splat <0> in either first or second argument. - For first argument <0>: vselect <0>, X, Y -> Y - For second argument <0>: vselect Y, <0>, X -> AND(<X>, !<Y>) - For third argument <0>: vselect X, Y, <0> -> AND(<Y>, <X>) Detailed explanation in the implementation.
1 parent 4f7a27c commit b00d0c5

File tree

2 files changed

+75
-14
lines changed

2 files changed

+75
-14
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
191191
// Combine vector mask reductions into alltrue/anytrue
192192
setTargetDAGCombine(ISD::SETCC);
193193

194+
// Convert vselect of various zero arguments to AND
195+
setTargetDAGCombine(ISD::VSELECT);
196+
194197
// Convert vector to integer bitcasts to bitmask
195198
setTargetDAGCombine(ISD::BITCAST);
196199

@@ -3210,6 +3213,64 @@ static SDValue performTruncateCombine(SDNode *N,
32103213
return truncateVectorWithNARROW(OutVT, In, DL, DAG);
32113214
}
32123215

3216+
static SDValue performVSelectCombine(SDNode *N, SelectionDAG &DAG) {
3217+
// In the tablegen.td, vselect A B C -> bitselect B C A
3218+
3219+
// SCENARIO A
3220+
// vselect <0>, X, Y
3221+
// -> bitselect X, Y, <0>
3222+
// -> or (AND(X, <0>), AND(<Y>, !<0>))
3223+
// -> or (0, AND(<Y>, !<0>))
3224+
// -> AND(Y, !<0>)
3225+
// -> AND(Y, 1)
3226+
// -> Y
3227+
3228+
// SCENARIO B
3229+
// vselect Y, <0>, X
3230+
// -> bitselect <0>, X, Y
3231+
// -> or (AND(<0>, Y), AND(<X>, !<Y>))
3232+
// -> or (0, AND(<X>, !<Y>))
3233+
// -> AND(<X>, !<Y>)
3234+
3235+
// SCENARIO C
3236+
// vselect X, Y, <0>
3237+
// -> bitselect Y, <0>, X
3238+
// -> or (AND(Y, X), AND(<0>, !X))
3239+
// -> or (AND(Y, X), <0>)
3240+
// -> AND(Y, X)
3241+
3242+
using namespace llvm::SDPatternMatch;
3243+
assert(N->getOpcode() == ISD::VSELECT);
3244+
3245+
SDLoc DL(N);
3246+
3247+
SDValue Cond = N->getOperand(0), LHS = N->getOperand(1),
3248+
RHS = N->getOperand(2);
3249+
EVT NVT = N->getValueType(0);
3250+
3251+
APInt SplatValue;
3252+
3253+
// SCENARIO A
3254+
if (ISD::isConstantSplatVector(Cond.getNode(), SplatValue) &&
3255+
SplatValue.isZero())
3256+
return RHS;
3257+
3258+
// SCENARIO B
3259+
if (ISD::isConstantSplatVector(LHS.getNode(), SplatValue) &&
3260+
SplatValue.isZero())
3261+
return DAG.getNode(
3262+
ISD::AND, DL, NVT,
3263+
{RHS, DAG.getSExtOrTrunc(DAG.getNOT(DL, Cond, Cond.getValueType()), DL,
3264+
NVT)});
3265+
3266+
// SCENARIO C
3267+
if (ISD::isConstantSplatVector(RHS.getNode(), SplatValue) &&
3268+
SplatValue.isZero())
3269+
return DAG.getNode(ISD::AND, DL, NVT,
3270+
{LHS, DAG.getSExtOrTrunc(Cond, DL, NVT)});
3271+
return SDValue();
3272+
}
3273+
32133274
static SDValue performBitcastCombine(SDNode *N,
32143275
TargetLowering::DAGCombinerInfo &DCI) {
32153276
using namespace llvm::SDPatternMatch;
@@ -3505,6 +3566,8 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
35053566
switch (N->getOpcode()) {
35063567
default:
35073568
return SDValue();
3569+
case ISD::VSELECT:
3570+
return performVSelectCombine(N, DCI.DAG);
35083571
case ISD::BITCAST:
35093572
return performBitcastCombine(N, DCI);
35103573
case ISD::SETCC:

llvm/test/CodeGen/WebAssembly/simd-bitselect.ll

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ define void @bitselect_first_zero(ptr %output, ptr %input) {
66
; CHECK-LABEL: bitselect_first_zero:
77
; CHECK: .functype bitselect_first_zero (i32, i32) -> ()
88
; CHECK-NEXT: # %bb.0: # %start
9-
; CHECK-NEXT: v128.const $push7=, 0, 0, 0, 0
10-
; CHECK-NEXT: local.tee $push6=, $3=, $pop7
11-
; CHECK-NEXT: v128.load $push5=, 0($1)
12-
; CHECK-NEXT: local.tee $push4=, $2=, $pop5
9+
; CHECK-NEXT: v128.load $push6=, 0($1)
10+
; CHECK-NEXT: local.tee $push5=, $2=, $pop6
1311
; CHECK-NEXT: v128.const $push0=, 2139095040, 2139095040, 2139095040, 2139095040
1412
; CHECK-NEXT: v128.and $push1=, $2, $pop0
15-
; CHECK-NEXT: i32x4.eq $push2=, $3, $pop1
16-
; CHECK-NEXT: v128.bitselect $push3=, $pop6, $pop4, $pop2
17-
; CHECK-NEXT: v128.store 0($0), $pop3
13+
; CHECK-NEXT: v128.const $push2=, 0, 0, 0, 0
14+
; CHECK-NEXT: i32x4.ne $push3=, $pop1, $pop2
15+
; CHECK-NEXT: v128.and $push4=, $pop5, $pop3
16+
; CHECK-NEXT: v128.store 0($0), $pop4
1817
; CHECK-NEXT: return
1918
start:
2019
%input.val = load <4 x i32>, ptr %input, align 16
@@ -30,15 +29,14 @@ define void @bitselect_second_zero(ptr %output, ptr %input) {
3029
; CHECK-LABEL: bitselect_second_zero:
3130
; CHECK: .functype bitselect_second_zero (i32, i32) -> ()
3231
; CHECK-NEXT: # %bb.0: # %start
33-
; CHECK-NEXT: v128.load $push7=, 0($1)
34-
; CHECK-NEXT: local.tee $push6=, $2=, $pop7
35-
; CHECK-NEXT: v128.const $push5=, 0, 0, 0, 0
36-
; CHECK-NEXT: local.tee $push4=, $3=, $pop5
32+
; CHECK-NEXT: v128.load $push6=, 0($1)
33+
; CHECK-NEXT: local.tee $push5=, $2=, $pop6
3734
; CHECK-NEXT: v128.const $push0=, 2139095040, 2139095040, 2139095040, 2139095040
3835
; CHECK-NEXT: v128.and $push1=, $2, $pop0
39-
; CHECK-NEXT: i32x4.eq $push2=, $3, $pop1
40-
; CHECK-NEXT: v128.bitselect $push3=, $pop6, $pop4, $pop2
41-
; CHECK-NEXT: v128.store 0($0), $pop3
36+
; CHECK-NEXT: v128.const $push2=, 0, 0, 0, 0
37+
; CHECK-NEXT: i32x4.eq $push3=, $pop1, $pop2
38+
; CHECK-NEXT: v128.and $push4=, $pop5, $pop3
39+
; CHECK-NEXT: v128.store 0($0), $pop4
4240
; CHECK-NEXT: return
4341
start:
4442
%input.val = load <4 x i32>, ptr %input, align 16

0 commit comments

Comments
 (0)