ConstProp: Add RemoveUselessMasking, implement for a few ops

This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis committed 2020-12-12 12:10:14 +02:00
1 parent 00a2560905
commit b2eeb104f7
1 file changed
+88
@@ -24,6 +24,13 @@ static uint64_t getMask(T Op) {
return (~0ULL) >> (64 - NumBits);
}
template<>
static uint64_t getMask(IROp_Header* Op) {
uint64_t NumBits = Op->Size * 8;
return (~0ULL) >> (64 - NumBits);
}
#ifdef _M_X86_64
// very lazy heuristics
static bool IsImmLogical(uint64_t imm, unsigned width) { return imm < 0x8000'0000; }
@@ -107,6 +114,29 @@ std::tuple<MemOffsetType, uint8_t, OrderedNode*, OrderedNode*> MemExtendedAddres
return { MEM_OFFSET_SXTX, 1, IREmit->UnwrapNode(AddressHeader->Args[0]), IREmit->UnwrapNode(AddressHeader->Args[1]) };
}
OrderedNodeWrapper RemoveUselessMasking(IREmitter *IREmit, OrderedNodeWrapper src, uint64_t mask) {
auto IROp = IREmit->GetOpHeader(src);
if (IROp->Op == OP_AND) {
auto Op = IROp->C<IR::IROp_And>();
uint64_t imm;
if (IREmit->IsValueConstant(IROp->Args[1], &imm) && ((imm & mask) == mask)) {
return RemoveUselessMasking(IREmit, IROp->Args[0], mask);
}
} else if (IROp->Op == OP_BFE) {
auto Op = IROp->C<IR::IROp_Bfe>();
if (Op->lsb == 0) {
uint64_t imm = 1ULL << (Op->Width-1);
imm = (imm-1) *2 + 1;
if ((imm & mask) == mask) {
return RemoveUselessMasking(IREmit, IROp->Args[0], mask);
}
}
}
return src;
}
bool ConstProp::Run(IREmitter *IREmit) {
bool Changed = false;
@@ -227,6 +257,28 @@ bool ConstProp::Run(IREmitter *IREmit) {
for (auto [CodeNode, IROp] : CurrentIR.GetAllCode()) {
switch (IROp->Op) {
case OP_AND:
case OP_OR:
case OP_XOR:
case OP_NOT:
case OP_ADD:
case OP_SUB:
case OP_LSHR:
case OP_ASHR:
case OP_LSHL:
case OP_BFE: {
for (int i = 0; i < IROp->NumArgs; i++) {
auto newArg = RemoveUselessMasking(IREmit, IROp->Args[i], getMask(IROp));
if (newArg != IROp->Args[i]) {
IREmit->ReplaceNodeArgument(CodeNode, i, IREmit->UnwrapNode(newArg));
Changed = true;
}
}
break;
}
}
switch (IROp->Op) {
/*
case OP_UMUL:
case OP_DIV:
@@ -427,6 +479,42 @@ bool ConstProp::Run(IREmitter *IREmit) {
IREmit->ReplaceAllUsesWith(CodeNode, Arg);
Changed = true;
continue;
} else {
auto newArg = RemoveUselessMasking(IREmit, Op->Header.Args[1], IROp->Size * 8 - 1);
if (newArg != Op->Header.Args[1]) {
IREmit->ReplaceNodeArgument(CodeNode, 1, IREmit->UnwrapNode(newArg));
Changed = true;
continue;
}
}
break;
}
case OP_LSHR: {
auto Op = IROp->CW<IR::IROp_Lshr>();
uint64_t Constant1;
uint64_t Constant2;
if (IREmit->IsValueConstant(Op->Header.Args[0], &Constant1) &&
IREmit->IsValueConstant(Op->Header.Args[1], &Constant2)) {
uint64_t NewConstant = (Constant1 >> Constant2) & getMask(Op);
IREmit->ReplaceWithConstant(CodeNode, NewConstant);
Changed = true;
continue;
}
else if (IREmit->IsValueConstant(Op->Header.Args[1], &Constant2) &&
Constant2 == 0) {
IREmit->SetWriteCursor(CodeNode);
OrderedNode *Arg = CurrentIR.GetNode(Op->Header.Args[0]);
IREmit->ReplaceAllUsesWith(CodeNode, Arg);
Changed = true;
continue;
} else {
auto newArg = RemoveUselessMasking(IREmit, Op->Header.Args[1], IROp->Size * 8 - 1);
if (newArg != Op->Header.Args[1]) {
IREmit->ReplaceNodeArgument(CodeNode, 1, IREmit->UnwrapNode(newArg));
Changed = true;
continue;
}
}
break;
}