Skip to content

Commit

Permalink
[IR] add block operand support for ir.
Browse files Browse the repository at this point in the history
  • Loading branch information
winter-wang committed Aug 24, 2023
1 parent 1c0db09 commit cc2252b
Show file tree
Hide file tree
Showing 25 changed files with 753 additions and 133 deletions.
11 changes: 10 additions & 1 deletion paddle/ir/core/block.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
#include "paddle/ir/core/region.h"

namespace ir {
Block::~Block() { clear(); }
Block::~Block() {
assert(use_empty() && "block destroyed still has uses.");
clear();
}
void Block::push_back(Operation *op) { insert(ops_.end(), op); }

void Block::push_front(Operation *op) { insert(ops_.begin(), op); }
Expand Down Expand Up @@ -51,4 +54,10 @@ void Block::SetParent(Region *parent, Region::iterator position) {
position_ = position;
}

Block::UseIterator Block::use_begin() const { return first_use_; }

Block::UseIterator Block::use_end() const { return Block::UseIterator(); }

bool Block::HasOneUse() const { return first_use_ && !first_use_.next_use(); }

} // namespace ir
15 changes: 15 additions & 0 deletions paddle/ir/core/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
#include <cstddef>
#include <list>

#include "paddle/ir/core/block_operand.h"
#include "paddle/ir/core/dll_decl.h"
#include "paddle/ir/core/region.h"
#include "paddle/ir/core/use_iterator.h"

namespace ir {
class Operation;
Expand Down Expand Up @@ -56,6 +58,18 @@ class IR_API Block {
void clear();
operator Region::iterator() { return position_; }

///
/// \brief Provide iterator interface to access Value use chain.
///
using UseIterator = ValueUseIterator<BlockOperand>;
UseIterator use_begin() const;
UseIterator use_end() const;
BlockOperand first_use() const { return first_use_; }
void set_first_use(BlockOperand first_use) { first_use_ = first_use; }
bool use_empty() const { return !first_use_; }
bool HasOneUse() const;
BlockOperand *first_use_addr() { return &first_use_; }

private:
Block(Block &) = delete;
Block &operator=(const Block &) = delete;
Expand All @@ -68,5 +82,6 @@ class IR_API Block {
Region *parent_; // not owned
OpListType ops_; // owned
Region::iterator position_;
BlockOperand first_use_;
};
} // namespace ir
113 changes: 113 additions & 0 deletions paddle/ir/core/block_operand.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/ir/core/block_operand.h"
#include "paddle/ir/core/block.h"
#include "paddle/ir/core/block_operand_impl.h"
#include "paddle/ir/core/enforce.h"

namespace ir {

#define CHECK_BLOCKOPEREND_NULL_IMPL(func_name) \
IR_ENFORCE(impl_, \
"impl_ pointer is null when call func:" #func_name \
" , in class: BlockOperand.")

BlockOperand &BlockOperand::operator=(const BlockOperand &rhs) {
if (this == &rhs) return *this;
impl_ = rhs.impl_;
return *this;
}

BlockOperand::operator bool() const { return impl_ && impl_->source(); }

BlockOperand BlockOperand::next_use() const {
CHECK_BLOCKOPEREND_NULL_IMPL(next_use);
return impl_->next_use();
}

Block *BlockOperand::source() const {
CHECK_BLOCKOPEREND_NULL_IMPL(source);
return impl_->source();
}

void BlockOperand::set_source(Block *source) {
CHECK_BLOCKOPEREND_NULL_IMPL(set_source);
impl_->set_source(source);
}

Operation *BlockOperand::owner() const {
CHECK_BLOCKOPEREND_NULL_IMPL(owner);
return impl_->owner();
}

void BlockOperand::RemoveFromUdChain() {
CHECK_BLOCKOPEREND_NULL_IMPL(RemoveFromUdChain);
return impl_->RemoveFromUdChain();
}

// details
namespace detail {

Operation *BlockOperandImpl::owner() const { return owner_; }

BlockOperand BlockOperandImpl::next_use() const { return next_use_; }

Block *BlockOperandImpl::source() const { return source_; }

void BlockOperandImpl::set_source(Block *source) {
RemoveFromUdChain();
if (!source) {
return;
}
source_ = source;
InsertToUdChain();
}

BlockOperandImpl::BlockOperandImpl(Block *source, ir::Operation *owner)
: source_(source), owner_(owner) {
if (!source) {
return;
}
InsertToUdChain();
}

void BlockOperandImpl::InsertToUdChain() {
prev_use_addr_ = source_->first_use_addr();
next_use_ = source_->first_use();
if (next_use_) {
next_use_.impl()->prev_use_addr_ = &next_use_;
}
source_->set_first_use(this);
}

void BlockOperandImpl::RemoveFromUdChain() {
if (!source_) return;
if (!prev_use_addr_) return;
if (prev_use_addr_ == source_->first_use_addr()) {
source_->set_first_use(next_use_);
} else {
*prev_use_addr_ = next_use_;
}
if (next_use_) {
next_use_.impl()->prev_use_addr_ = prev_use_addr_;
}
next_use_ = nullptr;
prev_use_addr_ = nullptr;
source_ = nullptr;
}

BlockOperandImpl::~BlockOperandImpl() { RemoveFromUdChain(); }
} // namespace detail
} // namespace ir
73 changes: 73 additions & 0 deletions paddle/ir/core/block_operand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "paddle/ir/core/cast_utils.h"
#include "paddle/ir/core/type.h"

namespace ir {
class Operation;
class Value;
class Block;

namespace detail {
class BlockOperandImpl;
} // namespace detail

///
/// \brief OpOperand class represents the op_operand of operation. This class
/// only provides interfaces, for specific implementation, see Impl class.
///
class IR_API BlockOperand {
public:
BlockOperand() = default;

BlockOperand(const BlockOperand &other) = default;

BlockOperand(detail::BlockOperandImpl *impl) : impl_(impl) {} // NOLINT

BlockOperand &operator=(const BlockOperand &rhs);

bool operator==(const BlockOperand &other) const {
return impl_ == other.impl_;
}

bool operator!=(const BlockOperand &other) const {
return !operator==(other);
}

bool operator!() const { return impl_ == nullptr; }

operator bool() const;

BlockOperand next_use() const;

Block *source() const;

void set_source(Block *source);

Operation *owner() const;

void RemoveFromUdChain();

friend Operation;

detail::BlockOperandImpl *impl() const { return impl_; }

private:
detail::BlockOperandImpl *impl_{nullptr};
};

} // namespace ir
61 changes: 61 additions & 0 deletions paddle/ir/core/block_operand_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "paddle/ir/core/block_operand.h"

namespace ir {
class Operation;
class Block;

namespace detail {
///
/// \brief OpOperandImpl
///
class BlockOperandImpl {
public:
Operation* owner() const;

BlockOperand next_use() const;

Block* source() const;

void set_source(Block*);

/// Remove this op_operand from the current use list.
void RemoveFromUdChain();

~BlockOperandImpl();

friend Operation;

private:
BlockOperandImpl(Block* source, Operation* owner);

// Insert self to the UD chain holded by source_;
// It is not safe. So set provate.
void InsertToUdChain();

BlockOperand next_use_ = nullptr;

BlockOperand* prev_use_addr_ = nullptr;

Block* source_;

Operation* const owner_ = nullptr;
};

} // namespace detail
} // namespace ir
6 changes: 4 additions & 2 deletions paddle/ir/core/builtin_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ Block *ModuleOp::block() {
ModuleOp ModuleOp::Create(IrContext *context, Program *pointer) {
ir::OpInfo info = context->GetRegisteredOpInfo(name());
OperationArgument argument(info);
argument.AddRegion()->emplace_back();
argument.num_regions = 1;
argument.AddAttribute("program", PointerAttribute::get(context, pointer));
return ModuleOp(Operation::Create(std::move(argument)));
Operation *op = Operation::Create(std::move(argument));
op->region(0).emplace_back();
return ModuleOp(op);
}

void ModuleOp::Destroy() {
Expand Down
Loading

0 comments on commit cc2252b

Please sign in to comment.