Skip to content

Commit 54566ba

Browse files
authored
[SandboxIR] Implement Operator (#112805)
This patch implements sandboxir::Operator mirroring llvm::Operator.
1 parent 00d30bd commit 54566ba

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===- Operator.h -----------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_SANDBOXIR_OPERATOR_H
10+
#define LLVM_SANDBOXIR_OPERATOR_H
11+
12+
#include "llvm/IR/Operator.h"
13+
#include "llvm/SandboxIR/Instruction.h"
14+
#include "llvm/SandboxIR/User.h"
15+
16+
namespace llvm::sandboxir {
17+
18+
class Operator : public User {
19+
public:
20+
// The Operator class is intended to be used as a utility, and is never itself
21+
// instantiated.
22+
Operator() = delete;
23+
void *operator new(size_t s) = delete;
24+
25+
static bool classof(const Instruction *) { return true; }
26+
static bool classof(const ConstantExpr *) { return true; }
27+
static bool classof(const Value *From) {
28+
return llvm::Operator::classof(From->Val);
29+
}
30+
bool hasPoisonGeneratingFlags() const {
31+
return cast<llvm::Operator>(Val)->hasPoisonGeneratingFlags();
32+
}
33+
};
34+
35+
class OverflowingBinaryOperator : public Operator {
36+
public:
37+
bool hasNoUnsignedWrap() const {
38+
return cast<llvm::OverflowingBinaryOperator>(Val)->hasNoUnsignedWrap();
39+
}
40+
bool hasNoSignedWrap() const {
41+
return cast<llvm::OverflowingBinaryOperator>(Val)->hasNoSignedWrap();
42+
}
43+
unsigned getNoWrapKind() const {
44+
return cast<llvm::OverflowingBinaryOperator>(Val)->getNoWrapKind();
45+
}
46+
static bool classof(const Instruction *From) {
47+
return llvm::OverflowingBinaryOperator::classof(
48+
cast<llvm::Instruction>(From->Val));
49+
}
50+
static bool classof(const ConstantExpr *From) {
51+
return llvm::OverflowingBinaryOperator::classof(
52+
cast<llvm::ConstantExpr>(From->Val));
53+
}
54+
static bool classof(const Value *From) {
55+
return llvm::OverflowingBinaryOperator::classof(From->Val);
56+
}
57+
};
58+
} // namespace llvm::sandboxir
59+
60+
#endif // LLVM_SANDBOXIR_OPERATOR_H

llvm/include/llvm/SandboxIR/Value.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class Module;
2828
class UnaryInstruction;
2929
class CmpInst;
3030
class IntrinsicInst;
31+
class Operator;
32+
class OverflowingBinaryOperator;
3133

3234
/// Iterator for the `Use` edges of a Value's users.
3335
/// \Returns a `Use` when dereferenced.
@@ -158,6 +160,8 @@ class Value {
158160
friend class Utils; // For `Val`.
159161
friend class Module; // For `Val`.
160162
friend class IntrinsicInst; // For `Val`.
163+
friend class Operator; // For `Val`.
164+
friend class OverflowingBinaryOperator; // For `Val`.
161165
// Region needs to manipulate metadata in the underlying LLVM Value, we don't
162166
// expose metadata in sandboxir.
163167
friend class Region;

llvm/unittests/SandboxIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_llvm_unittest(SandboxIRTests
99
IntrinsicInstTest.cpp
1010
PassTest.cpp
1111
RegionTest.cpp
12+
OperatorTest.cpp
1213
SandboxIRTest.cpp
1314
TrackerTest.cpp
1415
TypesTest.cpp
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//===- OperatorTest.cpp ---------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/SandboxIR/Operator.h"
10+
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/SandboxIR/Context.h"
12+
#include "llvm/SandboxIR/Function.h"
13+
#include "llvm/SandboxIR/Instruction.h"
14+
#include "llvm/SandboxIR/Module.h"
15+
#include "llvm/SandboxIR/Value.h"
16+
#include "llvm/Support/SourceMgr.h"
17+
#include "gtest/gtest.h"
18+
19+
using namespace llvm;
20+
21+
struct OperatorTest : public testing::Test {
22+
LLVMContext C;
23+
std::unique_ptr<Module> M;
24+
25+
void parseIR(LLVMContext &C, const char *IR) {
26+
SMDiagnostic Err;
27+
M = parseAssemblyString(IR, Err, C);
28+
if (!M)
29+
Err.print("OperatorTest", errs());
30+
}
31+
BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
32+
for (BasicBlock &BB : F)
33+
if (BB.getName() == Name)
34+
return &BB;
35+
llvm_unreachable("Expected to find basic block!");
36+
}
37+
};
38+
39+
TEST_F(OperatorTest, Operator) {
40+
parseIR(C, R"IR(
41+
define void @foo(i8 %v1) {
42+
%add0 = add i8 %v1, 42
43+
%add1 = add nuw i8 %v1, 42
44+
ret void
45+
}
46+
)IR");
47+
llvm::Function *LLVMF = &*M->getFunction("foo");
48+
sandboxir::Context Ctx(C);
49+
sandboxir::Function *F = Ctx.createFunction(LLVMF);
50+
auto *BB = &*F->begin();
51+
auto It = BB->begin();
52+
auto *OperatorI0 = cast<sandboxir::Operator>(&*It++);
53+
auto *OperatorI1 = cast<sandboxir::Operator>(&*It++);
54+
EXPECT_FALSE(OperatorI0->hasPoisonGeneratingFlags());
55+
EXPECT_TRUE(OperatorI1->hasPoisonGeneratingFlags());
56+
}
57+
58+
TEST_F(OperatorTest, OverflowingBinaryOperator) {
59+
parseIR(C, R"IR(
60+
define void @foo(i8 %v1) {
61+
%add = add i8 %v1, 42
62+
%addNSW = add nsw i8 %v1, 42
63+
%addNUW = add nuw i8 %v1, 42
64+
ret void
65+
}
66+
)IR");
67+
llvm::Function *LLVMF = &*M->getFunction("foo");
68+
sandboxir::Context Ctx(C);
69+
sandboxir::Function *F = Ctx.createFunction(LLVMF);
70+
auto *BB = &*F->begin();
71+
auto It = BB->begin();
72+
auto *Add = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
73+
auto *AddNSW = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
74+
auto *AddNUW = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
75+
EXPECT_FALSE(Add->hasNoUnsignedWrap());
76+
EXPECT_FALSE(Add->hasNoSignedWrap());
77+
EXPECT_EQ(Add->getNoWrapKind(), llvm::OverflowingBinaryOperator::AnyWrap);
78+
79+
EXPECT_FALSE(AddNSW->hasNoUnsignedWrap());
80+
EXPECT_TRUE(AddNSW->hasNoSignedWrap());
81+
EXPECT_EQ(AddNSW->getNoWrapKind(),
82+
llvm::OverflowingBinaryOperator::NoSignedWrap);
83+
84+
EXPECT_TRUE(AddNUW->hasNoUnsignedWrap());
85+
EXPECT_FALSE(AddNUW->hasNoSignedWrap());
86+
EXPECT_EQ(AddNUW->getNoWrapKind(),
87+
llvm::OverflowingBinaryOperator::NoUnsignedWrap);
88+
}

0 commit comments

Comments
 (0)