OrenIshShalom
OrenIshShalom

Reputation: 7112

LLVM Loop Invariant Code Motion (-licm) pass

I have some simple C loop code, and I want to simplify it as much as possible. Here is the original C file:

#include <stdio.h>

char *foo(char *s)
{
    while (*s == 'a' || *s == 'b')
    {
        s++;
    }
    return s;
}

int main(int argc, char **argv)
{
    char *s1 = argv[1];
    char *s2 = foo(s1);
    return 0;
}

I've tried using opt with the -licm flag, which is supposed to:

remove as much code from the body of a loop as possible. It does this by either hoisting code into the preheader block

But when I look at the loop body, I see that lines 21 and 22 are really redundant, as %s.addr did not change, and so lines 21 and 22 can be safely deleted, and instead of %tmp3 we can use %tmp1 from line 23 onward.

 13 while.cond:                                       ; preds = %while.body, %entry
 14   %tmp = load i8*, i8** %s.addr, align 8
 15   %tmp1 = load i8, i8* %tmp, align 1
 16   %conv = sext i8 %tmp1 to i32
 17   %cmp = icmp eq i32 %conv, 97
 18   br i1 %cmp, label %lor.end, label %lor.rhs
 19 
 20 lor.rhs:                                          ; preds = %while.cond
 21   %tmp2 = load i8*, i8** %s.addr, align 8
 22   %tmp3 = load i8, i8* %tmp2, align 1
 23   %conv2 = sext i8 %tmp3 to i32
 24   %cmp3 = icmp eq i32 %conv2, 98
 25   br label %lor.end

What am I missing? is there some other pass to achieve this goal?

Upvotes: 2

Views: 1713

Answers (1)

Johan
Johan

Reputation: 3871

You are missing that %s.addr is not invariant in the while loop. The loop invariant code motion optimization identifies expressions that do not change between iterations and try to lift them out of the loop. What you are looking for is something like common subexpression elimination. This optimization identifies repeated computation of the same subexpression and tries to remove all but one. In my version of opt this optimization is enabled by the -early-cse switch.

Upvotes: 2

Related Questions