[llvm] [SandboxIR] Implement Operator (PR #112805)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 17 23:44:21 PDT 2024


https://github.com/vporpo updated https://github.com/llvm/llvm-project/pull/112805

>From 263e39125898c35c771a69cfcc066edd328f01a4 Mon Sep 17 00:00:00 2001
From: Vasileios Porpodas <vporpodas at google.com>
Date: Thu, 17 Oct 2024 15:02:48 -0700
Subject: [PATCH] [SandboxIR] Implement Operator

This patch implements sandboxir::Operator mirroring llvm::Operator.
---
 llvm/include/llvm/SandboxIR/Operator.h    | 60 ++++++++++++++++
 llvm/include/llvm/SandboxIR/Value.h       |  4 ++
 llvm/unittests/SandboxIR/CMakeLists.txt   |  1 +
 llvm/unittests/SandboxIR/OperatorTest.cpp | 88 +++++++++++++++++++++++
 4 files changed, 153 insertions(+)
 create mode 100644 llvm/include/llvm/SandboxIR/Operator.h
 create mode 100644 llvm/unittests/SandboxIR/OperatorTest.cpp

diff --git a/llvm/include/llvm/SandboxIR/Operator.h b/llvm/include/llvm/SandboxIR/Operator.h
new file mode 100644
index 00000000000000..95c450807191b4
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/Operator.h
@@ -0,0 +1,60 @@
+//===- Operator.h -----------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SANDBOXIR_OPERATOR_H
+#define LLVM_SANDBOXIR_OPERATOR_H
+
+#include "llvm/IR/Operator.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/SandboxIR/User.h"
+
+namespace llvm::sandboxir {
+
+class Operator : public User {
+public:
+  // The Operator class is intended to be used as a utility, and is never itself
+  // instantiated.
+  Operator() = delete;
+  void *operator new(size_t s) = delete;
+
+  static bool classof(const Instruction *) { return true; }
+  static bool classof(const ConstantExpr *) { return true; }
+  static bool classof(const Value *From) {
+    return llvm::Operator::classof(From->Val);
+  }
+  bool hasPoisonGeneratingFlags() const {
+    return cast<llvm::Operator>(Val)->hasPoisonGeneratingFlags();
+  }
+};
+
+class OverflowingBinaryOperator : public Operator {
+public:
+  bool hasNoUnsignedWrap() const {
+    return cast<llvm::OverflowingBinaryOperator>(Val)->hasNoUnsignedWrap();
+  }
+  bool hasNoSignedWrap() const {
+    return cast<llvm::OverflowingBinaryOperator>(Val)->hasNoSignedWrap();
+  }
+  unsigned getNoWrapKind() const {
+    return cast<llvm::OverflowingBinaryOperator>(Val)->getNoWrapKind();
+  }
+  static bool classof(const Instruction *From) {
+    return llvm::OverflowingBinaryOperator::classof(
+        cast<llvm::Instruction>(From->Val));
+  }
+  static bool classof(const ConstantExpr *From) {
+    return llvm::OverflowingBinaryOperator::classof(
+        cast<llvm::ConstantExpr>(From->Val));
+  }
+  static bool classof(const Value *From) {
+    return llvm::OverflowingBinaryOperator::classof(From->Val);
+  }
+};
+} // namespace llvm::sandboxir
+
+#endif // LLVM_SANDBOXIR_OPERATOR_H
diff --git a/llvm/include/llvm/SandboxIR/Value.h b/llvm/include/llvm/SandboxIR/Value.h
index 3509f2a8d83650..58088684bf18ec 100644
--- a/llvm/include/llvm/SandboxIR/Value.h
+++ b/llvm/include/llvm/SandboxIR/Value.h
@@ -28,6 +28,8 @@ class Module;
 class UnaryInstruction;
 class CmpInst;
 class IntrinsicInst;
+class Operator;
+class OverflowingBinaryOperator;
 
 /// Iterator for the `Use` edges of a Value's users.
 /// \Returns a `Use` when dereferenced.
@@ -158,6 +160,8 @@ class Value {
   friend class Utils;                 // For `Val`.
   friend class Module;                // For `Val`.
   friend class IntrinsicInst;         // For `Val`.
+  friend class Operator;              // For `Val`.
+  friend class OverflowingBinaryOperator; // For `Val`.
   // Region needs to manipulate metadata in the underlying LLVM Value, we don't
   // expose metadata in sandboxir.
   friend class Region;
diff --git a/llvm/unittests/SandboxIR/CMakeLists.txt b/llvm/unittests/SandboxIR/CMakeLists.txt
index 1e83bda7a1f6d1..b20ef829ed0c95 100644
--- a/llvm/unittests/SandboxIR/CMakeLists.txt
+++ b/llvm/unittests/SandboxIR/CMakeLists.txt
@@ -9,6 +9,7 @@ add_llvm_unittest(SandboxIRTests
   IntrinsicInstTest.cpp
   PassTest.cpp
   RegionTest.cpp
+  OperatorTest.cpp
   SandboxIRTest.cpp
   TrackerTest.cpp
   TypesTest.cpp
diff --git a/llvm/unittests/SandboxIR/OperatorTest.cpp b/llvm/unittests/SandboxIR/OperatorTest.cpp
new file mode 100644
index 00000000000000..031e2adf406927
--- /dev/null
+++ b/llvm/unittests/SandboxIR/OperatorTest.cpp
@@ -0,0 +1,88 @@
+//===- OperatorTest.cpp ---------------------------------------------------===//
+//
+// 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/SandboxIR/Operator.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/SandboxIR/Context.h"
+#include "llvm/SandboxIR/Function.h"
+#include "llvm/SandboxIR/Instruction.h"
+#include "llvm/SandboxIR/Module.h"
+#include "llvm/SandboxIR/Value.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct OperatorTest : public testing::Test {
+  LLVMContext C;
+  std::unique_ptr<Module> M;
+
+  void parseIR(LLVMContext &C, const char *IR) {
+    SMDiagnostic Err;
+    M = parseAssemblyString(IR, Err, C);
+    if (!M)
+      Err.print("OperatorTest", errs());
+  }
+  BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
+    for (BasicBlock &BB : F)
+      if (BB.getName() == Name)
+        return &BB;
+    llvm_unreachable("Expected to find basic block!");
+  }
+};
+
+TEST_F(OperatorTest, Operator) {
+  parseIR(C, R"IR(
+define void @foo(i8 %v1) {
+  %add0 = add i8 %v1, 42
+  %add1 = add nuw i8 %v1, 42
+  ret void
+}
+)IR");
+  llvm::Function *LLVMF = &*M->getFunction("foo");
+  sandboxir::Context Ctx(C);
+  sandboxir::Function *F = Ctx.createFunction(LLVMF);
+  auto *BB = &*F->begin();
+  auto It = BB->begin();
+  auto *OperatorI0 = cast<sandboxir::Operator>(&*It++);
+  auto *OperatorI1 = cast<sandboxir::Operator>(&*It++);
+  EXPECT_FALSE(OperatorI0->hasPoisonGeneratingFlags());
+  EXPECT_TRUE(OperatorI1->hasPoisonGeneratingFlags());
+}
+
+TEST_F(OperatorTest, OverflowingBinaryOperator) {
+  parseIR(C, R"IR(
+define void @foo(i8 %v1) {
+  %add = add i8 %v1, 42
+  %addNSW = add nsw i8 %v1, 42
+  %addNUW = add nuw i8 %v1, 42
+  ret void
+}
+)IR");
+  llvm::Function *LLVMF = &*M->getFunction("foo");
+  sandboxir::Context Ctx(C);
+  sandboxir::Function *F = Ctx.createFunction(LLVMF);
+  auto *BB = &*F->begin();
+  auto It = BB->begin();
+  auto *Add = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
+  auto *AddNSW = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
+  auto *AddNUW = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
+  EXPECT_FALSE(Add->hasNoUnsignedWrap());
+  EXPECT_FALSE(Add->hasNoSignedWrap());
+  EXPECT_EQ(Add->getNoWrapKind(), llvm::OverflowingBinaryOperator::AnyWrap);
+
+  EXPECT_FALSE(AddNSW->hasNoUnsignedWrap());
+  EXPECT_TRUE(AddNSW->hasNoSignedWrap());
+  EXPECT_EQ(AddNSW->getNoWrapKind(),
+            llvm::OverflowingBinaryOperator::NoSignedWrap);
+
+  EXPECT_TRUE(AddNUW->hasNoUnsignedWrap());
+  EXPECT_FALSE(AddNUW->hasNoSignedWrap());
+  EXPECT_EQ(AddNUW->getNoWrapKind(),
+            llvm::OverflowingBinaryOperator::NoUnsignedWrap);
+}



More information about the llvm-commits mailing list