static BytecodeExpression notEqual(BytecodeExpression left, BytecodeExpression right)
    {
        requireNonNull(left, "left is null");
        requireNonNull(right, "right is null");
        checkArgument(left.getType().equals(right.getType()), "left and right must be the same type");

        OpCode comparisonInstruction;
        OpCode noMatchJumpInstruction;

        Class<?> type = left.getType().getPrimitiveType();
        if (type == int.class) {
            comparisonInstruction = null;
            noMatchJumpInstruction = IF_ICMPEQ;
        }
        else if (type == long.class) {
            comparisonInstruction = LCMP;
            noMatchJumpInstruction = IFEQ;
        }
        else if (type == float.class) {
            comparisonInstruction = FCMPL;
            noMatchJumpInstruction = IFEQ;
        }
        else if (type == double.class) {
            comparisonInstruction = DCMPL;
            noMatchJumpInstruction = IFEQ;
        }
        else if (type == null) {
            comparisonInstruction = null;
            noMatchJumpInstruction = IF_ACMPEQ;
        }
        else {
            throw new IllegalArgumentException("Not equal than does not support " + type);
        }
        return new ComparisonBytecodeExpression("!=", comparisonInstruction, noMatchJumpInstruction, left, right);
    }
@SuppressWarnings({"FloatingPointEquality", "ComparisonToNaN", "EqualsNaN", "EqualsWithItself"})
    @Test
    public void testNotEqual()
            throws Exception
    {
        assertBytecodeExpression(notEqual(constantInt(7), constantInt(3)), 7 != 3, "(7 != 3)");
        assertBytecodeExpression(notEqual(constantInt(7), constantInt(7)), 7 != 7, "(7 != 7)");

        assertBytecodeExpression(notEqual(constantLong(7L), constantLong(3L)), 7L != 3L, "(7L != 3L)");
        assertBytecodeExpression(notEqual(constantLong(7L), constantLong(7L)), 7L != 7L, "(7L != 7L)");

        assertBytecodeExpression(notEqual(constantFloat(7.7f), constantFloat(3.3f)), 7.7f != 3.3f, "(7.7f != 3.3f)");
        assertBytecodeExpression(notEqual(constantFloat(7.7f), constantFloat(7.7f)), 7.7f != 7.7f, "(7.7f != 7.7f)");
        assertBytecodeExpression(notEqual(constantFloat(Float.NaN), constantFloat(7.7f)), Float.NaN != 7.7f, "(NaNf != 7.7f)");
        assertBytecodeExpression(notEqual(constantFloat(Float.NaN), constantFloat(Float.NaN)), Float.NaN != Float.NaN, "(NaNf != NaNf)");

        assertBytecodeExpression(notEqual(constantDouble(7.7), constantDouble(3.3)), 7.7 != 3.3, "(7.7 != 3.3)");
        assertBytecodeExpression(notEqual(constantDouble(7.7), constantDouble(7.7)), 7.7 != 7.7, "(7.7 != 7.7)");
        assertBytecodeExpression(notEqual(constantDouble(Double.NaN), constantDouble(7.7)), Double.NaN != 7.7, "(NaN != 7.7)");
        assertBytecodeExpression(notEqual(constantDouble(7.7), constantDouble(Double.NaN)), 7.7 != Double.NaN, "(7.7 != NaN)");
        assertBytecodeExpression(notEqual(constantDouble(Double.NaN), constantDouble(Double.NaN)), Double.NaN != Double.NaN, "(NaN != NaN)");

        // the byte code is verifying with != but that breaks check style so we use
        assertBytecodeExpression(notEqual(constantString("foo"), constantString("bar")), !"foo".equals("bar"), "(\"foo\" != \"bar\")");
        assertBytecodeExpression(notEqual(constantString("foo"), constantString("foo")), !"foo".equals("foo"), "(\"foo\" != \"foo\")");
    }