def test_function_tailcall(self): """ Test if a tailcall in a function works out nicely """ # Prepare an optimizable module: builder = irutils.Builder() module = ir.Module('test') builder.set_module(module) function = builder.new_function('x', ir.Binding.GLOBAL, ir.i8) builder.set_function(function) entry = builder.new_block() function.entry = entry a = ir.Parameter('a', ir.i8) function.add_parameter(a) b = ir.Parameter('b', ir.i8) function.add_parameter(b) builder.set_block(entry) one = builder.emit(ir.Const(1, 'const', ir.i8)) a2 = builder.emit(ir.add(a, one, 'a2', ir.i8)) b2 = builder.emit(ir.add(b, one, 'b2', ir.i8)) result = builder.emit(ir.FunctionCall(function, [a2, b2], 'rv', ir.i8)) builder.emit(ir.Return(result)) # Verify first version: module.display() verify_module(module) self.assertFalse(function.is_leaf()) # Run optimizer: self.opt.run(module) # Verify again: module.display() verify_module(module) self.assertTrue(function.is_leaf())
def test_glue_with_phi(self): """ After replacing the predecessor, the use info of a phi is messed up. """ block1 = self.builder.new_block() block4 = self.builder.new_block() # This one must be eliminated block6 = self.builder.new_block() self.builder.emit(ir.Jump(block1)) self.builder.set_block(block1) cnst = self.builder.emit(ir.Const(0, 'const', ir.i16)) self.builder.emit(ir.Jump(block4)) self.builder.set_block(block4) self.builder.emit(ir.Jump(block6)) self.builder.set_block(block6) phi = self.builder.emit(ir.Phi('res24', ir.i16)) phi.set_incoming(block4, cnst) cnst2 = self.builder.emit(ir.Const(2, 'cnst2', ir.i16)) binop = self.builder.emit(ir.add(phi, cnst2, 'binop', ir.i16)) phi.set_incoming(block6, binop) self.builder.emit(ir.Jump(block6)) verify_module(self.module) # Act: self.clean_pass.run(self.module) self.assertNotIn(block4, self.function)
def test_add0(self): f = self.b.new_procedure("test", ir.Binding.GLOBAL) self.b.set_function(f) self.b.set_block(self.b.new_block()) v1 = ir.Const(12, "const", ir.i32) self.b.emit(v1) v2 = ir.Const(0, "const", ir.i32) self.b.emit(v2) v3 = ir.add(v1, v2, "add", ir.i32) self.b.emit(v3)
def test_builder(self): f = self.b.new_procedure("test", ir.Binding.GLOBAL) self.b.set_function(f) entry = self.b.new_block() f.entry = entry self.b.set_block(entry) bb = self.b.new_block() self.b.emit(ir.Jump(bb)) self.b.set_block(bb) v1 = self.b.emit(ir.Const(5, "const", ir.i32)) v2 = self.b.emit(ir.Const(7, "const", ir.i32)) self.b.emit(ir.add(v1, v2, "add", ir.i32)) self.b.emit(ir.Exit()) self.cf.run(self.m)
def test_use(self): """ Check if use def information is correctly administered """ c1 = ir.Const(1, "one", ir.i32) c2 = ir.Const(2, "two", ir.i32) c3 = ir.Const(3, "three", ir.i32) c4 = ir.Const(4, "four", ir.i32) add = ir.add(c1, c2, "add", ir.i32) self.assertEqual({c1, c2}, add.uses) # Replace usage by setting the variable: add.a = c3 self.assertEqual({c3, c2}, add.uses) # Replace use by changing value: add.replace_use(c2, c4) self.assertEqual({c3, c4}, add.uses) self.assertEqual(c4, add.b)
def test_add(self): """ See if the ir classes can be constructed """ v1 = ir.Const(1, "const", ir.i32) v2 = ir.Const(2, "const", ir.i32) ir.add(v1, v2, "add", ir.i32)