Skip to content

Commit

Permalink
Merge branch 'master_prm' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
chuang13 committed Nov 21, 2023
2 parents 1538fd1 + e51543d commit c99b6ec
Show file tree
Hide file tree
Showing 113 changed files with 7,961 additions and 909 deletions.
5 changes: 0 additions & 5 deletions .gitattributes

This file was deleted.

3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ endif()

### VKGC build LLPC ################################################################
if(ICD_BUILD_LLPC)
include("cmake/compilerutils.cmake")
add_compilerutils_projects()

target_include_directories(vkgc
INTERFACE
${PROJECT_SOURCE_DIR}/llpc/include
Expand Down
40 changes: 40 additions & 0 deletions cmake/compilerutils.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
##
#######################################################################################################################
#
# Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#######################################################################################################################

set(LLPC_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/..")

# Function to add compilerutils as LLVM external projects.
# This appends the project names to LLVM_EXTERNAL_PROJECTS and sets each LLVM_EXTERNAL_*_SOURCE_DIR,
# all in the caller's scope.
macro(add_compilerutils_projects)
if (NOT compilerutils IN_LIST LLVM_EXTERNAL_PROJECTS)
if (NOT llvm_dialects IN_LIST LLVM_EXTERNAL_PROJECTS)
list(APPEND LLVM_EXTERNAL_PROJECTS llvm_dialects)
set(LLVM_EXTERNAL_LLVM_DIALECTS_SOURCE_DIR "${LLPC_SOURCE_DIR}/imported/llvm-dialects")
endif()
list(APPEND LLVM_EXTERNAL_PROJECTS CompilerUtils)
set(LLVM_EXTERNAL_COMPILERUTILS_SOURCE_DIR "${LLPC_SOURCE_DIR}/compilerutils")
endif()
endmacro()
3 changes: 3 additions & 0 deletions cmake/continuations.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@

set(LLPC_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/..")

include("${LLPC_SOURCE_DIR}/cmake/compilerutils.cmake")

# Macro to add continuations and its dependencies as LLVM external projects.
# This appends the project names to LLVM_EXTERNAL_PROJECTS and sets each LLVM_EXTERNAL_*_SOURCE_DIR,
# all in the caller's scope.
macro(add_continuations_projects)
add_compilerutils_projects()
if (NOT continuations IN_LIST LLVM_EXTERNAL_PROJECTS)
if (NOT llvm_dialects IN_LIST LLVM_EXTERNAL_PROJECTS)
list(APPEND LLVM_EXTERNAL_PROJECTS llvm_dialects)
Expand Down
37 changes: 37 additions & 0 deletions compilerutils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.13.4)

project(CompilerUtils LANGUAGES CXX)

function(set_compiler_options PROJECT_NAME)
# Output with color if in terminal: https://github.com/ninja-build/ninja/wiki/FAQ
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options("${PROJECT_NAME}" PRIVATE -fdiagnostics-color=always)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options("${PROJECT_NAME}" PRIVATE -fcolor-diagnostics)
endif()
endfunction()

add_llvm_library(LLVMCompilerUtils
lib/CompilerUtils.cpp
lib/TypeLowering.cpp

DEPENDS
intrinsics_gen

LINK_COMPONENTS
Analysis
Core
Support
)

target_include_directories(LLVMCompilerUtils PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<INSTALL_INTERFACE:include>
)

target_link_libraries(LLVMCompilerUtils PUBLIC llvm_dialects)
set_compiler_options(LLVMCompilerUtils)

target_compile_features(LLVMCompilerUtils PUBLIC cxx_std_17)
set_target_properties(LLVMCompilerUtils PROPERTIES CXX_EXTENSIONS OFF)
71 changes: 71 additions & 0 deletions compilerutils/include/compilerutils/CompilerUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
***********************************************************************************************************************
*
* Copyright (c) 2023 Advanced Micro Devices, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************************************************************************/

//===- CompilerUtils.h - Library for compiler frontends -------------------===//
//
// Implements several shared helper functions.
//
//===----------------------------------------------------------------------===//

#ifndef COMPILERUTILS_H
#define COMPILERUTILS_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/IRBuilder.h"

namespace llvm {

class CallInst;
class Function;
class Type;
class Value;

} // namespace llvm

namespace CompilerUtils {

// Create an LLVM function call to the named function. The callee is built
// automatically based on return type and its parameters.
//
// @param funcName : Name of the callee
// @param retTy : Return type of the callee
// @param args : Arguments to pass to the callee
// @param attribs : Function attributes
// @param instName : Name to give instruction
llvm::CallInst *createNamedCall(llvm::IRBuilder<> &, llvm::StringRef, llvm::Type *, llvm::ArrayRef<llvm::Value *>,
llvm::ArrayRef<llvm::Attribute::AttrKind>, const llvm::Twine & = "");

// Modify the function argument types, and return the new function. NOTE: the
// function does not do any uses replacement, so the caller should call
// replaceAllUsesWith() for the function and arguments afterwards.
llvm::Function *mutateFunctionArguments(llvm::Function &, llvm::Type *, const llvm::ArrayRef<llvm::Type *>,
llvm::AttributeList);

} // namespace CompilerUtils

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -60,43 +60,49 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/IRBuilder.h"

namespace lgc {

class TypeLowering;

/// Given a type, check if it should be replaced.
///
/// Return an empty vector if this function doesn't know how to handle the given type. Subsequent conversion rules will
/// then be considered.
/// Return an empty vector if this function doesn't know how to handle the given
/// type. Subsequent conversion rules will then be considered.
///
/// Otherwise, return a vector with the replacement type(s). If the type is known to remain unchanged, return a
/// singleton vector containing just the original type.
/// Otherwise, return a vector with the replacement type(s). If the type is
/// known to remain unchanged, return a singleton vector containing just the
/// original type.
using TypeLoweringFn = llvm::SmallVector<llvm::Type *>(TypeLowering &, llvm::Type *);

/// Given a constant that is known to be meant to be replaced based on its type, attempt to replace it.
/// Given a constant that is known to be meant to be replaced based on its type,
/// attempt to replace it.
///
/// Return a non-empty vector if this function was able to handle the constant.
///
/// Otherwise, return an empty vector, and subsequent rules will be applied. Default rules exist for poison, undef,
/// and "null-like" (zeroinitializer etc.).
/// Otherwise, return an empty vector, and subsequent rules will be applied.
/// Default rules exist for poison, undef, and "null-like" (zeroinitializer
/// etc.).
using ConstantTypeLoweringFn = llvm::SmallVector<llvm::Constant *>(TypeLowering &, llvm::Constant *,
llvm::ArrayRef<llvm::Type *>);

// =====================================================================================================================
/// Helper for lowerings that need to replace values of one type by one or more values of another type.
/// Helper for lowerings that need to replace values of one type by one or more
/// values of another type.
///
/// This helper really has two parts:
///
/// - A type-level part that applies @ref TypeLoweringFn rules and caches the result
/// - A value-level part that maintains a mapping of replaced values and provides generic handlers for core
/// - A type-level part that applies @ref TypeLoweringFn rules and caches the
/// result
/// - A value-level part that maintains a mapping of replaced values and
/// provides generic handlers for core
/// instructions like phi, select, and alloca
///
/// The type-level part can be reused even as the value-level part is cleared by @ref finishCleanup, assuming that the
/// type replacements are consistent (which they might not always be, e.g. where the replacement depends on the target
/// architecture).
/// The type-level part can be reused even as the value-level part is cleared by
/// @ref finishCleanup, assuming that the type replacements are consistent
/// (which they might not always be, e.g. where the replacement depends on the
/// target architecture).
///
/// The value-level part is meant to be used as a nested @ref llvm_dialects::Visitor client. It requires RPO traversal
/// order. Its intended use is along the following lines:
/// The value-level part is meant to be used as a nested @ref
/// llvm_dialects::Visitor client. It requires RPO traversal order. Its intended
/// use is along the following lines:
/// @code
/// struct MyPayload {
/// TypeLowering lowering;
Expand All @@ -108,8 +114,9 @@ using ConstantTypeLoweringFn = llvm::SmallVector<llvm::Constant *>(TypeLowering
///
/// MyPayload payload;
///
/// // Reverse post order traversal through functions, replacing instructions with converted types as we go.
/// static const auto visitor = VisitorBuilder<MyPayload>
/// // Reverse post order traversal through functions, replacing instructions
/// with converted types as we go. static const auto visitor =
/// VisitorBuilder<MyPayload>
/// .add(...)
/// .nest(&TypeLowering::registerVisitors)
/// .build();
Expand All @@ -118,42 +125,42 @@ using ConstantTypeLoweringFn = llvm::SmallVector<llvm::Constant *>(TypeLowering
/// // Fixup phi nodes.
/// payload.lowering.finishPhis();
///
/// // Erase all instructions that "have been replaced" (by calling replaceInstruction for them).
/// payload.lowering.finishCleanup();
/// // Erase all instructions that "have been replaced" (by calling
/// replaceInstruction for them). payload.lowering.finishCleanup();
/// @endcode
class TypeLowering {
public:
TypeLowering(llvm::LLVMContext &context);
TypeLowering(llvm::LLVMContext &);

llvm::LLVMContext &getContext() const { return m_builder.getContext(); }

void addRule(std::function<TypeLoweringFn> rule);
void addConstantRule(std::function<ConstantTypeLoweringFn> rule);
void addRule(std::function<TypeLoweringFn>);
void addConstantRule(std::function<ConstantTypeLoweringFn>);

llvm::ArrayRef<llvm::Type *> convertType(llvm::Type *type);
llvm::ArrayRef<llvm::Type *> convertType(llvm::Type *);

static void registerVisitors(llvm_dialects::VisitorBuilder<TypeLowering> &builder);
static void registerVisitors(llvm_dialects::VisitorBuilder<TypeLowering> &);

llvm::SmallVector<llvm::Value *> getValue(llvm::Value *value);
llvm::SmallVector<llvm::Value *> getValueOptional(llvm::Value *value);
void replaceInstruction(llvm::Instruction *inst, llvm::ArrayRef<llvm::Value *> mapping);
void eraseInstruction(llvm::Instruction *inst);
llvm::SmallVector<llvm::Value *> getValue(llvm::Value *);
llvm::SmallVector<llvm::Value *> getValueOptional(llvm::Value *);
void replaceInstruction(llvm::Instruction *, llvm::ArrayRef<llvm::Value *>);
void eraseInstruction(llvm::Instruction *);

llvm::Function *lowerFunctionArguments(llvm::Function &fn);
llvm::Function *lowerFunctionArguments(llvm::Function &);
void finishPhis();
bool finishCleanup();

private:
void recordValue(llvm::Value *value, llvm::ArrayRef<llvm::Value *> mapping);
void replaceMappingWith(llvm::Value *toReplace, llvm::Value *with);
void recordValue(llvm::Value *, llvm::ArrayRef<llvm::Value *>);
void replaceMappingWith(llvm::Value *, llvm::Value *);

void visitAlloca(llvm::AllocaInst &alloca);
void visitExtract(llvm::ExtractValueInst &extract);
void visitInsert(llvm::InsertValueInst &insert);
void visitLoad(llvm::LoadInst &load);
void visitPhi(llvm::PHINode &phi);
void visitSelect(llvm::SelectInst &select);
void visitStore(llvm::StoreInst &store);
void visitAlloca(llvm::AllocaInst &);
void visitExtract(llvm::ExtractValueInst &);
void visitInsert(llvm::InsertValueInst &);
void visitLoad(llvm::LoadInst &);
void visitPhi(llvm::PHINode &);
void visitSelect(llvm::SelectInst &);
void visitStore(llvm::StoreInst &);

/// Type conversion rules.
llvm::SmallVector<std::function<TypeLoweringFn>> m_rules;
Expand All @@ -170,18 +177,18 @@ class TypeLowering {
/// Map original values to type-converted values.
///
/// For 1-1 mappings, this stores a value pointer.
/// For 1-N mappings, this stores ((index << 1) | 1), where index is the index into m_convertedValueList at which the
/// converted values can be found.
/// For 1-N mappings, this stores ((index << 1) | 1), where index is the index
/// into m_convertedValueList at which the converted values can be found.
llvm::DenseMap<llvm::Value *, uintptr_t> m_valueMap;
std::vector<llvm::Value *> m_convertedValueList;

/// Reverse map of values that occur as type-converted values to where they occur. The vector elements are either a
/// value pointer (for 1-1 mapped values) or ((index << 1) | 1), where index is the index into m_convertedValueList.
/// Reverse map of values that occur as type-converted values to where they
/// occur. The vector elements are either a value pointer (for 1-1 mapped
/// values) or ((index << 1) | 1), where index is the index into
/// m_convertedValueList.
llvm::DenseMap<llvm::Value *, llvm::SmallVector<uintptr_t>> m_valueReverseMap;

std::vector<std::pair<llvm::PHINode *, llvm::SmallVector<llvm::PHINode *>>> m_phis;
std::vector<llvm::Instruction *> m_instructionsToErase;
llvm::SmallVector<llvm::Function *> m_functionToErase;
llvm::SmallVector<llvm::Function *> m_functionsToErase;
};

} // namespace lgc
Loading

0 comments on commit c99b6ec

Please sign in to comment.