1 | //===- llvm/unittest/CodeGen/AArch64SelectionDAGTest.cpp -------------------------===// |
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 | |
9 | #include "llvm/Analysis/MemoryLocation.h" |
10 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
11 | #include "llvm/AsmParser/Parser.h" |
12 | #include "llvm/CodeGen/MachineModuleInfo.h" |
13 | #include "llvm/CodeGen/SelectionDAG.h" |
14 | #include "llvm/CodeGen/TargetLowering.h" |
15 | #include "llvm/IR/MDBuilder.h" |
16 | #include "llvm/MC/TargetRegistry.h" |
17 | #include "llvm/Support/KnownBits.h" |
18 | #include "llvm/Support/SourceMgr.h" |
19 | #include "llvm/Support/TargetSelect.h" |
20 | #include "llvm/Target/TargetMachine.h" |
21 | #include "gtest/gtest.h" |
22 | |
23 | namespace llvm { |
24 | |
25 | class AArch64SelectionDAGTest : public testing::Test { |
26 | protected: |
27 | static void SetUpTestCase() { |
28 | InitializeAllTargets(); |
29 | InitializeAllTargetMCs(); |
30 | } |
31 | |
32 | void SetUp() override { |
33 | StringRef Assembly = "define void @f() { ret void }" ; |
34 | |
35 | Triple TargetTriple("aarch64--" ); |
36 | std::string Error; |
37 | const Target *T = TargetRegistry::lookupTarget(ArchName: "" , TheTriple&: TargetTriple, Error); |
38 | // FIXME: These tests do not depend on AArch64 specifically, but we have to |
39 | // initialize a target. A skeleton Target for unittests would allow us to |
40 | // always run these tests. |
41 | if (!T) |
42 | GTEST_SKIP(); |
43 | |
44 | TargetOptions Options; |
45 | TM = std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>( |
46 | T->createTargetMachine(TT: "AArch64" , CPU: "" , Features: "+sve" , Options, RM: std::nullopt, |
47 | CM: std::nullopt, OL: CodeGenOptLevel::Aggressive))); |
48 | if (!TM) |
49 | GTEST_SKIP(); |
50 | |
51 | SMDiagnostic SMError; |
52 | M = parseAssemblyString(AsmString: Assembly, Err&: SMError, Context); |
53 | if (!M) |
54 | report_fatal_error(reason: SMError.getMessage()); |
55 | M->setDataLayout(TM->createDataLayout()); |
56 | |
57 | F = M->getFunction(Name: "f" ); |
58 | if (!F) |
59 | report_fatal_error(reason: "F?" ); |
60 | |
61 | MachineModuleInfo MMI(TM.get()); |
62 | |
63 | MF = std::make_unique<MachineFunction>(args&: *F, args&: *TM, args: *TM->getSubtargetImpl(*F), args: 0, |
64 | args&: MMI); |
65 | |
66 | DAG = std::make_unique<SelectionDAG>(args&: *TM, args: CodeGenOptLevel::None); |
67 | if (!DAG) |
68 | report_fatal_error(reason: "DAG?" ); |
69 | OptimizationRemarkEmitter ORE(F); |
70 | DAG->init(NewMF&: *MF, NewORE&: ORE, PassPtr: nullptr, LibraryInfo: nullptr, UA: nullptr, PSIin: nullptr, BFIin: nullptr, FnVarLocs: nullptr); |
71 | } |
72 | |
73 | TargetLoweringBase::LegalizeTypeAction getTypeAction(EVT VT) { |
74 | return DAG->getTargetLoweringInfo().getTypeAction(Context, VT); |
75 | } |
76 | |
77 | EVT getTypeToTransformTo(EVT VT) { |
78 | return DAG->getTargetLoweringInfo().getTypeToTransformTo(Context, VT); |
79 | } |
80 | |
81 | LLVMContext Context; |
82 | std::unique_ptr<LLVMTargetMachine> TM; |
83 | std::unique_ptr<Module> M; |
84 | Function *F; |
85 | std::unique_ptr<MachineFunction> MF; |
86 | std::unique_ptr<SelectionDAG> DAG; |
87 | }; |
88 | |
89 | TEST_F(AArch64SelectionDAGTest, computeKnownBits_ZERO_EXTEND_VECTOR_INREG) { |
90 | SDLoc Loc; |
91 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
92 | auto Int16VT = EVT::getIntegerVT(Context, BitWidth: 16); |
93 | auto InVecVT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 4); |
94 | auto OutVecVT = EVT::getVectorVT(Context, VT: Int16VT, NumElements: 2); |
95 | auto InVec = DAG->getConstant(Val: 0, DL: Loc, VT: InVecVT); |
96 | auto Op = DAG->getNode(Opcode: ISD::ZERO_EXTEND_VECTOR_INREG, DL: Loc, VT: OutVecVT, Operand: InVec); |
97 | auto DemandedElts = APInt(2, 3); |
98 | KnownBits Known = DAG->computeKnownBits(Op, DemandedElts); |
99 | EXPECT_TRUE(Known.isZero()); |
100 | } |
101 | |
102 | TEST_F(AArch64SelectionDAGTest, computeKnownBitsSVE_ZERO_EXTEND_VECTOR_INREG) { |
103 | SDLoc Loc; |
104 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
105 | auto Int16VT = EVT::getIntegerVT(Context, BitWidth: 16); |
106 | auto InVecVT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 4, IsScalable: true); |
107 | auto OutVecVT = EVT::getVectorVT(Context, VT: Int16VT, NumElements: 2, IsScalable: true); |
108 | auto InVec = DAG->getConstant(Val: 0, DL: Loc, VT: InVecVT); |
109 | auto Op = DAG->getNode(Opcode: ISD::ZERO_EXTEND_VECTOR_INREG, DL: Loc, VT: OutVecVT, Operand: InVec); |
110 | auto DemandedElts = APInt(2, 3); |
111 | KnownBits Known = DAG->computeKnownBits(Op, DemandedElts); |
112 | |
113 | // We don't know anything for SVE at the moment. |
114 | EXPECT_EQ(Known.Zero, APInt(16, 0u)); |
115 | EXPECT_EQ(Known.One, APInt(16, 0u)); |
116 | EXPECT_FALSE(Known.isZero()); |
117 | } |
118 | |
119 | TEST_F(AArch64SelectionDAGTest, computeKnownBits_EXTRACT_SUBVECTOR) { |
120 | SDLoc Loc; |
121 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
122 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 3); |
123 | auto IdxVT = EVT::getIntegerVT(Context, BitWidth: 64); |
124 | auto Vec = DAG->getConstant(Val: 0, DL: Loc, VT: VecVT); |
125 | auto ZeroIdx = DAG->getConstant(Val: 0, DL: Loc, VT: IdxVT); |
126 | auto Op = DAG->getNode(Opcode: ISD::EXTRACT_SUBVECTOR, DL: Loc, VT: VecVT, N1: Vec, N2: ZeroIdx); |
127 | auto DemandedElts = APInt(3, 7); |
128 | KnownBits Known = DAG->computeKnownBits(Op, DemandedElts); |
129 | EXPECT_TRUE(Known.isZero()); |
130 | } |
131 | |
132 | TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_SIGN_EXTEND_VECTOR_INREG) { |
133 | SDLoc Loc; |
134 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
135 | auto Int16VT = EVT::getIntegerVT(Context, BitWidth: 16); |
136 | auto InVecVT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 4); |
137 | auto OutVecVT = EVT::getVectorVT(Context, VT: Int16VT, NumElements: 2); |
138 | auto InVec = DAG->getConstant(Val: 1, DL: Loc, VT: InVecVT); |
139 | auto Op = DAG->getNode(Opcode: ISD::SIGN_EXTEND_VECTOR_INREG, DL: Loc, VT: OutVecVT, Operand: InVec); |
140 | auto DemandedElts = APInt(2, 3); |
141 | EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 15u); |
142 | } |
143 | |
144 | TEST_F(AArch64SelectionDAGTest, ComputeNumSignBitsSVE_SIGN_EXTEND_VECTOR_INREG) { |
145 | SDLoc Loc; |
146 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
147 | auto Int16VT = EVT::getIntegerVT(Context, BitWidth: 16); |
148 | auto InVecVT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 4, /*IsScalable=*/true); |
149 | auto OutVecVT = EVT::getVectorVT(Context, VT: Int16VT, NumElements: 2, /*IsScalable=*/true); |
150 | auto InVec = DAG->getConstant(Val: 1, DL: Loc, VT: InVecVT); |
151 | auto Op = DAG->getNode(Opcode: ISD::SIGN_EXTEND_VECTOR_INREG, DL: Loc, VT: OutVecVT, Operand: InVec); |
152 | auto DemandedElts = APInt(2, 3); |
153 | EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 1u); |
154 | } |
155 | |
156 | TEST_F(AArch64SelectionDAGTest, ComputeNumSignBits_EXTRACT_SUBVECTOR) { |
157 | SDLoc Loc; |
158 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
159 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 3); |
160 | auto IdxVT = EVT::getIntegerVT(Context, BitWidth: 64); |
161 | auto Vec = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
162 | auto ZeroIdx = DAG->getConstant(Val: 0, DL: Loc, VT: IdxVT); |
163 | auto Op = DAG->getNode(Opcode: ISD::EXTRACT_SUBVECTOR, DL: Loc, VT: VecVT, N1: Vec, N2: ZeroIdx); |
164 | auto DemandedElts = APInt(3, 7); |
165 | EXPECT_EQ(DAG->ComputeNumSignBits(Op, DemandedElts), 7u); |
166 | } |
167 | |
168 | TEST_F(AArch64SelectionDAGTest, SimplifyDemandedVectorElts_EXTRACT_SUBVECTOR) { |
169 | TargetLowering TL(*TM); |
170 | |
171 | SDLoc Loc; |
172 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
173 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 3); |
174 | auto IdxVT = EVT::getIntegerVT(Context, BitWidth: 64); |
175 | auto Vec = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
176 | auto ZeroIdx = DAG->getConstant(Val: 0, DL: Loc, VT: IdxVT); |
177 | auto Op = DAG->getNode(Opcode: ISD::EXTRACT_SUBVECTOR, DL: Loc, VT: VecVT, N1: Vec, N2: ZeroIdx); |
178 | auto DemandedElts = APInt(3, 7); |
179 | auto KnownUndef = APInt(3, 0); |
180 | auto KnownZero = APInt(3, 0); |
181 | TargetLowering::TargetLoweringOpt TLO(*DAG, false, false); |
182 | EXPECT_EQ(TL.SimplifyDemandedVectorElts(Op, DemandedElts, KnownUndef, |
183 | KnownZero, TLO), |
184 | false); |
185 | } |
186 | |
187 | TEST_F(AArch64SelectionDAGTest, SimplifyDemandedBitsNEON) { |
188 | TargetLowering TL(*TM); |
189 | |
190 | SDLoc Loc; |
191 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
192 | auto InVecVT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 16); |
193 | SDValue UnknownOp = DAG->getRegister(Reg: 0, VT: InVecVT); |
194 | SDValue Mask1S = DAG->getConstant(Val: 0x8A, DL: Loc, VT: Int8VT); |
195 | SDValue Mask1V = DAG->getSplatBuildVector(VT: InVecVT, DL: Loc, Op: Mask1S); |
196 | SDValue N0 = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: InVecVT, N1: Mask1V, N2: UnknownOp); |
197 | |
198 | SDValue Mask2S = DAG->getConstant(Val: 0x55, DL: Loc, VT: Int8VT); |
199 | SDValue Mask2V = DAG->getSplatBuildVector(VT: InVecVT, DL: Loc, Op: Mask2S); |
200 | |
201 | SDValue Op = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: InVecVT, N1: N0, N2: Mask2V); |
202 | // N0 = ?000?0?0 |
203 | // Mask2V = 01010101 |
204 | // => |
205 | // Known.Zero = 00100000 (0xAA) |
206 | KnownBits Known; |
207 | APInt DemandedBits = APInt(8, 0xFF); |
208 | TargetLowering::TargetLoweringOpt TLO(*DAG, false, false); |
209 | EXPECT_TRUE(TL.SimplifyDemandedBits(Op, DemandedBits, Known, TLO)); |
210 | EXPECT_EQ(Known.Zero, APInt(8, 0xAA)); |
211 | } |
212 | |
213 | TEST_F(AArch64SelectionDAGTest, SimplifyDemandedBitsSVE) { |
214 | TargetLowering TL(*TM); |
215 | |
216 | SDLoc Loc; |
217 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
218 | auto InVecVT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 16, /*IsScalable=*/true); |
219 | SDValue UnknownOp = DAG->getRegister(Reg: 0, VT: InVecVT); |
220 | SDValue Mask1S = DAG->getConstant(Val: 0x8A, DL: Loc, VT: Int8VT); |
221 | SDValue Mask1V = DAG->getSplatVector(VT: InVecVT, DL: Loc, Op: Mask1S); |
222 | SDValue N0 = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: InVecVT, N1: Mask1V, N2: UnknownOp); |
223 | |
224 | SDValue Mask2S = DAG->getConstant(Val: 0x55, DL: Loc, VT: Int8VT); |
225 | SDValue Mask2V = DAG->getSplatVector(VT: InVecVT, DL: Loc, Op: Mask2S); |
226 | |
227 | SDValue Op = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: InVecVT, N1: N0, N2: Mask2V); |
228 | |
229 | // N0 = ?000?0?0 |
230 | // Mask2V = 01010101 |
231 | // => |
232 | // Known.Zero = 00100000 (0xAA) |
233 | KnownBits Known; |
234 | APInt DemandedBits = APInt(8, 0xFF); |
235 | TargetLowering::TargetLoweringOpt TLO(*DAG, false, false); |
236 | EXPECT_TRUE(TL.SimplifyDemandedBits(Op, DemandedBits, Known, TLO)); |
237 | EXPECT_EQ(Known.Zero, APInt(8, 0xAA)); |
238 | } |
239 | |
240 | // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. |
241 | TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_ADD) { |
242 | SDLoc Loc; |
243 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
244 | auto UnknownOp = DAG->getRegister(Reg: 0, VT: IntVT); |
245 | auto Mask = DAG->getConstant(Val: 0x8A, DL: Loc, VT: IntVT); |
246 | auto N0 = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: IntVT, N1: Mask, N2: UnknownOp); |
247 | auto N1 = DAG->getConstant(Val: 0x55, DL: Loc, VT: IntVT); |
248 | auto Op = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: IntVT, N1: N0, N2: N1); |
249 | // N0 = ?000?0?0 |
250 | // N1 = 01010101 |
251 | // => |
252 | // Known.One = 01010101 (0x55) |
253 | // Known.Zero = 00100000 (0x20) |
254 | KnownBits Known = DAG->computeKnownBits(Op); |
255 | EXPECT_EQ(Known.Zero, APInt(8, 0x20)); |
256 | EXPECT_EQ(Known.One, APInt(8, 0x55)); |
257 | } |
258 | |
259 | // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. |
260 | TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_UADDO_CARRY) { |
261 | SDLoc Loc; |
262 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
263 | auto UnknownOp = DAG->getRegister(Reg: 0, VT: IntVT); |
264 | auto Mask_Zero = DAG->getConstant(Val: 0x28, DL: Loc, VT: IntVT); |
265 | auto Mask_One = DAG->getConstant(Val: 0x20, DL: Loc, VT: IntVT); |
266 | auto N0 = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: IntVT, N1: Mask_Zero, N2: UnknownOp); |
267 | N0 = DAG->getNode(Opcode: ISD::OR, DL: Loc, VT: IntVT, N1: Mask_One, N2: N0); |
268 | auto N1 = DAG->getConstant(Val: 0x65, DL: Loc, VT: IntVT); |
269 | |
270 | KnownBits Known; |
271 | |
272 | auto UnknownBorrow = DAG->getRegister(Reg: 1, VT: IntVT); |
273 | auto OpUnknownBorrow = |
274 | DAG->getNode(Opcode: ISD::UADDO_CARRY, DL: Loc, VT: IntVT, N1: N0, N2: N1, N3: UnknownBorrow); |
275 | // N0 = 0010?000 |
276 | // N1 = 01100101 |
277 | // B = ? |
278 | // => |
279 | // Known.Zero = 01110000 (0x70) |
280 | // Known.One = 10000100 (0x84) |
281 | Known = DAG->computeKnownBits(Op: OpUnknownBorrow); |
282 | EXPECT_EQ(Known.Zero, APInt(8, 0x70)); |
283 | EXPECT_EQ(Known.One, APInt(8, 0x84)); |
284 | |
285 | auto ZeroBorrow = DAG->getConstant(Val: 0x0, DL: Loc, VT: IntVT); |
286 | auto OpZeroBorrow = |
287 | DAG->getNode(Opcode: ISD::UADDO_CARRY, DL: Loc, VT: IntVT, N1: N0, N2: N1, N3: ZeroBorrow); |
288 | // N0 = 0010?000 |
289 | // N1 = 01100101 |
290 | // B = 0 |
291 | // => |
292 | // Known.Zero = 01110010 (0x72) |
293 | // Known.One = 10000101 (0x85) |
294 | Known = DAG->computeKnownBits(Op: OpZeroBorrow); |
295 | EXPECT_EQ(Known.Zero, APInt(8, 0x72)); |
296 | EXPECT_EQ(Known.One, APInt(8, 0x85)); |
297 | |
298 | auto OneBorrow = DAG->getConstant(Val: 0x1, DL: Loc, VT: IntVT); |
299 | auto OpOneBorrow = |
300 | DAG->getNode(Opcode: ISD::UADDO_CARRY, DL: Loc, VT: IntVT, N1: N0, N2: N1, N3: OneBorrow); |
301 | // N0 = 0010?000 |
302 | // N1 = 01100101 |
303 | // B = 1 |
304 | // => |
305 | // Known.Zero = 01110001 (0x71) |
306 | // Known.One = 10000110 (0x86) |
307 | Known = DAG->computeKnownBits(Op: OpOneBorrow); |
308 | EXPECT_EQ(Known.Zero, APInt(8, 0x71)); |
309 | EXPECT_EQ(Known.One, APInt(8, 0x86)); |
310 | } |
311 | |
312 | // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. |
313 | TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_SUB) { |
314 | SDLoc Loc; |
315 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
316 | auto N0 = DAG->getConstant(Val: 0x55, DL: Loc, VT: IntVT); |
317 | auto UnknownOp = DAG->getRegister(Reg: 0, VT: IntVT); |
318 | auto Mask = DAG->getConstant(Val: 0x2e, DL: Loc, VT: IntVT); |
319 | auto N1 = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: IntVT, N1: Mask, N2: UnknownOp); |
320 | auto Op = DAG->getNode(Opcode: ISD::SUB, DL: Loc, VT: IntVT, N1: N0, N2: N1); |
321 | // N0 = 01010101 |
322 | // N1 = 00?0???0 |
323 | // => |
324 | // Known.One = 00000001 (0x1) |
325 | // Known.Zero = 10000000 (0x80) |
326 | KnownBits Known = DAG->computeKnownBits(Op); |
327 | EXPECT_EQ(Known.Zero, APInt(8, 0x80)); |
328 | EXPECT_EQ(Known.One, APInt(8, 0x1)); |
329 | } |
330 | |
331 | // Piggy-backing on the AArch64 tests to verify SelectionDAG::computeKnownBits. |
332 | TEST_F(AArch64SelectionDAGTest, ComputeKnownBits_USUBO_CARRY) { |
333 | SDLoc Loc; |
334 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
335 | auto N0 = DAG->getConstant(Val: 0x5a, DL: Loc, VT: IntVT); |
336 | auto UnknownOp = DAG->getRegister(Reg: 0, VT: IntVT); // ???????? |
337 | auto Mask1_Zero = DAG->getConstant(Val: 0x8, DL: Loc, VT: IntVT); // 00001000 |
338 | auto Mask1_One = DAG->getConstant(Val: 0x20, DL: Loc, VT: IntVT); // 00100000 |
339 | // N1 = (???????? & 00001000) | 00100000 = 0010?000 |
340 | auto N1 = DAG->getNode(Opcode: ISD::AND, DL: Loc, VT: IntVT, N1: Mask1_Zero, N2: UnknownOp); |
341 | N1 = DAG->getNode(Opcode: ISD::OR, DL: Loc, VT: IntVT, N1: Mask1_One, N2: N1); |
342 | |
343 | KnownBits Known; |
344 | |
345 | auto UnknownBorrow = DAG->getRegister(Reg: 1, VT: IntVT); |
346 | auto OpUnknownBorrow = |
347 | DAG->getNode(Opcode: ISD::USUBO_CARRY, DL: Loc, VT: IntVT, N1: N0, N2: N1, N3: UnknownBorrow); |
348 | // N0 = 01011010 |
349 | // N1 = 0010?000 |
350 | // B = ? |
351 | // => |
352 | // Known.Zero = 11000100 (0xc4) |
353 | // Known.One = 00110000 (0x30) |
354 | Known = DAG->computeKnownBits(Op: OpUnknownBorrow); |
355 | EXPECT_EQ(Known.Zero, APInt(8, 0xc4)); |
356 | EXPECT_EQ(Known.One, APInt(8, 0x30)); |
357 | |
358 | auto ZeroBorrow = DAG->getConstant(Val: 0x0, DL: Loc, VT: IntVT); |
359 | auto OpZeroBorrow = |
360 | DAG->getNode(Opcode: ISD::USUBO_CARRY, DL: Loc, VT: IntVT, N1: N0, N2: N1, N3: ZeroBorrow); |
361 | // N0 = 01011010 |
362 | // N1 = 0010?000 |
363 | // B = 0 |
364 | // => |
365 | // Known.Zero = 11000101 (0xc5) |
366 | // Known.One = 00110010 (0x32) |
367 | Known = DAG->computeKnownBits(Op: OpZeroBorrow); |
368 | EXPECT_EQ(Known.Zero, APInt(8, 0xc5)); |
369 | EXPECT_EQ(Known.One, APInt(8, 0x32)); |
370 | |
371 | auto OneBorrow = DAG->getConstant(Val: 0x1, DL: Loc, VT: IntVT); |
372 | auto OpOneBorrow = |
373 | DAG->getNode(Opcode: ISD::USUBO_CARRY, DL: Loc, VT: IntVT, N1: N0, N2: N1, N3: OneBorrow); |
374 | // N0 = 01011010 |
375 | // N1 = 0010?000 |
376 | // B = 1 |
377 | // => |
378 | // Known.Zero = 11000110 (0xc6) |
379 | // Known.One = 00110001 (0x31) |
380 | Known = DAG->computeKnownBits(Op: OpOneBorrow); |
381 | EXPECT_EQ(Known.Zero, APInt(8, 0xc6)); |
382 | EXPECT_EQ(Known.One, APInt(8, 0x31)); |
383 | } |
384 | |
385 | TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_BUILD_VECTOR) { |
386 | TargetLowering TL(*TM); |
387 | |
388 | SDLoc Loc; |
389 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
390 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: false); |
391 | // Create a BUILD_VECTOR |
392 | SDValue Op = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
393 | EXPECT_EQ(Op->getOpcode(), ISD::BUILD_VECTOR); |
394 | EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); |
395 | |
396 | APInt UndefElts; |
397 | APInt DemandedElts; |
398 | EXPECT_FALSE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); |
399 | |
400 | // Width=16, Mask=3 |
401 | DemandedElts = APInt(16, 3); |
402 | EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); |
403 | } |
404 | |
405 | TEST_F(AArch64SelectionDAGTest, isSplatValue_Fixed_ADD_of_BUILD_VECTOR) { |
406 | TargetLowering TL(*TM); |
407 | |
408 | SDLoc Loc; |
409 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
410 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: false); |
411 | |
412 | // Should create BUILD_VECTORs |
413 | SDValue Val1 = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
414 | SDValue Val2 = DAG->getConstant(Val: 3, DL: Loc, VT: VecVT); |
415 | EXPECT_EQ(Val1->getOpcode(), ISD::BUILD_VECTOR); |
416 | SDValue Op = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: VecVT, N1: Val1, N2: Val2); |
417 | |
418 | EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); |
419 | |
420 | APInt UndefElts; |
421 | APInt DemandedElts; |
422 | EXPECT_FALSE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); |
423 | |
424 | // Width=16, Mask=3 |
425 | DemandedElts = APInt(16, 3); |
426 | EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); |
427 | } |
428 | |
429 | TEST_F(AArch64SelectionDAGTest, isSplatValue_Scalable_SPLAT_VECTOR) { |
430 | TargetLowering TL(*TM); |
431 | |
432 | SDLoc Loc; |
433 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
434 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: true); |
435 | // Create a SPLAT_VECTOR |
436 | SDValue Op = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
437 | EXPECT_EQ(Op->getOpcode(), ISD::SPLAT_VECTOR); |
438 | EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); |
439 | |
440 | APInt UndefElts; |
441 | APInt DemandedElts(1,1); |
442 | EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); |
443 | } |
444 | |
445 | TEST_F(AArch64SelectionDAGTest, isSplatValue_Scalable_ADD_of_SPLAT_VECTOR) { |
446 | TargetLowering TL(*TM); |
447 | |
448 | SDLoc Loc; |
449 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
450 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: true); |
451 | |
452 | // Should create SPLAT_VECTORS |
453 | SDValue Val1 = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
454 | SDValue Val2 = DAG->getConstant(Val: 3, DL: Loc, VT: VecVT); |
455 | EXPECT_EQ(Val1->getOpcode(), ISD::SPLAT_VECTOR); |
456 | SDValue Op = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: VecVT, N1: Val1, N2: Val2); |
457 | |
458 | EXPECT_TRUE(DAG->isSplatValue(Op, /*AllowUndefs=*/false)); |
459 | |
460 | APInt UndefElts; |
461 | APInt DemandedElts(1, 1); |
462 | EXPECT_TRUE(DAG->isSplatValue(Op, DemandedElts, UndefElts)); |
463 | } |
464 | |
465 | TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Fixed_BUILD_VECTOR) { |
466 | TargetLowering TL(*TM); |
467 | |
468 | SDLoc Loc; |
469 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
470 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: false); |
471 | // Create a BUILD_VECTOR |
472 | SDValue Op = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
473 | EXPECT_EQ(Op->getOpcode(), ISD::BUILD_VECTOR); |
474 | |
475 | int SplatIdx = -1; |
476 | EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); |
477 | EXPECT_EQ(SplatIdx, 0); |
478 | } |
479 | |
480 | TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Fixed_ADD_of_BUILD_VECTOR) { |
481 | TargetLowering TL(*TM); |
482 | |
483 | SDLoc Loc; |
484 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
485 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: false); |
486 | |
487 | // Should create BUILD_VECTORs |
488 | SDValue Val1 = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
489 | SDValue Val2 = DAG->getConstant(Val: 3, DL: Loc, VT: VecVT); |
490 | EXPECT_EQ(Val1->getOpcode(), ISD::BUILD_VECTOR); |
491 | SDValue Op = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: VecVT, N1: Val1, N2: Val2); |
492 | |
493 | int SplatIdx = -1; |
494 | EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); |
495 | EXPECT_EQ(SplatIdx, 0); |
496 | } |
497 | |
498 | TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Scalable_SPLAT_VECTOR) { |
499 | TargetLowering TL(*TM); |
500 | |
501 | SDLoc Loc; |
502 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
503 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: true); |
504 | // Create a SPLAT_VECTOR |
505 | SDValue Op = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
506 | EXPECT_EQ(Op->getOpcode(), ISD::SPLAT_VECTOR); |
507 | |
508 | int SplatIdx = -1; |
509 | EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); |
510 | EXPECT_EQ(SplatIdx, 0); |
511 | } |
512 | |
513 | TEST_F(AArch64SelectionDAGTest, getSplatSourceVector_Scalable_ADD_of_SPLAT_VECTOR) { |
514 | TargetLowering TL(*TM); |
515 | |
516 | SDLoc Loc; |
517 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
518 | auto VecVT = EVT::getVectorVT(Context, VT: IntVT, NumElements: 16, IsScalable: true); |
519 | |
520 | // Should create SPLAT_VECTORS |
521 | SDValue Val1 = DAG->getConstant(Val: 1, DL: Loc, VT: VecVT); |
522 | SDValue Val2 = DAG->getConstant(Val: 3, DL: Loc, VT: VecVT); |
523 | EXPECT_EQ(Val1->getOpcode(), ISD::SPLAT_VECTOR); |
524 | SDValue Op = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: VecVT, N1: Val1, N2: Val2); |
525 | |
526 | int SplatIdx = -1; |
527 | EXPECT_EQ(DAG->getSplatSourceVector(Op, SplatIdx), Op); |
528 | EXPECT_EQ(SplatIdx, 0); |
529 | } |
530 | |
531 | TEST_F(AArch64SelectionDAGTest, getRepeatedSequence_Patterns) { |
532 | TargetLowering TL(*TM); |
533 | |
534 | SDLoc Loc; |
535 | unsigned NumElts = 16; |
536 | MVT IntVT = MVT::i8; |
537 | MVT VecVT = MVT::getVectorVT(VT: IntVT, NumElements: NumElts); |
538 | |
539 | // Base scalar constants. |
540 | SDValue Val0 = DAG->getConstant(Val: 0, DL: Loc, VT: IntVT); |
541 | SDValue Val1 = DAG->getConstant(Val: 1, DL: Loc, VT: IntVT); |
542 | SDValue Val2 = DAG->getConstant(Val: 2, DL: Loc, VT: IntVT); |
543 | SDValue Val3 = DAG->getConstant(Val: 3, DL: Loc, VT: IntVT); |
544 | SDValue UndefVal = DAG->getUNDEF(VT: IntVT); |
545 | |
546 | // Build some repeating sequences. |
547 | SmallVector<SDValue, 16> Pattern1111, Pattern1133, Pattern0123; |
548 | for(int I = 0; I != 4; ++I) { |
549 | Pattern1111.append(NumInputs: 4, Elt: Val1); |
550 | Pattern1133.append(NumInputs: 2, Elt: Val1); |
551 | Pattern1133.append(NumInputs: 2, Elt: Val3); |
552 | Pattern0123.push_back(Elt: Val0); |
553 | Pattern0123.push_back(Elt: Val1); |
554 | Pattern0123.push_back(Elt: Val2); |
555 | Pattern0123.push_back(Elt: Val3); |
556 | } |
557 | |
558 | // Build a non-pow2 repeating sequence. |
559 | SmallVector<SDValue, 16> Pattern022; |
560 | Pattern022.push_back(Elt: Val0); |
561 | Pattern022.append(NumInputs: 2, Elt: Val2); |
562 | Pattern022.push_back(Elt: Val0); |
563 | Pattern022.append(NumInputs: 2, Elt: Val2); |
564 | Pattern022.push_back(Elt: Val0); |
565 | Pattern022.append(NumInputs: 2, Elt: Val2); |
566 | Pattern022.push_back(Elt: Val0); |
567 | Pattern022.append(NumInputs: 2, Elt: Val2); |
568 | Pattern022.push_back(Elt: Val0); |
569 | Pattern022.append(NumInputs: 2, Elt: Val2); |
570 | Pattern022.push_back(Elt: Val0); |
571 | |
572 | // Build a non-repeating sequence. |
573 | SmallVector<SDValue, 16> Pattern1_3; |
574 | Pattern1_3.append(NumInputs: 8, Elt: Val1); |
575 | Pattern1_3.append(NumInputs: 8, Elt: Val3); |
576 | |
577 | // Add some undefs to make it trickier. |
578 | Pattern1111[1] = Pattern1111[2] = Pattern1111[15] = UndefVal; |
579 | Pattern1133[0] = Pattern1133[2] = UndefVal; |
580 | |
581 | auto *BV1111 = |
582 | cast<BuildVectorSDNode>(Val: DAG->getBuildVector(VT: VecVT, DL: Loc, Ops: Pattern1111)); |
583 | auto *BV1133 = |
584 | cast<BuildVectorSDNode>(Val: DAG->getBuildVector(VT: VecVT, DL: Loc, Ops: Pattern1133)); |
585 | auto *BV0123= |
586 | cast<BuildVectorSDNode>(Val: DAG->getBuildVector(VT: VecVT, DL: Loc, Ops: Pattern0123)); |
587 | auto *BV022 = |
588 | cast<BuildVectorSDNode>(Val: DAG->getBuildVector(VT: VecVT, DL: Loc, Ops: Pattern022)); |
589 | auto *BV1_3 = |
590 | cast<BuildVectorSDNode>(Val: DAG->getBuildVector(VT: VecVT, DL: Loc, Ops: Pattern1_3)); |
591 | |
592 | // Check for sequences. |
593 | SmallVector<SDValue, 16> Seq1111, Seq1133, Seq0123, Seq022, Seq1_3; |
594 | BitVector Undefs1111, Undefs1133, Undefs0123, Undefs022, Undefs1_3; |
595 | |
596 | EXPECT_TRUE(BV1111->getRepeatedSequence(Seq1111, &Undefs1111)); |
597 | EXPECT_EQ(Undefs1111.count(), 3u); |
598 | EXPECT_EQ(Seq1111.size(), 1u); |
599 | EXPECT_EQ(Seq1111[0], Val1); |
600 | |
601 | EXPECT_TRUE(BV1133->getRepeatedSequence(Seq1133, &Undefs1133)); |
602 | EXPECT_EQ(Undefs1133.count(), 2u); |
603 | EXPECT_EQ(Seq1133.size(), 4u); |
604 | EXPECT_EQ(Seq1133[0], Val1); |
605 | EXPECT_EQ(Seq1133[1], Val1); |
606 | EXPECT_EQ(Seq1133[2], Val3); |
607 | EXPECT_EQ(Seq1133[3], Val3); |
608 | |
609 | EXPECT_TRUE(BV0123->getRepeatedSequence(Seq0123, &Undefs0123)); |
610 | EXPECT_EQ(Undefs0123.count(), 0u); |
611 | EXPECT_EQ(Seq0123.size(), 4u); |
612 | EXPECT_EQ(Seq0123[0], Val0); |
613 | EXPECT_EQ(Seq0123[1], Val1); |
614 | EXPECT_EQ(Seq0123[2], Val2); |
615 | EXPECT_EQ(Seq0123[3], Val3); |
616 | |
617 | EXPECT_FALSE(BV022->getRepeatedSequence(Seq022, &Undefs022)); |
618 | EXPECT_FALSE(BV1_3->getRepeatedSequence(Seq1_3, &Undefs1_3)); |
619 | |
620 | // Try again with DemandedElts masks. |
621 | APInt Mask1111_0 = APInt::getOneBitSet(numBits: NumElts, BitNo: 0); |
622 | EXPECT_TRUE(BV1111->getRepeatedSequence(Mask1111_0, Seq1111, &Undefs1111)); |
623 | EXPECT_EQ(Undefs1111.count(), 0u); |
624 | EXPECT_EQ(Seq1111.size(), 1u); |
625 | EXPECT_EQ(Seq1111[0], Val1); |
626 | |
627 | APInt Mask1111_1 = APInt::getOneBitSet(numBits: NumElts, BitNo: 2); |
628 | EXPECT_TRUE(BV1111->getRepeatedSequence(Mask1111_1, Seq1111, &Undefs1111)); |
629 | EXPECT_EQ(Undefs1111.count(), 1u); |
630 | EXPECT_EQ(Seq1111.size(), 1u); |
631 | EXPECT_EQ(Seq1111[0], UndefVal); |
632 | |
633 | APInt Mask0123 = APInt(NumElts, 0x7777); |
634 | EXPECT_TRUE(BV0123->getRepeatedSequence(Mask0123, Seq0123, &Undefs0123)); |
635 | EXPECT_EQ(Undefs0123.count(), 0u); |
636 | EXPECT_EQ(Seq0123.size(), 4u); |
637 | EXPECT_EQ(Seq0123[0], Val0); |
638 | EXPECT_EQ(Seq0123[1], Val1); |
639 | EXPECT_EQ(Seq0123[2], Val2); |
640 | EXPECT_EQ(Seq0123[3], SDValue()); |
641 | |
642 | APInt Mask1_3 = APInt::getHighBitsSet(numBits: 16, hiBitsSet: 8); |
643 | EXPECT_TRUE(BV1_3->getRepeatedSequence(Mask1_3, Seq1_3, &Undefs1_3)); |
644 | EXPECT_EQ(Undefs1_3.count(), 0u); |
645 | EXPECT_EQ(Seq1_3.size(), 1u); |
646 | EXPECT_EQ(Seq1_3[0], Val3); |
647 | } |
648 | |
649 | TEST_F(AArch64SelectionDAGTest, getTypeConversion_SplitScalableMVT) { |
650 | MVT VT = MVT::nxv4i64; |
651 | EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypeSplitVector); |
652 | ASSERT_TRUE(getTypeToTransformTo(VT).isScalableVector()); |
653 | } |
654 | |
655 | TEST_F(AArch64SelectionDAGTest, getTypeConversion_PromoteScalableMVT) { |
656 | MVT VT = MVT::nxv2i32; |
657 | EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypePromoteInteger); |
658 | ASSERT_TRUE(getTypeToTransformTo(VT).isScalableVector()); |
659 | } |
660 | |
661 | TEST_F(AArch64SelectionDAGTest, getTypeConversion_NoScalarizeMVT_nxv1f32) { |
662 | MVT VT = MVT::nxv1f32; |
663 | EXPECT_NE(getTypeAction(VT), TargetLoweringBase::TypeScalarizeVector); |
664 | ASSERT_TRUE(getTypeToTransformTo(VT).isScalableVector()); |
665 | } |
666 | |
667 | TEST_F(AArch64SelectionDAGTest, getTypeConversion_SplitScalableEVT) { |
668 | EVT VT = EVT::getVectorVT(Context, MVT::i64, 256, true); |
669 | EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypeSplitVector); |
670 | EXPECT_EQ(getTypeToTransformTo(VT), VT.getHalfNumVectorElementsVT(Context)); |
671 | } |
672 | |
673 | TEST_F(AArch64SelectionDAGTest, getTypeConversion_WidenScalableEVT) { |
674 | EVT FromVT = EVT::getVectorVT(Context, MVT::i64, 6, true); |
675 | EVT ToVT = EVT::getVectorVT(Context, MVT::i64, 8, true); |
676 | |
677 | EXPECT_EQ(getTypeAction(FromVT), TargetLoweringBase::TypeWidenVector); |
678 | EXPECT_EQ(getTypeToTransformTo(FromVT), ToVT); |
679 | } |
680 | |
681 | TEST_F(AArch64SelectionDAGTest, |
682 | getTypeConversion_ScalarizeScalableEVT_nxv1f128) { |
683 | EVT VT = EVT::getVectorVT(Context, MVT::f128, ElementCount::getScalable(MinVal: 1)); |
684 | EXPECT_EQ(getTypeAction(VT), TargetLoweringBase::TypeScalarizeScalableVector); |
685 | EXPECT_EQ(getTypeToTransformTo(VT), MVT::f128); |
686 | } |
687 | |
688 | TEST_F(AArch64SelectionDAGTest, TestFold_STEP_VECTOR) { |
689 | SDLoc Loc; |
690 | auto IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
691 | auto VecVT = EVT::getVectorVT(Context, MVT::i8, 16, true); |
692 | |
693 | // Should create SPLAT_VECTOR |
694 | SDValue Zero = DAG->getConstant(Val: 0, DL: Loc, VT: IntVT); |
695 | SDValue Op = DAG->getNode(ISD::STEP_VECTOR, Loc, VecVT, Zero); |
696 | EXPECT_EQ(Op.getOpcode(), ISD::SPLAT_VECTOR); |
697 | } |
698 | |
699 | TEST_F(AArch64SelectionDAGTest, ReplaceAllUsesWith) { |
700 | SDLoc Loc; |
701 | EVT IntVT = EVT::getIntegerVT(Context, BitWidth: 8); |
702 | |
703 | SDValue N0 = DAG->getConstant(Val: 0x42, DL: Loc, VT: IntVT); |
704 | SDValue N1 = DAG->getRegister(Reg: 0, VT: IntVT); |
705 | // Construct node to fill arbitrary ExtraInfo. |
706 | SDValue N2 = DAG->getNode(Opcode: ISD::SUB, DL: Loc, VT: IntVT, N1: N0, N2: N1); |
707 | EXPECT_FALSE(DAG->getHeapAllocSite(N2.getNode())); |
708 | EXPECT_FALSE(DAG->getNoMergeSiteInfo(N2.getNode())); |
709 | EXPECT_FALSE(DAG->getPCSections(N2.getNode())); |
710 | MDNode *MD = MDNode::get(Context, MDs: std::nullopt); |
711 | DAG->addHeapAllocSite(Node: N2.getNode(), MD); |
712 | DAG->addNoMergeSiteInfo(Node: N2.getNode(), NoMerge: true); |
713 | DAG->addPCSections(Node: N2.getNode(), MD); |
714 | EXPECT_EQ(DAG->getHeapAllocSite(N2.getNode()), MD); |
715 | EXPECT_TRUE(DAG->getNoMergeSiteInfo(N2.getNode())); |
716 | EXPECT_EQ(DAG->getPCSections(N2.getNode()), MD); |
717 | |
718 | SDValue Root = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: IntVT, N1: N2, N2); |
719 | EXPECT_EQ(Root->getOperand(0)->getOpcode(), ISD::SUB); |
720 | // Create new node and check that ExtraInfo is propagated on RAUW. |
721 | SDValue New = DAG->getNode(Opcode: ISD::ADD, DL: Loc, VT: IntVT, N1, N2: N1); |
722 | EXPECT_FALSE(DAG->getHeapAllocSite(New.getNode())); |
723 | EXPECT_FALSE(DAG->getNoMergeSiteInfo(New.getNode())); |
724 | EXPECT_FALSE(DAG->getPCSections(New.getNode())); |
725 | |
726 | DAG->ReplaceAllUsesWith(From: N2, To: New); |
727 | EXPECT_EQ(Root->getOperand(0), New); |
728 | EXPECT_EQ(DAG->getHeapAllocSite(New.getNode()), MD); |
729 | EXPECT_TRUE(DAG->getNoMergeSiteInfo(New.getNode())); |
730 | EXPECT_EQ(DAG->getPCSections(New.getNode()), MD); |
731 | } |
732 | |
733 | TEST_F(AArch64SelectionDAGTest, computeKnownBits_extload_known01) { |
734 | SDLoc Loc; |
735 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
736 | auto Int32VT = EVT::getIntegerVT(Context, BitWidth: 32); |
737 | auto Int64VT = EVT::getIntegerVT(Context, BitWidth: 64); |
738 | auto Ptr = DAG->getConstant(Val: 0, DL: Loc, VT: Int64VT); |
739 | auto PtrInfo = |
740 | MachinePointerInfo::getFixedStack(MF&: DAG->getMachineFunction(), FI: 0); |
741 | AAMDNodes AA; |
742 | MDBuilder MDHelper(*DAG->getContext()); |
743 | MDNode *Range = MDHelper.createRange(Lo: APInt(8, 0), Hi: APInt(8, 2)); |
744 | MachineMemOperand *MMO = DAG->getMachineFunction().getMachineMemOperand( |
745 | PtrInfo, F: MachineMemOperand::MOLoad, Size: 8, BaseAlignment: Align(8), AAInfo: AA, Ranges: Range); |
746 | |
747 | auto ALoad = DAG->getExtLoad(ExtType: ISD::EXTLOAD, dl: Loc, VT: Int32VT, Chain: DAG->getEntryNode(), |
748 | Ptr, MemVT: Int8VT, MMO); |
749 | KnownBits Known = DAG->computeKnownBits(Op: ALoad); |
750 | EXPECT_EQ(Known.Zero, APInt(32, 0xfe)); |
751 | EXPECT_EQ(Known.One, APInt(32, 0)); |
752 | |
753 | auto ZLoad = DAG->getExtLoad(ExtType: ISD::ZEXTLOAD, dl: Loc, VT: Int32VT, Chain: DAG->getEntryNode(), |
754 | Ptr, MemVT: Int8VT, MMO); |
755 | Known = DAG->computeKnownBits(Op: ZLoad); |
756 | EXPECT_EQ(Known.Zero, APInt(32, 0xfffffffe)); |
757 | EXPECT_EQ(Known.One, APInt(32, 0)); |
758 | |
759 | auto SLoad = DAG->getExtLoad(ExtType: ISD::SEXTLOAD, dl: Loc, VT: Int32VT, Chain: DAG->getEntryNode(), |
760 | Ptr, MemVT: Int8VT, MMO); |
761 | Known = DAG->computeKnownBits(Op: SLoad); |
762 | EXPECT_EQ(Known.Zero, APInt(32, 0xfffffffe)); |
763 | EXPECT_EQ(Known.One, APInt(32, 0)); |
764 | } |
765 | |
766 | TEST_F(AArch64SelectionDAGTest, computeKnownBits_extload_knownnegative) { |
767 | SDLoc Loc; |
768 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
769 | auto Int32VT = EVT::getIntegerVT(Context, BitWidth: 32); |
770 | auto Int64VT = EVT::getIntegerVT(Context, BitWidth: 64); |
771 | auto Ptr = DAG->getConstant(Val: 0, DL: Loc, VT: Int64VT); |
772 | auto PtrInfo = |
773 | MachinePointerInfo::getFixedStack(MF&: DAG->getMachineFunction(), FI: 0); |
774 | AAMDNodes AA; |
775 | MDBuilder MDHelper(*DAG->getContext()); |
776 | MDNode *Range = MDHelper.createRange(Lo: APInt(8, 0xf0), Hi: APInt(8, 0xff)); |
777 | MachineMemOperand *MMO = DAG->getMachineFunction().getMachineMemOperand( |
778 | PtrInfo, F: MachineMemOperand::MOLoad, Size: 8, BaseAlignment: Align(8), AAInfo: AA, Ranges: Range); |
779 | |
780 | auto ALoad = DAG->getExtLoad(ExtType: ISD::EXTLOAD, dl: Loc, VT: Int32VT, Chain: DAG->getEntryNode(), |
781 | Ptr, MemVT: Int8VT, MMO); |
782 | KnownBits Known = DAG->computeKnownBits(Op: ALoad); |
783 | EXPECT_EQ(Known.Zero, APInt(32, 0)); |
784 | EXPECT_EQ(Known.One, APInt(32, 0xf0)); |
785 | |
786 | auto ZLoad = DAG->getExtLoad(ExtType: ISD::ZEXTLOAD, dl: Loc, VT: Int32VT, Chain: DAG->getEntryNode(), |
787 | Ptr, MemVT: Int8VT, MMO); |
788 | Known = DAG->computeKnownBits(Op: ZLoad); |
789 | EXPECT_EQ(Known.Zero, APInt(32, 0xffffff00)); |
790 | EXPECT_EQ(Known.One, APInt(32, 0x000000f0)); |
791 | |
792 | auto SLoad = DAG->getExtLoad(ExtType: ISD::SEXTLOAD, dl: Loc, VT: Int32VT, Chain: DAG->getEntryNode(), |
793 | Ptr, MemVT: Int8VT, MMO); |
794 | Known = DAG->computeKnownBits(Op: SLoad); |
795 | EXPECT_EQ(Known.Zero, APInt(32, 0)); |
796 | EXPECT_EQ(Known.One, APInt(32, 0xfffffff0)); |
797 | } |
798 | |
799 | TEST_F(AArch64SelectionDAGTest, |
800 | computeKnownBits_AVGFLOORU_AVGFLOORS_AVGCEILU_AVGCEILS) { |
801 | SDLoc Loc; |
802 | auto Int8VT = EVT::getIntegerVT(Context, BitWidth: 8); |
803 | auto Int16VT = EVT::getIntegerVT(Context, BitWidth: 16); |
804 | auto Int8Vec8VT = EVT::getVectorVT(Context, VT: Int8VT, NumElements: 8); |
805 | auto Int16Vec8VT = EVT::getVectorVT(Context, VT: Int16VT, NumElements: 8); |
806 | |
807 | SDValue UnknownOp0 = DAG->getRegister(Reg: 0, VT: Int8Vec8VT); |
808 | SDValue UnknownOp1 = DAG->getRegister(Reg: 1, VT: Int8Vec8VT); |
809 | |
810 | SDValue ZextOp0 = |
811 | DAG->getNode(Opcode: ISD::ZERO_EXTEND, DL: Loc, VT: Int16Vec8VT, Operand: UnknownOp0); |
812 | SDValue ZextOp1 = |
813 | DAG->getNode(Opcode: ISD::ZERO_EXTEND, DL: Loc, VT: Int16Vec8VT, Operand: UnknownOp1); |
814 | // ZextOp0 = 00000000???????? |
815 | // ZextOp1 = 00000000???????? |
816 | // => (for all AVG* instructions) |
817 | // Known.Zero = 1111111100000000 (0xFF00) |
818 | // Known.One = 0000000000000000 (0x0000) |
819 | auto Zeroes = APInt(16, 0xFF00); |
820 | auto Ones = APInt(16, 0x0000); |
821 | |
822 | SDValue AVGFLOORU = |
823 | DAG->getNode(Opcode: ISD::AVGFLOORU, DL: Loc, VT: Int16Vec8VT, N1: ZextOp0, N2: ZextOp1); |
824 | KnownBits KnownAVGFLOORU = DAG->computeKnownBits(Op: AVGFLOORU); |
825 | EXPECT_EQ(KnownAVGFLOORU.Zero, Zeroes); |
826 | EXPECT_EQ(KnownAVGFLOORU.One, Ones); |
827 | |
828 | SDValue AVGFLOORS = |
829 | DAG->getNode(Opcode: ISD::AVGFLOORS, DL: Loc, VT: Int16Vec8VT, N1: ZextOp0, N2: ZextOp1); |
830 | KnownBits KnownAVGFLOORS = DAG->computeKnownBits(Op: AVGFLOORS); |
831 | EXPECT_EQ(KnownAVGFLOORS.Zero, Zeroes); |
832 | EXPECT_EQ(KnownAVGFLOORS.One, Ones); |
833 | |
834 | SDValue AVGCEILU = |
835 | DAG->getNode(Opcode: ISD::AVGCEILU, DL: Loc, VT: Int16Vec8VT, N1: ZextOp0, N2: ZextOp1); |
836 | KnownBits KnownAVGCEILU = DAG->computeKnownBits(Op: AVGCEILU); |
837 | EXPECT_EQ(KnownAVGCEILU.Zero, Zeroes); |
838 | EXPECT_EQ(KnownAVGCEILU.One, Ones); |
839 | |
840 | SDValue AVGCEILS = |
841 | DAG->getNode(Opcode: ISD::AVGCEILS, DL: Loc, VT: Int16Vec8VT, N1: ZextOp0, N2: ZextOp1); |
842 | KnownBits KnownAVGCEILS = DAG->computeKnownBits(Op: AVGCEILS); |
843 | EXPECT_EQ(KnownAVGCEILS.Zero, Zeroes); |
844 | EXPECT_EQ(KnownAVGCEILS.One, Ones); |
845 | } |
846 | |
847 | } // end namespace llvm |
848 | |