0

I'm using the prebuilt LLVM 6.0, when I perform llvm pass -mem2reg to generate SSA, the IR code remains as is without being changed. But when I use the prebuilt LLVM 3.8 to do the same thing, the llvm pass works. However, I need to use LLVM 6.0 because I'm using other tools that leverage this LLVM version.

To give a concrete example: Here is the c code

int main(int argc, char** argv){
    int total_lines = 0;
    int total_chars = 0;

    int count_chars = 0;
    int count_lines = 0;

    if(argc == 1){
        printf("Please specify count line and chars\n");
    } else if (argc ==2){
        if (!strcmp(argv[1], "-c")){
            count_chars = 1;
        }else if (!strcmp(argv[1], "-l")){
            count_lines = 1;
        }
    }

    char buffer[1024];
    while (fgets(buffer, 1024,stdin)){
        if (count_chars)
            total_chars += sizeof(buffer);
        if (count_lines)
            total_lines += lineCount();
    }
    if (count_chars)
        printf("Count chars is:: %d\n", total_chars);
    if (count_lines)
        printf("Count Lines is:: %d\n", total_lines);
    return 0;
}

I run the LLVM pass to generate the SSA and then generate the human readable IR code using the following commands:

LLVM_6.0_bin/bin/clang -c -emit-llvm example.c
LLVM_6.0_bin/bin/llvm-dis example.bc -o h1.ll

//SSA LLVM pass 
LLVM_6.0_bin/bin/opt -mem2reg example.bc -o example_SSA.bc
LLVM_6.0_bin/bin/llvm-dis example_SSA.bc -o h2.ll

diff h1 h2 //I receive the following

< ; ModuleID = 'example.bc'
---
> ; ModuleID = 'example_SSA.bc'

While when I do the same previous steps but using prebuilt LLVM 3.8, and diff h1 h2 I get many differences including the following

< ; <label>:50                                      ; preds = %29
<   %51 = load i32, i32* %count_chars, align 4
<   %52 = icmp ne i32 %51, 0
<   br i1 %52, label %53, label %56
< 
< ; <label>:53                                      ; preds = %50
<   %54 = load i32, i32* %total_chars, align 4
<   %55 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.4, i32 0, i32 0), i32 %54)
<   br label %56
< 
< ; <label>:56                                      ; preds = %53, %50
<   %57 = load i32, i32* %count_lines, align 4
<   %58 = icmp ne i32 %57, 0
<   br i1 %58, label %59, label %62
< 
< ; <label>:59                                      ; preds = %56
<   %60 = load i32, i32* %total_lines, align 4
<   %61 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([21 x i8], [21 x i8]* @.str.5, i32 0, i32 0), i32 %60)
<   br label %62
---
> ; <label>:22                                      ; preds = %38, %21
>   %total_lines.0 = phi i32 [ 0, %21 ], [ %total_lines.1, %38 ]
>   %total_chars.0 = phi i32 [ 0, %21 ], [ %total_chars.1, %38 ]
>   %23 = getelementptr inbounds [1024 x i8], [1024 x i8]* %buffer, i32 0, i32 0
>   %24 = load %struct._IO_FILE*, %struct._IO_FILE** @stdin, align 8
>   %25 = call i8* @fgets(i8* %23, i32 1024, %struct._IO_FILE* %24)
>   %26 = icmp ne i8* %25, null
>   br i1 %26, label %27, label %39

Mohannad
  • 93
  • 12
  • Could you add a minimal working example that illustrates what you mean. Also please provide the generated IR for both solutions. For instance a simple C main-function that does some assignment based on input arguments – JKRT Jun 12 '20 at 12:55
  • I added more explanation – Mohannad Jun 12 '20 at 13:05

1 Answers1

1

I found the solution it's based on this answer LLVM opt mem2reg has no effect

The new version of LLVM annotates the bitcode generated by clang to prevent additional optimizations later on. So I just had to add these flags -Xclang -disable-O0-optnone to the clang command

LLVM_6.0_bin/bin/clang -c -emit-llvm example.c

To

LLVM_6.0_bin/bin/clang -Xclang -disable-O0-optnone -c -emit-llvm example.c

Mohannad
  • 93
  • 12