[llvm] f7d7847 - [LoongArch][MC] Refine MCInstrAnalysis based on registers used (#71276)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 9 23:54:36 PST 2023


Author: ZhaoQi
Date: 2023-11-10T15:54:33+08:00
New Revision: f7d784709673ca185f6fb0633fd53c72e81f2ae1

URL: https://github.com/llvm/llvm-project/commit/f7d784709673ca185f6fb0633fd53c72e81f2ae1
DIFF: https://github.com/llvm/llvm-project/commit/f7d784709673ca185f6fb0633fd53c72e81f2ae1.diff

LOG: [LoongArch][MC] Refine MCInstrAnalysis based on registers used (#71276)

MCInstrAnalysis can return properties of instructions (e.g., isCall(),
isBranch(),...) based on the informations that MCInstrDesc can get from
*InstrInfo*.td files. These infos are based on opcodes only, but JIRL
can have different properties based on different registers used.

So this patch refines several MCInstrAnalysis methods: isTerminator,
isCall,isReturn,isBranch,isUnconditionalBranch and isIndirectBranch.

This patch also allows BOLT which will be supported on LoongArch later
to get right instruction infos.

Added: 
    llvm/unittests/Target/LoongArch/MCInstrAnalysisTest.cpp

Modified: 
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
    llvm/unittests/Target/LoongArch/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
index 942e667bc261872..d580c3457fecff8 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
@@ -104,6 +104,82 @@ class LoongArchMCInstrAnalysis : public MCInstrAnalysis {
 
     return false;
   }
+
+  bool isTerminator(const MCInst &Inst) const override {
+    if (MCInstrAnalysis::isTerminator(Inst))
+      return true;
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case LoongArch::JIRL:
+      return Inst.getOperand(0).getReg() == LoongArch::R0;
+    }
+  }
+
+  bool isCall(const MCInst &Inst) const override {
+    if (MCInstrAnalysis::isCall(Inst))
+      return true;
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case LoongArch::JIRL:
+      return Inst.getOperand(0).getReg() != LoongArch::R0;
+    }
+  }
+
+  bool isReturn(const MCInst &Inst) const override {
+    if (MCInstrAnalysis::isReturn(Inst))
+      return true;
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case LoongArch::JIRL:
+      return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+             Inst.getOperand(1).getReg() == LoongArch::R1;
+    }
+  }
+
+  bool isBranch(const MCInst &Inst) const override {
+    if (MCInstrAnalysis::isBranch(Inst))
+      return true;
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case LoongArch::JIRL:
+      return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+             Inst.getOperand(1).getReg() != LoongArch::R1;
+    }
+  }
+
+  bool isUnconditionalBranch(const MCInst &Inst) const override {
+    if (MCInstrAnalysis::isUnconditionalBranch(Inst))
+      return true;
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case LoongArch::JIRL:
+      return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+             Inst.getOperand(1).getReg() != LoongArch::R1;
+    }
+  }
+
+  bool isIndirectBranch(const MCInst &Inst) const override {
+    if (MCInstrAnalysis::isIndirectBranch(Inst))
+      return true;
+
+    switch (Inst.getOpcode()) {
+    default:
+      return false;
+    case LoongArch::JIRL:
+      return Inst.getOperand(0).getReg() == LoongArch::R0 &&
+             Inst.getOperand(1).getReg() != LoongArch::R1;
+    }
+  }
 };
 
 } // end namespace

diff  --git a/llvm/unittests/Target/LoongArch/CMakeLists.txt b/llvm/unittests/Target/LoongArch/CMakeLists.txt
index fef4f8e15461834..e6f8ec073721f6e 100644
--- a/llvm/unittests/Target/LoongArch/CMakeLists.txt
+++ b/llvm/unittests/Target/LoongArch/CMakeLists.txt
@@ -20,6 +20,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_target_unittest(LoongArchTests
   InstSizes.cpp
+  MCInstrAnalysisTest.cpp
   )
 
 set_property(TARGET LoongArchTests PROPERTY FOLDER "Tests/UnitTests/TargetTests")

diff  --git a/llvm/unittests/Target/LoongArch/MCInstrAnalysisTest.cpp b/llvm/unittests/Target/LoongArch/MCInstrAnalysisTest.cpp
new file mode 100644
index 000000000000000..6a208d274a0d39e
--- /dev/null
+++ b/llvm/unittests/Target/LoongArch/MCInstrAnalysisTest.cpp
@@ -0,0 +1,107 @@
+//===- MCInstrAnalysisTest.cpp - LoongArchMCInstrAnalysis unit tests ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCInstrAnalysis.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "gtest/gtest.h"
+
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+class InstrAnalysisTest : public testing::TestWithParam<const char *> {
+protected:
+  std::unique_ptr<const MCInstrInfo> Info;
+  std::unique_ptr<const MCInstrAnalysis> Analysis;
+
+  static void SetUpTestSuite() {
+    LLVMInitializeLoongArchTargetInfo();
+    LLVMInitializeLoongArchTarget();
+    LLVMInitializeLoongArchTargetMC();
+  }
+
+  InstrAnalysisTest() {
+    std::string Error;
+    const Target *TheTarget =
+        TargetRegistry::lookupTarget(Triple::normalize(GetParam()), Error);
+    Info = std::unique_ptr<const MCInstrInfo>(TheTarget->createMCInstrInfo());
+    Analysis = std::unique_ptr<const MCInstrAnalysis>(
+        TheTarget->createMCInstrAnalysis(Info.get()));
+  }
+};
+
+} // namespace
+
+static MCInst beq() {
+  return MCInstBuilder(LoongArch::BEQ)
+      .addReg(LoongArch::R0)
+      .addReg(LoongArch::R1)
+      .addImm(32);
+}
+
+static MCInst bl() { return MCInstBuilder(LoongArch::BL).addImm(32); }
+
+static MCInst jirl(unsigned RD, unsigned RJ = LoongArch::R10) {
+  return MCInstBuilder(LoongArch::JIRL).addReg(RD).addReg(RJ).addImm(16);
+}
+
+TEST_P(InstrAnalysisTest, IsTerminator) {
+  EXPECT_TRUE(Analysis->isTerminator(beq()));
+  EXPECT_FALSE(Analysis->isTerminator(bl()));
+  EXPECT_TRUE(Analysis->isTerminator(jirl(LoongArch::R0)));
+  EXPECT_FALSE(Analysis->isTerminator(jirl(LoongArch::R5)));
+}
+
+TEST_P(InstrAnalysisTest, IsCall) {
+  EXPECT_FALSE(Analysis->isCall(beq()));
+  EXPECT_TRUE(Analysis->isCall(bl()));
+  EXPECT_TRUE(Analysis->isCall(jirl(LoongArch::R1)));
+  EXPECT_FALSE(Analysis->isCall(jirl(LoongArch::R0)));
+}
+
+TEST_P(InstrAnalysisTest, IsReturn) {
+  EXPECT_FALSE(Analysis->isReturn(beq()));
+  EXPECT_FALSE(Analysis->isReturn(bl()));
+  EXPECT_TRUE(Analysis->isReturn(jirl(LoongArch::R0, LoongArch::R1)));
+  EXPECT_FALSE(Analysis->isReturn(jirl(LoongArch::R0)));
+  EXPECT_FALSE(Analysis->isReturn(jirl(LoongArch::R1)));
+}
+
+TEST_P(InstrAnalysisTest, IsBranch) {
+  EXPECT_TRUE(Analysis->isBranch(beq()));
+  EXPECT_FALSE(Analysis->isBranch(bl()));
+  EXPECT_TRUE(Analysis->isBranch(jirl(LoongArch::R0)));
+  EXPECT_FALSE(Analysis->isBranch(jirl(LoongArch::R1)));
+  EXPECT_FALSE(Analysis->isBranch(jirl(LoongArch::R0, LoongArch::R1)));
+}
+
+TEST_P(InstrAnalysisTest, IsUnconditionalBranch) {
+  EXPECT_FALSE(Analysis->isUnconditionalBranch(beq()));
+  EXPECT_FALSE(Analysis->isUnconditionalBranch(bl()));
+  EXPECT_TRUE(Analysis->isUnconditionalBranch(jirl(LoongArch::R0)));
+  EXPECT_FALSE(Analysis->isUnconditionalBranch(jirl(LoongArch::R1)));
+  EXPECT_FALSE(
+      Analysis->isUnconditionalBranch(jirl(LoongArch::R0, LoongArch::R1)));
+}
+
+TEST_P(InstrAnalysisTest, IsIndirectBranch) {
+  EXPECT_FALSE(Analysis->isIndirectBranch(beq()));
+  EXPECT_FALSE(Analysis->isIndirectBranch(bl()));
+  EXPECT_TRUE(Analysis->isIndirectBranch(jirl(LoongArch::R0)));
+  EXPECT_FALSE(Analysis->isIndirectBranch(jirl(LoongArch::R1)));
+  EXPECT_FALSE(Analysis->isIndirectBranch(jirl(LoongArch::R0, LoongArch::R1)));
+}
+
+INSTANTIATE_TEST_SUITE_P(LA32And64, InstrAnalysisTest,
+                         testing::Values("loongarch32", "loongarch64"));


        


More information about the llvm-commits mailing list