1//===- WebAssemblyLegalizerInfo.cpp ------------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements the targeting of the Machinelegalizer class for
10/// WebAssembly.
11//===----------------------------------------------------------------------===//
12
13#include "WebAssemblyLegalizerInfo.h"
14#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
15#include "WebAssemblySubtarget.h"
16#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
18
19#define DEBUG_TYPE "wasm-legalinfo"
20
21using namespace llvm;
22using namespace LegalizeActions;
23
24WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
25 const WebAssemblySubtarget &ST) {
26 using namespace TargetOpcode;
27
28 const LLT i32 = LLT::integer(SizeInBits: 32);
29 const LLT i64 = LLT::integer(SizeInBits: 64);
30
31 const LLT f32 = LLT::floatIEEE(SizeInBits: 32);
32 const LLT f64 = LLT::floatIEEE(SizeInBits: 64);
33
34 const LLT s32 = LLT::scalar(SizeInBits: 32);
35 const LLT s64 = LLT::scalar(SizeInBits: 64);
36
37 getActionDefinitionsBuilder(Opcode: G_IMPLICIT_DEF)
38 .legalFor(Types: {i32, i64, f32, f64})
39 .widenScalarToNextPow2(TypeIdx: 0)
40 .clampScalar(TypeIdx: 0, MinTy: s32, MaxTy: s64);
41
42 getActionDefinitionsBuilder(Opcodes: {G_CONSTANT, G_ADD, G_SUB, G_MUL, G_UDIV, G_SDIV,
43 G_UREM, G_SREM, G_AND, G_OR, G_XOR})
44 .legalFor(Types: {i32, i64})
45 .widenScalarToNextPow2(TypeIdx: 0)
46 .clampScalar(TypeIdx: 0, MinTy: s32, MaxTy: s64);
47
48 getActionDefinitionsBuilder(Opcodes: {G_ASHR, G_LSHR, G_SHL})
49 .legalFor(Types: {{i32, i32}, {i64, i64}})
50 .widenScalarToNextPow2(TypeIdx: 0)
51 .clampScalar(TypeIdx: 0, MinTy: s32, MaxTy: s64)
52 .scalarSameSizeAs(TypeIdx: 1, SameSizeIdx: 0);
53
54 getActionDefinitionsBuilder(Opcodes: {G_CTLZ, G_CTTZ, G_CTPOP})
55 .legalFor(Types: {{i32, i32}, {i64, i64}})
56 .widenScalarToNextPow2(TypeIdx: 1)
57 .clampScalar(TypeIdx: 1, MinTy: s32, MaxTy: s64)
58 .scalarSameSizeAs(TypeIdx: 0, SameSizeIdx: 1);
59
60 getActionDefinitionsBuilder(Opcodes: {G_CTLZ_ZERO_POISON, G_CTTZ_ZERO_POISON}).lower();
61
62 getActionDefinitionsBuilder(Opcodes: {G_ROTL, G_ROTR})
63 .legalFor(Types: {{i32, i32}, {i64, i64}})
64 .scalarSameSizeAs(TypeIdx: 1, SameSizeIdx: 0)
65 .lower();
66
67 getActionDefinitionsBuilder(Opcodes: {G_FSHL, G_FSHR}).lower();
68
69 getActionDefinitionsBuilder(Opcodes: {G_ANYEXT, G_SEXT, G_ZEXT})
70 .legalFor(Types: {{i64, i32}})
71 .clampScalar(TypeIdx: 0, MinTy: s64, MaxTy: s64)
72 .clampScalar(TypeIdx: 1, MinTy: s32, MaxTy: s32);
73
74 getActionDefinitionsBuilder(Opcode: G_TRUNC)
75 .legalFor(Types: {{i32, i64}})
76 .clampScalar(TypeIdx: 0, MinTy: s32, MaxTy: s32)
77 .clampScalar(TypeIdx: 1, MinTy: s64, MaxTy: s64);
78
79 getActionDefinitionsBuilder(Opcode: G_SEXT_INREG)
80 .customFor(Pred: ST.hasSignExt(), Types: {i32, i64})
81 .clampScalar(TypeIdx: 0, MinTy: s32, MaxTy: s64)
82 .lower();
83
84 getActionDefinitionsBuilder(Opcodes: {G_FCONSTANT, G_FABS, G_FNEG, G_FCEIL, G_FFLOOR,
85 G_INTRINSIC_TRUNC, G_FNEARBYINT, G_FRINT,
86 G_INTRINSIC_ROUNDEVEN, G_FSQRT, G_FADD, G_FSUB,
87 G_FMUL, G_FDIV})
88 .legalFor(Types: {f32, f64})
89 .minScalar(TypeIdx: 0, Ty: s32);
90
91 getActionDefinitionsBuilder(Opcode: G_FCOPYSIGN)
92 .legalFor(Types: {f32, f64})
93 .minScalar(TypeIdx: 0, Ty: s32)
94 .scalarSameSizeAs(TypeIdx: 1, SameSizeIdx: 0);
95
96 getActionDefinitionsBuilder(Opcode: G_FPEXT)
97 .legalFor(Types: {{f64, f32}})
98 .clampScalar(TypeIdx: 0, MinTy: s64, MaxTy: s64)
99 .clampScalar(TypeIdx: 1, MinTy: s32, MaxTy: s32);
100
101 getActionDefinitionsBuilder(Opcode: G_FPTRUNC)
102 .legalFor(Types: {{f32, f64}})
103 .clampScalar(TypeIdx: 0, MinTy: s32, MaxTy: s32)
104 .clampScalar(TypeIdx: 1, MinTy: s64, MaxTy: s64);
105
106 getLegacyLegalizerInfo().computeTables();
107}
108
109bool WebAssemblyLegalizerInfo::legalizeCustom(
110 LegalizerHelper &Helper, MachineInstr &MI,
111 LostDebugLocObserver &LocObserver) const {
112 switch (MI.getOpcode()) {
113 case TargetOpcode::G_SEXT_INREG: {
114 assert(MI.getOperand(2).isImm() && "Expected immediate");
115
116 // Mark only 8/16/32-bit SEXT_INREG as legal
117 auto [DstType, SrcType] = MI.getFirst2LLTs();
118 auto ExtFromWidth = MI.getOperand(i: 2).getImm();
119
120 if (ExtFromWidth == 8 || ExtFromWidth == 16 ||
121 (DstType.getScalarSizeInBits() == 64 && ExtFromWidth == 32)) {
122 return true;
123 }
124
125 return Helper.lower(MI, TypeIdx: 0, Ty: DstType) != LegalizerHelper::UnableToLegalize;
126 }
127 default:
128 break;
129 }
130 return false;
131}
132