Hi, currently the following two lines of code with integer variables get compiled completely differently: if (d0<tmp) d0=tmp; d0 = d0<tmp? tmp : do; The first is compiled into two separate basic blocks, which my backend then optimizes into a conditional move with if-conversion (after instruction selection so not much optimization possible anymore). The second line is compiled into select operations, which my backend is able to compile into much more efficient max instructions. Shouldn't the first form be optimized into the second somewhere in the compiler front-end? In other words, do we already have a pass that should optimize this, and if not, is it worthwhile working on one? Thanks, Bjorn De Sutter Computer Systems Lab Ghent University
Hi Bjorn,> currently the following two lines of code with integer variables get compiled completely differently: > > if (d0<tmp) d0=tmp;there must be something else going on because this void bar(int); void foo(int d0, int tmp) { if (d0 < tmp) d0=tmp; bar(d0); } when compiled like this clang -S -O4 -o - sel.c gives this define void @foo(i32 %d0, i32 %tmp) nounwind uwtable { entry: %cmp = icmp slt i32 %d0, %tmp %tmp.d0 = select i1 %cmp, i32 %tmp, i32 %d0 tail call void @bar(i32 %tmp.d0) nounwind ret void } Did you supply the optimizers with DataLayout information. I mean this kind of stuff in the IR: target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" Ciao, Duncan.> > d0 = d0<tmp? tmp : do; > > The first is compiled into two separate basic blocks, which my backend then optimizes into a conditional move with if-conversion (after instruction selection so not much optimization possible anymore). The second line is compiled into select operations, which my backend is able to compile into much more efficient max instructions. > > Shouldn't the first form be optimized into the second somewhere in the compiler front-end? In other words, do we already have a pass that should optimize this, and if not, is it worthwhile working on one? > > Thanks, > > Bjorn De Sutter > Computer Systems Lab > Ghent University > > > > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >
On 1/18/2013 6:19 AM, Duncan Sands wrote:> Hi Bjorn, > >> currently the following two lines of code with integer variables get >> compiled completely differently: >> >> if (d0<tmp) d0=tmp; > > there must be something else going on because this > > void bar(int); > void foo(int d0, int tmp) { > if (d0 < tmp) d0=tmp; > bar(d0); > } > > when compiled like this > > clang -S -O4 -o - sel.c > > gives this > > define void @foo(i32 %d0, i32 %tmp) nounwind uwtable { > entry: > %cmp = icmp slt i32 %d0, %tmp > %tmp.d0 = select i1 %cmp, i32 %tmp, i32 %d0 > tail call void @bar(i32 %tmp.d0) nounwind > ret void > }Last time I looked at this code, it only handled blocks with a single value in it, e.g. if.cond: ... %oldvalue ... br i1 %cond, %if.then, %skip if.then: %value = something <-- single instruction in this block br %skip skip: %newvalue = phi [ %oldvalue, %if.cond ], [ %newvalue, %if.then ] The simplification was happening in SimplifyCFG, and was driven by the existence of a phi node in the join block (in "skip" in this case). If there were more instructions in "if.then", the code would not handle it. I have actually extended it to handle multiple phis a while back. I guess I should upstream it if nobody else has done it yet... -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation