IR中的
%.sroa.3.0.copyload = load volatile i16, i16* bitcast (i8* getelementptr inbounds (i8, i8* bitcast (%struct.str* @global to i8*), i64 14) to i16*), align 2
store volatile i16 %.sroa.3.0.copyload, i16* %.sroa.3, align 2
struct形式为
struct str3 {
int x3[2];
char y3[2];
};
struct str2 {
struct str3 p3;
short x2;
};
struct str1 {
struct str2 p2;
char x1;
};
struct str {
struct str1 p1;
int x;
};
内存排布
0 0 0 0 0
Type list: i32
0 0 0 0 1
Type list: i32
0 0 0 1 0
Type list: i8
0 0 0 1 1
Type list: i8
0 0 1
Type list: i16
0 1
Type list: i8
1
Type list: i32
32 64 72 80 112 136 192
14*8 = 112后面是无用的内存空间,getelementptr无效
删除load指令,并将load的所有use全部替换为Value 0!
void RemoveStruct::BitCastGetelementPtr(Instruction* &instr) {
SmallVector<Instruction*,128> *WorkListDel = new SmallVector<Instruction* ,128>();
Instruction* getelement_inst = instr->getNextNode();
assert(getelement_inst->getNumOperands() == 2);
int bit_width = getelement_inst->getOperand(0)->getType()->getPointerElementType()->getIntegerBitWidth();
Value* op_1 = getelement_inst->getOperand(1);
ConstantInt* width;
int byte_nums;
if (isa<llvm::ConstantInt>(op_1)) {
width = llvm::dyn_cast<llvm::ConstantInt>(op_1);
byte_nums = width->getSExtValue();
}
// byte_nums 就是14
Value* val = instr->getOperand(0);
Type* val_ty = val->getType()->getPointerElementType();
vector<int> val_list;
map<vector<int>, Type*> val_map;
int align = 0;
BitCastStruct(val_list, val_ty, val_map, align);
map<vector<int>, Type*>::iterator iter;
int bitcast_bitwidth = instr->getType()->getPointerElementType()->getIntegerBitWidth();
int actual_width = bitcast_bitwidth * byte_nums;
int val_width = 0;
int step_width = 1;
int use_width = 0;
bool flag = false;
vector<int> begin = val_map.begin()->first;
int begin_size = begin.size();
for (iter = val_map.begin(); iter != val_map.end(); iter++) {
vector<int> vec_temp = iter->first;
// 当vec_temp的size改变时,说明struct进行了嵌套,需要对其进行align补齐,其中补齐的bit
// bit数就是 (align - (use_width % align))
if (begin_size != vec_temp.size()) {
begin_size = vec_temp.size();
use_width = (align - (use_width % align)) + use_width;
}
val_width = iter->second->getIntegerBitWidth();
while (use_width % val_width != 0) {
use_width += step_width;
}
use_width += val_width;
outs() << " " << use_width;
if (use_width - val_width == actual_width) { flag = true; }
}
outs() <<"\n";
// flag标志是否getelementptr到错误内存
if (flag == false) {
for (Value::user_iterator UI = getelement_inst->user_begin(), E =getelement_inst->user_end(); UI != E; ++UI) {
User *U = *UI;
assert(isa<Instruction> (U));
Instruction* CI = dyn_cast<Instruction> (U);
if (CI->getOpcode() == llvm::Instruction::BitCast) {
WorkListDel->push_back(CI);
for (Value::user_iterator UI2 = CI->user_begin(), E2 =CI->user_end(); UI2 != E2; ++UI2) {
User *U2 = *UI2;
assert(isa<Instruction> (U2));
Instruction* CI_2 = dyn_cast<Instruction> (U2);
if (CI_2->getOpcode() == llvm::Instruction::Load) {
Value* zero = ConstantInt::get(CI_2->getType(), 0);
CI_2->replaceAllUsesWith(zero);
WorkListDel->push_back(CI_2);
} else if (CI_2->getOpcode() == llvm::Instruction::Store) {
WorkListDel->push_back(CI_2);
} else {
assert(0);
}
}
} else if (CI->getOpcode() == llvm::Instruction::Load) {
Value* zero = ConstantInt::get(CI->getType(), 0);
CI->replaceAllUsesWith(zero);
WorkListDel->push_back(CI);
} else if (CI->getOpcode() == llvm::Instruction::Store) {
WorkListDel->push_back(CI);
} else {
assert(0);
}
}
WorkListDel->push_back(instr);
WorkListDel->push_back(instr->getNextNode());
}
while (!WorkListDel->empty()) {
Instruction *instruction = WorkListDel->pop_back_val();
instruction->eraseFromParent();
}
}