brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.0 KiB · f6b8ca7 Raw
135 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 "RISCVISelLowering.h"9#include "RISCVSelectionDAGInfo.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/Support/raw_ostream.h"22#include "llvm/Target/TargetMachine.h"23#include "gtest/gtest.h"24 25namespace llvm {26 27class RISCVSelectionDAGTest : public testing::Test {28 29protected:30  static void SetUpTestCase() {31    LLVMInitializeRISCVTargetInfo();32    LLVMInitializeRISCVTarget();33    LLVMInitializeRISCVTargetMC();34  }35 36  void SetUp() override {37    StringRef Assembly = "define void @f() { ret void }";38 39    Triple TargetTriple("riscv64", "unknown", "linux");40 41    std::string Error;42    const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);43 44    TargetOptions Options;45    TM = std::unique_ptr<TargetMachine>(T->createTargetMachine(46        TargetTriple, "generic", "", Options, std::nullopt, std::nullopt,47        CodeGenOptLevel::Default));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  LLVMContext Context;74  std::unique_ptr<TargetMachine> TM;75  std::unique_ptr<Module> M;76  Function *F = nullptr;77  std::unique_ptr<MachineFunction> MF;78  std::unique_ptr<SelectionDAG> DAG;79};80 81/// SRLW: Logical Shift Right82TEST_F(RISCVSelectionDAGTest, computeKnownBits_SRLW) {83  // Given the following IR snippet:84  //  define i64 @f(i32 %x, i32 %y) {85  //   %a = and i32 %x, 2147483647  ; zeros the MSB for %x86  //   %b = lshr i32 %a, %y87  //   %c = zext i32 %b to i64 ; makes the most significant 32 bits 088  //   ret i64 %c89  //  }90  // The Optimized SelectionDAG as show by llc -mtriple="riscv64"91  // -debug-only=isel-dump is:92  //      t0: ch,glue = EntryToken93  //          t2: i64,ch = CopyFromReg t0, Register:i64 %094  //        t18: i64 = and t2, Constant:i64<2147483647>95  //        t4: i64,ch = CopyFromReg t0, Register:i64 %196  //      t20: i64 = RISCVISD::SRLW t18, t497  //    t22: i64 = and t20, Constant:i64<4294967295>98  //  t13: ch,glue = CopyToReg t0, Register:i64 $x10, t2299  //  t14: ch = RISCVISD::RET_GLUE t13, Register:i64 $x10, t13:1100  //101  // The DAG created below is derived from this102  SDLoc Loc;103  auto Int64VT = EVT::getIntegerVT(Context, 64);104  auto Px = DAG->getRegister(0, Int64VT);105  auto Py = DAG->getConstant(2147483647, Loc, Int64VT);106  auto N1 = DAG->getNode(ISD::AND, Loc, Int64VT, Px, Py);107  auto Qx = DAG->getRegister(0, Int64VT);108  auto N2 = DAG->getNode(RISCVISD::SRLW, Loc, Int64VT, N1, Qx);109  auto Py2 = DAG->getConstant(4294967295, Loc, Int64VT);110  auto N3 = DAG->getNode(ISD::AND, Loc, Int64VT, N2, Py2);111  // N1 = Px & 0x7FFFFFFF112  // The first AND ensures that the input to the shift has bit 31 cleared.113  // This means bits [63:31] of N1 are known to be zero.114  //115  // N2 = SRLW N1, Qx116  // SRLW performs a 32-bit logical right shift and then sign-extends the117  // 32-bit result to 64 bits. Because we know N1's bit 31 is 0, the118  // 32-bit result of the shift will also have its sign bit (bit 31) as 0.119  // Therefore, the sign-extension is guaranteed to be a zero-extension.120  //121  // N3 = N2 & 0xFFFFFFFF122  // This second AND is part of the canonical pattern to clear the upper123  // 32 bits, explicitly performing the zero-extension. From a KnownBits124  // perspective, it's redundant, as N2's upper bits are already known zero.125  //126  // As a result, for N3, we know the upper 32 bits are zero (from the effective127  // zero-extension) and we also know bit 31 is zero (from the initial AND).128  // This gives us 33 known most-significant zero bits.129  KnownBits Known = DAG->computeKnownBits(N3);130  EXPECT_EQ(Known.Zero, APInt(64, -2147483648));131  EXPECT_EQ(Known.One, APInt(64, 0));132}133 134} // end namespace llvm135