[SandboxIR] Implement Operator (#112805)
This patch implements sandboxir::Operator mirroring llvm::Operator.
This commit is contained in:
60
llvm/include/llvm/SandboxIR/Operator.h
Normal file
60
llvm/include/llvm/SandboxIR/Operator.h
Normal file
@@ -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
|
||||
@@ -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 @@ protected:
|
||||
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;
|
||||
|
||||
@@ -9,6 +9,7 @@ add_llvm_unittest(SandboxIRTests
|
||||
IntrinsicInstTest.cpp
|
||||
PassTest.cpp
|
||||
RegionTest.cpp
|
||||
OperatorTest.cpp
|
||||
SandboxIRTest.cpp
|
||||
TrackerTest.cpp
|
||||
TypesTest.cpp
|
||||
|
||||
88
llvm/unittests/SandboxIR/OperatorTest.cpp
Normal file
88
llvm/unittests/SandboxIR/OperatorTest.cpp
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user