Is there a difference between "lower" and "legalize" in TIR?

Both, FLowerIntrinsic and FLegalize are the same type, and they are handled in a pretty much the same way. Is one of them being phased out?

Hi, good catch! They are designed to deal with op intrinsic lowering and op legalization respectively in the lowering pass. Ideally, we always want to use intrinsic lowering before legalization if available. I don’t think we are going to phase out any of them for now because there could be diverse need for intrinsic lowering and legalization in packed function type in the future.

Intrinsics and ops are represented in the same way in TIR though. What is the intended behavior of “legalization” that is different from “lowering”?

Legalization is when there is no available op intrinsic lowering function available, we might use other op to combine and implement some op. For example, here the exp10 op on llvm platform is implemented as legalization.

So technically I don’t think they are very different in behavior, i.e., the type of functions are the same in TIR. It’s more of a conceptual difference for now.

From what I’ve seen so far there is no difference at all, conceptual or not. We should stick to one and get rid of the other. Both operate on the same TIR representation. In one case the TIR expression is replaced by another function call, in the other the resulting expression is more complicated, but it’s still a TIR expression.

We should not have multiple concepts that do the same thing. On the contrary, we should aim to reduce the number of different abstractions.

I do agree that we don’t want abstractions that are not useful.

Just to explain a bit more: any op could have both legalization and intrinsic lowering function. Type-wise, yes they are all TIR expressions and technically there’s no difference. Concept-wise, since any op can have both implementation and we always prefer lower intrinsic function rather than legalization function, they are different IMHO. And the legalization function could be shared across platform, that’s another difference.

Why would an op have both? This is still the question that hasn’t been answered. What was the intent behind having “lowering” and “legalization” as different things?

Thanks @kparzysz . I believe the argument can go both ways in here. If we view the overall IR as “staged”, lowering means we have a strategy to map them to the corresponding low level intrinsics.

While legalization means we remap the op by composing using other expressions, which still need to be lowered in order to remain valid in the target platform.

For example, mapping exp => llvm.exp is a way of lowering, but because llvm does not have sigmoid, imagine we have a sigmoid op, mapping sigmoid(x)=>1 /(1 + exp(-x)) will be called legalization, and we still need to map the exp to llvm.exp after legalize in order to run on the target platform.

Sorry I was posting on a wrong thread

@kparzysz Thanks for asking! For example, there might be some rare TVM intrinsics like tir.erf that may be lowered to some cuda intrinsic (using Lowering), but those intrinsics aren’t guaranteed to exist on other hardware platforms, and in this case, we substitute the intrinsic with more complicated computation (using Legalization)

Most op likely will have a generic legalization strategy(in case target lowering strategy does not exist), and specific lowering strategy per target

The goal is to rewrite the TIR into a way that the target’s codegen can handle. Rewriting exp into llvm.exp can be seen as legalization too. There can be targets that can generate code directly for exp. In fact, the translation from exp to llvm.exp is only there for convenience (automation). The LLVM code generator could be changed to handle exp just fine.

The distinction, as presented so far, is very subjective, and IMO unnecessary.

I do not disagree, that is why I think the argument can go both ways. One pt here though is that legalization means we need to recursively call the lowering strategy on the return expr of the legalized code, while in the case of lowering we do not need to do so.

We could certainly name all the cases Legalization and still make things work. So it is mainly a technical design tradeoff that we need to make and in this case we can see arguments for both sides.