|
| 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 |
0 commit comments