blob: 8c6c95b124ebc08bcf3d051f31ce25ef79713695 [file] [edit]
//===-- WebAssemblyGISel.td - Wasm GlobalISel Patterns -----*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file contains patterns that are relevant to GlobalISel, including
/// GIComplexOperandMatcher definitions for equivalent SelectionDAG
/// ComplexPatterns.
//
//===----------------------------------------------------------------------===//
include "WebAssembly.td"
include "WebAssemblyCombine.td"
defvar ModeAddr32 = DefaultMode;
def ModeAddr64 : HwMode<[HasAddr64]>;
def p0i : ValueTypeByHwMode<[ModeAddr32, ModeAddr64],
[i32, i64]>;
def p0 : PtrValueTypeByHwMode<p0i, 0>;
def : Pat<(p0 (ptradd p0:$lhs, p0i:$rhs)),
(ADD_I32 I32:$lhs, I32:$rhs)>, Requires<[HasAddr32]>;
def : Pat<(p0 (ptradd p0:$lhs, p0i:$rhs)),
(ADD_I64 I64:$lhs, I64:$rhs)>, Requires<[HasAddr64]>;
def : Pat<(frameindex:$fi),
(COPY_I32 (to_tframeindex $fi))>, Requires<[HasAddr32]>;
def : Pat<(frameindex:$fi),
(COPY_I64 (to_tframeindex $fi))>, Requires<[HasAddr64]>;
// G_ICMP between p0
multiclass ComparisonP0<CondCode cond, string Name> {
def : Pat<(setcc p0:$lhs, p0:$rhs, cond),
(!cast<NI>(Name # "_I32") I32:$lhs, I32:$rhs)>, Requires<[HasAddr32]>;
def : Pat<(setcc p0:$lhs, p0:$rhs, cond),
(!cast<NI>(Name # "_I64") I64:$lhs, I64:$rhs)>, Requires<[HasAddr64]>;
}
defm : ComparisonP0<SETEQ, "EQ">;
defm : ComparisonP0<SETNE, "NE">;
defm : ComparisonP0<SETLT, "LT_S">;
defm : ComparisonP0<SETULT, "LT_U">;
defm : ComparisonP0<SETGT, "GT_S">;
defm : ComparisonP0<SETUGT, "GT_U">;
defm : ComparisonP0<SETLE, "LE_S">;
defm : ComparisonP0<SETULE, "LE_U">;
defm : ComparisonP0<SETGE, "GE_S">;
defm : ComparisonP0<SETUGE, "GE_U">;
// G_SELECT of p0
def : Pat<(select I32:$cond, p0:$lhs, p0:$rhs),
(SELECT_I32 I32:$lhs, I32:$rhs, I32:$cond)>, Requires<[HasAddr32]>;
def : Pat<(select I32:$cond, p0:$lhs, p0:$rhs),
(SELECT_I64 I64:$lhs, I64:$rhs, I32:$cond)>, Requires<[HasAddr64]>;
// ISD::SELECT requires its operand to conform to getBooleanContents, but
// WebAssembly's select interprets any non-zero value as true, so we can fold
// a setne with 0 into a select.
def : Pat<(select (i32 (setne I32:$cond, 0)), p0:$lhs, p0:$rhs),
(SELECT_I32 I32:$lhs, I32:$rhs, I32:$cond)>, Requires<[HasAddr32]>;
def : Pat<(select (i32 (setne I32:$cond, 0)), p0:$lhs, p0:$rhs),
(SELECT_I64 I64:$lhs, I64:$rhs, I32:$cond)>, Requires<[HasAddr64]>;
// And again, this time with seteq instead of setne and the arms reversed.
def : Pat<(select (i32 (seteq I32:$cond, 0)), p0:$lhs, p0:$rhs),
(SELECT_I32 I32:$rhs, I32:$lhs, I32:$cond)>, Requires<[HasAddr32]>;
def : Pat<(select (i32 (seteq I32:$cond, 0)), p0:$lhs, p0:$rhs),
(SELECT_I64 I64:$rhs, I64:$lhs, I32:$cond)>, Requires<[HasAddr64]>;
//===----------------------------------------------------------------------===//
// Complex pattern equivalents
//===----------------------------------------------------------------------===//
def gi_AddrOps32 : GIComplexOperandMatcher<s32, "selectAddrOperands32">,
GIComplexPatternEquiv<AddrOps32>;
def gi_AddrOps64 : GIComplexOperandMatcher<s64, "selectAddrOperands64">,
GIComplexPatternEquiv<AddrOps64>;