12
12
// ===----------------------------------------------------------------------===//
13
13
#include " mlir/Dialect/LLVMIR/LLVMDialect.h"
14
14
#include " TypeDetail.h"
15
+ #include " mlir/Dialect/LLVMIR/LLVMAttrs.h"
15
16
#include " mlir/Dialect/LLVMIR/LLVMInterfaces.h"
16
17
#include " mlir/Dialect/LLVMIR/LLVMTypes.h"
17
18
#include " mlir/IR/Builders.h"
@@ -2854,6 +2855,39 @@ static void moveConstantAllocasToEntryBlock(
2854
2855
}
2855
2856
}
2856
2857
2858
+ static Value handleByValArgument (OpBuilder &builder, Operation *callable,
2859
+ Value argument,
2860
+ NamedAttribute byValAttribute) {
2861
+ auto func = cast<LLVM::LLVMFuncOp>(callable);
2862
+ LLVM::MemoryEffectsAttr memoryEffects = func.getMemoryAttr ();
2863
+ // If there is no memory effects attribute, assume that the function is
2864
+ // not read-only.
2865
+ bool isReadOnly = memoryEffects &&
2866
+ memoryEffects.getArgMem () != ModRefInfo::ModRef &&
2867
+ memoryEffects.getArgMem () != ModRefInfo::Mod;
2868
+ if (isReadOnly)
2869
+ return argument;
2870
+ // Resolve the pointee type and its size.
2871
+ auto ptrType = cast<LLVM::LLVMPointerType>(argument.getType ());
2872
+ Type elementType = cast<TypeAttr>(byValAttribute.getValue ()).getValue ();
2873
+ unsigned int typeSize =
2874
+ DataLayout (callable->getParentOfType <DataLayoutOpInterface>())
2875
+ .getTypeSize (elementType);
2876
+ // Allocate the new value on the stack.
2877
+ Value one = builder.create <LLVM::ConstantOp>(
2878
+ func.getLoc (), builder.getI64Type (), builder.getI64IntegerAttr (1 ));
2879
+ Value allocaOp =
2880
+ builder.create <LLVM::AllocaOp>(func.getLoc (), ptrType, elementType, one);
2881
+ // Copy the pointee to the newly allocated value.
2882
+ Value copySize = builder.create <LLVM::ConstantOp>(
2883
+ func.getLoc (), builder.getI64Type (), builder.getI64IntegerAttr (typeSize));
2884
+ Value isVolatile = builder.create <LLVM::ConstantOp>(
2885
+ func.getLoc (), builder.getI1Type (), builder.getBoolAttr (false ));
2886
+ builder.create <LLVM::MemcpyOp>(func.getLoc (), allocaOp, argument, copySize,
2887
+ isVolatile);
2888
+ return allocaOp;
2889
+ }
2890
+
2857
2891
namespace {
2858
2892
struct LLVMInlinerInterface : public DialectInlinerInterface {
2859
2893
using DialectInlinerInterface::DialectInlinerInterface;
@@ -2866,8 +2900,19 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
2866
2900
auto funcOp = dyn_cast<LLVM::LLVMFuncOp>(callable);
2867
2901
if (!callOp || !funcOp)
2868
2902
return false ;
2869
- // TODO: Handle argument and result attributes;
2870
- if (funcOp.getArgAttrs () || funcOp.getResAttrs ())
2903
+ if (auto attrs = funcOp.getArgAttrs ()) {
2904
+ for (Attribute attr : *attrs) {
2905
+ auto attrDict = cast<DictionaryAttr>(attr);
2906
+ for (NamedAttribute attr : attrDict) {
2907
+ if (attr.getName () == LLVMDialect::getByValAttrName ())
2908
+ continue ;
2909
+ // TODO: Handle all argument attributes;
2910
+ return false ;
2911
+ }
2912
+ }
2913
+ }
2914
+ // TODO: Handle result attributes;
2915
+ if (funcOp.getResAttrs ())
2871
2916
return false ;
2872
2917
// TODO: Handle exceptions.
2873
2918
if (funcOp.getPersonality ())
@@ -2942,6 +2987,14 @@ struct LLVMInlinerInterface : public DialectInlinerInterface {
2942
2987
dst.replaceAllUsesWith (src);
2943
2988
}
2944
2989
2990
+ Value handleArgument (OpBuilder &builder, Operation *call, Operation *callable,
2991
+ Value argument, Type targetType,
2992
+ DictionaryAttr argumentAttrs) const final {
2993
+ if (auto attr = argumentAttrs.getNamed (LLVMDialect::getByValAttrName ()))
2994
+ return handleByValArgument (builder, callable, argument, *attr);
2995
+ return argument;
2996
+ }
2997
+
2945
2998
void processInlinedCallBlocks (
2946
2999
Operation *call,
2947
3000
iterator_range<Region::iterator> inlinedBlocks) const override {
0 commit comments