Skip to content

Commit 40e9092

Browse files
committed
Optimize away mask of 63 for shl ( zext (and i32 63)))
1 parent b707a7d commit 40e9092

File tree

5 files changed

+43
-4
lines changed

5 files changed

+43
-4
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ class WebAssemblyDAGToDAGISel final : public SelectionDAGISel {
7070
bool SelectAddrOperands32(SDValue Op, SDValue &Offset, SDValue &Addr);
7171
bool SelectAddrOperands64(SDValue Op, SDValue &Offset, SDValue &Addr);
7272

73+
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
74+
75+
bool selectShiftMask64FromI32(SDValue N, SDValue &ShAmt) {
76+
return selectShiftMask(N, 64, ShAmt);
77+
}
7378
// Include the pieces autogenerated from the target description.
7479
#include "WebAssemblyGenDAGISel.inc"
7580

@@ -539,6 +544,36 @@ bool WebAssemblyDAGToDAGISel::SelectAddrOperands64(SDValue Op, SDValue &Offset,
539544
return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, Op, Offset, Addr);
540545
}
541546

547+
bool WebAssemblyDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth,
548+
SDValue &ShAmt) {
549+
550+
ShAmt = N;
551+
552+
if (ShAmt.getOpcode() == ISD::AND &&
553+
isa<ConstantSDNode>(ShAmt.getOperand(1))) {
554+
const APInt &AndMask = ShAmt.getConstantOperandAPInt(1);
555+
556+
// Since the max shift amount is a power of 2 we can subtract 1 to make a
557+
// mask that covers the bits needed to represent all shift amounts.
558+
assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
559+
APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
560+
561+
if (ShMask.isSubsetOf(AndMask)) {
562+
ShAmt = ShAmt.getOperand(0);
563+
} else {
564+
// SimplifyDemandedBits may have optimized the mask so try restoring any
565+
// bits that are known zero.
566+
KnownBits Known = CurDAG->computeKnownBits(ShAmt.getOperand(0));
567+
if (ShMask.isSubsetOf(AndMask | Known.Zero))
568+
ShAmt = ShAmt.getOperand(0);
569+
}
570+
return true;
571+
}
572+
573+
// TODO: Port rest of riscv if applicable
574+
return false;
575+
}
576+
542577
/// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
543578
/// for instruction scheduling.
544579
FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,

llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3343,7 +3343,6 @@ static SDValue performAnyAllCombine(SDNode *N, SelectionDAG &DAG) {
33433343
Ret = DAG.getNOT(DL, Ret, MVT::i1);
33443344
return DAG.getZExtOrTrunc(Ret, DL, N->getValueType(0));
33453345
};
3346-
33473346
if (SDValue AnyTrueEQ = CombineSetCC(Intrinsic::wasm_anytrue, ISD::SETEQ,
33483347
Intrinsic::wasm_alltrue))
33493348
return AnyTrueEQ;

llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,8 @@ def : Pat<(i64 (WebAssemblyWrapperREL texternalsym:$addr)),
460460
include "WebAssemblyInstrMemory.td"
461461
include "WebAssemblyInstrCall.td"
462462
include "WebAssemblyInstrControl.td"
463-
include "WebAssemblyInstrInteger.td"
464463
include "WebAssemblyInstrConv.td"
464+
include "WebAssemblyInstrInteger.td"
465465
include "WebAssemblyInstrFloat.td"
466466
include "WebAssemblyInstrAtomics.td"
467467
include "WebAssemblyInstrSIMD.td"

llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ multiclass ComparisonInt<CondCode cond, string name, bits<32> i32Inst, bits<32>
4444
!strconcat("i64.", name), i64Inst>;
4545
}
4646

47+
// ComplexPattern
48+
def shiftMask64FromI32
49+
: ComplexPattern<i32, 1, "selectShiftMask64FromI32", [], [], 0>;
50+
4751
// The spaces after the names are for aesthetic purposes only, to make
4852
// operands line up vertically after tab expansion.
4953
let isCommutable = 1 in
@@ -101,6 +105,9 @@ def : Pat<(shl I64:$lhs, (and I64:$rhs, 63)), (SHL_I64 I64:$lhs, I64:$rhs)>;
101105
def : Pat<(sra I64:$lhs, (and I64:$rhs, 63)), (SHR_S_I64 I64:$lhs, I64:$rhs)>;
102106
def : Pat<(srl I64:$lhs, (and I64:$rhs, 63)), (SHR_U_I64 I64:$lhs, I64:$rhs)>;
103107

108+
def : Pat<(shl I64:$lhs, (zext(shiftMask64FromI32 I32:$rhs))),
109+
(SHL_I64 I64:$lhs, (I64_EXTEND_U_I32 I32:$rhs))>;
110+
104111
// Optimize away an explicit mask on a rotate count.
105112
def : Pat<(rotl I32:$lhs, (and I32:$rhs, 31)), (ROTL_I32 I32:$lhs, I32:$rhs)>;
106113
def : Pat<(rotr I32:$lhs, (and I32:$rhs, 31)), (ROTR_I32 I32:$lhs, I32:$rhs)>;

llvm/test/CodeGen/WebAssembly/masked-shifts.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ define i64 @shl_i64_i32(i64 %v, i32 %x) {
2424
; CHECK-NEXT: # %bb.0:
2525
; CHECK-NEXT: local.get 0
2626
; CHECK-NEXT: local.get 1
27-
; CHECK-NEXT: i32.const 63
28-
; CHECK-NEXT: i32.and
2927
; CHECK-NEXT: i64.extend_i32_u
3028
; CHECK-NEXT: i64.shl
3129
; CHECK-NEXT: # fallthrough-return

0 commit comments

Comments
 (0)