[PATCH] Teach DeadArgElimination not to eliminate return values of functions with 'returned' arguments

Stephen Lin swlin at post.harvard.edu
Sun Jun 23 10:57:57 PDT 2013


> This does conflict with the theoretical separation of concerns between
> optimizer and codegen in LLVM though. This patch does not promote subsequent
> mid-level optimization opportunities; treating values as live when they are
> actually unused may actually obscure other mid-level optimization
> opportunities.
>
> Dan
>

I understand, and I'm not thrilled about it either, but is there an
alternative course of action you can think of? The problem is that the
return value provides potentially valuable information, and there's no
good way (as far as I can tell) to get it back at the CodeGen level if
it's dropped from the IR because it would require interprocedural
coordination of code generation.

Also, in theory, some mid level optimization could be done, even if it
is not done now. A 'returned' argument implies the argument and return
value are aliases of each other in all code dominated by the function
call, so IR optimizers would be free to replace one with the other. As
mentioned in other e-mails, it is, the problem is that, in the general
case, it is difficult to know which alternative to pick; however, an
IR pass could, at a minimum, canonicalize this:

  %struct.A = type { i32 }

  declare %struct.A* @a_ctor(%struct.A* returned)
  declare void @bar(%struct.A*)

  define %struct.A* @foo() {
  entry:
    %a = alloca %struct.A, align 4
    %b = call %struct.A* @a_ctor(%struct.A* %a)
    call void @bar(%struct.A* %a)
    ret %struct.A* %b
  }

into:

  %struct.A = type { i32 }

  declare %struct.A* @a_ctor(%struct.A* returned)
  declare void @bar(%struct.A*)

  define %struct.A* @foo() {
  entry:
   %a = alloca %struct.A, align 4
   %b = call %struct.A* @a_ctor(%struct.A* %a)
   %0 = select i1 undef, %struct.A* %a, %struct.A* %b
   call void @bar(%struct.A* %0)
   ret %struct.A* %0
  }

or even:

  %struct.A = type { i32 }

  declare %struct.A* @a_ctor(%struct.A* returned)
  declare void @bar(%struct.A*)

  define %struct.A* @foo() {
  entry:
   %a = alloca %struct.A, align 4
   %b = call %struct.A* @a_ctor(%struct.A* %a)
   %0 = select i1 undef, %struct.A* %a, %struct.A* %b
   %1 = select i1 undef, %struct.A* %a, %struct.A* %b
   call void @bar(%struct.A* %0)
   ret %struct.A* %1
  }

The reason for not doing this immediately is that I do not think much
code is prepared to deal with the "select i1 undef, %struct.A* %a,
%struct.A* %b" pattern in an intelligent way.

Stephen



More information about the llvm-commits mailing list