Why does an extra instruction appear during code generation of a condition and a loop and how to get rid of it?

Why does an extra instruction appear during code generation of a condition (br) and a loop and how to get rid of it?

Here is an example of my source code, a fictional programming language…

alg hello1 (int a)
begin
	int x = 0;

	until (x < 10)
		PRINT("qwerty");
	end
	
	x = x+2;
end

alg
begin
	hello1(10);
end

Here is an example of code-generated code…

; ModuleID = 'main'
source_filename = "main"

@0 = private unnamed_addr constant [7 x i8] c"qwerty\00", align 1
@1 = private unnamed_addr constant [3 x i8] c"%s\00", align 1

define internal void @hello1(i64 %a) {
entry:
  %0 = alloca i64
  store i64 %a, i64* %0
  %1 = alloca i64
  store i64 0, i64* %1
  %2 = load i64, i64* %1
  %cmptmp = icmp ult i64 %2, 10
  %3 = icmp ne i1 %cmptmp, false
  br i1 %3, label %forloop, label %forcont
  %4 = load i64, i64* %1; <- These structures were not inserted correctly, how could they even appear?
  %5 = load i64, i64* %1; <-----------

forloop:                                          ; preds = %forloop, %entry
  %printfCall = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @1, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @0, i32 0, i32 0))
  %cmptmp1 = icmp ult i64 %4, 10
  %6 = icmp ne i1 %cmptmp1, false
  br i1 %6, label %forloop, label %forcont
  ; <----Here everything is correct, for example

forcont:                                          ; preds = %forloop, %entry
  %addtmp = add i64 %5, 2
  store i64 %addtmp, i64* %1
}

declare i32 @printf(i8*, ...)

define void @main() {
entry:
  call void @hello1(i64 10)
}

This is how I described the code generation procedure for a conditional construct and a regular block…

llvm::Value *NIfStatement::codeGen(CodeGenContext &context)
{
    cout << "Generating if statement" << endl;
    Value *condValue = this->condition.codeGen(context);
    if (!condValue)
        return nullptr;

    condValue = CastToBoolean(context, condValue);

    Function *theFunction = context.builder.GetInsertBlock()->getParent(); // the function where if statement is in

    BasicBlock *thenBB = BasicBlock::Create(context.llvmContext, "then", theFunction);
    BasicBlock *falseBB = BasicBlock::Create(context.llvmContext, "else");
    BasicBlock *mergeBB = BasicBlock::Create(context.llvmContext, "ifcont");

    if (this->falseBlock)
    {
        context.builder.CreateCondBr(condValue, thenBB, falseBB);
    }
    else
    {
        context.builder.CreateCondBr(condValue, thenBB, mergeBB);
    }

    context.builder.SetInsertPoint(thenBB);

    context.pushBlock(thenBB);

    this->trueBlock.codeGen(context);

    context.popBlock();

    thenBB = context.builder.GetInsertBlock();

    if (thenBB->getTerminator() == nullptr)
    { //
        context.builder.CreateBr(mergeBB);
    }

    if (this->falseBlock)
    {
        theFunction->getBasicBlockList().push_back(falseBB); //
        context.builder.SetInsertPoint(falseBB);             //

        context.pushBlock(thenBB);

        this->falseBlock->codeGen(context);

        context.popBlock();

        context.builder.CreateBr(mergeBB);
    }

    theFunction->getBasicBlockList().push_back(mergeBB); //
    context.builder.SetInsertPoint(mergeBB);             //

    return nullptr;
}

llvm::Value *NBlock::codeGen(CodeGenContext &context)
{
    cout << "Generating block" << endl;
    Value *last = nullptr;
    for (auto it = this->statements.begin(); it != this->statements.end(); it++)
    {
        last = (*it)->codeGen(context);
    }
    return last;
}

Please tell me how to fix this bug? :pleading_face:

I don’t think the problem is in the C++ you pasted here (apart from anything else that’s the code for an if not a loop). Time to fire up the debugger, put a breakpoint on CreateLoad, and work out why the basic-block is wrong there I think.