This is a follow up question from this one.
I am using llvm::CloneFunctionInto defined in llvm/Transforms/Utils/Cloning.h in order to create a new function after code generation with the right signature inferred from the type of the return values. This works nicely but it is slow
I am trying to optimize this a little bit by some way to move or transfer the function body from the old function to the new one, is there a utility for that?
I am trying to hack a way to do the transfer by looking at the code in CloneFunctionInto, but wanted to see if an existing function exists
Shamelessly stolen from the Arg Promotion pass (search for splice):
// Since we have now created the new function, splice the body of the old
// function right into the new function, leaving the old rotting hulk of the
// function empty.
NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList());
Where NF is the new function you're cloning into and F is the old function that you have just cloned.
Related
What I want to achieve:
A Blueprint Callable function that takes UPARAM(ref) bool& as a parameter which can but doesn't have to be passed inside of Blueprint Graph (variable doesn't have to be plugged into input pin to this node for the graph to compile). And by *asing on if the parameter has been passed or not, the function will behave in a slightly different way.
For example, I was able to create something like this in C++ (pastebin imgur):
void Func(bool& param = *(bool*)0)
{
if (¶m == nullptr)
// do something
}
Above code compiles and consistently behaves in VS2022, allows to call Func() without passing any parameters in it and execute code basing on if the parameter has been passed which is the exact behavior that I'm looking for.
However, this code is a C++ undefined behaviour not allowed for UFUNCTIONs. So, when I try to declare something similar as BlueprintCallable UFUNCTION in Unreal, this of course will not compile:
UFUNCTION(BlueprintCallable)
static void Func(UPARAM(ref) bool& param = *(bool*)nullptr);
due to error:
C++ Default parameter not parsed: param "(bool)nullptr"
So my question is:
Is the "behaviour/functionality" that I want to achieve even possible in BlueprintCallable functions?
Is there any workaround to what I've described above? For example in form of macros, custom data containers or function specifiers?
I think summary of my question might be a little bit misleading. I just want to recreate this type of code/behaviour pastebin imgur in Unreal's 'UFUNCTION(BlueprintCallable)'. Yes, I understand that given example is an UB, but this is the closest result to what I want to create. This is just an example.
This question is Unreal Engine / UFUNCTION related. This is not a typical C++ issue. Unreal uses macros for UFUNCTION declaration and compiles in a different way than regular C++ (UFunctions). Because of that pointer cannot be used as parameter in this case as Unreal does not allow it. However pointer would be an actual solution to this question if it were only about pure C++.
Possible but not exact solutions:
meta = AutoCreateRefTerm( "param" ) can be specified in the UFUNCTION declaration. This allows Blueprint Node to have default value in pass-by-ref pin. However, with this approach another condition (bool pin) is needed because it is not possible check if actual variable gets passed or not.
In comments TOptional has been mentioned. This data container is actually something that exactly fits here, but TOptional cannot be used as parameter in BlueprintCallable UFUNCTION due to "Error: Unrecognized type 'TOptional' - type must be a UCLASS, USTRUCT, UENUM, or global delegate.", or at least I don't know how to use it.
My question has been closed as a dupe of Is null reference possible? which isn't true. My question asks for high level functionality in Unreal's Blueprints/UFUNCTIONS that would omit the need of "null reference". Something like TOptional::IsSet
I'm trying to find a way to optimize away empty global constructors. Previous optimizations will turn constructors into functions that do nothing. I need to add a new pass to remove these functions from llvm.global_ctors.
First, I tried optimizeGlobalCtorsList but this function doesn't actually call the callback I give it even though llvm.global_ctors is populated.
Then I tried running GlobalOptPass. I tried this:
llvm::GlobalOptPass pass;
llvm::ModuleAnalysisManager MAM{true};
pass.run(module, MAM);
This ends up dereferencing a null pointer in AnalysisManager::lookupPass. I think I need to perform some sort of initialization or registration but I don't know how to do that. All the references on "llvm pass registration" talk about registering the pass with opt. I don't want to do that. I just want to run the pass.
Look in lib/Transforms/IPO/PassManagerBuilder.cpp (or lib/Passes/PassBuilder.cpp for the new pass manager) to see how opt sets up its pass pipeline. The code for opt is in tools/opt/opt.cpp and is very small, delegating almost all of its work to the core libraries.
You could use opt as a template for your own tool, or you could hack on the pass building pipline to insert your pass where you want it.
I'm looking to make a general, lazy evaluation-esque procedure to streamline my code.
Right now, I have the ability to speed up the execution of mathematical functions - provided that I pre-process it by calling another method first. More concretely, given a function of the type:
const Eigen::MatrixXd<double, -1, -1> function_name(const Eigen::MatrixXd<double, -1, -1>& input)
I can pass this into another function, g, which will produce a new version of function_name g_p, which can be executed faster.
I would like to abstract all this busy-work away from the end-user. Ideally, I'd like to make a class such that when any function f matching function_name's method signature is called on any input (say, x), the following happens instead:
The class checks if f has been called before.
If it hasn't, it calls g(f), followed by g_p(x).
If it has, it just calls g_p(x)
This is tricky for two reasons. The first, is I don't know how to get a reference to the current method, or if that's even possible, and pass it to g. There might be a way around this, but passing one function to the other would be simplest/cleanest for me.
The second bigger issue is how to force the calls to g. I have read about the execute around pattern, which almost works for this purpose - except that, unless I'm understanding it wrong, it would be impossible to reference f in the surrounding function calls.
Is there any way to cleanly implement my dream class? I ideally want to eventually generalize beyond the type of function_name (perhaps with templates), but can take this one step at a time. I am also open to other solution to get the same functionality.
I don't think a "perfect" solution is possible in C++, for the following reasons.
If the calling site says:
result = object->f(x);
as compiled this will call into the unoptimized version. At this point you're pretty much hamstrung, since there's no way in C++ to change where a function call goes, that's determined at compile-time for static linkage, and at runtime via vtable lookup for virtual (dynamic) linkage. Whatever the case, it's not something you can directly alter. Other languages do allow this, e.g. Lua, and rather ironically C++'s great-grandfather BCPL also permits it. However C++ doesn't.
TL;DR to get a workable solution to this, you need to modify either the called function, or every calling site that uses one of these.
Long answer: you'll need to do one of two things. You can either offload the problem to the called class and make all functions look something like this:
const <return_type> myclass:f(x)
{
static auto unoptimized = [](x) -> <return_type>
{
// Do the optimizable heavy lifting here;
return whatever;
};
static auto optimized = g(unoptimized);
return optimized(x);
}
However I very strongly suspect this is exactly what you don't want to do, because assuming the end-user you're talking about is the author of the class, this fails your requirement to offload this from the end-user.
However, you can also solve it by using a template, but that requires modification to every place you call one of these. In essence you encapsulate the above logic in a template function, replacing unoptimized with the bare class member, and leaving most everything else alone. Then you just call the template function at the calling site, and it should work.
This does have the advantage of a relatively small change at the calling site:
result = object->f(x);
becomes either:
result = optimize(object->f, x);
or:
result = optimize(object->f)(x);
depending on how you set the optimize template up. It also has the advantage of no changes at all to the class.
So I guess it comes down to where you wan't to make the changes.
Yet another choice. Would it be an option to take the class as authored by the end user, and pass the cpp and h files through a custom pre-processor? That could go through the class and automatically make the changes outlined above, which then yields the advantage of no change needed at the calling site.
Im using SFML and its Vector2f as well as a normal c++ vector.
Im using a class called projectiles, within is a default constructor and
///////////////////////////////////
// Construct with position and velocities
//////////////////////////////////
projectile::projectile(const sf::Vector2f itsPosition, const sf::Vector2f itsVel):
position(itsPosition),
vel(itsVel)
{}
the call comes from main in the form of
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
projectiles.push_back(sf::Vector2f(rectPos), sf::Vector2f(10,10));
}
leading to the error
no matching function for call to 'std::vector<projectile>::push_back(sf::Vector2<float>, sf::Vector2<float>)'|
do I need to let it initialize with the default constructor then edit after or is there something simple I'm missing here
Your issue is that you are passing two arguments to the push_back method, which is defined as only taking one argument. There is literally no definition for that function with more than one argument, so the compiler complains that you are looking for a method that doesn't exist. Source: (http://www.cplusplus.com/reference/vector/vector/push_back/)
What you actually need to do, is construct a new projectile, and then pass it back.
As immibis stated in his comment on your question, there is another method that might do what you want, emplace_back(). You may want to try changing the method to that instead. I've never used that method, so I can't say much beyond that. Source: (http://www.cplusplus.com/reference/vector/vector/emplace_back/)
I'm trying to implement the following functionality;
a function with no explicit return will by default return the last evaluation in the last executed block
So, currently the process i'm doing is
1) create a Function
llvm::Function* result = llvm::Function::Create(Compiler::Detail::getAnonymousFunctionSignature(llvmContext),
llvm::GlobalValue::ExternalLinkage,
name,
module());
result->setCallingConv( llvm::CallingConv::C );
2) add blocks and evaluations to the blocks
builder.createFoo.....
However, only in the second phase i have the llvm::Value* (and compile-time type) that i want to use by default as return value. The problem is that i need to use this type to determine the signature of the created function
Question:
how do i solve the problem?
is possible to change the signature after the function is created? is it legal?
do i need to create a new function with the updated signature and copy/assign the entry block of the first function to it and thats it? or do i need to reevaluate all the expressions?
is possible to not create the function before code generation? if it is so, at what point should i create the function?
a code example of how to achieve this would be awesome. thanks!
You cannot change function signature, because this will mean that it will have different Type (and thus you will need to update all the users, etc.; this procedure in most cases cannot be done automagically).
There are multiple possible solutions, for example, you can create the function with the updated signature, then use the functions from lib/Transforms/Utils/CloneFunction.cpp to copy the function body and then hack on the return type.
A better solution exists than CloneFunctionInto(), according to https://stackoverflow.com/a/18751365/2024042:
NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList());
Where NF is the new function you're cloning into and F is the old function that you have just cloned.