Skip to content

Commit 010f1ea

Browse files
authored
[DAG][ARM] ComputeKnownBitsForTargetNode - add handling for ARMISD VORRIMM\VBICIMM nodes (#149494)
### Summary This PR resolves #147179
1 parent 3f757a3 commit 010f1ea

File tree

3 files changed

+203
-0
lines changed

3 files changed

+203
-0
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20065,6 +20065,29 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
2006520065
Known = KnownOp0.intersectWith(KnownOp1);
2006620066
break;
2006720067
}
20068+
case ARMISD::VORRIMM:
20069+
case ARMISD::VBICIMM: {
20070+
unsigned Encoded = Op.getConstantOperandVal(1);
20071+
unsigned DecEltBits = 0;
20072+
uint64_t DecodedVal = ARM_AM::decodeVMOVModImm(Encoded, DecEltBits);
20073+
20074+
unsigned EltBits = Op.getScalarValueSizeInBits();
20075+
if (EltBits != DecEltBits) {
20076+
// Be conservative: only update Known when EltBits == DecEltBits.
20077+
// This is believed to always be true for VORRIMM/VBICIMM today, but if
20078+
// that changes in the future, doing nothing here is safer than risking
20079+
// subtle bugs.
20080+
break;
20081+
}
20082+
20083+
KnownBits KnownLHS = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
20084+
bool IsVORR = Op.getOpcode() == ARMISD::VORRIMM;
20085+
APInt Imm(DecEltBits, DecodedVal);
20086+
20087+
Known.One = IsVORR ? (KnownLHS.One | Imm) : (KnownLHS.One & ~Imm);
20088+
Known.Zero = IsVORR ? (KnownLHS.Zero & ~Imm) : (KnownLHS.Zero | Imm);
20089+
break;
20090+
}
2006820091
}
2006920092
}
2007020093

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
//===----------------------------------------------------------------------===//
2+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3+
// See https://llvm.org/LICENSE.txt for license information.
4+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5+
//
6+
//===----------------------------------------------------------------------===//
7+
8+
#include "ARMISelLowering.h"
9+
#include "MCTargetDesc/ARMAddressingModes.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/IR/Module.h"
17+
#include "llvm/MC/TargetRegistry.h"
18+
#include "llvm/Support/KnownBits.h"
19+
#include "llvm/Support/SourceMgr.h"
20+
#include "llvm/Support/TargetSelect.h"
21+
#include "llvm/Target/TargetMachine.h"
22+
#include "gtest/gtest.h"
23+
24+
namespace llvm {
25+
26+
class ARMSelectionDAGTest : public testing::Test {
27+
protected:
28+
static void SetUpTestCase() {
29+
LLVMInitializeARMTargetInfo();
30+
LLVMInitializeARMTarget();
31+
LLVMInitializeARMTargetMC();
32+
}
33+
34+
void SetUp() override {
35+
StringRef Assembly = "define void @f() { ret void }";
36+
37+
Triple TargetTriple("armv7-unknown-none-eabi");
38+
39+
std::string Error;
40+
const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
41+
42+
TargetOptions Options;
43+
TM = std::unique_ptr<TargetMachine>(
44+
T->createTargetMachine(TargetTriple,
45+
/*CPU*/ "cortex-a9",
46+
/*Features*/ "+neon", Options, std::nullopt,
47+
std::nullopt, CodeGenOptLevel::Aggressive));
48+
49+
SMDiagnostic SMError;
50+
M = parseAssemblyString(Assembly, SMError, Context);
51+
if (!M)
52+
report_fatal_error(SMError.getMessage());
53+
M->setDataLayout(TM->createDataLayout());
54+
55+
F = M->getFunction("f");
56+
if (!F)
57+
report_fatal_error("Function 'f' not found");
58+
59+
MachineModuleInfo MMI(TM.get());
60+
61+
MF = std::make_unique<MachineFunction>(*F, *TM, *TM->getSubtargetImpl(*F),
62+
MMI.getContext(), /*FunctionNum*/ 0);
63+
64+
DAG = std::make_unique<SelectionDAG>(*TM, CodeGenOptLevel::None);
65+
if (!DAG)
66+
report_fatal_error("SelectionDAG allocation failed");
67+
68+
OptimizationRemarkEmitter ORE(F);
69+
DAG->init(*MF, ORE, /*LibInfo*/ nullptr, /*AA*/ nullptr,
70+
/*AC*/ nullptr, /*MDT*/ nullptr, /*MSDT*/ nullptr, MMI, 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<TargetMachine> TM;
83+
std::unique_ptr<Module> M;
84+
Function *F = nullptr;
85+
std::unique_ptr<MachineFunction> MF;
86+
std::unique_ptr<SelectionDAG> DAG;
87+
};
88+
89+
/// VORR (immediate): per-lane OR with 32-bit elements.
90+
/// cmode=0x0 puts imm8 in byte0 => per-lane constant = 0x000000AA.
91+
TEST_F(ARMSelectionDAGTest, computeKnownBits_VORRIMM) {
92+
SDLoc DL;
93+
EVT VT = MVT::v4i32;
94+
SDValue LHS = DAG->getRegister(0, VT);
95+
96+
SDValue EncSD =
97+
DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);
98+
SDValue Op = DAG->getNode(ARMISD::VORRIMM, DL, VT, LHS, EncSD);
99+
100+
// LHS(per-lane) = ???????? ???????? ???????? ????????
101+
// Encoded(per-lane) = 00000000 00000000 00000000 10101010 (0x000000AA)
102+
// =>
103+
// Known.One = 00000000 00000000 00000000 10101010 (0x000000AA)
104+
// Known.Zero = 00000000 00000000 00000000 00000000 (0x00000000)
105+
APInt DemandedElts = APInt::getAllOnes(4);
106+
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
107+
EXPECT_EQ(Known.One, APInt(32, 0xAA));
108+
EXPECT_EQ(Known.Zero, APInt(32, 0x0));
109+
}
110+
111+
/// VBIC (immediate): x & ~imm with 32-bit elements.
112+
/// LHS(per-lane)=0xFFFFFFFF; imm per-lane = 0x000000AA => result = 0xFFFFFF55
113+
TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM) {
114+
SDLoc DL;
115+
EVT VT = MVT::v4i32;
116+
117+
SDValue LHS = DAG->getConstant(APInt(32, 0xFFFFFFFF), DL, VT);
118+
119+
SDValue EncSD =
120+
DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);
121+
SDValue Op = DAG->getNode(ARMISD::VBICIMM, DL, VT, LHS, EncSD);
122+
123+
// LHS(per-lane) = 11111111 11111111 11111111 11111111 (0xFFFFFFFF)
124+
// Encoded(per-lane) = 00000000 00000000 00000000 10101010 (0x000000AA)
125+
// =>
126+
// Known.One = 11111111 11111111 11111111 01010101 (0xFFFFFF55)
127+
// Known.Zero = 00000000 00000000 00000000 10101010 (0x000000AA)
128+
APInt DemandedElts = APInt::getAllOnes(4);
129+
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
130+
EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF55));
131+
EXPECT_EQ(Known.Zero, APInt(32, 0x000000AA));
132+
}
133+
134+
/// VORR (immediate): per-lane OR with 32-bit elements.
135+
/// Encoded = 0x2AA (cmode=0x2, imm8=0xAA) => per-lane constant = 0x0000AA00.
136+
TEST_F(ARMSelectionDAGTest, computeKnownBits_VORRIMM_cmode2) {
137+
SDLoc DL;
138+
EVT VT = MVT::v4i32;
139+
SDValue LHS = DAG->getRegister(0, VT);
140+
141+
// Use the exact encoded immediate the reviewer asked for.
142+
SDValue EncSD =
143+
DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x2, 0xAA), DL, MVT::i32);
144+
SDValue Op = DAG->getNode(ARMISD::VORRIMM, DL, VT, LHS, EncSD);
145+
146+
// LHS (per-lane) = ???????? ???????? ???????? ????????
147+
// Encoded (per-lane) = 00000000 00000000 10101010 00000000 (0x0000AA00)
148+
// =>
149+
// Known.One = 00000000 00000000 10101010 00000000 (0x0000AA00)
150+
// Known.Zero = 00000000 00000000 00000000 00000000 (0x00000000)
151+
APInt DemandedElts = APInt::getAllOnes(4);
152+
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
153+
EXPECT_EQ(Known.One, APInt(32, 0x0000AA00));
154+
EXPECT_EQ(Known.Zero, APInt(32, 0x00000000));
155+
}
156+
157+
/// VBIC (immediate) with constant-all-ones LHS:
158+
/// Encoded = 0x2AA => per-lane constant = 0x0000AA00; VBIC = A & ~Imm.
159+
TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM_cmode2_lhs_ones) {
160+
SDLoc DL;
161+
EVT VT = MVT::v4i32;
162+
163+
SDValue LHS = DAG->getConstant(APInt(32, 0xFFFFFFFF), DL, VT);
164+
SDValue EncSD =
165+
DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x2, 0xAA), DL, MVT::i32);
166+
SDValue Op = DAG->getNode(ARMISD::VBICIMM, DL, VT, LHS, EncSD);
167+
168+
// LHS (per-lane) = 11111111 11111111 11111111 11111111
169+
// Encoded (per-lane) = 00000000 00000000 10101010 00000000 (0x0000AA00)
170+
// =>
171+
// Known.One = 11111111 11111111 01010101 11111111 (0xFFFF55FF)
172+
// Known.Zero = 00000000 00000000 10101010 00000000 (0x0000AA00)
173+
APInt DemandedElts = APInt::getAllOnes(4);
174+
KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);
175+
EXPECT_EQ(Known.One, APInt(32, 0xFFFF55FF));
176+
EXPECT_EQ(Known.Zero, APInt(32, 0x0000AA00));
177+
}
178+
179+
} // end namespace llvm

llvm/unittests/Target/ARM/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ set(LLVM_LINK_COMPONENTS
2222
add_llvm_target_unittest(ARMTests
2323
MachineInstrTest.cpp
2424
InstSizes.cpp
25+
ARMSelectionDAGTest.cpp
2526
)

0 commit comments

Comments
 (0)