SSATmp* Simplifier::simplifyNot(SSATmp* src) { // const XORs are handled in simplifyXor() assert(!src->isConst()); assert(src->getType() == Type::Bool); IRInstruction* inst = src->getInstruction()->getSrc(0)->getInstruction(); Opcode op = inst->getOpcode(); // TODO: Add more algebraic simplification rules for NOT switch (op) { case OpXor: { // !!X --> bool(X) if (isNotInst(inst->getSrc(0))) { return m_tb->genConvToBool(inst->getSrc(0)); } break; } // !(X cmp Y) --> X opposite_cmp Y case OpLt: case OpLte: case OpGt: case OpGte: case OpEq: case OpNeq: case OpSame: case OpNSame: return m_tb->genCmp(negateQueryOp(op), inst->getSrc(0), inst->getSrc(1)); // TODO !(X | non_zero) --> 0 default: (void)op; } return NULL; }
SSATmp* Simplifier::simplifyNot(SSATmp* src) { IRInstruction* inst = src->getInstruction(); Opcode op = inst->getOpcode(); // TODO: Add more algebraic simplification rules for NOT switch (op) { case ConvToBool: return simplifyNot(inst->getSrc(0)); case OpXor: { // !!X --> bool(X) if (isNotInst(inst->getSrc(0))) { return m_tb->genConvToBool(inst->getSrc(0)); } break; } // !(X cmp Y) --> X opposite_cmp Y case OpLt: case OpLte: case OpGt: case OpGte: case OpEq: case OpNeq: case OpSame: case OpNSame: // XXX: this could technically be losing a ConvToBool, except // that we kinda know "not" instructions (Xor with 1) are always // going to be followed by ConvToBool. // // TODO(#2058865): This would make more sense with a real Not // instruction and allowing boolean output types for query ops. return m_tb->genCmp(negateQueryOp(op), inst->getSrc(0), inst->getSrc(1)); case InstanceOf: case NInstanceOf: case InstanceOfBitmask: case NInstanceOfBitmask: // TODO: combine this with the above check and use isQueryOp or // add an isNegatable. return m_tb->gen(negateQueryOp(op), inst->getNumSrcs(), inst->getSrcs().begin()); // TODO !(X | non_zero) --> 0 default: (void)op; } return nullptr; }