LLVM 23.0.0git
WebAssemblyLegalizerInfo.cpp
Go to the documentation of this file.
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
18
19#define DEBUG_TYPE "wasm-legalinfo"
20
21using namespace llvm;
22using namespace LegalizeActions;
23
25 const WebAssemblySubtarget &ST) {
26 using namespace TargetOpcode;
27
28 const LLT i32 = LLT::integer(32);
29 const LLT i64 = LLT::integer(64);
30
31 const LLT f32 = LLT::floatIEEE(32);
32 const LLT f64 = LLT::floatIEEE(64);
33
34 const LLT s32 = LLT::scalar(32);
35 const LLT s64 = LLT::scalar(64);
36
37 getActionDefinitionsBuilder(G_IMPLICIT_DEF)
38 .legalFor({i32, i64, f32, f64})
39 .widenScalarToNextPow2(0)
40 .clampScalar(0, s32, s64);
41
42 getActionDefinitionsBuilder({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({i32, i64})
45 .widenScalarToNextPow2(0)
46 .clampScalar(0, s32, s64);
47
48 getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL})
49 .legalFor({{i32, i32}, {i64, i64}})
50 .widenScalarToNextPow2(0)
51 .clampScalar(0, s32, s64)
52 .scalarSameSizeAs(1, 0);
53
54 getActionDefinitionsBuilder({G_CTLZ, G_CTTZ, G_CTPOP})
55 .legalFor({{i32, i32}, {i64, i64}})
56 .widenScalarToNextPow2(1)
57 .clampScalar(1, s32, s64)
58 .scalarSameSizeAs(0, 1);
59
60 getActionDefinitionsBuilder({G_CTLZ_ZERO_POISON, G_CTTZ_ZERO_POISON}).lower();
61
62 getActionDefinitionsBuilder({G_ROTL, G_ROTR})
63 .legalFor({{i32, i32}, {i64, i64}})
64 .scalarSameSizeAs(1, 0)
65 .lower();
66
67 getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
68
70 .legalForCartesianProduct({i32}, {i32, i64})
71 .widenScalarToNextPow2(1)
72 .clampScalar(0, s32, s32)
73 .clampScalar(1, s32, s64);
74
75 getActionDefinitionsBuilder({G_UMIN, G_UMAX, G_SMIN, G_SMAX}).lower();
76
77 getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
78
79 getActionDefinitionsBuilder({G_ANYEXT, G_SEXT, G_ZEXT})
80 .legalFor({{i64, i32}})
81 .clampScalar(0, s64, s64)
82 .clampScalar(1, s32, s32);
83
85 .legalFor({{i32, i64}})
86 .clampScalar(0, s32, s32)
87 .clampScalar(1, s64, s64);
88
89 getActionDefinitionsBuilder(G_SEXT_INREG)
90 .customFor(ST.hasSignExt(), {i32, i64})
91 .clampScalar(0, s32, s64)
92 .lower();
93
94 getActionDefinitionsBuilder({G_FCONSTANT, G_FABS, G_FNEG, G_FCEIL, G_FFLOOR,
95 G_INTRINSIC_TRUNC, G_FNEARBYINT, G_FRINT,
96 G_INTRINSIC_ROUNDEVEN, G_FSQRT, G_FADD, G_FSUB,
97 G_FMUL, G_FDIV})
98 .legalFor({f32, f64})
99 .minScalar(0, s32);
100
101 getActionDefinitionsBuilder(G_FCOPYSIGN)
102 .legalFor({f32, f64})
103 .minScalar(0, s32)
104 .scalarSameSizeAs(1, 0);
105
107 .legalFor({{f64, f32}})
108 .clampScalar(0, s64, s64)
109 .clampScalar(1, s32, s32);
110
112 .legalFor({{f32, f64}})
113 .clampScalar(0, s32, s32)
114 .clampScalar(1, s64, s64);
115
117 .legalFor({{i32, f32}, {f32, i32}, {i64, f64}, {f64, i64}})
118 .clampScalar(0, s32, s64)
119 .clampScalar(1, s32, s64);
120
121 getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
122 .legalForCartesianProduct({i32, i64}, {f32, f64})
123 .clampScalar(0, s32, s64)
124 .minScalar(1, s32);
125
126 // TODO: once comparison ops are in place
127 /*if (ST.hasNontrappingFPToInt()) {
128 getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
129 .legalForCartesianProduct({i32, i64}, {f32, f64})
130 .clampScalar(0, s32, s64)
131 .minScalar(1, s32);
132 } else {
133 getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
134 .lowerForCartesianProduct({i32, i64}, {f32, f64})
135 .clampScalar(0, s32, s64)
136 .minScalar(1, s32);
137 }*/
138
139 getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
140 .legalForCartesianProduct({f32, f64}, {i32, i64})
141 .minScalar(0, s32)
142 .clampScalar(1, s32, s64);
143
145 .legalForCartesianProduct({i32, i64, f32, f64}, {i32})
146 .widenScalarToNextPow2(0)
147 .clampScalar(0, s32, s64)
148 .clampScalar(1, s32, s32);
149
151}
152
155 LostDebugLocObserver &LocObserver) const {
156 switch (MI.getOpcode()) {
157 case TargetOpcode::G_SEXT_INREG: {
158 assert(MI.getOperand(2).isImm() && "Expected immediate");
159
160 // Mark only 8/16/32-bit SEXT_INREG as legal
161 auto [DstType, SrcType] = MI.getFirst2LLTs();
162 auto ExtFromWidth = MI.getOperand(2).getImm();
163
164 if (ExtFromWidth == 8 || ExtFromWidth == 16 ||
165 (DstType.getScalarSizeInBits() == 64 && ExtFromWidth == 32)) {
166 return true;
167 }
168
169 return Helper.lower(MI, 0, DstType) != LegalizerHelper::UnableToLegalize;
170 }
171 default:
172 break;
173 }
174 return false;
175}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
IRTranslator LLVM IR MI
Interface for Targets to specify which operations they can successfully select and how the others sho...
This file declares the targeting of the Machinelegalizer class for WebAssembly.
This file provides WebAssembly-specific target descriptions.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
static LLT integer(unsigned SizeInBits)
static LLT floatIEEE(unsigned SizeInBits)
LLVM_ABI void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)
Ensure the scalar is at least as wide as Ty.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)
Change the type TypeIdx to have the same scalar size as type SameSizeIdx.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)
Limit the range of scalar sizes to MinTy and MaxTy.
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & customFor(std::initializer_list< LLT > Types)
@ UnableToLegalize
Some kind of error has occurred and we could not legalize this instruction.
LLVM_ABI LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty)
Legalize an instruction by splitting it into simpler parts, hopefully understood by the target.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
Representation of each machine instruction.
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
WebAssemblyLegalizerInfo(const WebAssemblySubtarget &ST)
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.