In this part, we introduce some flags that shows up in both POJ and GCJ.
-mem2reg : It promotes alloca instructions which only have loads and stores as uses.
example source code:
int foo(int x, int cond)
{
if (cond > 0)
x = 1;
else
x = -1;
return x;
}
LLVM-IR code without -mem2reg
define dso_local i32 @foo(i32 %x, i32 %cond) #0 {
entry:
%x.addr = alloca i32, align 4
%cond.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
store i32 %cond, i32* %cond.addr, align 4
%0 = load i32, i32* %cond.addr, align 4
%cmp = icmp sgt i32 %0, 0
br i1 %cmp, label %if.then, label %if.else
if.then: ; preds = %entry
store i32 1, i32* %x.addr, align 4
br label %if.end
if.else: ; preds = %entry
store i32 -1, i32* %x.addr, align 4
br label %if.end
if.end: ; preds = %if.else, %if.then
%1 = load i32, i32* %x.addr, align 4
ret i32 %1}
LLVM-IR code with -mem2reg
define dso_local i32 @foo(i32 %x, i32 %cond) #0 {
entry:
%cmp = icmp sgt i32 %cond, 0
br i1 %cmp, label %if.then, label %if.else
if.then: ; preds = %entry
br label %if.end
if.else: ; preds = %entry
br label %if.end
if.end: ; preds = %if.else, %if.then
%x.addr.0 = phi i32 [ 1, %if.then ], [ -1, %if.else ]
ret i32 %x.addr.0}
We can find that the load/store/alloca insts are all turned into real SSA-format, which helps reduce the useless inst and boost the quality of IR Code.
3) Simplify CFG.
-loop-rotate: converts loops into do/while style loops. The below example are from LLVM_LOOP_ROTATE
-instcombine :Combine instructions to form fewer, simple instructions.
example source code:
int main() {
int i =0;
int a = 1,b=2,c=3;
float k = 34;
i += a;
i += k;
printf("%d",i);
return i;
}
LLVM-IR code without -instcombine
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
%5 = alloca i32, align 4
%6 = alloca float, align 4
store i32 0, i32* %1, align 4
store i32 0, i32* %2, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
store i32 3, i32* %5, align 4
store float 3.400000e+01, float* %6, align 4
%7 = load i32, i32* %3, align 4
%8 = load i32, i32* %2, align 4
%9 = add nsw i32 %8, %7
store i32 %9, i32* %2, align 4
%10 = load float, float* %6, align 4
%11 = load i32, i32* %2, align 4
%12 = sitofp i32 %11 to float
%13 = fadd float %12, %10
%14 = fptosi float %13 to i32
store i32 %14, i32* %2, align 4
%15 = load i32, i32* %2, align 4
%16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i32 %15)
%17 = load i32, i32* %2, align 4
ret i32 %17
}
declare dso_local i32 @printf(i8*, ...) #1
LLVM-IR code with -instcombine
define dso_local i32 @main() #0 {
%1 = call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i64 0, i64 0), i32 35) #2
ret i32 35
}
declare dso_local i32 @printf(i8*, ...) #1
As we can see, the abudunt instructions can be removed through -instcomine, we should also mention that different types can be analysed and convert into the same if not needed.