llvm.org GIT mirror llvm / 2ce5d0b
[globalisel] Introduce LegalityQuery to better encapsulate the legalizer decisions. NFC. Summary: `getAction(const InstrAspect &) const` breaks encapsulation by exposing the smaller components that are used to decide how to legalize an instruction. This is a problem because we need to change the implementation of LegalizerInfo so that it's able to describe particular type combinations rather than just cartesian products of types. For example, declaring the following setAction({..., 0, s32}, Legal) setAction({..., 0, s64}, Legal) setAction({..., 1, s32}, Legal) setAction({..., 1, s64}, Legal) currently declares these type combinations as legal: {s32, s32} {s64, s32} {s32, s64} {s64, s64} but we currently have no means to say that, for example, {s64, s32} is not legal. Some operations such as G_INSERT/G_EXTRACT/G_MERGE_VALUES/ G_UNMERGE_VALUES has relationships between the types that are currently described incorrectly. Additionally, G_LOAD/G_STORE currently have no means to legalize non-atomics differently to atomics. The necessary information is in the MMO but we have no way to use this in the legalizer. Similarly, there is currently no way for the register type and the memory type to differ so there is no way to cleanly represent extending-load/truncating-store in a way that can't be broken by optimizers (resulting in illegal MIR). This patch introduces LegalityQuery which provides all the information needed by the legalizer to make a decision on whether something is legal and how to legalize it. Reviewers: ab, t.p.northover, qcolombet, rovka, aditya_nandakumar, volkan, reames, bogner Reviewed By: bogner Subscribers: bogner, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D42244 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323342 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 2 years ago
5 changed file(s) with 146 addition(s) and 101 deletion(s). Raw diff Collapse all Expand all
5858 MI.getOperand(1).getReg(), MRI)) {
5959 unsigned DstReg = MI.getOperand(0).getReg();
6060 LLT DstTy = MRI.getType(DstReg);
61 if (isInstUnsupported(TargetOpcode::G_AND, DstTy) ||
62 isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy))
61 if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) ||
62 isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
6363 return false;
6464 DEBUG(dbgs() << ".. Combine MI: " << MI;);
6565 Builder.setInstr(MI);
8686 MI.getOperand(1).getReg(), MRI)) {
8787 unsigned DstReg = MI.getOperand(0).getReg();
8888 LLT DstTy = MRI.getType(DstReg);
89 if (isInstUnsupported(TargetOpcode::G_SHL, DstTy) ||
90 isInstUnsupported(TargetOpcode::G_ASHR, DstTy) ||
91 isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy))
89 if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) ||
90 isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) ||
91 isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}}))
9292 return false;
9393 DEBUG(dbgs() << ".. Combine MI: " << MI;);
9494 Builder.setInstr(MI);
120120 MI.getOperand(1).getReg(), MRI)) {
121121 unsigned DstReg = MI.getOperand(0).getReg();
122122 LLT DstTy = MRI.getType(DstReg);
123 if (isInstUnsupported(TargetOpcode::G_IMPLICIT_DEF, DstTy))
123 if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}}))
124124 return false;
125125 DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;);
126126 Builder.setInstr(MI);
276276
277277 /// Checks if the target legalizer info has specified anything about the
278278 /// instruction, or if unsupported.
279 bool isInstUnsupported(unsigned Opcode, const LLT &DstTy) const {
280 auto Action = LI.getAction({Opcode, 0, DstTy});
281 return Action.first == LegalizerInfo::LegalizeAction::Unsupported ||
282 Action.first == LegalizerInfo::LegalizeAction::NotFound;
279 bool isInstUnsupported(const LegalityQuery &Query) const {
280 auto Step = LI.getAction(Query);
281 return Step.Action == LegalizerInfo::LegalizeAction::Unsupported ||
282 Step.Action == LegalizerInfo::LegalizeAction::NotFound;
283283 }
284284 };
285285
5050 }
5151 };
5252
53 /// The LegalityQuery object bundles together all the information that's needed
54 /// to decide whether a given operation is legal or not.
55 /// For efficiency, it doesn't make a copy of Types so care must be taken not
56 /// to free it before using the query.
57 struct LegalityQuery {
58 unsigned Opcode;
59 ArrayRef Types;
60 };
61
5362 class LegalizerInfo {
5463 public:
5564 enum LegalizeAction : std::uint8_t {
97106
98107 /// Sentinel value for when no action was found in the specified table.
99108 NotFound,
109 };
110
111 /// The result of a query. It either indicates a final answer of Legal or
112 /// Unsupported or describes an action that must be taken to make an operation
113 /// more legal.
114 struct LegalizeActionStep {
115 /// The action to take or the final answer.
116 LegalizeAction Action;
117 /// If describing an action, the type index to change. Otherwise zero.
118 unsigned TypeIdx;
119 /// If describing an action, the new type for TypeIdx. Otherwise LLT{}.
120 LLT NewType;
121
122 LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx,
123 const LLT &NewType)
124 : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {}
125
126 bool operator==(const LegalizeActionStep &RHS) const {
127 return std::tie(Action, TypeIdx, NewType) ==
128 std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType);
129 }
100130 };
101131
102132 LegalizerInfo();
258288 LegalizeAction DecreaseAction,
259289 LegalizeAction IncreaseAction);
260290
291 /// Determine what action should be taken to legalize the described
292 /// instruction. Requires computeTables to have been called.
293 ///
294 /// \returns a description of the next legalization step to perform.
295 LegalizeActionStep getAction(const LegalityQuery &Query) const;
296
297 /// Determine what action should be taken to legalize the given generic
298 /// instruction.
299 ///
300 /// \returns a description of the next legalization step to perform.
301 LegalizeActionStep getAction(const MachineInstr &MI,
302 const MachineRegisterInfo &MRI) const;
303
304 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
305
306 virtual bool legalizeCustom(MachineInstr &MI,
307 MachineRegisterInfo &MRI,
308 MachineIRBuilder &MIRBuilder) const;
309
310 private:
261311 /// Determine what action should be taken to legalize the given generic
262312 /// instruction opcode, type-index and type. Requires computeTables to have
263313 /// been called.
264314 ///
265315 /// \returns a pair consisting of the kind of legalization that should be
266316 /// performed and the destination type.
267 std::pair getAction(const InstrAspect &Aspect) const;
268
269 /// Determine what action should be taken to legalize the given generic
270 /// instruction.
271 ///
272 /// \returns a tuple consisting of the LegalizeAction that should be
273 /// performed, the type-index it should be performed on and the destination
274 /// type.
275 std::tuple
276 getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
277
278 bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const;
279
280 virtual bool legalizeCustom(MachineInstr &MI,
281 MachineRegisterInfo &MRI,
282 MachineIRBuilder &MIRBuilder) const;
283
284 private:
317 std::pair
318 getAspectAction(const InstrAspect &Aspect) const;
319
285320 /// The SizeAndActionsVec is a representation mapping between all natural
286321 /// numbers and an Action. The natural number represents the bit size of
287322 /// the InstrAspect. For example, for a target with native support for 32-bit
3535 LegalizerHelper::legalizeInstrStep(MachineInstr &MI) {
3636 DEBUG(dbgs() << "Legalizing: "; MI.print(dbgs()));
3737
38 auto Action = LI.getAction(MI, MRI);
39 switch (std::get<0>(Action)) {
38 auto Step = LI.getAction(MI, MRI);
39 switch (Step.Action) {
4040 case LegalizerInfo::Legal:
4141 DEBUG(dbgs() << ".. Already legal\n");
4242 return AlreadyLegal;
4545 return libcall(MI);
4646 case LegalizerInfo::NarrowScalar:
4747 DEBUG(dbgs() << ".. Narrow scalar\n");
48 return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
48 return narrowScalar(MI, Step.TypeIdx, Step.NewType);
4949 case LegalizerInfo::WidenScalar:
5050 DEBUG(dbgs() << ".. Widen scalar\n");
51 return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
51 return widenScalar(MI, Step.TypeIdx, Step.NewType);
5252 case LegalizerInfo::Lower:
5353 DEBUG(dbgs() << ".. Lower\n");
54 return lower(MI, std::get<1>(Action), std::get<2>(Action));
54 return lower(MI, Step.TypeIdx, Step.NewType);
5555 case LegalizerInfo::FewerElements:
5656 DEBUG(dbgs() << ".. Reduce number of elements\n");
57 return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
57 return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
5858 case LegalizerInfo::Custom:
5959 DEBUG(dbgs() << ".. Custom legalization\n");
6060 return LI.legalizeCustom(MI, MRI, MIRBuilder) ? Legalized
923923 // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
924924 // First, check if G_FNEG is marked as Lower. If so, we may
925925 // end up with an infinite loop as G_FSUB is used to legalize G_FNEG.
926 if (LI.getAction({G_FNEG, Ty}).first == LegalizerInfo::Lower)
926 if (LI.getAction({G_FNEG, {Ty}}).Action == LegalizerInfo::Lower)
927927 return UnableToLegalize;
928928 unsigned Res = MI.getOperand(0).getReg();
929929 unsigned LHS = MI.getOperand(1).getReg();
162162 // we have any hope of doing well with something like <13 x i3>. Even the common
163163 // cases should do better than what we have now.
164164 std::pair
165 LegalizerInfo::getAction(const InstrAspect &Aspect) const {
165 LegalizerInfo::getAspectAction(const InstrAspect &Aspect) const {
166166 assert(TablesInitialized && "backend forgot to call computeTables");
167167 // These *have* to be implemented for now, they're the fundamental basis of
168168 // how everything else is transformed.
185185 return MRI.getType(MI.getOperand(OpIdx).getReg());
186186 }
187187
188 std::tuple
188 LegalizerInfo::LegalizeActionStep
189 LegalizerInfo::getAction(const LegalityQuery &Query) const {
190 for (unsigned i = 0; i < Query.Types.size(); ++i) {
191 auto Action = getAspectAction({Query.Opcode, i, Query.Types[i]});
192 if (Action.first != Legal)
193 return {Action.first, i, Action.second};
194 }
195 return {Legal, 0, LLT{}};
196 }
197
198 LegalizerInfo::LegalizeActionStep
189199 LegalizerInfo::getAction(const MachineInstr &MI,
190200 const MachineRegisterInfo &MRI) const {
201 SmallVector Types;
191202 SmallBitVector SeenTypes(8);
192203 const MCOperandInfo *OpInfo = MI.getDesc().OpInfo;
193204 // FIXME: probably we'll need to cache the results here somehow?
204215 SeenTypes.set(TypeIdx);
205216
206217 LLT Ty = getTypeFromTypeIdx(MI, MRI, i, TypeIdx);
207 auto Action = getAction({MI.getOpcode(), TypeIdx, Ty});
208 if (Action.first != Legal)
209 return std::make_tuple(Action.first, TypeIdx, Action.second);
210 }
211 return std::make_tuple(Legal, 0, LLT{});
218 Types.push_back(Ty);
219 }
220 return getAction({MI.getOpcode(), Types});
212221 }
213222
214223 bool LegalizerInfo::isLegal(const MachineInstr &MI,
215224 const MachineRegisterInfo &MRI) const {
216 return std::get<0>(getAction(MI, MRI)) == Legal;
225 return getAction(MI, MRI).Action == Legal;
217226 }
218227
219228 bool LegalizerInfo::legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI,
5959
6060 for (unsigned opcode : {G_ADD, G_SUB}) {
6161 // Check we infer the correct types and actually do what we're told.
62 ASSERT_EQ(L.getAction({opcode, LLT::scalar(8)}),
63 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
64 ASSERT_EQ(L.getAction({opcode, LLT::scalar(16)}),
65 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
66 ASSERT_EQ(L.getAction({opcode, LLT::scalar(32)}),
67 std::make_pair(LegalizerInfo::Legal, LLT::scalar(32)));
68 ASSERT_EQ(L.getAction({opcode, LLT::scalar(64)}),
69 std::make_pair(LegalizerInfo::Legal, LLT::scalar(64)));
62 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(8)}}),
63 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
64 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(16)}}),
65 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
66 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(32)}}),
67 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Legal, 0, LLT{}));
68 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(64)}}),
69 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Legal, 0, LLT{}));
7070
7171 // Make sure the default for over-sized types applies.
72 ASSERT_EQ(L.getAction({opcode, LLT::scalar(128)}),
73 std::make_pair(LegalizerInfo::NarrowScalar, LLT::scalar(64)));
72 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(128)}}),
73 LegalizerInfo::LegalizeActionStep(LegalizerInfo::NarrowScalar, 0, LLT::scalar(64)));
7474 // Make sure we also handle unusual sizes
75 ASSERT_EQ(L.getAction({opcode, LLT::scalar(1)}),
76 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
77 ASSERT_EQ(L.getAction({opcode, LLT::scalar(31)}),
78 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
79 ASSERT_EQ(L.getAction({opcode, LLT::scalar(33)}),
80 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(64)));
81 ASSERT_EQ(L.getAction({opcode, LLT::scalar(63)}),
82 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(64)));
83 ASSERT_EQ(L.getAction({opcode, LLT::scalar(65)}),
84 std::make_pair(LegalizerInfo::NarrowScalar, LLT::scalar(64)));
75 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(1)}}),
76 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
77 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(31)}}),
78 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
79 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(33)}}),
80 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(64)));
81 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(63)}}),
82 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(64)));
83 ASSERT_EQ(L.getAction({opcode, {LLT::scalar(65)}}),
84 LegalizerInfo::LegalizeActionStep(LegalizerInfo::NarrowScalar, 0, LLT::scalar(64)));
8585 }
8686 }
8787
105105
106106 // Check we infer the correct types and actually do what we're told for some
107107 // simple cases.
108 ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 8)}),
109 std::make_pair(LegalizerInfo::Legal, LLT::vector(8, 8)));
110 ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 7)}),
111 std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(8, 8)));
112 ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),
113 std::make_pair(LegalizerInfo::MoreElements, LLT::vector(8, 8)));
114 ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 32)}),
115 std::make_pair(LegalizerInfo::FewerElements, LLT::vector(4, 32)));
108 ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 8)}}),
109 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Legal, 0, LLT{}));
110 ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 7)}}),
111 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::vector(8, 8)));
112 ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(2, 8)}}),
113 LegalizerInfo::LegalizeActionStep(LegalizerInfo::MoreElements, 0, LLT::vector(8, 8)));
114 ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 32)}}),
115 LegalizerInfo::LegalizeActionStep(LegalizerInfo::FewerElements, 0, LLT::vector(4, 32)));
116116 // Check a few non-power-of-2 sizes:
117 ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 3)}),
118 std::make_pair(LegalizerInfo::WidenScalar, LLT::vector(3, 8)));
119 ASSERT_EQ(L.getAction({G_ADD, LLT::vector(3, 8)}),
120 std::make_pair(LegalizerInfo::MoreElements, LLT::vector(8, 8)));
117 ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 3)}}),
118 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::vector(3, 8)));
119 ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 8)}}),
120 LegalizerInfo::LegalizeActionStep(LegalizerInfo::MoreElements, 0, LLT::vector(8, 8)));
121121 }
122122
123123 TEST(LegalizerInfoTest, MultipleTypes) {
136136 L.computeTables();
137137
138138 // Check we infer the correct types and actually do what we're told.
139 ASSERT_EQ(L.getAction({G_PTRTOINT, 0, s64}),
140 std::make_pair(LegalizerInfo::Legal, s64));
141 ASSERT_EQ(L.getAction({G_PTRTOINT, 1, p0}),
142 std::make_pair(LegalizerInfo::Legal, p0));
139 ASSERT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}),
140 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Legal, 0, LLT{}));
141
143142 // Make sure we also handle unusual sizes
144 ASSERT_EQ(L.getAction({G_PTRTOINT, 0, LLT::scalar(65)}),
145 std::make_pair(LegalizerInfo::NarrowScalar, s64));
146 ASSERT_EQ(L.getAction({G_PTRTOINT, 1, LLT::pointer(0, 32)}),
147 std::make_pair(LegalizerInfo::Unsupported, LLT::pointer(0, 32)));
143 ASSERT_EQ(
144 L.getAction({G_PTRTOINT, {LLT::scalar(65), s64}}),
145 LegalizerInfo::LegalizeActionStep(LegalizerInfo::NarrowScalar, 0, s64));
146 ASSERT_EQ(
147 L.getAction({G_PTRTOINT, {s64, LLT::pointer(0, 32)}}),
148 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Unsupported, 1, LLT::pointer(0, 32)));
148149 }
149150
150151 TEST(LegalizerInfoTest, MultipleSteps) {
160161
161162 L.computeTables();
162163
163 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(16)}),
164 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
165 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(32)}),
166 std::make_pair(LegalizerInfo::Lower, LLT::scalar(32)));
164 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}),
165 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
166 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(32)}}),
167 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Lower, 0, LLT::scalar(32)));
167168 }
168169
169170 TEST(LegalizerInfoTest, SizeChangeStrategy) {
178179
179180 // Check we infer the correct types and actually do what we're told.
180181 for (unsigned Size : {1, 8, 16, 32}) {
181 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(Size)}),
182 std::make_pair(LegalizerInfo::Legal, LLT::scalar(Size)));
182 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(Size)}}),
183 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Legal, 0, LLT{}));
183184 }
184 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(2)}),
185 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(8)));
186 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(7)}),
187 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(8)));
188 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(9)}),
189 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(16)));
190 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(17)}),
191 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
192 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(31)}),
193 std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
194 ASSERT_EQ(L.getAction({G_UREM, LLT::scalar(33)}),
195 std::make_pair(LegalizerInfo::Unsupported, LLT::scalar(33)));
185 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(2)}}),
186 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(8)));
187 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(7)}}),
188 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(8)));
189 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(9)}}),
190 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(16)));
191 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(17)}}),
192 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
193 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(31)}}),
194 LegalizerInfo::LegalizeActionStep(LegalizerInfo::WidenScalar, 0, LLT::scalar(32)));
195 ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(33)}}),
196 LegalizerInfo::LegalizeActionStep(LegalizerInfo::Unsupported, 0, LLT::scalar(33)));
196197 }
197198 }