Skip to content

Commit 64c42a8

Browse files
committed
Handle optimization case w.r.t. load on GEP
1 parent 6686b87 commit 64c42a8

File tree

4 files changed

+26
-4
lines changed

4 files changed

+26
-4
lines changed

lib/type/DITypeExtractor.cpp

+20-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ bool load_to(const llvm::LoadInst* load) {
8383
return detail::get_operand_to<T>(load).has_value();
8484
}
8585

86-
std::optional<llvm::DIType*> reset_load_related_basic(const dataflow::ValuePath&, llvm::DIType* type_to_reset,
86+
std::optional<llvm::DIType*> reset_load_related_basic(const dataflow::ValuePath& path, llvm::DIType* type_to_reset,
8787
const llvm::LoadInst* load) {
8888
auto* type = type_to_reset;
8989

@@ -101,6 +101,25 @@ std::optional<llvm::DIType*> reset_load_related_basic(const dataflow::ValuePath&
101101
return type;
102102
}
103103

104+
// a (last?) load to a GEP of a composite likely loads the first member in an optimized context:
105+
const bool last_load = path.start_value().value_or(nullptr) == load;
106+
if (last_load && load_to<llvm::GetElementPtrInst>(load)) {
107+
if (auto* may_be_member_type = llvm::dyn_cast<llvm::DIDerivedType>(type)) {
108+
LOG_DEBUG("Load on GEP, return basetype " << log::ditype_str(may_be_member_type->getBaseType()))
109+
if (di::util::is_member(*may_be_member_type)) {
110+
auto type_of_member = may_be_member_type->getBaseType();
111+
if (auto member = llvm::dyn_cast<llvm::DIDerivedType>(type_of_member)) {
112+
may_be_member_type = member;
113+
if (auto* member_composite_type = llvm::dyn_cast<llvm::DICompositeType>(member->getBaseType())) {
114+
auto members_of_composite_type = di::util::get_composite_members(*member_composite_type);
115+
assert(members_of_composite_type.size() > 0 && "Load to composite expects at least one member");
116+
return (*members_of_composite_type.begin());
117+
}
118+
}
119+
}
120+
}
121+
}
122+
104123
if (auto* maybe_ptr_to_type = llvm::dyn_cast<llvm::DIDerivedType>(type)) {
105124
if (di::util::is_pointer(*maybe_ptr_to_type)) {
106125
LOG_DEBUG("Load of pointer-like " << log::ditype_str(maybe_ptr_to_type))

lib/type/Dimeta.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ std::optional<QualifiedType> type_for(const llvm::Value* value) {
253253

254254
return {};
255255
}
256+
256257
} // namespace experimental
257258

258259
} // namespace dimeta

lib/type/Dimeta.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ class Module;
2727

2828
namespace dimeta {
2929

30-
using DimetaDIVar = std::variant<llvm::DILocalVariable*, llvm::DIGlobalVariable*>;
30+
using DimetaDIVariable = std::variant<llvm::DILocalVariable*, llvm::DIGlobalVariable*>;
3131

3232
struct DimetaData {
3333
enum MemLoc { kStack = 0, kHeap, kGlobal };
3434
MemLoc memory_location{kStack};
35-
std::optional<DimetaDIVar> di_variable{}; // if existing the named variable w.r.t. allocation
35+
std::optional<DimetaDIVariable> di_variable{}; // if existing the named variable w.r.t. allocation
3636
std::optional<llvm::DIType*> entry_type{}; // determined to be the allocation including "pointer" DITypes
3737
std::optional<llvm::DIType*> base_type{}; // The base type (int, struct X...) of the allocated memory
3838
std::optional<llvm::DILocation*> di_location{}; // Loc of call (malloc etc.)/alloca. Not set for global
@@ -59,7 +59,8 @@ std::optional<CompileUnitTypeList> compile_unit_types(const llvm::Module*);
5959

6060
namespace experimental {
6161
std::optional<QualifiedType> type_for(const llvm::Value*);
62-
}
62+
63+
} // namespace experimental
6364

6465
} // namespace dimeta
6566

test/pass/gep/array.c

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %c-to-llvm %s | %apply-verifier 2>&1 | %filecheck %s
2+
// RUN: %c-to-llvm %s | %opt -O2 | %apply-verifier 2>&1 | %filecheck %s
23

34
#include <stdlib.h>
45

0 commit comments

Comments
 (0)