llvm2alive: evaluate constexpr fncall arguments only once
they were being evaluated twice, duplicating the number of constexpr instructions
MODIFY
llvm_util/known_fns.cpp
llvm_util/known_fns.cpp
@@ -20,21 +20,11 @@ namespace llvm_util {
pair<unique_ptr<Instr>, bool>
known_call(llvm::CallInst &i, const llvm::TargetLibraryInfo &TLI,
- BasicBlock &BB,
- function<Value*(llvm::ConstantExpr *)> constexpr_conv,
- function<Value*(AggregateValue *)> copy_inserter) {
+ BasicBlock &BB, const vector<Value*> &args) {
auto ty = llvm_type2alive(i.getType());
if (!ty)
RETURN_FAIL_KNOWN();
- vector<Value*> args;
- for (auto &arg : i.args()) {
- auto a = get_operand(arg, constexpr_conv, copy_inserter);
- if (!a)
- RETURN_FAIL_KNOWN();
- args.emplace_back(a);
- }
-
// TODO: add support for checking mismatch of C vs C++ alloc fns
if (llvm::isMallocLikeFn(&i, &TLI, false)) {
bool isNonNull = i.getCalledFunction()->getName() != "malloc";

MODIFY
llvm_util/known_fns.h
llvm_util/known_fns.h
// Distributed under the MIT license that can be found in the LICENSE file.
#include "ir/function.h"
-#include <functional>
#include <memory>
#include <utility>
+#include <vector>
namespace llvm {
class CallInst;
-class ConstantExpr;
class TargetLibraryInfo;
}
namespace IR {
class BasicBlock;
class Instr;
+class Value;
}
namespace llvm_util {
@@ -24,8 +24,6 @@ namespace llvm_util {
// returned bool indicates whether it's a known function call
std::pair<std::unique_ptr<IR::Instr>, bool>
known_call(llvm::CallInst &i, const llvm::TargetLibraryInfo &TLI,
- IR::BasicBlock &BB,
- std::function<IR::Value*(llvm::ConstantExpr *)> constexpr_conv,
- std::function<IR::Value*(IR::AggregateValue *)> copy_inserter);
+ IR::BasicBlock &BB, const std::vector<IR::Value*> &args);
}

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
@@ -228,9 +228,15 @@ public:
}
RetTy visitCallInst(llvm::CallInst &i) {
- auto [call_val, known] = known_call(i, TLI, *BB,
- [this](auto I) { return convert_constexpr(I); },
- [this](auto ag) { return copy_inserter(ag); });
+ vector<Value *> args;
+ for (auto &arg : i.args()) {
+ auto a = get_operand(arg);
+ if (!a)
+ return error(i);
+ args.emplace_back(a);
+ }
+
+ auto [call_val, known] = known_call(i, TLI, *BB, args);
if (call_val)
RETURN_IDENTIFIER(move(call_val));
@@ -261,19 +267,15 @@ public:
auto call = make_unique<FnCall>(*ty, value_name(i), move(fn_name), flags,
!known);
auto argI = fn->arg_begin(), argE = fn->arg_end();
- for (auto &arg : i.args()) {
- auto a = get_operand(arg);
- if (!a)
- return error(i);
-
+ for (auto &arg : args) {
unsigned attr = FnCall::ArgNone;
if (argI != argE) {
// Check whether arg itr finished early because it was var arg
if (argI->hasByValAttr())
attr |= FnCall::ArgByVal;
- argI++;
+ ++argI;
}
- call->addArg(*a, attr);
+ call->addArg(*arg, attr);
}
RETURN_IDENTIFIER(move(call));
}

llvm2alive: evaluate constexpr fncall arguments only once
they were being evaluated twice, duplicating the number of constexpr instructions