diffkemp
diffkemp copied to clipboard
`simplifycfg` pass sometimes represents `&&` with `select` instead of `and` instruction
simplifycfg
pass (used for simplifying/merging basic blocks) which is part of passes which are used in build-kernel
command sometimes represents combined condition with &&
using select
instruction instead of and
instruction. This can cause inequality in simple examples like extraction condition to function.
Example to replicate behaviour:
// old version
int foo(int a, int b, int c) {
if (a < b && a < c) {
return 0;
}
else return 1;
}
// new version
#include <stdbool.h>
// (edited: should be bool not int)
bool bar(int a, int b, int c) {
return a < b && a < c;
}
int foo(int a, int b, int c) {
if (bar(a, b, c)) {
return 0;
}
else return 1;
}
Commands to compare the versions:
# build both version
bin/diffkemp build --clang-append="-O1" --clang-append="-Xclang" --clang-append="-disable-llvm-passes" <path-to-c_file> <build_dir>
# run passes used in build-kernel command (includes simplifycfg)
python3 -c "from diffkemp.llvm_ir.kernel_llvm_source_builder import KernelLlvmSourceBuilder
opt = KernelLlvmSourceBuilder._opt_llvm
opt(<path-to-llvm-file-in-build-dir>)
"
# compare snapshots
bin/diffkemp -vvdd compare --stdout <old_build> <new_build>
Snippet of output:
; Old version
%4 = icmp slt i32 %0, %1, !dbg !17
%5 = icmp slt i32 %0, %2
%or.cond = and i1 %4, %5, !dbg !19
; New version
%4 = icmp slt i32 %0, %1, !dbg !18
%5 = icmp slt i32 %0, %2
%spec.select = select i1 %4, i1 %5, i1 false, !dbg !19
This should be resolved by #322 (once it is merged)