Example #1
0
TEST(Simplifier, LdObjInvoke) {
  IRUnit unit{test_context};
  Simplifier sim{unit};
  auto const dummy = BCMarker::Dummy();
  auto const taken = unit.defBlock();

  // LdObjInvoke t1:Cls doesn't simplify
  {
    auto type = Type::Cls;
    auto cls = unit.gen(Conjure, dummy, type);
    auto load = unit.gen(LdObjInvoke, dummy, taken, cls->dst());
    auto result = sim.simplify(load, false);
    EXPECT_NO_CHANGE(result);
  }

  // LdObjInvoke t1:Cls(C), where C is persistent but has no __invoke
  // doesn't simplify.
  {
    auto type = Type::cns(SystemLib::s_IteratorClass);
    auto cls = unit.gen(Conjure, dummy, type);
    auto load = unit.gen(LdObjInvoke, dummy, taken, cls->dst());
    auto result = sim.simplify(load, false);
    EXPECT_NO_CHANGE(result);
  }
}
Example #2
0
TEST(Simplifier, LdObjClass) {
  IRUnit unit{test_context};
  Simplifier sim{unit};
  auto const dummy = BCMarker::Dummy();
  auto const cls = SystemLib::s_IteratorClass;

  // LdObjClass t1:Obj<=C doesn't simplify
  {
    auto sub = Type::Obj.specialize(cls);
    auto obj = unit.gen(Conjure, dummy, sub);
    auto load = unit.gen(LdObjClass, dummy, obj->dst());
    auto result = sim.simplify(load, false);
    EXPECT_NO_CHANGE(result);
  }

  // LdObjClass t1:Obj=C --> Cls(C)
  {
    auto exact = Type::Obj.specializeExact(cls);
    auto obj = unit.gen(Conjure, dummy, exact);
    auto load = unit.gen(LdObjClass, dummy, obj->dst());
    auto result = sim.simplify(load, false);
    EXPECT_EQ(result.dst->clsVal(), cls);
    EXPECT_EQ(result.instrs.size(), 0);
  }
}
Example #3
0
TEST(Simplifier, Count) {
  IRUnit unit{test_context};
  Simplifier sim{unit};
  BCMarker dummy = BCMarker::Dummy();

  // Count($null) --> 0
  {
    auto null = unit.gen(Conjure, dummy, Type::Null);
    auto count = unit.gen(Count, dummy, null->dst());
    auto result = sim.simplify(count, false);

    EXPECT_NE(nullptr, result.dst);
    EXPECT_EQ(0, result.instrs.size());
    EXPECT_EQ(0, result.dst->intVal());
  }

  // Count($bool_int_dbl_str) --> 1
  {
    auto ty = Type::Bool | Type::Int | Type::Dbl | Type::Str | Type::Res;
    auto val = unit.gen(Conjure, dummy, ty);
    auto count = unit.gen(Count, dummy, val->dst());
    auto result = sim.simplify(count, false);

    EXPECT_NE(nullptr, result.dst);
    EXPECT_EQ(0, result.instrs.size());
    EXPECT_EQ(1, result.dst->intVal());
  }

  // Count($array_no_kind) --> CountArray($array_no_kind)
  {
    auto arr = unit.gen(Conjure, dummy, Type::Arr);
    auto count = unit.gen(Count, dummy, arr->dst());
    auto result = sim.simplify(count, false);

    EXPECT_NE(nullptr, result.dst);
    EXPECT_EQ(1, result.instrs.size());
    EXPECT_MATCH(result.instrs[0], CountArray, arr->dst());
  }

  // Count($array_not_nvtw) --> CountArrayFast($array_not_nvtw)
  {
    auto ty = Type::Arr.specialize(ArrayData::kPackedKind);
    auto arr = unit.gen(Conjure, dummy, ty);
    auto count = unit.gen(Count, dummy, arr->dst());
    auto result = sim.simplify(count, false);

    EXPECT_NE(nullptr, result.dst);
    EXPECT_EQ(1, result.instrs.size());
    EXPECT_MATCH(result.instrs[0], CountArrayFast, arr->dst());
  }

  // Count($some_obj) --> Count($some_obj)
  {
    auto obj = unit.gen(Conjure, dummy, Type::Obj);
    auto count = unit.gen(Count, dummy, obj->dst());
    auto result = sim.simplify(count, false);
    EXPECT_NO_CHANGE(result);
  }

}
Example #4
0
TEST(Simplifier, JumpConstFold) {
  BCMarker dummy = BCMarker::Dummy();
  IRUnit unit(0);
  Simplifier sim(unit);

  OptionSetter<bool> r(RuntimeOption::EvalHHIRBytecodeControlFlow, false);

  // Folding JmpZero and JmpNZero.
  {
    auto tester = [&] (SSATmp* val, Opcode op) {
      auto jmp = unit.gen(op, dummy, unit.defBlock(), val);
      return sim.simplify(jmp, false);
    };

    auto resultFalseZero  = tester(unit.cns(false),  JmpZero);
    auto resultFalseNZero = tester(unit.cns(false), JmpNZero);
    auto resultTrueZero   = tester(unit.cns(true),   JmpZero);
    auto resultTrueNZero  = tester(unit.cns(true),  JmpNZero);

    EXPECT_SINGLE_OP(resultFalseNZero, Nop);
    EXPECT_SINGLE_OP(resultTrueZero, Nop);

    EXPECT_SINGLE_OP(resultFalseZero, Jmp);
    EXPECT_SINGLE_OP(resultTrueNZero, Jmp);
  }

  // Don't do this if bytecode control flow is on.
  {
    OptionSetter<bool> r(RuntimeOption::EvalHHIRBytecodeControlFlow, true);

    auto jmp = unit.gen(JmpNZero, dummy, unit.defBlock(), unit.cns(false));
    auto result = sim.simplify(jmp, false);
    EXPECT_NO_CHANGE(result);
    ASSERT_TRUE(RuntimeOption::EvalHHIRBytecodeControlFlow);
  }
  ASSERT_FALSE(RuntimeOption::EvalHHIRBytecodeControlFlow);

  // Folding query jumps.
  {
    auto jmpeqTaken = unit.gen(JmpEq, dummy, unit.cns(10), unit.cns(10));
    auto result = sim.simplify(jmpeqTaken, false);
    EXPECT_SINGLE_OP(result, Jmp);

    auto jmpeqNTaken = unit.gen(JmpEq, dummy, unit.cns(10), unit.cns(400));
    result = sim.simplify(jmpeqNTaken, false);
    EXPECT_SINGLE_OP(result, Nop);
  }
}