isa and friends as an alternative to dynamic cast?

I see a bunch of definitions scattered throughout LLVM, and I could not
find good documentation on them. I don't understand why they exist when
LLVM is being compiled with RTTI enabled. It seems to me that:

isa<T>(x) is a substitute for (dynamic_cast<T>(x) != NULL)

and there are some other similar casting tools defined in Casting.h. Why
should I use these instead of C++'s built-in features?

Evan Jones

Not really. C++ dynamic_cast<T>(x), as I understand it, is a dynamic
type-checker that will walk the class hierarchy to determine if "x" is a
subclass of "T", and hence, "is it a thing of type T". This means a
bunch of loads to traverse the tree.

LLVM does not have a complex hierarchy of Instructions and Values, so
this is just extra overhead. If you look at
llvm/include/llvm/Instructions.h, for example, look at the classof()
implementations by each instruction. isa<> is defined in terms of these
classof() member functions. LLVM also provides a dyn_cast<T>(x) that is
"like" dynamic_cast<T>(x), but faster, because it benefits from LLVM's
class hierarchy.

In Casting.h, you'll find:

// isa<X> - Return true if the parameter to the template is an instance
// of the template type argument. Used like this:
//
// if (isa<Type*>(myVal)) { ... }
//
template <typename To, typename From>
inline bool isa_impl(const From &Val) {
  return To::classof(&Val);
}

Also take a look at the definition of dyn_cast<X> in the same file.

I see a bunch of definitions scattered throughout LLVM, and I could not
find good documentation on them. I don't understand why they exist when
LLVM is being compiled with RTTI enabled. It seems to me that:

isa<T>(x) is a substitute for (dynamic_cast<T>(x) != NULL)

Misha seems to have answered your question, but documentation is found here:
http://llvm.cs.uiuc.edu/docs/ProgrammersManual.html#isa

-Tanya

Ah, perfect! Thank you both.

Evan Jones

Evan,

In case it wasn’t obvious from Misha’s answer, the main reason for doing this is speed. RTTI is not very quick. Since LLVM is well contained, there are no IR classes that LLVM doesn’t know about it. Using dynamic_cast is really only warranted when blending libraries together that have inheritance relationships between them that aren’t known in one or more of the libraries. Since we don’t have that situation in LLVM, using the various Casting.h facilities allows all that “dynamic” casting to actually be done statically, hence no runtime performance penalty.

If you wonder why LLVM is fast … this is just one of the many reasons.

Reid.

Right. This is why I was somewhat suprized to see the "isa" facilities
included in LLVM without also disabling rtti. It will reduce the memory
footprint a fair bit if you do disable it, at least based on my
experience with other C++ projects.

Evan Jones

That's a good point.

Evan Jones wrote:

Yeah, I petitioned Chris on this a long time ago but he had a good reason for not disabling it. I think LLVM uses some minimal RTTI features, but I can’t remember what now.

Reid.

Reid is right. isa on an instruction literally loads a field out of the instruction and compares it against a constant. As another example, a good compiler (ahem, like LLVM :slight_smile: ), turns this:

if (... = dyn_cast<LoadInst>(Y)) {
...
} else if (... = dyn_cast<StoreInst>(Y)) {
...
} else if (... = dyn_cast<AllocaInst>(Y)) {
...

Into:

switch (Y->getOpcode()) {
case Instruction::Load:
   ...
case Instruction::Store:
   ...
case Instruction::AllocaInst:
   ...

Which is something that is just not possible with RTTI.

-Chris

That's a good point.

I think there are some issues with doing this (e.g. EH doesn't work, so the very few places we use it would have to be modified), but other than that I fully support the idea.

-Chris

Evan Jones wrote:

In case it wasn't obvious from Misha's answer, the main reason for
doing this is speed. RTTI is not very quick.

Right. This is why I was somewhat suprized to see the "isa" facilities
included in LLVM without also disabling rtti. It will reduce the memory
footprint a fair bit if you do disable it, at least based on my
experience with other C++ projects.

Evan Jones

_______________________________________________
LLVM Developers mailing list
LLVMdev@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev

_______________________________________________
LLVM Developers mailing list
LLVMdev@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev

-Chris

This may be the case with GCC, but VC++ allows exception handling to be enabled while RTTI is disabled. According to VC++ documentation, RTTI is needed only to support dynamic_cast, the typeid operator, and the type_info class.

Chris Lattner wrote:

As far as I can tell, exceptions work just fine without RTTI when using gcc 3.4.2. dynamic_cast, on the hand, crashes without RTTI (no compilation error or warning is generated).

Jeff Cohen wrote:

My understanding is that EH works fine without RTTI. However, we use
typeid in LLVM in a few limited spots like lib/VMCore/Pass.cpp

Reid.

That requires RTTI.

Anyway, I verified exceptions really don't need RTTI in VC++ also. Furthermore, VC++ complains when dynamic_cast is used with RTTI disabled.

Reid Spencer wrote: