198 lines · cpp
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-exception5//6//===----------------------------------------------------------------------===//7 8#include "ARMSelectionDAGInfo.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 24namespace llvm {25 26class ARMSelectionDAGTest : public testing::Test {27protected: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.91TEST_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 // LHS(per-lane) = 00000000 00000000 00000000 00000000 (0x00000000)111 // Encoded(per-lane) = 00000000 00000000 00000000 10101010 (0x000000AA)112 // =>113 // Known.One = 00000000 00000000 00000000 10101010 (0x000000AA)114 // Known.Zero = 11111111 11111111 11111111 01010101 (0x00000000)115 SDValue Zero = DAG->getConstant(0, DL, MVT::i32);116 SDValue ZeroVec = DAG->getSplatBuildVector(VT, DL, Zero);117 Op = DAG->getNode(ARMISD::VORRIMM, DL, VT, ZeroVec, EncSD);118 SDValue FrVORRIMM = DAG->getFreeze(Op);119 Known = DAG->computeKnownBits(FrVORRIMM);120 EXPECT_EQ(Known.One, APInt(32, 0xAA));121 EXPECT_EQ(Known.Zero, APInt(32, 0xFFFFFF55));122}123 124/// VBIC (immediate): x & ~imm with 32-bit elements.125/// LHS(per-lane)=0xFFFFFFFF; imm per-lane = 0x000000AA => result = 0xFFFFFF55126TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM) {127 SDLoc DL;128 EVT VT = MVT::v4i32;129 130 SDValue LHS = DAG->getConstant(APInt(32, 0xFFFFFFFF), DL, VT);131 132 SDValue EncSD =133 DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x0, 0xAA), DL, MVT::i32);134 SDValue Op = DAG->getNode(ARMISD::VBICIMM, DL, VT, LHS, EncSD);135 136 // LHS(per-lane) = 11111111 11111111 11111111 11111111 (0xFFFFFFFF)137 // Encoded(per-lane) = 00000000 00000000 00000000 10101010 (0x000000AA)138 // =>139 // Known.One = 11111111 11111111 11111111 01010101 (0xFFFFFF55)140 // Known.Zero = 00000000 00000000 00000000 10101010 (0x000000AA)141 APInt DemandedElts = APInt::getAllOnes(4);142 KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);143 EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF55));144 EXPECT_EQ(Known.Zero, APInt(32, 0x000000AA));145 146 SDValue FrVBICIMM = DAG->getFreeze(Op);147 Known = DAG->computeKnownBits(FrVBICIMM);148 EXPECT_EQ(Known.One, APInt(32, 0xFFFFFF55));149 EXPECT_EQ(Known.Zero, APInt(32, 0x000000AA));150}151 152/// VORR (immediate): per-lane OR with 32-bit elements.153/// Encoded = 0x2AA (cmode=0x2, imm8=0xAA) => per-lane constant = 0x0000AA00.154TEST_F(ARMSelectionDAGTest, computeKnownBits_VORRIMM_cmode2) {155 SDLoc DL;156 EVT VT = MVT::v4i32;157 SDValue LHS = DAG->getRegister(0, VT);158 159 // Use the exact encoded immediate the reviewer asked for.160 SDValue EncSD =161 DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x2, 0xAA), DL, MVT::i32);162 SDValue Op = DAG->getNode(ARMISD::VORRIMM, DL, VT, LHS, EncSD);163 164 // LHS (per-lane) = ???????? ???????? ???????? ????????165 // Encoded (per-lane) = 00000000 00000000 10101010 00000000 (0x0000AA00)166 // =>167 // Known.One = 00000000 00000000 10101010 00000000 (0x0000AA00)168 // Known.Zero = 00000000 00000000 00000000 00000000 (0x00000000)169 APInt DemandedElts = APInt::getAllOnes(4);170 KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);171 EXPECT_EQ(Known.One, APInt(32, 0x0000AA00));172 EXPECT_EQ(Known.Zero, APInt(32, 0x00000000));173}174 175/// VBIC (immediate) with constant-all-ones LHS:176/// Encoded = 0x2AA => per-lane constant = 0x0000AA00; VBIC = A & ~Imm.177TEST_F(ARMSelectionDAGTest, computeKnownBits_VBICIMM_cmode2_lhs_ones) {178 SDLoc DL;179 EVT VT = MVT::v4i32;180 181 SDValue LHS = DAG->getConstant(APInt(32, 0xFFFFFFFF), DL, VT);182 SDValue EncSD =183 DAG->getTargetConstant(ARM_AM::createVMOVModImm(0x2, 0xAA), DL, MVT::i32);184 SDValue Op = DAG->getNode(ARMISD::VBICIMM, DL, VT, LHS, EncSD);185 186 // LHS (per-lane) = 11111111 11111111 11111111 11111111187 // Encoded (per-lane) = 00000000 00000000 10101010 00000000 (0x0000AA00)188 // =>189 // Known.One = 11111111 11111111 01010101 11111111 (0xFFFF55FF)190 // Known.Zero = 00000000 00000000 10101010 00000000 (0x0000AA00)191 APInt DemandedElts = APInt::getAllOnes(4);192 KnownBits Known = DAG->computeKnownBits(Op, DemandedElts);193 EXPECT_EQ(Known.One, APInt(32, 0xFFFF55FF));194 EXPECT_EQ(Known.Zero, APInt(32, 0x0000AA00));195}196 197} // end namespace llvm198