Skip to content

Commit c7a074b

Browse files
committed
[CIR] Add Intrinsic handling skeleton
1 parent 32e3971 commit c7a074b

File tree

5 files changed

+388
-1
lines changed

5 files changed

+388
-1
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
//===- CIRIntrinsics.h - CIR Intrinsic Function Handling ----------*- C++
2+
//-*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file defines a set of enums which allow processing of intrinsic
11+
// functions. Values of these enum types are returned by
12+
// Function::getIntrinsicID.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_CLANG_CIR_DIALECT_INTRINSICS_H
17+
#define LLVM_CLANG_CIR_DIALECT_INTRINSICS_H
18+
19+
#include "mlir/IR/BuiltinAttributes.h"
20+
#include "mlir/IR/SymbolTable.h"
21+
#include "clang/CIR/Dialect/IR/CIRDialect.h"
22+
#include "llvm/ADT/ArrayRef.h"
23+
#include "llvm/ADT/StringRef.h"
24+
#include "llvm/IR/Intrinsics.h"
25+
#include "llvm/Support/TypeSize.h"
26+
#include <optional>
27+
#include <string>
28+
// #include "mlir/IR/Types.h"
29+
#include "mlir/Interfaces/DataLayoutInterfaces.h"
30+
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
31+
#include "clang/CIR/Interfaces/ASTAttrInterfaces.h"
32+
#include "clang/CIR/Interfaces/CIRFPTypeInterface.h"
33+
34+
namespace mlir {
35+
class Type;
36+
class ModuleOp;
37+
class MLIRContext;
38+
} // namespace mlir
39+
40+
namespace llvm {
41+
class StringRef;
42+
43+
namespace Intrinsic {
44+
struct IITDescriptor; // No need to duplicate the definition here
45+
} // namespace Intrinsic
46+
47+
} // namespace llvm
48+
namespace cir {
49+
class LLVMIntrinsicCallOp;
50+
class FuncOp;
51+
// FIXME: Unsure if we need a proper function type
52+
53+
namespace Intrinsic {
54+
55+
// Abstraction for the arguments of the noalias intrinsics
56+
static const int NoAliasScopeDeclScopeArg = 0;
57+
58+
// Intrinsic ID type. This is an opaque typedef to facilitate splitting up
59+
// the enum into target-specific enums.
60+
typedef unsigned ID;
61+
62+
enum IndependentIntrinsics : unsigned {
63+
not_intrinsic = 0, // Must be zero
64+
65+
// Get the intrinsic enums generated from Intrinsics.td
66+
#define GET_INTRINSIC_ENUM_VALUES
67+
#include "llvm/IR/IntrinsicEnums.inc"
68+
#undef GET_INTRINSIC_ENUM_VALUES
69+
};
70+
71+
/// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
72+
/// Note, this version is for intrinsics with no overloads. Use the other
73+
/// version of getName if overloads are required.
74+
llvm::StringRef getName(ID id);
75+
76+
/// Return the LLVM name for an intrinsic, without encoded types for
77+
/// overloading, such as "llvm.ssa.copy".
78+
llvm::StringRef getBaseName(ID id);
79+
80+
/// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx" or
81+
/// "llvm.ssa.copy.p0s_s.1". Note, this version of getName supports overloads.
82+
/// This is less efficient than the StringRef version of this function. If no
83+
/// overloads are required, it is safe to use this version, but better to use
84+
/// the StringRef version. If one of the types is based on an unnamed type, a
85+
/// function type will be computed. Providing FT will avoid this computation.
86+
std::string getName(ID Id, llvm::ArrayRef<mlir::Type> Tys, mlir::ModuleOp M,
87+
mlir::Type FT = nullptr);
88+
89+
/// Return the LLVM name for an intrinsic. This is a special version only to
90+
/// be used by LLVMIntrinsicCopyOverloadedName. It only supports overloads
91+
/// based on named types.
92+
std::string getNameNoUnnamedTypes(ID Id, llvm::ArrayRef<mlir::Type> Tys);
93+
94+
/// Return the function type for an intrinsic.
95+
mlir::Type *getType(mlir::MLIRContext& Context, ID id,
96+
llvm::ArrayRef<mlir::Type> Tys = {});
97+
98+
/// Returns true if the intrinsic can be overloaded.
99+
bool isOverloaded(ID id);
100+
101+
ID lookupIntrinsicID(llvm::StringRef Name);
102+
103+
// FIXME: Uses table from LLVM, but we don't have it yet.
104+
/// Return the attributes for an intrinsic.
105+
// AttributeList getAttributes(mlir::MLIRContext &C, ID id);
106+
// this is also defined as:
107+
// /// This defines the "Intrinsic::getAttributes(ID id)" method.
108+
// #define GET_INTRINSIC_ATTRIBUTES
109+
// #include "llvm/IR/IntrinsicImpl.inc"
110+
// #undef GET_INTRINSIC_ATTRIBUTES
111+
112+
/// Look up the Function declaration of the intrinsic \p id in the Module
113+
/// \p M. If it does not exist, add a declaration and return it. Otherwise,
114+
/// return the existing declaration.
115+
///
116+
/// The \p Tys parameter is for intrinsics with overloaded types (e.g., those
117+
/// using iAny, fAny, vAny, or pAny). For a declaration of an overloaded
118+
/// intrinsic, Tys must provide exactly one type for each overloaded type in
119+
/// the intrinsic.
120+
LLVMIntrinsicCallOp getOrInsertDeclaration(mlir::ModuleOp M, ID id,
121+
llvm::ArrayRef<mlir::Type> Tys = {});
122+
123+
/// Look up the Function declaration of the intrinsic \p id in the Module
124+
/// \p M and return it if it exists. Otherwise, return nullptr. This version
125+
/// supports non-overloaded intrinsics.
126+
LLVMIntrinsicCallOp getDeclarationIfExists(const mlir::ModuleOp *M, ID id);
127+
128+
/// This version supports overloaded intrinsics.
129+
LLVMIntrinsicCallOp getDeclarationIfExists(mlir::ModuleOp M, ID id,
130+
llvm::ArrayRef<mlir::Type> Tys,
131+
mlir::Type FT = nullptr);
132+
133+
/// Map a Clang builtin name to an intrinsic ID.
134+
ID getIntrinsicForClangBuiltin(llvm::StringRef TargetPrefix,
135+
llvm::StringRef BuiltinName);
136+
137+
/// Map a MS builtin name to an intrinsic ID.
138+
ID getIntrinsicForMSBuiltin(llvm::StringRef TargetPrefix,
139+
llvm::StringRef BuiltinName);
140+
141+
// FIXME: Uses table from LLVM, but we don't have it yet.
142+
// /// Returns true if the intrinsic ID is for one of the "Constrained
143+
// /// Floating-Point Intrinsics".
144+
// bool isConstrainedFPIntrinsic(ID QID);
145+
146+
// /// Returns true if the intrinsic ID is for one of the "Constrained
147+
// /// Floating-Point Intrinsics" that take rounding mode metadata.
148+
// bool hasConstrainedFPRoundingModeOperand(ID QID);
149+
150+
/// Return the IIT table descriptor for the specified intrinsic into an array
151+
/// of IITDescriptors.
152+
void getIntrinsicInfoTableEntries(
153+
ID id, llvm::SmallVectorImpl<llvm::Intrinsic::IITDescriptor> &T);
154+
155+
enum MatchIntrinsicTypesResult {
156+
MatchIntrinsicTypes_Match = 0,
157+
MatchIntrinsicTypes_NoMatchRet = 1,
158+
MatchIntrinsicTypes_NoMatchArg = 2,
159+
};
160+
161+
/// Match the specified function type with the type constraints specified by
162+
/// the .td file. If the given type is an overloaded type it is pushed to the
163+
/// ArgTys vector.
164+
///
165+
/// Returns false if the given type matches with the constraints, true
166+
/// otherwise.
167+
MatchIntrinsicTypesResult
168+
matchIntrinsicSignature(FuncOp FTy,
169+
llvm::ArrayRef<llvm::Intrinsic::IITDescriptor> &Infos,
170+
llvm::SmallVectorImpl<mlir::Type> &ArgTys);
171+
172+
/// Verify if the intrinsic has variable arguments. This method is intended to
173+
/// be called after all the fixed arguments have been matched first.
174+
///
175+
/// This method returns true on error.
176+
bool matchIntrinsicVarArg(
177+
bool isVarArg, llvm::ArrayRef<llvm::Intrinsic::IITDescriptor> &Infos);
178+
179+
/// Gets the type arguments of an intrinsic call by matching type contraints
180+
/// specified by the .td file. The overloaded types are pushed into the
181+
/// AgTys vector.
182+
///
183+
/// Returns false if the given ID and function type combination is not a
184+
/// valid intrinsic call.
185+
bool getIntrinsicSignature(Intrinsic::ID, mlir::Type FT,
186+
llvm::SmallVectorImpl<mlir::Type> &ArgTys);
187+
188+
/// Same as previous, but accepts a Function instead of ID and FunctionType.
189+
bool getIntrinsicSignature(FuncOp F, llvm::SmallVectorImpl<mlir::Type> &ArgTys);
190+
191+
// Checks if the intrinsic name matches with its signature and if not
192+
// returns the declaration with the same signature and remangled name.
193+
// An existing GlobalValue with the wanted name but with a wrong prototype
194+
// or of the wrong kind will be renamed by adding ".renamed" to the name.
195+
std::optional<LLVMIntrinsicCallOp> remangleIntrinsicFunction(FuncOp F);
196+
197+
} // namespace Intrinsic
198+
} // namespace cir
199+
200+
#endif // LLVM_CLANG_CIR_DIALECT_INTRINSICS_H

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "mlir/IR/Verifier.h"
3434
#include "clang/AST/Expr.h"
3535
#include "clang/Basic/Cuda.h"
36+
#include "clang/CIR/Dialect/IR/CIRIntrinsics.h"
3637
#include "clang/CIR/Dialect/IR/CIRTypes.h"
3738
#include "clang/CIR/MissingFeatures.h"
3839

@@ -2477,6 +2478,11 @@ void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
24772478
setCommonAttributes(aliasGD, alias);
24782479
}
24792480

2481+
cir::LLVMIntrinsicCallOp
2482+
CIRGenModule::getIntrinsic(unsigned IID, ArrayRef<mlir::Type> Tys) {
2483+
return cir::Intrinsic::getOrInsertDeclaration(getModule(), (cir::Intrinsic::ID)IID, Tys);
2484+
}
2485+
24802486
mlir::Type CIRGenModule::convertType(QualType type) {
24812487
return genTypes.convertType(type);
24822488
}

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,8 @@ class CIRGenModule : public CIRGenTypeCache {
655655
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op,
656656
GlobalDecl aliasGD, cir::FuncOp aliasee,
657657
cir::GlobalLinkageKind linkage);
658-
658+
cir::LLVMIntrinsicCallOp getIntrinsic(unsigned IID,
659+
ArrayRef<mlir::Type> Tys);
659660
mlir::Type convertType(clang::QualType type);
660661

661662
/// Set the visibility for the given global.

0 commit comments

Comments
 (0)