Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR][ABI] Apply CC lowering pass by default #842

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@
#ifndef CLANG_CIR_MISSINGFEATURES_H
#define CLANG_CIR_MISSINGFEATURES_H

constexpr bool cirMissingFeatureAssertionMode =
true; // Change to `false` to use llvm_unreachable

// Some assertions knowingly generate incorrect code. This macro allows us to
// switch between using `assert` and `llvm_unreachable` for these cases.
#define cir_assert_or_abort(cond, msg) \
do { \
if (cirMissingFeatureAssertionMode) { \
assert((cond) && msg); \
} else { \
llvm_unreachable(msg); \
} \
} while (0)

namespace cir {

struct MissingFeatures {
Expand Down Expand Up @@ -205,6 +219,26 @@ struct MissingFeatures {

//===--- ABI lowering --===//

static bool SPIRVABI() { return false; }

static bool AArch64TypeClassification() { return false; }

static bool X86ArgTypeClassification() { return false; }
static bool X86DefaultABITypeConvertion() { return false; }
static bool X86GetFPTypeAtOffset() { return false; }
static bool X86RetTypeClassification() { return false; }
static bool X86TypeClassification() { return false; }

static bool ABIClangTypeKind() { return false; }
static bool ABIEnterStructForCoercedAccess() { return false; }
static bool ABIFuncPtr() { return false; }
static bool ABIInRegAttribute() { return false; }
static bool ABINestedRecordLayout() { return false; }
static bool ABINoProtoFunctions() { return false; }
static bool ABIParameterCoercion() { return false; }
static bool ABIPointerParameterAttrs() { return false; }
static bool ABITransparentUnionHandling() { return false; }

//-- Missing AST queries

static bool CXXRecordDeclIsEmptyCXX11() { return false; }
Expand Down
11 changes: 7 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2978,10 +2978,6 @@ def fclangir_lib_opt : Flag<["-"], "fclangir-lib-opt">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
Alias<fclangir_lib_opt_EQ>,
HelpText<"Enable C/C++ library based optimizations">;
def fclangir_call_conv_lowering : Flag<["-"], "fclangir-call-conv-lowering">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable ClangIR calling convention lowering">,
MarshallingInfoFlag<FrontendOpts<"ClangIREnableCallConvLowering">>;
def fclangir_mem2reg : Flag<["-"], "fclangir-mem2reg">,
Visibility<[ClangOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable mem2reg on the flat ClangIR">,
Expand All @@ -3007,6 +3003,13 @@ defm clangir_direct_lowering : BoolFOption<"clangir-direct-lowering",
FrontendOpts<"ClangIRDirectLowering">, DefaultTrue,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Lower directly from ClangIR to LLVM">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Lower through MLIR to LLVM">>;
// FIXME(cir): Remove this option once all pre-existing tests are compatible with
// the calling convention lowering pass.
defm clangir_call_conv_lowering : BoolFOption<"clangir-call-conv-lowering",
sitio-couto marked this conversation as resolved.
Show resolved Hide resolved
FrontendOpts<"ClangIRCallConvLowering">, DefaultTrue,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Transform CIR to abide to calling convetions during lowering">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Ignore calling convetion during lowering">,
BothFlags<[], [ClangOption, CC1Option], "">>;

def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR, emit the .cir file">;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ class FrontendOptions {
unsigned ClangIRLibOpt : 1;

// Enable Clang IR call conv lowering pass.
unsigned ClangIREnableCallConvLowering : 1;
unsigned ClangIRCallConvLowering : 1;

// Enable Clang IR mem2reg pass on the flat CIR.
unsigned ClangIREnableMem2Reg : 1;
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CIR/Dialect/Transforms/CallConvLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//


#include "TargetLowering/LowerModule.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/MissingFeatures.h"

#define GEN_PASS_DEF_CALLCONVLOWERING
#include "clang/CIR/Dialect/Passes.h.inc"
Expand Down Expand Up @@ -44,6 +44,12 @@ struct CallConvLoweringPattern : public OpRewritePattern<FuncOp> {
auto calls = op.getSymbolUses(module);
if (calls.has_value()) {
for (auto call : calls.value()) {
// FIXME(cir): Function pointers are ignored.
if (isa<GetGlobalOp>(call.getUser())) {
cir_assert_or_abort(!::cir::MissingFeatures::ABIFuncPtr(), "NYI");
continue;
}

auto callOp = cast<CallOp>(call.getUser());
if (lowerModule->rewriteFunctionCall(callOp, op).failed())
return failure();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ bool isAggregateTypeForABI(Type T) {
Type useFirstFieldIfTransparentUnion(Type Ty) {
if (auto RT = dyn_cast<StructType>(Ty)) {
if (RT.isUnion())
llvm_unreachable("NYI");
cir_assert_or_abort(
!::cir::MissingFeatures::ABITransparentUnionHandling(), "NYI");
}
return Ty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ clang::TypeInfo CIRLowerContext::getTypeInfoImpl(const Type T) const {
} else if (isa<StructType>(T)) {
typeKind = clang::Type::Record;
} else {
llvm_unreachable("Unhandled type class");
cir_assert_or_abort(!::cir::MissingFeatures::ABIClangTypeKind(),
"Unhandled type class");
// FIXME(cir): Completely wrong. Just here to make it non-blocking.
typeKind = clang::Type::Builtin;
}

// FIXME(cir): Here we fetch the width and alignment of a type considering the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ arrangeFreeFunctionLikeCall(LowerTypes &LT, LowerModule &LM,
// FIXME(cir): Properly check if function is no-proto.
if (/*IsPrototypedFunction=*/true) {
if (fnType.isVarArg())
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::isVarArg(), "NYI");

if (::cir::MissingFeatures::extParamInfo())
llvm_unreachable("NYI");
Expand Down Expand Up @@ -147,7 +147,7 @@ void LowerModule::constructAttributeList(StringRef Name,
[[fallthrough]];
case ABIArgInfo::Direct:
if (RetAI.getInReg())
llvm_unreachable("InReg attribute is NYI");
cir_assert_or_abort(!::cir::MissingFeatures::ABIInRegAttribute(), "NYI");
assert(!::cir::MissingFeatures::noFPClass());
break;
case ABIArgInfo::Ignore:
Expand Down Expand Up @@ -253,7 +253,7 @@ const LowerFunctionInfo &LowerTypes::arrangeFunctionDeclaration(FuncOp fnOp) {
// When declaring a function without a prototype, always use a
// non-variadic type.
if (fnOp.getNoProto()) {
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::ABINoProtoFunctions(), "NYI");
}

return arrangeFreeFunctionType(FTy);
Expand Down
39 changes: 28 additions & 11 deletions clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ Value enterStructPointerForCoercedAccess(Value SrcPtr, StructType SrcSTy,
FirstEltSize < CGF.LM.getDataLayout().getTypeStoreSize(SrcSTy))
return SrcPtr;

llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::ABIEnterStructForCoercedAccess(),
"NYI");
return SrcPtr; // FIXME: This is a temporary workaround for the assertion
// above.
}

/// Create a store to \param Dst from \param Src where the source and
Expand Down Expand Up @@ -272,6 +275,13 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn,
SmallVector<Value, 8> ArgVals;
ArgVals.reserve(Args.size());

// FIXME(cir): non-blocking workaround for argument types that are not yet
// properly handled by the ABI.
if (cirMissingFeatureAssertionMode && FI.arg_size() != Args.size()) {
assert(::cir::MissingFeatures::ABIParameterCoercion());
return success();
}

// Create a pointer value for every parameter declaration. This usually
// entails copying one or more LLVM IR arguments into an alloca. Don't push
// any cleanups or do anything that might unwind. We do that separately, so
Expand Down Expand Up @@ -310,7 +320,8 @@ LowerFunction::buildFunctionProlog(const LowerFunctionInfo &FI, FuncOp Fn,
// http://llvm.org/docs/LangRef.html#paramattrs.
if (ArgI.getDirectOffset() == 0 && isa<PointerType>(LTy) &&
isa<PointerType>(ArgI.getCoerceToType())) {
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::ABIPointerParameterAttrs(),
"NYI");
}

// Prepare the argument value. If we have the trivial case, handle it
Expand Down Expand Up @@ -487,15 +498,20 @@ LogicalResult LowerFunction::generateCode(FuncOp oldFn, FuncOp newFn,
const auto hasNoUses = [](Value val) { return val.getUses().empty(); };
assert(std::all_of(Args.begin(), Args.end(), hasNoUses) && "Missing RAUW?");

// NOTE(cir): While the new function has the ABI-aware parameters, the old
// function still has the function logic. To complete the migration, we have
// to move the old function body to the new function.

// Backup references to entry blocks.
Block *srcBlock = &oldFn.getBody().front();
Block *dstBlock = &newFn.getBody().front();

// Migrate function body to new ABI-aware function.
assert(oldFn.getBody().hasOneBlock() &&
"Multiple blocks in original function not supported");
rewriter.inlineRegionBefore(oldFn.getBody(), newFn.getBody(),
newFn.getBody().end());

// Move old function body to new function.
// FIXME(cir): The merge below is not very good: will not work if SrcFn has
// multiple blocks and it mixes the new and old prologues.
rewriter.mergeBlocks(&oldFn.getBody().front(), &newFn.getBody().front(),
newFn.getArguments());
// Merge entry blocks to ensure correct branching.
rewriter.mergeBlocks(srcBlock, dstBlock, newFn.getArguments());

// FIXME(cir): What about saving parameters for corotines? Should we do
// something about it in this pass? If the change with the calling
Expand Down Expand Up @@ -613,7 +629,7 @@ Value LowerFunction::rewriteCallOp(FuncType calleeTy, FuncOp origCallee,
// Chain calls use this same code path to add the invisible chain parameter
// to the function type.
if (origCallee.getNoProto() || Chain) {
llvm_unreachable("NYI");
cir_assert_or_abort(::cir::MissingFeatures::ABINoProtoFunctions(), "NYI");
}

assert(!::cir::MissingFeatures::CUDA());
Expand Down Expand Up @@ -900,7 +916,8 @@ ::cir::TypeEvaluationKind LowerFunction::getEvaluationKind(Type type) {
// FIXME(cir): Implement type classes for CIR types.
if (isa<StructType>(type))
return ::cir::TypeEvaluationKind::TEK_Aggregate;
if (isa<BoolType, IntType, SingleType, DoubleType>(type))
if (isa<BoolType, IntType, SingleType, DoubleType, LongDoubleType, VectorType,
PointerType>(type))
return ::cir::TypeEvaluationKind::TEK_Scalar;
llvm_unreachable("NYI");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class RequiredArgs {
if (!prototype.isVarArg())
return All;

llvm_unreachable("Variadic function is NYI");
cir_assert_or_abort(!::cir::MissingFeatures::variadicFunctions(), "NYI");
return All; // FIXME(cir): Temporary workaround for the assertion above.
}

bool allowsOptionalArgs() const { return NumRequired != ~0U; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,13 @@ LogicalResult LowerModule::rewriteFunctionDefinition(FuncOp op) {
llvm_unreachable("ExtraAttrs are NYI");
}

if (LowerFunction(*this, rewriter, op, newFn)
.generateCode(op, newFn, FI)
.failed())
return failure();
// Is a function definition: handle the body.
if (!op.isDeclaration()) {
if (LowerFunction(*this, rewriter, op, newFn)
.generateCode(op, newFn, FI)
.failed())
return failure();
}

// Erase original ABI-agnostic function.
rewriter.eraseOp(op);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,7 @@ mlir::Type LowerTypes::convertType(Type T) {
}

llvm::outs() << "Missing default ABI-specific type for " << T << "\n";
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::X86DefaultABITypeConvertion(),
"NYI");
return T;
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ void EmptySubobjectMap::ComputeEmptySubobjectSizes() {
continue;

// TODO(cir): Handle nested record types.
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::ABINestedRecordLayout(),
"NYI");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(Type RetTy,
return ABIArgInfo::getIgnore();

if (const auto _ = dyn_cast<VectorType>(RetTy)) {
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::vectorType(), "NYI");
}

// Large vector types should be returned via memory.
Expand Down Expand Up @@ -128,7 +128,9 @@ AArch64ABIInfo::classifyArgumentType(Type Ty, bool IsVariadic,
: ABIArgInfo::getDirect());
}

llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::AArch64TypeClassification(),
"NYI");
return {};
}

std::unique_ptr<TargetLoweringInfo>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class SPIRVABIInfo : public ABIInfo {

private:
void computeInfo(LowerFunctionInfo &FI) const override {
llvm_unreachable("ABI NYI");
cir_assert_or_abort(!::cir::MissingFeatures::SPIRVABI(), "NYI");
}
};

Expand Down
16 changes: 11 additions & 5 deletions clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ Type getFPTypeAtOffset(Type IRType, unsigned IROffset,
if (IROffset == 0 && isa<SingleType, DoubleType>(IRType))
return IRType;

llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::X86GetFPTypeAtOffset(), "NYI");
return IRType; // FIXME(cir): Temporary workaround for the assertion above.
}

} // namespace
Expand Down Expand Up @@ -337,7 +338,8 @@ void X86_64ABIInfo::classify(Type Ty, uint64_t OffsetBase, Class &Lo, Class &Hi,
postMerge(Size, Lo, Hi);
} else {
llvm::outs() << "Missing X86 classification for type " << Ty << "\n";
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::X86TypeClassification(),
"NYI");
}
// FIXME: _Decimal32 and _Decimal64 are SSE.
// FIXME: _float128 and _Decimal128 are (SSE, SSEUp).
Expand Down Expand Up @@ -436,7 +438,9 @@ Type X86_64ABIInfo::GetINTEGERTypeAtOffset(Type DestTy, unsigned IROffset,
unsigned TySizeInBytes =
(unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();

assert(TySizeInBytes != SourceOffset && "Empty field?");
// FIXME(cir): Temporary workaround to make things non-blocking.
if (!cirMissingFeatureAssertionMode)
assert(TySizeInBytes != SourceOffset && "Empty field?");

// It is always safe to classify this as an integer type up to i64 that
// isn't larger than the structure.
Expand Down Expand Up @@ -492,7 +496,8 @@ ::cir::ABIArgInfo X86_64ABIInfo::classifyReturnType(Type RetTy) const {
break;

default:
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::X86RetTypeClassification(),
"NYI");
}

Type HighPart = {};
Expand Down Expand Up @@ -566,7 +571,8 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(Type Ty, unsigned freeIntRegs,
break;
}
default:
llvm_unreachable("NYI");
cir_assert_or_abort(!::cir::MissingFeatures::X86ArgTypeClassification(),
"NYI");
}

Type HighPart = {};
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CIR/FrontendAction/CIRGenAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,7 @@ class CIRGenConsumer : public clang::ASTConsumer {
feOptions.ClangIRLibOpt, libOptOpts, passOptParsingFailure,
action == CIRGenAction::OutputType::EmitCIRFlat,
action == CIRGenAction::OutputType::EmitMLIR,
feOptions.ClangIREnableCallConvLowering,
feOptions.ClangIREnableMem2Reg)
feOptions.ClangIRCallConvLowering, feOptions.ClangIREnableMem2Reg)
.failed()) {
if (!passOptParsingFailure.empty())
diagnosticsEngine.Report(diag::err_drv_cir_pass_opt_parsing)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2960,7 +2960,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ClangIRVerifyDiags = true;

if (Args.hasArg(OPT_fclangir_call_conv_lowering))
Opts.ClangIREnableCallConvLowering = true;
Opts.ClangIRCallConvLowering = true;

if (const Arg *A = Args.getLastArg(OPT_fclangir_lifetime_check,
OPT_fclangir_lifetime_check_EQ)) {
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/OpenCL/addrspace-alloca.cl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -cl-std=CL3.0 -O0 -fclangir -emit-cir -triple spirv64-unknown-unknown %s -o %t.cir
// RUN: %clang_cc1 -cl-std=CL3.0 -O0 -fclangir -fno-clangir-call-conv-lowering -emit-cir -triple spirv64-unknown-unknown %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
// RUN: %clang_cc1 -cl-std=CL3.0 -O0 -fclangir -emit-llvm -triple spirv64-unknown-unknown %s -o %t.ll
// RUN: %clang_cc1 -cl-std=CL3.0 -O0 -fclangir -fno-clangir-call-conv-lowering -emit-llvm -triple spirv64-unknown-unknown %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM


Expand Down
Loading
Loading