anchor.diff:            identical(element, compiler.dynamicClass)) {
           // The constant folder also does this optimization, but we make
           // it safe by assuming it may have not run.
  -        push(newLiteralBool(true), node);
  +        push(newLiteralBool(!negative), node);
         } else if (element == compiler.stringClass) {
  -        checkString(input, '===');
  +        checkString(input, relation);
           attachLocationToLast(node);
         } else if (element == compiler.doubleClass) {
  -        checkDouble(input, '===');
  +        checkDouble(input, relation);
           attachLocationToLast(node);
         } else if (element == compiler.numClass) {
  -        checkNum(input, '===');
  +        checkNum(input, relation);
           attachLocationToLast(node);
         } else if (element == compiler.boolClass) {
  -        checkBool(input, '===');
  +        checkBool(input, relation);
           attachLocationToLast(node);
         } else if (element == compiler.functionClass) {
  -        checkFunction(input, type);
  +        checkFunction(input, type, negative: negative);
           attachLocationToLast(node);
         } else if (element == compiler.intClass) {
           // The is check in the code tells us that it might not be an
           // int. So we do a typeof first to avoid possible
           // deoptimizations on the JS engine due to the Math.floor check.
  -        checkNum(input, '===');
  +        checkNum(input, relation);
           js.Expression numTest = pop();
  -        checkBigInt(input, '===');
  -        push(new js.Binary('&&', numTest, pop()), node);
  +        checkBigInt(input, relation);
  +        push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node);
         } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
  -        handleNumberOrStringSupertypeCheck(input, type);
  +        handleNumberOrStringSupertypeCheck(input, type, negative: negative);
           attachLocationToLast(node);
         } else if (Elements.isStringOnlySupertype(element, compiler)) {
  -        handleStringSupertypeCheck(input, type);
  +        handleStringSupertypeCheck(input, type, negative: negative);
           attachLocationToLast(node);
         } else if (identical(element, compiler.listClass)
                    || Elements.isListSupertype(element, compiler)) {
  -        handleListOrSupertypeCheck(input, type);
  +        handleListOrSupertypeCheck(input, type, negative: negative);
           attachLocationToLast(node);
         } else if (element.isTypedef()) {
  -        checkNonNull(input);
  +        if (negative) {
  +          checkNull(input);
  +        } else {
  +          checkNonNull(input);
  +        }
           js.Expression nullTest = pop();
  -        checkType(input, type);
  -        push(new js.Binary('&&', nullTest, pop()));
  +        checkType(input, type, negative: negative);
  +        push(new js.Binary(negative ? '||' : '&&', nullTest, pop()));
           attachLocationToLast(node);
         } else if (input.canBePrimitive(compiler) || input.canBeNull()) {
  -        checkObject(input, '===');
  +        checkObject(input, relation);
           js.Expression objectTest = pop();
  -        checkType(input, type);
  -        push(new js.Binary('&&', objectTest, pop()), node);
  +        checkType(input, type, negative: negative);
  +        push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node);
         } else {
  -        checkType(input, type);
  +        checkType(input, type, negative: negative);
           attachLocationToLast(node);
         }
       }
       if (node.nullOk) {
  -      checkNull(input);
  -      push(new js.Binary('||', pop(), pop()), node);
  +      if (negative) {
  +        checkNonNull(input);
  +        push(new js.Binary('&&', pop(), pop()), node);
  +      } else {
  +        checkNull(input);
  +        push(new js.Binary('||', pop(), pop()), node);
  +      }
       }
     }
   
  
positive.code: 
    }
  
    void handleNumberOrStringSupertypeCheck(HInstruction input, DartType type) {
      assert(!identical(type.element, compiler.listClass)
             && !Elements.isListSupertype(type.element, compiler)
             && !Elements.isStringOnlySupertype(type.element, compiler));
      checkNum(input, '===');
      js.Expression numberTest = pop();
      checkString(input, '===');
      js.Expression stringTest = pop();
      checkObject(input, '===');
      js.Expression objectTest = pop();
      checkType(input, type);
      push(new js.Binary('||',
                         new js.Binary('||', numberTest, stringTest),
                         new js.Binary('&&', objectTest, pop())));
    }
  
    void handleStringSupertypeCheck(HInstruction input, DartType type) {
      assert(!identical(type.element, compiler.listClass)
             && !Elements.isListSupertype(type.element, compiler)
             && !Elements.isNumberOrStringSupertype(type.element, compiler));
      checkString(input, '===');
      js.Expression stringTest = pop();
      checkObject(input, '===');
      js.Expression objectTest = pop();
      checkType(input, type);
      push(new js.Binary('||',
                         stringTest,
                         new js.Binary('&&', objectTest, pop())));
    }
  
    void handleListOrSupertypeCheck(HInstruction input, DartType type) {
      assert(!identical(type.element, compiler.stringClass)
             && !Elements.isStringOnlySupertype(type.element, compiler)
             && !Elements.isNumberOrStringSupertype(type.element, compiler));
      checkObject(input, '===');
      js.Expression objectTest = pop();
      checkArray(input, '===');
      js.Expression arrayTest = pop();
      checkType(input, type);
      push(new js.Binary('&&',
                         objectTest,
                         new js.Binary('||', arrayTest, pop())));
    }
  
    void visitIs(HIs node) {
      DartType type = node.typeExpression;
      world.registerIsCheck(type, work.resolutionTree);
      HInstruction input = node.expression;
  
      if (node.isVariableCheck || node.isCompoundCheck) {
        use(node.checkCall);
      } else {
        assert(node.isRawCheck);
        LibraryElement coreLibrary = compiler.coreLibrary;
  
negative.code:   void generateNot(HInstruction input) {
      bool canGenerateOptimizedComparison(HInstruction instruction) {
        if (instruction is !HRelational) return false;
  
        HRelational relational = instruction;
        BinaryOperation operation = relational.operation(backend.constantSystem);
  
        HInstruction left = relational.left;
        HInstruction right = relational.right;
        if (left.instructionType.isUseful() && left.isString() &&
            right.instructionType.isUseful() && right.isString()) {
          return true;
        }
  
        // This optimization doesn't work for NaN, so we only do it if the
        // type is known to be an integer.
        return left.instructionType.isUseful() && left.isInteger()
  