Implementing `+=` in LLVM IR

Hello, I am new to LLVM, and I’m writing my first compiler using Python and the llvmlite wrapper. I am trying to implement the functionality to increment variables, and it kind of works, but my IR has an extra load instruction in it that is messing with the results, and I’m not sure how to avoid it, since I need it in both two different places.

This IR will do what I need:

And this IR is what I currently generate:

The two are identical except for the additional load instruction in the second example, where %".3" is loaded into memory twice, and the instruction that gets passed into the second printf call.

These are the two conflicting functions:

# Visitor for using variables
def visit_var_usage(self, name):
    var_addr = self.symbol_table[name]
    return self.builder.load(var_addr)

# There is a bug here, which causes the value to be loaded into memory twice. I suspect it's because var_usage also loads it into memory, and incrementing the variable's value gets parsed as a variable usage.

# The issue is that it needs to be loaded into memory inside visit_increment so that it can be used inside the `fadd` instruction.
def visit_increment(self, variable, val):
    dbl_val = ir.Constant(ir.DoubleType(), val)    # Convert the number to be added into an LLVM object
    var_addr = self.symbol_table[variable]         # Get the value and load it into memory
    load_instr = self.builder.load(var_addr)
    return self.builder.fadd(load_instr, dbl_val)  # Increment the variable's value by the specified amount

Since the statement x += 3 will load the variable x using the first function and then increment it using the second function, and both load it into memory, there are two load instructions instead of one.

Why visit_var_usage is being called isn’t immediately obvious to me here. And if it were to generate a redundant load that would not really be an issue and is trivial dead code removed later.

Much more important for your increment statement is that you aren’t storing the new value back into the variable. You first use a load to get the value inside the variable, then you use fadd to add the value with another. But aren’t yet storing the resulting value back into the variable.

I only have experience with the C++ API but if I had to guess it’d look something like this in python?:

load_instr = self.builder.load(var_addr)
incremented = self.builder.fadd(load_instr, dbl_val)
self.builder.store(incremented,var_addr)
return incremented

Do double check whether store is a thing and it’s documentation.

store() is valid instruction in the llvmlite wrapper. I tried what you suggested, and although the resulting IR isn’t exactly the same as the correct_ir file, the output is correct. I suspected my code was close to working, but that there was something I was missing. Thanks for pointing that out. I appreciate your help.