Reputation: 21
I want to write an LLVM pass to reduce &&
in LLVM IR, but I can't find the specific instructions for it in IR. For example,
#include <iostream>
int main(){
bool a = true;
bool b = false;
bool c = a && b;
return 0;
}
and I get the IR,
define dso_local i32 @main() #4 {
%1 = alloca i32, align 4
%2 = alloca i8, align 1
%3 = alloca i8, align 1
%4 = alloca i8, align 1
store i32 0, i32* %1, align 4
store i8 1, i8* %2, align 1
store i8 0, i8* %3, align 1
%5 = load i8, i8* %2, align 1
%6 = trunc i8 %5 to i1
br i1 %6, label %7, label %10
7: ; preds = %0
%8 = load i8, i8* %3, align 1
%9 = trunc i8 %8 to i1
br label %10
10: ; preds = %7, %0
%11 = phi i1 [ false, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i8
store i8 %12, i8* %4, align 1
ret i32 0
}
but I tried this one,
#include <iostream>
int main(){
int a = 10;
int b = 10;
int c;
c = a && b;
return 0;
}
and I get this
define dso_local i32 @main() #4 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 10, i32* %2, align 4
store i32 10, i32* %3, align 4
%5 = load i32, i32* %2, align 4
%6 = icmp ne i32 %5, 0
br i1 %6, label %7, label %10
7: ; preds = %0
%8 = load i32, i32* %3, align 4
%9 = icmp ne i32 %8, 0
br label %10
10: ; preds = %7, %0
%11 = phi i1 [ false, %0 ], [ %9, %7 ]
%12 = zext i1 %11 to i32
store i32 %12, i32* %4, align 4
ret i32 0
}
I use LLVM 10 in ubuntu. I'll appreciate any answers or suggestions.
Upvotes: 2
Views: 1035
Reputation: 370445
There is no LLVM instruction that specifically corresponds to the &&
operator. It can and will be translated in different ways depending on the expression and the optimization settings.
When you have optimizations enabled, the operands are side effect free (and not expensive to evaluate) and the whole expression can't be optimized away, clang
will usually convert both operands to i1
and apply the logical and
operator on them.
When optimizations are disabled or the operands have side effects, it'll usually be translated using branch instructions. That's the case in the two examples you posted.
Note that expr1 && expr2
is semantically equivalent to expr1 ? expr2 : false
and you'll generally get the same LLVM code for both.
If you're okay with treating expr1 ? expr2 : false
and other equivalent code (for example using if
statements) the same as &&
, you can try to detect the branching pattern created by them. If you need your pass to also be applicable after optimizations, you'll also have to detect at least the pattern of converting to i1 and and
ing.
If you only want your transformation to apply to &&
and nothing else, you simply can't do it at the LLVM level. You'd need an AST transformation at the Clang level.
Upvotes: 3