[LLVMdev] Missed optimisation opportunities?

Jeremy Lakeman Jeremy.Lakeman at gmail.com
Sat Mar 30 03:36:07 PDT 2013


I'm writing a front end for an existing interpreted language with slightly
odd semantics for primitive values.
Similar to the values in a database table, any value could be null, even
for non-pointer types.
For example a boolean variable could be true, false, or null.
To model this behaviour, I'm passing an {i1, [type]} around for every
numeric type. And using insertvalue / extractvalue all over the place.

So when compiling this simple CS example;

function long fib (long al_x)
long ll_i=0, ll_ret=0, ll_last=0, ll_last2=1

if isnull(al_x) then
    return al_x
end if

ll_i=1
do while ll_i<=al_x
    ll_ret=ll_last+ll_last2
    ll_last2=ll_last
    ll_last=ll_ret
    ll_i++
loop
return ll_ret
end function

With the following function passes;
        FunctionPasses->add(new DataLayout(*JITEngine->getDataLayout()));
        FunctionPasses->add(createBasicAliasAnalysisPass());
        FunctionPasses->add(createPromoteMemoryToRegisterPass());
        FunctionPasses->add(createInstructionCombiningPass());
        FunctionPasses->add(createReassociatePass());
        FunctionPasses->add(createGVNPass());
        FunctionPasses->add(createCFGSimplificationPass());

Which does a pretty good job of cleaning up most of the messy & verbose
code generated by my front end.

I end up with the following bitcode;

define x86_stdcallcc { i1, i32 } @fib({ i1, i32 } %arg_al_x) {
entry:
  %"3_4" = extractvalue { i1, i32 } %arg_al_x, 0
  br i1 %"3_4", label %Line15_Offset120, label %Line8_Offset38

Line8_Offset38:                                   ; preds =
%Line9_Offset52, %entry
  %ll_last2.0 = phi { i1, i32 } [ %ll_last.0, %Line9_Offset52 ], [ { i1
false, i32 1 }, %entry ]
  %ll_last.0 = phi { i1, i32 } [ %"9_64_composed", %Line9_Offset52 ], [
zeroinitializer, %entry ]
  %ll_i.0 = phi { i1, i32 } [ %"12_98", %Line9_Offset52 ], [ { i1 false,
i32 1 }, %entry ]
  %"8_38_isnull" = extractvalue { i1, i32 } %ll_i.0, 0
  %"8_38_value" = extractvalue { i1, i32 } %ll_i.0, 1
  %"8_42_value" = extractvalue { i1, i32 } %arg_al_x, 1
  %"8_46_value" = icmp sle i32 %"8_38_value", %"8_42_value"
  %"8_48_not_null" = xor i1 %"8_38_isnull", true
  %"8_48_and_not_null" = and i1 %"8_46_value", %"8_48_not_null"
  br i1 %"8_48_and_not_null", label %Line9_Offset52, label %Line15_Offset120

Line9_Offset52:                                   ; preds = %Line8_Offset38
  %"9_60_isnull" = extractvalue { i1, i32 } %ll_last2.0, 0
  %"9_56_isnull" = extractvalue { i1, i32 } %ll_last.0, 0
  %"9_64_isnull" = or i1 %"9_56_isnull", %"9_60_isnull"
  %"9_56_value" = extractvalue { i1, i32 } %ll_last.0, 1
  %"9_60_value" = extractvalue { i1, i32 } %ll_last2.0, 1
  %"9_64" = add i32 %"9_56_value", %"9_60_value"
  %0 = insertvalue { i1, i32 } zeroinitializer, i1 %"9_64_isnull", 0
  %"9_64_composed" = insertvalue { i1, i32 } %0, i32 %"9_64", 1
  %"12_98_value" = add i32 %"8_38_value", 1
  %1 = insertvalue { i1, i32 } zeroinitializer, i1 %"8_38_isnull", 0
  %"12_98" = insertvalue { i1, i32 } %1, i32 %"12_98_value", 1
  br label %Line8_Offset38

Line15_Offset120:                                 ; preds =
%Line8_Offset38, %entry
  %_return_value.0 = phi { i1, i32 } [ %arg_al_x, %entry ], [ %ll_last.0,
%Line8_Offset38 ]
  ret { i1, i32 } %_return_value.0
}

None of the local variables in this example can ever be null. Each of these
extractvalue expressions will always evaluate to i1 0;

  %"8_38_isnull" = extractvalue { i1, i32 } %ll_i.0, 0
  %"9_60_isnull" = extractvalue { i1, i32 } %ll_last2.0, 0
  %"9_56_isnull" = extractvalue { i1, i32 } %ll_last.0, 0

Is there an existing function pass I could add that would clean this up? Or
is this example just slightly too complex?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130330/010effa5/attachment.html>


More information about the llvm-dev mailing list