[Mesa-dev] [PATCH 10/11] clover: Add function for building a clover::module for non-TGSI targets

Tom Stellard thomas.stellard at amd.com
Mon May 14 11:06:35 PDT 2012


On Mon, May 14, 2012 at 05:19:10PM +0200, Francisco Jerez wrote:
> Tom Stellard <tstellar at gmail.com> writes:
> 
> > On Sun, May 13, 2012 at 04:10:50PM +0200, Francisco Jerez wrote:
> >> Tom Stellard <tstellar at gmail.com> writes:
> >> 
> >> > On Sun, May 13, 2012 at 12:40:43AM +0200, Francisco Jerez wrote:
> >> >>[...]
> >> >> I can think of two different ways this could work (your solution would
> >> >> be somewhere in between):
> >> >> 
> >> >>  - The r600g LLVM back-end could support some well-defined output object
> >> >>    format (e.g. the one implemented by the clover::module classes), like
> >> >>    most of the other LLVM back-ends.  You probably want to do this
> >> >>    anyway if you want to be able to compile CL programs off-line.  If
> >> >>    you do it this way, the state tracker will just call clang to
> >> >>    completion using the appropriate target and pass the generated
> >> >>    machine code to the pipe driver.
> >> >> 
> >> >>    If you think supporting different hardware versions with different
> >> >>    ISAs would be a problem under this scheme, we could have another
> >> >>    compute cap that would determine a specific variant of the ISA.
> >> >>
> >> >
> >> > I think this is the most practical of these two options.  However, the
> >> > biggest draw back of this solution is that if a target uses a backend that
> >> > is not a part of the LLVM tree (the r600 backend is not in the LLVM tree,
> >> > but I'm working on getting it in), the backend would have to be included
> >> > as a part of clover and drivers using LLVM for other state tracker would
> >> > end up with one copy of their LLVM backend in clover and another in the
> >> > driver.
> >> 
> >> Apparently it's already standard practice in LLVM to build back-ends as
> >> separate object files.  I don't see why you couldn't build the r600
> >> back-end as a shared library.  There's no reason for it to be duplicated
> >> in the source tree or the address space of the process it's running in.
> >>
> >
> > I don't think this will work if clover and the back-end link
> > statically to the LLVM libraries, which is what Mesa does by default.
> > LLVM relies on global pointers to identify float types within
> > a module, so it doesn't work to pass a module between shared libraries that
> > have each linked separately with LLVM, which is what will be happening
> > if the Clang frontend and the backend live in separate shared objects.
> >
> 
> I don't think that's going to be a problem.  If you do it this way the
> state tracker will be generating r600 machine code directly and there
> should be no pointer identifiers being leaked through the gallium API.
> 
> But, anyway, I think you want to link to the r600 back-end from the
> target instead of linking from the state tracker and pipe driver, that
> way you make sure you're only linking once.
> 
> >
> >> > I guess this might be able to work, but I'm not really sure why doing
> >> > it this way would be better than what is implemented in this patch.
> >> >
> >> I just think it would be useful by itself to have the r600 back-end able
> >> to emit machine code in a specific object file format, and at the same
> >> time, by doing so you avoid driver-specific code in the state tracker
> >> that does one thing or another depending on the hardware it's running
> >> on, which seems like a layering violation to me.
> >
> > State trackers already use caps to do different things depending on
> > what hardware it's running.  So, I'm not really sure why using
> > PIPE_SHADER_CAP_PREFFERED_IR is any different.
> >
> 
> I'm aware, but the fact that we're already doing it elsewhere doesn't
> mean it's a good practice if it can be avoided.  
> 
> If it turns out it can't be avoided, IMHO, any driver caps that affect
> the state tracker behaviour should have a well-defined meaning
> independent from the pipe driver that is running behind, i.e. a state
> tracker should never have to do: "if (r600) { /* do something */ } else
> { /* do something else */ }".
>

I agree with you here.  Just so I'm clear, when you say you don't want
"if (r600) { /* do something */ } else { /* do something else */ }"
are you referring to this block of code:

module
clover::compile_program_llvm(const compat::string &source,
                             const compat::string &target) {

   if (target == compat::string("TGSI")) {
#if 0
      build_binary(source, target, "cl_input");
      module m = load_binary("cl_input.o");
      std::remove("cl_input.o");
      return m;
#else
      return module();
   } else {
      return build_module_llvm(source, target, "cl_input");
   }
#endif
}

If so, would it be better if this decision was based on the value of
PIPE_SHADER_CAP_PREFFERED_IR?

 
> >> 
> >> >>  - Another option would be to forget about driver-specific IRs in the
> >> >>    compute API.  The pipe driver would have the choice between TGSI and
> >> >>    LLVM, if it wants LLVM, the state tracker would do roughly what
> >> >>    you're doing here using some sort of "identity" LLVM target that
> >> >>    would do nothing but describing the peculiarities of the hardware
> >> >>    (e.g. endianness, widths of the supported primitive types), which in
> >> >>    turn would be queried from the pipe driver using compute caps.
> >> >>
> >> >
> >> > This is the way I thought it would work initially, but the only way to
> >> > describe a target to Clang is by using the target triple, so passing a
> >> > list of caps into Clang is not going to work.
> >> >
> >> Why not?  You're in control of the back-end, maybe I'm missing something
> >> but I don't see why the state tracker couldn't provide all the required
> >> parameters to the back-end as it's instantiated.
> >>
> >
> > Clang doesn't consult the backend when it converts OpenCL C to LLVM IR,
> > so passing extra information to the backend won't help.  We need to pass
> > target information directly to Clang and the only way to do this is via
> > the target triple.
> >
> >
> >> If this is impossible for some reason, can't we encode these parameters
> >> in the processor variant part of the target triple?  Aren't these
> >> parameters supposed to be encoded as a target description string at some
> >> point anyway?
> >>
> >
> > The target description string is one of the attributes on the TargetInfo
> > class in Clang, but there are others as well.  Take a look at the
> > Targets.cpp file in Clang and you'll see what I'm talking about:
> > http://clang.llvm.org/doxygen/Targets_8cpp-source.html
> >
> >
> >> >> Personally I think the latter would be closer to ideal, but I guess it
> >> >> would also involve more work...
> >> >
> >> > My preference is to keep this patch as is.  At this point, I'm not
> >> > really sure why the proposed alternate solutions would be better than
> >> > the current implementation, and I think if we want to support out of
> >> > tree backends, we will need to at least have the option of doing it this
> >> > way.
> >> >
> >> What bothers me of this solution is that you're pumping bytecode using a
> >> generic representation, but in a non-generic way, that isn't going to be
> >> useful for drivers other than r600 that want compute programs in the
> >> same representation -- at least not without a number of driver-specific
> >> ad-hoc changes in both LLVM and the CL state tracker.
> >> 
> >
> > This is exactly what other state trackers do.  They produce a generic
> > representation (TGSI) in a non-generic way.  For example, st/mesa might
> > produce a TGSI fragment shader that uses indirect addressing for r600g,
> > but the TGSI representation of the shader is not generic.  That TGSI
> > program will not run on r300g, because that driver does not support
> > indirect addressing.
> 
> I didn't mean that all the code produced by the state tracker should be
> able to run on any hardware, I meant that whatever means you use to
> generate that code should be made as reusable for other drivers as
> possible.
> 
> >> I'm fine with the CL state tracker giving out code in LLVM IR, but, if
> >> it does, I really think it makes no sense for it to even know it's
> >> running on r600.
> >>
> > Even though LLVM is a generic representation it's not always possible
> > to produce an LLVM bitcode program that is guaranteed to run on every
> > target, so if we use LLVM IR it will have to some knowledge about that
> > target on which it will executed.
> >
> 
> Yes, what we are discussing is how to pass this information from the
> pipe driver to the compiler.  If you don't want to fix clang, and you
> don't like my other proposal either, I'd consider separating the driver
> cap that determines the IR from the one that determines the target,
> until we have a generic way to pass the target description to the
> compiler.
>

I agree that having separate caps for the IR and the target is a good
idea.  This is what I was proposing in the previous discussion about
this http://lists.freedesktop.org/archives/mesa-dev/2012-April/020959.html

Maybe we can revisit this discussion.  What do you think about limiting
the values of PIPE_SHADER_CAP_PREFFERED_IR to {TGSI, LLVM, NATIVE} and
then adding a cap like PIPE_SHADER_CAP_LLVM_TARGET that returns the name
of the target (e.g. r600 for r600g)

-Tom

> >
> >> > Even though I prefer this solution, ultimately I want to come up with
> >> > something that works for everyone even if it isn't exactly what I
> >> > proposed.  So, I hope we will be able to work something out.
> >> >
> >> > -Tom
> >
> > -Tom




> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev




More information about the mesa-dev mailing list